/[svn]/libgig/trunk/src/RIFF.h
ViewVC logotype

Contents of /libgig/trunk/src/RIFF.h

Parent Directory Parent Directory | Revision Log Revision Log


Revision 833 - (show annotations) (download) (as text)
Sun Feb 5 17:30:13 2006 UTC (14 years, 8 months ago) by schoenebeck
File MIME type: text/x-c++hdr
File size: 12464 byte(s)
* src/RIFF.cpp: bugfix in File::Save() methods which did not ensure that
  the whole RIFF tree was already built before writing which caused opening
  an existing file and saving it afterwards to write just an empty file

1 /***************************************************************************
2 * *
3 * libgig - C++ cross-platform Gigasampler format file loader library *
4 * *
5 * Copyright (C) 2003-2005 by Christian Schoenebeck *
6 * <cuse@users.sourceforge.net> *
7 * *
8 * This library is free software; you can redistribute it and/or modify *
9 * it under the terms of the GNU General Public License as published by *
10 * the Free Software Foundation; either version 2 of the License, or *
11 * (at your option) any later version. *
12 * *
13 * This library is distributed in the hope that it will be useful, *
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
16 * GNU General Public License for more details. *
17 * *
18 * You should have received a copy of the GNU General Public License *
19 * along with this library; if not, write to the Free Software *
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, *
21 * MA 02111-1307 USA *
22 ***************************************************************************/
23
24 #ifndef __RIFF_H__
25 #define __RIFF_H__
26
27 #define POSIX 1
28 #define DEBUG 0
29
30 #include <string>
31 #include <list>
32 #include <map>
33 #include <iostream>
34
35 #ifdef HAVE_CONFIG_H
36 # include <config.h>
37 #endif
38
39 #if POSIX
40 # include <sys/types.h>
41 # include <sys/stat.h>
42 # include <fcntl.h>
43 # include <unistd.h>
44 #endif // POSIX
45
46 #include <stdint.h>
47
48 //typedef unsigned char uint8_t;
49 //typedef unsigned short uint16_t;
50 //typedef unsigned int uint32_t;
51
52 #include <stdio.h>
53
54 #if WORDS_BIGENDIAN
55 # define CHUNK_ID_RIFF 0x52494646
56 # define CHUNK_ID_RIFX 0x52494658
57 # define CHUNK_ID_LIST 0x4C495354
58 #else // little endian
59 # define CHUNK_ID_RIFF 0x46464952
60 # define CHUNK_ID_RIFX 0x58464952
61 # define CHUNK_ID_LIST 0x5453494C
62 #endif // WORDS_BIGENDIAN
63
64 #define CHUNK_HEADER_SIZE 8
65 #define LIST_HEADER_SIZE 12
66 #define RIFF_HEADER_SIZE 12
67
68
69 /** RIFF specific classes and definitions */
70 namespace RIFF {
71
72 /* just symbol prototyping */
73 class Chunk;
74 class List;
75 class File;
76
77 typedef std::string String;
78
79 /** Whether file stream is open in read or in read/write mode. */
80 typedef enum {
81 stream_mode_read = 0,
82 stream_mode_read_write = 1,
83 stream_mode_closed = 2
84 } stream_mode_t;
85
86 /** Current state of the file stream. */
87 typedef enum {
88 stream_ready = 0,
89 stream_end_reached = 1,
90 stream_closed = 2
91 } stream_state_t;
92
93 /** File stream position dependent to these relations. */
94 typedef enum {
95 stream_start = 0,
96 stream_curpos = 1,
97 stream_backward = 2,
98 stream_end = 3
99 } stream_whence_t;
100
101 /** Provides convenient methods to access data of RIFF chunks in general. */
102 class Chunk {
103 public:
104 Chunk(File* pFile, unsigned long StartPos, List* Parent);
105 String GetChunkIDString();
106 uint32_t GetChunkID() { return ChunkID; }; ///< Chunk ID in unsigned integer representation.
107 List* GetParent() { return pParent; }; ///< Returns pointer to the chunk's parent list chunk.
108 unsigned long GetSize() { return CurrentChunkSize; }; ///< Chunk size in bytes (without header, thus the chunk data body)
109 unsigned long GetNewSize() { return NewChunkSize; }; ///< New chunk size if it was modified with Resize().
110 unsigned long GetPos() { return ulPos; }; ///< Position within the chunk data body
111 unsigned long GetFilePos() { return ulStartPos + ulPos; }; ///< Current, actual offset in file.
112 unsigned long SetPos(unsigned long Where, stream_whence_t Whence = stream_start);
113 unsigned long RemainingBytes();
114 stream_state_t GetState();
115 unsigned long Read(void* pData, unsigned long WordCount, unsigned long WordSize);
116 unsigned long ReadInt8(int8_t* pData, unsigned long WordCount = 1);
117 unsigned long ReadUint8(uint8_t* pData, unsigned long WordCount = 1);
118 unsigned long ReadInt16(int16_t* pData, unsigned long WordCount = 1);
119 unsigned long ReadUint16(uint16_t* pData, unsigned long WordCount = 1);
120 unsigned long ReadInt32(int32_t* pData, unsigned long WordCount = 1);
121 unsigned long ReadUint32(uint32_t* pData, unsigned long WordCount = 1);
122 int8_t ReadInt8();
123 uint8_t ReadUint8();
124 int16_t ReadInt16();
125 uint16_t ReadUint16();
126 int32_t ReadInt32();
127 uint32_t ReadUint32();
128 unsigned long Write(void* pData, unsigned long WordCount, unsigned long WordSize);
129 unsigned long WriteInt8(int8_t* pData, unsigned long WordCount = 1);
130 unsigned long WriteUint8(uint8_t* pData, unsigned long WordCount = 1);
131 unsigned long WriteInt16(int16_t* pData, unsigned long WordCount = 1);
132 unsigned long WriteUint16(uint16_t* pData, unsigned long WordCount = 1);
133 unsigned long WriteInt32(int32_t* pData, unsigned long WordCount = 1);
134 unsigned long WriteUint32(uint32_t* pData, unsigned long WordCount = 1);
135 void* LoadChunkData();
136 void ReleaseChunkData();
137 void Resize(int iNewSize);
138 virtual ~Chunk();
139 protected:
140 uint32_t ChunkID;
141 uint32_t CurrentChunkSize; /* in bytes */
142 uint32_t NewChunkSize; /* in bytes (if chunk was scheduled to be resized) */
143 List* pParent;
144 File* pFile;
145 unsigned long ulStartPos; /* actual position in file where chunk (without header) starts */
146 unsigned long ulPos; /* # of bytes from ulStartPos */
147 uint8_t* pChunkData;
148 unsigned long ulChunkDataSize;
149
150 Chunk(File* pFile);
151 Chunk(File* pFile, List* pParent, uint32_t uiChunkID, uint uiBodySize);
152 void ReadHeader(unsigned long fPos);
153 void WriteHeader(unsigned long fPos);
154 unsigned long ReadSceptical(void* pData, unsigned long WordCount, unsigned long WordSize);
155 inline void swapBytes_16(void* Word) {
156 uint8_t byteCache = *((uint8_t*) Word);
157 *((uint8_t*) Word) = *((uint8_t*) Word + 1);
158 *((uint8_t*) Word + 1) = byteCache;
159 }
160 inline void swapBytes_32(void* Word) {
161 uint8_t byteCache = *((uint8_t*) Word);
162 *((uint8_t*) Word) = *((uint8_t*) Word + 3);
163 *((uint8_t*) Word + 3) = byteCache;
164 byteCache = *((uint8_t*) Word + 1);
165 *((uint8_t*) Word + 1) = *((uint8_t*) Word + 2);
166 *((uint8_t*) Word + 2) = byteCache;
167 }
168 inline void swapBytes(void* Word, unsigned long WordSize) {
169 uint8_t byteCache;
170 unsigned long lo = 0, hi = WordSize - 1;
171 for (; lo < hi; hi--, lo++) {
172 byteCache = *((uint8_t*) Word + lo);
173 *((uint8_t*) Word + lo) = *((uint8_t*) Word + hi);
174 *((uint8_t*) Word + hi) = byteCache;
175 }
176 }
177 inline String convertToString(uint32_t word) {
178 String result;
179 for (int i = 0; i < 4; i++) {
180 uint8_t byte = *((uint8_t*)(&word) + i);
181 char c = byte;
182 result += c;
183 }
184 return result;
185 }
186 virtual unsigned long WriteChunk(unsigned long ulWritePos, unsigned long ulCurrentDataOffset);
187 virtual void __resetPos(); ///< Sets Chunk's read/write position to zero.
188
189 friend class List;
190 };
191
192 /** Provides convenient methods to access data of RIFF list chunks and their subchunks. */
193 class List : public Chunk {
194 public:
195 List(File* pFile, unsigned long StartPos, List* Parent);
196 String GetListTypeString();
197 uint32_t GetListType() { return ListType; } ///< Returns unsigned integer representation of the list's ID
198 Chunk* GetSubChunk(uint32_t ChunkID);
199 List* GetSubList(uint32_t ListType);
200 Chunk* GetFirstSubChunk();
201 Chunk* GetNextSubChunk();
202 List* GetFirstSubList();
203 List* GetNextSubList();
204 unsigned int CountSubChunks();
205 unsigned int CountSubChunks(uint32_t ChunkID);
206 unsigned int CountSubLists();
207 unsigned int CountSubLists(uint32_t ListType);
208 Chunk* AddSubChunk(uint32_t uiChunkID, uint uiBodySize);
209 List* AddSubList(uint32_t uiListType);
210 void DeleteSubChunk(Chunk* pSubChunk);
211 virtual ~List();
212 protected:
213 typedef std::map<uint32_t, RIFF::Chunk*> ChunkMap;
214 typedef std::list<Chunk*> ChunkList;
215
216 uint32_t ListType;
217 ChunkList* pSubChunks;
218 ChunkMap* pSubChunksMap;
219 ChunkList::iterator ChunksIterator;
220 ChunkList::iterator ListIterator;
221
222 List(File* pFile);
223 List(File* pFile, List* pParent, uint32_t uiListID);
224 void ReadHeader(unsigned long fPos);
225 void WriteHeader(unsigned long fPos);
226 void LoadSubChunks();
227 void LoadSubChunksRecursively();
228 virtual unsigned long WriteChunk(unsigned long ulWritePos, unsigned long ulCurrentDataOffset);
229 virtual void __resetPos(); ///< Sets List Chunk's read/write position to zero and causes all sub chunks to do the same.
230 };
231
232 /** Parses arbitrary RIFF files and provides together with it's base classes convenient methods to walk through the RIFF tree. */
233 class File : public List {
234 public:
235 File(uint32_t FileType);
236 File(const String& path);
237 stream_mode_t GetMode();
238 bool SetMode(stream_mode_t NewMode);
239 String GetFileName();
240 virtual void Save();
241 virtual void Save(const String& path);
242 virtual ~File();
243 protected:
244 #if POSIX
245 int hFileRead; ///< handle / descriptor for reading from file
246 int hFileWrite; ///< handle / descriptor for writing to (some) file
247 #else
248 FILE* hFileRead; ///< handle / descriptor for reading from file
249 FILE* hFileWrite; ///< handle / descriptor for writing to (some) file
250 #endif // POSIX
251 String Filename;
252 bool bEndianNative;
253
254 void LogAsResized(Chunk* pResizedChunk);
255 friend class Chunk;
256 friend class List;
257 private:
258 stream_mode_t Mode;
259 ChunkList ResizedChunks; ///< All chunks which have been resized (enlarged / shortened).
260
261 unsigned long GetFileSize();
262 void ResizeFile(unsigned long ulNewSize);
263 #if POSIX
264 unsigned long __GetFileSize(int hFile);
265 #else
266 unsigned long __GetFileSize(FILE* hFile);
267 #endif
268 };
269
270 /** Will be thrown whenever an error occurs while parsing a RIFF file. */
271 class Exception {
272 public:
273 String Message;
274
275 Exception(String Message) { Exception::Message = Message; };
276 void PrintMessage();
277 virtual ~Exception() {};
278 };
279
280 String libraryName();
281 String libraryVersion();
282
283 } // namespace RIFF
284 #endif // __RIFF_H__

  ViewVC Help
Powered by ViewVC