Mesh Oriented datABase  (version 5.5.0)
An array-based unstructured mesh library
TagCompare.hpp
Go to the documentation of this file.
1 #ifndef TAG_COMPARE_HPP
2 #define TAG_COMPARE_HPP
3 
4 #include "TagInfo.hpp"
5 #include "VarLenTag.hpp"
6 #include <vector>
7 
8 namespace moab
9 {
10 
11 /* OPAQUE FUNCTORS */
12 
13 /** Test fixed-length opaque tags for equality */
15 {
16  private:
17  const void* value;
18  int size;
19 
20  public:
21  TagBytesEqual( const void* v, int s ) : value( v ), size( s ) {}
22  bool operator()( const void* data ) const
23  {
24  return !memcmp( value, data, size );
25  }
26 };
27 /** Test if fixed-length opaque tag values are less than a value */
29 {
30  private:
31  const void* value;
32  int size;
33 
34  public:
35  TagBytesLess( const void* v, int s ) : value( v ), size( s ) {}
36  bool operator()( const void* data ) const
37  {
38  return 0 < memcmp( value, data, size );
39  }
40 };
41 /** Test variable-length opaque tags for equality */
43 {
44  private:
45  const void* value;
46  int size;
47 
48  public:
49  TagVarBytesEqual( const void* v, int s ) : value( v ), size( s ) {}
50  bool operator()( const void* data ) const
51  {
52  const VarLenTag* vdata = reinterpret_cast< const VarLenTag* >( data );
53  return (int)vdata->size() == size && !memcmp( value, vdata->data(), size );
54  }
55  bool operator()( const VarLenTag& vdata ) const
56  {
57  return (int)vdata.size() == size && !memcmp( value, vdata.data(), size );
58  }
59 };
60 /** Test if variable-length opaque tag values are less than a value */
62 {
63  private:
64  const void* value;
65  int size;
66 
67  public:
68  TagVarBytesLess( const void* v, int s ) : value( v ), size( s ) {}
69  bool operator()( const void* data ) const
70  {
71  const VarLenTag* vdata = reinterpret_cast< const VarLenTag* >( data );
72  if( (int)vdata->size() < size )
73  return 0 <= memcmp( vdata->data(), value, vdata->size() );
74  else
75  return 0 < memcmp( vdata->data(), value, size );
76  }
77  bool operator()( const VarLenTag& vdata ) const
78  {
79  if( (int)vdata.size() < size )
80  return 0 <= memcmp( vdata.data(), value, vdata.size() );
81  else
82  return 0 < memcmp( vdata.data(), value, size );
83  }
84 };
85 
86 /* TEMPLATE FUNCTORS */
87 
88 /** Compare fixed-length tags containing a known data type */
89 template < typename T >
91 {
92  private:
93  const T* value;
94  int size;
95 
96  public:
97  TagTypeEqual( const void* v, int s ) : value( reinterpret_cast< const T* >( v ) ), size( s / sizeof( T ) ) {}
98 
99  bool operator()( const void* data ) const
100  {
101  const T* ddata = reinterpret_cast< const T* >( data );
102  for( int i = 0; i < size; ++i )
103  if( value[i] != ddata[i] ) return false;
104  return true;
105  }
106 };
107 
108 /** Compare fixed-length tags containing a known data type */
109 template < typename T >
111 {
112  private:
113  const T* value;
114  int size;
115 
116  public:
117  TagTypeLess( const void* v, int s ) : value( reinterpret_cast< const T* >( v ) ), size( s / sizeof( T ) ) {}
118 
119  bool operator()( const void* data ) const
120  {
121  const T* ddata = reinterpret_cast< const T* >( data );
122  for( int i = 0; i < size; ++i )
123  if( value[i] <= ddata[i] ) return false;
124  return true;
125  }
126 };
127 
128 /** Compare single-value tags containing a known data type
129  * Optimization of TagTypeEqual for 1-value case.
130  */
131 template < typename T >
133 {
134  private:
136  int size;
137 
138  public:
139  TagOneTypeEqual( const void* v ) : value( *reinterpret_cast< const T* >( v ) ), size( 0 ) {}
140 
141  bool operator()( const void* data ) const
142  {
143  const T* ddata = reinterpret_cast< const T* >( data );
144  return *ddata == value;
145  }
146 };
147 
148 /** Compare single-value tags containing a known data type
149  * Optimization of TagTypeLess for 1-value case.
150  */
151 template < typename T >
153 {
154  private:
156  int size;
157 
158  public:
159  TagOneTypeLess( const void* v ) : value( *reinterpret_cast< const T* >( v ) ), size( 0 ) {}
160 
161  bool operator()( const void* data ) const
162  {
163  const T* ddata = reinterpret_cast< const T* >( data );
164  return *ddata < value;
165  }
166 };
167 
168 /** Compare variable-length tags containing a known data type */
169 template < typename T >
171 {
172  private:
173  const T* value;
174  int size;
175 
176  public:
177  TagVarTypeEqual( const void* v, int s ) : value( reinterpret_cast< const T* >( v ) ), size( s / sizeof( T ) ) {}
178 
179  bool operator()( const void* data ) const
180  {
181  const VarLenTag* vdata = reinterpret_cast< const VarLenTag* >( data );
182  if( vdata->size() != size * sizeof( T ) ) return false;
183  const T* ddata = reinterpret_cast< const T* >( vdata->data() );
184  for( int i = 0; i < size; ++i )
185  if( value[i] != ddata[i] ) return false;
186  return true;
187  }
188 
189  bool operator()( const VarLenTag& vdata ) const
190  {
191  if( vdata.size() != size * sizeof( T ) ) return false;
192  const T* ddata = reinterpret_cast< const T* >( vdata.data() );
193  for( int i = 0; i < size; ++i )
194  if( value[i] != ddata[i] ) return false;
195  return true;
196  }
197 };
198 
199 /** Compare variable-length tags containing a known data type */
200 template < typename T >
202 {
203  private:
204  const T* value;
205  int size;
206 
207  public:
208  TagVarTypeLess( const void* v, int s ) : value( reinterpret_cast< const T* >( v ) ), size( s / sizeof( T ) ) {}
209  bool operator()( const void* data ) const
210  {
211  const VarLenTag* vdata = reinterpret_cast< const VarLenTag* >( data );
212  const T* ddata = reinterpret_cast< const T* >( vdata->data() );
213  if( (int)vdata->size() < sizeof( T ) * size )
214  {
215  for( int i = 0; i < vdata->size() / sizeof( T ); ++i )
216  if( value[i] < ddata[i] ) return false;
217  }
218  else
219  {
220  for( int i = 0; i < vdata->size() / sizeof( T ); ++i )
221  if( value[i] <= ddata[i] ) return false;
222  }
223  return true;
224  }
225  bool operator()( const VarLenTag& vdata ) const
226  {
227  const T* ddata = reinterpret_cast< const T* >( vdata.data() );
228  if( (int)vdata.size() < sizeof( T ) * size )
229  {
230  for( int i = 0; i < vdata.size() / sizeof( T ); ++i )
231  if( value[i] < ddata[i] ) return false;
232  }
233  else
234  {
235  for( int i = 0; i < vdata.size() / sizeof( T ); ++i )
236  if( value[i] <= ddata[i] ) return false;
237  }
238  return true;
239  }
240 };
241 
242 /* TYPE FUNCTORS */
243 
250 
257 
264 
265 /* SEARCHING */
266 
267 template < class Functor, class IteratorType >
268 static inline void find_tag_values( Functor compare, IteratorType begin, IteratorType end, Range& results )
269 {
270  Range::iterator insert = results.begin();
271  for( IteratorType i = begin; i != end; ++i )
272  if( compare( i->second ) ) insert = results.insert( insert, i->first );
273 }
274 
275 template < class Functor, class IteratorType >
276 static inline void find_tag_values( Functor compare,
277  IteratorType begin,
278  IteratorType end,
279  std::vector< EntityHandle >& results )
280 {
281  for( IteratorType i = begin; i != end; ++i )
282  if( compare( i->second ) ) results.push_back( i->first );
283 }
284 
285 template < class Functor, class TagMap >
286 static inline void find_map_values( Functor compare,
287  Range::const_iterator lower,
288  Range::const_iterator upper,
289  const TagMap& tag_map,
290  Range& results )
291 {
292  Range::iterator insert = results.begin();
293  for( ; lower != upper; ++lower )
294  {
295  typename TagMap::const_iterator i = tag_map.find( *lower );
296  if( i != tag_map.end() && compare( i->second ) ) insert = results.insert( insert, *lower );
297  }
298 }
299 
300 /** Find all entities for which a tag has a specific value
301  *\param IteratorType : an iterator that has map behavior:
302  * the value of 'first' is the entity handle.
303  * the value of 'second' is a pointer to the tag data.
304  *\param ContainerType : std::vector<EntityHandle> or Range
305  */
306 template < class IteratorType, class ContainerType >
307 static inline void find_tag_values_equal( const TagInfo& tag_info,
308  const void* value,
309  int size,
310  IteratorType begin,
311  IteratorType end,
312  ContainerType& results )
313 {
314  switch( tag_info.get_data_type() )
315  {
316  case MB_TYPE_INTEGER:
317  if( size == sizeof( int ) )
318  find_tag_values< TagOneIntEqual, IteratorType >( TagOneIntEqual( value ), begin, end, results );
319  else
320  find_tag_values< TagIntsEqual, IteratorType >( TagIntsEqual( value, size ), begin, end, results );
321  break;
322 
323  case MB_TYPE_DOUBLE:
324  if( size == sizeof( double ) )
325  find_tag_values< TagOneDoubleEqual, IteratorType >( TagOneDoubleEqual( value ), begin, end, results );
326  else
327  find_tag_values< TagDoublesEqual, IteratorType >( TagDoublesEqual( value, size ), begin, end, results );
328  break;
329 
330  case MB_TYPE_HANDLE:
331  if( size == sizeof( EntityHandle ) )
332  find_tag_values< TagOneHandleEqual, IteratorType >( TagOneHandleEqual( value ), begin, end, results );
333  else
334  find_tag_values< TagHandlesEqual, IteratorType >( TagHandlesEqual( value, size ), begin, end, results );
335  break;
336 
337  default:
338  find_tag_values< TagBytesEqual, IteratorType >( TagBytesEqual( value, size ), begin, end, results );
339  break;
340  }
341 }
342 template < class IteratorType, class ContainerType >
343 static inline void find_tag_varlen_values_equal( const TagInfo& tag_info,
344  const void* value,
345  int size,
346  IteratorType begin,
347  IteratorType end,
348  ContainerType& results )
349 {
350  switch( tag_info.get_data_type() )
351  {
352  case MB_TYPE_INTEGER:
353  find_tag_values< TagVarIntsEqual, IteratorType >( TagVarIntsEqual( value, size ), begin, end, results );
354  break;
355  case MB_TYPE_DOUBLE:
356  find_tag_values< TagVarDoublesEqual, IteratorType >( TagVarDoublesEqual( value, size ), begin, end,
357  results );
358  break;
359  case MB_TYPE_HANDLE:
360  find_tag_values< TagVarHandlesEqual, IteratorType >( TagVarHandlesEqual( value, size ), begin, end,
361  results );
362  break;
363  default:
364  find_tag_values< TagVarBytesEqual, IteratorType >( TagVarBytesEqual( value, size ), begin, end, results );
365  break;
366  }
367 }
368 
369 /** Find all entities for which a tag has a specific value
370  *\param IteratorType : an iterator that has map behavior:
371  * the value of 'first' is the entity handle.
372  * the value of 'second' is a pointer to the tag data.
373  *\param ContainerType : std::vector<EntityHandle> or Range
374  */
375 template < class TagMap >
376 static inline void find_map_values_equal( const TagInfo& tag_info,
377  const void* value,
378  int size,
379  Range::const_iterator begin,
381  const TagMap& tag_map,
382  Range& results )
383 {
384  switch( tag_info.get_data_type() )
385  {
386  case MB_TYPE_INTEGER:
387  if( size == sizeof( int ) )
388  find_map_values< TagOneIntEqual, TagMap >( TagOneIntEqual( value ), begin, end, tag_map, results );
389  else
390  find_map_values< TagIntsEqual, TagMap >( TagIntsEqual( value, size ), begin, end, tag_map, results );
391  break;
392 
393  case MB_TYPE_DOUBLE:
394  if( size == sizeof( double ) )
395  find_map_values< TagOneDoubleEqual, TagMap >( TagOneDoubleEqual( value ), begin, end, tag_map,
396  results );
397  else
398  find_map_values< TagDoublesEqual, TagMap >( TagDoublesEqual( value, size ), begin, end, tag_map,
399  results );
400  break;
401 
402  case MB_TYPE_HANDLE:
403  if( size == sizeof( EntityHandle ) )
404  find_map_values< TagOneHandleEqual, TagMap >( TagOneHandleEqual( value ), begin, end, tag_map,
405  results );
406  else
407  find_map_values< TagHandlesEqual, TagMap >( TagHandlesEqual( value, size ), begin, end, tag_map,
408  results );
409  break;
410 
411  default:
412  find_map_values< TagBytesEqual, TagMap >( TagBytesEqual( value, size ), begin, end, tag_map, results );
413  break;
414  }
415 }
416 template < class TagMap >
417 static inline void find_map_varlen_values_equal( const TagInfo& tag_info,
418  const void* value,
419  int size,
420  Range::const_iterator begin,
422  const TagMap& tag_map,
423  Range& results )
424 {
425  switch( tag_info.get_data_type() )
426  {
427  case MB_TYPE_INTEGER:
428  find_map_values< TagVarIntsEqual, TagMap >( TagVarIntsEqual( value, size ), begin, end, tag_map, results );
429  break;
430  case MB_TYPE_DOUBLE:
431  find_map_values< TagVarDoublesEqual, TagMap >( TagVarDoublesEqual( value, size ), begin, end, tag_map,
432  results );
433  break;
434  case MB_TYPE_HANDLE:
435  find_map_values< TagVarHandlesEqual, TagMap >( TagVarHandlesEqual( value, size ), begin, end, tag_map,
436  results );
437  break;
438  default:
439  find_map_values< TagVarBytesEqual, TagMap >( TagVarBytesEqual( value, size ), begin, end, tag_map,
440  results );
441  break;
442  }
443 }
444 
445 /** Iterator to use in find_tag_values_equal for arrays of data */
447 {
448  public:
449  typedef std::pair< EntityHandle, const char* > data_type;
450 
451  private:
452  size_t step;
454 
455  public:
456  ByteArrayIterator( EntityHandle start_handle, const void* data_array, size_t tag_size )
457  : step( tag_size ), data( start_handle, reinterpret_cast< const char* >( data_array ) )
458 
459  {
460  }
461  ByteArrayIterator( EntityHandle start_handle, const void* data_array, const TagInfo& tag_info )
462  : step( tag_info.get_size() == MB_VARIABLE_LENGTH ? sizeof( VarLenTag ) : tag_info.get_size() ),
463  data( start_handle, reinterpret_cast< const char* >( data_array ) )
464  {
465  }
466  bool operator==( const ByteArrayIterator& other ) const
467  {
468  return data.first == other.data.first;
469  }
470  bool operator!=( const ByteArrayIterator& other ) const
471  {
472  return data.first != other.data.first;
473  }
475  {
476  ++data.first;
477  data.second += step;
478  return *this;
479  }
481  {
482  ByteArrayIterator result( *this );
483  operator++();
484  return result;
485  }
487  {
488  --data.first;
489  data.second -= step;
490  return *this;
491  }
493  {
494  ByteArrayIterator result( *this );
495  operator--();
496  return result;
497  }
499  {
500  data.first += amt;
501  data.second += amt * step;
502  return *this;
503  }
505  {
506  data.first -= amt;
507  data.second -= amt * step;
508  return *this;
509  }
511  {
512  return data.first - other.data.first;
513  }
514  const data_type& operator*() const
515  {
516  return data;
517  }
518  const data_type* operator->() const
519  {
520  return &data;
521  }
522 };
523 
524 static inline std::pair< EntityType, EntityType > type_range( EntityType type )
525 {
526  if( type == MBMAXTYPE )
527  return std::pair< EntityType, EntityType >( MBVERTEX, MBMAXTYPE );
528  else
529  {
530  EntityType next = type;
531  ++next;
532  return std::pair< EntityType, EntityType >( type, next );
533  }
534 }
535 
536 /** Dummy container that counts insertions rather than maintaining a list of entities */
538 {
539  private:
540  size_t mCount;
541 
542  public:
543  InsertCount( size_t initial_count = 0 ) : mCount( initial_count ) {}
544 
545  typedef int iterator;
546  iterator begin() const
547  {
548  return 0;
549  }
550  iterator end() const
551  {
552  return mCount;
553  }
555  {
556  mCount += last - first + 1;
557  return end();
558  }
559  iterator insert( iterator /* hint */, EntityHandle /* value */ )
560  {
561  ++mCount;
562  return end();
563  }
564 };
565 
566 } // namespace moab
567 
568 #endif