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 #include <stdint.h>
00056
00057 #ifdef WIN32
00058 # include <windows.h>
00059 typedef unsigned int uint;
00060 #endif // WIN32
00061
00062 #include <stdio.h>
00063
00064 #if WORDS_BIGENDIAN
00065 # define CHUNK_ID_RIFF 0x52494646
00066 # define CHUNK_ID_RIFX 0x52494658
00067 # define CHUNK_ID_LIST 0x4C495354
00068 #else // little endian
00069 # define CHUNK_ID_RIFF 0x46464952
00070 # define CHUNK_ID_RIFX 0x58464952
00071 # define CHUNK_ID_LIST 0x5453494C
00072 #endif // WORDS_BIGENDIAN
00073
00074 #define CHUNK_HEADER_SIZE 8
00075 #define LIST_HEADER_SIZE 12
00076 #define RIFF_HEADER_SIZE 12
00077
00078
00098 namespace RIFF {
00099
00100
00101 class Chunk;
00102 class List;
00103 class File;
00104
00105 typedef std::string String;
00106
00108 typedef enum {
00109 stream_mode_read = 0,
00110 stream_mode_read_write = 1,
00111 stream_mode_closed = 2
00112 } stream_mode_t;
00113
00115 typedef enum {
00116 stream_ready = 0,
00117 stream_end_reached = 1,
00118 stream_closed = 2
00119 } stream_state_t;
00120
00122 typedef enum {
00123 stream_start = 0,
00124 stream_curpos = 1,
00125 stream_backward = 2,
00126 stream_end = 3
00127 } stream_whence_t;
00128
00130 typedef enum {
00131 endian_little = 0,
00132 endian_big = 1,
00133 endian_native = 2
00134 } endian_t;
00135
00141 class Chunk {
00142 public:
00143 Chunk(File* pFile, unsigned long StartPos, List* Parent);
00144 String GetChunkIDString();
00145 uint32_t GetChunkID() { return ChunkID; };
00146 List* GetParent() { return pParent; };
00147 unsigned long GetSize() { return CurrentChunkSize; };
00148 unsigned long GetNewSize() { return NewChunkSize; };
00149 unsigned long GetPos() { return ulPos; };
00150 unsigned long GetFilePos() { return ulStartPos + ulPos; };
00151 unsigned long SetPos(unsigned long Where, stream_whence_t Whence = stream_start);
00152 unsigned long RemainingBytes();
00153 stream_state_t GetState();
00154 unsigned long Read(void* pData, unsigned long WordCount, unsigned long WordSize);
00155 unsigned long ReadInt8(int8_t* pData, unsigned long WordCount = 1);
00156 unsigned long ReadUint8(uint8_t* pData, unsigned long WordCount = 1);
00157 unsigned long ReadInt16(int16_t* pData, unsigned long WordCount = 1);
00158 unsigned long ReadUint16(uint16_t* pData, unsigned long WordCount = 1);
00159 unsigned long ReadInt32(int32_t* pData, unsigned long WordCount = 1);
00160 unsigned long ReadUint32(uint32_t* pData, unsigned long WordCount = 1);
00161 int8_t ReadInt8();
00162 uint8_t ReadUint8();
00163 int16_t ReadInt16();
00164 uint16_t ReadUint16();
00165 int32_t ReadInt32();
00166 uint32_t ReadUint32();
00167 unsigned long Write(void* pData, unsigned long WordCount, unsigned long WordSize);
00168 unsigned long WriteInt8(int8_t* pData, unsigned long WordCount = 1);
00169 unsigned long WriteUint8(uint8_t* pData, unsigned long WordCount = 1);
00170 unsigned long WriteInt16(int16_t* pData, unsigned long WordCount = 1);
00171 unsigned long WriteUint16(uint16_t* pData, unsigned long WordCount = 1);
00172 unsigned long WriteInt32(int32_t* pData, unsigned long WordCount = 1);
00173 unsigned long WriteUint32(uint32_t* pData, unsigned long WordCount = 1);
00174 void* LoadChunkData();
00175 void ReleaseChunkData();
00176 void Resize(int iNewSize);
00177 virtual ~Chunk();
00178 protected:
00179 uint32_t ChunkID;
00180 uint32_t CurrentChunkSize;
00181 uint32_t NewChunkSize;
00182 List* pParent;
00183 File* pFile;
00184 unsigned long ulStartPos;
00185 unsigned long ulPos;
00186 uint8_t* pChunkData;
00187 unsigned long ulChunkDataSize;
00188
00189 Chunk(File* pFile);
00190 Chunk(File* pFile, List* pParent, uint32_t uiChunkID, uint uiBodySize);
00191 void ReadHeader(unsigned long fPos);
00192 void WriteHeader(unsigned long fPos);
00193 unsigned long ReadSceptical(void* pData, unsigned long WordCount, unsigned long WordSize);
00194 inline void swapBytes_16(void* Word) {
00195 uint8_t byteCache = *((uint8_t*) Word);
00196 *((uint8_t*) Word) = *((uint8_t*) Word + 1);
00197 *((uint8_t*) Word + 1) = byteCache;
00198 }
00199 inline void swapBytes_32(void* Word) {
00200 uint8_t byteCache = *((uint8_t*) Word);
00201 *((uint8_t*) Word) = *((uint8_t*) Word + 3);
00202 *((uint8_t*) Word + 3) = byteCache;
00203 byteCache = *((uint8_t*) Word + 1);
00204 *((uint8_t*) Word + 1) = *((uint8_t*) Word + 2);
00205 *((uint8_t*) Word + 2) = byteCache;
00206 }
00207 inline void swapBytes(void* Word, unsigned long WordSize) {
00208 uint8_t byteCache;
00209 unsigned long lo = 0, hi = WordSize - 1;
00210 for (; lo < hi; hi--, lo++) {
00211 byteCache = *((uint8_t*) Word + lo);
00212 *((uint8_t*) Word + lo) = *((uint8_t*) Word + hi);
00213 *((uint8_t*) Word + hi) = byteCache;
00214 }
00215 }
00216 inline String convertToString(uint32_t word) {
00217 String result;
00218 for (int i = 0; i < 4; i++) {
00219 uint8_t byte = *((uint8_t*)(&word) + i);
00220 char c = byte;
00221 result += c;
00222 }
00223 return result;
00224 }
00225 virtual unsigned long WriteChunk(unsigned long ulWritePos, unsigned long ulCurrentDataOffset);
00226 virtual void __resetPos();
00227
00228 friend class List;
00229 };
00230
00236 class List : public Chunk {
00237 public:
00238 List(File* pFile, unsigned long StartPos, List* Parent);
00239 String GetListTypeString();
00240 uint32_t GetListType() { return ListType; }
00241 Chunk* GetSubChunk(uint32_t ChunkID);
00242 List* GetSubList(uint32_t ListType);
00243 Chunk* GetFirstSubChunk();
00244 Chunk* GetNextSubChunk();
00245 List* GetFirstSubList();
00246 List* GetNextSubList();
00247 unsigned int CountSubChunks();
00248 unsigned int CountSubChunks(uint32_t ChunkID);
00249 unsigned int CountSubLists();
00250 unsigned int CountSubLists(uint32_t ListType);
00251 Chunk* AddSubChunk(uint32_t uiChunkID, uint uiBodySize);
00252 List* AddSubList(uint32_t uiListType);
00253 void DeleteSubChunk(Chunk* pSubChunk);
00254 void MoveSubChunk(Chunk* pSrc, Chunk* pDst);
00255 virtual ~List();
00256 protected:
00257 typedef std::map<uint32_t, RIFF::Chunk*> ChunkMap;
00258 typedef std::list<Chunk*> ChunkList;
00259
00260 uint32_t ListType;
00261 ChunkList* pSubChunks;
00262 ChunkMap* pSubChunksMap;
00263 ChunkList::iterator ChunksIterator;
00264 ChunkList::iterator ListIterator;
00265
00266 List(File* pFile);
00267 List(File* pFile, List* pParent, uint32_t uiListID);
00268 void ReadHeader(unsigned long fPos);
00269 void WriteHeader(unsigned long fPos);
00270 void LoadSubChunks();
00271 void LoadSubChunksRecursively();
00272 virtual unsigned long WriteChunk(unsigned long ulWritePos, unsigned long ulCurrentDataOffset);
00273 virtual void __resetPos();
00274 };
00275
00282 class File : public List {
00283 public:
00284 File(uint32_t FileType);
00285 File(const String& path);
00286 stream_mode_t GetMode();
00287 bool SetMode(stream_mode_t NewMode);
00288 void SetByteOrder(endian_t Endian);
00289 String GetFileName();
00290 virtual void Save();
00291 virtual void Save(const String& path);
00292 virtual ~File();
00293 protected:
00294 #if POSIX
00295 int hFileRead;
00296 int hFileWrite;
00297 #elif defined(WIN32)
00298 HANDLE hFileRead;
00299 HANDLE hFileWrite;
00300 #else
00301 FILE* hFileRead;
00302 FILE* hFileWrite;
00303 #endif // POSIX
00304 String Filename;
00305 bool bEndianNative;
00306
00307 void LogAsResized(Chunk* pResizedChunk);
00308 void UnlogResized(Chunk* pResizedChunk);
00309 friend class Chunk;
00310 friend class List;
00311 private:
00312 stream_mode_t Mode;
00313 ChunkList ResizedChunks;
00314
00315 unsigned long GetFileSize();
00316 void ResizeFile(unsigned long ulNewSize);
00317 #if POSIX
00318 unsigned long __GetFileSize(int hFile);
00319 #elif defined(WIN32)
00320 unsigned long __GetFileSize(HANDLE hFile);
00321 #else
00322 unsigned long __GetFileSize(FILE* hFile);
00323 #endif
00324 };
00325
00329 class Exception {
00330 public:
00331 String Message;
00332
00333 Exception(String Message) { Exception::Message = Message; }
00334 void PrintMessage();
00335 virtual ~Exception() {}
00336 };
00337
00338 String libraryName();
00339 String libraryVersion();
00340
00341 }
00342 #endif // __RIFF_H__