LCOV - code coverage report
Current view: top level - src - VarLenTag.hpp (source / functions) Hit Total Coverage
Test: coverage_sk.info Lines: 44 46 95.7 %
Date: 2020-12-16 07:07:30 Functions: 10 11 90.9 %
Branches: 14 18 77.8 %

           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

Generated by: LCOV version 1.11