123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964 |
- ////////////////////////////////////////////////////////////////////////////////
- //
- // Copyright 2016 RWS Inc, All Rights Reserved
- //
- // This program is free software; you can redistribute it and/or modify
- // it under the terms of version 2 of the GNU General Public License as published by
- // the Free Software Foundation
- //
- // This program is distributed in the hope that it will be useful,
- // but WITHOUT ANY WARRANTY; without even the implied warranty of
- // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- // GNU General Public License for more details.
- //
- // You should have received a copy of the GNU General Public License along
- // with this program; if not, write to the Free Software Foundation, Inc.,
- // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- //
- //////////////////////////////////////////////////////////////////////////////
- //
- // File.h
- //
- // History:
- // 07/29/95 JMI Started.
- //
- // 01/22/97 JMI Added NeutralEndian which never byte swaps and additional
- // overload for Open() to open memfiles that grow when writes
- // exceed their bounds.
- //
- // 01/28/97 JMI Added yet another Open() overload that allows one to open
- // an existing FILE* stream with an RFile.
- //
- // 01/28/97 JMI Added yet another Open() overload that allows one to open
- // an existing FILE* stream with an RFile.
- // And yet another Open() which opens from another RFile
- // that is already attached to disk or memory. This is use-
- // ful for descended classes such as RIff (so they can sub-
- // class an existing RFile).
- //
- // 02/04/97 MJR/JMI Added RFileEZSave() and RFileEZLoad() that are meant
- // to replace the myclass.Load(char*) and
- // myclass.Save(char*) that has been written so far for
- // nearly every class that loads and saves. These new funcs
- // are essentially macros that will allocate an RFile, open
- // it with the specified filename, permissions, and endian
- // format, call the specified class's Load or Save, check
- // for error, close the RFile, and deallocate the RFile.
- //
- // 02/05/97 JMI Protected Read and Write for void* (see comments there
- // for details). Consequently, I had to add an overload
- // for char* that was being caught by the void* version
- // before.
- // Also, added Read and Writes for RPixel32.
- //
- // 02/10/97 JMI Added rspAnyLoad() and rspAnySave(). There are two types
- // of implementations for these functions. One is the
- // explicit overload where someone defines an rspAnyLoad/Save
- // specific to the overloaded type and the other is implicit
- // in that there is a template function that catches all the
- // ones that don't have an explicit overload.
- // Also, added explicit overloads for most RFile supported
- // types.
- //
- // 02/10/97 JMI RFILE_INSTANTIATE_ANYLOAD and SAVE had a bug where they
- // returned the number of items read or written instead of
- // 0 indicating success or non-zero indicating failure.
- //
- // 06/28/97 MJR Metrowerks compiler has a problem with explicit functions
- // being created AFTER templates of the same name are
- // defined. I simply rearranged the order so it works.
- //
- // 10/06/99 JMI rspEZSave() was not deleting its RFile when done.
- //
- //////////////////////////////////////////////////////////////////////////////
- //
- // See CPP comment for details.
- //
- //////////////////////////////////////////////////////////////////////////////
- #ifndef FILE_H
- #define FILE_H
- //////////////////////////////////////////////////////////////////////////////
- // Headers.
- //////////////////////////////////////////////////////////////////////////////
- #include <stdio.h>
- #include "Blue.h"
- // If PATHS_IN_INCLUDES macro is defined, we can utilized relative
- // paths to a header file. In this case we generally go off of our
- // RSPiX root directory. System.h MUST be included before this macro
- // is evaluated. System.h is the header that, based on the current
- // platform (or more so in this case on the compiler), defines
- // PATHS_IN_INCLUDES. Blue.h includes system.h so you can include that
- // instead.
- #ifdef PATHS_IN_INCLUDES
- #ifdef ALLOW_RFILE_REOPEN
- #include "ORANGE/CDT/List.h"
- #endif // ALLOW_RFILE_REOPEN
- #else
- #ifdef ALLOW_RFILE_REOPEN
- #include "List.h"
- #endif // ALLOW_RFILE_REOPEN
- #endif // PATHS_IN_INCLUDES
- //////////////////////////////////////////////////////////////////////////////
- // Macros.
- //////////////////////////////////////////////////////////////////////////////
- #ifdef ALLOW_RFILE_REOPEN
- #define KEEPCONNECTEDANDUPDATELASTACCESS Reconnect(), m_lLastAccess = rspGetMilliseconds()
- #else // ALLOW_RFILE_REOPEN
- #define KEEPCONNECTEDANDUPDATELASTACCESS
- #endif // ALLOW_RFILE_REOPEN
- #define MAX_MODE_LEN 6
- #define MAX_NAME_LEN 512
- // Size of buffer used to byte swap by Write(). It'd be safe to make sure
- // this number is a multiple of 8 (our largest base type is 8 bytes).
- #define RFILE_SWAP_SIZE 1024
- //////////////////////////////////////////////////////////////////////////////
- // Typedefs.
- //////////////////////////////////////////////////////////////////////////////
- // Forward declared for typedef'd protos.
- class RFile;
- //////////////////////////////////////////////////////////////////////////////
- class RFile
- {
- public: // Typedefs & Enums.
- // Use for flags field of Open():
- typedef enum
- {
- // No flags.
- NoFlags = 0x0000,
- // Binary mode. All numbers written to file as numbers.
- Binary = 0x0001,
- // ASCII mode. All numbers written to file as text.
- Ascii = 0x0002
- } Flags;
- // Use for endian field of Open and SetEndian calls.
- typedef enum
- {
- BigEndian, // Big endian (byte swaps on little endian systems).
- NeutralEndian, // Neutral endian (Never byte swaps).
- LittleEndian // Little endian (byte swaps on big endian systems).
- } Endian;
- typedef short (*OpenHook)( // Returns 0 to bypass default Open's
- // functionality. Non-zero for normal ops.
- RFile* pfile, // Pointer to RFile being opened.
- const char* pszFileName, // File path and name to open.
- const char* pszFlags, // Open flags ala fopen.
- Endian endian, // Endian nature of file.
- long lUser); // User value.
- typedef short (*CloseHook)( // Returns 0 to bypass default Close's
- // functionality.
- RFile* pfile, // Pointer to RFile being closed.
- long lUser); // User value.
- // This is the type of the function that is called before every disk
- // read or write operation to let the user know of (and, perhaps, act
- // upon) delays that may occur.
- typedef void (*CritiCall)( // Returns nothing.
- long lBytes); // Bytes about to be read or written.
- public: // Construction/Destruction.
- // Default constructor.
- RFile(void);
- // Destructor.
- ~RFile(void);
- //////////////////////////////////////////////////////////////////////////////
- public: // Methods.
- ////////////////////////////////////////////////////////////////////////
- // Open, Close, and operation flags.
- ////////////////////////////////////////////////////////////////////////
- // Open file pszFileName with fopen flags pszFlags and endian format
- // endian { RFile::Big, RFile::Little }.
- // Returns 0 on success.
- short Open( // Returns 0 on success.
- const char* pszFileName, // Filename to open.
- const char* pszFlags, // fopen flags to use for opening.
- Endian endian, // { RFile::BigEndian | RFile::LittleEndian | RFile::NeutralEndian }.
- Flags flags = // See comments in Typedefs & Enums section
- Binary); // above.
- // Open memory pFile of size lSize and endian format endian.
- // Size and location of memory will not be affected by RFile.
- // { RFile::Big, RFile::Little }.
- // Returns 0 on success.
- short Open( // Returns 0 on success.
- void* pFile, // Pointer to memory to open.
- long lSize, // Size of *pFile in bytes.
- Endian endian); // { RFile::BigEndian | RFile::LittleEndian | RFile::NeutralEndian }.
- // Open memory pFile of size lSize and endian format endian.
- // RFile may size and or relocate the memory in order to expand the memory file.
- // Deallocates on Close().
- // { RFile::Big, RFile::Little }.
- // Returns 0 on success.
- short Open( // Returns 0 on success.
- long lSize, // Size in bytes to begin with.
- long lGrowSize, // Min amount in bytes to grow memory file when written passed end.
- // Note: The larger of lGrowSize and the amount overwritten will
- // be allocated in the case of an overrun.
- Endian endian); // { RFile::BigEndian | RFile::LittleEndian | RFile::NeutralEndian }.
- // Open an existing FILE* stream.
- // Once a FILE* is opened, you can use this class's Close() instead of fclose(),
- // if that is more convenient.
- short Open( // Returns 0 on success.
- FILE* fs, // FILE* stream to open.
- Endian endian, // { RFile::BigEndian | RFile::LittleEndian | RFile::NeutralEndian }.
- Flags flags = // See comments in Typedefs & Enums section
- Binary); // above.
- // Open an existing RFile.
- // "Ack!" you say ... and I agree.
- // This basically begins what I like to think of as a synchronization between two RFiles.
- // This RFile snags the current state (basically copies the members) from the specified
- // RFile. Then, one can use the new RFile to access the file/memory/whatever that the
- // original RFile is attached to. When Close() is called, the synchronization is finsished
- // by updating the original RFile with the state from this.
- // Danger: Do not access the original RFile between Open(RFile*)/Close() pairs!
- short Open( // Returns 0 on success.
- RFile* pfile); // RFile to open.
- // Sets an Open(char*...) hook. NOTE: You CAN call any RFile Open from
- // within an Open hook. The Open hook should return 0 to bypass RFile's
- // functionality.
- static void SetOpenHook(OpenHook hook, long lUser)
- { ms_hOpen = hook; ms_lOpenUser = lUser; }
- // Change the endian format used to read/write the file.
- // Returns nothing.
- void SetEndian(Endian endian);
- // Set the size of the buffer used to read from the disk.
- // This function only applies to files open from the disk.
- // Returns 0 on success.
- short SetBufferSize(size_t stBufSize)
- {
- if (IsFile() == TRUE)
- {
- KEEPCONNECTEDANDUPDATELASTACCESS;
- return (short)setvbuf(m_fs, NULL, _IOFBF, stBufSize);
- }
- else
- if (IsMemory() == TRUE)
- return 0;
- else
- return -1;
- }
- // Close a file successfully opened with Open().
- // Returns 0 on success.
- short Close(void);
- // Sets a Close() hook. NOTE: You CAN call any RFile Close from
- // within a Close hook. The Close hook should return 0 to bypass RFile's
- // functionality.
- static void SetCloseHook(CloseHook hook, long lUser)
- { ms_hClose = hook; ms_lCloseUser = lUser; }
- ////////////////////////////////////////////////////////////////////////
- // Position.
- ////////////////////////////////////////////////////////////////////////
- // Seeks within the file based on the supplied position argument
- // { SEEK_SET, SEEK_CUR, SEEK_END }.
- // Returns 0 on success.
- short Seek(long lPos, long lOrigin);
- // Returns the current file position or -1 on error.
- long Tell(void);
- ////////////////////////////////////////////////////////////////////////
- // Read.
- ////////////////////////////////////////////////////////////////////////
- protected:
- // NOTE: THIS FUNCTION IS PROTECTED FOR AN IMPORTANT REASON:
- // This function was a catch all for any unsupported type. The dis-
- // advantage was that, if you had a type that needed to be swapped
- // but was not supported, this API would happily accept it, but not
- // swap it. This could cause hard to detect problems.
- // If you are reading or writing something that does not require
- // swapping, cast it as U8* or S8*.
- // Reads lNum bytes from currently open file.
- // Returns number of bytes successfully read.
- long Read(void* pData, long lNum);
- public:
- // Reads lNum char values from currently open file.
- // Returns number of char values successfully read.
- long Read(char* pcData, long lNum)
- { return Read((void*)pcData, lNum); }
- // Reads lNum U8 values from currently open file.
- // Returns number of U8 values successfully read.
- long Read(U8* pu8Data, long lNum = 1L);
- // Reads lNum S8 values from currently open file.
- // Returns number of S8 values successfully read.
- long Read(S8* ps8Data, long lNum = 1L);
- // Reads lNum U16 values from currently open file.
- // Returns number of U16 values successfully read.
- long Read(U16* pu16Data, long lNum = 1L);
-
- // Reads lNum S16 values from currently open file.
- // Returns number of S16 values successfully read.
- long Read(S16* ps16Data, long lNum = 1L);
- // Reads lNum RPixel24 values from currently open file.
- // Returns number of RPixel24 values successfully read.
- long Read(RPixel24* ppix24, long lNum = 1L);
- // Reads lNum U32 values from currently open file.
- // Returns number of U32 values successfully read.
- long Read(U32* pu32Data, long lNum = 1L);
- // Reads lNum S32 values from currently open file.
- // Returns number of S32 values successfully read.
- long Read(S32* ps32Data, long lNum = 1L);
- // Reads lNum RPixel32 values from currently open file.
- // Returns number of RPixel32 values successfully read.
- long Read(RPixel32* ppix32Data, long lNum = 1L)
- { return Read((U32*)ppix32Data, lNum); }
- // Reads lNum U64 values from currently open file.
- // Returns number of U64 values successfully read.
- long Read(U64* pu64Data, long lNum = 1L);
- // Reads lNum S64 values from currently open file.
- // Returns number of S64 values successfully read.
- long Read(S64* ps64Data, long lNum = 1L);
- // Reads lNum float values from currently open file.
- // Returns number of float values successfully read.
- long Read(float* pfData, long lNum = 1L);
- // Reads lNum double values from currently open file.
- // Returns number of double values successfully read.
- long Read(double* pdData, long lNum = 1L);
- // Reads a NULL terminated string. The '\0' must be
- // actually in the file to denote the end of the string.
- // pszString must point to a memory block sufficiently large
- // enough to hold the string.
- // Returns number of characters successfully read,
- // including the NULL terminator (unlike strlen()).
- long Read(char* pszString);
- ////////////////////////////////////////////////////////////////////////
- // Write.
- ////////////////////////////////////////////////////////////////////////
- protected:
- // NOTE: THIS FUNCTION IS PROTECTED FOR AN IMPORTANT REASON:
- // This function was a catch all for any unsupported type. The dis-
- // advantage was that, if you had a type that needed to be swapped
- // but was not supported, this API would happily accept it, but not
- // swap it. This could cause hard to detect problems.
- // If you are reading or writing something that does not require
- // swapping, cast it as U8* or S8*.
- // Writes lNum bytes from currently open file.
- // Returns number of bytes successfully written.
- long Write(const void* pData, long lNum);
- public:
- // Writes lNum char values to currently open file.
- // Returns number of U8 values successfully written.
- long Write(const char* pcData, long lNum)
- { return Write((void*)pcData, lNum); }
- // Writes lNum U8 values to currently open file.
- // Returns number of U8 values successfully written.
- long Write(const U8* pu8Data, long lNum = 1L);
- // Writes lNum S8 values to currently open file.
- // Returns number of S8 values successfully written.
- long Write(const S8* ps8Data, long lNum = 1L);
- // Writes lNum U16 values to currently open file.
- // Returns number of U16 values successfully written.
- long Write(const U16* pu16Data, long lNum = 1L);
- // Writes lNum S16 values to currently open file.
- // Returns number of S16 values successfully written.
- long Write(const S16* ps16Data, long lNum = 1L);
- // Writes lNum RPixel24 values to currently open file.
- // Returns number of RPixel24 values successfully written.
- long Write(const RPixel24* ppix24, long lNum = 1L);
- // Writes lNum U32 values to currently open file.
- // Returns number of U32 values successfully written.
- long Write(const U32* pu32Data, long lNum = 1L);
- // Writes lNum S32 values to currently open file.
- // Returns number of S32 values successfully written.
- long Write(const S32* ps32Data, long lNum = 1L);
- // Writes lNum RPixel32 values to currently open file.
- // Returns number of RPixel32 values successfully written.
- long Write(const RPixel32* ppix32Data, long lNum = 1L)
- { return Write((U32*)ppix32Data, lNum); }
- // Writes lNum U64 values to currently open file.
- // Returns number of U64 values successfully written.
- long Write(const U64* pu64Data, long lNum = 1L);
- // Writes lNum S64 values to currently open file.
- // Returns number of S64 values successfully written.
- long Write(const S64* ps64Data, long lNum = 1L);
- // Writes lNum float values to the currently open file.
- // Returns number of float values successfully written.
- long Write(const float* pfData, long lNum = 1L);
- // Writes lNum double values to the currently open file.
- // Returns number of double values successfully written.
- long Write(const double* pdData, long lNum = 1L);
- // Writes a NULL terminated string. The '\0' must be
- // actually written to file to denote the end of the string.
- // Returns number of characters successfully written,
- // including the NULL terminator (unlike strlen()).
- long Write(const char* pszString);
- ////////////////////////////////////////////////////////////////////////
- // These functions write one value when passed by value.
- // This is useful for writing literals, variables that should be written
- // by other than their type, and for variables of types that are not
- // pointer overloaded by other Write(type*, long) RFile functions.
- ////////////////////////////////////////////////////////////////////////
- // Writes one char.
- long Write(char cVal)
- { return Write(&cVal, 1); }
- // Writes one U8.
- long Write(U8 u8Val)
- { return Write(&u8Val); }
- // Writes one S8.
- long Write(S8 s8Val)
- { return Write(&s8Val); }
- // Writes one U16.
- long Write(U16 u16Val)
- { return Write(&u16Val); }
- // Writes one S16.
- long Write(S16 s16Val)
- { return Write(&s16Val); }
- // Writes one RPixel24.
- long Write(RPixel24 pix24Val)
- { return Write(&pix24Val); }
- // Writes one U32.
- long Write(U32 u32Val)
- { return Write(&u32Val); }
- // Writes one S32.
- long Write(S32 s32Val)
- { return Write(&s32Val); }
- // Writes one RPixel32.
- long Write(RPixel32 pix32Val)
- { return Write(&pix32Val); }
- // Writes one float.
- long Write(float fVal)
- { return Write(&fVal); }
- // Writes one U64.
- long Write(U64 u64Val)
- { return Write(&u64Val); }
- // Writes one S64.
- long Write(S64 s64Val)
- { return Write(&s64Val); }
- // Writes one double.
- long Write(double dVal)
- { return Write(&dVal); }
- //////////////////////////////////////////////////////////////////////////////
- public: // Querries.
- ////////////////////////////////////////////////////////////////////////
- // Querries.
- ////////////////////////////////////////////////////////////////////////
- // Returns TRUE, if open, FALSE if closed.
- short IsOpen(void) { return (m_fs == NULL && m_pucFile == NULL ? FALSE : TRUE); }
- // Returns TRUE, if connected to a non-memory file.
- short IsFile(void) { return (m_fs == NULL ? FALSE : TRUE); }
- // Returns TRUE, if connected to a memory file.
- short IsMemory(void) { return (m_pucFile == NULL ? FALSE : TRUE); }
- // Returns FALSE if no error has occurred on this stream; TRUE if an
- // error has occurred.
- short Error(void)
- {
- if (IsFile() == TRUE)
- {
- KEEPCONNECTEDANDUPDATELASTACCESS;
- return (ferror(m_fs) == 0 ? FALSE : TRUE);
- }
- else
- if (IsMemory() == TRUE)
- return m_sMemError;
- else
- return TRUE;
- }
- // Clears any error that has occurred on this stream.
- void ClearError(void)
- {
- if (IsFile() == TRUE)
- {
- KEEPCONNECTEDANDUPDATELASTACCESS;
- clearerr(m_fs);
- }
- else
- if (IsMemory() == TRUE)
- m_sMemError = FALSE;
- }
- // Returns TRUE if end of file has been reached, FALSE otherwise.
- // For disk files, does not return TRUE until the first i/o operation
- // fails due to EOF.
- short IsEOF(void)
- {
- if (IsFile() == TRUE)
- {
- KEEPCONNECTEDANDUPDATELASTACCESS;
- return (feof(m_fs) == 0 ? FALSE : TRUE);
- }
- else
- if (IsMemory() == TRUE)
- return (m_pucCur == m_pucFile + m_lSize);
- else
- return TRUE;
- }
- // Returns the size of the file on success. Negative on error.
- long GetSize(void);
- // Returns the endian setting for this object.
- short GetEndian(void)
- { return m_endian; }
- // Returns the memory ptr if this is a memory file; NULL, otherwise.
- // NOTE: This buffer may move after any Write() call that exceeds the
- // existing buffer size.
- UCHAR* GetMemory(void)
- { return m_pucFile; }
- //////////////////////////////////////////////////////////////////////////////
- protected: // Functions for my friends.
- // Sets the instantiable user value.
- void SetUserVal(long lUser)
- { m_lUser = lUser; }
- // Gets the instantiable user value.
- long GetUserVal(void)
- { return m_lUser; }
- //////////////////////////////////////////////////////////////////////////////
- protected: // Internal functions.
- /////////// Binary Reads /////////////////////////////////////////////////////
- // Reads in 8 bit data, swapped if necessary (BWAH HA).
- long Read8( // Returns number of 8 bit items read.
- U8* pu8, // In: 8 bit data to read (swapping, if necessary).
- long lNum); // In: Number of 8 bit items to read.
- // Reads in 16 bit data, swapped if necessary.
- long Read16( // Returns number of 16 bit items read.
- U16* pu16, // In: 16 bit data to read (swapping, if necessary).
- long lNum); // In: Number of 16 bit items to read.
- // Reads in 24 bit data, swapped if necessary.
- long Read24( // Returns number of 24 bit items read.
- RPixel24* ppix24, // In: 24 bit data to read (swapping, if necessary).
- long lNum); // In: Number of 24 bit items to read.
- // Reads in 32 bit data, swapped if necessary.
- long Read32( // Returns number of 32 bit items read.
- U32* pu32, // In: 32 bit data to read (swapping, if necessary).
- long lNum); // In: Number of 32 bit items to read.
- // Reads in 64 bit data, swapped if necessary.
- long Read64( // Returns number of 64 bit items read.
- U64* pu64, // In: 64 bit data to read (swapping, if necessary).
- long lNum); // In: Number of 64 bit items to read.
- /////////// Binary Writes ////////////////////////////////////////////////////
- // Writes out 8 bit data, swapped if necessary (BWAH HA).
- long Write8( // Returns number of 8 bit items written.
- const U8* pu8, // In: 8 bit data to write (swapping, if necessary).
- long lNum); // In: Number of 8 bit items to write.
- // Writes out 16 bit data, swapped if necessary.
- long Write16( // Returns number of 16 bit items written.
- const U16* pu16, // In: 16 bit data to write (swapping, if necessary).
- long lNum); // In: Number of 16 bit items to write.
- // Writes out 24 bit data, swapped if necessary.
- long Write24( // Returns number of 24 bit items written.
- const RPixel24* ppix24, // In: 24 bit data to write (swapping, if necessary).
- long lNum); // In: Number of 24 bit items to write.
- // Writes out 32 bit data, swapped if necessary.
- long Write32( // Returns number of 32 bit items written.
- const U32* pu32, // In: 32 bit data to write (swapping, if necessary).
- long lNum); // In: Number of 32 bit items to write.
- // Writes out 64 bit data, swapped if necessary.
- long Write64( // Returns number of 64 bit items written.
- const U64* pu64, // In: 64 bit data to write (swapping, if necessary).
- long lNum); // In: Number of 64 bit items to write.
- #ifdef ALLOW_RFILE_REOPEN
- // Disconnects this RFile from the disk temporarily so that another
- // can use the FILE* that is made available. Returns 0 on success.
- short Disconnect(void);
- // Reconnects a disk file that has been previously disconnected.
- // Does nothing if connected (i.e., if m_sDisconnected == FALSE).
- // Returns 0 on success.
- short Reconnect(void);
- // Disconnect the RFile attached to disk file that was accessed
- // longest ago.
- // Returns 0 on success.
- static short MakeStreamAvailable(void);
- #endif // ALLOW_RFILE_REOPEN
- //////////////////////////////////////////////////////////////////////////////
- friend class RRes;
- //////////////////////////////////////////////////////////////////////////////
- public: // Member variables.
- FILE* m_fs; // Stdio file stream ptr.
- static CritiCall ms_criticall; // Called on every read and write with
- // the amount that is about to be
- // processed.
- protected: // Member variables.
- UCHAR* m_pucFile; // Memory file ptr.
- short m_sOwnMem; // TRUE, if RFile allocated m_pucFile.
- UCHAR* m_pucCur; // Current position in memory file.
- long m_lSize; // Size of memory file (in bytes).
- long m_lGrowSize; // Amount to grow memfile when buffer
- // overwritten.
- short m_sMemError; // TRUE if memory file access functions
- // caused an error.
- Endian m_endian; // Endian type.
- Flags m_flags; // Flags. See comments in Typedefs &
- // Enums section above.
- RFile* m_pfileSynch; // RFile this RFile is synchronized with.
- // Used on Close() to resynch.
- static U8 ms_au8SwapBuf[RFILE_SWAP_SIZE]; // Used to byte swap by Write().
- // Hook stuff.
- long m_lUser; // Instantiable hook value.
- static OpenHook ms_hOpen; // Hook for calls to Open(char*...).
- static long ms_lOpenUser; // User value passed to m_hOpen.
- short m_sOpenSem; // Semaphore to block recursion greater
- // than 1.
- static CloseHook ms_hClose; // Hook for calls to Close().
- static long ms_lCloseUser; // User value passed to m_hClose.
- short m_sCloseSem; // Semaphore to block recursion greater
- // than 1.
- #ifdef ALLOW_RFILE_REOPEN
- // Reopen stuff.
- static RList <RFile> ms_listOpen; // List of open RFiles.
- long m_lLastAccess; // Time of last access.
- char m_szFlags[MAX_MODE_LEN + 1]; // Last Open's flags.
- short m_sDisconnected; // TRUE if file has been
- // diskonnected.
- char m_szFileName[MAX_NAME_LEN + 1]; // Filename for reopening.
- #endif // ALLOW_RFILE_REOPEN
- };
- ////////////////////////////////////////////////////////////////////////////////
- // This template function offers an easy way to use any object's Load()
- // function. Most RSPiX objects have a Load() function that expects an RFile*
- // as its only parameter. This function opens the file, calls the object's
- // Load(), and closes the file, all with full error checking. Note that the
- // file mode defaults to "rb" and the endian mode defaults to LittleEndian.
- ////////////////////////////////////////////////////////////////////////////////
- #define rspEZLoad(a,b) RFileEZLoad(a,b,"rb",RFile::LittleEndian)
- #define rspEZSave(a,b) RFileEZSave(a,b,"wb",RFile::LittleEndian)
- #ifdef _DEBUG
- #define RFileEZLoad(a,b,c,d) RFileEZLoadDebug(__FILE__, __LINE__, a, b, c, d)
- #endif
- template <class ClassType>
- #ifdef _DEBUG
- short RFileEZLoadDebug(
- char* FILE_MACRO,
- long LINE_MACRO,
- #else
- short RFileEZLoad(
- #endif
- ClassType* pObject,
- char* pszName,
- char* pszMode,
- RFile::Endian endian)
- {
- short sResult = 0;
- // Create RFile object
- RFile* pFile = new RFile;
- if (pFile != 0)
- {
- // Open the file
- sResult = pFile->Open(pszName, pszMode, endian);
- if (sResult == 0)
- {
- // Call the specified object's Load()
- sResult = pObject->Load(pFile);
- // If no error was returned then check for file I/O errors. This
- // may be redundant if the object's Load() already checked for file
- // errors, but if it didn't then this becomes very important.
- if ((sResult == 0) && pFile->Error())
- {
- sResult = -1;
- #ifdef _DEBUG
- STRACE("%s(%ld):RFileEZLoad(): File I/O Error!\n", FILE_MACRO, LINE_MACRO);
- #endif
- }
- // Close the file
- pFile->Close();
- }
- else
- {
- sResult = -1;
- #ifdef _DEBUG
- STRACE("%s(%ld):RFileEZLoad(): Couldn't open file '%s'!\n", FILE_MACRO, LINE_MACRO, pszName);
- #endif
- }
-
- // Delete file object
- delete pFile;
- }
- else
- {
- sResult = -1;
- #ifdef _DEBUG
- STRACE("%s(%ld):RFileEZLoad(): Couldn't create RFile object!\n", FILE_MACRO, LINE_MACRO);
- #endif
- }
- return sResult;
- }
- ////////////////////////////////////////////////////////////////////////////////
- // This template function offers an easy way to use any object's Save()
- // function. Most RSPiX objects have a Save() function that expects an RFile*
- // as its only parameter. This function opens the file, calls the object's
- // Save(), and closes the file, all with full error checking. Note that the
- // file mode defaults to "wb" and the endian mode defaults to LittleEndian.
- ////////////////////////////////////////////////////////////////////////////////
- #ifdef _DEBUG
- #define RFileEZSave(a,b,c,d) RFileEZSaveDebug(__FILE__, __LINE__, a, b, c, d)
- #endif
- template <class ClassType>
- #ifdef _DEBUG
- short RFileEZSaveDebug(
- char* FILE_MACRO,
- long LINE_MACRO,
- #else
- short RFileEZSave(
- #endif
- ClassType* pObject,
- char* pszName,
- char* pszMode,
- RFile::Endian endian)
- {
- short sResult = 0;
- // Create RFile object
- RFile* pFile = new RFile;
- if (pFile != 0)
- {
- // Open the file
- sResult = pFile->Open(pszName, pszMode, endian);
- if (sResult == 0)
- {
- // Call the specified object's Save()
- sResult = pObject->Save(pFile);
- // If no error was returned then check for file I/O errors. This
- // may be redundant if the object's Save() already checked for file
- // errors, but if it didn't then this becomes very important.
- if ((sResult == 0) && pFile->Error())
- {
- sResult = -1;
- #ifdef _DEBUG
- STRACE("%s(%ld):RFileEZSave(): File I/O Error!\n", FILE_MACRO, LINE_MACRO);
- #endif
- }
- // Close the file
- pFile->Close();
- }
- else
- {
- sResult = -1;
- #ifdef _DEBUG
- STRACE("%s(%ld):RFileEZSave(): Couldn't open file '%s'!\n", FILE_MACRO, LINE_MACRO, pszName);
- #endif
- }
- delete pFile;
- pFile = 0;
- }
- else
- {
- sResult = -1;
- #ifdef _DEBUG
- STRACE("%s(%ld):RFileEZSave(): Couldn't create RFile object!\n", FILE_MACRO, LINE_MACRO);
- #endif
- }
- return sResult;
- }
- ////////// rspAnyLoad() and rspAnySave() /////////////////////////////////////
- // There are two types of implementations for these functions. One is the
- // explicit overload where someone defines an rspAnyLoad/Save specific to the
- // overloaded type and the other is implicit in that there is a template
- // function that catches all the ones that don't have an explicit overload.
- //////////////////////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////////////////////
- // Explicit overloads for rspAnyLoad and rspAnySave.
- //
- // NOTICE: Metrowerks compiler has a problem with these explicit functions
- // being created AFTER the templates for them are defined. The solution is
- // simply to define these BEFORE the templates.
- //////////////////////////////////////////////////////////////////////////////
- // This macro makes it easy to create explicit versions of rspAnyLoad() for
- // basic types that are supported by RFile. Could be enhanced by allowing
- // caller to specify how to cast the value before calling RFile::Read().
- #define RFILE_INSTANTIATE_ANYLOAD(type) \
- inline \
- short rspAnyLoad( /* Returns 0 on success.*/ \
- type* ptype, /* Ptr to type to load.*/ \
- RFile* pfile) /* Open RFile to load from. Must have read access.*/ \
- { \
- return (pfile->Read(ptype) == 1) ? 0 : 1; \
- }
- // This macro makes it easy to create explicit versions of rspAnySave() for
- // basic types that are supported by RFile. Could be enhanced by allowing
- // caller to specify how to cast the value before calling RFile::Write().
- #define RFILE_INSTANTIATE_ANYSAVE(type) \
- inline \
- short rspAnySave( /* Returns 0 on success.*/ \
- type* ptype, /* Ptr to float to load.*/ \
- RFile* pfile) /* Open RFile to save to. Must have write access.*/ \
- { \
- return (pfile->Write(ptype) == 1) ? 0 : 1; \
- }
- RFILE_INSTANTIATE_ANYLOAD(U8)
- RFILE_INSTANTIATE_ANYSAVE(U8)
- RFILE_INSTANTIATE_ANYLOAD(S8)
- RFILE_INSTANTIATE_ANYSAVE(S8)
- RFILE_INSTANTIATE_ANYLOAD(U16)
- RFILE_INSTANTIATE_ANYSAVE(U16)
- RFILE_INSTANTIATE_ANYLOAD(S16)
- RFILE_INSTANTIATE_ANYSAVE(S16)
- RFILE_INSTANTIATE_ANYLOAD(RPixel24)
- RFILE_INSTANTIATE_ANYSAVE(RPixel24)
- RFILE_INSTANTIATE_ANYLOAD(U32)
- RFILE_INSTANTIATE_ANYSAVE(U32)
- RFILE_INSTANTIATE_ANYLOAD(S32)
- RFILE_INSTANTIATE_ANYSAVE(S32)
- RFILE_INSTANTIATE_ANYLOAD(RPixel32)
- RFILE_INSTANTIATE_ANYSAVE(RPixel32)
- RFILE_INSTANTIATE_ANYLOAD(float)
- RFILE_INSTANTIATE_ANYSAVE(float)
- RFILE_INSTANTIATE_ANYLOAD(U64)
- RFILE_INSTANTIATE_ANYSAVE(U64)
- RFILE_INSTANTIATE_ANYLOAD(S64)
- RFILE_INSTANTIATE_ANYSAVE(S64)
- RFILE_INSTANTIATE_ANYLOAD(double)
- RFILE_INSTANTIATE_ANYSAVE(double)
- //////////////////////////////////////////////////////////////////////////////
- // Loads any type that does not have a specific overload. This implicit one
- // only works for types that have their own Load(RFile*) member function.
- //////////////////////////////////////////////////////////////////////////////
- template <class obj>
- short rspAnyLoad( // Returns 0 on success.
- obj* pobj, // Ptr to object to load.
- RFile* pfile) // Open RFile. Must have read access.
- {
- return pobj->Load(pfile);
- }
- //////////////////////////////////////////////////////////////////////////////
- // Saves any type that does not have a specific overload. This implicit one
- // only works for types that have their own Save(RFile*) member function.
- //////////////////////////////////////////////////////////////////////////////
- template <class obj>
- short rspAnySave( // Returns 0 on success.
- obj* pobj, // Ptr to object to save.
- RFile* pfile) // Open RFile. Must have write access.
- {
- return pobj->Save(pfile);
- }
- // Find the correct file. This will favor the prefpath
- // for reading, and always use the prefpath for writing.
- // On systems without a prefpath, it just returns pszName, otherwise
- // it will find the right file name and return it in platform-
- // specific notation.
- // This may return a static buffer, and as such is not thread safe.
- extern const char *FindCorrectFile(const char *pszName, const char *pszMode);
- #endif // FILE_H
- //////////////////////////////////////////////////////////////////////////////
- // EOF
- //////////////////////////////////////////////////////////////////////////////
|