#charset "us-ascii"
/*
* Copyright (c) 2001, 2006 Michael J. Roberts
*
* This file is part of TADS 3.
*
* This header defines the File intrinsic class.
*/
#ifndef _FILE_H_
#define _FILE_H_
/* include our base class definition */
#include "systype.h"
/*
* File methods use the CharacterSet and ByteArray intrinsic
* classes, so include their headers to make sure they're available to
* File users.
*/
#include "charset.h"
#include "bytearr.h"
/* ------------------------------------------------------------------------ */
/*
* File access modes. These are used when calling the file open methods
* to specify how the file is to be accessed.
*/
/*
* Read mode - the file is opened for reading (writing is not allowed).
* When opened in this mode, the file must exist, or a
* FileNotFoundException is thrown from the open method.
*/
#define FileAccessRead 0x0001
/*
* Write mode - the file is opened for writing (reading is not allowed).
* When opened in this mode, if the file doesn't already exist, a new file
* is created; if the file does already exist, the existing data in the
* file are discarded (i.e., the file is truncated to zero length) on
* open.
*/
#define FileAccessWrite 0x0002
/*
* Read/write mode, keeping existing contents - the file is opened for
* both reading and writing. If the file does not exist, a new file is
* created. If the file does already exist, the existing contents of the
* file are kept intact on open.
*/
#define FileAccessReadWriteKeep 0x0003
/*
* Read/write mode, truncating existing contents - the file is opened for
* both reading and writing. If the file does not exist, a new file is
* created. If the file does already exist, the existing contents of the
* file are discarded (i.e., the file is truncated to zero length) on
* open.
*/
#define FileAccessReadWriteTrunc 0x0004
/* ------------------------------------------------------------------------ */
/*
* Special file identifiers. These identifiers can be passed to the 'open'
* routines in place of the filename string argument.
*
* The actual name and location of a special file is determined by the
* interpreter. Since games use these internal identifiers rather than the
* actual system filenames when accessing special files, different
* interpreters can adapt to different local conventions without bothering
* the game code with the details. The game code simply refers to the file
* it wants using the virtual identifier, and the interpreter takes care of
* the rest.
*
* Note that special files generally bypass the interpreter "file safety"
* settings. This is important because it allows the library and games a
* degree of controlled access to the file system, even when the file
* safety settings wouldn't normally allow similar access for arbitrary
* file operations. Even though this special file access can bypass the
* file safety level, it doesn't compromise security, because the
* interpreter has exclusive control over the names and locations of the
* special files - thus a game can only access the particular files that
* the interpreter designates as special, and can't use special files to
* access arbitrary file system entities.
*/
/*
* The library defaults file. This is the special file where the library
* stores user-controlled start-up default settings.
*/
#define LibraryDefaultsFile 0x0001
/* ------------------------------------------------------------------------ */
/*
* The File intrinsic class provides access to files in the external file
* system. This lets you create, read, and write files. The class
* supports text files (with translations to and from local character
* sets), "data" files (using the special TADS 2 binary file format), and
* "raw" files (this mode lets you manipulate files in arbitrary text or
* binary formats by giving you direct access to the raw bytes in the
* file).
*/
intrinsic class File 'file/030002': Object
{
/*
* File has no constructors, so it is not possible to create a File
* with the 'new' operator. To create a file, use one of the static
* creator methods instead:
*
* f = File.openTextFile()
*
* All of the open methods throw exceptions if the open fails:
*
* FileNotFoundException - indicates that the requested file doesn't
* exist. This is thrown when the access mode requires an existing
* file but the named file does not exist.
*
* FileCreationException - indicates that the requested file could not
* be created. This is thrown when the access mode requires creating
* a new file but the named file cannot be created.
*
* FileOpenException - indicates that the requested file could not be
* opened. This is thrown when the access mode allows either an
* existing file to be opened or a new file to be created, but neither
* could be accomplished.
*
* FileSafetyException - the requested access mode is not allowed for
* the given file due to the current file safety level set by the
* user. Users can set the file safety level (through command-line
* switches or other preference mechanisms which vary by interpreter)
* to restrict the types of file operations that applications are
* allowed to perform, in order to protect their systems from
* malicious programs. This exception indicates that the user has set
* a safety level that is too restrictive for the requested operation.
*/
/*
* Static creator method: open a text file. Returns a File object
* that can be used to read or write the file. 'access' is the
* read/write mode, and must be one of FileAccessRead or
* FileAccessWrite. 'charset' is a CharacterSet object, or can
* optionally be a string naming a character set, in which case a
* CharacterSet object for the named character set will automatically
* be created. If 'charset' is omitted, a default "us-ascii"
* character set will be used.
*
* When a file is opened in text mode for reading, each call to
* readFile() reads and returns a line of text from the file. When a
* file is opened in text mode for writing, any existing file is
* discarded and replaced with the new data. Each read and write to a
* text file is mapped through the CharacterSet in effect at the time
* of the read or write.
*/
static openTextFile(filename, access, charset?);
/*
* Static creator method: open a file in 'data' mode. Returns a File
* object that can be used to read or write the file. 'access'
* indicates the desired read/write access and the disposition of any
* existing file; any of the FileAccessXxx modes can be used.
*
* When a file is opened in data mode, you can read and write
* integers, strings, and 'true' values to the file, and the values in
* the file are marked with their datatype in a private data format.
* Because the file uses a tads-specific format, this mode cannot be
* used to read files created by other applications or write files for
* use by other applications; however, this storage format is
* convenient for storing simple data values because the File object
* takes care of converting to and from a portable binary format.
*/
static openDataFile(filename, access);
/*
* Static creator method: open a file in 'raw' mode. Returns a File
* object that can be used to read or write the file. 'access'
* indicates the desired read/write access mode and the disposition of
* any existing file; any of the FileAccessXxx modes can be used.
*
* When a file is opened in raw mode, only ByteArray values can be
* read and written. The File object performs no translations of the
* bytes read or written. This mode requires the calling program
* itself to perform all data conversions to and from a raw byte
* format, but the benefit of this extra work is that this mode can be
* used to read and write files in arbitrary data formats, including
* formats defined by other applications.
*/
static openRawFile(filename, access);
/*
* get the CharacterSet object the File is currently using; returns
* nil for a non-text file
*/
getCharacterSet();
/*
* Set the CharacterSet object the File is to use from now on. This
* is not meaningful except for text files. 'charset' must be a
* CharacterSet object; in particular note that a character set name
* given as a string is not allowed here.
*/
setCharacterSet(charset);
/*
* Close the file. Flushes any buffered information to the underlying
* system file and releases any system resources (such as share locks
* or system buffers) associated with the file. After this routine is
* called, no further operations on the file can be performed (a
* FileClosedException will be thrown if any subsequent operations are
* attempted).
*
* It's not strictly necessary to call closeFile() on a File, since the
* system will automatically do this work when the File object becomes
* unreachable and is discarded by the garbage collector. However, it
* is good practice to close a file explicitly by calling this method
* as soon as the program reaches a point at which it knows it's done
* with the file, because garbage collection might not run for a
* significant amount of time after the program is actually done with
* the file, in which case the system resources associated with the
* file would be needlessly retained for this extended time.
*/
closeFile();
/*
* Read from the file. Returns a data value that depends on the file
* mode, as described below, or nil at end of file.
*
* If the file is open in text mode, this reads a line of text from the
* file and returns a string with the text of the line read. A line of
* text is a sequence of characters terminated with a line-ending
* sequence, which is a carriage return, line feed, CR/LF pair, LF/CR
* pair, or a Unicode line terminator character (0x2028) if the file is
* being read with one of the Unicode encodings. If the line read ends
* in a line-ending sequence, the returned text will end in a '\n'
* character, regardless of which of the possible line-ending sequences
* is actually in the file, so the caller need not worry about the
* details of the external file's format. Every line read from the
* file will end in a '\n' except possibly the last line - if the file
* does not end with a line-ending sequence, then the last line read
* from the file will not end in a '\n' character. All bytes read from
* the file will be mapped to characters through the CharacterSet
* object currently in effect in the file, so the returned string will
* always be a standard Unicode string, regardless of the byte encoding
* of the file.
*
* If the file is open in 'data' mode, this reads one data element
* using the private tads-specific data format. The result is a value
* of one of the types writable with writeFile() in 'data' mode. In
* order to read a 'data' file, the file must have been previously
* written in 'data' mode.
*/
readFile();
/*
* Write to the file. Writes the given value to the file in a format
* that depends on the file mode, as described below. No return
* value; if an error occurs writing the data, this throws a
* FileIOException.
*
* If the file is open in text mode, this writes text to the file,
* converting the given value to a string if necessary (and throwing
* an error if such a conversion is not possible), and translating the
* string to be written to bytes by mapping the string through the
* CharacterSet object currently in effect for the file. Note that no
* line-ending characters are automatically added to the output, so if
* the caller wishes to write line terminators, it should simply
* include a '\n' character at the end of each line.
*
* If the file is open in 'data' mode, this writes the value, which
* must be a string, integer, enum, or 'true' value, in a private
* tads-specific data format that can later be read using the same
* format. The values are converted to the private binary format,
* which is portable across platforms: a file written in 'data' mode
* on one machine can be copied (byte-for-byte) to another machine,
* even one that uses different hardware and a different operating
* system, and read back in 'data' mode on the new machine to yield
* the original values written.
*/
writeFile(val);
/*
* Read bytes from the file into the given ByteArray object. This can
* only be used for a file opened in 'raw' mode. If 'start' and 'cnt'
* are given, they give the starting index in the byte array at which
* the bytes read are to be stored, and the number of bytes to read,
* respectively; if these are omitted, one byte is read from the file
* for each byte in the byte array.
*
* Returns the number of bytes actually read into the byte array,
* which will be less than or equal to the number requested. If the
* number read is less than the number requested, it means that the
* end of the file was encountered, and only the returned number of
* bytes were available.
*/
readBytes(byteArr, start?, cnt?);
/*
* Write bytes from the ByteArray object into the file. This can only
* be used for a file opened in 'raw' mode. If 'start' and 'cnt' are
* given, they give the starting index in the byte array of the bytes
* to be written, and the number of bytes to write, respectively; if
* these are omitted, all of the bytes in the array are written.
*
* No return value; if an error occurs writing the data, a
* FileIOException is thrown.
*/
writeBytes(byteArr, start?, cnt?);
/*
* Get the current read/write position in the file. Returns the byte
* offset in the file of the next byte to be read or written. Note
* that this value is an offset, so 0 is the offset of the first byte
* in the file.
*/
getPos();
/*
* Set the current read/write position in the file. 'pos' is a byte
* offset in the file; 0 is the offset of the first byte.
*
* For files in 'text' and 'data' modes, a caller should NEVER set the
* file position to any value other than a value previously returned
* by getPos(), because other positions might violate the format
* constraints. For example, if you move the file position to a byte
* in the middle of a line-ending sequence in a text file, subsequent
* reading from the file might misinterpret the sequence as something
* other than a line ending, or as an extra line ending. If you move
* the position in a 'data' file to a byte in the middle of an integer
* value, reading from the file would misinterpret as a data type tag
* a byte that is part of the integer value instead. So it is never
* meaningful or safe to set an arbitrary byte offset in these file
* formats; only values known to be valid by virtue of having been
* returned from getPos() can be used here in these modes.
*/
setPos(pos);
/*
* Set the current read/write position to the end of the file. This
* can be used, for example, to open a 'data' mode file for
* read/write/keep access (keeping the contents of an existing file)
* and then adding more data after all of the existing data in the
* file.
*/
setPosEnd();
/*
* Static creator method: open a resource in 'text' mode. This acts
* like openTextFile(), but rather than opening an ordinary file, this
* method opens a resource. Resources differ from ordinary files in
* two important respects. First, a resource is named with a
* URL-style path rather than a local file system name. Second, a
* resource can be embedded in the program's executable (.t3) file, or
* can be embedded in an external resource bundle (.3r0, etc) file.
*
* Resources are read-only, so the access mode is implicitly
* FileAccessRead.
*/
static openTextResource(resname, charset?);
/*
* Static creator method: open a resource in 'raw' mode. This acts
* like openRawFile(), but opens a resource rather than an ordinary
* file.
*
* Resources are read-only, so the access mode is implicitly
* FileAccessRead.
*/
static openRawResource(resname);
/* get the size in bytes of the file */
getFileSize();
}
#endif /* _FILE_H_ */
TADS 3 Library Manual
Generated on 4/11/2008 from TADS version 3.0.16