1
15
16 #include <memory.h>
17 #include <algorithm>
18
19 #include "VarLenSparseTag.hpp"
20 #include "moab/Range.hpp"
21 #include "TagCompare.hpp"
22 #include "SequenceManager.hpp"
23 #include "moab/Error.hpp"
24 #include "moab/ErrorHandler.hpp"
25 #include "moab/CN.hpp"
26
27 namespace moab
28 {
29
30 VarLenSparseTag::VarLenSparseTag( const char* name, DataType type, const void* default_value, int default_value_bytes )
31 : TagInfo( name, MB_VARIABLE_LENGTH, type, default_value, default_value_bytes )
32 {
33 }
34
35 VarLenSparseTag::~VarLenSparseTag()
36 {
37 release_all_data( 0, 0, true );
38 }
39
40 TagType VarLenSparseTag::get_storage_type() const
41 {
42 return MB_TAG_SPARSE;
43 }
44
45 ErrorCode VarLenSparseTag::release_all_data( SequenceManager*, Error*, bool )
46 {
47 mData.clear();
48 return MB_SUCCESS;
49 }
50
51 ErrorCode VarLenSparseTag::get_data_ptr( Error* ,
52 EntityHandle entity_handle,
53 const void*& ptr,
54 int& length ) const
55 {
56 MapType::const_iterator iter = mData.find( entity_handle );
57
58 if( iter != mData.end() )
59 {
60 ptr = iter->second.data();
61 length = iter->second.size();
62 }
63 else if( get_default_value() )
64 {
65 ptr = get_default_value();
66 length = get_default_value_size();
67 }
68 else
69 return MB_TAG_NOT_FOUND;
70
71 return MB_SUCCESS;
72 }
73
74 ErrorCode VarLenSparseTag::get_data( const SequenceManager*,
75 Error* ,
76 const EntityHandle*,
77 size_t,
78 void* ) const
79 {
80 MB_SET_ERR( MB_VARIABLE_DATA_LENGTH, "No size specified for variable-length tag " << get_name() << " data" );
81 }
82
83 ErrorCode VarLenSparseTag::get_data( const SequenceManager*,
84 Error* ,
85 const Range& ,
86 void* ) const
87 {
88 MB_SET_ERR( MB_VARIABLE_DATA_LENGTH, "No size specified for variable-length tag " << get_name() << " data" );
89 }
90
91 ErrorCode VarLenSparseTag::get_data( const SequenceManager*,
92 Error* ,
93 const EntityHandle* entities,
94 size_t num_entities,
95 const void** pointers,
96 int* lengths ) const
97 {
98 if( !lengths )
99 {
100 MB_SET_ERR( MB_VARIABLE_DATA_LENGTH, "No size specified for variable-length tag " << get_name() << " data" );
101 }
102
103 ErrorCode rval;
104 for( size_t i = 0; i < num_entities; ++i )
105 {
106 rval = get_data_ptr( NULL, entities[i], pointers[i], lengths[i] );
107 if( rval != MB_SUCCESS ) return rval;
108 }
109
110 return MB_SUCCESS;
111 }
112
113 ErrorCode VarLenSparseTag::get_data( const SequenceManager*,
114 Error* ,
115 const Range& entities,
116 const void** pointers,
117 int* lengths ) const
118 {
119 if( !lengths )
120 {
121 MB_SET_ERR( MB_VARIABLE_DATA_LENGTH, "No size specified for variable-length tag " << get_name() << " data" );
122 }
123
124 ErrorCode rval;
125 Range::const_iterator i;
126 for( i = entities.begin(); i != entities.end(); ++i, ++pointers, ++lengths )
127 {
128 rval = get_data_ptr( NULL, *i, *pointers, *lengths );
129 if( rval != MB_SUCCESS ) return rval;
130 }
131
132 return MB_SUCCESS;
133 }
134
135 ErrorCode VarLenSparseTag::set_data( SequenceManager* ,
136 Error* ,
137 const EntityHandle* ,
138 size_t ,
139 const void* )
140 {
141 MB_SET_ERR( MB_VARIABLE_DATA_LENGTH, "No size specified for variable-length tag " << get_name() << " data" );
142 }
143
144 ErrorCode VarLenSparseTag::set_data( SequenceManager* ,
145 Error* ,
146 const Range& ,
147 const void* )
148 {
149 MB_SET_ERR( MB_VARIABLE_DATA_LENGTH, "No size specified for variable-length tag " << get_name() << " data" );
150 }
151
152 ErrorCode VarLenSparseTag::set_data( SequenceManager* seqman,
153 Error* ,
154 const EntityHandle* entities,
155 size_t num_entities,
156 void const* const* pointers,
157 const int* lengths )
158 {
159 ErrorCode rval = validate_lengths( NULL, lengths, num_entities );MB_CHK_ERR( rval );
160
161 rval = seqman->check_valid_entities( NULL, entities, num_entities, true );MB_CHK_ERR( rval );
162
163 for( size_t i = 0; i < num_entities; ++i )
164 {
165 if( lengths[i] )
166 mData[entities[i]].set( pointers[i], lengths[i] );
167 else
168 {
169 MapType::iterator iter = mData.find( entities[i] );
170 if( iter != mData.end() )
171 {
172 iter->second.clear();
173 mData.erase( iter );
174 }
175 }
176 }
177
178 return MB_SUCCESS;
179 }
180
181 ErrorCode VarLenSparseTag::set_data( SequenceManager* seqman,
182 Error* ,
183 const Range& entities,
184 void const* const* pointers,
185 const int* lengths )
186 {
187 ErrorCode rval = validate_lengths( NULL, lengths, entities.size() );MB_CHK_ERR( rval );
188
189 rval = seqman->check_valid_entities( NULL, entities );MB_CHK_ERR( rval );
190
191 Range::const_iterator i;
192 for( i = entities.begin(); i != entities.end(); ++i, ++pointers, ++lengths )
193 {
194 if( *lengths )
195 mData[*i].set( *pointers, *lengths );
196 else
197 {
198 MapType::iterator iter = mData.find( *i );
199 if( iter != mData.end() )
200 {
201 iter->second.clear();
202 mData.erase( iter );
203 }
204 }
205 }
206
207 return MB_SUCCESS;
208 }
209
210 ErrorCode VarLenSparseTag::clear_data( SequenceManager* seqman,
211 Error* ,
212 const EntityHandle* entities,
213 size_t num_entities,
214 const void* value_ptr,
215 int value_len )
216 {
217 if( 0 == value_len )
218 {
219 remove_data( seqman, 0, entities, num_entities );
220 return MB_SUCCESS;
221 }
222
223 ErrorCode rval = validate_lengths( NULL, &value_len, 1 );MB_CHK_ERR( rval );
224
225 rval = seqman->check_valid_entities( NULL, entities, num_entities, true );MB_CHK_ERR( rval );
226
227 for( size_t i = 0; i < num_entities; ++i )
228 mData[entities[i]].set( value_ptr, value_len );
229
230 return MB_SUCCESS;
231 }
232
233 ErrorCode VarLenSparseTag::clear_data( SequenceManager* seqman,
234 Error* ,
235 const Range& entities,
236 const void* value_ptr,
237 int value_len )
238 {
239 if( 0 == value_len )
240 {
241 remove_data( seqman, 0, entities );
242 return MB_SUCCESS;
243 }
244
245 ErrorCode rval = validate_lengths( NULL, &value_len, 1 );MB_CHK_ERR( rval );
246
247 rval = seqman->check_valid_entities( NULL, entities );MB_CHK_ERR( rval );
248
249 Range::const_iterator i;
250 for( i = entities.begin(); i != entities.end(); ++i )
251 mData[*i].set( value_ptr, value_len );
252
253 return MB_SUCCESS;
254 }
255
256 ErrorCode VarLenSparseTag::remove_data( SequenceManager*,
257 Error* ,
258 const EntityHandle* entities,
259 size_t num_entities )
260 {
261 ErrorCode result = MB_SUCCESS;
262 for( size_t i = 0; i < num_entities; ++i )
263 {
264 MapType::iterator p = mData.find( entities[i] );
265 if( p == mData.end() )
266 return MB_TAG_NOT_FOUND;
267 else
268 {
269 p->second.clear();
270 mData.erase( p );
271 }
272 }
273
274 return result;
275 }
276
277 ErrorCode VarLenSparseTag::remove_data( SequenceManager*, Error* , const Range& entities )
278 {
279 ErrorCode result = MB_SUCCESS;
280 for( Range::iterator i = entities.begin(); i != entities.end(); ++i )
281 {
282 MapType::iterator p = mData.find( *i );
283 if( p == mData.end() )
284 return MB_TAG_NOT_FOUND;
285 else
286 {
287 p->second.clear();
288 mData.erase( p );
289 }
290 }
291
292 return result;
293 }
294
295 ErrorCode VarLenSparseTag::tag_iterate( SequenceManager*,
296 Error* ,
297 Range::iterator&,
298 const Range::iterator&,
299 void*&,
300 bool )
301 {
302 MB_SET_ERR( MB_VARIABLE_DATA_LENGTH, "Cannot iterate over variable-length tag data" );
303 }
304
305 template < class Container >
306 static inline void get_tagged( const VarLenSparseTag::MapType& mData, EntityType type, Container& output_range )
307 {
308 VarLenSparseTag::MapType::const_iterator iter;
309 typename Container::iterator hint = output_range.begin();
310 if( MBMAXTYPE == type )
311 {
312 for( iter = mData.begin(); iter != mData.end(); ++iter )
313 hint = output_range.insert( hint, iter->first );
314 }
315 else
316 {
317 #ifdef MOAB_HAVE_UNORDERED_MAP
318 for( iter = mData.begin(); iter != mData.end(); ++iter )
319 if( TYPE_FROM_HANDLE( iter->first ) == type ) hint = output_range.insert( hint, iter->first );
320 #else
321 iter = mData.lower_bound( FIRST_HANDLE( type ) );
322 VarLenSparseTag::MapType::const_iterator end = mData.lower_bound( LAST_HANDLE( type ) + 1 );
323 for( ; iter != end; ++iter )
324 hint = output_range.insert( hint, iter->first );
325 #endif
326 }
327 }
328
329 template < class Container >
330 static inline void get_tagged( const VarLenSparseTag::MapType& mData,
331 Range::const_iterator begin,
332 Range::const_iterator end,
333 Container& output_range )
334 {
335 typename Container::iterator hint = output_range.begin();
336 for( Range::const_iterator i = begin; i != end; ++i )
337 if( mData.find( *i ) != mData.end() ) hint = output_range.insert( hint, *i );
338 }
339
340 template < class Container >
341 static inline void get_tagged( const VarLenSparseTag::MapType& mData,
342 Container& entities,
343 EntityType type,
344 const Range* intersect )
345 {
346 if( !intersect )
347 get_tagged< Container >( mData, type, entities );
348 else if( MBMAXTYPE == type )
349 get_tagged< Container >( mData, intersect->begin(), intersect->end(), entities );
350 else
351 {
352 std::pair< Range::iterator, Range::iterator > r = intersect->equal_range( type );
353 get_tagged< Container >( mData, r.first, r.second, entities );
354 }
355 }
356
357
358 ErrorCode VarLenSparseTag::get_tagged_entities( const SequenceManager*,
359 Range& entities,
360 EntityType type,
361 const Range* intersect ) const
362 {
363 get_tagged( mData, entities, type, intersect );
364 return MB_SUCCESS;
365 }
366
367
368 ErrorCode VarLenSparseTag::num_tagged_entities( const SequenceManager*,
369 size_t& output_count,
370 EntityType type,
371 const Range* intersect ) const
372 {
373 InsertCount counter( output_count );
374 get_tagged( mData, counter, type, intersect );
375 output_count = counter.end();
376 return MB_SUCCESS;
377 }
378
379 ErrorCode VarLenSparseTag::find_entities_with_value(
380 #ifdef MOAB_HAVE_UNORDERED_MAP
381 const SequenceManager* seqman,
382 #else
383 const SequenceManager*,
384 #endif
385 Error*,
386 Range& output_entities,
387 const void* value,
388 int value_bytes,
389 const EntityType type,
390 const Range* intersect_entities ) const
391 {
392 if( value_bytes && value_bytes != get_size() ) return MB_INVALID_SIZE;
393
394 MapType::const_iterator iter, end;
395 #ifdef MOAB_HAVE_UNORDERED_MAP
396 if( intersect_entities )
397 {
398 std::pair< Range::iterator, Range::iterator > r;
399 if( type == MBMAXTYPE )
400 {
401 r.first = intersect_entities->begin();
402 r.second = intersect_entities->end();
403 }
404 else
405 {
406 r = intersect_entities->equal_range( type );
407 }
408
409 find_map_varlen_values_equal( *this, value, get_size(), r.first, r.second, mData, output_entities );
410 }
411 else if( type == MBMAXTYPE )
412 {
413 find_tag_varlen_values_equal( *this, value, get_size(), mData.begin(), mData.end(), output_entities );
414 }
415 else
416 {
417 Range tmp;
418 seqman->get_entities( type, tmp );
419 find_map_varlen_values_equal( *this, value, get_size(), tmp.begin(), tmp.end(), mData, output_entities );
420 }
421 #else
422 if( intersect_entities )
423 {
424 for( Range::const_pair_iterator p = intersect_entities->begin(); p != intersect_entities->end(); ++p )
425 {
426 iter = mData.lower_bound( p->first );
427 end = mData.upper_bound( p->second );
428 find_tag_varlen_values_equal( *this, value, get_size(), iter, end, output_entities );
429 }
430 }
431 else
432 {
433 if( type == MBMAXTYPE )
434 {
435 iter = mData.begin();
436 end = mData.end();
437 }
438 else
439 {
440 iter = mData.lower_bound( CREATE_HANDLE( type, MB_START_ID ) );
441 end = mData.upper_bound( CREATE_HANDLE( type, MB_END_ID ) );
442 }
443 find_tag_varlen_values_equal( *this, value, get_size(), iter, end, output_entities );
444 }
445 #endif
446
447 return MB_SUCCESS;
448 }
449
450 bool VarLenSparseTag::is_tagged( const SequenceManager*, EntityHandle h ) const
451 {
452 return mData.find( h ) != mData.end();
453 }
454
455 ErrorCode VarLenSparseTag::get_memory_use( const SequenceManager*,
456 unsigned long& total,
457 unsigned long& per_entity ) const
458 {
459 total = mData.size() * ( 3 * sizeof( void* ) + sizeof( VarLenTag ) );
460 for( MapType::const_iterator i = mData.begin(); i != mData.end(); ++i )
461 total += i->second.mem();
462 if( !mData.empty() ) per_entity = total / mData.size();
463 total += sizeof( *this ) + TagInfo::get_memory_use();
464
465 return MB_SUCCESS;
466 }
467
468 }