Main Page | Alphabetical List | Compound List | File List | Compound Members | File Members

tkevents.c

Go to the documentation of this file.
00001 /****************************************************************************************/
00002 /*  TKARRAY.C                                                                                                                                                   */
00003 /*                                                                                      */
00004 /*  Author: Stephen Balkum                                                                  */
00005 /*  Description: Time-keyed events implementation.                                                                              */
00006 /*                                                                                      */
00007 /*  The contents of this file are subject to the Genesis3D Public License               */
00008 /*  Version 1.01 (the "License"); you may not use this file except in                   */
00009 /*  compliance with the License. You may obtain a copy of the License at                */
00010 /*  http://www.genesis3d.com                                                            */
00011 /*                                                                                      */
00012 /*  Software distributed under the License is distributed on an "AS IS"                 */
00013 /*  basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.  See                */
00014 /*  the License for the specific language governing rights and limitations              */
00015 /*  under the License.                                                                  */
00016 /*                                                                                      */
00017 /*  The Original Code is Genesis3D, released March 25, 1999.                            */
00018 /*Genesis3D Version 1.1 released November 15, 1999                            */
00019 /*  Copyright (C) 1999 WildTangent, Inc. All Rights Reserved           */
00020 /*                                                                                      */
00021 /****************************************************************************************/
00022 /* geTKEvents
00023         (Time-Keyed-Events)
00024 
00025         geTKEvents is a sorted array of times with an identifying descriptor.
00026         The descriptors are stored as strings in a separate, packed buffer.
00027 
00028         Error conditions are reported to errorlog
00029 */
00030 #include <assert.h>
00031 #include <stdio.h>
00032 
00033 #include "TKEvents.h"
00034 #include "TKArray.h"
00035 #include "ErrorLog.h"
00036 #include "ram.h"
00037 #include "string.h"
00038 
00039 typedef struct
00040 {
00041         geTKEvents_TimeType EventTime;
00042         uint32 DataOffset;
00043 }       EventType;
00044 
00045 typedef struct geTKEventsIterator 
00046 {
00047         geTKEvents_TimeType EndTime;
00048         int CurrentIndex;
00049 }       geTKEventsIterator;
00050 
00051 typedef struct geTKEvents
00052 {
00053         geTKArray* pTimeKeys;
00054         uint32 DataSize;
00055         char* pEventData;
00056 
00057         geTKEventsIterator Iterator;
00058 }       geTKEvents;
00059 
00060 
00061 
00062 // General validity test.
00063 // Use TKE_ASSERT_VALID to test array for reasonable data.
00064 #ifdef _DEBUG
00065 
00066 #define TKE_ASSERT_VALID(E) geTKEvents_Asserts(E)
00067 
00068 // Do not call this function directly.  Use TKE_ASSERT_VALID
00069 static void GENESISCC geTKEvents_Asserts(const geTKEvents* E)
00070 {
00071         assert( (E) != NULL );
00072         assert( (E)->pTimeKeys != NULL );
00073         if(geTKArray_NumElements((E)->pTimeKeys) == 0)
00074         {
00075                 assert( (E)->pEventData == NULL );
00076         }
00077         else
00078         {
00079                 assert( (E)->pEventData != NULL );
00080         }
00081 }
00082 
00083 #else // !_DEBUG
00084 
00085 #define TKE_ASSERT_VALID(E) ((void)0)
00086 
00087 #endif // _DEBUG
00088 
00089 geTKEvents* GENESISCC geTKEvents_Create(void)
00090         // Creates a new event array.
00091 {
00092         geTKEvents* pEvents;
00093 
00094         pEvents = GE_RAM_ALLOCATE_STRUCT(geTKEvents);
00095         if(!pEvents)
00096         {
00097                 geErrorLog_Add(ERR_TKEVENTS_CREATE_ENOMEM, NULL);
00098                 return NULL;
00099         }
00100 
00101         pEvents->pTimeKeys = geTKArray_Create(sizeof(EventType));
00102         if(!pEvents->pTimeKeys)
00103         {
00104                 geErrorLog_Add(ERR_TKEVENTS_CREATE_ENOMEM, NULL);
00105                 geRam_Free(pEvents);
00106                 return NULL;
00107         }
00108 
00109         pEvents->DataSize = 0;
00110         pEvents->pEventData = NULL;
00111 
00112         pEvents->Iterator.CurrentIndex = 0;
00113         pEvents->Iterator.EndTime = -99e33f;    // you could sample here I suppose...
00114         
00115         return pEvents;
00116 }
00117 
00118 
00119 void GENESISCC geTKEvents_Destroy(geTKEvents** ppEvents)
00120         // Destroys array.
00121 {
00122         geTKEvents* pE;
00123 
00124         assert(ppEvents);
00125         pE = *ppEvents;
00126         assert(pE);
00127 
00128         if( pE->pEventData != NULL )
00129                 {
00130                         geRam_Free(pE->pEventData);
00131                 }
00132         
00133         if (pE->pTimeKeys != NULL)
00134                 {
00135                         geTKArray_Destroy(&pE->pTimeKeys);
00136                 }
00137         geRam_Free(*ppEvents);
00138         *ppEvents = NULL;
00139 }
00140 
00141 
00142 geBoolean GENESISCC geTKEvents_Insert(geTKEvents* pEvents, geTKEvents_TimeType tKey, const char* pEventData)
00143 {
00144         int nIndex;
00145         uint32 DataLength;
00146         uint32 InitialOffset;
00147         int nNumElements;
00148         EventType* pKeyInfo;
00149         char* pNewData;
00150 
00151         TKE_ASSERT_VALID(pEvents);
00152 
00153         if( geTKArray_Insert(&pEvents->pTimeKeys, tKey, &nIndex) != GE_TRUE )
00154         {
00155                 geErrorLog_Add(ERR_TKEVENTS_INSERT, NULL);
00156                 return GE_FALSE;
00157         }
00158         pKeyInfo = geTKArray_Element(pEvents->pTimeKeys, nIndex);
00159         assert( pKeyInfo != NULL ); // I just successfully added it; it better be there.
00160 
00161         DataLength = strlen(pEventData) + 1;
00162 
00163         // Resize data to add new stuff
00164         pNewData = geRam_Realloc(pEvents->pEventData, pEvents->DataSize + DataLength);
00165         if(!pNewData)
00166         {
00167                 geErrorLog_Add(ERR_TKEVENTS_INSERT_ENOMEM, NULL);
00168                 if( geTKArray_DeleteElement(&pEvents->pTimeKeys, nIndex) == GE_FALSE)
00169                 {
00170                         // This object is now in an unstable state.
00171                         assert(0);
00172                 }
00173                 // invalidate the iterator
00174                 pEvents->Iterator.EndTime = -99e33f;    // you could sample here I suppose...
00175                 return GE_FALSE;
00176         }
00177         pEvents->pEventData = pNewData;
00178 
00179         // Find where new data will go
00180         nNumElements = geTKArray_NumElements(pEvents->pTimeKeys);
00181         assert(nIndex < nNumElements); // sanity check
00182         if(nIndex == nNumElements - 1)
00183         {
00184                 // We were added to the end
00185                 InitialOffset = pEvents->DataSize;
00186         }
00187         else
00188         {
00189                 EventType* pNextKeyInfo = geTKArray_Element(pEvents->pTimeKeys, nIndex + 1);
00190                 assert( pNextKeyInfo != NULL );
00191 
00192                 InitialOffset = pNextKeyInfo->DataOffset;
00193         }
00194         pKeyInfo->DataOffset = InitialOffset;
00195 
00196         // Add new data, moving only if necessary
00197         if(InitialOffset < pEvents->DataSize)
00198         {
00199                 memmove(pEvents->pEventData + InitialOffset + DataLength,       // dest
00200                                 pEvents->pEventData + InitialOffset,                            // src
00201                                 pEvents->DataSize - InitialOffset);                                     // count
00202         }
00203         memcpy( pEvents->pEventData + InitialOffset,    // dest
00204                         pEventData,                                                             // src
00205                         DataLength);                                                    // count
00206 
00207         pEvents->DataSize += DataLength;
00208 
00209         // Bump all remaining offsets up
00210         nIndex++;
00211         while(nIndex < nNumElements)
00212         {
00213                 pKeyInfo = geTKArray_Element(pEvents->pTimeKeys, nIndex);
00214                 assert( pKeyInfo != NULL );
00215                 pKeyInfo->DataOffset += DataLength;
00216 
00217                 nIndex++;
00218         }
00219 
00220         // invalidate the iterator
00221         pEvents->Iterator.EndTime = -99e33f;    // you could sample here I suppose...
00222 
00223         return GE_TRUE;
00224 }
00225 
00226 
00227 geBoolean GENESISCC geTKEvents_Delete(geTKEvents* pEvents, geTKEvents_TimeType tKey)
00228 {
00229         int nIndex, Count;
00230         geTKEvents_TimeType tFound;
00231         EventType* pKeyInfo;
00232         int DataOffset, DataSize;
00233         char *pNewData;
00234 
00235         TKE_ASSERT_VALID(pEvents);
00236 
00237         nIndex = geTKArray_BSearch(pEvents->pTimeKeys, tKey);
00238 
00239         if( nIndex < 0 )
00240         {       // no key wasn't found
00241                 geErrorLog_Add(ERR_TKEVENTS_DELETE_NOT_FOUND, NULL);
00242                 return GE_FALSE;
00243         }
00244 
00245         tFound = geTKArray_ElementTime(pEvents->pTimeKeys, nIndex);
00246         if(tFound < tKey - GE_TKA_TIME_TOLERANCE)
00247         {
00248                 // key not found
00249                 geErrorLog_Add(ERR_TKEVENTS_DELETE_NOT_FOUND, NULL);
00250                 return GE_FALSE;
00251         }
00252 
00253         pKeyInfo = geTKArray_Element(pEvents->pTimeKeys, nIndex);
00254         DataOffset = pKeyInfo->DataOffset;
00255         if(nIndex < geTKArray_NumElements(pEvents->pTimeKeys) - 1)
00256         {
00257                 // not the last element
00258                 pKeyInfo = geTKArray_Element(pEvents->pTimeKeys, nIndex + 1);
00259                 DataSize = pKeyInfo->DataOffset - DataOffset;
00260 
00261                 memmove(pEvents->pEventData + DataOffset,                               // dest
00262                                 pEvents->pEventData + DataOffset + DataSize,    // src
00263                                 pEvents->DataSize - DataOffset - DataSize);             // count
00264         }
00265         else
00266         {
00267                 // It's the last element and no memory needs to be moved
00268                 DataSize = pEvents->DataSize - DataOffset;
00269         }
00270 
00271         // Adjust data
00272         pEvents->DataSize -= DataSize;
00273         if (pEvents->DataSize == 0)
00274         {
00275                 geRam_Free (pEvents->pEventData);
00276                 pEvents->pEventData = NULL;
00277         }
00278         else
00279         {
00280                 pNewData = geRam_Realloc(pEvents->pEventData, pEvents->DataSize);
00281                 // If the reallocation failed, it doesn't really hurt.  However, it is a 
00282                 // sign of problems ahead.
00283                 if(pNewData)
00284                 {
00285                         pEvents->pEventData = pNewData;
00286                 }
00287         }
00288 
00289         // Finally, remove this element
00290         geTKArray_DeleteElement(&pEvents->pTimeKeys, nIndex);
00291 
00292         // Adjust the offsets
00293         Count = geTKArray_NumElements(pEvents->pTimeKeys);
00294         while(nIndex < Count)
00295         {
00296                 pKeyInfo = geTKArray_Element(pEvents->pTimeKeys, nIndex);
00297                 assert( pKeyInfo != NULL );
00298                 pKeyInfo->DataOffset -= DataSize;
00299                 nIndex++;
00300         }
00301 
00302         // invalidate the iterator
00303         pEvents->Iterator.EndTime = -99e33f;    // you could sample here I suppose...
00304 
00305         return GE_TRUE;
00306 }
00307 
00308 
00309 #define TKEVENTS_ASCII_FILE_TYPE 0x56454B54 // 'TKEV'
00310 #define TKEVENTS_FILE_VERSION 0x00F0            // Restrict to 16 bits
00311 
00312 #define TKEVENTS_BIN_FILE_TYPE   0x42454B54 // 'TKEB'
00313 #define TKEVENTS_TIMEKEYS_ID "TimeKeys"
00314 #define TKEVENTS_DATASIZE_ID "DataSize"
00315 
00316 
00317 geTKEvents* GENESISCC geTKEvents_CreateFromFile(
00318         geVFile* pFile)                                 // stream positioned at array data
00319         // Creates a new array from the given stream.
00320 {
00321         uint32 u;
00322         geTKEvents* pEvents;
00323 
00324         assert( pFile != NULL );
00325 
00326         // Read the format/version flag
00327         if(geVFile_Read(pFile, &u, sizeof(u)) == GE_FALSE)
00328         {
00329                 geErrorLog_Add(ERR_TKEVENTS_FILE_READ, NULL);
00330                 return NULL;
00331         }
00332 
00333         pEvents = GE_RAM_ALLOCATE_STRUCT(geTKEvents);
00334         if(!pEvents)
00335         {
00336                 geErrorLog_Add(ERR_TKEVENTS_CREATE_ENOMEM, NULL);
00337                 return NULL;
00338         }
00339         pEvents->pEventData = NULL;
00340         pEvents->pTimeKeys  = NULL;
00341 
00342         if(u == TKEVENTS_ASCII_FILE_TYPE)
00343         {
00344                 int             i;
00345                 uint32  v;
00346                 char    VersionString[32];
00347 #define LINE_LENGTH 256
00348                 char line[LINE_LENGTH];
00349                 char* pTextLine = NULL;
00350                 EventType* pEInfo;
00351                 geTKEvents_TimeType Time;
00352 
00353 #define ABORT_READ_AND_FREE { geErrorLog_Add(ERR_TKEVENTS_FILE_READ, NULL); geTKEvents_Destroy(&pEvents); return NULL; }
00354 #define ABORT_READ_AND_FREE_ALL                         \
00355 {                                                                                       \
00356         geErrorLog_Add(ERR_TKEVENTS_FILE_READ, NULL);   \
00357         geTKEvents_Destroy(&pEvents);                   \
00358         if(pTextLine != NULL)                                   \
00359                 geRam_Free(pTextLine);                          \
00360         return NULL;                                                    \
00361 }
00362 
00363                 // Read and build the version.
00364                 if      (geVFile_GetS(pFile, VersionString, sizeof(VersionString)) == GE_FALSE)
00365                 {
00366                         geErrorLog_Add(ERR_TKEVENTS_FILE_READ, NULL);
00367                         return NULL;
00368                 }
00369                 sscanf(VersionString, "%X.%X\n", &u, &v);
00370                 v |= (u << 8);
00371                 // Should this structure change, then actually code multiversion support.
00372                 if(v != TKEVENTS_FILE_VERSION)
00373                         ABORT_READ_AND_FREE;
00374 
00375                 if(geVFile_GetS(pFile, line, LINE_LENGTH) == GE_FALSE)
00376                         ABORT_READ_AND_FREE;
00377 
00378                 if(strnicmp(line, TKEVENTS_DATASIZE_ID, sizeof(TKEVENTS_DATASIZE_ID)-1) != 0)
00379                         ABORT_READ_AND_FREE;
00380 
00381                 if(sscanf(line + sizeof(TKEVENTS_DATASIZE_ID)-1, "%d", &pEvents->DataSize) != 1)
00382                         ABORT_READ_AND_FREE;
00383                 if (pEvents->DataSize +1> LINE_LENGTH)
00384                         ABORT_READ_AND_FREE;
00385 
00386                 if(geVFile_GetS(pFile, line, LINE_LENGTH) == GE_FALSE)
00387                         ABORT_READ_AND_FREE;
00388 
00389                 if(strnicmp(line, TKEVENTS_TIMEKEYS_ID, sizeof(TKEVENTS_TIMEKEYS_ID)-1) != 0)
00390                         ABORT_READ_AND_FREE;
00391 
00392                 if(sscanf(line + sizeof(TKEVENTS_TIMEKEYS_ID)-1, "%d", &i) != 1)
00393                         ABORT_READ_AND_FREE;
00394 
00395                 pEvents->pTimeKeys = geTKArray_Create(sizeof(EventType));
00396                 if(!pEvents->pTimeKeys)
00397                         ABORT_READ_AND_FREE;
00398 
00399                 pEvents->pEventData = geRam_Allocate(pEvents->DataSize);
00400                 if(!pEvents->pEventData)
00401                         ABORT_READ_AND_FREE_ALL;
00402 
00403                 // The strings are read in with a CR.  The max line length will then be
00404                 // the datasize + 1.
00405                 pTextLine = geRam_Allocate(pEvents->DataSize + 1);
00406                 if(pTextLine == NULL)
00407                         ABORT_READ_AND_FREE_ALL;
00408 
00409                 while(i > 0)
00410                 {
00411                         char    TimeString[64];
00412                         if      (geVFile_GetS(pFile, TimeString, sizeof(TimeString)) == GE_FALSE)
00413                                 ABORT_READ_AND_FREE_ALL;
00414                         if(sscanf(TimeString, "%f %d\n", &Time, &v) != 2)
00415                                 ABORT_READ_AND_FREE_ALL;
00416                         if(!geTKArray_Insert(&pEvents->pTimeKeys, Time, (int*)&u))
00417                                 ABORT_READ_AND_FREE_ALL;
00418                         pEInfo = geTKArray_Element(pEvents->pTimeKeys, u);
00419                         pEInfo->DataOffset = v;
00420                         //if(!fgets(pEvents->pEventData + v, pEvents->DataSize - v, pFile))
00421                         if(geVFile_GetS(pFile, pTextLine, pEvents->DataSize + 1) == GE_FALSE)
00422                                 ABORT_READ_AND_FREE_ALL;
00423                         // strip the CR
00424                         pTextLine[strlen(pTextLine) - 1] = 0;
00425                                 {  // maybe strip the rest of the CR
00426                                         int len = strlen(pTextLine)-1;
00427                                         if (pTextLine[len] == 13)  // remove trailing /r  (binary file mode)
00428                                                 {
00429                                                         pTextLine[len] = 0;
00430                                                 }
00431                                 }
00432                         strcpy(pEvents->pEventData + v, pTextLine);
00433                         
00434                         i--;
00435                 }
00436 
00437                 if(pTextLine != NULL)
00438                         geRam_Free(pTextLine);
00439         }
00440         else
00441         {
00442                 if(u == TKEVENTS_BIN_FILE_TYPE)
00443                         {
00444                                 if(geVFile_Read(pFile, &u, sizeof(u)) == GE_FALSE)
00445                                         {
00446                                                 geErrorLog_Add(ERR_TKEVENTS_FILE_READ, NULL);
00447                                                 geTKEvents_Destroy(&pEvents);
00448                                                 return GE_FALSE;
00449                                         }
00450                                 if (u != TKEVENTS_FILE_VERSION)
00451                                         {
00452                                                 geErrorLog_AddString(-1,"Failure to recognize TKEvents file version", NULL);
00453                                                 geTKEvents_Destroy(&pEvents);
00454                                                 return GE_FALSE;
00455                                         }
00456 
00457                                 if(geVFile_Read(pFile, &(pEvents->DataSize), sizeof(pEvents->DataSize)) == GE_FALSE)
00458                                         {
00459                                                 geErrorLog_Add(ERR_TKEVENTS_FILE_READ, NULL);
00460                                                 geTKEvents_Destroy(&pEvents);
00461                                                 return NULL;
00462                                         }
00463 
00464                                 pEvents->pEventData = geRam_Allocate(pEvents->DataSize);
00465                                 if(!pEvents->pEventData)
00466                                         {
00467                                                 geErrorLog_Add(ERR_TKEVENTS_CREATE_ENOMEM, NULL);
00468                                                 geTKEvents_Destroy(&pEvents);
00469                                                 return NULL;
00470                                         }
00471 
00472                                 if(geVFile_Read(pFile, pEvents->pEventData, pEvents->DataSize) == GE_FALSE)
00473                                         {
00474                                                 geErrorLog_Add(ERR_TKEVENTS_FILE_READ, NULL);
00475                                                 geTKEvents_Destroy(&pEvents);
00476                                                 return NULL;
00477                                         }
00478                                 pEvents->pTimeKeys = geTKArray_CreateFromBinaryFile(pFile);
00479                                 if(!pEvents->pTimeKeys)
00480                                         {
00481                                                 geErrorLog_Add(ERR_TKEVENTS_FILE_READ, NULL);
00482                                                 geTKEvents_Destroy(&pEvents);
00483                                                 return NULL;
00484                                         }
00485                         }
00486         }
00487 
00488         return pEvents;
00489 }
00490 
00491 
00492 #define CHECK_FOR_WRITE(uu) if(uu <= 0) { geErrorLog_Add(ERR_TKEVENTS_FILE_WRITE, NULL); return GE_FALSE; }
00493 
00494 geBoolean GENESISCC geTKEvents_WriteToFile(
00495         const geTKEvents* pEvents,              // sorted array to write
00496         geVFile* pFile)                                 // stream positioned for writing
00497         // Writes the array to the given stream.
00498 {
00499         uint32  u;
00500         int             NumElements;
00501         int             i;
00502         EventType* pEInfo;
00503 
00504         assert( pEvents != NULL );
00505         assert( pFile != NULL );
00506 
00507         u = TKEVENTS_ASCII_FILE_TYPE;
00508         if(geVFile_Write(pFile, &u, sizeof(u)) == GE_FALSE)
00509                 {
00510                         geErrorLog_Add(ERR_TKEVENTS_FILE_WRITE, NULL);
00511                         return GE_FALSE;
00512                 }
00513 
00514         // Write the version
00515         if      (geVFile_Printf(pFile,
00516                                           " %X.%.2X\n",
00517                                           (TKEVENTS_FILE_VERSION & 0xFF00) >> 8,
00518                                           TKEVENTS_FILE_VERSION & 0x00FF) == GE_FALSE)
00519         {
00520                 geErrorLog_Add(ERR_TKEVENTS_FILE_WRITE, NULL);
00521                 return GE_FALSE;
00522         }
00523 
00524         // Write the data size first and then combine the time array and string
00525         // data into one loop of human readable output.
00526         if      (geVFile_Printf(pFile, "%s %d\n", TKEVENTS_DATASIZE_ID, pEvents->DataSize) == GE_FALSE)
00527         {
00528                 geErrorLog_Add(ERR_TKEVENTS_FILE_WRITE, NULL);
00529                 return GE_FALSE;
00530         }
00531 
00532         // Write the TimeKeys array and string data.
00533         NumElements = geTKArray_NumElements(pEvents->pTimeKeys);
00534         if      (geVFile_Printf(pFile, "%s %d\n", TKEVENTS_TIMEKEYS_ID, NumElements) == GE_FALSE)
00535         {
00536                 geErrorLog_Add(ERR_TKEVENTS_FILE_WRITE, NULL);
00537                 return GE_FALSE;
00538         }
00539 
00540         for(i=0;i<NumElements;i++)
00541                 {
00542                         pEInfo = geTKArray_Element(pEvents->pTimeKeys, i);
00543                         if      (geVFile_Printf(pFile, "%f %d\n", pEInfo->EventTime, pEInfo->DataOffset) == GE_FALSE)
00544                         {
00545                                 geErrorLog_Add(ERR_TKEVENTS_FILE_WRITE, NULL);
00546                                 return GE_FALSE;
00547                         }
00548                         if      (geVFile_Printf(pFile, "%s\n", pEvents->pEventData + pEInfo->DataOffset) == GE_FALSE)
00549                         {
00550                                 geErrorLog_Add(ERR_TKEVENTS_FILE_WRITE, NULL);
00551                                 return GE_FALSE;
00552                         }
00553                 }
00554         return GE_TRUE;
00555 }
00556 
00557 
00558 
00559 geBoolean GENESISCC geTKEvents_WriteToBinaryFile(
00560         const geTKEvents* pEvents,              // sorted array to write
00561         geVFile* pFile)                                 // stream positioned for writing
00562         // Writes the array to the given stream.
00563 {
00564         uint32 u;
00565         assert( pEvents != NULL );
00566         assert( pFile != NULL );
00567 
00568         u = TKEVENTS_BIN_FILE_TYPE;
00569         if(geVFile_Write(pFile, &u, sizeof(u)) == GE_FALSE)
00570                 {
00571                         geErrorLog_Add(ERR_TKEVENTS_FILE_WRITE, NULL);
00572                         return GE_FALSE;
00573                 }
00574         u = TKEVENTS_FILE_VERSION;
00575         // Write the version
00576         if(geVFile_Write(pFile, &u, sizeof(u)) == GE_FALSE)
00577                 {
00578                         geErrorLog_Add(ERR_TKEVENTS_FILE_WRITE, NULL);
00579                         return GE_FALSE;
00580                 }
00581 
00582         if(geVFile_Write(pFile, &pEvents->DataSize, sizeof(pEvents->DataSize)) == GE_FALSE)
00583                 {
00584                         geErrorLog_Add(ERR_TKEVENTS_FILE_WRITE, NULL);
00585                         return GE_FALSE;
00586                 }
00587 
00588         if(geVFile_Write(pFile, pEvents->pEventData, pEvents->DataSize) == GE_FALSE)
00589                 {
00590                         geErrorLog_Add(ERR_TKEVENTS_FILE_WRITE, NULL);
00591                         return GE_FALSE;
00592                 }
00593 
00594         if (geTKArray_WriteToBinaryFile(pEvents->pTimeKeys, pFile)==GE_FALSE)
00595                 {
00596                         geErrorLog_Add(ERR_TKEVENTS_FILE_WRITE, NULL);
00597                         return GE_FALSE;
00598                 }
00599         return GE_TRUE;
00600 }
00601 
00602 GENESISAPI geBoolean GENESISCC geTKEvents_GetExtents(geTKEvents *Events,
00603                 geTKEvents_TimeType *FirstEventTime,
00604                 geTKEvents_TimeType *LastEventTime)
00605 {
00606         int Count;
00607         assert( Events != NULL );
00608         
00609         Count = geTKArray_NumElements(Events->pTimeKeys);
00610         if (Count<0)
00611                 {
00612                         return GE_FALSE;
00613                 }
00614 
00615         *FirstEventTime = geTKArray_ElementTime(Events->pTimeKeys, 0);
00616         *LastEventTime  = geTKArray_ElementTime(Events->pTimeKeys, Count-1);
00617         return GE_TRUE;
00618 }
00619 
00620 void GENESISCC geTKEvents_SetupIterator(
00621         geTKEvents* pEvents,                            // Event list to iterate
00622         geTKEvents_TimeType StartTime,                          // Inclusive search start
00623         geTKEvents_TimeType EndTime)                            // Non-inclusive search stop
00624         // For searching or querying the array for events between two times
00625         // times are compaired [StartTime,EndTime), '[' is inclusive, ')' is 
00626         // non-inclusive.  This prepares the PathGetNextEvent() function.  
00627 {
00628         geTKEventsIterator* pTKEI;
00629 
00630         assert( pEvents != NULL );
00631 
00632         pTKEI = &pEvents->Iterator;
00633 
00634         pTKEI->EndTime = EndTime;
00635 
00636         // Initialize search with first index before StartTime
00637         pTKEI->CurrentIndex = geTKArray_BSearch(pEvents->pTimeKeys, StartTime - GE_TKA_TIME_TOLERANCE);
00638         while( (pTKEI->CurrentIndex > -1) && 
00639                 (geTKArray_ElementTime(pEvents->pTimeKeys, pTKEI->CurrentIndex) >= StartTime - GE_TKA_TIME_TOLERANCE) )
00640         {
00641                 pTKEI->CurrentIndex--;
00642         }
00643 }
00644 
00645 
00646 geBoolean GENESISCC geTKEvents_GetNextEvent(
00647         geTKEvents* pEvents,                            // Event list to iterate
00648         geTKEvents_TimeType *pTime,                             // Return time, if found
00649         const char **ppEventString)             // Return data, if found
00650         // Iterates from StartTime to EndTime as setup in geTKEvents_CreateIterator()
00651         // and for each event between these times [StartTime,EndTime)
00652         // this function will return Time and EventString returned for that event
00653         // and the iterator will be positioned for the next search.  When there 
00654         // are no more events in the range, this function will return NULL (Time
00655         // will be 0 and ppEventString will be empty).
00656 {
00657         geTKEventsIterator* pTKEI;
00658         geTKArray* pTimeKeys;
00659         EventType* pKeyInfo;
00660         int Index;
00661 
00662         assert(pEvents);
00663         assert(pTime);
00664         assert(ppEventString);
00665 
00666         pTKEI = &pEvents->Iterator;
00667 
00668         pTimeKeys = pEvents->pTimeKeys;
00669 
00670         pTKEI->CurrentIndex++;
00671         Index = pTKEI->CurrentIndex;
00672         if(Index < geTKArray_NumElements(pTimeKeys))
00673         {
00674                 *pTime = geTKArray_ElementTime(pTimeKeys, Index);
00675                 if(*pTime + GE_TKA_TIME_TOLERANCE < pTKEI->EndTime)
00676                 {
00677                         // Looks good.  Get the string and return.
00678                         pKeyInfo = geTKArray_Element(pTimeKeys, Index);
00679                         *ppEventString = pEvents->pEventData + pKeyInfo->DataOffset;
00680                         return GE_TRUE;
00681                 }
00682         }
00683 
00684         // None found, clean up
00685         *pTime = 0.0f;
00686         *ppEventString = NULL;
00687         return GE_FALSE;
00688 }

Generated on Tue Sep 30 12:36:31 2003 for GTestAndEngine by doxygen 1.3.2