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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 833 - (hide annotations) (download) (as text)
Sun Feb 5 17:30:13 2006 UTC (18 years, 2 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 schoenebeck 2 /***************************************************************************
2     * *
3     * libgig - C++ cross-platform Gigasampler format file loader library *
4     * *
5 schoenebeck 384 * Copyright (C) 2003-2005 by Christian Schoenebeck *
6     * <cuse@users.sourceforge.net> *
7 schoenebeck 2 * *
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 schoenebeck 11 #ifdef HAVE_CONFIG_H
36     # include <config.h>
37     #endif
38    
39 schoenebeck 2 #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 schoenebeck 780 class File;
76 schoenebeck 2
77     typedef std::string String;
78    
79 schoenebeck 780 /** Whether file stream is open in read or in read/write mode. */
80     typedef enum {
81 schoenebeck 798 stream_mode_read = 0,
82     stream_mode_read_write = 1,
83     stream_mode_closed = 2
84 schoenebeck 780 } stream_mode_t;
85    
86 schoenebeck 2 /** 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 schoenebeck 780 Chunk(File* pFile, unsigned long StartPos, List* Parent);
105 schoenebeck 2 String GetChunkIDString();
106 schoenebeck 11 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 schoenebeck 780 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 schoenebeck 11 unsigned long GetPos() { return ulPos; }; ///< Position within the chunk data body
111 schoenebeck 2 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 schoenebeck 780 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 schoenebeck 384 virtual ~Chunk();
139 schoenebeck 2 protected:
140     uint32_t ChunkID;
141 schoenebeck 780 uint32_t CurrentChunkSize; /* in bytes */
142     uint32_t NewChunkSize; /* in bytes (if chunk was scheduled to be resized) */
143 schoenebeck 2 List* pParent;
144 schoenebeck 780 File* pFile;
145 schoenebeck 2 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 schoenebeck 800 unsigned long ulChunkDataSize;
149 schoenebeck 2
150 schoenebeck 780 Chunk(File* pFile);
151     Chunk(File* pFile, List* pParent, uint32_t uiChunkID, uint uiBodySize);
152 schoenebeck 2 void ReadHeader(unsigned long fPos);
153 schoenebeck 780 void WriteHeader(unsigned long fPos);
154 schoenebeck 2 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 schoenebeck 780 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 schoenebeck 2 };
191    
192     /** Provides convenient methods to access data of RIFF list chunks and their subchunks. */
193     class List : public Chunk {
194     public:
195 schoenebeck 780 List(File* pFile, unsigned long StartPos, List* Parent);
196 schoenebeck 2 String GetListTypeString();
197 schoenebeck 11 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 schoenebeck 2 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 schoenebeck 780 Chunk* AddSubChunk(uint32_t uiChunkID, uint uiBodySize);
209     List* AddSubList(uint32_t uiListType);
210     void DeleteSubChunk(Chunk* pSubChunk);
211 schoenebeck 384 virtual ~List();
212 schoenebeck 2 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 schoenebeck 780 List(File* pFile);
223     List(File* pFile, List* pParent, uint32_t uiListID);
224 schoenebeck 2 void ReadHeader(unsigned long fPos);
225 schoenebeck 780 void WriteHeader(unsigned long fPos);
226 schoenebeck 2 void LoadSubChunks();
227 schoenebeck 833 void LoadSubChunksRecursively();
228 schoenebeck 780 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 schoenebeck 2 };
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 schoenebeck 798 File(uint32_t FileType);
236 schoenebeck 2 File(const String& path);
237 schoenebeck 780 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 schoenebeck 384 virtual ~File();
243 schoenebeck 780 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 schoenebeck 2 private:
258 schoenebeck 780 stream_mode_t Mode;
259     ChunkList ResizedChunks; ///< All chunks which have been resized (enlarged / shortened).
260    
261 schoenebeck 2 unsigned long GetFileSize();
262 schoenebeck 780 void ResizeFile(unsigned long ulNewSize);
263 schoenebeck 798 #if POSIX
264     unsigned long __GetFileSize(int hFile);
265     #else
266     unsigned long __GetFileSize(FILE* hFile);
267     #endif
268 schoenebeck 2 };
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 schoenebeck 518 String libraryName();
281     String libraryVersion();
282    
283 schoenebeck 2 } // namespace RIFF
284     #endif // __RIFF_H__

  ViewVC Help
Powered by ViewVC