1 #include "TagInfo.hpp"
2 #include "moab/Error.hpp"
3 #include "moab/ErrorHandler.hpp"
4 #include <string.h>  /* memcpy */
5 #include <stdlib.h>  /* realloc & free */
6 #include <assert.h>
7 
8 namespace moab {
9 
TagInfo(const char * name,int size,DataType type,const void * default_value,int default_value_size)10 TagInfo::TagInfo(const char* name,
11                  int size,
12                  DataType type,
13                  const void* default_value,
14                  int default_value_size)
15  : mDefaultValue(NULL),
16    mMeshValue(NULL),
17    mDefaultValueSize(default_value_size),
18    mMeshValueSize(0),
19    mDataSize(size),
20    dataType(type)
21 {
22   if (default_value) {
23     mDefaultValue = malloc(mDefaultValueSize);
24     memcpy(mDefaultValue, default_value, mDefaultValueSize);
25   }
26   if (name)
27     mTagName = name;
28 }
29 
~TagInfo()30 TagInfo::~TagInfo()
31 {
32   free(mDefaultValue);
33   mDefaultValue = 0;
34   mDefaultValueSize = 0;
35 }
36 
size_from_data_type(DataType t)37 int TagInfo::size_from_data_type(DataType t)
38 {
39   static const int sizes[] = {1,
40                               sizeof(int),
41                               sizeof(double),
42                               1,
43                               sizeof(EntityHandle),
44                               0 };
45    return sizes[t];
46 }
47 
equals_default_value(const void * data,int size) const48 bool TagInfo::equals_default_value(const void* data, int size) const
49 {
50   if (!get_default_value())
51     return false;
52 
53   if (variable_length() && size != get_default_value_size())
54     return false;
55 
56   if (!variable_length() && size >=0 && size != get_size())
57     return false;
58 
59   if (get_data_type() == MB_TYPE_BIT) {
60     assert(get_size() <= 8 && get_default_value_size() == 1);
61     unsigned char byte1 = *reinterpret_cast<const unsigned char*>(data);
62     unsigned char byte2 = *reinterpret_cast<const unsigned char*>(get_default_value());
63     unsigned char mask = (unsigned char)((1u << get_size()) - 1);
64     return (byte1 & mask) == (byte2 & mask);
65   }
66   else {
67     return !memcmp(data, get_default_value(), get_default_value_size());
68   }
69 }
70 
71 // Check that all lengths are valid multiples of the type size.
72 // Returns true if all lengths are valid, false otherwise.
check_valid_sizes(const int * sizes,int num_sizes) const73 bool TagInfo::check_valid_sizes(const int* sizes, int num_sizes) const
74 {
75   const unsigned size = size_from_data_type(get_data_type());
76   if (1 == size)
77     return true;
78 
79   unsigned sum = 0;
80   for (int i = 0; i < num_sizes; ++i)
81     sum |= ((unsigned)sizes[i]) % size;
82 
83   return (0 == sum);
84 }
85 
validate_lengths(Error *,const int * lengths,size_t num_lengths) const86 ErrorCode TagInfo::validate_lengths(Error* /* error_handler */,
87                                     const int* lengths,
88                                     size_t num_lengths) const
89 {
90   int bits = 0;
91   if (variable_length()) {
92     if (!lengths) {
93       MB_SET_ERR(MB_VARIABLE_DATA_LENGTH, "No size specified for variable-length tag");
94     }
95     const unsigned type_size = size_from_data_type(get_data_type());
96     if (type_size == 1)
97       return MB_SUCCESS;
98     for (size_t i = 0; i < num_lengths; ++i)
99       bits |= lengths[i] % type_size;
100   }
101   else if (lengths) {
102     for (size_t i = 0; i < num_lengths; ++i)
103       bits |= lengths[i] - get_size();
104   }
105   if (0 == bits)
106     return MB_SUCCESS;
107 
108   MB_SET_ERR(MB_INVALID_SIZE, "Tag data with invalid size");
109 }
110 
111 } // namespace moab
112