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 #define POSIX 1
00028 #define DEBUG 0
00029
00030 #include <string>
00031 #include <list>
00032 #include <map>
00033 #include <iostream>
00034
00035 #ifdef HAVE_CONFIG_H
00036 # include <config.h>
00037 #endif
00038
00039 #if POSIX
00040 # include <sys/types.h>
00041 # include <sys/stat.h>
00042 # include <fcntl.h>
00043 # include <unistd.h>
00044 #endif // POSIX
00045
00046 #include <stdint.h>
00047
00048
00049
00050
00051
00052 #include <stdio.h>
00053
00054 #if WORDS_BIGENDIAN
00055 # define CHUNK_ID_RIFF 0x52494646
00056 # define CHUNK_ID_RIFX 0x52494658
00057 # define CHUNK_ID_LIST 0x4C495354
00058 #else // little endian
00059 # define CHUNK_ID_RIFF 0x46464952
00060 # define CHUNK_ID_RIFX 0x58464952
00061 # define CHUNK_ID_LIST 0x5453494C
00062 #endif // WORDS_BIGENDIAN
00063
00064 #define CHUNK_HEADER_SIZE 8
00065 #define LIST_HEADER_SIZE 12
00066 #define RIFF_HEADER_SIZE 12
00067
00068
00070 namespace RIFF {
00071
00072
00073 class Chunk;
00074 class List;
00075 class File;
00076
00077 typedef std::string String;
00078
00080 typedef enum {
00081 stream_mode_read = 0,
00082 stream_mode_read_write = 1,
00083 stream_mode_closed = 2
00084 } stream_mode_t;
00085
00087 typedef enum {
00088 stream_ready = 0,
00089 stream_end_reached = 1,
00090 stream_closed = 2
00091 } stream_state_t;
00092
00094 typedef enum {
00095 stream_start = 0,
00096 stream_curpos = 1,
00097 stream_backward = 2,
00098 stream_end = 3
00099 } stream_whence_t;
00100
00102 class Chunk {
00103 public:
00104 Chunk(File* pFile, unsigned long StartPos, List* Parent);
00105 String GetChunkIDString();
00106 uint32_t GetChunkID() { return ChunkID; };
00107 List* GetParent() { return pParent; };
00108 unsigned long GetSize() { return CurrentChunkSize; };
00109 unsigned long GetNewSize() { return NewChunkSize; };
00110 unsigned long GetPos() { return ulPos; };
00111 unsigned long GetFilePos() { return ulStartPos + ulPos; };
00112 unsigned long SetPos(unsigned long Where, stream_whence_t Whence = stream_start);
00113 unsigned long RemainingBytes();
00114 stream_state_t GetState();
00115 unsigned long Read(void* pData, unsigned long WordCount, unsigned long WordSize);
00116 unsigned long ReadInt8(int8_t* pData, unsigned long WordCount = 1);
00117 unsigned long ReadUint8(uint8_t* pData, unsigned long WordCount = 1);
00118 unsigned long ReadInt16(int16_t* pData, unsigned long WordCount = 1);
00119 unsigned long ReadUint16(uint16_t* pData, unsigned long WordCount = 1);
00120 unsigned long ReadInt32(int32_t* pData, unsigned long WordCount = 1);
00121 unsigned long ReadUint32(uint32_t* pData, unsigned long WordCount = 1);
00122 int8_t ReadInt8();
00123 uint8_t ReadUint8();
00124 int16_t ReadInt16();
00125 uint16_t ReadUint16();
00126 int32_t ReadInt32();
00127 uint32_t ReadUint32();
00128 unsigned long Write(void* pData, unsigned long WordCount, unsigned long WordSize);
00129 unsigned long WriteInt8(int8_t* pData, unsigned long WordCount = 1);
00130 unsigned long WriteUint8(uint8_t* pData, unsigned long WordCount = 1);
00131 unsigned long WriteInt16(int16_t* pData, unsigned long WordCount = 1);
00132 unsigned long WriteUint16(uint16_t* pData, unsigned long WordCount = 1);
00133 unsigned long WriteInt32(int32_t* pData, unsigned long WordCount = 1);
00134 unsigned long WriteUint32(uint32_t* pData, unsigned long WordCount = 1);
00135 void* LoadChunkData();
00136 void ReleaseChunkData();
00137 void Resize(int iNewSize);
00138 virtual ~Chunk();
00139 protected:
00140 uint32_t ChunkID;
00141 uint32_t CurrentChunkSize;
00142 uint32_t NewChunkSize;
00143 List* pParent;
00144 File* pFile;
00145 unsigned long ulStartPos;
00146 unsigned long ulPos;
00147 uint8_t* pChunkData;
00148 unsigned long ulChunkDataSize;
00149
00150 Chunk(File* pFile);
00151 Chunk(File* pFile, List* pParent, uint32_t uiChunkID, uint uiBodySize);
00152 void ReadHeader(unsigned long fPos);
00153 void WriteHeader(unsigned long fPos);
00154 unsigned long ReadSceptical(void* pData, unsigned long WordCount, unsigned long WordSize);
00155 inline void swapBytes_16(void* Word) {
00156 uint8_t byteCache = *((uint8_t*) Word);
00157 *((uint8_t*) Word) = *((uint8_t*) Word + 1);
00158 *((uint8_t*) Word + 1) = byteCache;
00159 }
00160 inline void swapBytes_32(void* Word) {
00161 uint8_t byteCache = *((uint8_t*) Word);
00162 *((uint8_t*) Word) = *((uint8_t*) Word + 3);
00163 *((uint8_t*) Word + 3) = byteCache;
00164 byteCache = *((uint8_t*) Word + 1);
00165 *((uint8_t*) Word + 1) = *((uint8_t*) Word + 2);
00166 *((uint8_t*) Word + 2) = byteCache;
00167 }
00168 inline void swapBytes(void* Word, unsigned long WordSize) {
00169 uint8_t byteCache;
00170 unsigned long lo = 0, hi = WordSize - 1;
00171 for (; lo < hi; hi--, lo++) {
00172 byteCache = *((uint8_t*) Word + lo);
00173 *((uint8_t*) Word + lo) = *((uint8_t*) Word + hi);
00174 *((uint8_t*) Word + hi) = byteCache;
00175 }
00176 }
00177 inline String convertToString(uint32_t word) {
00178 String result;
00179 for (int i = 0; i < 4; i++) {
00180 uint8_t byte = *((uint8_t*)(&word) + i);
00181 char c = byte;
00182 result += c;
00183 }
00184 return result;
00185 }
00186 virtual unsigned long WriteChunk(unsigned long ulWritePos, unsigned long ulCurrentDataOffset);
00187 virtual void __resetPos();
00188
00189 friend class List;
00190 };
00191
00193 class List : public Chunk {
00194 public:
00195 List(File* pFile, unsigned long StartPos, List* Parent);
00196 String GetListTypeString();
00197 uint32_t GetListType() { return ListType; }
00198 Chunk* GetSubChunk(uint32_t ChunkID);
00199 List* GetSubList(uint32_t ListType);
00200 Chunk* GetFirstSubChunk();
00201 Chunk* GetNextSubChunk();
00202 List* GetFirstSubList();
00203 List* GetNextSubList();
00204 unsigned int CountSubChunks();
00205 unsigned int CountSubChunks(uint32_t ChunkID);
00206 unsigned int CountSubLists();
00207 unsigned int CountSubLists(uint32_t ListType);
00208 Chunk* AddSubChunk(uint32_t uiChunkID, uint uiBodySize);
00209 List* AddSubList(uint32_t uiListType);
00210 void DeleteSubChunk(Chunk* pSubChunk);
00211 virtual ~List();
00212 protected:
00213 typedef std::map<uint32_t, RIFF::Chunk*> ChunkMap;
00214 typedef std::list<Chunk*> ChunkList;
00215
00216 uint32_t ListType;
00217 ChunkList* pSubChunks;
00218 ChunkMap* pSubChunksMap;
00219 ChunkList::iterator ChunksIterator;
00220 ChunkList::iterator ListIterator;
00221
00222 List(File* pFile);
00223 List(File* pFile, List* pParent, uint32_t uiListID);
00224 void ReadHeader(unsigned long fPos);
00225 void WriteHeader(unsigned long fPos);
00226 void LoadSubChunks();
00227 void LoadSubChunksRecursively();
00228 virtual unsigned long WriteChunk(unsigned long ulWritePos, unsigned long ulCurrentDataOffset);
00229 virtual void __resetPos();
00230 };
00231
00233 class File : public List {
00234 public:
00235 File(uint32_t FileType);
00236 File(const String& path);
00237 stream_mode_t GetMode();
00238 bool SetMode(stream_mode_t NewMode);
00239 String GetFileName();
00240 virtual void Save();
00241 virtual void Save(const String& path);
00242 virtual ~File();
00243 protected:
00244 #if POSIX
00245 int hFileRead;
00246 int hFileWrite;
00247 #else
00248 FILE* hFileRead;
00249 FILE* hFileWrite;
00250 #endif // POSIX
00251 String Filename;
00252 bool bEndianNative;
00253
00254 void LogAsResized(Chunk* pResizedChunk);
00255 friend class Chunk;
00256 friend class List;
00257 private:
00258 stream_mode_t Mode;
00259 ChunkList ResizedChunks;
00260
00261 unsigned long GetFileSize();
00262 void ResizeFile(unsigned long ulNewSize);
00263 #if POSIX
00264 unsigned long __GetFileSize(int hFile);
00265 #else
00266 unsigned long __GetFileSize(FILE* hFile);
00267 #endif
00268 };
00269
00271 class Exception {
00272 public:
00273 String Message;
00274
00275 Exception(String Message) { Exception::Message = Message; };
00276 void PrintMessage();
00277 virtual ~Exception() {};
00278 };
00279
00280 String libraryName();
00281 String libraryVersion();
00282
00283 }
00284 #endif // __RIFF_H__