MOAB: Mesh Oriented datABase
(version 5.4.1)
|
00001 #ifndef VAR_LEN_TAG_HPP 00002 #define VAR_LEN_TAG_HPP 00003 00004 #include <cstdlib> 00005 #include <cstring> 00006 00007 namespace moab 00008 { 00009 00010 /* Remove this preprocessor macro to compile 00011 * simple implementation w/ no inlined storage 00012 */ 00013 #define VAR_LEN_TAG_ELIDE_DATA 00014 00015 /* Define class data layout depending on macros: 00016 * VAR_LEN_TAG_ELIDE_DATA and TEMPLATE_SPECIALIZATION 00017 */ 00018 #ifndef VAR_LEN_TAG_ELIDE_DATA 00019 00020 /* The trivial implementation */ 00021 public 00022 VarLenTagData 00023 { 00024 public: 00025 struct 00026 { 00027 struct 00028 { 00029 unsigned size; 00030 unsigned char* array; 00031 } mPointer; 00032 } mData; 00033 }; 00034 00035 #elif !defined( MOAB_TEMPLATE_SPECIALIZATION ) 00036 00037 /* A little more advanced data structure for VarLenTag. 00038 * If the amount of tag data is less than or equal to the 00039 * size of the array pointer, store it inline in the pointer 00040 * value field so no memory needs to be allocated. 00041 */ 00042 class VarLenTagData 00043 { 00044 public: 00045 enum 00046 { 00047 INLINE_COUNT = sizeof( unsigned char* ) 00048 }; 00049 00050 union 00051 { 00052 struct 00053 { 00054 unsigned char* array; 00055 unsigned size; 00056 } mPointer; 00057 struct 00058 { 00059 unsigned char array[INLINE_COUNT]; 00060 unsigned size; 00061 } mInline; 00062 } mData; 00063 }; 00064 00065 #else 00066 00067 /* Most complex implementation. Same as the previous one, except 00068 * when storing data inline, also utilize any padding in the struct. 00069 * This implementation requires support for template specialization. 00070 * 00071 * - The data must be first in the struct to avoid alignment issues 00072 * for double and 64-bit handle values on some platforms. 00073 * - The size must therefore be at the end of the struct (including 00074 * after any padding) because a) it cannot be at the beginning and 00075 * b) it must be at the same location in both structs in the union. 00076 * - For the mPointer variation, the padding must be declared 00077 * explicitly in order for the size to be forced to the end. 00078 * - Template specialization is used to avoid declaring a 00079 * zero-length array for pad on 32-bit platforms. 00080 * NOTE: GCC allows zero-length arrays, but Sun's compiler 00081 * (and most others) do not. 00082 */ 00083 template < unsigned > 00084 class VarLenTagDataTemplate 00085 { 00086 public: 00087 inline VarLenTagDataTemplate() {} 00088 00089 struct MallocData 00090 { 00091 unsigned char* array; 00092 unsigned size; 00093 }; 00094 00095 enum 00096 { 00097 INLINE_COUNT = sizeof( MallocData ) - sizeof( unsigned ) 00098 }; 00099 00100 union 00101 { 00102 struct 00103 { 00104 unsigned char* array; 00105 unsigned char pad[INLINE_COUNT - sizeof( unsigned char* )]; 00106 unsigned size; 00107 } mPointer; 00108 struct 00109 { 00110 unsigned char array[INLINE_COUNT]; 00111 unsigned size; 00112 } mInline; 00113 } mData; 00114 }; 00115 00116 template <> 00117 class VarLenTagDataTemplate< 0u > 00118 { 00119 public: 00120 inline VarLenTagDataTemplate< 0u >() {} 00121 00122 enum 00123 { 00124 INLINE_COUNT = sizeof( unsigned char* ) 00125 }; 00126 00127 union 00128 { 00129 struct 00130 { 00131 unsigned char* array; 00132 unsigned size; 00133 } mPointer; 00134 struct 00135 { 00136 unsigned char array[INLINE_COUNT]; 00137 unsigned size; 00138 } mInline; 00139 } mData; 00140 }; 00141 00142 typedef VarLenTagDataTemplate< sizeof( unsigned char* ) - sizeof( unsigned ) > VarLenTagData; 00143 00144 #endif 00145 00146 /**\brief Class for storing variable-length tag data 00147 * 00148 * Class for managing variable-length tag data. 00149 *\NOTE This class must behave as if it were initialized to empty 00150 * if it is memset to zero w/out invoking any constructor. 00151 */ 00152 class VarLenTag 00153 { 00154 protected: 00155 VarLenTagData mData; 00156 00157 public: 00158 inline VarLenTag() 00159 { 00160 mData.mData.mPointer.size = 0; 00161 } 00162 inline VarLenTag( unsigned size ); 00163 inline ~VarLenTag() 00164 { 00165 clear(); 00166 } 00167 inline VarLenTag( const VarLenTag& copy ); 00168 inline VarLenTag( unsigned size, const void* data ); 00169 00170 inline unsigned size() const 00171 { 00172 return mData.mData.mPointer.size; 00173 } 00174 00175 inline unsigned char* data() 00176 #ifdef VAR_LEN_TAG_ELIDE_DATA 00177 { 00178 return size() <= VarLenTagData::INLINE_COUNT ? mData.mData.mInline.array : mData.mData.mPointer.array; 00179 } 00180 #else 00181 { 00182 return mData.mData.mPointer.array; 00183 } 00184 #endif 00185 00186 inline unsigned long mem() const 00187 #ifdef VAR_LEN_TAG_ELIDE_DATA 00188 { 00189 return size() <= VarLenTagData::INLINE_COUNT ? 0 : size(); 00190 } 00191 #else 00192 { 00193 return size(); 00194 } 00195 #endif 00196 00197 inline const unsigned char* data() const 00198 { 00199 return const_cast< VarLenTag* >( this )->data(); 00200 } 00201 00202 inline unsigned char* resize( unsigned size ); 00203 00204 inline void clear(); 00205 00206 inline void set( const void* dat, unsigned sz ) 00207 { 00208 memcpy( resize( sz ), dat, sz ); 00209 } 00210 00211 inline VarLenTag& operator=( const VarLenTag& other ) 00212 { 00213 set( other.data(), other.size() ); 00214 return *this; 00215 } 00216 }; 00217 00218 inline unsigned char* VarLenTag::resize( unsigned s ) 00219 { 00220 #ifdef VAR_LEN_TAG_ELIDE_DATA 00221 if( s <= VarLenTagData::INLINE_COUNT ) 00222 { 00223 if( size() > VarLenTagData::INLINE_COUNT ) 00224 { 00225 unsigned char* tmp_ptr = mData.mData.mPointer.array; 00226 memcpy( mData.mData.mInline.array, tmp_ptr, s ); 00227 free( tmp_ptr ); 00228 } 00229 mData.mData.mInline.size = s; 00230 return mData.mData.mInline.array; 00231 } 00232 else if( size() <= VarLenTagData::INLINE_COUNT ) 00233 { 00234 void* tmp_ptr = malloc( s ); 00235 memcpy( tmp_ptr, mData.mData.mInline.array, size() ); 00236 mData.mData.mPointer.array = reinterpret_cast< unsigned char* >( tmp_ptr ); 00237 } 00238 else 00239 #endif 00240 if( size() < s ) 00241 { 00242 void* tmp_ptr = size() ? realloc( mData.mData.mPointer.array, s ) : malloc( s ); 00243 mData.mData.mPointer.array = reinterpret_cast< unsigned char* >( tmp_ptr ); 00244 } 00245 mData.mData.mPointer.size = s; 00246 return mData.mData.mPointer.array; 00247 } 00248 00249 inline VarLenTag::VarLenTag( unsigned sz ) 00250 { 00251 #ifdef VAR_LEN_TAG_ELIDE_DATA 00252 if( sz > VarLenTagData::INLINE_COUNT ) 00253 #endif 00254 mData.mData.mPointer.array = reinterpret_cast< unsigned char* >( malloc( sz ) ); 00255 mData.mData.mPointer.size = sz; 00256 } 00257 00258 inline void VarLenTag::clear() 00259 { 00260 #ifdef VAR_LEN_TAG_ELIDE_DATA 00261 if( size() > VarLenTagData::INLINE_COUNT ) 00262 #else 00263 if( size() ) 00264 #endif 00265 free( mData.mData.mPointer.array ); 00266 mData.mData.mPointer.size = 0; 00267 } 00268 00269 inline VarLenTag::VarLenTag( const VarLenTag& copy ) : mData( copy.mData ) 00270 { 00271 #ifdef VAR_LEN_TAG_ELIDE_DATA 00272 if( size() > VarLenTagData::INLINE_COUNT ) 00273 #endif 00274 { 00275 mData.mData.mPointer.array = reinterpret_cast< unsigned char* >( malloc( size() ) ); 00276 memcpy( mData.mData.mPointer.array, copy.mData.mData.mPointer.array, size() ); 00277 } 00278 } 00279 00280 inline VarLenTag::VarLenTag( unsigned sz, const void* dat ) 00281 { 00282 mData.mData.mPointer.size = 0; 00283 if( sz ) memcpy( resize( sz ), dat, sz ); 00284 } 00285 00286 } // namespace moab 00287 00288 #endif