1 /****************************************************************************************/
\r
4 /* Author: Eli Boling */
\r
5 /* Description: Memory file system implementation */
\r
6 /* Bug repair for 1.1 release - thanks to Tim Brengle */
\r
8 /* The contents of this file are subject to the Genesis3D Public License */
\r
9 /* Version 1.01 (the "License"); you may not use this file except in */
\r
10 /* compliance with the License. You may obtain a copy of the License at */
\r
11 /* http://www.genesis3d.com */
\r
13 /* Software distributed under the License is distributed on an "AS IS" */
\r
14 /* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See */
\r
15 /* the License for the specific language governing rights and limitations */
\r
16 /* under the License. */
\r
18 /* The Original Code is Genesis3D, released March 25, 1999. */
\r
19 /*Genesis3D Version 1.1 released November 15, 1999 */
\r
20 /* Copyright (C) 1999 WildTangent, Inc. All Rights Reserved */
\r
22 /****************************************************************************************/
\r
23 #define WIN32_LEAN_AND_MEAN
\r
24 #include <windows.h>
\r
31 #include "basetype.h"
\r
37 #include "fsmemory.h"
\r
40 #define MEMORYFILE_SIGNATURE 0x3130464D
\r
43 #define MEMORYFINDER_SIGNATURE 0x3230464D
\r
45 #define CHECK_HANDLE(H) assert(H);assert(H->Signature == MEMORYFILE_SIGNATURE);
\r
46 #define CHECK_FINDER(F) assert(F);assert(F->Signature == MEMORYFINDER_SIGNATURE);
\r
48 #define MEMORY_FILE_GROW 0x2000
\r
50 typedef struct MemoryFile
\r
52 unsigned int Signature;
\r
57 geBoolean WeOwnMemory;
\r
61 static void * GENESISCC FSMemory_FinderCreate(
\r
64 const char * FileSpec)
\r
69 static geBoolean GENESISCC FSMemory_FinderGetNextFile(void *Handle)
\r
75 static geBoolean GENESISCC FSMemory_FinderGetProperties(void *Handle, geVFile_Properties *Props)
\r
81 static void GENESISCC FSMemory_FinderDestroy(void *Handle)
\r
86 static void * GENESISCC FSMemory_Open(
\r
91 unsigned int OpenModeFlags)
\r
96 static void * GENESISCC FSMemory_OpenNewSystem(
\r
100 unsigned int OpenModeFlags)
\r
102 MemoryFile * NewFS;
\r
103 geVFile_MemoryContext * MemContext;
\r
105 if (FS || Name || !Context)
\r
108 MemContext = Context;
\r
110 // Don't allow the user to pass in memory pointer if we're updating or creating, because
\r
111 // we don't know what allocation functions we should use to resize their block if
\r
112 // necessary. If you want to create a new file, you have to pass in NULL and let
\r
113 // us manage the allocations.
\r
114 if (MemContext->Data && (OpenModeFlags & (GE_VFILE_OPEN_UPDATE | GE_VFILE_OPEN_CREATE)))
\r
117 if (OpenModeFlags & GE_VFILE_OPEN_DIRECTORY)
\r
120 NewFS = geRam_Allocate(sizeof(*NewFS));
\r
123 memset(NewFS, 0, sizeof(*NewFS));
\r
125 NewFS->Memory = MemContext->Data;
\r
126 NewFS->Size = MemContext->DataLength;
\r
127 NewFS->AllocatedSize = NewFS->Size;
\r
131 NewFS->ReadOnly = GE_TRUE;
\r
132 NewFS->WeOwnMemory = GE_FALSE;
\r
136 NewFS->ReadOnly = GE_FALSE;
\r
137 NewFS->WeOwnMemory = GE_TRUE;
\r
140 NewFS->Signature = MEMORYFILE_SIGNATURE;
\r
145 static geBoolean GENESISCC FSMemory_UpdateContext(
\r
152 geVFile_MemoryContext * MemoryContext;
\r
159 CHECK_HANDLE(File);
\r
161 if (ContextSize != sizeof(geVFile_MemoryContext))
\r
164 MemoryContext = Context;
\r
166 MemoryContext->Data = File->Memory;
\r
167 MemoryContext->DataLength = File->Size;
\r
172 static void GENESISCC FSMemory_Close(void *Handle)
\r
178 CHECK_HANDLE(File);
\r
180 if (File->WeOwnMemory == GE_TRUE && File->Memory)
\r
181 geRam_Free(File->Memory);
\r
185 static int GENESISCC ClampOperationSize(const MemoryFile *File, int Size)
\r
187 return min(File->Size - File->Position, Size);
\r
190 static char * GENESISCC DataPtr(const MemoryFile *File)
\r
192 return File->Memory + File->Position;
\r
195 static geBoolean GENESISCC FSMemory_GetS(void *Handle, void *Buff, int MaxLen)
\r
203 assert(MaxLen != 0);
\r
207 CHECK_HANDLE(File);
\r
209 MaxLen = ClampOperationSize(File, MaxLen);
\r
218 // Bug fix thanks to Tim Brengle
\r
221 //while (*p != '\n' && MaxLen > 0)
\r
222 while (*p != '\n' && MaxLen > 1)
\r
228 File->Position += p - Start + 1;
\r
229 assert(File->Position <= File->Size);
\r
230 assert(File->Size <= File->AllocatedSize);
\r
246 static geBoolean GENESISCC FSMemory_Read(void *Handle, void *Buff, int Count)
\r
251 assert(Count != 0);
\r
255 CHECK_HANDLE(File);
\r
257 if (ClampOperationSize(File, Count) != Count)
\r
260 memcpy(Buff, DataPtr(File), Count);
\r
262 File->Position += Count;
\r
263 assert(File->Position <= File->Size);
\r
264 assert(File->Size <= File->AllocatedSize);
\r
269 static geBoolean GENESISCC TestForExpansion(MemoryFile *File, int Size)
\r
272 assert(File->ReadOnly == GE_FALSE);
\r
273 assert(File->WeOwnMemory == GE_TRUE);
\r
275 assert(File->AllocatedSize >= File->Size);
\r
276 assert(File->AllocatedSize >= File->Position);
\r
278 if (File->AllocatedSize - File->Position < Size)
\r
283 NewSize = ((File->AllocatedSize + Size + (MEMORY_FILE_GROW - 1)) / MEMORY_FILE_GROW) * MEMORY_FILE_GROW;
\r
284 NewBlock = geRam_Realloc(File->Memory, NewSize);
\r
287 File->Memory = NewBlock;
\r
288 File->AllocatedSize = NewSize;
\r
289 //printf("FSMemory: Expanded file to %d bytes\n", NewSize);
\r
295 static geBoolean GENESISCC FSMemory_Write(void *Handle, const void *Buff, int Count)
\r
300 assert(Count != 0);
\r
304 CHECK_HANDLE(File);
\r
306 if (File->ReadOnly == GE_TRUE)
\r
309 if (TestForExpansion(File, Count) == GE_FALSE)
\r
312 memcpy(DataPtr(File), Buff, Count);
\r
314 File->Position += Count;
\r
315 if (File->Size < File->Position)
\r
316 File->Size = File->Position;
\r
321 static geBoolean GENESISCC FSMemory_Seek(void *Handle, int Where, geVFile_Whence Whence)
\r
327 CHECK_HANDLE(File);
\r
333 case GE_VFILE_SEEKCUR:
\r
334 NewPos = File->Position + Where;
\r
335 if (NewPos > File->AllocatedSize)
\r
337 if (File->ReadOnly == GE_TRUE)
\r
339 if (TestForExpansion(File, Where) == GE_FALSE)
\r
342 File->Position = NewPos;
\r
345 case GE_VFILE_SEEKEND:
\r
346 if (File->Size < Where)
\r
348 File->Position = File->Size - Where;
\r
351 case GE_VFILE_SEEKSET:
\r
352 if (Where > File->AllocatedSize)
\r
354 if (File->ReadOnly == GE_TRUE)
\r
356 if (TestForExpansion(File, Where - File->Position) == GE_FALSE)
\r
359 File->Position = Where;
\r
363 assert(!"Unknown seek kind");
\r
366 if (File->Position > File->Size)
\r
367 File->Size = File->Position;
\r
369 assert(File->Size <= File->AllocatedSize);
\r
370 assert(File->Position <= File->AllocatedSize);
\r
375 static geBoolean GENESISCC FSMemory_EOF(const void *Handle)
\r
377 const MemoryFile * File;
\r
381 CHECK_HANDLE(File);
\r
383 if (File->Position == File->Size)
\r
389 static geBoolean GENESISCC FSMemory_Tell(const void *Handle, long *Position)
\r
391 const MemoryFile * File;
\r
395 CHECK_HANDLE(File);
\r
397 *Position = File->Position;
\r
402 static geBoolean GENESISCC FSMemory_Size(const void *Handle, long *Size)
\r
404 const MemoryFile * File;
\r
408 CHECK_HANDLE(File);
\r
410 *Size = File->Size;
\r
415 static geBoolean GENESISCC FSMemory_GetProperties(const void *Handle, geVFile_Properties *Properties)
\r
417 assert(!"Not implemented");
\r
421 static geBoolean GENESISCC FSMemory_SetSize(void *Handle, long Size)
\r
423 assert(!"Not implemented");
\r
427 static geBoolean GENESISCC FSMemory_SetAttributes(void *Handle, geVFile_Attributes Attributes)
\r
429 assert(!"Not implemented");
\r
433 static geBoolean GENESISCC FSMemory_SetTime(void *Handle, const geVFile_Time *Time)
\r
435 assert(!"Not implemented");
\r
439 static geBoolean GENESISCC FSMemory_SetHints(void *Handle, const geVFile_Hints *Hints)
\r
441 assert(!"Not implemented");
\r
445 static geBoolean GENESISCC FSMemory_FileExists(geVFile *FS, void *Handle, const char *Name)
\r
450 static geBoolean GENESISCC FSMemory_Disperse(
\r
453 const char *Directory,
\r
454 geBoolean Recursive)
\r
459 static geBoolean GENESISCC FSMemory_DeleteFile(geVFile *FS, void *Handle, const char *Name)
\r
464 static geBoolean GENESISCC FSMemory_RenameFile(geVFile *FS, void *Handle, const char *Name, const char *NewName)
\r
469 static geVFile_SystemAPIs FSMemory_APIs =
\r
471 FSMemory_FinderCreate,
\r
472 FSMemory_FinderGetNextFile,
\r
473 FSMemory_FinderGetProperties,
\r
474 FSMemory_FinderDestroy,
\r
476 FSMemory_OpenNewSystem,
\r
477 FSMemory_UpdateContext,
\r
479 FSMemory_DeleteFile,
\r
480 FSMemory_RenameFile,
\r
481 FSMemory_FileExists,
\r
493 FSMemory_GetProperties,
\r
496 FSMemory_SetAttributes,
\r
501 const geVFile_SystemAPIs * GENESISCC FSMemory_GetAPIs(void)
\r
503 return &FSMemory_APIs;
\r