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
00081 # define LIST_TYPE_INFO 0x494E464F
00082 # define CHUNK_ID_ICMT 0x49434D54
00083 # define CHUNK_ID_ICOP 0x49434F50
00084 # define CHUNK_ID_ICRD 0x49435244
00085 # define CHUNK_ID_IENG 0x49454E47
00086 # define CHUNK_ID_INAM 0x494E414D
00087 # define CHUNK_ID_IPRD 0x49505244
00088 # define CHUNK_ID_ISFT 0x49534654
00089
00090 # define CHUNK_ID_SMPL 0x736D706C
00091
00092 #else // little endian
00093 # define CHUNK_ID_RIFF 0x46464952
00094 # define CHUNK_ID_RIFX 0x58464952
00095 # define CHUNK_ID_LIST 0x5453494C
00096
00097 # define LIST_TYPE_INFO 0x4F464E49
00098 # define CHUNK_ID_ICMT 0x544D4349
00099 # define CHUNK_ID_ICOP 0x504F4349
00100 # define CHUNK_ID_ICRD 0x44524349
00101 # define CHUNK_ID_IENG 0x474E4549
00102 # define CHUNK_ID_INAM 0x4D414E49
00103 # define CHUNK_ID_IPRD 0x44525049
00104 # define CHUNK_ID_ISFT 0x54465349
00105
00106 # define CHUNK_ID_SMPL 0x6C706D73
00107
00108 #endif // WORDS_BIGENDIAN
00109
00110 #define CHUNK_HEADER_SIZE 8
00111 #define LIST_HEADER_SIZE 12
00112 #define RIFF_HEADER_SIZE 12
00113
00114
00134 namespace RIFF {
00135
00136
00137 class Chunk;
00138 class List;
00139 class File;
00140
00141 typedef std::string String;
00142
00144 typedef enum {
00145 stream_mode_read = 0,
00146 stream_mode_read_write = 1,
00147 stream_mode_closed = 2
00148 } stream_mode_t;
00149
00151 typedef enum {
00152 stream_ready = 0,
00153 stream_end_reached = 1,
00154 stream_closed = 2
00155 } stream_state_t;
00156
00158 typedef enum {
00159 stream_start = 0,
00160 stream_curpos = 1,
00161 stream_backward = 2,
00162 stream_end = 3
00163 } stream_whence_t;
00164
00166 typedef enum {
00167 endian_little = 0,
00168 endian_big = 1,
00169 endian_native = 2
00170 } endian_t;
00171
00177 class Chunk {
00178 public:
00179 Chunk(File* pFile, unsigned long StartPos, List* Parent);
00180 String GetChunkIDString();
00181 uint32_t GetChunkID() { return ChunkID; }
00182 List* GetParent() { return pParent; }
00183 unsigned long GetSize() { return CurrentChunkSize; }
00184 unsigned long GetNewSize() { return NewChunkSize; }
00185 unsigned long GetPos() { return ulPos; }
00186 unsigned long GetFilePos() { return ulStartPos + ulPos; }
00187 unsigned long SetPos(unsigned long Where, stream_whence_t Whence = stream_start);
00188 unsigned long RemainingBytes();
00189 stream_state_t GetState();
00190 unsigned long Read(void* pData, unsigned long WordCount, unsigned long WordSize);
00191 unsigned long ReadInt8(int8_t* pData, unsigned long WordCount = 1);
00192 unsigned long ReadUint8(uint8_t* pData, unsigned long WordCount = 1);
00193 unsigned long ReadInt16(int16_t* pData, unsigned long WordCount = 1);
00194 unsigned long ReadUint16(uint16_t* pData, unsigned long WordCount = 1);
00195 unsigned long ReadInt32(int32_t* pData, unsigned long WordCount = 1);
00196 unsigned long ReadUint32(uint32_t* pData, unsigned long WordCount = 1);
00197 int8_t ReadInt8();
00198 uint8_t ReadUint8();
00199 int16_t ReadInt16();
00200 uint16_t ReadUint16();
00201 int32_t ReadInt32();
00202 uint32_t ReadUint32();
00203 unsigned long Write(void* pData, unsigned long WordCount, unsigned long WordSize);
00204 unsigned long WriteInt8(int8_t* pData, unsigned long WordCount = 1);
00205 unsigned long WriteUint8(uint8_t* pData, unsigned long WordCount = 1);
00206 unsigned long WriteInt16(int16_t* pData, unsigned long WordCount = 1);
00207 unsigned long WriteUint16(uint16_t* pData, unsigned long WordCount = 1);
00208 unsigned long WriteInt32(int32_t* pData, unsigned long WordCount = 1);
00209 unsigned long WriteUint32(uint32_t* pData, unsigned long WordCount = 1);
00210 void* LoadChunkData();
00211 void ReleaseChunkData();
00212 void Resize(int iNewSize);
00213 virtual ~Chunk();
00214 protected:
00215 uint32_t ChunkID;
00216 uint32_t CurrentChunkSize;
00217 uint32_t NewChunkSize;
00218 List* pParent;
00219 File* pFile;
00220 unsigned long ulStartPos;
00221 unsigned long ulPos;
00222 uint8_t* pChunkData;
00223 unsigned long ulChunkDataSize;
00224
00225 Chunk(File* pFile);
00226 Chunk(File* pFile, List* pParent, uint32_t uiChunkID, uint uiBodySize);
00227 void ReadHeader(unsigned long fPos);
00228 void WriteHeader(unsigned long fPos);
00229 unsigned long ReadSceptical(void* pData, unsigned long WordCount, unsigned long WordSize);
00230 inline void swapBytes_16(void* Word) {
00231 uint8_t byteCache = *((uint8_t*) Word);
00232 *((uint8_t*) Word) = *((uint8_t*) Word + 1);
00233 *((uint8_t*) Word + 1) = byteCache;
00234 }
00235 inline void swapBytes_32(void* Word) {
00236 uint8_t byteCache = *((uint8_t*) Word);
00237 *((uint8_t*) Word) = *((uint8_t*) Word + 3);
00238 *((uint8_t*) Word + 3) = byteCache;
00239 byteCache = *((uint8_t*) Word + 1);
00240 *((uint8_t*) Word + 1) = *((uint8_t*) Word + 2);
00241 *((uint8_t*) Word + 2) = byteCache;
00242 }
00243 inline void swapBytes(void* Word, unsigned long WordSize) {
00244 uint8_t byteCache;
00245 unsigned long lo = 0, hi = WordSize - 1;
00246 for (; lo < hi; hi--, lo++) {
00247 byteCache = *((uint8_t*) Word + lo);
00248 *((uint8_t*) Word + lo) = *((uint8_t*) Word + hi);
00249 *((uint8_t*) Word + hi) = byteCache;
00250 }
00251 }
00252 inline String convertToString(uint32_t word) {
00253 String result;
00254 for (int i = 0; i < 4; i++) {
00255 uint8_t byte = *((uint8_t*)(&word) + i);
00256 char c = byte;
00257 result += c;
00258 }
00259 return result;
00260 }
00261 virtual unsigned long WriteChunk(unsigned long ulWritePos, unsigned long ulCurrentDataOffset);
00262 virtual void __resetPos();
00263
00264 friend class List;
00265 };
00266
00272 class List : public Chunk {
00273 public:
00274 List(File* pFile, unsigned long StartPos, List* Parent);
00275 String GetListTypeString();
00276 uint32_t GetListType() { return ListType; }
00277 Chunk* GetSubChunk(uint32_t ChunkID);
00278 List* GetSubList(uint32_t ListType);
00279 Chunk* GetFirstSubChunk();
00280 Chunk* GetNextSubChunk();
00281 List* GetFirstSubList();
00282 List* GetNextSubList();
00283 unsigned int CountSubChunks();
00284 unsigned int CountSubChunks(uint32_t ChunkID);
00285 unsigned int CountSubLists();
00286 unsigned int CountSubLists(uint32_t ListType);
00287 Chunk* AddSubChunk(uint32_t uiChunkID, uint uiBodySize);
00288 List* AddSubList(uint32_t uiListType);
00289 void DeleteSubChunk(Chunk* pSubChunk);
00290 void MoveSubChunk(Chunk* pSrc, Chunk* pDst);
00291 virtual ~List();
00292 protected:
00293 typedef std::map<uint32_t, RIFF::Chunk*> ChunkMap;
00294 typedef std::list<Chunk*> ChunkList;
00295
00296 uint32_t ListType;
00297 ChunkList* pSubChunks;
00298 ChunkMap* pSubChunksMap;
00299 ChunkList::iterator ChunksIterator;
00300 ChunkList::iterator ListIterator;
00301
00302 List(File* pFile);
00303 List(File* pFile, List* pParent, uint32_t uiListID);
00304 void ReadHeader(unsigned long fPos);
00305 void WriteHeader(unsigned long fPos);
00306 void LoadSubChunks();
00307 void LoadSubChunksRecursively();
00308 virtual unsigned long WriteChunk(unsigned long ulWritePos, unsigned long ulCurrentDataOffset);
00309 virtual void __resetPos();
00310 void DeleteChunkList();
00311 };
00312
00319 class File : public List {
00320 public:
00321 File(uint32_t FileType);
00322 File(const String& path);
00323 stream_mode_t GetMode();
00324 bool SetMode(stream_mode_t NewMode);
00325 void SetByteOrder(endian_t Endian);
00326 String GetFileName();
00327 virtual void Save();
00328 virtual void Save(const String& path);
00329 virtual ~File();
00330 protected:
00331 #if POSIX
00332 int hFileRead;
00333 int hFileWrite;
00334 #elif defined(WIN32)
00335 HANDLE hFileRead;
00336 HANDLE hFileWrite;
00337 #else
00338 FILE* hFileRead;
00339 FILE* hFileWrite;
00340 #endif // POSIX
00341 String Filename;
00342 bool bEndianNative;
00343
00344 void LogAsResized(Chunk* pResizedChunk);
00345 void UnlogResized(Chunk* pResizedChunk);
00346 friend class Chunk;
00347 friend class List;
00348 private:
00349 stream_mode_t Mode;
00350 ChunkList ResizedChunks;
00351
00352 unsigned long GetFileSize();
00353 void ResizeFile(unsigned long ulNewSize);
00354 #if POSIX
00355 unsigned long __GetFileSize(int hFile);
00356 #elif defined(WIN32)
00357 unsigned long __GetFileSize(HANDLE hFile);
00358 #else
00359 unsigned long __GetFileSize(FILE* hFile);
00360 #endif
00361 void Cleanup();
00362 };
00363
00367 class Exception {
00368 public:
00369 String Message;
00370
00371 Exception(String Message) { Exception::Message = Message; }
00372 void PrintMessage();
00373 virtual ~Exception() {}
00374 };
00375
00376 String libraryName();
00377 String libraryVersion();
00378
00379 }
00380 #endif // __RIFF_H__