![]() |
Mesh Oriented datABase
(version 5.4.1)
Array-based unstructured mesh datastructure
|
00001 #ifndef VAR_LEN_TAG_HPP
00002 #define VAR_LEN_TAG_HPP
00003
00004 #include
00005 #include
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