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.
55  const GA_AttributeSet &getSet() const { return *mySet; }
57  GA_AttributeSet &getSet() { return *mySet; }
58  /// @}
59 
60  /// Report memory usage
61  int64 getMemoryUsage(bool inclusive) const
62  {
63  int64 mem = inclusive ? sizeof(*this) : 0;
64  mem += myTable.getMemoryUsage(false);
65  for (auto it = myTable.begin(); !it.atEnd(); ++it)
66  mem += it->second->getMemoryUsage(true);
67  mem += myPrivateTable.getMemoryUsage(false);
68  for (auto it = myPrivateTable.begin(); !it.atEnd(); ++it)
69  mem += it->second->getMemoryUsage(true);
70  return mem;
71  }
73  {
74  int64 mem = 0;
75  for (auto it = myTable.begin(); !it.atEnd(); ++it)
76  mem += it->second->getDeviceMemoryUsage();
77  for (auto it = myPrivateTable.begin(); !it.atEnd(); ++it)
78  mem += it->second->getDeviceMemoryUsage();
79  return mem;
80  }
81 
82  /// Report a cache-count. This is bumped when attributes are
83  /// created/destroyed (and hence renamed)
84  /// Only unique to the GA_Detail that owns it, so combine
85  /// with the GA_Detail::getUniqueId()
86  /// (Name comes from OP_Node::getVersionParms which has a similar
87  /// meaning)
88  exint getVersionParms() const { return myVersionParms; }
89 
90  /// Count memory usage using a UT_MemoryCounter in order to count
91  /// shared memory correctly.
92  /// If inclusive is true, the size of this object is counted,
93  /// else only memory owned by this object is counted.
94  /// If this is pointed to by the calling object, inclusive should be true.
95  /// If this is contained in the calling object, inclusive should be false.
96  /// (Its memory was already counted in the size of the calling object.)
97  void countMemory(UT_MemoryCounter &counter, bool inclusive) const;
98 
99  GA_Attribute *find(GA_AttributeScope scope, const UT_StringRef &name) const;
100  GA_AttributeProxy *findProxy(GA_AttributeScope scope, const UT_StringRef &name) const;
101 
103  void clear()
104  {
105  bumpVersionParms();
106  myTable.clear();
107  myPrivateTable.clear();
108  // Group table is cleared elsewhere.
109  }
110 
112  exint entries() const
113  {
114  return myTable.size() + myPrivateTable.size() + numGroups();
115  }
118  {
119  if (scope == GA_SCOPE_PUBLIC)
120  return myTable.size();
121  if (scope == GA_SCOPE_PRIVATE)
122  return myPrivateTable.size();
123  if (scope == GA_SCOPE_GROUP)
124  return numGroups();
125  return entries();
126  }
128  bool empty() const
129  {
130  return myTable.empty() && myPrivateTable.empty() && (numGroups()==0);
131  }
133  bool empty(GA_AttributeScope scope) const
134  { return entries(scope) == 0; }
135 
137  {
138  public:
141  : myIterator()
142  , myDict(NULL)
143  , myScope(GA_SCOPE_INVALID)
144  , myCurrentScope(GA_SCOPE_INVALID)
145  {}
146 
148  iterator(const iterator &src) { *this = src; }
151 
153  const char *name() const
154  {
155  const GA_Attribute *atr =
156  proxy()->getAttribute();
157  return atr ? atr->getName().c_str() : nullptr;
158  }
161  {
162  if (myCurrentScope != GA_SCOPE_GROUP)
163  {
164  return myIterator->second;
165  }
166  return UTverify_cast<GA_ElementGroup*>(myGroupIterator->second)->getProxy().get();
167  }
170  {
171  return proxy()->getAttribute();
172  }
175  {
176  return attrib();
177  }
179  bool operator==(const iterator &cmp) const
180  {
181  UT_ASSERT_P(myDict == cmp.myDict);
182  UT_ASSERT_P(myScope == cmp.myScope);
183  return myIterator.getCurrent() == cmp.myIterator.getCurrent() || (myIterator.atEnd() && cmp.myIterator.atEnd());
184  }
186  bool operator!=(const iterator &cmp) const
187  {
188  UT_ASSERT_P(myDict == cmp.myDict);
189  UT_ASSERT_P(myScope == cmp.myScope);
190  return myIterator.getCurrent() != cmp.myIterator.getCurrent() && !(myIterator.atEnd() && cmp.myIterator.atEnd());
191  }
193  bool atEnd() const
194  {
195  return myIterator.atEnd();
196  }
197 
200  {
201  UT_ASSERT_P(!myIterator.atEnd());
202  ++myIterator;
203  // NOTE: This makes use of that myIterator and myGroupIterator
204  // will have identical memory layouts.
205  if (myScope == GA_SCOPE_INVALID && myIterator.atEnd())
206  {
207  if (myCurrentScope == GA_SCOPE_PUBLIC)
208  {
209  myIterator = myDict->myPrivateTable.begin();
210  myCurrentScope = GA_SCOPE_PRIVATE;
211  if (!myIterator.atEnd())
212  return *this;
213  }
214  if (myCurrentScope == GA_SCOPE_PRIVATE)
215  {
216  const UT_ArrayStringMap<GA_Group *> *grouptable = myDict->getGroupTable();
217  if (grouptable)
218  {
219  myGroupIterator = grouptable->begin();
220  myCurrentScope = GA_SCOPE_GROUP;
221  }
222  }
223  }
224  return *this;
225  }
226 
229  {
230  myIterator = src.myIterator;
231  myDict = src.myDict;
232  myScope = src.myScope;
233  myCurrentScope = src.myCurrentScope;
234  return *this;
235  }
236  private:
238  iterator(const GA_AttributeDict *dict,
239  GA_AttributeScope scope,
240  bool end)
241  : myDict(dict)
242  , myScope(scope)
243  , myCurrentScope(scope)
244  {
245  if (scope == GA_SCOPE_PUBLIC)
246  {
247  myIterator = end ? dict->myTable.end() : dict->myTable.begin();
248  }
249  else if (scope == GA_SCOPE_INVALID)
250  {
251  if (!end)
252  {
253  myIterator = dict->myTable.begin();
254  if (!myIterator.atEnd())
255  {
256  myCurrentScope = GA_SCOPE_PUBLIC;
257  return;
258  }
259  myIterator = dict->myPrivateTable.begin();
260  if (!myIterator.atEnd())
261  {
262  myCurrentScope = GA_SCOPE_PRIVATE;
263  return;
264  }
265  const UT_ArrayStringMap<GA_Group *> *grouptable = dict->getGroupTable();
266  if (grouptable)
267  {
268  myGroupIterator = grouptable->begin();
269  myCurrentScope = GA_SCOPE_GROUP;
270  }
271  else
272  myCurrentScope = GA_SCOPE_PRIVATE;
273  return;
274  }
275  const UT_ArrayStringMap<GA_Group *> *grouptable = dict->getGroupTable();
276  if (grouptable)
277  {
278  myGroupIterator = grouptable->end();
279  myCurrentScope = GA_SCOPE_GROUP;
280  }
281  else
282  {
283  myIterator = dict->myPrivateTable.end();
284  myCurrentScope = GA_SCOPE_PRIVATE;
285  }
286  }
287  else if (scope == GA_SCOPE_GROUP)
288  {
289  const UT_ArrayStringMap<GA_Group *> *grouptable = dict->getGroupTable();
290  if (grouptable)
291  myGroupIterator = end ? grouptable->end() : grouptable->begin();
292  else
293  myIterator = dict->myPrivateTable.end();
294  }
295  else
296  {
297  UT_ASSERT_P(scope == GA_SCOPE_PRIVATE);
298  myIterator = end ? dict->myPrivateTable.end() : dict->myPrivateTable.begin();
299  }
300  }
301  union {
304  };
305  const GA_AttributeDict *myDict;
306  GA_AttributeScope myScope;
307  GA_AttributeScope myCurrentScope;
308  friend class GA_AttributeDict;
309  };
310 
311  class GA_API Range
312  {
313  public:
315  : myBegin()
316  , myEnd()
317  {
318  }
319 
321  : myBegin(dict.begin(scope))
322  , myEnd(dict.end(scope))
323  {
324  }
325 
328 
329  SYS_FORCE_INLINE iterator begin() const { return myBegin; }
330  SYS_FORCE_INLINE iterator end() const { return myEnd; }
331 
332  private:
333  iterator myBegin;
334  iterator myEnd;
335  };
336 
339  { return Range(*this, scope); }
340 
341  static int compareAlpha(GA_Attribute *const*a, GA_Attribute *const*b)
342  {
343  const char *aname = (*a)->getName();
344  const char *bname = (*b)->getName();
345  if (!strcmp(aname, "P"))
346  return -1;
347  if (!strcmp(bname, "P"))
348  return 1;
349 
350  // Not case-sensitive
351  return UT_String::compareNumberedString(aname,bname,false);
352  }
353 
354  /// Iterator which traverses attributes in given order
356 
357  /// @{
358  /// Unordered (fastest) iteration
360  iterator begin(GA_AttributeScope scope = GA_SCOPE_INVALID) const
361  { return iterator(this, scope, false); }
363  iterator end(GA_AttributeScope scope = GA_SCOPE_INVALID) const
364  { return iterator(this, scope, true); }
365  /// @}
366 
367  /// @{
368  /// Ordered iteration. This traverses attributes in a fixed order
371  {
372  iterator it(this, scope, false);
373  return ordered_iterator(it, compareAlpha);
374  }
377  {
378  return ordered_iterator();
379  }
380  /// @}
381 
382  template<typename FUNCTOR>
384  void forEachProxy(FUNCTOR &&functor) const
385  {
386  if (!myTable.empty())
387  myTable.forEachValue(functor);
388  if (!myPrivateTable.empty())
389  myPrivateTable.forEachValue(functor);
390  const UT_ArrayStringMap<GA_Group *> *grouptable = getGroupTable();
391  if (grouptable && !grouptable->empty())
392  {
393  grouptable->forEachValue([&functor](GA_Group *group){
394  functor(UTverify_cast<GA_ElementGroup*>(group)->getProxy().get());
395  });
396  }
397  }
398 
399  template<typename FUNCTOR>
401  void forEachProxy(GA_AttributeScope scope, FUNCTOR &&functor) const
402  {
403  if ((scope == GA_SCOPE_PUBLIC || scope == GA_SCOPE_INVALID) && !myTable.empty())
404  myTable.forEachValue(functor);
405  if ((scope == GA_SCOPE_PRIVATE || scope == GA_SCOPE_INVALID) && !myPrivateTable.empty())
406  myPrivateTable.forEachValue(functor);
407  if (scope == GA_SCOPE_GROUP || scope == GA_SCOPE_INVALID)
408  {
409  const UT_ArrayStringMap<GA_Group *> *grouptable = getGroupTable();
410  if (grouptable && !grouptable->empty())
411  {
412  grouptable->forEachValue([&functor](GA_Group *group){
413  functor(UTverify_cast<GA_ElementGroup*>(group)->getProxy().get());
414  });
415  }
416  }
417  }
418 
419  template<typename FUNCTOR>
421  void forEachAttribute(FUNCTOR &&functor) const
422  {
423  if (!myTable.empty())
424  {
425  myTable.forEachValue([&functor](GA_AttributeProxy *proxy){
426  functor(proxy->getAttribute());
427  });
428  }
429  if (!myPrivateTable.empty())
430  {
431  myPrivateTable.forEachValue([&functor](GA_AttributeProxy *proxy){
432  functor(proxy->getAttribute());
433  });
434  }
435  const UT_ArrayStringMap<GA_Group *> *grouptable = getGroupTable();
436  if (grouptable && !grouptable->empty())
437  {
438  grouptable->forEachValue([&functor](GA_Group *group){
439  functor(UTverify_cast<GA_ElementGroup*>(group));
440  });
441  }
442  }
443 
444  template<typename FUNCTOR>
446  void forEachAttribute(GA_AttributeScope scope, FUNCTOR &&functor) const
447  {
448  if ((scope == GA_SCOPE_PUBLIC || scope == GA_SCOPE_INVALID) && !myTable.empty())
449  {
450  myTable.forEachValue([&functor](GA_AttributeProxy *proxy){
451  functor(proxy->getAttribute());
452  });
453  }
454  if ((scope == GA_SCOPE_PRIVATE || scope == GA_SCOPE_INVALID) && !myPrivateTable.empty())
455  {
456  myPrivateTable.forEachValue([&functor](GA_AttributeProxy *proxy){
457  functor(proxy->getAttribute());
458  });
459  }
460  if (scope == GA_SCOPE_GROUP || scope == GA_SCOPE_INVALID)
461  {
462  const UT_ArrayStringMap<GA_Group *> *grouptable = getGroupTable();
463  if (grouptable && !grouptable->empty())
464  {
465  grouptable->forEachValue([&functor](GA_Group *group){
466  functor(UTverify_cast<GA_ElementGroup*>(group));
467  });
468  }
469  }
470  }
471 
472  template<typename FUNCTOR>
474  void forEachName(GA_AttributeScope scope, FUNCTOR &&functor) const
475  {
476  if ((scope == GA_SCOPE_PUBLIC || scope == GA_SCOPE_INVALID) && !myTable.empty())
477  myTable.forEachKey(functor);
478  if ((scope == GA_SCOPE_PRIVATE || scope == GA_SCOPE_INVALID) && !myPrivateTable.empty())
479  myPrivateTable.forEachKey(functor);
480  if (scope == GA_SCOPE_GROUP || scope == GA_SCOPE_INVALID)
481  {
482  const UT_ArrayStringMap<GA_Group *> *grouptable = getGroupTable();
483  if (grouptable && !grouptable->empty())
484  grouptable->forEachKey(functor);
485  }
486  }
487 
488 
489 private: // Methods
490 
491  /// @private
492  /// Used only by GA_AttributeSet
494  void setNumBuckets(GA_AttributeScope scope, size_t nbuckets)
495  {
496  if (scope == GA_SCOPE_PUBLIC)
497  myTable.setNumBuckets(nbuckets);
498  else if (scope == GA_SCOPE_PRIVATE)
499  myPrivateTable.setNumBuckets(nbuckets);
500  }
501 
502  /// @private
503  /// Used only by GA_AttributeSet
505  void setSet(GA_AttributeSet *s) { mySet = s; }
506 
508  void reserveNewSymbolTableSpace(GA_AttributeScope scope, exint n)
509  {
510  if (scope == GA_SCOPE_PUBLIC)
511  {
512  if (myTable.size()+n > myTable.bucket_count())
513  myTable.rehash(myTable.size()+n);
514  }
515  else if (scope == GA_SCOPE_PRIVATE)
516  {
517  if (myPrivateTable.size()+n > myPrivateTable.bucket_count())
518  myPrivateTable.rehash(myPrivateTable.size()+n);
519  }
520  }
521 
522 
524  void add(GA_AttributeScope scope, const UT_StringHolder &name, GA_AttributeProxy *proxy)
525  {
526  UT_ASSERT_P(proxy != NULL);
527  bumpVersionParms();
528  if (scope == GA_SCOPE_PUBLIC)
529  myTable.insert(std::make_pair(name, proxy));
530  else if (scope == GA_SCOPE_PRIVATE)
531  myPrivateTable.insert(std::make_pair(name, proxy));
532  // NOTE: We don't add the proxy to a table if scope is GA_SCOPE_GROUP,
533  // because it's already in the group table.
534  }
536  void remove(GA_AttributeScope scope, const UT_StringRef &name)
537  {
538  bumpVersionParms();
539  if (scope == GA_SCOPE_PUBLIC)
540  myTable.erase(name);
541  else if (scope == GA_SCOPE_PRIVATE)
542  myPrivateTable.erase(name);
543  // NOTE: We don't remove the proxy from a table if scope is GA_SCOPE_GROUP,
544  // because it's managed by the group table.
545  }
546  friend class GA_AttributeSet; // Only GA_AttributeSet can add/remove
547  friend class GA_GroupTable; // So group table can bump our parms.
548 
550  void bumpVersionParms() { myVersionParms++; }
551 
552  SYS_FORCE_INLINE exint numGroups() const
553  {
554  auto table = getGroupTable();
555  return table ? table->size() : 0;
556  }
557 
558  const UT_ArrayStringMap<GA_Group*> *getGroupTable() const;
559 
560 private: // Data
561 
562  MapType myTable;
563  MapType myPrivateTable;
564 
565  GA_AttributeSet *mySet;
566  exint myVersionParms;
567 };
568 
569 #endif
570 
SYS_FORCE_INLINE GA_AttributeProxy * proxy() const
SYS_FORCE_INLINE void forEachAttribute(FUNCTOR &&functor) const
Definition of a geometry attribute.
Definition: GA_Attribute.h:198
SYS_FORCE_INLINE void forEachAttribute(GA_AttributeScope scope, FUNCTOR &&functor) const
SYS_FORCE_INLINE void forEachName(GA_AttributeScope scope, FUNCTOR &&functor) const
SYS_FORCE_INLINE const iterator & operator=(const iterator &src)
SYS_FORCE_INLINE const char * name() const
SYS_FORCE_INLINE GA_Attribute * getAttribute()
UT_ArrayStringMap< GA_Group * >::const_iterator myGroupIterator
SYS_FORCE_INLINE void forEachValue(FUNCTOR &&functor) const
Definition: UT_ArrayMap.h:604
int64 getMemoryUsage(bool inclusive) const
Report memory usage.
SYS_FORCE_INLINE ordered_iterator obegin(GA_AttributeScope scope=GA_SCOPE_INVALID) const
SYS_FORCE_INLINE bool atEnd() const
SYS_FORCE_INLINE iterator begin() const
SYS_FORCE_INLINE exint entries(GA_AttributeScope scope) const
UT_ArrayStringMap< GA_Group * > MapType
Definition: GA_GroupTable.h:46
int64 exint
Definition: SYS_Types.h:125
GA_AttributeDict::iterator iterator
SYS_FORCE_INLINE void forEachKey(FUNCTOR &&functor) const
Definition: UT_ArrayMap.h:591
GLboolean GLboolean GLboolean GLboolean a
Definition: glcorearb.h:1222
GLdouble s
Definition: glad.h:3009
bool empty() const
Returns true iff there are no items in the set.
Definition: UT_ArraySet.h:409
SYS_FORCE_INLINE GA_Attribute * attrib() const
exint getVersionParms() const
iterator end()
Returns a non-const end iterator for the set.
Definition: UT_ArraySet.h:736
#define GA_API
Definition: GA_API.h:14
SYS_FORCE_INLINE TO_T UTverify_cast(FROM_T from)
Definition: UT_Assert.h:229
SYS_FORCE_INLINE bool operator!=(const iterator &cmp) const
Standard user attribute level.
Definition: GA_Types.h:149
FMT_CONSTEXPR auto find(Ptr first, Ptr last, T value, Ptr &out) -> bool
Definition: core.h:2138
MapType::iterator map_iterator
UT_ArrayStringMap< GA_AttributeProxy * > MapType
SYS_FORCE_INLINE iterator begin(GA_AttributeScope scope=GA_SCOPE_INVALID) const
IMATH_HOSTDEVICE constexpr int cmp(T a, T b) IMATH_NOEXCEPT
Definition: ImathFun.h:84
SYS_FORCE_INLINE const UT_StringHolder & getName() const
Definition: GA_Attribute.h:283
A string map of attributes to ease backward compatibility In the GB/GEO/GU library code would often p...
GA_AttributeScope
Definition: GA_Types.h:143
GLdouble n
Definition: glcorearb.h:2008
SYS_FORCE_INLINE GA_AttributeSet & getSet()
#define UT_ASSERT_P(ZZ)
Definition: UT_Assert.h:155
This class holds a reference to an attribute. Such an indirection level allows an easy way to invalid...
SYS_FORCE_INLINE Range(const GA_AttributeDict &dict, GA_AttributeScope scope)
GLuint GLuint end
Definition: glcorearb.h:475
iterator begin()
Returns a non-const iterator for the beginning of the set.
Definition: UT_ArraySet.h:721
#define SYS_FORCE_INLINE
Definition: SYS_Inline.h:45
GA_AttributeDict::iterator const_iterator
long long int64
Definition: SYS_Types.h:116
Data has no numeric representation.
Definition: GA_Types.h:146
SYS_FORCE_INLINE const char * c_str() const
SYS_FORCE_INLINE bool empty(GA_AttributeScope scope) const
GLuint const GLchar * name
Definition: glcorearb.h:786
SYS_FORCE_INLINE iterator & operator++()
UT_OrderedIterator< GA_Attribute *, iterator > ordered_iterator
Iterator which traverses attributes in given order.
GLboolean GLboolean GLboolean b
Definition: glcorearb.h:1222
SYS_FORCE_INLINE GA_Attribute * operator*() const
SYS_FORCE_INLINE bool operator==(const iterator &cmp) const
GLenum GLenum GLsizei void * table
Definition: glad.h:5129
SYS_FORCE_INLINE void clear()
SYS_FORCE_INLINE void forEachProxy(GA_AttributeScope scope, FUNCTOR &&functor) const
static int compareNumberedString(const char *s1, const char *s2, bool case_sensitive=true, bool allow_negatives=false)
MapType::const_iterator const_map_iterator
SYS_FORCE_INLINE ~iterator()
int64 getDeviceMemoryUsage() const
SYS_FORCE_INLINE Range()
SYS_FORCE_INLINE iterator end(GA_AttributeScope scope=GA_SCOPE_INVALID) const
SYS_FORCE_INLINE bool empty() const
SYS_FORCE_INLINE iterator end() const
SYS_FORCE_INLINE Range range(GA_AttributeScope scope) const
SYS_FORCE_INLINE ordered_iterator oend(GA_AttributeScope scope=GA_SCOPE_INVALID) const
SYS_FORCE_INLINE const GA_AttributeSet & getSet() const
ImageBuf OIIO_API add(Image_or_Const A, Image_or_Const B, ROI roi={}, int nthreads=0)
SYS_FORCE_INLINE void forEachProxy(FUNCTOR &&functor) const
SYS_FORCE_INLINE iterator()
static int compareAlpha(GA_Attribute *const *a, GA_Attribute *const *b)
GA_AttributeDict::const_map_iterator myIterator
SYS_FORCE_INLINE iterator(const iterator &src)
GLenum src
Definition: glcorearb.h:1793
SYS_FORCE_INLINE exint entries() const
PcpNodeRef_ChildrenIterator begin(const PcpNodeRef::child_const_range &r)
Support for range-based for loops for PcpNodeRef children ranges.
Definition: node.h:566