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