HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
UN_DataIndexMap.h
Go to the documentation of this file.
1 /*
2  * PROPRIETARY INFORMATION. This software is proprietary to
3  * Side Effects Software Inc., and is not to be reproduced,
4  * transmitted, or disclosed in any way without written permission.
5  *
6  * NAME: UN_DataIndexMap.h ( UN Library, C++)
7  *
8  * COMMENTS:
9  * Core functionality for a utility-based node.
10  */
11 
12 #ifndef __UN_DataIndexMap_h__
13 #define __UN_DataIndexMap_h__
14 
15 #include "UN_API.h"
16 #include "UN_Include.h"
17 #include <UT/UT_ArrayMap.h>
18 
19 
20 // ============================================================================
21 /// Maintains a mapping from data ID to data index in the data buffer.
22 
24 {
25 public:
26  /// Constructor.
28 
29  /// Adds a new data entry to the map.
30  /// Returns a pair, where the first component is the data ID that uniquely
31  /// identifies it in the graph, and the second component is the index
32  /// to the data entry in the data buffer arrays.
33  std::pair< UN_DataID, UN_DataIndex > addEntry();
34 
35  /// Adds a new data entry to the map, forcing it to have the given ID.
36  /// If a given ID is already in the map, returns the existing index.
37  std::pair< UN_DataID, UN_DataIndex > findOrAddEntry( UN_DataID data_id );
38 
39  /// Removes the data ID/Index lookup entry from the map.
40  /// Returns true on successs; false if ID was not found in the map.
41  bool removeEntry( UN_DataID data_id );
42 
43  /// Removes all the data IDs entries from the map.
44  /// @param 'reset_next_id' If true, the data ID generator is reset to zero.
45  void removeAllEntries( bool reset_next_id )
46  { clear( reset_next_id ); }
47 
48  /// Clears the map to an empty state, with no map entries.
49  /// @param 'reset_next_id' If true, the data ID generator is reset to zero.
50  /// This may be useful if a graph loads and clears nodes repeatedly,
51  /// but has the danger of anyone holding the previous IDs thinking
52  /// that this data is still valid.
53  /// So use this option with great caution!!!
54  // TODO: FIXME: consider removing the 'reset_next_id' parameter, since
55  // setting it to 'true' defeats the purpose of unique IDs.
56  // It's here because APEX resets IDs, but it does not need to.
57  void clear( bool reset_next_id = false );
58 
59  /// Returns true if the given ID refers to a valid entry in the map.
60  bool isValid( UN_DataID data_id ) const
61  {
62  auto &map = myIndexFromID;
63  return data_id && map.find(data_id) != map.end();
64  }
65 
66  // TODO: FIXME: introduce the concept of identity map, which may be
67  // a very common use case when we don't delete any entries.
68  // Just load and traverse and edit parms, etc.
69  // Have 1:1 flag and just caset ID to Index. When removing entry
70  // mark map as dirty, and rebuild it on subsequent access.
71  /// Returns an index into a data array buffer given the data ID.
73  {
74  // There is no index for an invalid data ID!
75  if( !data_id )
76  return UN_DataIndex();
77 
78  auto it = myIndexFromID.find( data_id );
79  if( it == myIndexFromID.end() )
80  return UN_DataIndex();
81  return it->second;
82  }
83 
84  /// Iterator for traversing valid data IDs in the map.
85  class IDIterator
86  {
87  public:
88  using iterator_category = std::input_iterator_tag;
91  using pointer = value_type*;
93 
94  IDIterator( const UN_DataIndexMap &map, bool end = false )
95  : myIter( end ? map.myIndexFromID.cend()
96  : map.myIndexFromID.cbegin() )
97  {}
98 
100  {
101  ++myIter;
102  return *this;
103  }
104 
106  {
107  auto bkup = *this;
108  ++myIter;
109  return bkup;
110  }
111 
112  bool operator ==( const IDIterator &b ) const
113  { return myIter == b.myIter; }
114 
115  bool operator !=( const IDIterator &b ) const
116  { return myIter != b.myIter; }
117 
119  { return myIter->first; }
120 
121  bool atEnd() const
122  { return myIter.atEnd(); }
123 
124  private:
125  /// Iterator into the map of valid IDs to their buffer indices.
127  };
128 
129  /// Iterator for traversing valid data IDs in the map in an ordered fashion.
131  {
132  public:
133  using iterator_category = std::input_iterator_tag;
136  using pointer = value_type*;
138 
139  OrderedIDIterator( const UN_DataIndexMap &map, bool end = false )
140  : myMap(map)
141  , myCurrentID( end ? map.idSize().exintValue() : 0 )
142  {
143  goPastInvalid();
144  }
145 
147  {
148  ++myCurrentID;
149  goPastInvalid();
150  return *this;
151  }
152 
154  {
155  auto bkup = *this;
156  ++myCurrentID;
157  goPastInvalid();
158  return bkup;
159  }
160 
161  bool operator ==( const OrderedIDIterator &b ) const
162  { return myCurrentID == b.myCurrentID; }
163 
164  bool operator !=( const OrderedIDIterator &b ) const
165  { return myCurrentID != b.myCurrentID; }
166 
168  { return UN_DataID(myCurrentID); }
169 
170  bool atEnd() const
171  { return myCurrentID >= myMap.idSize(); }
172  private:
173  void goPastInvalid()
174  {
175  // In graphs that don't have many deleted nodes, there won't be
176  // many invalid IDs, so scanning past them should be fast.
177  while( !atEnd() && !myMap.isValid(UN_DataID(myCurrentID)) )
178  myCurrentID++;
179  }
180 
181  private:
182  const UN_DataIndexMap & myMap;
183  exint myCurrentID;
184  };
185 
186 
187  /// Returns a range for iterating valid data IDs (order is not defined).
188  /// Best for fast iteration without large memory footprint,
189  /// but yields non-sorted IDs.
191  IDRange idRange() const
192  {
193  return IDRange( IDIterator(*this),
194  IDIterator(*this, true));
195  }
196 
197  /// Returns a range for iterating valid data IDs in an ascending order.
198  /// Best for iterating without large memory footprint, yields sorted IDs,
199  /// but does not perform any explicit sorting (scans past invalid holes by
200  /// checking the validity of IDs) so is only slightly slower than idRange().
203  {
204  return OrderedIDRange(
205  OrderedIDIterator(*this),
206  OrderedIDIterator(*this, true));
207  }
208 
209  /// Returns an array of valid (non-sorted) IDs.
210  /// Builds an array, by quickly traversing the map keys,
211  /// but yields non-sorted IDs.
213  {
214  UT_Array<UN_DataID> ids(myIndexFromID.size());
215  myIndexFromID.forEachKey([&](const UN_DataID &key)
216  {
217  ids.append(key);
218  });
219  return ids;
220  }
221 
222  /// Returns an array of valid IDs sorded in an ascending order.
223  /// Builds an array, but incurs sorting cost, so it's slower than ids().
225  {
226  auto node_ids( ids() );
227  node_ids.sort();
228  return node_ids;
229  }
230 
231 
232  /// Returns the number of valid data itmes in the map.
234  { return UN_DataSize( myIndexFromID.size() ); }
235 
236  /// Returns the upper limit on the valid indices issued by this container.
237  /// Ie, maximum index value plus one.
239  { return dataBufferSize(); }
240 
241  /// Returns the upper limit on the numerical value of the valid data IDs
242  /// issued by this container. Ie, maximum ID plus one.
244  { return UN_DataSize( myNextDataID.exintValue() ); }
245 
246  /// Returns the size of the data buffers that use indexing based
247  /// on this map. The size is calculated as the largest known index
248  /// issued by this map plus one.
250  { return UN_DataSize( myNextDataIndex.value() ); }
251 
252  /// Returns the number of free slots in the data buffer.
253  /// Ie, the buffer consists of data entry slots that are either occupied
254  /// or free, and this menthod returns the free slots count.
256  { return UN_DataSize( myFreeDataIndices.size() ); }
257 
258  /// Returns the number of valid data entries in the data buffer.
259  /// Ie, the buffer consists of data entry slots that are either occupied
260  /// or free, and this menthod returns the occupied slots count.
262  {
263  return UN_DataSize( dataBufferSize().exintValue()
264  - freeDataBufferSize().exintValue() );
265  }
266 
267  /// Merges another index map into this one, creating mappings for
268  /// the data entries to merged/copied from the given source.
269  ///
270  /// If @p combine_id_zero is true, the data for the ID zero is not mapped
271  /// to a brand new data slot, but is combined with existing slot ID of zero.
272  /// Some data containers use ID of zero for a special entry
273  /// that is treated differently than the other ones.
274  /// Notably, the node data container uses ID of zero for the root node,
275  /// and the root node from the src should not become a regular node in dst.
276  /// Instead, src root ID maps to dst root ID and their data is combined.
277  UN_DataMergeInfo merge( const UN_DataIndexMap &src_map,
278  bool combine_id_zero = false );
279 
280 private:
281  /// Helper method to add entries for the merged data.
282  UN_DataIDRemap mergeEntries( const UN_DataIndexMap &src_map,
283  bool combine_id_zero );
284 
285  /// Helper to add an entry to the map.
286  std::pair< UN_DataID, UN_DataIndex > addNewEntry( UN_DataID data_id );
287 
288 private:
289  /// A map from data ID to data index.
291 
292  /// A stack of indices to the free slots in the data buffer.
293  UT_Array< UN_DataIndex > myFreeDataIndices;
294 
295  /// The unique data ID that will be assigned to the next added entry.
296  UN_DataID myNextDataID;
297 
298  /// The data buffer array index that will be used if the buffer needs
299  /// to grow (ie, there is no more free slots in the buffer).
300  UN_DataIndex myNextDataIndex;
301 };
302 
303 
304 #endif
305 
UN_DataSize size() const
Returns the number of valid data itmes in the map.
std::input_iterator_tag iterator_category
UN_DataSize indexSize() const
int64 exint
Definition: SYS_Types.h:125
UNI_ID UN_DataID
Definition: UN_Include.h:254
Iterator for traversing valid data IDs in the map.
IDRange idRange() const
#define UN_API
Definition: UN_API.h:11
void removeAllEntries(bool reset_next_id)
std::input_iterator_tag iterator_category
bool operator==(const BaseDimensions< T > &a, const BaseDimensions< Y > &b)
Definition: Dimensions.h:137
UN_DataSize dataBufferSize() const
UN_DataSize usedDataBufferSize() const
GLuint GLuint end
Definition: glcorearb.h:475
UN_DataSize freeDataBufferSize() const
GLboolean GLboolean GLboolean b
Definition: glcorearb.h:1222
Maintains a mapping from data ID to data index in the data buffer.
Iterator for traversing valid data IDs in the map in an ordered fashion.
OrderedIDRange orderedIDRange() const
OrderedIDIterator(const UN_DataIndexMap &map, bool end=false)
IDIterator(const UN_DataIndexMap &map, bool end=false)
bool isValid(UN_DataID data_id) const
Returns true if the given ID refers to a valid entry in the map.
UN_DataSize idSize() const
UT_Array< UN_DataID > ids() const
OutGridT XformOp bool bool MergePolicy merge
bool operator!=(const BaseDimensions< T > &a, const BaseDimensions< Y > &b)
Definition: Dimensions.h:165
UN_DataIndex indexFromID(UN_DataID data_id) const
Returns an index into a data array buffer given the data ID.
value_type operator*() const
GLuint * ids
Definition: glcorearb.h:652
UT_Array< UN_DataID > sortedIDs() const
Definition: UNI_ID.h:25
typename set_type::const_iterator const_iterator
Definition: UT_ArrayMap.h:106
OrderedIDIterator operator++(int)