MOAB: Mesh Oriented datABase  (version 5.4.1)
VarLenTag.hpp
Go to the documentation of this file.
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
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines