00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #ifndef __RIFF_H__
00025 #define __RIFF_H__
00026
00027 #ifdef WIN32
00028 # define POSIX 0
00029 #endif
00030
00031 #ifndef POSIX
00032 # define POSIX 1
00033 #endif
00034
00035 #ifndef DEBUG
00036 # define DEBUG 0
00037 #endif
00038
00039 #include <string>
00040 #include <list>
00041 #include <map>
00042 #include <iostream>
00043
00044 #ifdef HAVE_CONFIG_H
00045 # include <config.h>
00046 #endif
00047
00048 #if POSIX
00049 # include <sys/types.h>
00050 # include <sys/stat.h>
00051 # include <fcntl.h>
00052 # include <unistd.h>
00053 #endif // POSIX
00054
00055 #ifdef _MSC_VER
00056
00057 typedef __int8 int8_t;
00058 typedef __int16 int16_t;
00059 typedef __int32 int32_t;
00060 typedef __int64 int64_t;
00061 typedef unsigned __int8 uint8_t;
00062 typedef unsigned __int16 uint16_t;
00063 typedef unsigned __int32 uint32_t;
00064 typedef unsigned __int64 uint64_t;
00065 #else
00066 #include <stdint.h>
00067 #endif
00068
00069 #ifdef WIN32
00070 # include <windows.h>
00071 typedef unsigned int uint;
00072 #endif // WIN32
00073
00074 #include <stdio.h>
00075
00076 #if WORDS_BIGENDIAN
00077 # define CHUNK_ID_RIFF 0x52494646
00078 # define CHUNK_ID_RIFX 0x52494658
00079 # define CHUNK_ID_LIST 0x4C495354
00080 #else // little endian
00081 # define CHUNK_ID_RIFF 0x46464952
00082 # define CHUNK_ID_RIFX 0x58464952
00083 # define CHUNK_ID_LIST 0x5453494C
00084 #endif // WORDS_BIGENDIAN
00085
00086 #define CHUNK_HEADER_SIZE 8
00087 #define LIST_HEADER_SIZE 12
00088 #define RIFF_HEADER_SIZE 12
00089
00090
00110 namespace RIFF {
00111
00112
00113 class Chunk;
00114 class List;
00115 class File;
00116
00117 typedef std::string String;
00118
00120 typedef enum {
00121 stream_mode_read = 0,
00122 stream_mode_read_write = 1,
00123 stream_mode_closed = 2
00124 } stream_mode_t;
00125
00127 typedef enum {
00128 stream_ready = 0,
00129 stream_end_reached = 1,
00130 stream_closed = 2
00131 } stream_state_t;
00132
00134 typedef enum {
00135 stream_start = 0,
00136 stream_curpos = 1,
00137 stream_backward = 2,
00138 stream_end = 3
00139 } stream_whence_t;
00140
00142 typedef enum {
00143 endian_little = 0,
00144 endian_big = 1,
00145 endian_native = 2
00146 } endian_t;
00147
00153 class Chunk {
00154 public:
00155 Chunk(File* pFile, unsigned long StartPos, List* Parent);
00156 String GetChunkIDString();
00157 uint32_t GetChunkID() { return ChunkID; }
00158 List* GetParent() { return pParent; }
00159 unsigned long GetSize() { return CurrentChunkSize; }
00160 unsigned long GetNewSize() { return NewChunkSize; }
00161 unsigned long GetPos() { return ulPos; }
00162 unsigned long GetFilePos() { return ulStartPos + ulPos; }
00163 unsigned long SetPos(unsigned long Where, stream_whence_t Whence = stream_start);
00164 unsigned long RemainingBytes();
00165 stream_state_t GetState();
00166 unsigned long Read(void* pData, unsigned long WordCount, unsigned long WordSize);
00167 unsigned long ReadInt8(int8_t* pData, unsigned long WordCount = 1);
00168 unsigned long ReadUint8(uint8_t* pData, unsigned long WordCount = 1);
00169 unsigned long ReadInt16(int16_t* pData, unsigned long WordCount = 1);
00170 unsigned long ReadUint16(uint16_t* pData, unsigned long WordCount = 1);
00171 unsigned long ReadInt32(int32_t* pData, unsigned long WordCount = 1);
00172 unsigned long ReadUint32(uint32_t* pData, unsigned long WordCount = 1);
00173 int8_t ReadInt8();
00174 uint8_t ReadUint8();
00175 int16_t ReadInt16();
00176 uint16_t ReadUint16();
00177 int32_t ReadInt32();
00178 uint32_t ReadUint32();
00179 unsigned long Write(void* pData, unsigned long WordCount, unsigned long WordSize);
00180 unsigned long WriteInt8(int8_t* pData, unsigned long WordCount = 1);
00181 unsigned long WriteUint8(uint8_t* pData, unsigned long WordCount = 1);
00182 unsigned long WriteInt16(int16_t* pData, unsigned long WordCount = 1);
00183 unsigned long WriteUint16(uint16_t* pData, unsigned long WordCount = 1);
00184 unsigned long WriteInt32(int32_t* pData, unsigned long WordCount = 1);
00185 unsigned long WriteUint32(uint32_t* pData, unsigned long WordCount = 1);
00186 void* LoadChunkData();
00187 void ReleaseChunkData();
00188 void Resize(int iNewSize);
00189 virtual ~Chunk();
00190 protected:
00191 uint32_t ChunkID;
00192 uint32_t CurrentChunkSize;
00193 uint32_t NewChunkSize;
00194 List* pParent;
00195 File* pFile;
00196 unsigned long ulStartPos;
00197 unsigned long ulPos;
00198 uint8_t* pChunkData;
00199 unsigned long ulChunkDataSize;
00200
00201 Chunk(File* pFile);
00202 Chunk(File* pFile, List* pParent, uint32_t uiChunkID, uint uiBodySize);
00203 void ReadHeader(unsigned long fPos);
00204 void WriteHeader(unsigned long fPos);
00205 unsigned long ReadSceptical(void* pData, unsigned long WordCount, unsigned long WordSize);
00206 inline void swapBytes_16(void* Word) {
00207 uint8_t byteCache = *((uint8_t*) Word);
00208 *((uint8_t*) Word) = *((uint8_t*) Word + 1);
00209 *((uint8_t*) Word + 1) = byteCache;
00210 }
00211 inline void swapBytes_32(void* Word) {
00212 uint8_t byteCache = *((uint8_t*) Word);
00213 *((uint8_t*) Word) = *((uint8_t*) Word + 3);
00214 *((uint8_t*) Word + 3) = byteCache;
00215 byteCache = *((uint8_t*) Word + 1);
00216 *((uint8_t*) Word + 1) = *((uint8_t*) Word + 2);
00217 *((uint8_t*) Word + 2) = byteCache;
00218 }
00219 inline void swapBytes(void* Word, unsigned long WordSize) {
00220 uint8_t byteCache;
00221 unsigned long lo = 0, hi = WordSize - 1;
00222 for (; lo < hi; hi--, lo++) {
00223 byteCache = *((uint8_t*) Word + lo);
00224 *((uint8_t*) Word + lo) = *((uint8_t*) Word + hi);
00225 *((uint8_t*) Word + hi) = byteCache;
00226 }
00227 }
00228 inline String convertToString(uint32_t word) {
00229 String result;
00230 for (int i = 0; i < 4; i++) {
00231 uint8_t byte = *((uint8_t*)(&word) + i);
00232 char c = byte;
00233 result += c;
00234 }
00235 return result;
00236 }
00237 virtual unsigned long WriteChunk(unsigned long ulWritePos, unsigned long ulCurrentDataOffset);
00238 virtual void __resetPos();
00239
00240 friend class List;
00241 };
00242
00248 class List : public Chunk {
00249 public:
00250 List(File* pFile, unsigned long StartPos, List* Parent);
00251 String GetListTypeString();
00252 uint32_t GetListType() { return ListType; }
00253 Chunk* GetSubChunk(uint32_t ChunkID);
00254 List* GetSubList(uint32_t ListType);
00255 Chunk* GetFirstSubChunk();
00256 Chunk* GetNextSubChunk();
00257 List* GetFirstSubList();
00258 List* GetNextSubList();
00259 unsigned int CountSubChunks();
00260 unsigned int CountSubChunks(uint32_t ChunkID);
00261 unsigned int CountSubLists();
00262 unsigned int CountSubLists(uint32_t ListType);
00263 Chunk* AddSubChunk(uint32_t uiChunkID, uint uiBodySize);
00264 List* AddSubList(uint32_t uiListType);
00265 void DeleteSubChunk(Chunk* pSubChunk);
00266 void MoveSubChunk(Chunk* pSrc, Chunk* pDst);
00267 virtual ~List();
00268 protected:
00269 typedef std::map<uint32_t, RIFF::Chunk*> ChunkMap;
00270 typedef std::list<Chunk*> ChunkList;
00271
00272 uint32_t ListType;
00273 ChunkList* pSubChunks;
00274 ChunkMap* pSubChunksMap;
00275 ChunkList::iterator ChunksIterator;
00276 ChunkList::iterator ListIterator;
00277
00278 List(File* pFile);
00279 List(File* pFile, List* pParent, uint32_t uiListID);
00280 void ReadHeader(unsigned long fPos);
00281 void WriteHeader(unsigned long fPos);
00282 void LoadSubChunks();
00283 void LoadSubChunksRecursively();
00284 virtual unsigned long WriteChunk(unsigned long ulWritePos, unsigned long ulCurrentDataOffset);
00285 virtual void __resetPos();
00286 void DeleteChunkList();
00287 };
00288
00295 class File : public List {
00296 public:
00297 File(uint32_t FileType);
00298 File(const String& path);
00299 stream_mode_t GetMode();
00300 bool SetMode(stream_mode_t NewMode);
00301 void SetByteOrder(endian_t Endian);
00302 String GetFileName();
00303 virtual void Save();
00304 virtual void Save(const String& path);
00305 virtual ~File();
00306 protected:
00307 #if POSIX
00308 int hFileRead;
00309 int hFileWrite;
00310 #elif defined(WIN32)
00311 HANDLE hFileRead;
00312 HANDLE hFileWrite;
00313 #else
00314 FILE* hFileRead;
00315 FILE* hFileWrite;
00316 #endif // POSIX
00317 String Filename;
00318 bool bEndianNative;
00319
00320 void LogAsResized(Chunk* pResizedChunk);
00321 void UnlogResized(Chunk* pResizedChunk);
00322 friend class Chunk;
00323 friend class List;
00324 private:
00325 stream_mode_t Mode;
00326 ChunkList ResizedChunks;
00327
00328 unsigned long GetFileSize();
00329 void ResizeFile(unsigned long ulNewSize);
00330 #if POSIX
00331 unsigned long __GetFileSize(int hFile);
00332 #elif defined(WIN32)
00333 unsigned long __GetFileSize(HANDLE hFile);
00334 #else
00335 unsigned long __GetFileSize(FILE* hFile);
00336 #endif
00337 };
00338
00342 class Exception {
00343 public:
00344 String Message;
00345
00346 Exception(String Message) { Exception::Message = Message; }
00347 void PrintMessage();
00348 virtual ~Exception() {}
00349 };
00350
00351 String libraryName();
00352 String libraryVersion();
00353
00354 }
00355 #endif // __RIFF_H__