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