Mesh Oriented datABase  (version 5.6.0)
An array-based unstructured mesh library
DenseTag.cpp
Go to the documentation of this file.
1 /** \file DenseTag.cpp
2  * \author Jason Kraftcheck
3  * \date 2010-12-14
4  */
5 
6 #include "DenseTag.hpp"
7 #include "moab/Range.hpp"
8 #include "TagCompare.hpp"
9 #include "SysUtil.hpp"
10 #include "SequenceManager.hpp"
11 #include "SequenceData.hpp"
12 #include "moab/Error.hpp"
13 #include "moab/ErrorHandler.hpp"
14 #include "moab/CN.hpp"
15 #include <utility>
16 
17 namespace moab
18 {
19 
20 inline static ErrorCode not_found( const std::string& /*name*/, EntityHandle /*h*/ )
21 {
22  // MB_TAG_NOT_FOUND could be a non-error condition, do not call MB_SET_ERR on it
23 #if 0
24  if (h)
25  fprintf(stderr, "[Warning]: No dense tag %s value for %s %ld\n",
26  name.c_str(),
28  (unsigned long)ID_FROM_HANDLE(h));
29  else
30  fprintf(stderr, "[Warning]: No dense tag %s value for root set\n", name.c_str());
31 #endif
32 
33  return MB_TAG_NOT_FOUND;
34 }
35 
36 inline static ErrorCode ent_not_found( const std::string& /*name*/, EntityHandle /*h*/ )
37 {
38  // MB_ENTITY_NOT_FOUND could be a non-error condition, do not call MB_SET_ERR on it
39 #if 0
40  fprintf(
41  stderr,
42  "[Warning]: Invalid entity handle setting tag %s: %s %ld\n",
43  name.c_str(),
45  (unsigned long)ID_FROM_HANDLE(h)
46  );
47 #endif
48 
49  return MB_ENTITY_NOT_FOUND;
50 }
51 
52 DenseTag::DenseTag( int index, const char* name, int size, DataType type, const void* default_value )
53  : TagInfo( name, size, type, default_value, size ), mySequenceArray( index ), meshValue( 0 )
54 {
55 }
56 
58 {
59  return MB_TAG_DENSE;
60 }
61 
63  Error* /* error */,
64  const char* name,
65  int bytes,
66  DataType type,
67  const void* default_value )
68 {
69  if( bytes < 1 ) return 0;
70 
71  int index;
72  if( MB_SUCCESS != seqman->reserve_tag_array( NULL, bytes, index ) ) return 0;
73 
74  return new DenseTag( index, name, bytes, type, default_value );
75 }
76 
78 {
79  assert( mySequenceArray < 0 );
80  delete[] meshValue;
81 }
82 
83 ErrorCode DenseTag::release_all_data( SequenceManager* seqman, Error* /* error */, bool delete_pending )
84 {
85  ErrorCode result = seqman->release_tag_array( NULL, mySequenceArray, delete_pending );
86  if( MB_SUCCESS == result && delete_pending ) mySequenceArray = -1;
87  return result;
88 }
89 
91  Error* /* error */,
92  EntityHandle h,
93  const unsigned char* const& ptr,
94  size_t& count ) const
95 {
96  // cast away the const-ness; do we really want to do this?
97  // probably we are not calling this anywhere;
98  // clang compiler found this
99  return get_array_private( seqman, NULL, h, const_cast< const unsigned char*& >( ptr ), count );
100 }
101 
103  Error* /* error */,
104  EntityHandle h,
105  const unsigned char*& ptr,
106  size_t& count ) const
107 {
108  const EntitySequence* seq = 0;
109  ErrorCode rval = seqman->find( h, seq );
110  if( MB_SUCCESS != rval )
111  {
112  if( !h )
113  { // Root set
114  ptr = meshValue;
115  count = 1;
116  return MB_SUCCESS;
117  }
118  else
119  { // Not root set
120  ptr = 0;
121  count = 0;
122  return ent_not_found( get_name(), h );
123  }
124  }
125 
126  const void* mem = seq->data()->get_tag_data( mySequenceArray );
127  ptr = reinterpret_cast< const unsigned char* >( mem );
128  count = seq->data()->end_handle() - h + 1;
129  if( ptr ) ptr += get_size() * ( h - seq->data()->start_handle() );
130 
131  return MB_SUCCESS;
132 }
133 
134 ErrorCode DenseTag::get_array( const EntitySequence* seq, const unsigned char* const& ptr ) const
135 {
136  // cast away the constness; otherwise it would be infinite recursion
137  // probably we are not calling this anywhere
138  return get_array_private( seq, const_cast< const unsigned char*& >( ptr ) );
139 }
140 
141 ErrorCode DenseTag::get_array_private( const EntitySequence* seq, const unsigned char*& ptr ) const
142 {
143  ptr = reinterpret_cast< const unsigned char* >( seq->data()->get_tag_data( mySequenceArray ) );
144  if( ptr ) ptr += get_size() * ( seq->start_handle() - seq->data()->start_handle() );
145 
146  return MB_SUCCESS;
147 }
148 
150  Error* /* error */,
151  EntityHandle h,
152  unsigned char*& ptr,
153  size_t& count,
154  bool allocate )
155 {
156  EntitySequence* seq = 0;
157  ErrorCode rval = seqman->find( h, seq );
158  if( MB_SUCCESS != rval )
159  {
160  if( !h )
161  { // Root set
162  if( !meshValue && allocate ) meshValue = new unsigned char[get_size()];
163  ptr = meshValue;
164  count = 1;
165  return MB_SUCCESS;
166  }
167  else
168  { // Not root set
169  ptr = 0;
170  count = 0;
171  return ent_not_found( get_name(), h );
172  }
173  }
174 
175  void* mem = seq->data()->get_tag_data( mySequenceArray );
176  if( !mem && allocate )
177  {
179  if( !mem )
180  {
181  MB_SET_ERR( MB_MEMORY_ALLOCATION_FAILED, "Memory allocation for dense tag data failed" );
182  }
183 
184  if( !get_default_value() ) memset( mem, 0, get_size() * seq->data()->size() );
185  }
186 
187  ptr = reinterpret_cast< unsigned char* >( mem );
188  count = seq->data()->end_handle() - h + 1;
189  if( ptr ) ptr += get_size() * ( h - seq->data()->start_handle() );
190  return MB_SUCCESS;
191 }
192 
194  Error* /* error */,
195  const EntityHandle* entities,
196  size_t num_entities,
197  void* adata ) const
198 {
199  size_t junk = 0;
200  unsigned char* ptr = reinterpret_cast< unsigned char* >( adata );
201  const EntityHandle* const end = entities + num_entities;
202  for( const EntityHandle* i = entities; i != end; ++i, ptr += get_size() )
203  {
204  const unsigned char* data = 0;
205  MB_CHK_ERR( get_array( seqman, NULL, *i, data, junk ) );
206 
207  if( data )
208  memcpy( ptr, data, get_size() );
209  else if( get_default_value() )
210  memcpy( ptr, get_default_value(), get_size() );
211  else
212  return not_found( get_name(), *i );
213  }
214 
215  return MB_SUCCESS;
216 }
217 
219  Error* /* error */,
220  const Range& entities,
221  void* values ) const
222 {
223  size_t avail = 0;
224  const unsigned char* array = NULL; // Initialize to get rid of warning
225  unsigned char* data = reinterpret_cast< unsigned char* >( values );
226 
227  for( Range::const_pair_iterator p = entities.const_pair_begin(); p != entities.const_pair_end(); ++p )
228  {
229  EntityHandle start = p->first;
230  while( start <= p->second )
231  {
232  MB_CHK_ERR( get_array( seqman, NULL, start, array, avail ) );
233 
234  const size_t count = std::min< size_t >( p->second - start + 1, avail );
235  if( array )
236  memcpy( data, array, get_size() * count );
237  else if( get_default_value() )
238  SysUtil::setmem( data, get_default_value(), get_size(), count );
239  else
240  return not_found( get_name(), start );
241 
242  data += get_size() * count;
243  start += count;
244  }
245  }
246 
247  return MB_SUCCESS;
248 }
249 
251  Error* /* error */,
252  const EntityHandle* entities,
253  size_t num_entities,
254  const void** pointers,
255  int* data_lengths ) const
256 {
257  ErrorCode result;
258  const EntityHandle* const end = entities + num_entities;
259  size_t junk = 0;
260  const unsigned char* ptr = NULL; // Initialize to get rid of warning
261 
262  if( data_lengths )
263  {
264  const int len = get_size();
265  SysUtil::setmem( data_lengths, &len, sizeof( int ), num_entities );
266  }
267 
268  for( const EntityHandle* i = entities; i != end; ++i, ++pointers )
269  {
270  result = get_array( seqman, NULL, *i, ptr, junk );
271  MB_CHK_ERR( result );
272 
273  if( ptr )
274  *pointers = ptr;
275  else if( get_default_value() )
276  *pointers = get_default_value();
277  else
278  return not_found( get_name(), *i );
279  }
280 
281  return MB_SUCCESS;
282 }
283 
285  Error* /* error */,
286  const Range& entities,
287  const void** pointers,
288  int* data_lengths ) const
289 {
290  size_t avail = 0;
291  const unsigned char* array = NULL;
292 
293  if( data_lengths )
294  {
295  int len = get_size();
296  SysUtil::setmem( data_lengths, &len, sizeof( int ), entities.size() );
297  }
298 
299  for( Range::const_pair_iterator p = entities.const_pair_begin(); p != entities.const_pair_end(); ++p )
300  {
301  EntityHandle start = p->first;
302  while( start <= p->second )
303  {
304  MB_CHK_ERR( get_array( seqman, NULL, start, array, avail ) );
305 
306  const size_t count = std::min< size_t >( p->second - start + 1, avail );
307  if( array )
308  {
309  for( EntityHandle end = start + count; start != end; ++start )
310  {
311  *pointers = array;
312  array += get_size();
313  ++pointers;
314  }
315  }
316  else if( const void* val = get_default_value() )
317  {
318  SysUtil::setmem( pointers, &val, sizeof( void* ), count );
319  pointers += count;
320  start += count;
321  }
322  else
323  {
324  return not_found( get_name(), start );
325  }
326  }
327  }
328 
329  return MB_SUCCESS;
330 }
331 
333  Error* /* error */,
334  const EntityHandle* entities,
335  size_t num_entities,
336  const void* data )
337 {
338  const unsigned char* ptr = reinterpret_cast< const unsigned char* >( data );
339  const EntityHandle* const end = entities + num_entities;
340  unsigned char* array = NULL;
341  size_t junk = 0;
342 
343  for( const EntityHandle* i = entities; i != end; ++i, ptr += get_size() )
344  {
345  MB_CHK_ERR( get_array_private( seqman, NULL, *i, array, junk, true ) );
346 
347  memcpy( array, ptr, get_size() );
348  }
349 
350  return MB_SUCCESS;
351 }
352 
353 ErrorCode DenseTag::set_data( SequenceManager* seqman, Error* /* error */, const Range& entities, const void* values )
354 {
355  const char* data = reinterpret_cast< const char* >( values );
356  unsigned char* array = NULL;
357  size_t avail = 0;
358 
359  for( Range::const_pair_iterator p = entities.const_pair_begin(); p != entities.const_pair_end(); ++p )
360  {
361  EntityHandle start = p->first;
362  while( start <= p->second )
363  {
364  MB_CHK_ERR( get_array_private( seqman, NULL, start, array, avail, true ) );
365 
366  const size_t count = std::min< size_t >( p->second - start + 1, avail );
367  memcpy( array, data, get_size() * count );
368  data += get_size() * count;
369  start += count;
370  }
371  }
372 
373  return MB_SUCCESS;
374 }
375 
377  Error* /* error */,
378  const EntityHandle* entities,
379  size_t num_entities,
380  void const* const* pointers,
381  const int* data_lengths )
382 {
383  MB_CHK_ERR( validate_lengths( NULL, data_lengths, num_entities ) );
384 
385  const EntityHandle* const end = entities + num_entities;
386  unsigned char* array = NULL;
387  size_t junk = 0;
388 
389  for( const EntityHandle* i = entities; i != end; ++i, ++pointers )
390  {
391  MB_CHK_ERR( get_array_private( seqman, NULL, *i, array, junk, true ) );
392 
393  memcpy( array, *pointers, get_size() );
394  }
395 
396  return MB_SUCCESS;
397 }
398 
400  Error* /* error */,
401  const Range& entities,
402  void const* const* pointers,
403  const int* /* data_lengths */ )
404 {
405  unsigned char* array = NULL;
406  size_t avail = 0;
407 
408  for( Range::const_pair_iterator p = entities.const_pair_begin(); p != entities.const_pair_end(); ++p )
409  {
410  EntityHandle start = p->first;
411  while( start <= p->second )
412  {
413  MB_CHK_ERR( get_array_private( seqman, NULL, start, array, avail, true ) );
414 
415  const EntityHandle end = std::min< EntityHandle >( p->second + 1, start + avail );
416  while( start != end )
417  {
418  memcpy( array, *pointers, get_size() );
419  ++start;
420  ++pointers;
421  array += get_size();
422  }
423  }
424  }
425 
426  return MB_SUCCESS;
427 }
428 
430  SequenceManager* seqman,
431  Error* /* error */,
432  const EntityHandle* entities,
433  size_t num_entities,
434  const void* value_ptr )
435 {
436  const EntityHandle* const end = entities + num_entities;
437  unsigned char* array = NULL;
438  size_t junk = 0;
439 
440  for( const EntityHandle* i = entities; i != end; ++i )
441  {
442  MB_CHK_ERR( get_array_private( seqman, NULL, *i, array, junk, allocate ) );
443 
444  if( array ) // Array should never be null if allocate == true
445  memcpy( array, value_ptr, get_size() );
446  }
447 
448  return MB_SUCCESS;
449 }
450 
452  SequenceManager* seqman,
453  Error* /* error */,
454  const Range& entities,
455  const void* value_ptr )
456 {
457  unsigned char* array = NULL;
458  size_t avail = 0;
459 
460  for( Range::const_pair_iterator p = entities.const_pair_begin(); p != entities.const_pair_end(); ++p )
461  {
462  EntityHandle start = p->first;
463  while( start <= p->second )
464  {
465  MB_CHK_ERR( get_array_private( seqman, NULL, start, array, avail, allocate ) );
466 
467  const size_t count = std::min< size_t >( p->second - start + 1, avail );
468  if( array ) // Array should never be null if allocate == true
469  SysUtil::setmem( array, value_ptr, get_size(), count );
470  start += count;
471  }
472  }
473 
474  return MB_SUCCESS;
475 }
476 
478  Error* /* error */,
479  const EntityHandle* entities,
480  size_t num_entities,
481  const void* value_ptr,
482  int value_len )
483 {
484  if( value_len && value_len != get_size() ) return MB_INVALID_SIZE;
485 
486  return clear_data( true, seqman, NULL, entities, num_entities, value_ptr );
487 }
488 
490  Error* /* error */,
491  const Range& entities,
492  const void* value_ptr,
493  int value_len )
494 {
495  if( value_len && value_len != get_size() ) return MB_INVALID_SIZE;
496 
497  return clear_data( true, seqman, NULL, entities, value_ptr );
498 }
499 
501  Error* /* error */,
502  const EntityHandle* entities,
503  size_t num_entities )
504 {
505  std::vector< unsigned char > zeros;
506  const void* value = get_default_value();
507  if( !value )
508  {
509  zeros.resize( get_size(), 0 );
510  value = &zeros[0];
511  }
512 
513  return clear_data( false, seqman, NULL, entities, num_entities, value );
514 }
515 
516 ErrorCode DenseTag::remove_data( SequenceManager* seqman, Error* /* error */, const Range& entities )
517 {
518  std::vector< unsigned char > zeros;
519  const void* value = get_default_value();
520  if( !value )
521  {
522  zeros.resize( get_size(), 0 );
523  value = &zeros[0];
524  }
525 
526  return clear_data( false, seqman, NULL, entities, value );
527 }
528 
530  Error* /* error */,
531  Range::iterator& iter,
532  const Range::iterator& end,
533  void*& data_ptr,
534  bool allocate )
535 {
536  // If asked for nothing, successfully return nothing.
537  if( iter == end ) return MB_SUCCESS;
538 
539  unsigned char* array = NULL;
540  size_t avail = 0;
541  MB_CHK_ERR( get_array_private( seqman, NULL, *iter, array, avail, allocate ) );
542  data_ptr = array;
543 
544  size_t count = std::min< size_t >( avail, *( iter.end_of_block() ) - *iter + 1 );
545  if( 0 != *end && *end <= *( iter.end_of_block() ) )
546  iter = end;
547  else
548  iter += count;
549 
550  return MB_SUCCESS;
551 }
552 
554  Range& entities_in,
555  EntityType type,
556  const Range* intersect_list ) const
557 {
558  Range tmp;
559  Range* entities = intersect_list ? &tmp : &entities_in;
560  Range::iterator hint = entities->begin();
561  std::pair< EntityType, EntityType > range = type_range( type );
563  for( EntityType t = range.first; t != range.second; ++t )
564  {
565  const TypeSequenceManager& map = seqman->entity_map( t );
566  for( i = map.begin(); i != map.end(); ++i )
567  if( ( *i )->data()->get_tag_data( mySequenceArray ) )
568  hint = entities->insert( hint, ( *i )->start_handle(), ( *i )->end_handle() );
569  }
570 
571  if( intersect_list ) entities_in = intersect( *entities, *intersect_list );
572 
573  return MB_SUCCESS;
574 }
575 
577  size_t& output_count,
578  EntityType type,
579  const Range* intersect ) const
580 {
581  Range tmp;
582  ErrorCode rval = get_tagged_entities( seqman, tmp, type, intersect );
583  output_count += tmp.size();
584 
585  return rval;
586 }
587 
589  Error* /* error */,
590  Range& output_entities,
591  const void* value,
592  int value_bytes,
593  EntityType type,
594  const Range* intersect_entities ) const
595 {
596  if( value_bytes && value_bytes != get_size() )
597  {
599  "Cannot compare data of size " << value_bytes << " with tag of size " << get_size() );
600  }
601 
602  if( !intersect_entities )
603  {
604  std::pair< EntityType, EntityType > range = type_range( type );
606  for( EntityType t = range.first; t != range.second; ++t )
607  {
608  const TypeSequenceManager& map = seqman->entity_map( t );
609  for( i = map.begin(); i != map.end(); ++i )
610  {
611  const void* data = ( *i )->data()->get_tag_data( mySequenceArray );
612  if( data )
613  {
614  ByteArrayIterator start( ( *i )->data()->start_handle(), data, *this );
615  ByteArrayIterator end( ( *i )->end_handle() + 1, 0, 0 );
616  start += ( *i )->start_handle() - ( *i )->data()->start_handle();
617  find_tag_values_equal( *this, value, get_size(), start, end, output_entities );
618  }
619  }
620  }
621  }
622  else
623  {
624  const unsigned char* array = NULL; // Initialize to get rid of warning
625  size_t count;
626 
627  Range::const_pair_iterator p = intersect_entities->begin();
628  if( type != MBMAXTYPE )
629  {
630  p = intersect_entities->lower_bound( type );
631  assert( TYPE_FROM_HANDLE( p->first ) == type );
632  }
633  for( ;
634  p != intersect_entities->const_pair_end() && ( MBMAXTYPE == type || TYPE_FROM_HANDLE( p->first ) == type );
635  ++p )
636  {
637  EntityHandle start = p->first;
638  while( start <= p->second )
639  {
640  MB_CHK_ERR( get_array( seqman, NULL, start, array, count ) );
641 
642  if( p->second - start < count - 1 ) count = p->second - start + 1;
643 
644  if( array )
645  {
646  ByteArrayIterator istart( start, array, *this );
647  ByteArrayIterator iend( start + count, 0, 0 );
648  find_tag_values_equal( *this, value, get_size(), istart, iend, output_entities );
649  }
650  start += count;
651  }
652  }
653  }
654 
655  return MB_SUCCESS;
656 }
657 
658 bool DenseTag::is_tagged( const SequenceManager* seqman, EntityHandle h ) const
659 {
660  const unsigned char* ptr = NULL; // Initialize to get rid of warning
661  size_t count;
662  return ( MB_SUCCESS == get_array( seqman, 0, h, ptr, count ) ) && ( NULL != ptr );
663 }
664 
666  unsigned long& total,
667  unsigned long& per_entity ) const
668 {
669  per_entity = get_size();
670  total = TagInfo::get_memory_use() + sizeof( *this );
671  for( EntityType t = MBVERTEX; t <= MBENTITYSET; ++t )
672  {
673  const TypeSequenceManager& map = seqman->entity_map( t );
674  const SequenceData* prev_data = 0;
675  for( TypeSequenceManager::const_iterator i = map.begin(); i != map.end(); ++i )
676  {
677  if( ( *i )->data() != prev_data && ( *i )->data()->get_tag_data( mySequenceArray ) )
678  {
679  prev_data = ( *i )->data();
680  total += get_size() * ( *i )->data()->size();
681  }
682  }
683  }
684 
685  return MB_SUCCESS;
686 }
687 
688 } // namespace moab