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

FSMEMORY.C

Go to the documentation of this file.
00001 /****************************************************************************************/
00002 /*  FSMEMORY.C                                                                          */
00003 /*                                                                                      */
00004 /*  Author: Eli Boling                                                                  */
00005 /*  Description: Memory file system implementation                                      */
00006 /*     Bug repair for 1.1 release - thanks to Tim Brengle                               */
00007 /*                                                                                      */
00008 /*  The contents of this file are subject to the Genesis3D Public License               */
00009 /*  Version 1.01 (the "License"); you may not use this file except in                   */
00010 /*  compliance with the License. You may obtain a copy of the License at                */
00011 /*  http://www.genesis3d.com                                                            */
00012 /*                                                                                      */
00013 /*  Software distributed under the License is distributed on an "AS IS"                 */
00014 /*  basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.  See                */
00015 /*  the License for the specific language governing rights and limitations              */
00016 /*  under the License.                                                                  */
00017 /*                                                                                      */
00018 /*  The Original Code is Genesis3D, released March 25, 1999.                            */
00019 /*Genesis3D Version 1.1 released November 15, 1999                            */
00020 /*  Copyright (C) 1999 WildTangent, Inc. All Rights Reserved           */
00021 /*                                                                                      */
00022 /****************************************************************************************/
00023 #define WIN32_LEAN_AND_MEAN
00024 #include        <windows.h>
00025 
00026 #include        <stdio.h>
00027 #include        <stdlib.h>
00028 #include        <string.h>
00029 #include        <assert.h>
00030 
00031 #include        "basetype.h"
00032 #include        "ram.h"
00033 
00034 #include        "vfile.h"
00035 #include        "vfile._h"
00036 
00037 #include        "fsmemory.h"
00038 
00039 //      "MF01"
00040 #define MEMORYFILE_SIGNATURE    0x3130464D
00041 
00042 //      "MF02"
00043 #define MEMORYFINDER_SIGNATURE  0x3230464D
00044 
00045 #define CHECK_HANDLE(H) assert(H);assert(H->Signature == MEMORYFILE_SIGNATURE);
00046 #define CHECK_FINDER(F) assert(F);assert(F->Signature == MEMORYFINDER_SIGNATURE);
00047 
00048 #define MEMORY_FILE_GROW        0x2000
00049 
00050 typedef struct  MemoryFile
00051 {
00052         unsigned int    Signature;
00053         char *                  Memory;
00054         int                             Size;
00055         int                             AllocatedSize;
00056         int                             Position;
00057         geBoolean               WeOwnMemory;
00058         geBoolean               ReadOnly;
00059 }       MemoryFile;
00060 
00061 static  void *  GENESISCC FSMemory_FinderCreate(
00062         geVFile *               FS,
00063         void *                  Handle,
00064         const char *    FileSpec)
00065 {
00066         return NULL;
00067 }
00068 
00069 static  geBoolean       GENESISCC FSMemory_FinderGetNextFile(void *Handle)
00070 {
00071         assert(!Handle);
00072         return GE_FALSE;
00073 }
00074 
00075 static  geBoolean       GENESISCC FSMemory_FinderGetProperties(void *Handle, geVFile_Properties *Props)
00076 {
00077         assert(!Handle);
00078         return GE_FALSE;
00079 }
00080 
00081 static  void GENESISCC FSMemory_FinderDestroy(void *Handle)
00082 {
00083         assert(!Handle);
00084 }
00085 
00086 static  void *  GENESISCC FSMemory_Open(
00087         geVFile *               FS,
00088         void *                  Handle,
00089         const char *    Name,
00090         void *                  Context,
00091         unsigned int    OpenModeFlags)
00092 {
00093         return NULL;
00094 }
00095 
00096 static  void *  GENESISCC FSMemory_OpenNewSystem(
00097         geVFile *               FS,
00098         const char *    Name,
00099         void *                  Context,
00100         unsigned int    OpenModeFlags)
00101 {
00102         MemoryFile *                    NewFS;
00103         geVFile_MemoryContext * MemContext;
00104 
00105         if      (FS || Name || !Context)
00106                 return NULL;
00107 
00108         MemContext = Context;
00109 
00110         // Don't allow the user to pass in memory pointer if we're updating or creating, because
00111         // we don't know what allocation functions we should use to resize their block if
00112         // necessary.  If you want to create a new file, you have to pass in NULL and let
00113         // us manage the allocations.
00114         if      (MemContext->Data && (OpenModeFlags & (GE_VFILE_OPEN_UPDATE | GE_VFILE_OPEN_CREATE)))
00115                 return NULL;
00116 
00117         if      (OpenModeFlags & GE_VFILE_OPEN_DIRECTORY)
00118                 return NULL;
00119 
00120         NewFS = geRam_Allocate(sizeof(*NewFS));
00121         if      (!NewFS)
00122                 return NewFS;
00123         memset(NewFS, 0, sizeof(*NewFS));
00124 
00125         NewFS->Memory = MemContext->Data;
00126         NewFS->Size = MemContext->DataLength;
00127         NewFS->AllocatedSize = NewFS->Size;
00128 
00129         if      (NewFS->Memory)
00130         {
00131                 NewFS->ReadOnly = GE_TRUE;
00132                 NewFS->WeOwnMemory = GE_FALSE;
00133         }
00134         else
00135         {
00136                 NewFS->ReadOnly = GE_FALSE;
00137                 NewFS->WeOwnMemory = GE_TRUE;
00138         }
00139 
00140         NewFS->Signature = MEMORYFILE_SIGNATURE;
00141 
00142         return NewFS;
00143 }
00144 
00145 static  geBoolean       GENESISCC FSMemory_UpdateContext(
00146         geVFile *               FS,
00147         void *                  Handle,
00148         void *                  Context,
00149         int                     ContextSize)
00150 {
00151         MemoryFile *                    File;
00152         geVFile_MemoryContext * MemoryContext;
00153 
00154         assert(FS);
00155         assert(Context);
00156         
00157         File = Handle;
00158         
00159         CHECK_HANDLE(File);
00160 
00161         if      (ContextSize != sizeof(geVFile_MemoryContext))
00162                 return GE_FALSE;
00163 
00164         MemoryContext = Context;
00165         
00166         MemoryContext->Data               = File->Memory;
00167         MemoryContext->DataLength = File->Size;
00168 
00169         return GE_TRUE;
00170 }
00171 
00172 static  void    GENESISCC FSMemory_Close(void *Handle)
00173 {
00174         MemoryFile *    File;
00175         
00176         File = Handle;
00177         
00178         CHECK_HANDLE(File);
00179 
00180         if      (File->WeOwnMemory == GE_TRUE && File->Memory)
00181                 geRam_Free(File->Memory);
00182         geRam_Free(File);
00183 }
00184 
00185 static int GENESISCC ClampOperationSize(const MemoryFile *File, int Size)
00186 {
00187         return min(File->Size - File->Position, Size);
00188 }
00189 
00190 static char * GENESISCC DataPtr(const MemoryFile *File)
00191 {
00192         return File->Memory + File->Position;
00193 }
00194 
00195 static  geBoolean       GENESISCC FSMemory_GetS(void *Handle, void *Buff, int MaxLen)
00196 {
00197         MemoryFile *    File;
00198         char *                  p;
00199         char *                  Start;
00200         char *                  pBuff;
00201 
00202         assert(Buff);
00203         assert(MaxLen != 0);
00204 
00205         File = Handle;
00206 
00207         CHECK_HANDLE(File);
00208 
00209         MaxLen = ClampOperationSize(File, MaxLen);
00210         if      (MaxLen == 0)
00211                 return GE_FALSE;
00212 
00213         p = DataPtr(File);
00214         pBuff = Buff;
00215         Start = p;
00216 
00217 //---------
00218 //   Bug fix thanks to Tim Brengle
00219 //---------
00220 
00221         //while (*p != '\n' && MaxLen > 0)
00222         while   (*p != '\n' && MaxLen > 1)
00223         {
00224                 *pBuff++ = *p++;
00225                 MaxLen--;
00226         }
00227 
00228         File->Position += p - Start + 1;
00229         assert(File->Position <= File->Size);
00230         assert(File->Size <= File->AllocatedSize);
00231 
00232         #if 0
00233                 if      (MaxLen != 0)
00234                 {
00235                         *pBuff = *p;
00236                         return GE_TRUE;
00237                 }
00238                 return GE_FALSE;
00239         #endif
00240         
00241         *(pBuff + 1) = 0;
00242         return GE_TRUE;
00243         
00244 }
00245 
00246 static  geBoolean       GENESISCC FSMemory_Read(void *Handle, void *Buff, int Count)
00247 {
00248         MemoryFile *    File;
00249 
00250         assert(Buff);
00251         assert(Count != 0);
00252 
00253         File = Handle;
00254 
00255         CHECK_HANDLE(File);
00256 
00257         if      (ClampOperationSize(File, Count) != Count)
00258                 return GE_FALSE;
00259 
00260         memcpy(Buff, DataPtr(File), Count);
00261 
00262         File->Position += Count;
00263         assert(File->Position <= File->Size);
00264         assert(File->Size <= File->AllocatedSize);
00265 
00266         return GE_TRUE;
00267 }
00268 
00269 static  geBoolean       GENESISCC TestForExpansion(MemoryFile *File, int Size)
00270 {
00271         assert(File);
00272         assert(File->ReadOnly == GE_FALSE);
00273         assert(File->WeOwnMemory == GE_TRUE);
00274 
00275         assert(File->AllocatedSize >= File->Size);
00276         assert(File->AllocatedSize >= File->Position);
00277 
00278         if      (File->AllocatedSize - File->Position < Size)
00279         {
00280                 int             NewSize;
00281                 char *  NewBlock;
00282 
00283                 NewSize = ((File->AllocatedSize + Size + (MEMORY_FILE_GROW - 1)) / MEMORY_FILE_GROW) * MEMORY_FILE_GROW;
00284                 NewBlock = geRam_Realloc(File->Memory, NewSize);
00285                 if      (!NewBlock)
00286                         return GE_FALSE;
00287                 File->Memory = NewBlock;
00288                 File->AllocatedSize = NewSize;
00289 //printf("FSMemory: Expanded file to %d bytes\n", NewSize);
00290         }
00291 
00292         return GE_TRUE;
00293 }
00294 
00295 static  geBoolean       GENESISCC FSMemory_Write(void *Handle, const void *Buff, int Count)
00296 {
00297         MemoryFile *    File;
00298 
00299         assert(Buff);
00300         assert(Count != 0);
00301 
00302         File = Handle;
00303 
00304         CHECK_HANDLE(File);
00305 
00306         if      (File->ReadOnly == GE_TRUE)
00307                 return GE_FALSE;
00308 
00309         if      (TestForExpansion(File, Count) == GE_FALSE)
00310                 return GE_FALSE;
00311 
00312         memcpy(DataPtr(File), Buff, Count);
00313         
00314         File->Position += Count;
00315         if      (File->Size < File->Position)
00316                 File->Size = File->Position;
00317 
00318         return GE_TRUE;
00319 }
00320 
00321 static  geBoolean       GENESISCC FSMemory_Seek(void *Handle, int Where, geVFile_Whence Whence)
00322 {
00323         MemoryFile *    File;
00324 
00325         File = Handle;
00326 
00327         CHECK_HANDLE(File);
00328 
00329         switch  (Whence)
00330         {
00331         int             NewPos;
00332 
00333         case    GE_VFILE_SEEKCUR:
00334                 NewPos = File->Position + Where;
00335                 if      (NewPos > File->AllocatedSize)
00336                 {
00337                         if      (File->ReadOnly == GE_TRUE)
00338                                 return GE_FALSE;
00339                         if      (TestForExpansion(File, Where) == GE_FALSE)
00340                                 return GE_FALSE;
00341                 }
00342                 File->Position = NewPos;
00343                 break;
00344 
00345         case    GE_VFILE_SEEKEND:
00346                 if      (File->Size < Where)
00347                         return GE_FALSE;
00348                 File->Position = File->Size - Where;
00349                 break;
00350 
00351         case    GE_VFILE_SEEKSET:
00352                 if      (Where > File->AllocatedSize)
00353                 {
00354                         if      (File->ReadOnly == GE_TRUE)
00355                                 return GE_FALSE;
00356                         if      (TestForExpansion(File, Where - File->Position) == GE_FALSE)
00357                                 return GE_FALSE;
00358                 }
00359                 File->Position = Where;
00360                 break;
00361 
00362         default:
00363                 assert(!"Unknown seek kind");
00364         }
00365 
00366         if      (File->Position > File->Size)
00367                 File->Size = File->Position;
00368         
00369         assert(File->Size <= File->AllocatedSize);
00370         assert(File->Position <= File->AllocatedSize);
00371 
00372         return GE_TRUE;
00373 }
00374 
00375 static  geBoolean       GENESISCC FSMemory_EOF(const void *Handle)
00376 {
00377         const MemoryFile *      File;
00378 
00379         File = Handle;
00380 
00381         CHECK_HANDLE(File);
00382 
00383         if      (File->Position == File->Size)
00384                 return GE_TRUE;
00385 
00386         return GE_FALSE;
00387 }
00388 
00389 static  geBoolean       GENESISCC FSMemory_Tell(const void *Handle, long *Position)
00390 {
00391         const MemoryFile *      File;
00392 
00393         File = Handle;
00394 
00395         CHECK_HANDLE(File);
00396 
00397         *Position = File->Position;
00398 
00399         return GE_TRUE;
00400 }
00401 
00402 static  geBoolean       GENESISCC FSMemory_Size(const void *Handle, long *Size)
00403 {
00404         const MemoryFile *      File;
00405 
00406         File = Handle;
00407 
00408         CHECK_HANDLE(File);
00409         
00410         *Size = File->Size;
00411 
00412         return GE_TRUE;
00413 }
00414 
00415 static  geBoolean       GENESISCC FSMemory_GetProperties(const void *Handle, geVFile_Properties *Properties)
00416 {
00417         assert(!"Not implemented");
00418         return GE_FALSE;
00419 }
00420 
00421 static  geBoolean       GENESISCC FSMemory_SetSize(void *Handle, long Size)
00422 {
00423         assert(!"Not implemented");
00424         return GE_FALSE;
00425 }
00426 
00427 static  geBoolean       GENESISCC FSMemory_SetAttributes(void *Handle, geVFile_Attributes Attributes)
00428 {
00429         assert(!"Not implemented");
00430         return GE_FALSE;
00431 }
00432 
00433 static  geBoolean       GENESISCC FSMemory_SetTime(void *Handle, const geVFile_Time *Time)
00434 {
00435         assert(!"Not implemented");
00436         return GE_FALSE;
00437 }
00438 
00439 static  geBoolean       GENESISCC FSMemory_SetHints(void *Handle, const geVFile_Hints *Hints)
00440 {
00441         assert(!"Not implemented");
00442         return GE_FALSE;
00443 }
00444 
00445 static  geBoolean       GENESISCC FSMemory_FileExists(geVFile *FS, void *Handle, const char *Name)
00446 {
00447         return GE_FALSE;
00448 }
00449 
00450 static  geBoolean       GENESISCC FSMemory_Disperse(
00451         geVFile *               FS,
00452         void *          Handle,
00453         const char *Directory,
00454         geBoolean       Recursive)
00455 {
00456         return GE_FALSE;
00457 }
00458 
00459 static  geBoolean       GENESISCC FSMemory_DeleteFile(geVFile *FS, void *Handle, const char *Name)
00460 {
00461         return GE_FALSE;
00462 }
00463 
00464 static  geBoolean       GENESISCC FSMemory_RenameFile(geVFile *FS, void *Handle, const char *Name, const char *NewName)
00465 {
00466         return GE_FALSE;
00467 }
00468 
00469 static  geVFile_SystemAPIs      FSMemory_APIs =
00470 {
00471         FSMemory_FinderCreate,
00472         FSMemory_FinderGetNextFile,
00473         FSMemory_FinderGetProperties,
00474         FSMemory_FinderDestroy,
00475 
00476         FSMemory_OpenNewSystem,
00477         FSMemory_UpdateContext,
00478         FSMemory_Open,
00479         FSMemory_DeleteFile,
00480         FSMemory_RenameFile,
00481         FSMemory_FileExists,
00482         FSMemory_Disperse,
00483         FSMemory_Close,
00484 
00485         FSMemory_GetS,
00486         FSMemory_Read,
00487         FSMemory_Write,
00488         FSMemory_Seek,
00489         FSMemory_EOF,
00490         FSMemory_Tell,
00491         FSMemory_Size,
00492 
00493         FSMemory_GetProperties,
00494 
00495         FSMemory_SetSize,
00496         FSMemory_SetAttributes,
00497         FSMemory_SetTime,
00498         FSMemory_SetHints,
00499 };
00500 
00501 const geVFile_SystemAPIs * GENESISCC FSMemory_GetAPIs(void)
00502 {
00503         return &FSMemory_APIs;
00504 }
00505 

Generated on Tue Sep 30 12:35:45 2003 for GTestAndEngine by doxygen 1.3.2