00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
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
00040 #define MEMORYFILE_SIGNATURE 0x3130464D
00041
00042
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
00111
00112
00113
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
00219
00220
00221
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
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