1 #ifndef BIT_TAG_HPP 2 #define BIT_TAG_HPP 3 4 #include "TagInfo.hpp" 5 #include "Internals.hpp" 6 #include <algorithm> 7 #include <vector> 8 #include <assert.h> 9 10 namespace moab { 11 12 class BitPage; 13 14 /**\brief data for a single bit tag */ 15 class BitTag : public TagInfo 16 { 17 private: 18 BitTag(const char * name,int size,const void * default_value)19 BitTag( const char* name, 20 int size, 21 const void* default_value ) 22 : TagInfo( name, size, MB_TYPE_BIT, default_value, default_value ? 1 : 0 ) 23 , requestedBitsPerEntity(0) 24 , storedBitsPerEntity(0) 25 , pageShift(0) 26 {} 27 28 public: 29 30 static BitTag* create_tag( const char* name, 31 int size, 32 const void* default_value = 0 ); 33 34 virtual ~BitTag(); 35 36 virtual TagType get_storage_type() const; 37 38 39 /**\brief Remove/clear tag data for all entities 40 * 41 * Remove tag values from entities. 42 * 43 *\param delete_pending If true, then release any global 44 * data associated with the tag in preparation for deleting 45 * the tag itself. 46 * 47 *\Note Invalidates tag if \c tag_delete_pending is true. The only 48 * valid method that can be invoked that is is the destructor. 49 * 50 *\param seqman Pointer to mesh entity database 51 */ 52 virtual ErrorCode release_all_data( SequenceManager* seqman, 53 Error* error_handler, 54 bool delete_pending ); 55 56 57 /**\brief Get tag value for passed entities 58 * 59 * Get tag values for specified entities. 60 * 61 *\Note Will fail for variable-length data. 62 *\param seqman Pointer to mesh entity database 63 *\param entities Entity handles for which to retrieve tag data 64 *\param num_entities Length of \c entities array 65 *\param data Pointer to memory in which to store consecutive tag values, 66 * one for each passed entity. 67 */ 68 virtual 69 ErrorCode get_data( const SequenceManager* seqman, 70 Error* error_handler, 71 const EntityHandle* entities, 72 size_t num_entities, 73 void* data ) const; 74 75 /**\brief Get tag value for passed entities 76 * 77 * Get tag values for specified entities. 78 * 79 *\Note Will fail for variable-length data. 80 *\param seqman Pointer to mesh entity database 81 *\param entities Entity handles for which to retrieve tag data 82 *\param data Pointer to memory in which to store consecutive tag values, 83 * one for each passed entity. 84 */ 85 virtual 86 ErrorCode get_data( const SequenceManager* seqman, 87 Error* error_handler, 88 const Range& entities, 89 void* data ) const; 90 91 /**\brief Get tag value for passed entities 92 * 93 * Get tag values for specified entities. 94 * 95 *\param seqman Pointer to mesh entity database 96 *\param entities Entity handles for which to retrieve tag data 97 *\param num_entities Length of \c entities array 98 *\param data_ptrs Array of pointers to tag values, one pointer 99 * for each passed entity. 100 *\param data_lengths One value for each entity specifying the 101 * length of the tag value for the corresponding 102 * entity. 103 */ 104 virtual 105 ErrorCode get_data( const SequenceManager* seqman, 106 Error* error_handler, 107 const EntityHandle* entities, 108 size_t num_entities, 109 const void** data_ptrs, 110 int* data_lengths ) const ; 111 112 113 /**\brief Get tag value for passed entities 114 * 115 * Get tag values for specified entities. 116 * 117 *\param seqman Pointer to mesh entity database 118 *\param entities Entity handles for which to retrieve tag data 119 *\param data_ptrs Array of pointers to tag values, one pointer 120 * for each passed entity. 121 *\param data_lengths One value for each entity specifying the 122 * length of the tag value for the corresponding 123 * entity. 124 */ 125 virtual 126 ErrorCode get_data( const SequenceManager* seqman, 127 Error* error_handler, 128 const Range& entities, 129 const void** data_ptrs, 130 int* data_lengths ) const; 131 132 /**\brief Set tag value for passed entities 133 * 134 * Store tag data or update stored tag values 135 *\Note Will fail for variable-length data. 136 *\param seqman Pointer to mesh entity database 137 *\param entities Entity handles for which to store tag data 138 *\param num_entities Length of \c entities array 139 *\param data Pointer to memory holding consecutive tag values, 140 * one for each passed entity. 141 */ 142 virtual 143 ErrorCode set_data( SequenceManager* seqman, 144 Error* error_handler, 145 const EntityHandle* entities, 146 size_t num_entities, 147 const void* data ); 148 149 /**\brief Set tag value for passed entities 150 * 151 * Store tag data or update stored tag values 152 *\Note Will fail for variable-length data. 153 *\param seqman Pointer to mesh entity database 154 *\param entities Entity handles for which to store tag data 155 *\param data Pointer to memory holding consecutive tag values, 156 * one for each passed entity. 157 */ 158 virtual 159 ErrorCode set_data( SequenceManager* seqman, 160 Error* error_handler, 161 const Range& entities, 162 const void* data ); 163 164 /**\brief Set tag value for passed entities 165 * 166 * Store tag data or update stored tag values 167 * 168 *\param seqman Pointer to mesh entity database 169 *\param entities Entity handles for which to store tag data 170 *\param num_entities Length of \c entities array 171 *\param data_ptrs Array of pointers to tag values, one pointer 172 * for each passed entity. 173 *\param data_lengths One value for each entity specifying the 174 * length of the tag value for the corresponding 175 * entity. Array is required for variable-length 176 * tags and is ignored for fixed-length tags. 177 */ 178 virtual 179 ErrorCode set_data( SequenceManager* seqman, 180 Error* error_handler, 181 const EntityHandle* entities, 182 size_t num_entities, 183 void const* const* data_ptrs, 184 const int* data_lengths ); 185 186 187 /**\brief Set tag value for passed entities 188 * 189 * Store tag data or update stored tag values 190 * 191 *\param seqman Pointer to mesh entity database 192 *\param entities Entity handles for which to store tag data 193 *\param data_ptrs Array of pointers to tag values, one pointer 194 * for each passed entity. 195 *\param data_lengths One value for each entity specifying the 196 * length of the tag value for the corresponding 197 * entity. Array is required for variable-length 198 * tags and is ignored for fixed-length tags. 199 */ 200 virtual 201 ErrorCode set_data( SequenceManager* seqman, 202 Error* error_handler, 203 const Range& entities, 204 void const* const* data_ptrs, 205 const int* data_lengths ); 206 207 /**\brief Set tag value for passed entities 208 * 209 * Store tag data or update stored tag values. 210 * 211 *\param seqman Pointer to mesh entity database 212 *\param entities Entity handles for which to store tag data 213 *\param num_entities Length of \c entities array 214 *\param value_ptr Pointer to a single tag value which is to be 215 * stored for each of the passed entities. 216 *\param value_len Length of tag value in bytes. Ignored for 217 * fixed-length tags. Required for variable- 218 * length tags. 219 */ 220 virtual 221 ErrorCode clear_data( SequenceManager* seqman, 222 Error* error_handler, 223 const EntityHandle* entities, 224 size_t num_entities, 225 const void* value_ptr, 226 int value_len = 0 ); 227 228 /**\brief Set tag value for passed entities 229 * 230 * Store tag data or update stored tag values. 231 * 232 *\param seqman Pointer to mesh entity database 233 *\param entities Entity handles for which to store tag data 234 *\param value_ptr Pointer to a single tag value which is to be 235 * stored for each of the passed entities. 236 *\param value_len Length of tag value in bytes. Ignored for 237 * fixed-length tags. Required for variable- 238 * length tags. 239 */ 240 virtual 241 ErrorCode clear_data( SequenceManager* seqman, 242 Error* error_handler, 243 const Range& entities, 244 const void* value_ptr, 245 int value_len = 0 ); 246 247 /**\brief Remove/clear tag data for entities 248 * 249 * Remove tag values from entities. 250 * 251 *\param seqman Pointer to mesh entity database 252 *\param entities Entity handles for which to store tag data 253 *\param num_entities Length of \c entities array 254 */ 255 virtual ErrorCode remove_data( SequenceManager* seqman, 256 Error* error_handler, 257 const EntityHandle* entities, 258 size_t num_entities ); 259 260 /**\brief Remove/clear tag data for entities 261 * 262 * Remove tag values from entities. 263 * 264 *\param seqman Pointer to mesh entity database 265 *\param entities Entity handles for which to store tag data 266 */ 267 virtual ErrorCode remove_data( SequenceManager* seqman, 268 Error* error_handler, 269 const Range& entities ); 270 271 /**\brief Access tag data via direct pointer into contiguous blocks 272 * 273 * Iteratively obtain direct access to contiguous blocks of tag 274 * storage. This function cannot be used with bit tags because 275 * of the compressed bit storage. This function cannot be used 276 * with variable length tags because it does not provide a mechanism 277 * to determine the length of the value for each entity. This 278 * function may be used with sparse tags, but if it is used, it 279 * will return data for a single entity at a time. 280 * 281 *\param iter As input, the first entity for which to return 282 * data. As output, one past the last entity for 283 * which data was returned. 284 *\param end One past the last entity for which data is desired 285 *\param data_ptr Output: pointer to tag storage. 286 * 287 *\Note If this function is called for entities for which no tag value 288 * has been set, but for which a default value exists, it will 289 * force the allocation of explicit storage for each such entity 290 * even though MOAB would normally not explicitly store tag values 291 * for such entities. 292 */ 293 virtual 294 ErrorCode tag_iterate( SequenceManager* seqman, 295 Error* error_handler, 296 Range::iterator& iter, 297 const Range::iterator& end, 298 void*& data_ptr, 299 bool allocate = true); 300 301 /**\brief Get all tagged entities 302 * 303 * Get the list of entities for which the a tag value has been set, 304 * or a close approximation if the tag storage scheme cannot 305 * accurately determine exactly which entities have explicit values. 306 * 307 *\param seqman Pointer to entity storage database 308 *\param output_entities Results *appended* to this range 309 *\param type Optional entity type. If specified, search is 310 * limited to entities of specified type. 311 *\param intersect Optional intersect list. If specified, 312 * search is restricted to entities in this list. 313 */ 314 virtual 315 ErrorCode get_tagged_entities( const SequenceManager* seqman, 316 Range& output_entities, 317 EntityType type = MBMAXTYPE, 318 const Range* intersect = 0 ) const; 319 320 /**\brief Count all tagged entities 321 * 322 * Count the entities for which the a tag value has been set, 323 * or a close approximation if the tag storage scheme cannot 324 * accurately determine exactly which entities have explicit values. 325 * 326 *\param seqman Pointer to entity storage database 327 *\param output_count This is *incremented* for each detected entity. 328 *\param type Optional entity type. If specified, search is 329 * limited to entities of specified type. 330 *\param intersect Optional intersect list. If specified, 331 * search is restricted to entities in this list. 332 */ 333 virtual 334 ErrorCode num_tagged_entities( const SequenceManager* seqman, 335 size_t& output_count, 336 EntityType type = MBMAXTYPE, 337 const Range* intersect = 0 ) const; 338 339 /**\brief Get all tagged entities with tag value 340 * 341 * Get the list of entities which have the specified tag value. 342 * 343 *\param seqman Pointer to entity storage database 344 *\param output_entities Results *appended* to this range 345 *\param value Pointer to tag value 346 *\param value_bytes Size of tag value in bytes. 347 *\param type Optional entity type. If specified, search is 348 * limited to entities of specified type. 349 *\param intersect_entities Optional intersect list. If specified, 350 * search is restricted to entities in this list. 351 */ 352 virtual 353 ErrorCode find_entities_with_value( const SequenceManager* seqman, 354 Error* error_handler, 355 Range& output_entities, 356 const void* value, 357 int value_bytes = 0, 358 EntityType type = MBMAXTYPE, 359 const Range* intersect_entities = 0 ) const; 360 361 /**\brief Check if entity is tagged */ 362 virtual bool is_tagged( const SequenceManager*, EntityHandle h ) const; 363 364 /**\brief Get memory use for tag data. 365 * 366 */ 367 ErrorCode get_memory_use( const SequenceManager* seqman, 368 unsigned long& total, 369 unsigned long& per_entity ) const; 370 371 /**\brief Get entities for which an explicit tag of the specified value is stored */ 372 ErrorCode get_entities_with_bits( EntityType type, 373 Range& entities, 374 unsigned char bits ) const; 375 376 /**\brief Get entities for which an explicit tag of the specified value is stored */ 377 ErrorCode get_entities_with_bits( const Range &range, 378 EntityType type, 379 Range& entities, 380 unsigned char bits ) const; 381 382 enum { Ln2PageSize = 12, //!< Constant: log2(PageSize) 383 PageSize = (1u << Ln2PageSize) //!< Constant: Bytes per BitPage (power of 2) 384 }; 385 386 private: 387 388 BitTag( const BitTag& ); 389 BitTag& operator=( const BitTag& ); 390 ErrorCode reserve( unsigned bits ); 391 default_val() const392 inline unsigned char default_val() const { 393 if (get_default_value()) 394 return *reinterpret_cast<const unsigned char*>(get_default_value()); 395 else 396 return 0; 397 } 398 399 std::vector<BitPage*> pageList[MBMAXTYPE]; //!< Array of BitPage instances storing actual data. 400 unsigned int requestedBitsPerEntity; //!< user-requested bits per entity 401 unsigned int storedBitsPerEntity; //!< allocated bits per entity (power of 2) 402 unsigned int pageShift; //!< log2( ents_per_page() ) 403 404 /**\brief Get indices from handle 405 * 406 *\param type Output: entity type 407 *\param page Output: index into pageList[type] 408 *\param offset Output: index into pageList[type][page] 409 */ unpack(EntityHandle h,EntityType & type,size_t & page,int & offset) const410 void unpack( EntityHandle h, EntityType& type, size_t& page, int& offset ) const 411 { 412 type = TYPE_FROM_HANDLE(h); 413 h = ID_FROM_HANDLE(h); 414 page = ((size_t)h) >> pageShift; // h / ents_per_page() 415 offset = h & ((1u<<pageShift)-1u); // h % ends_per_page() 416 } 417 418 /**\brief Get the number of tag values that are stored in each BitPage */ ents_per_page() const419 int ents_per_page() const { return 8*PageSize/storedBitsPerEntity; } 420 421 template <class Container> inline 422 void get_tagged( EntityType type, 423 Container& entities ) const; 424 template <class Container> inline 425 void get_tagged( Range::const_iterator begin, 426 Range::const_iterator end, 427 Container& entities ) const; 428 template <class Container> inline 429 void get_tagged( Container& entities, 430 EntityType type, 431 const Range* intersect ) const; 432 }; 433 434 } // namespace moab 435 436 #endif 437