iff.h 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315
  1. ////////////////////////////////////////////////////////////////////////////////
  2. //
  3. // Copyright 2016 RWS Inc, All Rights Reserved
  4. //
  5. // This program is free software; you can redistribute it and/or modify
  6. // it under the terms of version 2 of the GNU General Public License as published by
  7. // the Free Software Foundation
  8. //
  9. // This program is distributed in the hope that it will be useful,
  10. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. // GNU General Public License for more details.
  13. //
  14. // You should have received a copy of the GNU General Public License along
  15. // with this program; if not, write to the Free Software Foundation, Inc.,
  16. // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  17. //
  18. //////////////////////////////////////////////////////////////////////////////
  19. //
  20. // IFF.H
  21. //
  22. // History:
  23. // 08/14/96 JMI Started.
  24. //
  25. // 03/25/97 JMI Started tracking history of this file.
  26. // TOTALLY HOSED GetNextChunkPos() so it will not work for
  27. // root case unless you already happen to be where the root
  28. // is! It should be changed back from:
  29. // // The freshly initialized chunk is a special case . . .
  30. // if (pchunk->lSizePos == 0)
  31. // return Tell();
  32. // else
  33. // return pchunk->lSizePos // File position of size.
  34. // + sizeof(pchunk->ulSize) // Size of size field.
  35. // + pchunk->ulSize // Size of chunk.
  36. // + ((pchunk->ulSize % 2) ? 1 : 0); // New chunks on even
  37. // to:
  38. // // The freshly initialized chunk is a special case . . .
  39. // if (pchunk->lSizePos == 0)
  40. // return 0;
  41. // else
  42. // return pchunk->lSizePos // File position of size.
  43. // + sizeof(pchunk->ulSize) // Size of size field.
  44. // + pchunk->ulSize // Size of chunk.
  45. // + ((pchunk->ulSize % 2) ? 1 : 0); // New chunks on even
  46. //
  47. //////////////////////////////////////////////////////////////////////////////
  48. #ifndef IFF_H
  49. #define IFF_H
  50. //////////////////////////////////////////////////////////////////////////////
  51. // Please see the CPP file for an explanation of this API.
  52. //////////////////////////////////////////////////////////////////////////////
  53. //////////////////////////////////////////////////////////////////////////////
  54. // Headers.
  55. //////////////////////////////////////////////////////////////////////////////
  56. #include "System.h"
  57. // If PATHS_IN_INCLUDES macro is defined, we can utilized relative
  58. // paths to a header file. In this case we generally go off of our
  59. // RSPiX root directory. System.h MUST be included before this macro
  60. // is evaluated. System.h is the header that, based on the current
  61. // platform (or more so in this case on the compiler), defines
  62. // PATHS_IN_INCLUDES. Blue.h includes system.h so you can include that
  63. // instead.
  64. #ifdef PATHS_IN_INCLUDES
  65. #include "ORANGE/File/file.h"
  66. #include "ORANGE/CDT/stack.h"
  67. #else
  68. #include "file.h"
  69. #include "stack.h"
  70. #endif // PATHS_IN_INCLUDES
  71. //////////////////////////////////////////////////////////////////////////////
  72. // Macros.
  73. //////////////////////////////////////////////////////////////////////////////
  74. // Converts four characters to a four character code (a U32).
  75. //#define MAKE_IFF_FCC(a,b,c,d) RIff::IffStr2FCC(#a #b #c #d);
  76. //#define MAKE_RIFF_FCC(a,b,c,d) RIff::RiffStr2FCC(#a #b #c #d);
  77. // Compile time macros.
  78. #define MAKE_IFF_FCC(a, b, c, d) (((a) << 24) | ((b) << 16) | ((c) << 8) | (d))
  79. #define MAKE_RIFF_FCC(a, b, c, d) (((d) << 24) | ((c) << 16) | ((b) << 8) | (a))
  80. #define MAX_FORMS 50
  81. //////////////////////////////////////////////////////////////////////////////
  82. // Typedefs.
  83. //////////////////////////////////////////////////////////////////////////////
  84. typedef U32 FCC;
  85. //////////////////////////////////////////////////////////////////////////////
  86. class RIff : public RFile
  87. {
  88. public: // Construction/Destruction.
  89. // Default constructor.
  90. RIff(void);
  91. // Destructor.
  92. ~RIff(void);
  93. //////////////////////////////////////////////////////////////////////////////
  94. public: // Typedefs.
  95. typedef struct
  96. {
  97. FCC fccChunk; // Chunk type.
  98. FCC fccForm; // Form type for Form chunks, otherwise 0.
  99. ULONG ulSize; // Size of this chunk.
  100. long lDataPos; // Position, in file, of data for this chunk.
  101. long lSizePos; // Position, in file, of size for this chunk. Used
  102. // for writing chunks.
  103. } CHUNK, *PCHUNK;
  104. public: // Methods.
  105. ////////////////////////////////////////////////////////////////////////
  106. // General.
  107. ////////////////////////////////////////////////////////////////////////
  108. // Closes the file. We hook this from CNFile to avoid chunks being
  109. // left open.
  110. // Returns 0 on success.
  111. short Close(void);
  112. // Gets the string representation of the FCC for the current chunk.
  113. short GetChunk( // Returns 0 on success.
  114. char* pszFCC) // Array of at least FIVE(5(V)) bytes for string.
  115. {
  116. // If this is a RIFF file . . .
  117. if (m_endian == LittleEndian)
  118. RiffFCC2Str(m_chunk.fccChunk, pszFCC);
  119. else
  120. IffFCC2Str(m_chunk.fccChunk, pszFCC);
  121. return (m_chunk.fccChunk == 0) ? 1 : 0;
  122. }
  123. ULONG GetChunk(void) // Returns FCC of current chunk.
  124. { return m_chunk.fccChunk; }
  125. // Gets the FCC of the current chunk's FORM, if there is one.
  126. short GetForm( // Returns non-zero if no form.
  127. char* pszFCC) // Array of at least FIVE(5(V)) bytes for string.
  128. {
  129. // If this is a RIFF file . . .
  130. if (m_endian == LittleEndian)
  131. RiffFCC2Str(m_chunk.fccForm, pszFCC);
  132. else
  133. IffFCC2Str(m_chunk.fccForm, pszFCC);
  134. return (m_chunk.fccForm == 0) ? 1 : 0;
  135. }
  136. ULONG GetForm(void) // Returns FCC or 0 if no form for this chunk.
  137. { return m_chunk.fccForm; }
  138. ULONG GetSize(void) // Returns size of current chunk.
  139. { return m_chunk.ulSize; }
  140. // Get the file position of the next to the specified chunk.
  141. long GetNextChunkPos( // Returns the position of the next to the
  142. // chunk specified below.
  143. CHUNK* pchunk) // Chunk to evaluate.
  144. {
  145. // The freshly initialized chunk is a special case . . .
  146. if (pchunk->lSizePos == 0)
  147. return Tell();
  148. else
  149. return pchunk->lSizePos // File position of size.
  150. + sizeof(pchunk->ulSize) // Size of size field.
  151. + pchunk->ulSize // Size of chunk.
  152. + ((pchunk->ulSize % 2) ? 1 : 0); // New chunks on even
  153. // (16 bit) boundaries.
  154. }
  155. ////////////////////////////////////////////////////////////////////////
  156. // Reading.
  157. ////////////////////////////////////////////////////////////////////////
  158. // Finds the chunk specified by pszPath. "." is used as a separator be-
  159. // tween chunk names. A "." as the first character of the path, in-
  160. // dicates a full path from the root as opposed to a relative path.
  161. // For example, ".WAVE.fmt " or "fmt ".
  162. // Things to note:
  163. // 1) Relative paths are searched starting at the current level (i.e., the
  164. // current chunk is NOT descended into before searching) and the first
  165. // chunk checked is the one FOLLOWING the current.
  166. // 2) Any path ending in "." is descended into.
  167. // Examples: ".WAVE." puts you inside the "WAVE" FORM. ".WAVE"
  168. // puts you at the "WAVE" FORM. The path "." puts you above the "RIFF"
  169. // or "AIFF" chunk.
  170. short Find(char* pszPath); // Returns 0 on success.
  171. // Move from current chunk to the next chunk at this level. This must
  172. // be called before calling Get* functions after an Open. You
  173. // must call this before calling Descend. You must descend into chunks
  174. // that contain multiple sub chunks if you want to use Next to traverse
  175. // them.
  176. short Next(void); // Returns 0 if successful, 1 if no more chunks,
  177. // negative on error.
  178. // Descend into current chunk. This must be called for the top-level
  179. // chunk in the file in order to parse the sub chunks. It can be called
  180. // for any chunk that contains sub chunks.
  181. // After calling Descend, there is no current chunk until Next is called.
  182. short Descend(void); // Returns 0 if successful, 1 if no subchunks,
  183. // negative on error.
  184. // Ascend out of a chunk previously Descend'ed into. LIFO ordering, of
  185. // course. You must call Next after calling Ascend before any values
  186. // are valid.
  187. short Ascend(void); // Returns 0 if successful, 1 if no more chunks,
  188. // negative on error.
  189. ////////////////////////////////////////////////////////////////////////
  190. // Writing.
  191. ////////////////////////////////////////////////////////////////////////
  192. // Creates a chunk header of type fccChunk with room for a 32 bit size
  193. // field to later be filled in by EndChunk. If fccForm is not 0, a new
  194. // form is created.
  195. // Returns 0 on success.
  196. short CreateChunk(FCC fccChunk, FCC fccForm = 0);
  197. // Ends a chunk created by CreateChunk. The fcc parameters are only for
  198. // debugging and may be left out.
  199. // Returns 0 on success.
  200. short EndChunk(FCC fccChunk = 0, FCC fccForm = 0);
  201. //////////////////////////////////////////////////////////////////////////////
  202. public: // Static
  203. // Create FCC code for an IFF file based on a 4-character string
  204. // Platform independent. Open IFF files as ENDIAN_BIG.
  205. static ULONG IffStr2FCC(char* pszFCC)
  206. { return (pszFCC[0] << 24) | (pszFCC[1] << 16) | (pszFCC[2] << 8) | (pszFCC[3]); }
  207. // Create FCC code for an RIFF file based on a 4-characater string
  208. // Platform independent. Open RIFF files as ENDIAN_LITTLE.
  209. static ULONG RiffStr2FCC(char* pszFCC)
  210. { return (pszFCC[3] << 24) | (pszFCC[2] << 16) | (pszFCC[1] << 8) | (pszFCC[0]); }
  211. // Create 4-character string for an IFF file based on FCC.
  212. // Platform independent. Open IFF files as ENDIAN_BIG.
  213. static void IffFCC2Str( ULONG ulFCC, // FCC to convert.
  214. char* pszFCC) // String of at least 5 bytes.
  215. {
  216. pszFCC[0] = (char)(ulFCC >> 24);
  217. pszFCC[1] = (char)(ulFCC >> 16);
  218. pszFCC[2] = (char)(ulFCC >> 8);
  219. pszFCC[3] = (char)(ulFCC);
  220. pszFCC[4] = '\0';
  221. }
  222. // Create 4-character string for an RIFF file based on FCC.
  223. // Platform independent. Open RIFF files as ENDIAN_LITTLE.
  224. static void RiffFCC2Str(ULONG ulFCC, // FCC to convert.
  225. char* pszFCC) // String of at least 5 bytes.
  226. {
  227. pszFCC[3] = (char)(ulFCC >> 24);
  228. pszFCC[2] = (char)(ulFCC >> 16);
  229. pszFCC[1] = (char)(ulFCC >> 8);
  230. pszFCC[0] = (char)(ulFCC);
  231. pszFCC[4] = '\0';
  232. }
  233. //////////////////////////////////////////////////////////////////////////////
  234. public: // Querries.
  235. //////////////////////////////////////////////////////////////////////////////
  236. protected: // Internal functions.
  237. // Seek to non-relative position lPos but check current position first
  238. // and do a relative seek (SEEK_CUR). This should be better for reading
  239. // from CD. Won't seek if the distance is 0.
  240. // Returns 0 on success.
  241. short RelSeek(long lPos);
  242. // Initialize members.
  243. void Init(void);
  244. // Read chunk header.
  245. short ReadChunkHeader(void); // Returns 0 on success.
  246. // Determine if fcc is a FORM type.
  247. short IsForm( // Returns TRUE if fcc is a form; FALSE otherwise.
  248. FCC fcc);
  249. //////////////////////////////////////////////////////////////////////////////
  250. public: // Member variables.
  251. protected: // Protected member variables.
  252. RStack <PCHUNK> m_stack;
  253. CHUNK m_chunk;
  254. static FCC ms_afccIffForms[MAX_FORMS]; // Chunk FCC recognized
  255. // as being FORMs in IFF
  256. // files.
  257. static FCC ms_afccRiffForms[MAX_FORMS]; // Chunk FCC recognized
  258. // as being FORMs in RIFF
  259. // files.
  260. };
  261. #endif // IFF_H
  262. //////////////////////////////////////////////////////////////////////////////
  263. // EOF
  264. //////////////////////////////////////////////////////////////////////////////