HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
PDG_AttributeMap.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  * COMMENTS:
7  */
8 
9 #ifndef __PDG_ATTRIBUTE_MAP_H__
10 #define __PDG_ATTRIBUTE_MAP_H__
11 
12 #include "PDG_API.h"
13 
14 #include "PDG_AttributeArray.h"
15 #include "PDG_AttributeData.h"
16 #include "PDG_AttributeGeometry.h"
17 #include "PDG_AttributeHolder.h"
18 #include "PDG_AttributePyObject.h"
19 #include "PDG_AttributeRef.h"
20 #include "PDG_EvaluationContext.h"
21 #include "PDG_Types.h"
22 
23 #include <PDGT/PDGT_Value.h>
24 
25 #include <UT/UT_ArrayStringMap.h>
26 #include <UT/UT_ArrayStringSet.h>
27 #include <UT/UT_NonCopyable.h>
28 #include <UT/UT_RWLock.h>
29 #include <UT/UT_StringHolder.h>
30 #include <UT/UT_UniquePtr.h>
31 
32 class UT_JSONValue;
33 class UT_JSONWriter;
34 
35 class PDG_AttributeMerge;
36 class PDG_AttributeOwner;
38 
39 /**
40  * Map for storing, accessing and persisting PDG attribute data.
41  * Attributes are stored in a map of string value to attribute holder, which
42  * maintains a weak/strong reference to an attribute. Writing to an attrib value
43  * results in a deep copy being performed on the specified attribute (i.e. copy
44  * on write). Attribute handles are given to callers in the form of a
45  * PDG_ROAttributeRef or PDG_RWAttributeRef, depending on whether the caller
46  * requested a read only or read/write handle.
47  *
48  * Attributes are owned by a PDG_AttributeOwner instance. In most cases this is
49  * a PDG_WorkItem, and the attributes are accessed/modified when the node
50  * creates or cooks the work item.
51  *
52  * The attribute map maintains a separate table for static and dynamic
53  * attributes. Static attributes are any attributes created during the work
54  * item generation step, and dynamic attributes are attributes created or
55  * modified at any other point in time. If a work item attempts to modify
56  * a static attribute while cooking, including adding output files, then a
57  * copy made is in the dynamic map. The modifications are peformed on that
58  * rather than on the original static attribute. This means that when a work
59  * item is dirtied, it can easily roll back to the exact same state it was in
60  * before cooking. When a work item is being regenerated, only static values
61  * are considered. If the item is dirty then all dynamic attributes are
62  * discarded, otherwise if the item is still valid then the dynamic values
63  * are left as-is.
64  *
65  * The various merge* methods should be used to merge attribute map data
66  * from a parent or dependency on the work item. Care should be taken to only
67  * merge static attributes during work item generation. Dynamic attributes
68  * can be merged at any point between generation and the work item being marked
69  * as cooked.
70  */
72 {
73 public:
74  /// Prefix for all built-in PDG attributes that can potentially appear on
75  /// work items. User-created attributes cannot begin with this prefix.
77 
78  /// Name of the built-in input file list attribute, which contains the
79  /// read only list of input files to a work item
81 
82  /// Name of the built-in output file list attribute, which contains the
83  /// list of all output files from the work item, including any outputs
84  /// copied from inputs.
86 
87  /// Name of the built-in added file list attribute, which contains files
88  /// explicitly added to the work item.
90 
91  /// Name of the built-in command attribute
93 
94  /// Name of the built-in human readable label attribute
96 
97  /// Name of the built-in custom state attribute
99 
100  /// Name of the built-in cook percent attribute
102 
103  /// Name of the built-in partition size attribute
105 
106 
107  /// Special token indicating all attributes, used when binding attributes
108  /// with PDG_AttributeInfo.
110 
111  /// Special token used to indicate a "pseudo" attribute dependency, such
112  /// as the work item's index or frame. These attribute dependencies only
113  /// exist because the values are accessible via expressions like a regular
114  /// attribute, although the value itself is not stored as an attribute.
116 
117 
118  /// Flags for the standard input file attribute
119  static const uint16 theInputFileFlags;
120 
121  /// Flags for the standard output file attribute
123 
124  /// Flags for the standard added file attribute
125  static const uint16 theAddedFileFlags;
126 
127  /// Flags for the standard command string attribute
129 
130  /// Flags for the standard label attribute
131  static const uint16 theLabelFlags;
132 
133  /// Flags for the standard custom state attribute
135 
136  /// Save operation to perform
137  enum SaveType
138  {
139  /// Flatten attributes, saving both dynamic and static as a mix
141 
142  /// Save only static
144 
145  /// Save only dynamic
147 
148  /// Save all attributes, including ones from the parent map that
149  /// are not directly owned by this map
151  };
152 
153  /// Determines when to create an attribute, for refRW method calls that
154  /// can optionally create one if it does not yet exist.
156  {
157  /// Never create the attribute, even if its not found
159 
160  /// Always create the attribute if it does not exist
162 
163  /// Only create the attribute if its necessary to upgrade from
164  /// a static table entry to a dynamic table entry.
166  };
167 
168  /// Detrmines when to overwrite an attribute when requesting an RW
169  /// reference to it.
171  {
172  /// Never overwrite the attribute
174 
175  /// Only overwrite the attribute if the type matches
177 
178  /// Always overwrite the attribute. If the attribute exists with
179  /// different type, it will be removed and replaced with a new
180  /// attribute of the requested type.
181  eOverwriteAlways
182  };
183 
184  /// Enumeration of possible attribute change results during regeneration
186  {
187  /// No changes occured
189 
190  /// Attribute values were changed or added
192 
193  /// At least one attribute was deleted
194  eChangeDestructive
195  };
196 
197  /// Enumeration of attribute tables
199  {
200  /// Static attribute table, attributes in this table are modified when
201  /// the work item is generated
203 
204  /// Dynamic attribute table, attributes in this table are modified
205  /// outside of the generation step (during the cook, precook, etc).
207 
208  /// Number of attribute tables
210  };
211 
212 public:
213  /// Scoped lock of an attribute map and the node that owns the work item
214  /// associated with the attribute map. This is used to serialize access
215  /// to work item attributes when running a node callback or adding results
216  /// from the scheduler.
217  ///
218  /// When a node callback runs, the node's read lock and work item's write
219  /// lock are acquired. When a full-node callback like onRegenerate is
220  /// run, the node's write lock is acquired, effectively locking all attribs
221  /// on all items in the node.
222  ///
223  /// Internally, PDG does not require the use of this lock. The cook logic
224  /// and dependency graph are structure in such a way that work items don't
225  /// need to lock in order to safely access themselves or their parent. This
226  /// lock and the scoped locks around various work item callbacks exist for
227  /// the benefit of external code that requires direct, random access to
228  /// PDG work items. PDG attribute events, for example, can safely read
229  /// attribute data without locking.
230  template <bool Read>
232  {
233  public:
234  /// We must always acquire the global lock first, then the attrib lock.
235  /// Other places in the code such as the onRegenerate callback
236  /// assume that to be the case, and doing so in the wrong order will
237  /// cause a deadlock. The global lock is only acquired as a read lock
238  /// here -- acquring a write lock to the global lock can be used to get
239  /// exclusive access to ALL attribute maps that use the same lock.
240  ScopedLock(const PDG_AttributeMap& attribute_map)
241  : myGlobalLock(attribute_map.globalLock())
242  , myAttribLock(attribute_map.attributeLock())
243  , myAttribMap(attribute_map)
244  {
245  if (myGlobalLock)
246  myGlobalLock->readLock();
247 
248  if (Read)
249  myAttribLock.readLock();
250  else
251  myAttribLock.writeLock();
252  }
253 
255  {
256  if (Read)
257  myAttribLock.readUnlock();
258  else
259  {
260  myAttribMap.onUnlock();
261  myAttribLock.writeUnlock();
262  }
263 
264  if (myGlobalLock)
265  myGlobalLock->readUnlock();
266  }
267 
268  private:
269  UT_RWLock* myGlobalLock;
270  UT_RWLock& myAttribLock;
271  const PDG_AttributeMap& myAttribMap;
272  };
273 
274  /// Version of the above lock that only tries to lock, and sets a flag
275  /// to true or false based on whether the lock was acquired. This should
276  /// be used for UI updates that don't require access to a specific attrib
277  /// and are simply presenting current state, for example. It reduces the
278  /// amount of time the UI spends blocked on PDG structures.
280  {
281  public:
282  ScopedTryLock(const PDG_AttributeMap& attribute_map)
283  : myGlobalLock(attribute_map.globalLock())
284  , myAttribLock(attribute_map.attributeLock())
285  , myDidLockGlobal(false)
286  , myDidLockAttrib(false)
287  {
288  if (!myGlobalLock || myGlobalLock->tryReadLock())
289  {
290  myDidLockGlobal = true;
291  if (myAttribLock.tryReadLock())
292  myDidLockAttrib = true;
293  }
294  }
295 
297  {
298  if (myDidLockAttrib)
299  myAttribLock.readUnlock();
300 
301  if (myGlobalLock && myDidLockGlobal)
302  myGlobalLock->readUnlock();
303  }
304 
305  /// Returns true only if the lock was successful. This method should be
306  /// checked before performing any actions on this attribute map.
307  inline bool didLock() const
308  { return (myDidLockGlobal && myDidLockAttrib); }
309 
310  private:
311  UT_RWLock* myGlobalLock;
312  UT_RWLock& myAttribLock;
313  bool myDidLockGlobal;
314  bool myDidLockAttrib;
315  };
316 
317  /// Runs a functor on this map under the scoped read lock, so it's safe
318  /// for concurrent access on an arbitrary thread. This holds both the
319  /// global read lock and attribute map read lock, so it can always be
320  /// called in order to safely iterate over attribute values. This should
321  /// be used in, for example, an event handler callback in order to ensure
322  /// that the attributes are not also being written to by the owner or
323  /// a full-item list operation performed by another holder of the global
324  /// lock.
325  ///
326  /// If this map does not have an owner, or the owner does not have a
327  /// global lock, the functor will be called with only the local attribute
328  /// lock held.
329  template <typename Func>
330  bool lockedAccess(const Func& func) const
331  {
332  ScopedLock<true> auto_lock(*this);
333  func(*this);
334  return true;
335  }
336 
337  /// Same as above, but only try-locks. If the lock cannot be acquired the
338  /// functor is not run and the method returns false. If the functor is
339  /// run successfully this method returns true.
340  template <typename Func>
341  bool tryLockedAccess(const Func& func) const
342  {
343  ScopedTryLock auto_lock(*this);
344  if (!auto_lock.didLock())
345  return false;
346 
347  func(*this);
348  return true;
349  }
350 
351  /// Iterates over attributes in the map of the specified type, and invokes
352  /// the input function on each matching entry. This function operates on
353  /// the space of attribute names, and therefore will including parent map
354  /// attributes and dynamic attributes, if permitted by the active context.
355  ///
356  /// The supplied function can return true to halt iteration.
357  template <typename Attribute, typename Func>
358  void forEachRO(const Func& func) const
359  {
360  UT_ArrayStringSet names;
361  attributeNames(names, Attribute::TypeEnum);
362 
363  for (auto&& name : names)
364  {
365  auto&& ref = refRO<Attribute>(name);
366  if (ref && func(ref))
367  break;
368  }
369  }
370 
371 public:
372  explicit PDG_AttributeMap(
373  const PDG_AttributeOwner* owner,
374  bool has_runtime);
375  ~PDG_AttributeMap();
376 
377  /// Returns the memory usage of this attribute map
378  int64 getMemoryUsage(bool inclusive) const;
379 
380  /// Swaps the target attribute map contents with this one
381  void swap(PDG_AttributeMap& other);
382 
383  /// Freezes the attributes in the map, which invokes a deep copy on any
384  /// unowned attributes. This makes the map fully standalone, without any
385  /// shallow references to external attribute maps.
386  void freeze();
387 
388  /// Merges all attributes from another map into this one.
389  bool mergeFull(
390  PDG_AttributeMerge& attrib_merge,
391  const PDG_AttributeMap& other,
392  AttribTable dst_table=eTableStatic,
393  bool reset=true);
394 
395  /// Merges all attributes from another attribute owner into this one.
396  bool mergeFull(
397  PDG_AttributeMerge& attrib_merge,
398  const PDG_AttributeOwner* owner,
399  AttribTable dst_table=eTableStatic,
400  bool reset=true);
401 
402  /// Merges static attributes from another attribute owenr into this one.
403  bool mergeStatic(
404  PDG_AttributeMerge& attrib_merge,
405  const PDG_AttributeOwner* owner);
406 
407  /// Merges dynamic attributes from another attribute owenr into this one.
408  bool mergeDynamic(
409  PDG_AttributeMerge& attrib_merge,
410  const PDG_AttributeOwner* owner);
411 
412  /// Sets the parent map
413  void setParentMap(PDG_AttributeOwner* parent);
414 
415  /// Resolves any pending operations in the specified attribute merge map
416  void resolveMergeOps(PDG_AttributeMerge& attrib_merge);
417 
418  /// Erases any dynamic attributes, unowned attributes, or owned attributes
419  /// that were formed by concatenating input attributes. Returns true if
420  /// an attribute that was owned by this map is destroyed.
421  bool eraseDirty(bool include_unowned);
422 
423  /// Removes any stale attributes from the map from the deserialization
424  /// process
425  void eraseStale();
426 
427  /// Erases all attributes in this map
428  PDG_AttributeRef::Error eraseAll(bool include_internal);
429 
430  /// Erases all attributes of the specified Attribute type from the map
432 
433  /// Erases an attribute from the map by name
435 
436  /// Clears the contents of any owned concatenated attributes, but does
437  /// not remove them
438  void clearConcat(AttribTable table=eTableCount);
439 
440 
441  /// Returns the set of time dependent attributes for this map
442  bool timeDependentAttributes(
443  UT_ArrayStringSet& names) const;
444 
445  /// Checks for the existance of an attribute by name. Returns true if the
446  /// attribute is found, else false
447  bool hasAttribute(const UT_StringHolder& name) const;
448 
449  /// Returns the type of the attribute with the specified name
450  PDG_AttributeType attributeType(const UT_StringHolder& name) const;
451 
452  /// Returns the size of the attribute with the specified name
453  int attributeSize(const UT_StringHolder& name) const;
454 
455  /// Returns the set of attribute names in the map, for the specified
456  /// attribute type. Values are returned back as a string set.
457  void attributeNames(UT_ArrayStringSet& names,
458  PDG_AttributeType type) const;
459 
460  /// Returns the set of attribute names in the map, for the specified
461  /// attribute type. Values are returned back as an array, sorted by
462  /// attribute name.
463  void attributeNames(UT_StringArray& names,
464  PDG_AttributeType type) const;
465 
466  /// Returns the total number of attributes in the map, for the specified
467  /// atribute type.
468  int numAttributes(PDG_AttributeType type) const;
469 
470  /// Returns true if any attributes in this map match the specified pattern
471  bool attributeMatch(const PDG_AttributePattern& pattern,
472  bool include_internal) const;
473 
474  /// Returns the set of attribute names in the map that match the specified
475  /// attribute pattern. Returns true if anything matches, else false.
476  bool attributeMatch(UT_ArrayStringSet& names,
478  bool include_internal) const;
479 
480  /// Saves the attribute map to a JSON writer, in the most current data
481  /// format
482  bool save(UT_JSONWriter& writer,
483  SaveType save_type,
484  bool is_patch,
485  bool include_bound) const;
486 
487  /// Saves a single attribute holder to a JSON writer, in the most current
488  /// data format.
489  bool save(UT_JSONWriter& writer,
490  const PDG_AttributeHolder& holder,
491  const UT_StringHolder& name) const;
492 
493  /// Loads a V1 data format json object
494  bool loadV1(PDG_AttributeCollision strategy,
495  const UT_JSONValue& value);
496 
497  /// Loads a V2 data format json object
498  bool loadV2(SaveType save_type,
499  PDG_AttributeCollision strategy,
500  const UT_JSONValue& value);
501 
502  /// Returns the attribute owner
503  const PDG_AttributeOwner* owner() const
504  { return myOwner; }
505 
506  /// Returns a read-only handle to the standard input file attribute
508  inputFileRO(AttribTable table=eTableCount) const
509  {
510  return refRO<PDG_AttributeFile>(theInputFileName, table);
511  }
512 
513  /// Returns a read/write handle to the standard input file attribute
515  inputFileRW(CreateWhen create=eCreateNever,
516  AttribTable table=eTableCount)
517  {
518  return refRWC<PDG_AttributeFile>(
519  theInputFileName,
520  create,
521  eOverwriteMatch,
522  table,
523  true,
524  theInputFileFlags);
525  }
526 
527  /// Returns a read-only handle to the standard output file attribute
529  outputFileRO(AttribTable table=eTableCount) const
530  {
531  return refRO<PDG_AttributeFile>(theOutputFileName, table);
532  }
533 
534  /// Returns a read-write handle to the standard output file attribute
536  outputFileRW(CreateWhen create=eCreateNever,
537  AttribTable table=eTableCount)
538  {
539  return refRWC<PDG_AttributeFile>(
540  theOutputFileName,
541  create,
542  eOverwriteMatch,
543  table,
544  true,
545  theOutputFileFlags);
546  }
547 
548  /// Returns a read-only handle to the standard added file attribute
550  addedFileRO(AttribTable table=eTableCount) const
551  {
552  return refRO<PDG_AttributeFile>(theAddedFileName, table);
553  }
554 
555  /// Returns a read/write handle to the standard input file attribute
557  addedFileRW(CreateWhen create=eCreateNever,
558  AttribTable table=eTableCount)
559  {
560  return refRWC<PDG_AttributeFile>(
561  theAddedFileName,
562  create,
563  eOverwriteMatch,
564  table,
565  true,
566  theAddedFileFlags);
567  }
568 
569  /// Returns a read-only handle to the standard command string file
570  /// attribute
572  commandStringRO(AttribTable table=eTableCount) const
573  {
574  return refRO<PDG_AttributeString>(theCommandStringName, table);
575  }
576 
577  /// Returns a read/write handle to the standard input file attribute
579  commandStringRW(CreateWhen create=eCreateNever,
580  AttribTable table=eTableCount)
581  {
582  return refRWC<PDG_AttributeString>(
583  theCommandStringName,
584  create,
585  eOverwriteMatch,
586  table,
587  true,
588  theCommandStringFlags);
589  }
590 
591  /// Returns a read-only handle to the standard work item label
592  /// attribute
594  labelRO(AttribTable table=eTableCount) const
595  {
596  return refRO<PDG_AttributeString>(theLabelName, table);
597  }
598 
599  /// Returns a read/write handle to the standard work item label attribute
601  labelRW(CreateWhen create=eCreateNever,
602  AttribTable table=eTableCount)
603  {
604  return refRWC<PDG_AttributeString>(
605  theLabelName,
606  create,
607  eOverwriteMatch,
608  table,
609  true,
610  theLabelFlags);
611  }
612 
613  /// Returns a read-only handle to the standard work item custom state
614  /// attribute
616  stateRO(AttribTable table=eTableCount) const
617  {
618  return refRO<PDG_AttributeString>(theCustomStateName, table);
619  }
620 
621  /// Returns a read/write handle to the standard work item custom state
622  /// attribute
624  stateRW(CreateWhen create=eCreateNever,
625  AttribTable table=eTableCount)
626  {
627  return refRWC<PDG_AttributeString>(
628  theCustomStateName,
629  create,
630  eOverwriteMatch,
631  table,
632  true,
633  theCustomStateFlags);
634  }
635 
636  /// Returns a read-only handle to the standard work item cook progress
637  /// attribute
639  cookPercentRO(AttribTable table=eTableCount) const
640  {
641  return refRO<PDG_AttributeFloat>(theCookPercentName, table);
642  }
643 
644  /// Returns a read/write handle to the standard work item custom state
645  /// attribute
647  cookPercentRW(CreateWhen create=eCreateNever,
648  AttribTable table=eTableCount)
649  {
650  return refRWC<PDG_AttributeFloat>(
651  theCookPercentName,
652  create,
653  eOverwriteMatch,
654  table,
655  true,
656  theCustomStateFlags);
657  }
658 
659  /// Returns a read-only, const attribute handle. Will be invalid if the
660  /// specified attribute does not exist or is of the wrong type.
661  template <typename Attribute=PDG_AttributeData>
664  AttribTable table=eTableCount) const
665  {
668 
669  if (table == eTableCount)
670  table = isRuntime(local_ctx) ? eTableDynamic : eTableStatic;
671 
672  const PDG_AttributeHolder* holder =
673  attribHolderR<Attribute>(error, name, table, true);
674 
675  if (!holder)
676  return PDG_ROAttributeRef<Attribute>(nullptr, name, myOwner, error);
677  return PDG_ROAttributeRef<Attribute>(holder, name, myOwner);
678  }
679 
680  /// Returns a read/write, non-const attribute handle that permits both
681  /// flag and data manipulation. Does not create the attribute, but will
682  /// upgrade it from a parent map/lower table if necessary. Note that this
683  /// method is intionally distinct from the version below since it uses a
684  /// codepath that doesn't require a concrete Attribute type in order to
685  /// create an attribute reference.
686  template <typename Attribute>
689  {
691  if (!canWrite(local_ctx))
692  {
693  return PDG_RWAttributeRef<Attribute>(nullptr, name, myOwner,
695  }
696 
697  AttribTable table = isStatic(local_ctx) ? eTableStatic : eTableDynamic;
698 
699  UT_StringHolder valid;
700  PDG_AttributeData::makeValidName(valid, name, false);
701 
703  PDG_AttributeHolder* holder = attribHolderW<Attribute>(
704  error, valid, table);
705 
706  if (holder)
707  return PDG_RWAttributeRef<Attribute>(holder, valid, myOwner);
708  return PDG_RWAttributeRef<Attribute>(nullptr, name, myOwner, error);
709  }
710 
711  /// Returns a read/write, non-const attribute handle that permits both
712  /// flag and data manipulation. Optionally creates the attribute if it
713  /// does not exist. Will be invalid if the specified attribute does not
714  /// exist, is of the wrong type, or is marked as read-only.
715  template <typename Attribute>
718  bool create,
719  OverwriteWhen overwrite=eOverwriteMatch,
720  uint16 flags=0)
721  {
722  return refRWC<Attribute>(
723  name,
724  (create ? eCreateAlways : eCreateNever),
725  overwrite,
726  eTableCount,
727  false,
728  flags);
729  }
730 
731  /// Same as above, but with greater control on the creation flags.
732  template <typename Attribute>
735  CreateWhen create=eCreateNever,
736  OverwriteWhen overwrite=eOverwriteMatch,
737  AttribTable table=eTableCount,
738  bool allow_internal_names=false,
739  uint16 flags=0)
740  {
742  if (!canWrite(local_ctx))
743  {
744  return PDG_RWAttributeRef<Attribute>(nullptr, name, myOwner,
746  }
747 
748  UT_StringHolder valid;
749  PDG_AttributeData::makeValidName(valid, name, allow_internal_names);
750 
751  if (table == eTableCount)
752  table = isStatic(local_ctx) ? eTableStatic : eTableDynamic;
753 
755  PDG_AttributeHolder* holder = attribHolderC<Attribute>(error, valid,
756  create, overwrite, true, table, flags);
757 
758  if (holder)
759  return PDG_RWAttributeRef<Attribute>(holder, valid, myOwner);
760  return PDG_RWAttributeRef<Attribute>(nullptr, name, myOwner, error);
761  }
762 
763  /// Copies the specified attribute into an attribute on this map
764  template <typename Attribute>
767  bool overwrite_existing,
768  bool deep_copy)
769  {
771  if (!canWrite(local_ctx))
773 
774  UT_StringHolder valid;
776 
778  isStatic(local_ctx) ? eTableStatic : eTableDynamic;
779  OverwriteWhen overwrite =
780  overwrite_existing ? eOverwriteMatch : eOverwriteNever;
781 
783  PDG_AttributeHolder* holder = attribHolderC<Attribute>(error, valid,
784  eCreateAlways, overwrite, false, table, 0);
785  if (!holder)
786  return error;
787 
788  const PDG_AttributeHolder* ref_holder = ref.holder();
789  if (holder->isOwner())
790  {
791  holder->attribute<Attribute>()->copy(
792  ref_holder->template attribute<Attribute>());
793  }
794  else
795  {
796  holder->reset(*ref_holder, false, true);
797 
798  if (deep_copy)
799  holder->own();
800  }
801 
803  }
804 
805  /// Renames the specififed attribute
807  const UT_StringHolder& dst_name,
808  bool overwrite)
809  {
810  // Attributes cannot be renamed if we don't have write access
812  if (!canWrite(local_ctx))
814 
816  isStatic(local_ctx) ? eTableStatic : eTableDynamic;
817 
818  PDG_AttributeHolder* holder = nullptr;
819  AttribTable src_table = eTableCount;
820 
821  // Find the attribute in the desired table, or lower table if it does
822  // not exist
823  for (int i = table; i >= 0; i--)
824  {
825  auto&& attrib = myAttributes[i].find(src_name);
826  if (attrib != myAttributes[i].end())
827  {
828  holder = attrib->second.get();
829  src_table = static_cast<AttribTable>(i);
830  break;
831  }
832  }
833 
834  // If the attribute only exists in a lower table, return an error since
835  // we cannot manipulate that table.
836  if (src_table < table)
838 
839  // If there's no holder, there's nothing to rename
840  if (!holder)
842 
843  // Disallow renaming of write protected attributes
844  if (holder->hasFlag(PDG_AttributeFlag::eReadOnlyFlag))
846 
847  // Disallow renaming of internal attributes
848  if (holder->hasFlag(PDG_AttributeFlag::eInternalFlag))
850 
851  // Create a valid destination name
852  UT_StringHolder valid;
853  PDG_AttributeData::makeValidName(valid, dst_name);
854 
855  // Check for an existing attribute with the dest name
856  auto&& iter = myAttributes[table].find(valid);
857  if (iter != myAttributes[table].end())
858  {
859  // Internal attributes can never be the destination of a rename
860  if (iter->second->hasFlag(PDG_AttributeFlag::eInternalFlag))
862  // Return early if the caller doesn't want to overwrite
863  else if (!overwrite)
865 
866  // Erase the existing attribute
867  myAttributes[table].erase(iter);
868  }
869 
870  // Move the attribute into the map entry with the new name
871  HolderPtr holder_copy =
872  UTmakeUnique<PDG_AttributeHolder>(std::move(*holder));
873  myAttributes[table].emplace(valid, std::move(holder_copy));
874  myAttributes[table].erase(src_name);
875 
877  }
878 
879  /// Utility method that looks up a value from an attribute, with a given
880  /// index, and an optional flag filter
881  template <typename Attribute>
882  bool value(typename Attribute::Data& value,
883  const UT_StringHolder& name,
884  int index,
885  uint16 flags = 0) const
886  {
887  auto&& attribute = refRO<Attribute>(name);
888  if (!attribute || !attribute.hasFlags(flags))
889  return false;
891  return false;
892 
893  return attribute->value(value, index);
894  }
895 
896  /// Utility method that looks up an array value from an attribute, with an
897  /// optional flag filter
898  template <typename Attribute>
899  bool value(typename Attribute::Array& value,
900  const UT_StringHolder& name,
901  uint16 flags = 0) const
902  {
903  auto&& attribute = refRO<Attribute>(name);
904  if (!attribute || !attribute.hasFlags(flags))
905  return false;
907  return false;
908 
909  value = attribute->values();
910  return true;
911  }
912 
913  /// Utility method that sets an attribute value at a specified index, and
914  /// creates it if it does not already exist
915  template <typename Attribute>
917  const typename Attribute::Data& value,
918  int index,
919  bool create,
920  OverwriteWhen overwrite=eOverwriteMatch)
921  {
922  auto&& attribute = refRW<Attribute>(name, create, overwrite);
923  if (!attribute)
924  return attribute.error();
925  attribute->setValue(value, index);
927  }
928 
929  /// Utility method that sets an attribute array value, and creates it if
930  /// it does not already exist
931  template <typename Attribute>
933  const typename Attribute::Array& values,
934  bool create,
935  OverwriteWhen overwrite=eOverwriteMatch)
936  {
937  auto&& attribute = refRW<Attribute>(name, create, overwrite);
938  if (!attribute)
939  return attribute.error();
940  attribute->setValue(values);
942  }
943 
944  /// Utility method that clears all values from an attribute, and creates
945  /// it if it does not already exist
946  template <typename Attribute>
948  bool create,
949  OverwriteWhen overwrite=eOverwriteMatch)
950  {
951  auto&& attribute = refRW<Attribute>(name, create, overwrite);
952  if (!attribute)
953  return attribute.error();
954  attribute->clear();
956  }
957 
958  /// Queries all values of the specified attribute type and returns them as
959  /// a map.
960  template <typename Attribute>
961  bool values(typename Attribute::Map& value_map,
962  uint16 flags = 0) const
963  {
964  values<Attribute>(eTableStatic, value_map, flags);
966  if (isRuntime(local_ctx))
967  values<Attribute>(eTableDynamic, value_map, flags);
968  return true;
969  }
970 
971  /// Queries a scalar value by name/index and stores it as a PDGT_Value
972  bool value(PDGT_Value& value,
973  const UT_StringHolder& name,
974  int index,
975  uint16 flags = 0) const;
976 
977  /// Queries all values as PDGT_Values
978  bool values(PDGT_Value::Map& value_map,
979  uint16 flags = 0) const;
980 
981 
982  /// Returns true if attribute has the the specified flag set, else false
983  bool hasFlag(const UT_StringHolder& name,
984  PDG_AttributeFlag flag) const;
985 
986  /// Sets or clears a flag on the specified attribute
988  PDG_AttributeFlag flag,
989  bool set);
990 
991  /// Sets or clears a flag on all attributes
992  bool setFlagAll(PDG_AttributeFlag flag,
993  bool set);
994 
995 
996  /// Begins tracking attribute changes
997  void startChangeTracking();
998 
999  /// Ends tracking changes, returning true if a change made was
1000  ChangeResult endChangeTracking(bool check_all);
1001 
1002  /// Computes the hash value for attrib values, errors can occur if python
1003  /// objects hash() raises an exception.
1004  bool hash(SYS_HashType& hash_val,
1005  AttribTable table,
1006  bool include_internal,
1007  bool include_unowned,
1008  UT_WorkBuffer& errors) const;
1009 
1010  /// Computes the hash value for the specific attribute values specified in
1011  /// the set of names. This is the same as the function above, but it
1012  /// only applies to the indicated subset of attribs.
1013  bool hash(SYS_HashType& hash_val,
1014  const UT_ArrayStringSet& filter,
1015  AttribTable table,
1016  bool include_internal,
1017  bool include_unowned,
1018  UT_WorkBuffer& errors) const;
1019 
1020 private:
1021  /// Managed attribute holder pointer
1022  using HolderPtr = UT_UniquePtr<PDG_AttributeHolder>;
1023 
1024  /// String map to attribute holder - the actual storage type of this
1025  /// structure
1026  using Map = UT_ArrayStringMap<HolderPtr>;
1027 
1028 private:
1029  /// Returns the attribute lock for this attribute map
1030  UT_RWLock& attributeLock() const;
1031 
1032  /// Returns the global attribute lock for this map
1033  UT_RWLock* globalLock() const;
1034 
1035  /// Called when the map is unlocked
1036  void onUnlock() const;
1037 
1038  /// Internal logic for hashing attributes
1039  bool hashAttributes(
1040  SYS_HashType& hash_val,
1041  const UT_ArrayStringSet& filter,
1042  AttribTable table,
1043  bool include_internal,
1044  bool include_unowned,
1045  UT_WorkBuffer& errors) const;
1046 
1047  /// Returns a reference to the shared, static invalid attribute reg
1048  static PDG_AttributeHolder&
1049  invalidHolder();
1050 
1051  /// Returns true if the attribute owenr that owns this attribute map can
1052  /// create RW attribute references
1053  bool canWrite(const PDG_EvaluationContext* ctx) const;
1054 
1055  /// Returns true if called during a runtime/cook operation, instead of a
1056  /// generation operation
1057  bool isRuntime(const PDG_EvaluationContext* ctx) const;
1058 
1059  /// Returns true if called during work item generation
1060  bool isStatic(const PDG_EvaluationContext* ctx) const;
1061 
1062  /// Returns true if the specified attribute exists in the table
1063  bool hasAttribute(const UT_StringHolder& name,
1064  AttribTable table) const
1065  {
1066  if (myParentMap && myParentMap->hasAttribute(name, table))
1067  return true;
1068  return (myAttributes[table].find(name) != myAttributes[table].end());
1069  }
1070 
1071  /// Merges attributes from the source table in another map to dst
1072  /// table in this map.
1073  bool mergeMap(
1074  PDG_AttributeMerge& attrib_merge,
1075  UT_StringSet& exclusion_set,
1076  const PDG_AttributeMap& other,
1077  AttribTable src_table,
1078  AttribTable dst_table,
1079  bool flatten_dynamic);
1080 
1081  /// Merges an attribute from a different map into the dst table in this
1082  /// map.
1083  bool mergeAttribute(
1084  PDG_AttributeMerge& attrib_merge,
1085  UT_StringSet& exclusion_set,
1086  const PDG_AttributeHolder& other_holder,
1087  const UT_StringHolder& name,
1088  AttribTable dst_table);
1089 
1090  /// Loads an attribute from the json value, with the specified name, type
1091  /// and flags
1092  bool loadAttribute(AttribTable table,
1093  PDG_AttributeCollision strategy,
1095  const UT_StringHolder& name,
1096  uint16 flags,
1097  bool is_own,
1098  bool is_concat,
1099  const UT_JSONValue& data);
1100 
1101  /// Loads an old-style attribute entry from json
1102  bool loadV1Map(PDG_AttributeCollision strategy,
1104  const UT_JSONValue& data);
1105 
1106  /// Saves the values from the specified map into an instace of a generic
1107  /// data map
1108  bool values(AttribTable table,
1109  PDGT_Value::Map& value_map,
1110  uint16 flags) const
1111  {
1112  if (myParentMap)
1113  myParentMap->values(table, value_map, flags);
1114 
1115  for (auto&& attrib_pair : myAttributes[table])
1116  {
1117  const PDG_AttributeHolder& holder = *attrib_pair.second;
1118  if (!holder.hasFlags(flags))
1119  continue;
1121  continue;
1122  if (!attribToValue(value_map[attrib_pair.first], 0, holder))
1123  return false;
1124  }
1125 
1126  return true;
1127  }
1128 
1129  /// Saves the values from the specified map into an instance of the map
1130  /// data type
1131  template <typename Attribute>
1132  void values(AttribTable table,
1133  typename Attribute::Map& value_map,
1134  uint16 flags) const
1135  {
1136  if (myParentMap)
1137  myParentMap->values<Attribute>(table, value_map, flags);
1138 
1139  for (auto&& attrib_pair : myAttributes[table])
1140  {
1141  const PDG_AttributeHolder& holder = *attrib_pair.second;
1142  if (!holder.typeMatch<Attribute>())
1143  {
1144  value_map.erase(attrib_pair.first);
1145  continue;
1146  }
1147 
1148  if (!holder.hasFlags(flags))
1149  continue;
1151  continue;
1152 
1153  const Attribute* attribute = holder.attribute<Attribute>();
1154  if (attribute)
1155  value_map[attrib_pair.first] = attribute->values();
1156  }
1157  }
1158 
1159  /// Returns the size of an attribute
1160  static int attribSize(const PDG_AttributeHolder& src)
1161  {
1162  switch (src.type())
1163  {
1165  return src.attribute<PDG_AttributeInteger>()->size();
1167  return src.attribute<PDG_AttributeFloat>()->size();
1169  return src.attribute<PDG_AttributeString>()->size();
1171  return src.attribute<PDG_AttributeFile>()->size();
1173  return src.attribute<PDG_AttributePyObject>()->size();
1175  return src.attribute<PDG_AttributeGeometry>()->size();
1176  default:
1177  return -1;
1178  }
1179  }
1180 
1181  /// Concatenates an attribute
1182  static bool attribConcat(PDG_AttributeHolder& dst,
1183  const PDG_AttributeHolder& src)
1184  {
1185  if (src.type() != dst.type())
1186  return false;
1187 
1188  switch (dst.type())
1189  {
1191  return dst.concat<PDG_AttributeInteger>(src);
1193  return dst.concat<PDG_AttributeFloat>(src);
1195  return dst.concat<PDG_AttributeString>(src);
1197  return dst.concat<PDG_AttributeFile>(src);
1198  default:
1199  return false;
1200  }
1201 
1202  return true;
1203  }
1204 
1205  /// Updates the size of an attribute
1206  static bool attribAdjustSize(PDG_AttributeHolder& attrib,
1207  int offset)
1208  {
1209  switch (attrib.type())
1210  {
1212  return attrib.adjustSize<PDG_AttributeInteger>(offset);
1214  return attrib.adjustSize<PDG_AttributeFloat>(offset);
1216  return attrib.adjustSize<PDG_AttributeString>(offset);
1218  return attrib.adjustSize<PDG_AttributeFile>(offset);
1219  default:
1220  return false;
1221  }
1222 
1223  return true;
1224  }
1225 
1226  /// Clears an attribute
1227  static void attribClear(PDG_AttributeHolder& attrib)
1228  {
1229  switch (attrib.type())
1230  {
1232  attrib.clear<PDG_AttributeInteger>();
1233  break;
1235  attrib.clear<PDG_AttributeFloat>();
1236  break;
1238  attrib.clear<PDG_AttributeString>();
1239  break;
1241  attrib.clear<PDG_AttributeFile>();
1242  break;
1243  default:
1244  break;
1245  }
1246  }
1247 
1248  /// Saves the name of the specified attribute to the PDGT_Value variant.
1249  static bool attribToValue(PDGT_Value& value,
1250  int index,
1251  const PDG_AttributeHolder& holder)
1252  {
1253  switch (holder.type())
1254  {
1256  return attribToValue<PDG_AttributeFloat>(value, index, holder);
1258  return attribToValue<PDG_AttributeInteger>(value, index, holder);
1260  return attribToValue<PDG_AttributeString>(value, index, holder);
1262  {
1263  typename PDG_AttributeFile::Data temp;
1264  if (holder.attribute<PDG_AttributeFile>()->value(temp, index))
1265  value.setValue(temp.local_data());
1266  else
1267  value.setValue("");
1268  return true;
1269  }
1271  {
1272  UT_StringHolder str;
1273  if (holder.attribute<PDG_AttributePyObject>()->str(str))
1274  value.setValue(str);
1275  else
1276  value.setValue("");
1277  return true;
1278  }
1280  {
1281  UT_StringHolder str;
1282  if (holder.attribute<PDG_AttributeGeometry>()->desc(str))
1283  value.setValue(str);
1284  else
1285  value.setValue("");
1286  return true;
1287 
1288  }
1289  default:
1290  return false;
1291  }
1292 
1293  return false;
1294  }
1295 
1296  /// Helper method for storing an attribute value to a PDGT_Value variant.
1297  template <typename Attribute>
1298  static bool attribToValue(PDGT_Value& value,
1299  int index,
1300  const PDG_AttributeHolder& holder)
1301  {
1302  typename Attribute::Data temp;
1303  if (holder.attribute<Attribute>()->value(temp, index))
1304  value.setValue(temp);
1305  else
1306  value.setValue(typename Attribute::Data());
1307 
1308  return true;
1309  }
1310 
1311  /// Returns a const attribute holder an existing static or dynamic
1312  /// attribute. Uses the local context to determine if dynamic access
1313  /// is permitted.
1314  template <typename Attribute>
1315  const PDG_AttributeHolder*
1316  attribHolderR(const UT_StringHolder& name) const
1317  {
1320  AttribTable table = isRuntime(local_ctx) ? eTableDynamic : eTableStatic;
1321  return attribHolderR<Attribute>(error, name, table, true);
1322  }
1323 
1324  /// Returns an const attribute holder to an existing static or dynamic
1325  /// attribute. Does not create the attribute if it does not exist.
1326  template <typename Attribute>
1327  const PDG_AttributeHolder*
1328  attribHolderR(PDG_AttributeRef::Error& error,
1329  const UT_StringHolder& name,
1330  AttribTable table,
1331  bool check_parent) const
1332  {
1333  const PDG_AttributeHolder* holder = nullptr;
1334  for (int i = table; i >= 0; i--)
1335  {
1336  auto&& attrib = myAttributes[i].find(name);
1337  if (attrib != myAttributes[i].end())
1338  {
1339  holder = attrib->second.get();
1340  break;
1341  }
1342  }
1343 
1344  if (!holder)
1345  {
1346  if (myParentMap && check_parent)
1347  {
1348  return myParentMap->attribHolderR<Attribute>(
1349  error, name, table, true);
1350  }
1351 
1353  return nullptr;
1354  }
1355 
1356  if (!holder->typeMatch<Attribute>())
1357  {
1359  return nullptr;
1360  }
1361 
1363  return holder;
1364  }
1365 
1366  /// Returns an attribute holder for an existing or new attribute, either
1367  /// static or dynamic. If the attribute is static but we need a dynamic
1368  /// one, the existing static attribute is copied to the dynamic map.
1369  template <typename Attribute>
1370  PDG_AttributeHolder* attribHolderW(PDG_AttributeRef::Error& error,
1371  const UT_StringHolder& name,
1372  AttribTable table)
1373  {
1374  PDG_AttributeHolder* holder = nullptr;
1375  AttribTable src_table = eTableCount;
1376 
1377  // Check for the attribute in the desired table, and work downwards if
1378  // its not found
1379  for (int i = table; i >= 0; i--)
1380  {
1381  auto&& attrib = myAttributes[i].find(name);
1382  if (attrib != myAttributes[i].end())
1383  {
1384  holder = attrib->second.get();
1385  src_table = static_cast<AttribTable>(i);
1386  break;
1387  }
1388  }
1389 
1390  // If the attribute doesn't exist anywhere, check the parent map first
1391  // before returning an error.
1392  if (!holder)
1393  {
1394  // If a parent map is set, check for the attribute on the parent
1395  if (myParentMap)
1396  {
1397  const PDG_AttributeHolder* parent =
1398  attribHolderR<Attribute>(error, name, table, true);
1399 
1400  // We never create an attribute on the parent map, but if one
1401  // does exist make a copy of it and store it on this map.
1402  if (parent)
1403  {
1404  HolderPtr new_holder = UTmakeUnique<PDG_AttributeHolder>();
1405  new_holder->reset(*parent, parent->isOwner(), true);
1406  auto&& insert = myAttributes[table].emplace(
1407  name, std::move(new_holder));
1409  return insert.first->second.get();
1410  }
1411  }
1412 
1414  return nullptr;
1415  }
1416 
1417  // Read only attributes cannot be accessed for writing in any case
1418  if (holder->hasFlag(PDG_AttributeFlag::eReadOnlyFlag))
1419  {
1421  return nullptr;
1422  }
1423 
1424  // If the attribute exists in any of the tables but is the wrong type,
1425  // this is always an error.
1426  if (!holder->typeMatch<Attribute>())
1427  {
1429  return nullptr;
1430  }
1431 
1432  // If the attribute was found in a lower table than the one that was
1433  // requested, only create the attribute if the creation mode is
1434  // Always or Upgrade.
1435  if (src_table < table)
1436  {
1437  HolderPtr holder_copy = UTmakeUnique<PDG_AttributeHolder>();
1438  holder_copy->reset(*holder, holder->isOwner(), true);
1439 
1440  auto&& insert = myAttributes[table].emplace(
1441  name, std::move(holder_copy));
1443  return insert.first->second.get();
1444  }
1445 
1447  return holder;
1448  }
1449 
1450  /// Returns an attribute holder for an existing or new attribute, either
1451  /// static or dynamic. If the attribute is static but we need a dynamic
1452  /// one, the existing static attribute is copied to the dynamic map. This
1453  /// method will also create the attribute if needed, or if the type does
1454  /// not match, depending on the creation/overwrite options.
1455  template <typename Attribute>
1456  PDG_AttributeHolder* attribHolderC(PDG_AttributeRef::Error& error,
1457  const UT_StringHolder& name,
1458  CreateWhen create,
1459  OverwriteWhen overwrite,
1460  bool own,
1461  AttribTable table,
1462  uint16 flags)
1463  {
1464  PDG_AttributeHolder* holder = nullptr;
1465  AttribTable src_table = eTableCount;
1466 
1467  // Check for the attribute in the desired table, and work downwards if
1468  // its not found
1469  for (int i = table; i >= 0; i--)
1470  {
1471  auto&& attrib = myAttributes[i].find(name);
1472  if (attrib != myAttributes[i].end())
1473  {
1474  holder = attrib->second.get();
1475  src_table = static_cast<AttribTable>(i);
1476  break;
1477  }
1478  }
1479 
1480  // If the attribute doesn't exist anywhere, only create it when the
1481  // create mode is Always.
1482  if (!holder)
1483  {
1484  // If a parent map is set, check for the attribute on the parent
1485  if (myParentMap)
1486  {
1487  const PDG_AttributeHolder* parent =
1488  attribHolderR<Attribute>(error, name, table, true);
1489 
1490  // We never create an attribute on the parent map, but if one
1491  // does exist and we were request to upgrade if possible, make
1492  // a copy of it and store it on this map.
1493  if (parent)
1494  {
1495  if (create == eCreateNever)
1496  {
1498  return nullptr;
1499  }
1500 
1501  HolderPtr new_holder = UTmakeUnique<PDG_AttributeHolder>();
1502  new_holder->reset(*parent, parent->isOwner(), true);
1503 
1504  auto&& insert = myAttributes[table].emplace(
1505  name, std::move(new_holder));
1507  return insert.first->second.get();
1508  }
1509  }
1510 
1511  if (create != eCreateAlways)
1512  {
1514  return nullptr;
1515  }
1516 
1517  HolderPtr holder = UTmakeUnique<PDG_AttributeHolder>(
1518  own ? new Attribute() : nullptr,
1519  Attribute::TypeEnum,
1520  flags,
1521  own,
1522  false);
1523 
1524  auto&& insert = myAttributes[table].emplace(
1525  name, std::move(holder));
1527  return insert.first->second.get();
1528  }
1529 
1530  // If overwrite is off, we don't return back a holder
1531  if (overwrite == eOverwriteNever)
1532  {
1534  return nullptr;
1535  }
1536 
1537  // Read only attributes cannot be accessed for writing in any case
1538  if (holder->hasFlag(PDG_AttributeFlag::eReadOnlyFlag))
1539  {
1541  return nullptr;
1542  }
1543 
1544  // If the attribute exists in any of the tables but is the wrong type,
1545  // this is always an error.
1546  bool type_match = holder->typeMatch<Attribute>();
1547  if (!type_match && (overwrite != eOverwriteAlways))
1548  {
1550  return nullptr;
1551  }
1552 
1553  // If the attribute was found in a lower table than the one that was
1554  // requested, only create the attribute if the creation mode is
1555  // Always or Upgrade.
1556  if (src_table < table)
1557  {
1558  if (create == eCreateNever)
1559  {
1561  return nullptr;
1562  }
1563 
1564  HolderPtr holder_copy = UTmakeUnique<PDG_AttributeHolder>();
1565  if (!type_match)
1566  {
1567  holder_copy->reset(
1568  new Attribute(),
1569  Attribute::TypeEnum,
1570  flags,
1571  own,
1572  false,
1573  false);
1574  }
1575  else
1576  holder_copy->reset(*holder, holder->isOwner(), true);
1577 
1578  auto&& insert = myAttributes[table].emplace(
1579  name, std::move(holder_copy));
1581  return insert.first->second.get();
1582  }
1583 
1585  if (!type_match)
1586  {
1587  holder->reset(
1588  new Attribute(), Attribute::TypeEnum, flags, own, false, false);
1589  }
1590 
1591  return holder;
1592  }
1593 
1594 private:
1595  Map myAttributes[eTableCount];
1596  Map* myStaleAttributes;
1597  const PDG_AttributeOwner* myOwner;
1598  PDG_AttributeMap* myParentMap;
1599  mutable UT_RWLock myAttributeLock;
1600  bool myHasRuntimeAttribs;
1601 };
1602 
1603 #endif
A single, opaque PyObject.
GLbitfield flags
Definition: glcorearb.h:1596
PDG_RWAttributeRef< PDG_AttributeString > commandStringRW(CreateWhen create=eCreateNever, AttribTable table=eTableCount)
Returns a read/write handle to the standard input file attribute.
unsigned short uint16
Definition: SYS_Types.h:38
PDG_AttributeType type() const
Returns the attribute type.
PDG_AttributeRef::Error setValue(const UT_StringHolder &name, const typename Attribute::Array &values, bool create, OverwriteWhen overwrite=eOverwriteMatch)
bool desc(UT_StringHolder &str) const
bool hasFlag(PDG_AttributeFlag flag) const
Returns true if this attribute has the specified flag.
PDG_ROAttributeRef< PDG_AttributeString > labelRO(AttribTable table=eTableCount) const
bool adjustSize(int offset)
Sets the size of the attribute.
Never create the attribute, even if its not found.
static const UT_StringHolder theAddedFileName
static const uint16 theAddedFileFlags
Flags for the standard added file attribute.
PDG_AttributeRef::Error clearValues(const UT_StringHolder &name, bool create, OverwriteWhen overwrite=eOverwriteMatch)
OIIO_UTIL_API bool copy(string_view from, string_view to, std::string &err)
Attribute values were changed or added.
GLsizei const GLfloat * value
Definition: glcorearb.h:824
ScopedTryLock(const PDG_AttributeMap &attribute_map)
PDG_RWAttributeRef< PDG_AttributeFile > addedFileRW(CreateWhen create=eCreateNever, AttribTable table=eTableCount)
Returns a read/write handle to the standard input file attribute.
#define PDG_API
Definition: PDG_API.h:23
PDG_ROAttributeRef< PDG_AttributeString > stateRO(AttribTable table=eTableCount) const
static const UT_StringHolder thePseudoAttribName
PDG_AttributeRef::Error setValue(const UT_StringHolder &name, const typename Attribute::Data &value, int index, bool create, OverwriteWhen overwrite=eOverwriteMatch)
void clear()
Clears the attribute.
void swap(T &lhs, T &rhs)
Definition: pugixml.cpp:7172
std::size_t SYS_HashType
Define the type for hash values.
Definition: SYS_Hash.h:19
An array of UT_StringHolder values.
PDG_RWAttributeRef< PDG_AttributeFile > outputFileRW(CreateWhen create=eCreateNever, AttribTable table=eTableCount)
Returns a read-write handle to the standard output file attribute.
static const uint16 theCustomStateFlags
Flags for the standard custom state attribute.
PDG_AttributeRef::Error copyFrom(const UT_StringHolder &name, const PDG_ROAttributeRef< Attribute > &ref, bool overwrite_existing, bool deep_copy)
Copies the specified attribute into an attribute on this map.
bool hasFlags(uint16 flags) const
Returns true if this attribute has all of the specified flags set.
bool values(typename Attribute::Map &value_map, uint16 flags=0) const
Class which writes ASCII or binary JSON streams.
Definition: UT_JSONWriter.h:37
PDG_ROAttributeRef< PDG_AttributeString > commandStringRO(AttribTable table=eTableCount) const
const PDG_AttributeOwner * owner() const
Returns the attribute owner.
OIIO_FORCEINLINE vbool4 insert(const vbool4 &a, bool val)
Helper: substitute val for a[i].
Definition: simd.h:3436
The entire attribute map is read only.
static const UT_StringHolder theBuiltinPrefix
The requested attribute was not found - the ref is invalid.
bool value(typename Attribute::Data &value, const UT_StringHolder &name, int index, uint16 flags=0) const
No error was specified, i.e. the ref is valid.
static PDG_EvaluationContext * getContext()
Returns the thread-local PDG_EvaluationContext instance.
std::unique_ptr< T, Deleter > UT_UniquePtr
A smart pointer for unique ownership of dynamically allocated objects.
Definition: UT_UniquePtr.h:39
< returns > If no error
Definition: snippets.dox:2
PDG_ROAttributeRef< PDG_AttributeFile > addedFileRO(AttribTable table=eTableCount) const
Returns a read-only handle to the standard added file attribute.
ScopedLock(const PDG_AttributeMap &attribute_map)
const UT_StringHolder & local_data() const
Never overwrite the attribute.
static const UT_StringHolder theInputFileName
GLintptr offset
Definition: glcorearb.h:665
An array of PDG_File values, e.g. File info structs.
AttribTable
Enumeration of attribute tables.
PDG_RWAttributeRef< PDG_AttributeString > labelRW(CreateWhen create=eCreateNever, AttribTable table=eTableCount)
Returns a read/write handle to the standard work item label attribute.
PDG_RWAttributeRef< PDG_AttributeFloat > cookPercentRW(CreateWhen create=eCreateNever, AttribTable table=eTableCount)
GLboolean reset
Definition: glad.h:5138
void forEachRO(const Func &func) const
GLint ref
Definition: glcorearb.h:124
PDG_ROAttributeRef< PDG_AttributeFile > outputFileRO(AttribTable table=eTableCount) const
Returns a read-only handle to the standard output file attribute.
OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_ENTER class IMF_EXPORT_TEMPLATE_TYPE Array
Definition: ImfForward.h:22
static const UT_StringHolder theAllAttribName
void setValue(const PDGT_Value &value)
The requested attribute is static and was not upgraded to dynamic.
Flatten attributes, saving both dynamic and static as a mix.
PDG_ROAttributeRef< PDG_AttributeFloat > cookPercentRO(AttribTable table=eTableCount) const
Always create the attribute if it does not exist.
GLuint GLuint end
Definition: glcorearb.h:475
PDG_AttributeRef::Error rename(const UT_StringHolder &src_name, const UT_StringHolder &dst_name, bool overwrite)
Renames the specififed attribute.
bool value(typename Attribute::Array &value, const UT_StringHolder &name, uint16 flags=0) const
bool concat(const PDG_AttributeHolder &other)
Concats the specified attribute with the attribute in this holder.
The attribute is read-only and cannot be modified on this work item.
static const uint16 theCommandStringFlags
Flags for the standard command string attribute.
const PDG_AttributeHolder * holder() const
Returns the underlying attribute holder.
long long int64
Definition: SYS_Types.h:116
static const UT_StringHolder theLabelName
Name of the built-in human readable label attribute.
static const UT_StringHolder theCookPercentName
Name of the built-in cook percent attribute.
Number of attribute tables.
static const UT_StringHolder theOutputFileName
GLuint const GLchar * name
Definition: glcorearb.h:786
bool str(UT_StringHolder &str) const
GLushort pattern
Definition: glad.h:2583
PDG_AttributeFlag
Enumeration of extra attribute flags. Flags can be ORed together.
A single PDG_ApplicationShim::Geometry instance.
GLenum GLenum GLsizei void * table
Definition: glad.h:5129
static const UT_StringHolder thePartitionSizeName
Name of the built-in partition size attribute.
static const UT_StringHolder theCustomStateName
Name of the built-in custom state attribute.
static const uint16 theLabelFlags
Flags for the standard label attribute.
PDG_AttributeCollision
Definition: PDG_Types.h:528
bool tryLockedAccess(const Func &func) const
GLsizeiptr size
Definition: glcorearb.h:664
An array of fpreal values.
GLenum GLenum dst
Definition: glcorearb.h:1793
PDG_RWAttributeRef< Attribute > refRW(const UT_StringHolder &name, bool create, OverwriteWhen overwrite=eOverwriteMatch, uint16 flags=0)
GLenum func
Definition: glcorearb.h:783
PDG_AttributeType
Enumeration of possible attribute types.
GLenum GLsizei GLsizei GLint * values
Definition: glcorearb.h:1602
PDG_RWAttributeRef< PDG_AttributeString > stateRW(CreateWhen create=eCreateNever, AttribTable table=eTableCount)
PDG_RWAttributeRef< Attribute > refRW(const UT_StringHolder &name)
static const uint16 theInputFileFlags
Flags for the standard input file attribute.
static const uint16 theOutputFileFlags
Flags for the standard output file attribute.
bool value(DataType &data, int component) const
GLuint index
Definition: glcorearb.h:786
Only overwrite the attribute if the type matches.
Class to store JSON objects as C++ objects.
Definition: UT_JSONValue.h:99
OIIO_API bool attribute(string_view name, TypeDesc type, const void *val)
bool lockedAccess(const Func &func) const
SaveType
Save operation to perform.
Definition: core.h:1131
const Attribute * attribute() const
Const accessor for the own attribute - could be nullptr.
An array of int values.
PDG_RWAttributeRef< PDG_AttributeFile > inputFileRW(CreateWhen create=eCreateNever, AttribTable table=eTableCount)
Returns a read/write handle to the standard input file attribute.
PDG_ROAttributeRef< PDG_AttributeFile > inputFileRO(AttribTable table=eTableCount) const
Returns a read-only handle to the standard input file attribute.
PDG_RWAttributeRef< Attribute > refRWC(const UT_StringHolder &name, CreateWhen create=eCreateNever, OverwriteWhen overwrite=eOverwriteMatch, AttribTable table=eTableCount, bool allow_internal_names=false, uint16 flags=0)
Same as above, but with greater control on the creation flags.
ChangeResult
Enumeration of possible attribute change results during regeneration.
PDG_ROAttributeRef< Attribute > refRO(const UT_StringHolder &name, AttribTable table=eTableCount) const
static bool makeValidName(UT_StringHolder &name, const UT_StringHolder &str, bool allow_internal=false)
Reader/Writer mutex class.
Definition: UT_RWLock.h:48
type
Definition: core.h:1059
class IMF_EXPORT_TYPE Attribute
Definition: ImfForward.h:29
static const UT_StringHolder theCommandStringName
Name of the built-in command attribute.
Definition: format.h:895
FMT_CONSTEXPR auto find(Ptr first, Ptr last, T value, Ptr &out) -> bool
Definition: core.h:2089
GLint GLint GLint GLint GLint GLint GLint GLbitfield GLenum filter
Definition: glcorearb.h:1297
GLenum src
Definition: glcorearb.h:1793