name: File
synopsis:

>     g++ [flags ...] file ... -l /isip/tools/lib/$ISIP_BINARY/lib_system.a

>     #include <File.h>
>     File(STREAM stream = DEF_STREAM);
>     boolean open(const SysString& filename, MODE mode = READ_ONLY);
>     boolean put(const SysString& str);
>     boolean close();

quick start:

>     File out(File::ERROR);
>     File foo_wo;
>     SysString temp_file;

>     Integral::makeTemp(temp_file);

>     if (!foo_wo.open(temp_file, File::WRITE_ONLY)) {
>       Console::put(L"Error in open");
>     }

>     SysString str1(L"testing output\n");
>     out.put(str1);

>     foo_wo.put(str1);

>     foo_wo.close();

>     File::remove(temp_file);

description:
File: a general purpose file pointer. this class abstracts file manipulations, which are operating system specific, and provides a general interface that all classes should use to access files.
An important feature of this class is that a polling strategy for opening files is built into the class. When a file open fails, it is possible that the file exists, but the network file system for the computer is in error. This happens often in unix when dealing with files using the network file system. An effective solution is simply to wait a specified time, and try again. More often than not, the next open will succeed. Since all file I/O is centralized through this class, this feature is automatically available to all isip classes.
This class also has the ability to read from stdin (Standard Input) and write to stdout (Standard Output). There are two ways this can be done. The first is to pass `IN' or `OUT' to the constructor in order to read from stdin or write to stdout, respectively ( for example: File stdinFile(File::IN); ). The second is to use the `open' method, and pass a SysString type "-" as the first argument instead of a file name. See below for an example.
When reading from stdin, the input is buffered into a temporary file which is removed when the file object is closed.
dependencies:

- Integral
- Error
- MemoryManager
- SysChar
- SysString

public constants:

- define the class name:

      static const SysString CLASS_NAME = L"File";

- define some maximum sizes:

      static const long MAX_FNAME_SIZE = PATH_MAX;

      static const long BUF_SIZE = 8192;

- error count:

      static const long BAD_COUNT = -1;

- standard file streams:

      enum STREAM { NO_STREAM = -1, OUT, IN, ERROR, DEF_STREAM = NO_STREAM };

- seek positions:

      enum SEEK {POS = SEEK_SET, POS_PLUS_CUR = SEEK_CUR, POS_PLUS_END = SEEK_END }

- i/o modes:

      enum MODE { READ_ONLY = 0, READ_PLUS, WRITE_ONLY, WRITE_PLUS, APPEND_ONLY, APPEND_PLUS, DEF_MODE = READ_ONLY };

- i/o types:

      enum TYPE { TEXT = 0, BINARY, DEF_TYPE = TEXT };

- byte-order modes:

      enum BMODE {NATIVE = 0, SWAP, BIG_ENDIAN, LITTLE_ENDIAN, DEF_BMODE = NATIVE };

- names for each of the enumerated file modes and types:

      static const char SYS_TEXT_READ_ONLY[] = "r";

      static const char SYS_TEXT_READ_PLUS[] = "r+";

      static const char SYS_TEXT_WRITE_ONLY[] = "w";

      static const char SYS_TEXT_WRITE_PLUS[] = "w+";

      static const char SYS_TEXT_APPEND_ONLY[] = "a";

      static const char SYS_TEXT_APPEND_PLUS[] = "a+";

      static const char SYS_BINARY_READ_ONLY[] = "rb";

      static const char SYS_BINARY_READ_PLUS[] = "rb+";

      static const char SYS_BINARY_WRITE_ONLY[] = "wb";

      static const char SYS_BINARY_WRITE_PLUS[] = "wb+";

      static const char SYS_BINARY_APPEND_ONLY[] = "ab";

      static const char SYS_BINARY_APPEND_PLUS[] = "ab+";

- names for each of the enumerated file type:

      static const SysString TYPE_TEXT = L"text";

      static const SysString TYPE_BINARY = L"binary";

- indention and line wrapping:

      static const SysString INDENT_STR = L"  ";

      static const SysString WRAP_TERM_STR = L"\n";

      static const SysString WRAP_PRE_INDENT_STR = L"";

      static const SysString WRAP_POST_INDENT_STR = L">";

      static const long NO_WRAP = -1;

- a string denoting a piped input/output:

      static const SysString STREAM_FILE = L"-";

- default values of the class data:

      static const long DEF_LOCK = false;

      static const long DEF_INDENT = 0;

      static const long DEF_LINE_WRAP = NO_WRAP;

      static const long DEF_OPEN_RETRY = 5;

      static const long DEF_OPEN_DELAY = 2;

- default arguments to methods:

      static const long DEF_LOCK_RETRY = 5;

      static const long DEF_LOCK_DELAY = 2;

error codes:

- error code indicating general File class error:

      static const long ERR = 1000;

- error code indicating deletion of file object without closing File:

      static const long ERR_NOTCLS = 1001;

- error code indicating that the file is not open:

      static const long ERR_NOTOPN = 1002;

- error code indicating attempt to reopen a file:

      static const long ERR_REOPEN = 1003;

- error code indicating that the file could not be closed:

      static const long ERR_CLOSE = 1004;

- error code indicating that the file could not be flushed:

      static const long ERR_FLUSH = 1005;

- error code indicating file truncation error:

      static const long ERR_TRUNCT = 1006;

- error code indicating wrap setting error:

      static const long ERR_WRAP = 1007;

- error code indicating failure to decode binary mode:

      static const long ERR_DECODE = 1008;

protected data:

- the stream type

      STREAM stream_d;

- the file pointer:

      FILE* fp_d;

- open mode and type:

      MODE mode_d;

      TYPE type_d;

- lock flag:

      boolean lock_d;

- byte-order modes: can be an absolute byte-order (LITTLE_ENDIAN or BIG_ENDIAN) or a relative order to the machine (NATIVE or SWAP)

      BMODE byte_mode_d;

- byte-swap flag: this is relative to the machine's byte-order

      boolean byte_swap_d;

- indention level:

      long indent_level_d;

- line wrapping limit:

      long line_wrap_d;

- current column position:

      long column_position_d;

- file polling: open_retry_d is the number of times that the file will be polled for opening before an error is returned. open_delay_d is the delay in seconds between attempts to open the file.

      long open_retry_d;

      long open_delay_d;

- a static array of SysString objects to keep track of temporary files:

      static SysString** temp_files_d;

      static long temp_size_d;

      static long temp_num_d;

- declare a static debug level for all class instantiations:

      static Integral::DEBUG debug_level_d;

- static memory manager:

      static MemoryManager mgr_d;

required public methods:

- static methods:

      static const SysString& name();

      static boolean diagnose(Integral::DEBUG debug_level);

- debug methods:

      static boolean setDebug(Integral::DEBUG level);

      boolean debug(const unichar* message) const;

- destructor/constructor(s):

      ~File();

      File(STREAM stream = DEF_STREAM);

- assign methods:

      these methods are omitted because we do not ever want multiple
      file pointers on the same file

- operator= methods:

      these methods are omitted because we do not ever want multiple
      file pointers on the same file

- i/o methods:

      these methods are omitted because File can not write itself to an sof file

- equality methods:

      these methods are omitted because they are not useful for File objects

- memory management methods: the clear is omitted in order to force the user to open and close files in a disciplined manner

      static void* operator new(size_t size);

      static void* operator new[](size_t size);

      static void operator delete(void* ptr);

      static void operator delete[](void* ptr);

      static boolean setGrowSize(long grow_size);

class-specific public methods:

- memory size methods:

      long memSize() const;

- swap methods: this method serves as File's assignment method

      boolean swap(File& arg);

- get/set methods:

      boolean setStreamType(STREAM arg);

      boolean setFileMode(MODE arg);

      SysString** getTempFilename();

      long getNumTempFiles();

- standard file methods:

      boolean open(const unichar* filename, MODE mode = DEF_MODE, TYPE type = DEF_TYPE);

      boolean open(const SysString& filename, MODE mode = DEF_MODE, TYPE type = DEF_TYPE);

      boolean close();

      boolean flush();

      boolean truncate(long size);

- file polling methods: this method sets the number of times a file will be polled for opening before an error is returned

      boolean setOpenRetry(long retry, long delay);

- file locking methods:

      boolean lock(long retry = DEF_LOCK_RETRY, long DELAY = DEF_LOCK_DELAY);

      boolean unlock();

- positioning methods:

      boolean seek(long offset, SEEK mode);

      long tell() const;

      boolean eof() const;

      boolean rewind();

- file information methods:

      boolean isOpen() const;

      boolean isReadable() const;

      boolean isWritable() const;

      boolean isText() const;

      boolean isBinary() const;

      boolean isLocked() const;

      long size(boolean keep_position = true) const;

      static long size(const unichar* filename);

      static long size(const SysString& filename);

- single char i/o methods:

      boolean get(SysChar& chr);

      boolean put(const SysChar chr);

- string i/o methods:

      boolean get(SysString& str, long len = BUF_SIZE);

      boolean put(const SysString& str);

- buffer-based i/o methods: for binary files (with byte swapping)

      long read(void* ptr, long size, long num);

      long write(const void* ptr, long size, long num);

- formatting methods:

      boolean increaseIndention();

      boolean decreaseIndention();

      boolean setLineWrap(long ncols);

      long getLineWrap() const;

      long getLineLength() const;

- temporary file registration/cleanup methods:

      static boolean registerTemp(SysString& name);

      static boolean cleanTemps();

- disk-file operation methods:

      static boolean remove(const unichar* filename);

      static boolean remove(const SysString& filename);

      static boolean rename(const unichar* old_name, const unichar* new_name);

      static boolean rename(const SysString& old_name, const SysString& new_name);

      static boolean mkdir(const unichar* dir_name);

      static boolean mkdir(const SysString& dir_name);

      static boolean rmdir(const unichar* dir_name);

      static boolean rmdir(const SysString& dir_name);

      static boolean exists(const unichar* filename);

      static boolean exists(const SysString& filename);

      static boolean compare(const unichar* file1, const unichar* file2);

      static boolean compare(const SysString& file2, const SysString& file2);

- byte-order related methods:

      boolean setBMode(BMODE mode);

      BMODE getBMode() const;

- get the machine's byte-order methods:

      BMODE getMachineByteOrder() const;

- single value encode/decode methods:

      int16 encode(int16 value) const;

      int32 encode(int32 value) const;

      int64 encode(int64 value) const;

      int16 decode(int16 value) const;

      int32 decode(int32 value) const;

      int64 decode(int64 value) const;

- string manipulation methods:

      boolean substr(SysString& str, long offset, long num_elements = Integral::NO_POS) const;

- string search methods:

      long firstStr(const unichar* str, long start = Integral::NO_POS) const;

      long firstStr(const SysString& str, long start = Integral::NO_POS) const;

private methods:

- copy constructor: this is declared private so it cannot be called for the File class

      File(const File& arg);

- buffer encode/decode methods: they are used by read() and write()

      boolean encode(void* buf, long size, long nitems) const;

      boolean encode(void* obuf, const void* ibuf, long size, long nitems) const;

      boolean decode(void* buf, long size, long nitems) const;

      boolean decode(void* obuf, const void* ibuf, long size, long nitems) const;

example 1:

- This example shows how to open the file (shown in quick start) and read the string back in:

      // get a temporary file name
      //
      SysString temp_file;
      Integral::makeTemp(temp_file);

      // declare a file for writing
      //
      File write_file;

      // open the temporary file in write mode
      //
      if (!write_file.open(temp_file, File::WRITE_ONLY)) {
        Console::put(L"Error in open");
      }

      // create a string to write and write it to the file
      //
      SysString str1(L"testing output\n");
      write_file.put(str1);

      // close the file
      //
      write_file.close();

      // create a file for reading
      //
      File read_file;

      // open the temporary file for reading
      //
      if (read_file.open(temp_file, File::READ_PLUS)) {

        // lock the file so no one can edit it while we read
        //
        read_file.lock();

        // get the string out of the file
        //
        SysString str2;
        read_file.get(str2);

        // we should have read in the same file that we wrote
        //
        if (str2.ne(L"testing output")) {
          Console::put(L"Error in getString");
        }

        // release the file lock and close the file
        //
        read_file.unlock();
        read_file.close();
      }
      else {
        Console::put(L"Error in open");
      }

      // delete the temporary file
      //
      File::remove(temp_file);

example 2:

- The following example demonstrates one way to use the File class to read from stdin and write to stdout.

      // Create file objects.
      //
      File read_stdin;
      File write_stdout;

      // Initialize one string to "-"
      // and create a second to store output.
      //
      SysString str1(L"-");
      SysString str2;

      // "-" is passed as the first argument to
      // the open method to set the object to access
      // stdin/stdout. The second argument determines
      // whether the File object will read from stdin,
      // or write to stdout.
      //
      // In this case the object will read from stdin.
      //
      if(read_stdin.open(str1, File::READ_ONLY)){
        read_stdin.get(str2);
      }
      else {
        Console::put(L"Error Opening Stdin\n");
      }

      // Destroy the object.
      //
      read_stdin.close();

      // Again "-" is passed. This time the object
      // will write to stdout.
      //
      if(write_stdout.open(str1, File::WRITE_ONLY)){
        write_stdout.put(str2);
      }
      else {
        Console::put(L"Error Opening Stdout");
      }

      // Destroy the object.
      //
      write_stdout.close();

notes:

- The swap method helps to avoid possible memory problems when multiple pointers point to the same file
- Temporary files registered through the File::registerTemp() method will automatically be deleted upon exit (through either the normal Integral::exit() or the exception handling Error::exit()). If you generated the name for your temporary files through Integral::makeTemp they will automatically be registered through this system. You can still delete a temporary file if you like with File::remove(), the automated system will only delete those files that still exist.