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  }
72 
73  /// Report a cache-count. This is bumped when attributes are
74  /// created/destroyed (and hence renamed)
75  /// Only unique to the GA_Detail that owns it, so combine
76  /// with the GA_Detail::getUniqueId()
77  /// (Name comes from OP_Node::getVersionParms which has a similar
78  /// meaning)
79  exint getVersionParms() const { return myVersionParms; }
80 
81  /// Count memory usage using a UT_MemoryCounter in order to count
82  /// shared memory correctly.
83  /// If inclusive is true, the size of this object is counted,
84  /// else only memory owned by this object is counted.
85  /// If this is pointed to by the calling object, inclusive should be true.
86  /// If this is contained in the calling object, inclusive should be false.
87  /// (Its memory was already counted in the size of the calling object.)
88  void countMemory(UT_MemoryCounter &counter, bool inclusive) const;
89 
90  GA_Attribute *find(GA_AttributeScope scope, const UT_StringRef &name) const;
91  GA_AttributeProxy *findProxy(GA_AttributeScope scope, const UT_StringRef &name) const;
92 
94  void clear()
95  {
96  bumpVersionParms();
97  myTable.clear();
98  myPrivateTable.clear();
99  // Group table is cleared elsewhere.
100  }
101 
103  exint entries() const
104  {
105  return myTable.size() + myPrivateTable.size() + numGroups();
106  }
109  {
110  if (scope == GA_SCOPE_PUBLIC)
111  return myTable.size();
112  if (scope == GA_SCOPE_PRIVATE)
113  return myPrivateTable.size();
114  if (scope == GA_SCOPE_GROUP)
115  return numGroups();
116  return entries();
117  }
119  bool empty() const
120  {
121  return myTable.empty() && myPrivateTable.empty() && (numGroups()==0);
122  }
124  bool empty(GA_AttributeScope scope) const
125  { return entries(scope) == 0; }
126 
128  {
129  public:
132  : myIterator()
133  , myDict(NULL)
134  , myScope(GA_SCOPE_INVALID)
135  , myCurrentScope(GA_SCOPE_INVALID)
136  {}
137 
139  iterator(const iterator &src) { *this = src; }
142 
144  const char *name() const
145  {
146  const GA_Attribute *atr =
147  proxy()->getAttribute();
148  return atr ? atr->getName().c_str() : nullptr;
149  }
152  {
153  if (myCurrentScope != GA_SCOPE_GROUP)
154  {
155  return myIterator->second;
156  }
157  return UTverify_cast<GA_ElementGroup*>(myGroupIterator->second)->getProxy().get();
158  }
161  {
162  return proxy()->getAttribute();
163  }
166  {
167  return attrib();
168  }
170  bool operator==(const iterator &cmp) const
171  {
172  UT_ASSERT_P(myDict == cmp.myDict);
173  UT_ASSERT_P(myScope == cmp.myScope);
174  return myIterator.getCurrent() == cmp.myIterator.getCurrent() || (myIterator.atEnd() && cmp.myIterator.atEnd());
175  }
177  bool operator!=(const iterator &cmp) const
178  {
179  UT_ASSERT_P(myDict == cmp.myDict);
180  UT_ASSERT_P(myScope == cmp.myScope);
181  return myIterator.getCurrent() != cmp.myIterator.getCurrent() && !(myIterator.atEnd() && cmp.myIterator.atEnd());
182  }
184  bool atEnd() const
185  {
186  return myIterator.atEnd();
187  }
188 
191  {
192  UT_ASSERT_P(!myIterator.atEnd());
193  ++myIterator;
194  // NOTE: This makes use of that myIterator and myGroupIterator
195  // will have identical memory layouts.
196  if (myScope == GA_SCOPE_INVALID && myIterator.atEnd())
197  {
198  if (myCurrentScope == GA_SCOPE_PUBLIC)
199  {
200  myIterator = myDict->myPrivateTable.begin();
201  myCurrentScope = GA_SCOPE_PRIVATE;
202  if (!myIterator.atEnd())
203  return *this;
204  }
205  if (myCurrentScope == GA_SCOPE_PRIVATE)
206  {
207  const UT_ArrayStringMap<GA_Group *> *grouptable = myDict->getGroupTable();
208  if (grouptable)
209  {
210  myGroupIterator = grouptable->begin();
211  myCurrentScope = GA_SCOPE_GROUP;
212  }
213  }
214  }
215  return *this;
216  }
217 
220  {
221  myIterator = src.myIterator;
222  myDict = src.myDict;
223  myScope = src.myScope;
224  myCurrentScope = src.myCurrentScope;
225  return *this;
226  }
227  private:
229  iterator(const GA_AttributeDict *dict,
230  GA_AttributeScope scope,
231  bool end)
232  : myDict(dict)
233  , myScope(scope)
234  , myCurrentScope(scope)
235  {
236  if (scope == GA_SCOPE_PUBLIC)
237  {
238  myIterator = end ? dict->myTable.end() : dict->myTable.begin();
239  }
240  else if (scope == GA_SCOPE_INVALID)
241  {
242  if (!end)
243  {
244  myIterator = dict->myTable.begin();
245  if (!myIterator.atEnd())
246  {
247  myCurrentScope = GA_SCOPE_PUBLIC;
248  return;
249  }
250  myIterator = dict->myPrivateTable.begin();
251  if (!myIterator.atEnd())
252  {
253  myCurrentScope = GA_SCOPE_PRIVATE;
254  return;
255  }
256  const UT_ArrayStringMap<GA_Group *> *grouptable = dict->getGroupTable();
257  if (grouptable)
258  {
259  myGroupIterator = grouptable->begin();
260  myCurrentScope = GA_SCOPE_GROUP;
261  }
262  else
263  myCurrentScope = GA_SCOPE_PRIVATE;
264  return;
265  }
266  const UT_ArrayStringMap<GA_Group *> *grouptable = dict->getGroupTable();
267  if (grouptable)
268  {
269  myGroupIterator = grouptable->end();
270  myCurrentScope = GA_SCOPE_GROUP;
271  }
272  else
273  {
274  myIterator = dict->myPrivateTable.end();
275  myCurrentScope = GA_SCOPE_PRIVATE;
276  }
277  }
278  else if (scope == GA_SCOPE_GROUP)
279  {
280  const UT_ArrayStringMap<GA_Group *> *grouptable = dict->getGroupTable();
281  if (grouptable)
282  myGroupIterator = end ? grouptable->end() : grouptable->begin();
283  else
284  myIterator = dict->myPrivateTable.end();
285  }
286  else
287  {
288  UT_ASSERT_P(scope == GA_SCOPE_PRIVATE);
289  myIterator = end ? dict->myPrivateTable.end() : dict->myPrivateTable.begin();
290  }
291  }
292  union {
295  };
296  const GA_AttributeDict *myDict;
297  GA_AttributeScope myScope;
298  GA_AttributeScope myCurrentScope;
299  friend class GA_AttributeDict;
300  };
301 
302  class GA_API Range
303  {
304  public:
306  : myBegin()
307  , myEnd()
308  {
309  }
310 
312  : myBegin(dict.begin(scope))
313  , myEnd(dict.end(scope))
314  {
315  }
316 
319 
320  SYS_FORCE_INLINE iterator begin() const { return myBegin; }
321  SYS_FORCE_INLINE iterator end() const { return myEnd; }
322 
323  private:
324  iterator myBegin;
325  iterator myEnd;
326  };
327 
330  { return Range(*this, scope); }
331 
332  static int compareAlpha(GA_Attribute *const*a, GA_Attribute *const*b)
333  {
334  const char *aname = (*a)->getName();
335  const char *bname = (*b)->getName();
336  if (!strcmp(aname, "P"))
337  return -1;
338  if (!strcmp(bname, "P"))
339  return 1;
340 
341  // Not case-sensitive
342  return UT_String::compareNumberedString(aname,bname,false);
343  }
344 
345  /// Iterator which traverses attributes in given order
347 
348  /// @{
349  /// Unordered (fastest) iteration
351  iterator begin(GA_AttributeScope scope = GA_SCOPE_INVALID) const
352  { return iterator(this, scope, false); }
354  iterator end(GA_AttributeScope scope = GA_SCOPE_INVALID) const
355  { return iterator(this, scope, true); }
356  /// @}
357 
358  /// @{
359  /// Ordered iteration. This traverses attributes in a fixed order
362  {
363  iterator it(this, scope, false);
364  return ordered_iterator(it, compareAlpha);
365  }
368  {
369  return ordered_iterator();
370  }
371  /// @}
372 
373  template<typename FUNCTOR>
375  void forEachProxy(FUNCTOR &&functor) const
376  {
377  if (!myTable.empty())
378  myTable.forEachValue(functor);
379  if (!myPrivateTable.empty())
380  myPrivateTable.forEachValue(functor);
381  const UT_ArrayStringMap<GA_Group *> *grouptable = getGroupTable();
382  if (grouptable && !grouptable->empty())
383  {
384  grouptable->forEachValue([&functor](GA_Group *group){
385  functor(UTverify_cast<GA_ElementGroup*>(group)->getProxy().get());
386  });
387  }
388  }
389 
390  template<typename FUNCTOR>
392  void forEachProxy(GA_AttributeScope scope, FUNCTOR &&functor) const
393  {
394  if ((scope == GA_SCOPE_PUBLIC || scope == GA_SCOPE_INVALID) && !myTable.empty())
395  myTable.forEachValue(functor);
396  if ((scope == GA_SCOPE_PRIVATE || scope == GA_SCOPE_INVALID) && !myPrivateTable.empty())
397  myPrivateTable.forEachValue(functor);
398  if (scope == GA_SCOPE_GROUP || scope == GA_SCOPE_INVALID)
399  {
400  const UT_ArrayStringMap<GA_Group *> *grouptable = getGroupTable();
401  if (grouptable && !grouptable->empty())
402  {
403  grouptable->forEachValue([&functor](GA_Group *group){
404  functor(UTverify_cast<GA_ElementGroup*>(group)->getProxy().get());
405  });
406  }
407  }
408  }
409 
410  template<typename FUNCTOR>
412  void forEachAttribute(FUNCTOR &&functor) const
413  {
414  if (!myTable.empty())
415  {
416  myTable.forEachValue([&functor](GA_AttributeProxy *proxy){
417  functor(proxy->getAttribute());
418  });
419  }
420  if (!myPrivateTable.empty())
421  {
422  myPrivateTable.forEachValue([&functor](GA_AttributeProxy *proxy){
423  functor(proxy->getAttribute());
424  });
425  }
426  const UT_ArrayStringMap<GA_Group *> *grouptable = getGroupTable();
427  if (grouptable && !grouptable->empty())
428  {
429  grouptable->forEachValue([&functor](GA_Group *group){
430  functor(UTverify_cast<GA_ElementGroup*>(group));
431  });
432  }
433  }
434 
435  template<typename FUNCTOR>
437  void forEachAttribute(GA_AttributeScope scope, FUNCTOR &&functor) const
438  {
439  if ((scope == GA_SCOPE_PUBLIC || scope == GA_SCOPE_INVALID) && !myTable.empty())
440  {
441  myTable.forEachValue([&functor](GA_AttributeProxy *proxy){
442  functor(proxy->getAttribute());
443  });
444  }
445  if ((scope == GA_SCOPE_PRIVATE || scope == GA_SCOPE_INVALID) && !myPrivateTable.empty())
446  {
447  myPrivateTable.forEachValue([&functor](GA_AttributeProxy *proxy){
448  functor(proxy->getAttribute());
449  });
450  }
451  if (scope == GA_SCOPE_GROUP || scope == GA_SCOPE_INVALID)
452  {
453  const UT_ArrayStringMap<GA_Group *> *grouptable = getGroupTable();
454  if (grouptable && !grouptable->empty())
455  {
456  grouptable->forEachValue([&functor](GA_Group *group){
457  functor(UTverify_cast<GA_ElementGroup*>(group));
458  });
459  }
460  }
461  }
462 
463  template<typename FUNCTOR>
465  void forEachName(GA_AttributeScope scope, FUNCTOR &&functor) const
466  {
467  if ((scope == GA_SCOPE_PUBLIC || scope == GA_SCOPE_INVALID) && !myTable.empty())
468  myTable.forEachKey(functor);
469  if ((scope == GA_SCOPE_PRIVATE || scope == GA_SCOPE_INVALID) && !myPrivateTable.empty())
470  myPrivateTable.forEachKey(functor);
471  if (scope == GA_SCOPE_GROUP || scope == GA_SCOPE_INVALID)
472  {
473  const UT_ArrayStringMap<GA_Group *> *grouptable = getGroupTable();
474  if (grouptable && !grouptable->empty())
475  grouptable->forEachKey(functor);
476  }
477  }
478 
479 
480 private: // Methods
481 
482  /// @private
483  /// Used only by GA_AttributeSet
485  void setNumBuckets(GA_AttributeScope scope, size_t nbuckets)
486  {
487  if (scope == GA_SCOPE_PUBLIC)
488  myTable.setNumBuckets(nbuckets);
489  else if (scope == GA_SCOPE_PRIVATE)
490  myPrivateTable.setNumBuckets(nbuckets);
491  }
492 
493  /// @private
494  /// Used only by GA_AttributeSet
496  void setSet(GA_AttributeSet *s) { mySet = s; }
497 
499  void reserveNewSymbolTableSpace(GA_AttributeScope scope, exint n)
500  {
501  if (scope == GA_SCOPE_PUBLIC)
502  {
503  if (myTable.size()+n > myTable.bucket_count())
504  myTable.rehash(myTable.size()+n);
505  }
506  else if (scope == GA_SCOPE_PRIVATE)
507  {
508  if (myPrivateTable.size()+n > myPrivateTable.bucket_count())
509  myPrivateTable.rehash(myPrivateTable.size()+n);
510  }
511  }
512 
513 
515  void add(GA_AttributeScope scope, const UT_StringHolder &name, GA_AttributeProxy *proxy)
516  {
517  UT_ASSERT_P(proxy != NULL);
518  bumpVersionParms();
519  if (scope == GA_SCOPE_PUBLIC)
520  myTable.insert(std::make_pair(name, proxy));
521  else if (scope == GA_SCOPE_PRIVATE)
522  myPrivateTable.insert(std::make_pair(name, proxy));
523  // NOTE: We don't add the proxy to a table if scope is GA_SCOPE_GROUP,
524  // because it's already in the group table.
525  }
527  void remove(GA_AttributeScope scope, const UT_StringRef &name)
528  {
529  bumpVersionParms();
530  if (scope == GA_SCOPE_PUBLIC)
531  myTable.erase(name);
532  else if (scope == GA_SCOPE_PRIVATE)
533  myPrivateTable.erase(name);
534  // NOTE: We don't remove the proxy from a table if scope is GA_SCOPE_GROUP,
535  // because it's managed by the group table.
536  }
537  friend class GA_AttributeSet; // Only GA_AttributeSet can add/remove
538  friend class GA_GroupTable; // So group table can bump our parms.
539 
541  void bumpVersionParms() { myVersionParms++; }
542 
543  SYS_FORCE_INLINE exint numGroups() const
544  {
545  auto table = getGroupTable();
546  return table ? table->size() : 0;
547  }
548 
549  const UT_ArrayStringMap<GA_Group*> *getGroupTable() const;
550 
551 private: // Data
552 
553  MapType myTable;
554  MapType myPrivateTable;
555 
556  GA_AttributeSet *mySet;
557  exint myVersionParms;
558 };
559 
560 #endif
561 
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:591
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:578
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:348
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:675
#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:148
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:142
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:660
#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:145
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()
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)
FMT_CONSTEXPR auto find(Ptr first, Ptr last, T value, Ptr &out) -> bool
Definition: core.h:2089
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:483