HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
GA_AttributeDict.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: GA_AttributeDict.h ( GA Library, C++)
7  *
8  * COMMENTS:
9  */
10 
11 #pragma once
12 
13 #ifndef __GA_AttributeDict__
14 #define __GA_AttributeDict__
15 
16 #include "GA_API.h"
17 #include "GA_Attribute.h"
18 #include "GA_AttributeProxy.h"
19 #include "GA_ElementGroup.h"
20 #include "GA_Types.h"
21 
22 #include <UT/UT_Assert.h>
23 #include <UT/UT_OrderedIterator.h>
24 #include <UT/UT_String.h>
25 #include <UT/UT_StringHolder.h>
26 #include <UT/UT_ArrayStringMap.h>
27 
28 #include <SYS/SYS_Types.h>
29 
30 #include <stddef.h>
31 #include <string.h>
32 #include <utility>
33 
34 class GA_AttributeSet;
35 class GA_Group;
36 class UT_MemoryCounter;
37 
38 /// @brief A string map of attributes to ease backward compatibility
39 /// In the GB/GEO/GU library code would often pass around a GB_AttributeDict
40 /// around. The GA library really only requires a string map of attributes
41 /// since the attributes are managed by the GA_AttributeSet.
43 {
44 public:
48 
49  GA_AttributeDict() { myVersionParms = 0; }
51 
52  /// @{
53  /// Get access to the containing attribute set.
54  const GA_AttributeSet &getSet() const { return *mySet; }
55  GA_AttributeSet &getSet() { return *mySet; }
56  /// @}
57 
58  /// Report memory usage
59  int64 getMemoryUsage(bool inclusive) const
60  {
61  int64 mem = inclusive ? sizeof(*this) : 0;
62  mem += myTable.getMemoryUsage(false);
63  for (auto it = myTable.begin(); !it.atEnd(); ++it)
64  mem += it->second->getMemoryUsage(true);
65  mem += myPrivateTable.getMemoryUsage(false);
66  for (auto it = myPrivateTable.begin(); !it.atEnd(); ++it)
67  mem += it->second->getMemoryUsage(true);
68  return mem;
69  }
70 
71  /// Report a cache-count. This is bumped when attributes are
72  /// created/destroyed (and hence renamed)
73  /// Only unique to the GA_Detail that owns it, so combine
74  /// with the GA_Detail::getUniqueId()
75  /// (Name comes from OP_Node::getVersionParms which has a similar
76  /// meaning)
77  exint getVersionParms() const { return myVersionParms; }
78 
79  /// Count memory usage using a UT_MemoryCounter in order to count
80  /// shared memory correctly.
81  /// If inclusive is true, the size of this object is counted,
82  /// else only memory owned by this object is counted.
83  /// If this is pointed to by the calling object, inclusive should be true.
84  /// If this is contained in the calling object, inclusive should be false.
85  /// (Its memory was already counted in the size of the calling object.)
86  void countMemory(UT_MemoryCounter &counter, bool inclusive) const;
87 
88  GA_Attribute *find(GA_AttributeScope scope, const UT_StringRef &name) const;
89  GA_AttributeProxy *findProxy(GA_AttributeScope scope, const UT_StringRef &name) const;
90 
92  void clear()
93  {
94  bumpVersionParms();
95  myTable.clear();
96  myPrivateTable.clear();
97  // Group table is cleared elsewhere.
98  }
99 
101  exint entries() const
102  {
103  return myTable.size() + myPrivateTable.size() + numGroups();
104  }
106  {
107  if (scope == GA_SCOPE_PUBLIC)
108  return myTable.size();
109  if (scope == GA_SCOPE_PRIVATE)
110  return myPrivateTable.size();
111  if (scope == GA_SCOPE_GROUP)
112  return numGroups();
113  return entries();
114  }
115  bool empty() const
116  {
117  return myTable.empty() && myPrivateTable.empty() && (numGroups()==0);
118  }
119  bool empty(GA_AttributeScope scope) const
120  { return entries(scope) == 0; }
121 
123  {
124  public:
126  : myIterator()
127  , myDict(NULL)
128  , myScope(GA_SCOPE_INVALID)
129  , myCurrentScope(GA_SCOPE_INVALID)
130  {}
131 
132  iterator(const iterator &src) { *this = src; }
134 
135  const char *name() const
136  {
137  const GA_Attribute *atr =
138  proxy()->getAttribute();
139  return atr ? atr->getName().c_str() : nullptr;
140  }
142  {
143  if (myCurrentScope != GA_SCOPE_GROUP)
144  {
145  return myIterator->second;
146  }
147  return UTverify_cast<GA_ElementGroup*>(myGroupIterator->second)->getProxy().get();
148  }
150  {
151  return proxy()->getAttribute();
152  }
154  {
155  return attrib();
156  }
157  bool operator==(const iterator &cmp) const
158  {
159  UT_ASSERT_P(myDict == cmp.myDict);
160  UT_ASSERT_P(myScope == cmp.myScope);
161  return myIterator.getCurrent() == cmp.myIterator.getCurrent() || (myIterator.atEnd() && cmp.myIterator.atEnd());
162  }
163  bool operator!=(const iterator &cmp) const
164  {
165  UT_ASSERT_P(myDict == cmp.myDict);
166  UT_ASSERT_P(myScope == cmp.myScope);
167  return myIterator.getCurrent() != cmp.myIterator.getCurrent() && !(myIterator.atEnd() && cmp.myIterator.atEnd());
168  }
169  bool atEnd() const
170  {
171  return myIterator.atEnd();
172  }
174  {
175  UT_ASSERT_P(!myIterator.atEnd());
176  ++myIterator;
177  // NOTE: This makes use of that myIterator and myGroupIterator
178  // will have identical memory layouts.
179  if (myScope == GA_SCOPE_INVALID && myIterator.atEnd())
180  {
181  if (myCurrentScope == GA_SCOPE_PUBLIC)
182  {
183  myIterator = myDict->myPrivateTable.begin();
184  myCurrentScope = GA_SCOPE_PRIVATE;
185  if (!myIterator.atEnd())
186  return *this;
187  }
188  if (myCurrentScope == GA_SCOPE_PRIVATE)
189  {
190  const UT_ArrayStringMap<GA_Group *> *grouptable = myDict->getGroupTable();
191  if (grouptable)
192  {
193  myGroupIterator = grouptable->begin();
194  myCurrentScope = GA_SCOPE_GROUP;
195  }
196  }
197  }
198  return *this;
199  }
201  {
202  myIterator = src.myIterator;
203  myDict = src.myDict;
204  myScope = src.myScope;
205  myCurrentScope = src.myCurrentScope;
206  return *this;
207  }
208  private:
209  iterator(const GA_AttributeDict *dict,
210  GA_AttributeScope scope,
211  bool end)
212  : myDict(dict)
213  , myScope(scope)
214  , myCurrentScope(scope)
215  {
216  if (scope == GA_SCOPE_PUBLIC)
217  {
218  myIterator = end ? dict->myTable.end() : dict->myTable.begin();
219  }
220  else if (scope == GA_SCOPE_INVALID)
221  {
222  if (!end)
223  {
224  myIterator = dict->myTable.begin();
225  if (!myIterator.atEnd())
226  {
227  myCurrentScope = GA_SCOPE_PUBLIC;
228  return;
229  }
230  myIterator = dict->myPrivateTable.begin();
231  if (!myIterator.atEnd())
232  {
233  myCurrentScope = GA_SCOPE_PRIVATE;
234  return;
235  }
236  const UT_ArrayStringMap<GA_Group *> *grouptable = dict->getGroupTable();
237  if (grouptable)
238  {
239  myGroupIterator = grouptable->begin();
240  myCurrentScope = GA_SCOPE_GROUP;
241  }
242  else
243  myCurrentScope = GA_SCOPE_PRIVATE;
244  return;
245  }
246  const UT_ArrayStringMap<GA_Group *> *grouptable = dict->getGroupTable();
247  if (grouptable)
248  {
249  myGroupIterator = grouptable->end();
250  myCurrentScope = GA_SCOPE_GROUP;
251  }
252  else
253  {
254  myIterator = dict->myPrivateTable.end();
255  myCurrentScope = GA_SCOPE_PRIVATE;
256  }
257  }
258  else if (scope == GA_SCOPE_GROUP)
259  {
260  const UT_ArrayStringMap<GA_Group *> *grouptable = dict->getGroupTable();
261  if (grouptable)
262  myGroupIterator = end ? grouptable->end() : grouptable->begin();
263  else
264  myIterator = dict->myPrivateTable.end();
265  }
266  else
267  {
268  UT_ASSERT_P(scope == GA_SCOPE_PRIVATE);
269  myIterator = end ? dict->myPrivateTable.end() : dict->myPrivateTable.begin();
270  }
271  }
272  union {
275  };
276  const GA_AttributeDict *myDict;
277  GA_AttributeScope myScope;
278  GA_AttributeScope myCurrentScope;
279  friend class GA_AttributeDict;
280  };
281 
282  class GA_API Range
283  {
284  public:
286  : myBegin()
287  , myEnd()
288  {
289  }
290 
292  : myBegin(dict.begin(scope))
293  , myEnd(dict.end(scope))
294  {
295  }
296 
299 
300  iterator begin() const { return myBegin; }
301  iterator end() const { return myEnd; }
302 
303  private:
304  iterator myBegin;
305  iterator myEnd;
306  };
307 
309  { return Range(*this, scope); }
310 
311  static int compareAlpha(GA_Attribute *const*a, GA_Attribute *const*b)
312  {
313  const char *aname = (*a)->getName();
314  const char *bname = (*b)->getName();
315  if (!strcmp(aname, "P"))
316  return -1;
317  if (!strcmp(bname, "P"))
318  return 1;
319 
320  // Not case-sensitive
321  return UT_String::compareNumberedString(aname,bname,false);
322  }
323 
324  /// Iterator which traverses attributes in given order
326 
327  /// @{
328  /// Unordered (fastest) iteration
330  { return iterator(this, scope, false); }
332  { return iterator(this, scope, true); }
333  /// @}
334 
335  /// @{
336  /// Ordered iteration. This traverses attributes in a fixed order
338  {
339  iterator it(this, scope, false);
340  return ordered_iterator(it, compareAlpha);
341  }
343  {
344  return ordered_iterator();
345  }
346  /// @}
347 
348  template<typename FUNCTOR>
350  void forEachProxy(FUNCTOR &&functor) const
351  {
352  if (!myTable.empty())
353  myTable.forEachValue(functor);
354  if (!myPrivateTable.empty())
355  myPrivateTable.forEachValue(functor);
356  const UT_ArrayStringMap<GA_Group *> *grouptable = getGroupTable();
357  if (grouptable && !grouptable->empty())
358  {
359  grouptable->forEachValue([&functor](GA_Group *group){
360  functor(UTverify_cast<GA_ElementGroup*>(group)->getProxy().get());
361  });
362  }
363  }
364 
365  template<typename FUNCTOR>
367  void forEachProxy(GA_AttributeScope scope, FUNCTOR &&functor) const
368  {
369  if ((scope == GA_SCOPE_PUBLIC || scope == GA_SCOPE_INVALID) && !myTable.empty())
370  myTable.forEachValue(functor);
371  if ((scope == GA_SCOPE_PRIVATE || scope == GA_SCOPE_INVALID) && !myPrivateTable.empty())
372  myPrivateTable.forEachValue(functor);
373  if (scope == GA_SCOPE_GROUP || scope == GA_SCOPE_INVALID)
374  {
375  const UT_ArrayStringMap<GA_Group *> *grouptable = getGroupTable();
376  if (grouptable && !grouptable->empty())
377  {
378  grouptable->forEachValue([&functor](GA_Group *group){
379  functor(UTverify_cast<GA_ElementGroup*>(group)->getProxy().get());
380  });
381  }
382  }
383  }
384 
385  template<typename FUNCTOR>
387  void forEachAttribute(FUNCTOR &&functor) const
388  {
389  if (!myTable.empty())
390  {
391  myTable.forEachValue([&functor](GA_AttributeProxy *proxy){
392  functor(proxy->getAttribute());
393  });
394  }
395  if (!myPrivateTable.empty())
396  {
397  myPrivateTable.forEachValue([&functor](GA_AttributeProxy *proxy){
398  functor(proxy->getAttribute());
399  });
400  }
401  const UT_ArrayStringMap<GA_Group *> *grouptable = getGroupTable();
402  if (grouptable && !grouptable->empty())
403  {
404  grouptable->forEachValue([&functor](GA_Group *group){
405  functor(UTverify_cast<GA_ElementGroup*>(group));
406  });
407  }
408  }
409 
410  template<typename FUNCTOR>
412  void forEachAttribute(GA_AttributeScope scope, FUNCTOR &&functor) const
413  {
414  if ((scope == GA_SCOPE_PUBLIC || scope == GA_SCOPE_INVALID) && !myTable.empty())
415  {
416  myTable.forEachValue([&functor](GA_AttributeProxy *proxy){
417  functor(proxy->getAttribute());
418  });
419  }
420  if ((scope == GA_SCOPE_PRIVATE || scope == GA_SCOPE_INVALID) && !myPrivateTable.empty())
421  {
422  myPrivateTable.forEachValue([&functor](GA_AttributeProxy *proxy){
423  functor(proxy->getAttribute());
424  });
425  }
426  if (scope == GA_SCOPE_GROUP || scope == GA_SCOPE_INVALID)
427  {
428  const UT_ArrayStringMap<GA_Group *> *grouptable = getGroupTable();
429  if (grouptable && !grouptable->empty())
430  {
431  grouptable->forEachValue([&functor](GA_Group *group){
432  functor(UTverify_cast<GA_ElementGroup*>(group));
433  });
434  }
435  }
436  }
437 
438  template<typename FUNCTOR>
440  void forEachName(GA_AttributeScope scope, FUNCTOR &&functor) const
441  {
442  if ((scope == GA_SCOPE_PUBLIC || scope == GA_SCOPE_INVALID) && !myTable.empty())
443  myTable.forEachKey(functor);
444  if ((scope == GA_SCOPE_PRIVATE || scope == GA_SCOPE_INVALID) && !myPrivateTable.empty())
445  myPrivateTable.forEachKey(functor);
446  if (scope == GA_SCOPE_GROUP || scope == GA_SCOPE_INVALID)
447  {
448  const UT_ArrayStringMap<GA_Group *> *grouptable = getGroupTable();
449  if (grouptable && !grouptable->empty())
450  grouptable->forEachKey(functor);
451  }
452  }
453 
454 
455 private: // Methods
456 
457  /// @private
458  /// Used only by GA_AttributeSet
459  void setNumBuckets(GA_AttributeScope scope, size_t nbuckets)
460  {
461  if (scope == GA_SCOPE_PUBLIC)
462  myTable.setNumBuckets(nbuckets);
463  else if (scope == GA_SCOPE_PRIVATE)
464  myPrivateTable.setNumBuckets(nbuckets);
465  }
466 
467  /// @private
468  /// Used only by GA_AttributeSet
469  void setSet(GA_AttributeSet *s) { mySet = s; }
470  void reserveNewSymbolTableSpace(GA_AttributeScope scope, exint n)
471  {
472  if (scope == GA_SCOPE_PUBLIC)
473  {
474  if (myTable.size()+n > myTable.bucket_count())
475  myTable.rehash(myTable.size()+n);
476  }
477  else if (scope == GA_SCOPE_PRIVATE)
478  {
479  if (myPrivateTable.size()+n > myPrivateTable.bucket_count())
480  myPrivateTable.rehash(myPrivateTable.size()+n);
481  }
482  }
483 
484 
486  void add(GA_AttributeScope scope, const UT_StringHolder &name, GA_AttributeProxy *proxy)
487  {
488  UT_ASSERT_P(proxy != NULL);
489  bumpVersionParms();
490  if (scope == GA_SCOPE_PUBLIC)
491  myTable.insert(std::make_pair(name, proxy));
492  else if (scope == GA_SCOPE_PRIVATE)
493  myPrivateTable.insert(std::make_pair(name, proxy));
494  // NOTE: We don't add the proxy to a table if scope is GA_SCOPE_GROUP,
495  // because it's already in the group table.
496  }
498  void remove(GA_AttributeScope scope, const UT_StringRef &name)
499  {
500  bumpVersionParms();
501  if (scope == GA_SCOPE_PUBLIC)
502  myTable.erase(name);
503  else if (scope == GA_SCOPE_PRIVATE)
504  myPrivateTable.erase(name);
505  // NOTE: We don't remove the proxy from a table if scope is GA_SCOPE_GROUP,
506  // because it's managed by the group table.
507  }
508  friend class GA_AttributeSet; // Only GA_AttributeSet can add/remove
509  friend class GA_GroupTable; // So group table can bump our parms.
510 
512  void bumpVersionParms() { myVersionParms++; }
513 
514  exint numGroups() const;
515  const UT_ArrayStringMap<GA_Group*> *getGroupTable() const;
516 
517 private: // Data
518 
519  MapType myTable;
520  MapType myPrivateTable;
521 
522  GA_AttributeSet *mySet;
523  exint myVersionParms;
524 };
525 
526 #endif
527 
SYS_FORCE_INLINE void forEachAttribute(FUNCTOR &&functor) const
Definition of a geometry attribute.
Definition: GA_Attribute.h:190
const char * name() const
Range(const GA_AttributeDict &dict, GA_AttributeScope scope)
SYS_FORCE_INLINE void forEachAttribute(GA_AttributeScope scope, FUNCTOR &&functor) const
SYS_FORCE_INLINE void forEachName(GA_AttributeScope scope, FUNCTOR &&functor) const
iterator end(GA_AttributeScope scope=GA_SCOPE_INVALID) const
iterator begin(GA_AttributeScope scope=GA_SCOPE_INVALID) const
UT_ArrayStringMap< GA_Group * >::const_iterator myGroupIterator
SYS_FORCE_INLINE void forEachValue(FUNCTOR &&functor) const
Definition: UT_ArrayMap.h:570
iterator begin() const
int64 getMemoryUsage(bool inclusive) const
Report memory usage.
GA_AttributeProxy * proxy() const
UT_ArrayStringMap< GA_Group * > MapType
Definition: GA_GroupTable.h:45
GA_Attribute * attrib() const
exint entries(GA_AttributeScope scope) const
const iterator & operator=(const iterator &src)
GA_AttributeDict::iterator iterator
SYS_FORCE_INLINE void forEachKey(FUNCTOR &&functor) const
Definition: UT_ArrayMap.h:557
GLboolean GLboolean GLboolean GLboolean a
Definition: glcorearb.h:1221
bool empty() const
Returns true iff there are no items in the set.
Definition: UT_ArraySet.h:340
const GA_AttributeSet & getSet() const
exint getVersionParms() const
iterator end()
Returns a non-const end iterator for the set.
Definition: UT_ArraySet.h:667
#define GA_API
Definition: GA_API.h:12
SYS_FORCE_INLINE TO_T UTverify_cast(FROM_T from)
Definition: UT_Assert.h:199
bool empty() const
Standard user attribute level.
Definition: GA_Types.h:127
const UT_StringHolder & getName() const
Definition: GA_Attribute.h:251
MapType::iterator map_iterator
UT_ArrayStringMap< GA_AttributeProxy * > MapType
ordered_iterator obegin(GA_AttributeScope scope=GA_SCOPE_INVALID) const
bool operator==(const iterator &cmp) const
GA_AttributeSet & getSet()
A string map of attributes to ease backward compatibility In the GB/GEO/GU library code would often p...
long long int64
Definition: SYS_Types.h:107
GA_AttributeScope
Definition: GA_Types.h:121
GLdouble n
Definition: glcorearb.h:2007
GA_Attribute * operator*() const
Range range(GA_AttributeScope scope) const
int64 exint
Definition: SYS_Types.h:116
#define UT_ASSERT_P(ZZ)
Definition: UT_Assert.h:125
This class holds a reference to an attribute. Such an indirection level allows an easy way to invalid...
GLuint GLuint end
Definition: glcorearb.h:474
iterator begin()
Returns a non-const iterator for the beginning of the set.
Definition: UT_ArraySet.h:652
#define SYS_FORCE_INLINE
Definition: SYS_Inline.h:45
GA_Attribute * getAttribute()
GA_AttributeDict::iterator const_iterator
Data has no numeric representation.
Definition: GA_Types.h:124
SYS_FORCE_INLINE const char * c_str() const
GLuint const GLchar * name
Definition: glcorearb.h:785
UT_OrderedIterator< GA_Attribute *, iterator > ordered_iterator
Iterator which traverses attributes in given order.
GLboolean GLboolean GLboolean b
Definition: glcorearb.h:1221
SYS_FORCE_INLINE void clear()
int cmp(T a, T b)
Definition: ImathFun.h:119
SYS_FORCE_INLINE void forEachProxy(GA_AttributeScope scope, FUNCTOR &&functor) const
bool empty(GA_AttributeScope scope) const
static int compareNumberedString(const char *s1, const char *s2, bool case_sensitive=true, bool allow_negatives=false)
png_infop png_sPLT_tpp entries
Definition: png.h:2481
ordered_iterator oend(GA_AttributeScope scope=GA_SCOPE_INVALID) const
MapType::const_iterator const_map_iterator
iterator(const iterator &src)
bool operator!=(const iterator &cmp) const
SYS_FORCE_INLINE void forEachProxy(FUNCTOR &&functor) const
static int compareAlpha(GA_Attribute *const *a, GA_Attribute *const *b)
GA_AttributeDict::const_map_iterator myIterator
GLenum src
Definition: glcorearb.h:1792
SYS_FORCE_INLINE exint entries() const