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