![]()
geVFile
Description: Virtual file interface
Source file: …\genesis3d\OpenSource\Source\VFile\vfile.h
Contents:
Functions:
AddPath, Close , CreateFinder, DeleteFile, DestroyFinder, EOF , FileExists, FinderGetNextFile, FinderGetProperties, GetContext, GetProperties, GetS, Open, OpenNewSystem, Printf, Read, RenameFile, Seek, SetAttributes, SetHints, SetSize, SetTime, Size, Tell, TimeToWin32FileTime, UpdateContext, WriteTypes:
geVFile, geVFile_Attributes, geVFile_Finder, geVFile_Hints, geVFile_MemoryContext, geVFile_Properties, geVFile_Time, geVFile_TypeIdentifierMacros:
GE_VFILE_ATTRIB_READONLY, GE_VFILE_ATTRIB_DIRECTORY,GE_VFILE_OPEN_READONLY, GE_VFILE_OPEN_UPDATE,GE_VFILE_OPEN_CREATE,GE_VFILE_OPEN_DIRECTORY,GE_VFILE_TYPE_DOS, GE_VFILE_TYPE_MEMORY,GE_VFILE_TYPE_VIRTUALTutorial:
Table of ContentsAdditions for Genesis3D v1.6: None
![]()
Types:
typedef struct geVFile geVFile;
NOTE: The contents of this structure have been intentionally left out of the interface, by the designers of this module. Think of this as a handle only.
Return to Contents
;
typedef unsigned int geVFile_Attributes;
NOTE: The contents of this structure have been intentionally left out of the interface, by the designers of this module. Think of this as a handle only.
Return to Contents
typedef struct geVFile_Finder geVFile_Finder;
NOTE: The contents of this structure have been intentionally left out of the interface, by the designers of this module. Think of this as a handle only.
Return to Contents
typedef struct geVFile_Hints {
void * HintData;
int HintDataLength;
} geVFile_Hints;
Return to Contents
typedef struct geVFile_MemoryContext{
void * Data;
int DataLength;
} geVFile_MemoryContext;
Return to Contents
typedef struct geVFile_Properties{
geVFile_Time Time;
geVFile_Attributes AttributeFlags;
long Size;
geVFile_Hints Hints;
char Name[1024];
} geVFile_Properties;
Return to Contents
typedef struct geVFile_Time{
unsigned long Time1;
unsigned long Time2;
} geVFile_Time;
Return to Contents
typedef int geVFile_TypeIdentifier
NOTE: The contents of this structure have been intentionally left out of the interface, by the designers of this module. Think of this as a handle only.
Return to Contents
![]()
Macros:
GE_VFILE_ATTRIB_…
#define GE_VFILE_ATTRIB_READONLY 0x00000001
Return to Contents
GE_VFILE_OPEN_…
#define GE_VFILE_OPEN_READONLY 0x00000001
#define GE_VFILE_OPEN_DIRECTORY 0x00000008
Notes:
Return to Contents
GE_VFILE_SEEK (actually, geVFile_Whence)
typedef enum{
Return to Contents
GE_VFILE_TYPE_…
#define GE_VFILE_TYPE_DOS ( (geVFile_TypeIdentifier) 1L )
Return to Contents
![]()
Functions:
![]()
GENESISAPI geBoolean GENESISCC geVFile_AddPath(geVFile* FS1, const geVFile* FS2, geBoolean Append);
This function adds the path associated with FS2 to FS1's path list either at the end (if Append ==GE_TRUE) or at the beginning (if Append == GE_FALSE).
Returns:GE_TRUE if successful, GE_FALSE otherwise. (Currently it appears that a return value of GE_FALSE would indicate an internal error in Genesis3D.)
Notes:
Return to Contents
![]()
GENESISAPI geBoolean GENESISCC geVFile_Close (geVFile* File);
This function closes thegeVFile File previously opened by a call to geVFile_Open or geVFile_OpenNewSystem and frees up the resources.
Returns:GE_TRUE on success, GE_FALSE otherwise.
Notes:
Return to Contents
![]()
GENESISAPI FindergeVFile_Finder* GENESISCC geVFile_CreateFinder(geVFile* FileSystem, const char * FileSpec);
This function creates and returns ageVFile_Finder object to be utilized by the geVFile_FinderGet functions. The geVFile_Finder utilizes FileSystem as its root and FileSpec as the search specifier. This call should be accompanied by an eventual geVFile_DestroyFinder.
Returns: thegeVFile_Finder* created.
Notes:
Return to Contents
![]()
GENESISAPI geBoolean GENESISCC geVFile_DeleteFile(geVFile* FS, const char * FileName);
This function deletes the file specified by FileName from the FS filesystem.
Returns:GE_TRUE on success, GE_FALSE otherwise.
Notes:
Return to Contents
![]()
GENESISAPI void GENESISCC geVFile_DestroyFinder(geVFile_Finder* Finder);
This function destroys thegeVFile_Finder Finder created by a previous call to geVFile_CreateFinder freeing up its resources.
Returns: nothing.
Notes:
Return to Contents
![]()
GENESISAPI geBoolean GENESISCC geVFile_EOF (const geVFile* File);
This function test whether we have reached the End-of-File for File.
Returns:GE_TRUE if EOF has been reached, GE_FALSE otherwise.
Return to Contents
![]()
GENESISAPI geBoolean GENESISCC geVFile_FileExists(geVFile* FS, const char * FileName);
This function checks to see if the file specified by FileName exists in the file system FS. Only the path is checked, no searchlists are used.
Returns:GE_TRUE if the file exists, GE_FALSE otherwise.
Notes:
Return to Contents
![]()
GENESISAPI geBoolean GENESISCC geVFile_FinderGetNextFile(geVFile_Finder* Finder);
This function iterates to the next file under thegeVFile_Finder system. The actual file is accessed through geVFile_FinderGetProperties.
Returns:GE_FALSE if there is no file to iterate over, GE_TRUE otherwise.
Notes:
Return to Contents
![]()
GENESISAPI geBoolean GENESISCC geVFile_FinderGetProperties(const geVFile_Finder* Finder, geVFile_Properties* Properties);
This function returns the properties for the currentgeVFile pointed to by the geVFile_Finder Finder in Properties.
Returns:GE_TRUE if there is a file to return properties for, GE_FALSE otherwise.
Notes:
Return to Contents
![]()
GENESISAPI geVFile* GENESISCC geVFile_GetContext(const geVFile* File);
This function returns the "outer context" in which the file File was opened. This is currently only used by memory files and would return the address of the memory.
Returns: the result.
Notes:
Return to Contents
![]()
GENESISAPI geBoolean GENESISCC geVFile_GetProperties(const geVFile* File, geVFile_Properties* Properties);
This function returns the properties of thegeVFile File in Properties.
Returns:GE_TRUE if successful, GE_FALSE otherwise.
Return to Contents
![]()
GENESISAPI geBoolean GENESISCC geVFile_GetS(geVFile* File, void * Buff, int MaxLen);
This function returns up to MaxLen chars from File in Buff. This is intended to provide fgets functionality for geVFiles.
Returns:GE_TRUE on success, GE_FALSE otherwise.
Return to Contents
![]()
GENESISAPI geVFile* GENESISCC geVFile_Open(geVFile* FS, const char * Name, unsigned int OpenModeFlags);
This function opens the file specified by Name from the file system specified by FS with the OpenModeFlags and returns it.
Returns: the opened file.
Return to Contents
![]()
GENESISAPI geVFile* GENESISCC geVFile_OpenNewSystem(geVFile* FS, geVFile_TypeIdentifier FileSystemType, const char * Name, void * Context, unsigned int OpenModeFlags);
This function opens/creates the file specified by Name and FileSystemType in the file system FS using the mode of OpenModeFlags. The Context argument is only used by certain file types currently only represented by memory files. For memory files Context would be the pointer to the memory to used/accessed.
Returns: thegeVFile created.
Notes:
Return to Contents
![]()
GENESISAPI geBoolean GENESISCC geVFile_Printf(geVFile* File, const char * Format, ...);
This function provides printf capability to geVFiles.
Returns:GE_TRUE on success, GE_FALSE otherwise.
Return to Contents
![]()
GENESISAPI geBoolean GENESISCC geVFile_Read(geVFile* File, void * Buff, int Count);
This function reads Count bytes from File into the the buffer Buff.
Returns:GE_TRUE on success, GE_FALSE otherwise.
Return to Contents
![]()
GENESISAPI geBoolean GENESISCC geVFile_RenameFile(geVFile* FS, const char * FileName, const char * NewName);
This function renames the file specified by FileName in the file system FS to NewName.
Returns:GE_TRUE on success, GE_FALSE otherwise.
Notes:
Return to Contents
![]()
GENESISAPI geBoolean GENESISCC geVFile_Seek(geVFile* File, int where, geVFile_Whence Whence);
This function "seeks" to where in relation to Whence in file File. Whence is one of
|
GE_VFILE_SEEKCUR |
where is relative to the current file pointer |
|
GE_VFILE_SEEKEND |
where is relative to the end of the file |
|
GE_VFILE_SEEKSET |
where is relative to the beginning of the file |
Returns:GE_TRUE on success, GE_FALSE otherwise.
Return to Contents
![]()
GENESISAPI geBoolean GENESISCC geVFile_SetAttributes(geVFile* File, geVFile_Attributes Attributes);
This function sets to attributes of File to Attributes.
Returns:GE_TRUE on success, GE_FALSE otherwise.
Return to Contents
![]()
GENESISAPI geBoolean GENESISCC geVFile_SetHints(geVFile* File, const geVFile_Hints* Hints);
This function sets the hint data for File to Hints. This API is currently unsupported but will eventually apply to virtual files.
Returns:GE_FALSE in all cases.
Return to Contents
![]()
GENESISAPI geBoolean GENESISCC geVFile_SetSize(geVFile* File, long Size);
This function sets the size of File to Size. Any data beyond the new size is unrecoverable.
Returns:GE_TRUE on success, GE_FALSE otherwise.
Return to Contents
![]()
GENESISAPI geBoolean GENESISCC geVFile_SetTime(geVFile* File, const geVFile_Time* Time);
This function sets the time of File to Time.
Returns:GE_TRUE on success, GE_FALSE otherwise.
Return to Contents
![]()
GENESISAPI geBoolean GENESISCC geVFile_Size(const geVFile* File, long* Size);
This function retrieves the current size of the file File in Size.
Returns:GE_TRUE on success, GE_FALSE otherwise.
Return to Contents
![]()
GENESISAPI geBoolean GENESISCC geVFile_Tell(const geVFile* File, long* Position);
This function retrieves the current position of File's file pointer and returns it in Position.
Returns:GE_TRUE on success, GE_FALSE otherwise.
Return to Contents
![]()
GENESISAPI void GENESISCC geVFile_TimeToWin32FileTime(const geVFile_Time* , LPFILETIME Win32FileTime);
This function converts a geVFileTime to a Win32 FILETIME structure. Windows.h must be included before VFILE.H for this API to be supported.
Returns: nothing.
Notes:
Return to Contents
![]()
GENESISAPI geBoolean GENESISCC geVFile_UpdateContext(geVFile* FS, void * Context, int ContextSize);
This function returns the current context of FS in Context where ContextSize is the size of Context. This functionality is currently only implemented for memory files and it returns a pointer to the current memory buffer.
Returns:GE_TRUE on success, GE_FALSE otherwise.
Return to Contents
![]()
GENESISAPI geBoolean GENESISCC geVFile_Write(geVFile* File, const void * Buff, int Count);
This function writes Count bytes from Buff to File.
Returns:GE_TRUE on success, GE_FALSE otherwise.
Return to Contents
![]()
Tutorial:
Summary
Overview
Directories
Virtual Files
Memory Files
Search Paths
Finders
File Times
Return to Main Contents
(Note: This was copied directly from the official Genesis3D Api Reference)
Summary
geVFile is a file I/O subsystem designed to encapsulate and extend regular OS file operations.
Return to Tutorial Table of Contents
Overview
The geVFile system is intended to be used to abstract away normal file operations to allow other subsystems to read data from arbitrary sources. Included in this system is support for normal DOS files, memory files, virtual file systems and complex search paths. A memory file is a file which does its I/O operations to a block of memory, with no corresponding DOS file on disk. A virtual file system is a file which contains multiple files, potentially in a hierachy. A search path is a sequence of places to search for files to be opened.
One of the attributes of a geVFile is whether or not it is a directory. A file which is a directory can support Open operations, but not Read/Write operations. A file which is not a directory can support Read/Write operations, but not Open operations. This concept is key to understanding when you can use geVFiles for certain operations below. You may notice that we use the term file system from time to time, instead of file or geVFile. In general, we do this when referring to a file handle whose attributes indicate that it is a directory, and hence can support Open operations.
Two APIs exist for opening files. These are geVFile_OpenNewSystem, and geVFile_Open.We have diverged from the normal pattern of having Create/Destroy functions for geVFile because we did not wish to move too far from the classical model of file APIs, as these are comfortable to most developers. The difference between geVFile_OpenNewSystem and geVFile_Open is that geVFile_OpenNewSystem allows you to create a file without a prior existing geVFile, and also to specify the base system which is used for operations on the data. geVFileOpen requires that you pass in a valid geVFile to open the file from. To explain this better, we will go into a little depth on both functions here. Following this will be a walk through of the simplest way to obtain file handles, and then more complex, but more powerful ways.
The geVFile system has a mechanism for registering new file system access functions. The access functions define all possible APIs that the file system is capable of: open/close, read/write, seek, attributes etc. Each file system API (FSAPI) set allows you to access data from different media types (e.g. DOS vs memory). We have implemented three basic sets of file system access functions:
|
API |
Capability |
|
GE_VFILE_TYPE_DOS |
Supports access to DOS files and directories. |
|
GE_VFILE_TYPE_MEMORY |
Supports access to blocks of memory as files. |
|
GE_VFILE_TYPE_VIRTUAL |
Supports access to virtual file systems, |
geVFile_OpenNewSystem allows you to specify the base FSAPI used to perform operations on data, and the source of that data, in addition to the normal file access flags. A file that has been opened with geVFile_OpenNewSystem accesses that FSAPI for every file operation requested on the resulting geVFile.
geVFile_Open does not allow you to pass the FSAPI in explicitly. Instead, you pass it in implicitly by passing in a geVFile object. geVFile_Open will then use the FSAPI in the passed geVFile to perform the actual open operation. This is very powerful, as will be demonstrated below.
The APIs can be approached in steps, so we will discuss the easiest way (and the least powerful) first. The simple way to open a file (DOS only) with geVFile:
geVFile* File;
File = geVFile_OpenNewSystem(NULL, GE_VFILE_TYPE_DOS, "c:\\foo\\bar.dat", NULL, GE_VFILE_OPEN_READONLY);
The file handle created above can be used for the familiar file operations supported on individual files, such as Read, Seek and Close.
geVFile_Close is the method that you use to close a file and to destroy the geVFile object.
Return to Tutorial Table of Contents
Directories
Directories are simply files that contain other files. They are useful as an abstract concept because they permit us to define directories in places that are not quite the same as the conventional DOS directory structure. This permits the developer to write code which operates on files in directories, and replace the low level file system without having to change the high level code relying on that file system. Here is an example of how to open a DOS directory, and then open files from within that directory. Later, in the Virtual Files section, we will show you how this concept can be expanded to allow you to open files from a virtual file system without having to change much of your application code.
geBoolean OpenSomeFile(geVFile* Directory{
geVFile* File;
File =geVFile_Open(Directory, "test.txt", GE_VFILE_OPEN_READONLY);
voidmain(void){
Directory =geVFile_OpenNewSystem(NULL, GE_VFILE_TYPE_DOS, "c:\\myapp", NULL, GE_VFILE_OPEN_READONLY|GE_VFILE_OPEN_DIRECTORY);
if (OpenSomeFile(Directory) ==GE_FALSE)
Return to Tutorial Table of Contents
Virtual Files
Virtual files are single files that contain a complete directory structure, and the contents of multiple other files. They are sometimes referred to as collection files. Other parts of the industry might refer to these as PAK files. This file system defines operations on these types of files that make them completely transparent to the calling application. One purpose of the virtual file is to permit you to package up your application data into single files, and distribute that composite file as opposed to many smaller files. Runtime access to your data is extremely efficient.
In the next release of the engine, virtual file systems will be used to enable streaming operations on data to be made more efficient.
Virtual files are created by opening a file with read/write access, and then opening a new file system with the type GE_VFILE_TYPE_VIRTUAL, with the first file as the FS parameter. The file that is returned from this operation will be a directory. You can open files in it, either for read-only access, or for creation. When you do write operations to the files that you create within a virtual file system, those operations are forwarded on to the base file system used to create the virtual file system. When the virtual file system is closed, a directory is written to the base file system. When you reopen the virtual file system on the base file, the directory will be read, and used to locate the data that was written to the base file in the first place. The application code need not concern itself with these operations - as far as the client is concerned, the virtual file system just looks like a directory.
There are two ways to create virtual file systems. The first is more generic, and will work for any combination of file systems. The second is a sugar coated version which permits simple access to DOS files as virtual files. For the examples below, please refer to the definition of OpenSomeFile in the Directories example above.
voidmain(void){
// Create the virtual file system
File =geVFile_Open(VFS, "test.txt", GE_VFILE_OPEN_CREATE);
// Now reopen the virtual file system. For this example, we'll show the shortcut
Note that is perfectly OK to create directories inside a VFS. You do this just as if you were creating a directory under any file system. The VFS will maintain the hierarchy for you:
geVFile* Directory;
geVFile* File;
Directory =geVFile_Open(VFS, "MyNewDirectory", GE_VFILE_OPEN_DIRECTORY|GE_VFILE_OPEN_CREATE);
In the example above AnotherFile.txt is created within a virtual directory MyNewDirectory. If the VFS is a virtual file system, all read/write operations on AnotherFile.txt are forwarded on to the base file used to create the VFS. The VFS parameter used to create the Directory does not have to be a virtual file system. It could just be a DOS directory, in which case, you will create a directory on your disk.
Return to Tutorial Table of Contents
Memory Files
Memory files are files that have all their data in memory, not on any disk file. They can be created from an existing block of memory for read-only operations, or they can be created with no block of memory for write operations. They are useful for processing data that is embedded in your application as raw bytes. They also have applications for sending formatted data from one machine to another.
To create a memory file, you have to set up a memory file context to point to the data that you want to operate on. The context is passed into geVFile_OpenNewSystem, and a normal geVFile pointer is returned. This pointer is suitable for read/write operations only. It can be used as the base file for a virtual file system, which allows you to embed virtual file systems in your application data if you so choose. This can be useful for reading application data out of a binary resource in your executeable image, for example.
In the first example below, we open a memory file on an existing block of memory, and read from it. In the second example, we create a memory file for writing, passing no block of memory.
voidmain(void){
Context.Data = Data;
voidmain(void){
Context.Data =NULL;
// We want to be able to get back the data that we've written:
In the second example above, we used the function geVFile_UpdateContext to retrieve file system specific information. For Memory Files, you can retrieve a pointer to the current block of memory representing the file, along with its size. This pointer is valid only until the next operation on that file. You must treat the pointer as const. This API was added specifically to permit you to obtain the data from a memory file efficiently. It will also be used in the future to allow the client to obtain more specific information about particular file systems. In short, it's a back door.
Return to Tutorial Table of Contents
Search Paths
Search paths are a way of chaining multiple file systems together to allow open and search operations that fail on one file system to be retried on other file systems before potentially returning failure. Search paths were created with two goals in mind. First, it is desireable for users to be able to override file definitions with data of their own (for texture replacement, or patches, for example). Second, it is useful, from a configurable installation standpoint, to be able to have some files installed on your hard disk, some on a CDROM, and not have to change the application code to deal with arbitrary file location configurations. Search paths can make this easy.
For the first case, suppose that you have your application data in a virtual file, including textures for some backdrops. Now suppose that you want to allow the user to override your backdrop textures with texture files of their own. Here is one way to accomplish this:
geVFile* VFS;
geVFile* Directory;
geVFile* TextureDirectory;
VFS =geVFile_OpenNewSystem(NULL, GE_VFILE_TYPE_VIRTUAL, "c:\\myapp\\AppData.vfs", NULL,
In the example code above, we create a virtual directory from a virtual file that contains all our application data. We also open a true DOS directory, and add it as an alternative directory to look for files in. The GE_FALSE parameter to geVFile_AddPath makes the DOS directory become the first directory to be searched, followed by the virtual directory. If the application opens foo.bmp from TextureDirectory, the DOS directory c:\myapp\UserTextures will be searched first for the file. If the file is found there, it will be opened from there. If the file is not found there, then the virtual directory will be searched. Hence the user can override the definition of foo.bmp in your virtual file by placing foo.bmp in the UserTextures directory. This gives you very fine control over what the user can override, without having to change your underlying application code very much at all. You just set up the initial directories at application startup, and pass them around to your subsystems, which are oblivious to the indirections.
For the second case, suppose that you have a minimal install option which installs a few files to the local hard disk, but leaves most behind on a CD, and you want the application code to be able to deal with this easily. Here is how you could set this up.
geVFile* ApplicationDirectory;
geVFile* CDDirectory;
ApplicationDirectory =geVFile_OpenNewSystem(NULL, GE_VFILE_TYPE_DOS, "c:\\myapp, NULL, GE_VFILE_OPEN_UPDATE|GE_VFILE_OPEN_DIRECTORY);
Now, open operations on ApplicationDirectory will look first in the local DOS directory, and then on the CD. All the application has to do is pass around ApplicationDirectory, and files will be opened from the correct locations for any install configuration.
Return to Tutorial Table of Contents
Finders
Finders are objects that you use to locate files within a file system. They can also be used to iterate the files in a file system. You use them just as you would the findfirst and findnext functions under the RTL, with a slight change to the iteration sequence.
You create a finder with geVFile_CreateFinder, passing it a geVFile, which must be a directory, and a file spec to search for. To get to the first file in the finder, call geVFile_FinderGetNextFile. You can get to subsequent files by calling geVFile_FinderGetNextFile again. This makes the application code a little easier for iterating files:
geVFile_Finder* Finder;
Finder =geVFile_CreateFinder(Directory, "*.*");
Return to Tutorial Table of Contents
File Times
File times are an issue because we did not wish to reinvent the wheel for time/date APIs. Because of this, we provide access to file times in the APIs, but provide no means for interpreting these values. Instead, we have included a single API - geVFile_TimeToWin32FileTime - which you can use to convert the internal file times to a format that can be handled by the Win32 API for manipulating file times. This was done to avoid the need for a largely redundant API set that has limited value. If you wish to break out components of a file's time, convert it to Win32 format, and use the Win32 APIs.
Return to Tutorial Table of Contents
Return to Main Contents
End of Tutorial