[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Remarks on Files/Filenames



>  From: Sander van der Wal <svdwal@xs4all.nl>
>  ...
>  > >    BinReaderDesc = RECORD
>  > >      PROCEDURE (r: BinaryReader) ReadBool(VAR b: BOOLEAN);
>  > >      PROCEDURE (r: BinaryReader) ReadSet (VAR s: SET);
>  > >    END;
>  > Those two procs only appear in BinReader/Writer.  I don't see any
>  > reason why we can't spend those types a textual representation and add
>  > them to TextReader/Writer, too.
>  ...
>  A possible text representation could be TRUE and FALSE for Boolean
>  vaules and {10101...} for set vaules.
>   
I had such a representation in mind.  My idea was to be able to
exchange for debugging purposes a binary writer with a text writer.

>  > A GetDate procedure is missing.  Input: file name.  Output: time value
>  > plus error code.  How do we represent a time?  For Unix a time value
>  > is a record with a seconds and a microseconds field, both LONGINT.
>  > Anyone got a better idea?
>  
>  Your right again, I forgot it. I think a separate DateTime-type 
>  will be best, with PROCEDURE's to 
>    - test whether two datetimes are equal,
>    - test whether one datetime is smaller than the other
>    - test whehter a datetime is between two others
>    - to create a datetime from year, month, day, hour etc
>    - to make a string from a datetime.
>    
SysClock exports such a data type, but it is rather clumsy to do the
above operations or simple calculations like addition or subtraction
on it.  An additional representation is necessary IMO.

>  The Files module (or equivalent) should export the minimum and 
>  maximum datetime a File can have. The datetime of the last 
>  modification should be a readonly parameter (I think this is what
>  most OS'ses do) , and there should be a SetDate-method. Writer's 
>  should update the datetime of their associated File.
>  
Better make the time of last modification a hidden (File) attribute,
accessed by a tb procedure, since this value is always obtained from
the underlying OS.

>  
>  > Filenames: I'm missing any way to represent directories different than
>  > strings.  Maybe it would pay of to split a file name into a directory
>  > locator plus file name/extension.  A system-independent facility to
>  > get a directory's file listing would also be nice.  But I don't now if
>  > this is feasible at all.
>   
>  I think a Directories or FileDir module is feasable. A FileDir.Old
>  procedure will have a Filename as it's input parameter. A FileDir.
>  Enumerate will return a File or a FileDir. For this to work File
>  and FileDir should be derived from something more basic, like a
>  DirTreeEntry. This object will have the same attributes as a File
>  in my Files module, but no Riders can be associated with them. 
>  
I suggested a similar scheme in the below pseudo module, but I suggest
to differentiate more clearly between file and directory name.

>  > Just my two cents for now.  I hope that Files and Filenames will be
>  > intgrated into a more general class hierachy based on locators and
>  > channels.
>  
>  As soon as I know exactly what a Locator and a Channel is, this should 
>  be no problem. Besides, by not saying that a Filename is some kind
>  of Locator does not mean is isn't, mainly because clients of Filename
>  are interested in the Filename-aspects of the Filename, not if they are
>  derived from a more abstract class.
>  
Agreed.  Most aspects of file names are very specific, but it has the
one general purpose to point to some data.  This aspect is shared by a
lot of other locators (e.g. all URLs), and should be adequately
modeled in the IO libs.

--------

This is an outline of the abstract types that can serve as a basis for
building the IO libs.  Implementations of physical channels, like
FileLocator and FileChannel, would extend the the types ChannelLocator
and Channel.
  Note that all types described in the below pseudo module define
nothing more than a set of common functionality of their extensions.
They don't have any functionality themself; variables of one of those
types should never be created. 
  A module like the Oberon/F `Stores' would build on the Channel type
to define binary and textual readers and writers to do load and store
integer, real, string, etc values.  The Channel itself provides only
procedures for unstructured, BYTE based IO.
  The minimum set of devices implemented as extensions of Channel are
files, stdin, stdout, stderr, null, and (maybe) program arguments.
I'm sorry that I can't be more specific here, but I can't spend much
time on this right now.

-- mva

MODULE LowChannel;

TYPE
  Locator* = POINTER TO LocatorDesc;
  LocatorDesc* = RECORD
  (* abstract type;  a Locator designates either a channel or a directory; 
     used to turn entries of a directory into a ChannelLocator or a 
     DirectoryLocator *)
  END;
  



TYPE
  ChannelLocator* = POINTER TO ChannelLocator;
  ChannelLocatorDesc* = RECORD
  (* abstract type; such a ChannelLocator designates a Channel (see below) and
     allows to open the Channel using Old resp. New *)
    (LocatorDesc)
    PROCEDURE (loc: ChannelLocator) New(): Channel;
    PROCEDURE (loc: ChannelLocator) Old(): Channel;
    (* both New and Old may fail if the locator is invalid, or the user has no
       permissions to access the channel in the desired way (eg opening a
       read-only file with New) *)
  END;
  
TYPE
  Channel* = POINTER TO ChannelDesc;
  ChannelDesc* = RECORD
  (* a Channel is a chunk of bytes; it has certain attributes; byte readers 
     and writers can be attached to it *)
  (* possible attributes: readable, writable, length; other attributes (eg 
     positionable) may better be attached to reader/writer *)
    PROCEDURE (c: Channel) Length(): LONGINT;
    PROCEDURE (c: Channel) NewReader(): Reader;
    PROCEDURE (c: Channel) NewReader(): Writer;
    PROCEDURE (c: Channel) Flush;
    PROCEDURE (c: Channel) Close;
    PROCEDURE (c: Channel) Register(...);  (not so sure about this one)
  END;
  

TYPE 
  Reader* = POINTER TO ReaderDesc;
  ReaderDesc* = RECORD
    eof: BOOLEAN;
    PROCEDURE (r: Reader) Base(): Channel;
    PROCEDURE (r: Reader) Pos(): LONGINT;
    PROCEDURE (r: Reader) SetPos(pos: LONGINT);
    PROCEDURE (r: Reader) ReadByte(VAR x: BYTE);
    PROCEDURE (r: Reader) ReadBytes(VAR x: ARRAY OF BYTE; len: LONGINT);
    (* note that, except for Base, all the above procs mail fail *)
  END;

(* Writer: similar to Reader *)


  
TYPE
  DirectoryLocator* = POINTER TO DirectoryLocator;
  DirectoryLocatorDesc* = RECORD
  (* abtract type; refers to a collection of locators *)
    (LocatorDesc)
    PROCEDURE (loc: DirectoryLocator) New(): Directory;
    PROCEDURE (loc: DirectoryLocator) Old(): Directory;
    (* New creates a new directory, Old reads the contents of an existing
       directory *)
  END;

TYPE
  Directory* = POINTER TO DirectoryDesc;
  DirectoryDesc* = RECORD
  (* a Directory is a list of (guess what) directory entries; a single entry 
     can be turned into a Locator (eg ChannelLocator or DirectoryLocator);
     this definition differs from Oberon/F, where a directory refers to a whole
     file system, but has the advantage that it models more closely the common
     case of a hierachical file structure; examples for directories: file
     dir, mails in a mail folder, groups of a news server *)
    entries: DirectoryEntry;
    (* contains a list of directory entries *)
    
    PROCEDURE (dir: Directory) Rescan;
    (* brings internal list of directory entries up to date *)
  END;
  
TYPE
  DirectoryEntry* = POINTER TO DirectoryEntryDesc;
  DirectoryEntryDesc* = RECORD
    next, prev: DirectoryEntry
    
    PROCEDURE (de: DirectoryEntry) Locator(): Locator;
    (* turns an arbitrary entry into a valid Locator (if possible); most of the
       time the result will be a ChannelLocator (eg a FileLocator) or a
       DirectoryLocator (to model a hierachical directory structure) *)
  END;
  
END LowChannel.