Clarified that group chunks must have chunks in them
[iffl.git] / heads.h
blob27a77912a9e5a64681b5391b093eae9c1f4628e7
1 // This file is part of the interchange file format library.
2 //
3 // Copyright (C) 2003-2006 by Mike Sharov <msharov@users.sourceforge.net>
4 // This file is free software, distributed under the MIT License.
5 //
6 // heads.h
7 //
8 // Chunk header formats for the Interchange File Format.
9 //
11 #ifndef HEADS_H_6AE64E742217B13E3F576C6D5A4C3292
12 #define HEADS_H_6AE64E742217B13E3F576C6D5A4C3292
14 #include "config.h"
16 /// Contains functions for dealing with IFF formatted files.
17 namespace iff {
18 using namespace ustl;
20 //----------------------------------------------------------------------
21 // Type definitions
22 //----------------------------------------------------------------------
23 typedef uint32_t fmt_t; ///< Type for format fields in the headers
24 typedef uint32_t chsize_t; ///< Type for the chunk size field
25 typedef uint32_t ccount_t; ///< Type for the child count field
27 //----------------------------------------------------------------------
28 // IFF standard chunk formats
29 //----------------------------------------------------------------------
31 #if IFF_BYTE_ORDER == USTL_LITTLE_ENDIAN
32 #define IFF_FMT(a,b,c,d) ((((((::iff::fmt_t(d)<<8)|(c))<<8)|(b))<<8)|(a))
33 inline void boci2n (uint32_t& v) { v = le_to_native(v); }
34 inline uint32_t bon2i(uint32_t v) { return (native_to_le(v)); }
35 #else
36 #define IFF_FMT(a,b,c,d) ((((((::iff::fmt_t(a)<<8)|(b))<<8)|(c))<<8)|(d))
37 inline void boci2n (uint32_t& v) { v = be_to_native(v); }
38 inline uint32_t bon2i(uint32_t v) { return (native_to_be(v)); }
39 #endif
40 #define IFF_SFMT(s) IFF_FMT(s[0],s[1],s[2],s[3])
42 enum {
43 cfmt_Unknown = 0,
44 cfmt_FORM = IFF_FMT('F','O','R','M'),
45 cfmt_LIST = IFF_FMT('L','I','S','T'),
46 cfmt_CAT = IFF_FMT('C','A','T',' '),
47 cfmt_Filler = IFF_FMT(' ',' ',' ',' '),
48 cfmt_Bitmap = IFF_FMT('I','L','B','M'),
49 cfmt_Properties = IFF_FMT('P','R','O','P'),
50 cfmt_BitmapHeader = IFF_FMT('B','M','H','D'),
51 cfmt_ColorMap = IFF_FMT('C','M','A','P'),
52 cfmt_ColorLookupTable = IFF_FMT('C','L','U','T'),
53 cfmt_ColorCycle1 = IFF_FMT('C','R','N','G'),
54 cfmt_ColorCycle2 = IFF_FMT('C','C','R','T'),
55 cfmt_HotSpot = IFF_FMT('G','R','A','B'),
56 cfmt_Sprite = IFF_FMT('S','P','R','T'),
57 cfmt_VoiceHeader = IFF_FMT('V','H','D','R'),
58 cfmt_Name = IFF_FMT('N','A','M','E'),
59 cfmt_Copyright = IFF_FMT('(','c',')',' '),
60 cfmt_Author = IFF_FMT('A','U','T','H'),
61 cfmt_Annotation = IFF_FMT('A','N','N','O'),
62 cfmt_Attack = IFF_FMT('A','T','A','K'),
63 cfmt_Release = IFF_FMT('R','L','S','E'),
64 cfmt_Generic = IFF_FMT('B','O','D','Y'),
65 cfmt_Vector = IFF_FMT('V','E','C','T'),
66 cfmt_CountedContainer = IFF_FMT('C','N','T','R'),
67 cfmt_StringTable = IFF_FMT('S','T','R','T'),
68 cfmt_Autodetect = IFF_FMT('A','U','T','O')
71 //----------------------------------------------------------------------
73 /// \class CChunkHeader heads.h iff.h
74 ///
75 /// \brief Header for non-aggregate chunks.
76 ///
77 /// Contains size and format information for the chunk. Like
78 /// CContainerHeader, the written format is the spec too, so
79 /// can be written manually. The size is the size of the
80 /// chunk data, not including the header
81 ///
82 class CChunkHeader {
83 public:
84 inline CChunkHeader (void) : m_Format (cfmt_Generic), m_Size (0) { }
85 inline CChunkHeader (chsize_t size, fmt_t fmt = cfmt_Generic) : m_Format (fmt), m_Size (size) { }
86 inline void read (istream& is) { is >> m_Format >> m_Size; boci2n(m_Format); boci2n(m_Size); }
87 inline void write (ostream& os) const { os << bon2i(m_Format) << bon2i(m_Size); }
88 inline size_t stream_size (void) const { return (stream_size_of(m_Format) + stream_size_of(m_Size)); }
89 inline size_t Size (void) const { return (m_Size); }
90 inline size_t SizeWithHeader (void) const { return (Size() + stream_size()); }
91 inline fmt_t Format (void) const { return (m_Format); }
92 void Verify (fmt_t fmt = cfmt_Generic, const char* chunkName = "chunk", uoff_t offset = 0) const;
93 private:
94 fmt_t m_Format; ///< Format of the chunk
95 chsize_t m_Size; ///< Size of the chunk including the header.
98 //----------------------------------------------------------------------
100 /// \class CGroupHeader heads.h iff.h
102 /// \brief Header for aggregate chunks like FORM, LIST, and CAT
103 /// This header can be written standalone, or with WriteVector.
104 /// Each IFF file must start with a group header with file size
105 /// and type of contents.
107 class CGroupHeader : public CChunkHeader {
108 public:
109 CGroupHeader (void);
110 CGroupHeader (chsize_t size, fmt_t childFormat = cfmt_Generic, fmt_t fmt = cfmt_FORM);
111 inline void read (istream& is) { CChunkHeader::read (is); is >> m_ChildFormat; boci2n (m_ChildFormat); }
112 inline void write (ostream& os) const { CChunkHeader::write (os); os << bon2i(m_ChildFormat); }
113 inline size_t stream_size (void) const { return (CChunkHeader::stream_size() + stream_size_of(m_ChildFormat)); }
114 inline fmt_t ChildFormat (void) const { return (m_ChildFormat); }
115 inline size_t Size (void) const { return (CChunkHeader::Size() - (stream_size() - CChunkHeader::stream_size())); }
116 void Verify (fmt_t childFormat = cfmt_Generic, fmt_t fmt = cfmt_FORM, const char* chunkName = "FORM", uoff_t offset = 0) const;
117 private:
118 fmt_t m_ChildFormat; ///< Format of each child chunk.
121 //----------------------------------------------------------------------
123 /// \brief PROP section values
124 struct SProp {
125 fmt_t m_Name; ///< 4 character prop name (use IFF_FMT to define)
126 uint32_t m_Value; ///< Property value.
129 //----------------------------------------------------------------------
131 } // namespace iff
133 ALIGNOF(iff::CChunkHeader, IFF_GRAIN)
134 STD_STREAMABLE(iff::CChunkHeader)
135 STD_STREAMABLE(iff::CGroupHeader)
137 #endif