[Alephmodular-devel] Good progress on CFiles!
Status: Pre-Alpha
Brought to you by:
brefin
|
From: Br'fin <br...@ma...> - 2003-02-11 04:31:29
|
After working up the basics of the streams and the files types. Then
getting the existing API working using the classes, I expanded upon
CFileDesc and actually managed to push this through the code.
Things appear to be working still for saving and loading files and
handling preferences and vidmaster replays. All that really remains is
for me to cleanup the code a bit more so I can land this version.
In the meantime, I updated my document based upon what I've actually
implemented. So while I work on cleaning up the code, you can check out
what it looks like. I find myself fairly happy with the way this is
looking. Especially after having stumbled across clone methods to help
smooth out some spots that had a lot of potential for trouble.
-Jeremy Parsons
Note: This document is still evolving. But is being used to guide the
process
and is being updated to reflect final code.
Technical Specification: File Hardware Abstraction
First there was portable_files.h and it was good in concept. But there
was only a Macintosh implementation. And even so, there was an evident
bios in the structure towards the Macintosh.
Please note that this does not handle file browsing. That is in the
realm of the GUI.
Platform specific stuff can use the platform specific CFileDesc
constructor.
IE MacOS X would support CFileDesc_Carbon(FSSpec&)
CFileDescFactory is a singleton class that provides access to a set of
base CFileDesc locations.
But in order to navigate, you can't use just create a CFileDesc(...).
Instead you either use a platform specific filebrowser, or you find
files programatically by asking for a CFileDesc pointed at a standard
directory and then navigating through its subdirectories.
Since CFileDescFactory is a singleton, you get access to it's current
instance via CFileDescFactory::get_instance().
And a CFileDescFactory instance implements the following methods that
all return a CFileDesc*. You are responsible for deleting the pointer
when you are done with it.
CFileDesc* get_application_directory() const
The directory the application has been run from
(Typically Current dir if command line, directory of application
executable otherwise)
CFileDesc* get_preferences_directory() const
The location to store a user's specific settings
CFileDesc* get_save_game_directory() const
Default location to save games
CFileDesc* get_replay_directory() const
Default location to save replays. Most notably the replay that is
automatically
recorded whenever you play a game.
CFileDesc* get_resources_directory() const
Where to find other required support files. For instance theme files
for an SDL build.
CFileDesc represents a file or directory's location.
Under Unix, this would be the full path to a file. Under Macintosh this
is akin to a FSSpec. Most typically it refers to a parent directory and
knows the name of its object within that directory.
Most notably this has functions for creating the specified file,
opening the file for reading, or opening the file for writing.
The basic strategy for CFileDesc is to get an initial CFileDesc, either
from a platform specific file browser or by asking CFileDescFactory for
a CFileDesc to a specific directory. The CFileDesc is then malleable.
You can navigate it down within subdirectories to specify the file you
want. And when you are done you free your CFileDesc.
A CFileDesc implements the IFailable interface for reporting errors
during operations. See CError.h for more information on IFailable.
A given platform specific derivative should accept platform native file
specifications. (For interfacing with native file browsers)
Basic properties (Not necessarily public!) Internal represenation is
definitly platform dependant. For instance CFileDesc_Carbon implements
the basic information using MacOS FSSpec records.
The parent directory of the pointed to file or directory
The name of the current file or directory
The type of the current file or directory
See CFileType for more about the type of the element
Basic public operations include:
bool clone(CFileDesc*&)
Returns whether or not the cloning was successful
If successful, clone creates an entire duplicate of the current
CFileDesc. You are responsible for maintaining and deleting this copy.
If unsuccessful check the IFailable interface for errors. (Hence why
clone isn't a const method)
bool exists() const
Returns true if the referred to file or directory exists in the file
system
bool is_file() const
Returns true if the referred to item exists and is a file
bool is_directory() const
Returns true if the referred to item exists and is a directory
void get_name(std::string&) const
Returns in the passed string the name of the current file or directory
public file operations (These are errors if called on a directory)
void set_type(const CFileType& type)
Specifies the type of the file. You must call this before calling
create_file()
const CFileType& get_type() const
Returns the current type of the file. In the future this will be
expected to confer with the CFileType mechanisms to determine the
type of an arbitrary file.
bool create_file()
Creates the file specified by the CFileDesc at that location. It will
delete
a file that already exists in that location.
Returns true on success or false and an IFailable error state on
failure.
bool delete_file()
Deletes the specified file from the file system.
Returns true on success or false and an IFailable error state on
failure.
bool open_for_reading(IFileRef&)
Opens the specified file for binary reading and returns an istream
compatible class. You are responsible for deleting the returned class.
Returns true on success or false and an IFailable error state on
failure.
bool open_for_writing(OFileRef&)
Opens the specified file for binary writing and returns an ostream
compatible class. You are responsible for deleting the returned class.
Returns true on success or false and an IFailable error state on
failure.
open_resources_for_reading (Returns CResourceFileRef)
Not currently implemented
public directory operations (IDirectoryDesc) (These are errors if
called on a file)
Not currently implemented beyond navigate()
bool navigate(const std::string& _name)
On success, return true and the CFileDesc points to the new element.
On failure, for instance drilling down into multiple undefined
directories, navigate returns false, sets an IFailable error state
and doesn't change the location of the CFileDesc.
Note that it should be ok to specify one level of non-existing element
so you can then create it.
Protected operations
bool iofname(std::string&)
Returns an if/ofstream compatible path for the file. Used internally
for
initially opening the files for reading/writing. This means a platform
specific class has less to do, only needing to convert the platform
specific representation into a path type string.
swap(CFileDesc)
Safe Save support
Swaps contents of two file descs
These should be two files on the same device and use OS file swapping
calls where available
Not currently implemented.
Navigation of CFileDescs would include methods to work based on the
CFileDesc
ala CFileDesc GetParent() to get the parent of this directory
and CFileDesc GetNamedChild(itemname)
GetTemporaryCopy
Returns a CFileDesc to a temporary file in the same directory as the
current CFileDesc, the name should be unique and the file shouldn't
already exist.
IFileRef represents an open file for reading. Specifically it is a
typedef std::istream* IFileRef
COFileRef represents an open file for writing. Specifically it is a
typedef std::ostream* OFileRef
To close files of this sort, you should explicitly delete the class.
Save saving is not yet implemented.
A note on saving files. When you open a file for writing the following
transpires. You are given an ofstream derived object that is internally
associated with the current CFileDesc and a temporary one. The
temporary CFileDesc is guaranteed to be in the same directory as
CFileDesc and to have a unique name.
Upon proper closure of the stream the temporary file the following
happens.
If CFileDesc exists, than the temporary file is swapped with it and the
original content of CFileDesc discard (swap occurs, then temporary file
deleted) Otherwise the temporary file is renamed to the name in
CFileDesc.
ofstream.close() isn't virtual, so we can't override it, but it does
have a virtual destructor. Within there we can do:
this->close()
if(this->is_good()) // The closing of the file didn't raise any errors
{
curFileDesc.swap(tempFileDesc);
tempFileDesc.delete();
}
CResourceFileRef represents an open resource file.
We will support reading of resources. We will support a way of reading
in resources from a data file. We won't generally support saving of
resource files. (Any new file formats heading forward should be flat
files or bundles (multiple files in a strict directory hierarchy)
Resource files are not yet implemented.
CFileType represents the type of a file
CFileDesc is our friend and can use the protected virtual methods for
getting type_code, type_extension and the type checking.
There are three special cases of CFileType
CDirectoryType
a plain old directories
(a directory that was a bundle would be handled seperately)
CUnknownType
If we examine a CFileDesc and it matches no known types,
then CUnknownType is the tye used for the file
CFamilyType
A hierarchy of types for checking a file's type against. For
instance, checking if a given specific type is a map or a M2 file.
CCreatorFamilyType is a subset of the family type which also knows
its creator code.
All others descend from CTypedFileType which has basic operations
A file type generally encapsulates the following:
The file's creator: ala M2, Minf, or AlephModular)
The four character code associated with a file on MAcintosh: aka TEXT
The extension associated with the file on other systems: aka txt (as
in README.txt)
a test() method for checking whether or not a CFileDesc matches the
current type
a test_contents() method for checking within a file for a type match
Testing CDirectoryType against file decriptions only matches type with
directories
Testing CUnknownType against file descriptions is always false. It is
only assigned when either nothing is known, or everything else fails to
match.
Testing CFamilyType against file descriptions always fails.
Testing CTypedFileTypes against a file succeeds if type and creator
match or if the extension matches. Subclasses may perform more
complicated tests, such as inspecting the file's contents (by
implementing test_contents(FileDesc*))
test_contents() is seperate from test() so that if a first pass by
inspecting via test fails to locate a file's type, then that file can
be checked over the available types by performing the content tests of
the types.
FileTypes support a matches(FileType) method to tell if the type who's
matching method is being called considers itself to be the type of the
argument, or a logical element of that type's set.
CMarathon2MapType.matches(CAlephModularMapType) == false
CMarathon2MapType.matches(CMarathon2MapType) == true
CMarathon2MapType.matches(CMapFamily) == true
CMarathon2MapType.matches(CMarathon2Family) == true
I admit, on typing I'm trying to figure out if the class is
C<whatever>Type and is essentially a singleton. What is a decent way of
referring to one specific type or another?
A CFileTypeFactory that offers GetTypeFor("<whatever>") with a hash or
dictionary within?
Here are the existing families
Creators:
CAlephModularFamilyType
CMarathon2FamilyType
Files:
CImagesFamilyType
CMapFamilyType
CMusicFamilyType
CPhysicsFamilyType
CPreferencesFamilyType
CReplayFamilyType
CSaveGameFamilyType
CShapesFamilyType
CSoundsFamilyType
Actual File Types:
CAlephModularPreferencesFileType
CAlephModularReplayFileType
CAlephModularSaveGameFileType
CMarathon2ImagesFileType
CMarathon2MapFileType
CMarathon2PhysicsFileType
Cmarathon2ReplayFileType
CMarathon2ShapesFileType
CMarathon2SoundsFileType
File organization details:
Initial work will proceed in portable_files.h, files_macintosh.cpp,
Support/CFiles.cpp, Support/CFileTypes.h, Support/CFileTypes.cpp, and
CFileDesc_Carbon.h. At a later point in time when files are
reorganized, this will become
Support/CFiles.h (was portable_files.h)
Support/CFiles.cpp
Support/Carbon/CFileDesc_Carbon.h
Support/Carbon/CFileDesc_Carbon.cpp (was files_macintosh.cpp)
Support/CFileTypes.h
Support/CFileTypes.cpp
|