Re: [Alephmodular-devel] TS Draft: File abstraction
Status: Pre-Alpha
Brought to you by:
brefin
From: Woody Z. I. <woo...@sb...> - 2003-01-24 15:56:09
|
A couple thoughts up front... On Friday, January 24, 2003, at 01:39 AM, Br'fin wrote: > 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. And perhaps rightly so, at least for things like resource forks that we have to deal with but which (obviously) impose a Mac bias. (I haven't reviewed portable_files.h, so maybe there is more Mac bias than the "some" that needs to be there.) Obviously at the moment the SDL and Mac A1s are sharing code at some level and splitting apart into separate file handling code at some level - any analysis/comments on the situation there? My guess would be that the split comes too high since (IMO) that seems to be the case with most Mac/SDL splits in A1. > Please note that this does not handle file browsing. That is in the > realm of the GUI. So will there be a standard interface for things like "locate files that match my filter" (which may be used for populating a file browsing dialog) etc.? Such a thing would also be useful for a set of paths to search for a given file. > Platform specific stuff can use the platform specific CFileDesc > constructor. > IE Mac would wave CMacFileDesc(FSSpec&) > > But in order to naviagte, you can't use CFileDesc(...) You would need > to use a factory to build up the CFileDesc... ala > > CFileDesc *foo = FILE_DESC_FACTORY->ConstructFileDesc(CFileDesc > *directory, "file"); > ... > delete foo; So far this is a comment, an observation, not a quibble or recommendation etc., but... note that if you have multiple factories at once, the above construction requires that the program know which factory it should use at all times. If directory FileDescs that came from Factory A should always produce FileDescs from Factory A (and never from Factory B), then it would be better to have FileDescs know which factory they came from (either by virtue of the class structure, or by explicitly keeping a reference to the factory) and ask a FileDesc for a sub-FileDesc. (Or ask a FileDesc for its factory, and ask that for a sub-FileDesc, which maybe should be an option but asking the FileDesc directly is provided as a convenience method.) > The factory is also the most reasonable place to provide access to > CFileDescs for specific platform specific places. Ala preferences > directory and application directory > > CFileDesc *foo = FILE_DESC_FACTORY- > >GetSpecificDir(CFileDescFactory::ApplicationsDirectory); > // It is an error to delete this foo > > Specific directories so far are > ApplicationDirectory - The directory the application has been run from > (Current dir if command line, directory of application > executable otherwise) > PreferencesDirectory Note that some platforms may want to install and find data files somewhere other than the application directory. In general I think having more "specific directories", even if they map to the same real directory in practice, is going to be a Good Thing as it gives different platforms the opportunity to put things where they want at a finer granularity. Maybe on the whole I'm not understanding the role this plays in a larger system, but I have questions like: what about resource forks? what about searching multiple places? what _about_ support for file browsing? what about retrieving a directory's contents? etc. I like centralizing (in a Factory) all the explicit paths etc. - and since every FileDesc will come from one of these root FileDescs (right? well except for FileDescs that come from the OS-native representation I guess, but the Factory could be used for those too), the Factory gets to determine the C++ type of the FileDesc we end up using - but I am not sure what other benefits it offers (e.g., why _is_ it better to ask the Factory for a FileDesc every time we want a file within a directory, instead of asking the directory's FileDesc?). Please discuss. > CFileDesc represents a file'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 file within that directory. > Most notably this has functions for creating the specified file, > opening the file for reading, or opening the file for writing. > > A given platform specific derivative should accept platform native > file specifications. (For interfacing with native file browsers) > > Operations include > create_file > open_file_for_reading (Returns CFileRef) > open_file_for_writing (Returns CFileRef) > delete_file > > > CFileRef represents an open file > > Operations include > get_fpos > set_fpos > set_eof > get_file_length > read_file > write_file > close_file And a CFileRef is, I hope, a subclass of some more-general "read and write chunks of data" scheme that's also the basis for the "Packing" (serialization) stuff, rather like SDL_RWops, that provides the same interface for working with chunks of data in memory as it does for working with chunks of data in files. (SDL_RWops provides seek, tell, get length, close, and various read and write operations, both "raw" and packing- (and byte-swapping-) oriented.) A CFileRef would be allowed to return its CFileSpec on request of course. Memory chunks would return a special value (maybe NULL?) instead to indicate they're not file-backed. I'm not sure whether this involves a dynamic_cast<> and a subclass-specific query, or a "top-level" query to the CDataRef itself. (There may wish to be a corresponding method to get the base address of a CBufferRef also, for example.) Perhaps there would be a mechanism to associate a memory chunk with a file, that creates the file and writes out the memory chunk. But that could be dangerous if some folks start using the new CFileRef object for reading and writing, but others have still retained and are trying to use the CBufferRef (or whatever). Perhaps the interface should only support saving the buffer into a file, forcing the programmer to explicitly close the buffer (hmm, should be reference counted somehow?) and open the file, and then give the CFileRef to whomever needs it, to emphasize that they're two separate objects. What about "safe saves"? Should there be sort of built-in support for that sort of thing at a fairly low level? Man all this reinventing-the-wheel stuff really does make me wish we were sitting on top of libFoundation or something ;) I guess the important question to ask is "what flexibility/better platform-dependent conformance/etc. are we buying with this extra layer of wrapping?" I mean, why NOT just use some kind of standard mechanism like iostreams or stdio? at least for most of the interface? (you could supplement those mechanisms with some kind of abstraction only where needed.) I mean, they're there, they're familiar, they're tested, and they're not going to be going away any time soon. (I recognize that there are benefits to wrapping. I would just like to see them made explicit as part of the reasoning/justification.) Anyway please don't take any of the above really as 'argument', I'm glad to see a specific suggestion as a starting point and hope that a discussion (including "devil's advocate" questions to expose more detail and strengthen the underlying reasoning) will bring to light any appropriate alterations. Like I said, I don't have a good picture of where CFileSpec fits into the bigger structure, so a lot of the things I asked about could be irrelevant in the limited context of CFileSpec itself - but if they're not handled there, then where? Now I guess I'd better get on the stick with regard to the networking/input system eh? :) Woody |