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