1 #ifndef IMESH_MOAB_HPP
2 #define IMESH_MOAB_HPP
3 
4 #include "iMesh.h"
5 #include "MBiMesh.hpp"
6 #include "moab/Forward.hpp"
7 #include <cstring>
8 #include <cstdlib>
9 #include <cstdio>
10 
11 using namespace moab;
12 
13 /* map from MB's entity type to TSTT's entity topology */
14 extern const iMesh_EntityTopology tstt_topology_table[MBMAXTYPE+1];
15 
16 /* map from MB's entity type to TSTT's entity type */
17 extern const iBase_EntityType tstt_type_table[MBMAXTYPE+1];
18 
19 /* map to MB's entity type from TSTT's entity topology */
20 extern const EntityType mb_topology_table[MBMAXTYPE+1];
21 
22 /* map from TSTT's tag types to MOAB's */
23 extern const DataType mb_data_type_table[iBase_TagValueType_MAX+1];
24 
25 /* map from MOAB's tag types to tstt's */
26 extern const iBase_TagValueType tstt_data_type_table[MB_MAX_DATA_TYPE+1];
27 
28 /* map from MOAB's ErrorCode to tstt's */
29 extern "C" const iBase_ErrorType iBase_ERROR_MAP[MB_FAILURE+1];
30 
31 #include "MBiMesh.hpp"
32 
iMesh_isError(int code)33 static inline bool iMesh_isError(int code)
34   { return (iBase_SUCCESS != code); }
iMesh_isError(ErrorCode code)35 static inline bool iMesh_isError(ErrorCode code)
36   { return (MB_SUCCESS != code); }
37 
38 #define PP_CAT_(a,b) a ## b
39 #define PP_CAT(a,b) PP_CAT_(a,b)
40 
41 #define RETURN(CODE)                                                   \
42   do {                                                                 \
43     *err = MBIMESHI->set_last_error((CODE), "");                       \
44     return;                                                            \
45   } while(false)
46 
47 #define ERROR(CODE,MSG)                                                \
48   do {                                                                 \
49     *err = MBIMESHI->set_last_error((CODE), (MSG));                    \
50     return;                                                            \
51   } while(false)
52 
53 #define CHKERR(CODE,MSG)                                               \
54   do {                                                                 \
55     if (iMesh_isError((CODE)))                                         \
56       ERROR((CODE),(MSG));                                             \
57   } while(false)
58 
59 #define CHKENUM(VAL,TYPE,ERR)                                          \
60   do {                                                                 \
61     if ((VAL) < PP_CAT(TYPE, _MIN) || (VAL) > PP_CAT(TYPE, _MAX))      \
62       ERROR((ERR), "Invalid enumeration value");                       \
63   } while(false)
64 
65 // Ensure that a tag's data type matches the expected data type (entity handle
66 // and entity set handle tags are compatible with one another).
67 #define CHKTAGTYPE(TAG,TYPE)                                           \
68   do {                                                                 \
69     int type, result;                                                  \
70     iMesh_getTagType(instance, (TAG), &type, &result);                 \
71     CHKERR(result, "Couldn't get tag data type");                      \
72     if ((type == iBase_ENTITY_HANDLE &&                                \
73          (TYPE) == iBase_ENTITY_SET_HANDLE) ||                         \
74         (type == iBase_ENTITY_SET_HANDLE &&                            \
75          (TYPE) == iBase_ENTITY_HANDLE))                               \
76       break;                                                           \
77     if (type != (TYPE))                                                \
78       ERROR(iBase_INVALID_TAG_HANDLE, "Invalid tag data type");        \
79   } while(false)
80 
81 #define CHKNONEMPTY()                                                  \
82   do {                                                                 \
83     int count, result;                                                 \
84     iMesh_getNumOfType(instance, 0, iBase_ALL_TYPES, &count, &result); \
85     CHKERR(result, "Couldn't get number of entities");                 \
86     if (count == 0)                                                    \
87       ERROR(iBase_INVALID_ENTITY_HANDLE,                               \
88             "Invalid entity handle: mesh is empty");                   \
89   } while(false)
90 
91 // Check the array size, and allocate the array if necessary.
92 // Free the array upon leaving scope unless KEEP_ARRAY
93 // is invoked.
94 #define ALLOC_CHECK_ARRAY(array, this_size) \
95   iMeshArrayManager array ## _manager ( instance, reinterpret_cast<void**>(array), *(array ## _allocated), *(array ## _size), this_size, sizeof(**array), err ); \
96   if (iBase_SUCCESS != *err) return
97 
98 #define ALLOC_CHECK_TAG_ARRAY(array, this_size) \
99   iMeshArrayManager array ## _manager ( instance, reinterpret_cast<void**>(array), *(array ## _allocated), *(array ## _size), this_size, 1, err ); \
100   if (iBase_SUCCESS != *err) return
101 
102 #define KEEP_ARRAY(array) \
103   array ## _manager .keep_array()
104 
105 // Check the array size, and allocate the array if necessary.
106 // Do NOT free the array upon leaving scope.
107 #define ALLOC_CHECK_ARRAY_NOFAIL(array, this_size) \
108   ALLOC_CHECK_ARRAY(array, this_size); KEEP_ARRAY(array)
109 
110 
111 // Implement RAII pattern for allocated arrays
112 class iMeshArrayManager
113 {
114   void** arrayPtr;
115 
116 public:
117 
118 
iMeshArrayManager(iMesh_Instance instance,void ** array_ptr,int & array_allocated_space,int & array_size,int count,int val_size,int * err)119   iMeshArrayManager( iMesh_Instance instance,
120                      void** array_ptr,
121                      int& array_allocated_space,
122                      int& array_size,
123                      int count,
124                      int val_size,
125                      int* err ) : arrayPtr(0)
126   {
127     if (!array_allocated_space || !*array_ptr) {
128       *array_ptr = std::malloc(val_size * count);
129       array_allocated_space = array_size = count;
130       if (!*array_ptr) {
131         ERROR(iBase_MEMORY_ALLOCATION_FAILED, "Couldn't allocate array.");
132       }
133       arrayPtr = array_ptr;
134     }
135     else {
136       array_size = count;
137       if (array_allocated_space < count) {
138         ERROR(iBase_BAD_ARRAY_SIZE,
139           "Allocated array not large enough to hold returned contents.");
140       }
141     }
142     RETURN(iBase_SUCCESS);
143   }
144 
~iMeshArrayManager()145   ~iMeshArrayManager()
146   {
147     if (arrayPtr) {
148       std::free(*arrayPtr);
149       *arrayPtr = 0;
150     }
151   }
152 
keep_array()153   void keep_array()
154     { arrayPtr = 0; }
155 };
156 
compare_no_case(const char * str1,const char * str2,size_t n)157 inline int compare_no_case(const char *str1, const char *str2, size_t n) {
158    for (size_t i = 1; i != n && *str1 && toupper(*str1) == toupper(*str2);
159         ++i, ++str1, ++str2);
160    return toupper(*str2) - toupper(*str1);
161 }
162 
163 // Filter out non-MOAB options and remove the "moab:" prefix
filter_options(const char * begin,const char * end)164 inline std::string filter_options(const char *begin, const char *end)
165 {
166   const char *opt_begin = begin;
167   const char *opt_end   = begin;
168 
169   std::string filtered;
170   bool first = true;
171 
172   while (opt_end != end) {
173     opt_end = std::find(opt_begin, end, ' ');
174 
175     if (opt_end-opt_begin >= 5 && compare_no_case(opt_begin, "moab:", 5) == 0) {
176       if (!first)
177         filtered.push_back(';');
178       first = false;
179       filtered.append(opt_begin+5, opt_end);
180     }
181 
182     opt_begin = opt_end+1;
183   }
184   return filtered;
185 }
186 
187 #endif // IMESH_MOAB_HPP
188