Branch data Line data Source code
1 : : #ifndef VAR_LEN_TAG_HPP
2 : : #define VAR_LEN_TAG_HPP
3 : :
4 : : #include <stdlib.h>
5 : : #include <string.h>
6 : :
7 : : namespace moab
8 : : {
9 : :
10 : : /* Remove this preprocessor macro to compile
11 : : * simple implementation w/ no inlined storage
12 : : */
13 : : #define VAR_LEN_TAG_ELIDE_DATA
14 : :
15 : : /* Define class data layout depending on macros:
16 : : * VAR_LEN_TAG_ELIDE_DATA and TEMPLATE_SPECIALIZATION
17 : : */
18 : : #ifndef VAR_LEN_TAG_ELIDE_DATA
19 : :
20 : : /* The trivial implementation */
21 : : public
22 : : VarLenTagData
23 : : {
24 : : public:
25 : : struct
26 : : {
27 : : struct
28 : : {
29 : : unsigned size;
30 : : unsigned char* array;
31 : : } mPointer;
32 : : } mData;
33 : : };
34 : :
35 : : #elif !defined( MOAB_TEMPLATE_SPECIALIZATION )
36 : :
37 : : /* A little more advanced data structure for VarLenTag.
38 : : * If the amount of tag data is less than or equal to the
39 : : * size of the array pointer, store it inline in the pointer
40 : : * value field so no memory needs to be allocated.
41 : : */
42 : : class VarLenTagData
43 : : {
44 : : public:
45 : : enum
46 : : {
47 : : INLINE_COUNT = sizeof( unsigned char* )
48 : : };
49 : :
50 : : union
51 : : {
52 : : struct
53 : : {
54 : : unsigned char* array;
55 : : unsigned size;
56 : : } mPointer;
57 : : struct
58 : : {
59 : : unsigned char array[INLINE_COUNT];
60 : : unsigned size;
61 : : } mInline;
62 : : } mData;
63 : : };
64 : :
65 : : #else
66 : :
67 : : /* Most complex implementation. Same as the previous one, except
68 : : * when storing data inline, also utilize any padding in the struct.
69 : : * This implementation requires support for template specialization.
70 : : *
71 : : * - The data must be first in the struct to avoid alignment issues
72 : : * for double and 64-bit handle values on some platforms.
73 : : * - The size must therefore be at the end of the struct (including
74 : : * after any padding) because a) it cannot be at the beginning and
75 : : * b) it must be at the same location in both structs in the union.
76 : : * - For the mPointer variation, the padding must be declared
77 : : * explicitly in order for the size to be forced to the end.
78 : : * - Template specialization is used to avoid declaring a
79 : : * zero-length array for pad on 32-bit platforms.
80 : : * NOTE: GCC allows zero-length arrays, but Sun's compiler
81 : : * (and most others) do not.
82 : : */
83 : : template < unsigned >
84 : : class VarLenTagDataTemplate
85 : : {
86 : : public:
87 : 906 : inline VarLenTagDataTemplate() {}
88 : :
89 : : struct MallocData
90 : : {
91 : : unsigned char* array;
92 : : unsigned size;
93 : : };
94 : :
95 : : enum
96 : : {
97 : : INLINE_COUNT = sizeof( MallocData ) - sizeof( unsigned )
98 : : };
99 : :
100 : : union
101 : : {
102 : : struct
103 : : {
104 : : unsigned char* array;
105 : : unsigned char pad[INLINE_COUNT - sizeof( unsigned char* )];
106 : : unsigned size;
107 : : } mPointer;
108 : : struct
109 : : {
110 : : unsigned char array[INLINE_COUNT];
111 : : unsigned size;
112 : : } mInline;
113 : : } mData;
114 : : };
115 : :
116 : : template <>
117 : : class VarLenTagDataTemplate< 0u >
118 : : {
119 : : public:
120 : : inline VarLenTagDataTemplate< 0u >() {}
121 : :
122 : : enum
123 : : {
124 : : INLINE_COUNT = sizeof( unsigned char* )
125 : : };
126 : :
127 : : union
128 : : {
129 : : struct
130 : : {
131 : : unsigned char* array;
132 : : unsigned size;
133 : : } mPointer;
134 : : struct
135 : : {
136 : : unsigned char array[INLINE_COUNT];
137 : : unsigned size;
138 : : } mInline;
139 : : } mData;
140 : : };
141 : :
142 : : typedef VarLenTagDataTemplate< sizeof( unsigned char* ) - sizeof( unsigned ) > VarLenTagData;
143 : :
144 : : #endif
145 : :
146 : : /**\brief Class for storing variable-length tag data
147 : : *
148 : : * Class for managing variable-length tag data.
149 : : *\NOTE This class must behave as if it were initialized to empty
150 : : * if it is memset to zero w/out invoking any constructor.
151 : : */
152 : : class VarLenTag
153 : : {
154 : : protected:
155 : : VarLenTagData mData;
156 : :
157 : : public:
158 : 894 : inline VarLenTag()
159 : 894 : {
160 : 894 : mData.mData.mPointer.size = 0;
161 : 894 : }
162 : : inline VarLenTag( unsigned size );
163 : 834 : inline ~VarLenTag()
164 : : {
165 : 834 : clear();
166 : 834 : }
167 : : inline VarLenTag( const VarLenTag& copy );
168 : : inline VarLenTag( unsigned size, const void* data );
169 : :
170 : 3150995 : inline unsigned size() const
171 : : {
172 : 3150995 : return mData.mData.mPointer.size;
173 : : }
174 : :
175 : 1141 : inline unsigned char* data()
176 : : #ifdef VAR_LEN_TAG_ELIDE_DATA
177 : : {
178 [ + + ]: 1141 : return size() <= VarLenTagData::INLINE_COUNT ? mData.mData.mInline.array : mData.mData.mPointer.array;
179 : : }
180 : : #else
181 : : {
182 : : return mData.mData.mPointer.array;
183 : : }
184 : : #endif
185 : :
186 : 0 : inline unsigned long mem() const
187 : : #ifdef VAR_LEN_TAG_ELIDE_DATA
188 : : {
189 [ # # ]: 0 : return size() <= VarLenTagData::INLINE_COUNT ? 0 : size();
190 : : }
191 : : #else
192 : : {
193 : : return size();
194 : : }
195 : : #endif
196 : :
197 : 1105 : inline const unsigned char* data() const
198 : : {
199 : 1105 : return const_cast< VarLenTag* >( this )->data();
200 : : }
201 : :
202 : : inline unsigned char* resize( unsigned size );
203 : :
204 : : inline void clear();
205 : :
206 : 1115 : inline void set( const void* dat, unsigned sz )
207 : : {
208 : 1115 : memcpy( resize( sz ), dat, sz );
209 : 1115 : }
210 : :
211 : : inline VarLenTag& operator=( const VarLenTag& other )
212 : : {
213 : : set( other.data(), other.size() );
214 : : return *this;
215 : : }
216 : : };
217 : :
218 : 1123 : inline unsigned char* VarLenTag::resize( unsigned s )
219 : : {
220 : : #ifdef VAR_LEN_TAG_ELIDE_DATA
221 [ + + ]: 1123 : if( s <= VarLenTagData::INLINE_COUNT )
222 : : {
223 [ + + ]: 645 : if( size() > VarLenTagData::INLINE_COUNT )
224 : : {
225 : 15 : unsigned char* tmp_ptr = mData.mData.mPointer.array;
226 : 15 : memcpy( mData.mData.mInline.array, tmp_ptr, s );
227 : 15 : free( tmp_ptr );
228 : : }
229 : 645 : mData.mData.mInline.size = s;
230 : 645 : return mData.mData.mInline.array;
231 : : }
232 [ + + ]: 478 : else if( size() <= VarLenTagData::INLINE_COUNT )
233 : : {
234 : 462 : void* tmp_ptr = malloc( s );
235 : 462 : memcpy( tmp_ptr, mData.mData.mInline.array, size() );
236 : 462 : mData.mData.mPointer.array = reinterpret_cast< unsigned char* >( tmp_ptr );
237 : : }
238 : : else
239 : : #endif
240 [ + - ]: 16 : if( size() < s )
241 : : {
242 [ + - ]: 16 : void* tmp_ptr = size() ? realloc( mData.mData.mPointer.array, s ) : malloc( s );
243 : 16 : mData.mData.mPointer.array = reinterpret_cast< unsigned char* >( tmp_ptr );
244 : : }
245 : 478 : mData.mData.mPointer.size = s;
246 : 478 : return mData.mData.mPointer.array;
247 : : }
248 : :
249 : 24 : inline VarLenTag::VarLenTag( unsigned sz )
250 : : {
251 : : #ifdef VAR_LEN_TAG_ELIDE_DATA
252 [ + + ]: 12 : if( sz > VarLenTagData::INLINE_COUNT )
253 : : #endif
254 : 6 : mData.mData.mPointer.array = reinterpret_cast< unsigned char* >( malloc( sz ) );
255 : 12 : mData.mData.mPointer.size = sz;
256 : 12 : }
257 : :
258 : 3146848 : inline void VarLenTag::clear()
259 : : {
260 : : #ifdef VAR_LEN_TAG_ELIDE_DATA
261 [ + + ]: 3146848 : if( size() > VarLenTagData::INLINE_COUNT )
262 : : #else
263 : : if( size() )
264 : : #endif
265 : 417 : free( mData.mData.mPointer.array );
266 : 3146848 : mData.mData.mPointer.size = 0;
267 : 3146848 : }
268 : :
269 : : inline VarLenTag::VarLenTag( const VarLenTag& copy ) : mData( copy.mData )
270 : : {
271 : : #ifdef VAR_LEN_TAG_ELIDE_DATA
272 : : if( size() > VarLenTagData::INLINE_COUNT )
273 : : #endif
274 : : {
275 : : mData.mData.mPointer.array = reinterpret_cast< unsigned char* >( malloc( size() ) );
276 : : memcpy( mData.mData.mPointer.array, copy.mData.mData.mPointer.array, size() );
277 : : }
278 : : }
279 : :
280 : : inline VarLenTag::VarLenTag( unsigned sz, const void* dat )
281 : : {
282 : : mData.mData.mPointer.size = 0;
283 : : if( sz ) memcpy( resize( sz ), dat, sz );
284 : : }
285 : :
286 : : } // namespace moab
287 : :
288 : : #endif
|