00001 /** \file 00002 * \brief Binary File Access. 00003 * 00004 * See Copyright Notice in im_lib.h 00005 */ 00006 00007 #include "im_util.h" 00008 00009 #ifndef __IM_BINFILE_H 00010 #define __IM_BINFILE_H 00011 00012 #if defined(__cplusplus) 00013 extern "C" { 00014 #endif 00015 00016 00017 /** \defgroup binfile Binary File Access 00018 * 00019 * \par 00020 * These functions are very usefull for reading/writing binary files 00021 * that have headers or data that have to be converted depending on 00022 * the current CPU byte order. It can invert 2, 4 or 8 bytes numbers to/from little/big-endian orders. 00023 * \par 00024 * It will process the data only if the file format is diferent from the current CPU. 00025 * \par 00026 * Can read from disk or memory. In case of a memory buffer, the file name must be the \ref imBinMemoryFileName structure. 00027 * \par 00028 * See \ref im_binfile.h 00029 * \ingroup util */ 00030 00031 typedef struct _imBinFile imBinFile; 00032 00033 /** Opens an existant binary file for reading. 00034 * The default file byte order is the CPU byte order. 00035 * Returns NULL if failed. 00036 * \ingroup binfile */ 00037 imBinFile* imBinFileOpen(const char* pFileName); 00038 00039 /** Creates a new binary file for writing. 00040 * The default file byte order is the CPU byte order. 00041 * Returns NULL if failed. 00042 * \ingroup binfile */ 00043 imBinFile* imBinFileNew(const char* pFileName); 00044 00045 /** Closes the file. 00046 * \ingroup binfile */ 00047 void imBinFileClose(imBinFile* bfile); 00048 00049 /** Indicates that was an error on the last operation. 00050 * \ingroup binfile */ 00051 int imBinFileError(imBinFile* bfile); 00052 00053 /** Returns the file size in bytes. 00054 * \ingroup binfile */ 00055 unsigned long imBinFileSize(imBinFile* bfile); 00056 00057 /** Changes the file byte order. Returns the old one. 00058 * \ingroup binfile */ 00059 int imBinFileByteOrder(imBinFile* bfile, int pByteOrder); 00060 00061 /** Reads an array of count values with byte sizes: 1, 2, 4, or 8. And invert the byte order if necessary after read. 00062 * \ingroup binfile */ 00063 unsigned long imBinFileRead(imBinFile* bfile, void* pValues, unsigned long pCount, int pSizeOf); 00064 00065 /** Writes an array of values with sizes: 1, 2, 4, or 8. And invert the byte order if necessary before write.\n 00066 * <b>ATENTION</b>: The function will not make a temporary copy of the values to invert the byte order.\n 00067 * So after the call the values will be invalid, if the file byte order is diferent from the CPU byte order. 00068 * \ingroup binfile */ 00069 unsigned long imBinFileWrite(imBinFile* bfile, void* pValues, unsigned long pCount, int pSizeOf); 00070 00071 /** Writes a string without the NULL terminator. The function uses sprintf to compose the string. \n 00072 * The internal buffer is fixed at 4096 bytes. 00073 * \ingroup binfile */ 00074 unsigned long imBinFilePrintf(imBinFile* bfile, char *format, ...); 00075 00076 /** Reads an integer number from the current position until found a non integer character. 00077 * Returns a non zero value if sucessfull. 00078 * \ingroup binfile */ 00079 int imBinFileReadInteger(imBinFile* handle, int *value); 00080 00081 /** Reads an floating point number from the current position until found a non number character. 00082 * Returns a non zero value if sucessfull. 00083 * \ingroup binfile */ 00084 int imBinFileReadFloat(imBinFile* handle, float *value); 00085 00086 /** Moves the file pointer from the begining of the file.\n 00087 * When writing to a file seeking can go beyond the end of the file. 00088 * \ingroup binfile */ 00089 void imBinFileSeekTo(imBinFile* bfile, unsigned long pOffset); 00090 00091 /** Moves the file pointer from current position.\n 00092 * If the offset is a negative value the pointer moves backwards. 00093 * \ingroup binfile */ 00094 void imBinFileSeekOffset(imBinFile* bfile, long pOffset); 00095 00096 /** Moves the file pointer from the end of the file.\n 00097 * The offset is usually a negative value. 00098 * \ingroup binfile */ 00099 void imBinFileSeekFrom(imBinFile* bfile, long pOffset); 00100 00101 /** Returns the current offset position. 00102 * \ingroup binfile */ 00103 unsigned long imBinFileTell(imBinFile* bfile); 00104 00105 /** Indicates that the file pointer is at the end of the file. 00106 * \ingroup binfile */ 00107 int imBinFileEndOfFile(imBinFile* bfile); 00108 00109 /** Predefined I/O Modules. 00110 * \ingroup binfile */ 00111 enum imBinFileModule 00112 { 00113 IM_RAWFILE, /**< System dependent file I/O Rotines. */ 00114 IM_STREAM, /**< Standard Ansi C Stream I/O Rotines. */ 00115 IM_MEMFILE, /**< Uses a memory buffer (see \ref imBinMemoryFileName). */ 00116 IM_SUBFILE, /**< It is a sub file. FileName is a imBinFile* pointer from any other module. */ 00117 IM_FILEHANDLE,/**< System dependent file I/O Rotines, but FileName is a system file handle ("int" in UNIX and "HANDLE" in Windows). */ 00118 IM_IOCUSTOM0 /**< Other registered modules starts from here. */ 00119 }; 00120 00121 /** Sets the current I/O module. 00122 * \returns the previous function set, or -1 if failed. 00123 * See also \ref imBinFileModule. 00124 * \ingroup binfile */ 00125 int imBinFileSetCurrentModule(int pModule); 00126 00127 /** \brief Memory File I/O Filename 00128 * 00129 * \par 00130 * Fake file name for the memory I/O module. 00131 * \ingroup binfile */ 00132 typedef struct _imBinMemoryFileName 00133 { 00134 unsigned char *buffer; /**< The memory buffer. If you are reading the buffer must exists. 00135 * If you are writing the buffer can be internally allocated to the given size. The buffer is never free. 00136 * The buffer is allocated using "malloc", and reallocated using "realloc". Use "free" to release it. 00137 * To avoid RTL conflicts use the function imBinMemoryRelease. */ 00138 int size; /**< Size of the buffer. */ 00139 float reallocate; /**< Reallocate factor for the memory buffer when writing (size += reallocate*size). 00140 * Set reallocate to 0 to disable reallocation, in this case buffer must not be NULL. */ 00141 }imBinMemoryFileName; 00142 00143 /** Release the internal memory allocated when writing a Memory File (see \ref imBinMemoryFileName). 00144 * \ingroup binfile */ 00145 void imBinMemoryRelease(unsigned char *buffer); 00146 00147 00148 #if defined(__cplusplus) 00149 } 00150 #endif 00151 00152 00153 #if defined(__cplusplus) 00154 00155 /** Base class to help the creation of new modules.\n 00156 * It handles the read/write operations with byte order correction if necessary. 00157 * \ingroup binfile */ 00158 class imBinFileBase 00159 { 00160 friend class imBinSubFile; 00161 00162 protected: 00163 int IsNew, 00164 FileByteOrder, 00165 DoByteOrder; // to speed up byte order checking 00166 00167 // These will actually read/write the data 00168 virtual unsigned long ReadBuf(void* pValues, unsigned long pSize) = 0; 00169 virtual unsigned long WriteBuf(void* pValues, unsigned long pSize) = 0; 00170 00171 public: 00172 00173 int InitByteOrder(int ByteOrder) 00174 { 00175 int old_byte_order = this->FileByteOrder; 00176 this->FileByteOrder = ByteOrder; 00177 00178 if (ByteOrder != imBinCPUByteOrder()) 00179 this->DoByteOrder = 1; 00180 else 00181 this->DoByteOrder = 0; 00182 return old_byte_order; 00183 } 00184 00185 // These will take care of byte swap if needed. 00186 00187 unsigned long Read(void* pValues, unsigned long pCount, int pSizeOf) 00188 { 00189 unsigned long rSize = ReadBuf(pValues, pCount * pSizeOf); 00190 if (pSizeOf != 1 && DoByteOrder) imBinSwapBytes(pValues, pCount, pSizeOf); 00191 return rSize/pSizeOf; 00192 } 00193 00194 unsigned long Write(void* pValues, unsigned long pCount, int pSizeOf) 00195 { 00196 if (pSizeOf != 1 && DoByteOrder) imBinSwapBytes(pValues, pCount, pSizeOf); 00197 return WriteBuf(pValues, pCount * pSizeOf)/pSizeOf; 00198 } 00199 00200 virtual void Open(const char* pFileName) = 0; 00201 virtual void New(const char* pFileName) = 0; 00202 virtual void Close() = 0; 00203 virtual unsigned long FileSize() = 0; 00204 virtual int HasError() const = 0; 00205 virtual void SeekTo(unsigned long pOffset) = 0; 00206 virtual void SeekOffset(long pOffset) = 0; 00207 virtual void SeekFrom(long pOffset) = 0; 00208 virtual unsigned long Tell() const = 0; 00209 virtual int EndOfFile() const = 0; 00210 }; 00211 00212 /** File I/O module creation callback. 00213 * \ingroup binfile */ 00214 typedef imBinFileBase* (*imBinFileNewFunc)(); 00215 00216 /** Register a user I/O module.\n 00217 * Returns the new function set id.\n 00218 * Accepts up to 10 modules. 00219 * \ingroup binfile */ 00220 int imBinFileRegisterModule(imBinFileNewFunc pNewFunc); 00221 00222 #endif 00223 00224 #endif