Umasoft
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Groups Pages
LevellerTag.h
1 #ifndef __LEVELLER_TAG_H__
2 #define __LEVELLER_TAG_H__
3 /*
4  LevellerTag.h
5 
6  Tag storage support.
7  Copyright 2002-2005 Daylon Graphics Ltd. / Virtual Terrain Project
8  ____________________________________________________________________________
9  Please use a tab setting of 4 to view this file.
10  ____________________________________________________________________________
11 
12  This file came from part of the Leveller (tm) Software Developer's Kit.
13  It is the reference C++ code used to implement the hierarchical tag storage
14  system used by the public heightfield clipboard format (and possibly
15  elsewhere).
16 
17  This code is licenced under the LGPL (Lesser GNU Public Licence).
18  Basically, you can do whatever you want with it, including integrating
19  it with commercial software.
20 
21  Note: One-byte structure member alignment used.
22 
23  Tags are data storage entities that exist in a hierarchical relationship
24  within a root "tag", which is just an area of memory manipulated by the
25  CRootTag class.
26 
27  CRootTag always iterates through the entire block when searching for a tag.
28  This is not considered to be a problem since a) the number of tags is
29  small, b) the data is in memory, and c) once a match on the head of the
30  pathspec occurs, the search rapidly narrows. If the search time becomes
31  problematic, you can always use the tag's tagSize fields to store
32  aggregate size info in each tag, allowing you to skip a tag and all its
33  children in one shot. Calculating the values of this field is not
34  currently implemented.
35 
36  Note: this module doesn't know anything about the clipboard, since that
37  tends to be a platform-specific feature. Daylon Graphics may have
38  reference code for clipboard usage elsewhere in the Leveller SDK.
39 */
40 
41 #pragma pack(push, 1)
42 
43 namespace daylon {
44 
45 typedef uchar uint8, uchar, byte;
46 typedef char int8;
47 typedef short int16;
48 typedef unsigned short uint16, word;
49 typedef int int32;
50 typedef uint uint32, dword;
51 typedef float float32;
52 typedef double float64;
53 
54 typedef void* (*_MALLOCFUNC)(size_t);
55 typedef void (*_FREEFUNC)(void*);
56 typedef void* (*_MEMCOPYFUNC)(void*, const void*, size_t);
57 
58 
59 const size_t MAX_TAGNAMELEN = 15;
60 
61 enum
62 {
63  VALKIND_NONE = 0,
64  VALKIND_BINARY = 1,
65  VALKIND_CHAR = 2,
66  VALKIND_BYTE = 3,
67  VALKIND_INT16 = 4,
68  VALKIND_UINT16 = 5,
69  VALKIND_INT32 = 6,
70  VALKIND_UINT32 = 7,
71  VALKIND_FLOAT = 8,
72  VALKIND_DOUBLE = 9
73 };
74 
75 // Relation flags; OR together.
76 enum
77 {
78  TAGRELATION_CHILD = 1,
79  TAGRELATION_SIBLING = 2
80 };
81 
82 
83 typedef struct
84 {
85  char szName[MAX_TAGNAMELEN + 1];
86 
87  daylon::uint32 valueSize;
88  daylon::uint32 reserved;
89 
90  // To make seeking more efficient, one can,
91  // after writing all the tags, work through them,
92  // compute each one's full compound size, and
93  // store them here.
94  daylon::uint32 tagSize;
95  daylon::uint32 reserved2;
96 
97  daylon::int16 relationFlags;
98  daylon::int16 valueKind;
99 } TAGHEADER; // 36 bytes
100 
101 typedef union
102 {
103  daylon::int32 n;
104  daylon::float64 d;
105  daylon::byte c[1];
106 } TAGVALUE; // 8 bytes
107 
108 // A tag takes sizeof(TAGHEADER) + header.valueSize bytes.
109 // If a tag is storing a scalar type and header.valueSize
110 // is greater than the scalar's size, it means an array
111 // of scalar values is being stored, the number of which
112 // is valueSize / sizeof(scalar).
113 typedef struct
114 {
115  TAGHEADER header;
116  TAGVALUE value;
117 } TAG;
118 
119 #pragma pack(pop)
120 
121 
122 class CRootTag
123 {
124  // Implements a C++ interface to a
125  // virtual root tag. Call CalcNormalStorage
126  // to compute the storage for all the normal tags
127  // of each type you need,
128  // and CalcBinaryTagStorage for each binary tag.
129  // Sum the results together, allocate a block
130  // that size, and call SetStorage.
131  // Call Open to read or write tags.
132  // If you're writing a root tag, call Write
133  // to append each tag. If you're reading, call ReadTag.
134 
135  public:
136  CRootTag() : m_pRoot(NULL), m_mark(0), m_size(0),
137  m_openMode(0) {}
138  virtual ~CRootTag() {}
139 
140  size_t GetValSize(int) const;
141  size_t CalcNormalStorage(size_t numTags, int kind, size_t arraySize = 1) const;
142  size_t CalcBinaryTagStorage(size_t binSize) const;
143 
144  void SetStorage(void* p, size_t n)
145  { m_pRoot = (uchar*)p;
146  m_mark = 0; m_size = n; m_openMode = 0; }
147 
148  void Open(const char* pszMode);
149  void Close(void);
150 
151  // WriteParent() lets you write a parent tag.
152  void WriteParent(const char* pszName, bool bHasSibling)
153  { this->Write(pszName,
154  TAGRELATION_CHILD |
155  (bHasSibling ? TAGRELATION_SIBLING : 0));
156  }
157 
158  // Write() is the general-purpose tag appender.
159  void Write(
160  const char* pszName, int relationFlags,
161  int valueKind = VALKIND_NONE,
162  const void* pvData = NULL,
163  size_t datasize = 0);
164 
165  void Write(const char* pszName,
166  daylon::uint32 value,
167  bool bHasSibling);
168 
169  void Write(const char* pszName,
170  double value,
171  bool bHasSibling);
172 
173 
174  // WriteBinary() must be used if you are dynamically
175  // generating the tag's value, or if you want to
176  // save memory and create the value data inside
177  // the tag's memory area.
178  void* WriteBinary(
179  const char* pszName, bool bHasSibling,
180  size_t datasize);
181 
182  // Read() is the generic tag reader.
183  // Full pathspecs must always be given.
184  size_t Read(const char*, void**);
185  daylon::uint32 ReadUINT32(const char*, daylon::uint32 _default);
186  double ReadDouble(const char*, double _default);
187 
188  size_t MemSize(void) const
189  { return sizeof(*this) + m_size; }
190  void CopyFrom(const CRootTag&, _MALLOCFUNC, _MEMCOPYFUNC);
191  void Destroy(_FREEFUNC);
192 
193 #if VTDEBUG
194  void Dump(void);
195  void DumpTag(const char*);
196  static const char* TypeString(int);
197  static char* ValueString(const TAG&, char*);
198 #endif
199 
200  private:
201  uchar* m_pRoot;
202  size_t m_mark;
203  size_t m_size;
204  int m_openMode;
205 
206  void WasEndReached(void);
207  int SkipTag(void);
208  size_t ReadTag(const char*, void**);
209  size_t ArraySize(const TAG&) const;
210 
211 }; // CRootTag
212 
213 } // namespace daylon
214 
215 #endif // __LEVELLER_TAG_H__