HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
PDG_AttributeRef.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_REF_H__
10 #define __PDG_ATTRIBUTE_REF_H__
11 
12 #include "PDG_API.h"
13 
14 #include "PDG_AttributeData.h"
16 #include "PDG_AttributeFile.h"
17 #include "PDG_AttributeGeometry.h"
18 #include "PDG_AttributeHolder.h"
19 #include "PDG_AttributePrimitive.h"
20 #include "PDG_AttributePyObject.h"
21 #include "PDG_AttributeQuery.h"
22 #include "PDG_AttributeTypes.h"
23 
24 #include <UT/UT_Options.h>
25 #include <UT/UT_StringHolder.h>
26 #include <UT/UT_WorkBuffer.h>
27 
28 #include <SYS/SYS_Hash.h>
29 
30 class PDG_AttributeOwner;
31 class PDG_Node;
32 class PDG_Scheduler;
33 
34 /**
35  * Base class for attribute references
36  */
38 {
39 public:
41  const PDG_AttributeOwner* owner,
44  : myName(name)
45  , myOwner(owner)
46  , myError(error)
47  {
48  }
49 
50  /// Returns true if the handle is valid
51  inline operator bool() const
52  { return isValid(); }
53 
54  /// Returns true if the handle is valid
55  inline bool isValid() const
56  { return (myError == PDG_AttributeError::eNone);}
57 
58  /// Returns the error state of the handle
59  inline PDG_AttributeError error() const
60  { return myError; }
61 
62  /// Returns the name of the attribute referenced by this attrib ref
63  inline const UT_StringHolder&
64  name() const
65  { return myName; }
66 
67  /// Returns the PDG_AttributeOwner that owns the underlying attribute
68  const PDG_AttributeOwner* owner() const
69  { return myOwner; }
70 
71  /// Returns false and Writes an attribute error message into the buffer if
72  /// an error exists, or returns trues and does not modify the buffer if no
73  /// error has been recorded.
74  bool validate(UT_WorkBuffer& buffer) const;
75 
76  /// Same as above, except the attribute error is reported on the specified
77  /// node instead of returned as a buffer, if an error has occured. The
78  /// method still returns true if no error has occured, and false if one
79  /// has.
80  ///
81  /// The report_errors argument is provided as a convenience, to make it
82  /// possible to parametrically skip error reporting
83  bool validate(
84  const PDG_Node* node,
86 
87  /// Writes an attribute error format message to the buffer, based on the
88  /// supply error, attrib name and optional work item. Returns True if no
89  /// error is detected, or false if an error occured.
90  static bool attributeError(
93  const UT_StringHolder& attrib_name,
94  const PDG_AttributeOwner* owner=nullptr);
95 
96  /// Emits events when the attribute is modified
97  static void attributeModified(
98  const PDG_AttributeOwner* owner,
99  PDG_AttributeType attrib_type,
100  const UT_StringHolder& attrib_name);
101 
102  /// Localizes a path with the specified scheduler
103  static UT_StringHolder localizePath(
104  const UT_StringHolder& path,
105  const PDG_Scheduler* scheduler);
106 
107 protected:
111 };
112 
113 /**
114  * Base class for templated attribute references
115  */
116 template <typename Attribute, typename Holder>
118 {
119 public:
121 
122 public:
123  explicit PDG_AttributeRefT(Holder* holder,
124  const UT_StringHolder& name,
125  const PDG_AttributeOwner* owner,
128  : PDG_AttributeRef(name, owner, error)
129  , myHolder(holder)
130  {
131  }
132 
133  /// Returns the underlying attribute holder
134  inline Holder* holder() const
135  {
136  return myHolder;
137  }
138 
139  /// Returns a const pointer to the underlying attribute instance
140  inline const Attribute* attribute() const
141  {
142  return myHolder->template attribute<const Attribute>();
143  }
144 
145  /// Returns a const pointer to the underlying attribute instance,
146  /// casted to the specified type
147  template <typename T> const T* attributeT() const
148  {
149  return myHolder->template attribute<const T>();
150  }
151 
152  /// Returns a const pointer to the underlying attribute instance
153  inline const Attribute* operator->() const
154  {
155  return attribute();
156  }
157 
158  /// Returns true if the contained attribute has any data
159  inline bool hasData() const
160  {
161  return myHolder->template hasData<Attribute>();
162  }
163 
164  /// Returns true if the contained attribute holder owns its data
165  inline bool isOwner() const
166  {
167  return myHolder->isOwner();
168  }
169 
170  /// Returns the type of the contained attribute
171  inline PDG_AttributeType type() const
172  {
173  return myHolder->type();
174  }
175 
176  /// Returns the flags on the contained holder
177  inline uint16 flags() const
178  {
179  return myHolder->flags();
180  }
181 
182  /// Returns true if the contained holder has any flags set
183  inline bool hasAnyFlags() const
184  {
185  return myHolder->hasAnyFlags();
186  }
187 
188  /// Returns true if the contained holder has the specified flag set
189  inline bool hasFlag(PDG_AttributeFlag flag) const
190  {
191  return myHolder->hasFlag(flag);
192  }
193 
194  /// Returns true if the contained holder has all of the specified flags set
195  inline bool hasFlags(uint16 flags) const
196  {
197  return myHolder->hasFlags(flags);
198  }
199 
200  /// Returns true if the contained holder has any of the specified flags set
201  inline bool hasAnyFlags(uint16 flags) const
202  {
203  return myHolder->hasAnyFlags(flags);
204  }
205 
206  /// Returns true if the attribute is numeric
207  inline bool isNumeric() const
208  {
209  return (myHolder->type() == PDG_AttributeType::eIntegerArray) ||
210  (myHolder->type() == PDG_AttributeType::eFloatArray);
211  }
212 
213  /// Returns true if the attribute is an array
214  inline bool isArray() const
215  {
216  return PDG_AttributeData::isArrayType(myHolder->type());
217  }
218 
219  /// Returns a hash of the name, flags and values of the attribute
220  inline bool hash(
222  exint index,
223  bool include_value,
224  bool include_name,
225  bool include_flags,
226  UT_WorkBuffer& errors) const
227  {
228  result = 0;
229 
230  if (include_name)
231  SYShashCombine(result, myName);
232 
233  if (include_value)
234  {
235  SYS_HashType attrib_hash = 0;
236  if (!attribute()->hash(attrib_hash, index, errors))
237  return false;
238 
239  SYShashCombine(result, attrib_hash);
240  }
241 
242  if (include_flags)
243  SYShashCombine(result, flags());
244 
245  return true;
246  }
247 
248  /// Casts the value contained in the attribute at the particular index to a
249  /// numeric value, by looking up the value with the query string. Falls
250  /// a regular cast if query strings aren't supported
252  exint& query_index,
253  const PDG_AttributeQuery& query,
254  int index,
255  bool has_component) const
256  {
257  if (myHolder->type() == PDG_AttributeType::ePythonObject)
258  {
259  if (!has_component)
260  index = -1;
261  return myHolder->template attribute<PDG_AttributePyObject>()->query(
262  number, query, index);
263  }
264  else if (myHolder->type() == PDG_AttributeType::eDictArray)
265  {
266  if (!has_component)
267  index = 0;
268  return myHolder->template attribute<PDG_AttributeDictionary>()->query(
269  number, query, query_index, index);
270  }
271 
272  return asNumber(number, index);
273  }
274 
275  /// Casts the value contained in the attribute at the particular index to a
276  /// numeric value, if possible.
277  inline PDG_AttributeCast asNumber(fpreal& number, int index) const
278  {
279  if (myHolder->type() == PDG_AttributeType::eIntegerArray)
280  {
282  if (myHolder->template attribute<PDG_AttributeInteger>()->value(
283  temp, index))
284  {
285  number = temp;
287  }
288 
290  }
291  else if (myHolder->type() == PDG_AttributeType::eFloatArray)
292  {
293  if (myHolder->template attribute<PDG_AttributeFloat>()->value(
294  number, index))
295  {
297  }
298 
300  }
301 
303  }
304 
305  /// Casts the value contained in the attribute to a numeric array, if
306  /// possible.
307  template <typename Array>
308  inline PDG_AttributeCast asNumbers(Array& array) const
309  {
310  if (myHolder->type() == PDG_AttributeType::eIntegerArray)
311  {
312  auto&& attr = myHolder->template attribute<PDG_AttributeInteger>();
313  for (exint i = 0; i < attr->size(); i++)
314  array.append(attr->value(i));
316  }
317  else if (myHolder->type() == PDG_AttributeType::eFloatArray)
318  {
319  auto&& attr = myHolder->template attribute<PDG_AttributeFloat>();
320  for (exint i = 0; i < attr->size(); i++)
321  array.append(attr->value(i));
323  }
324 
326  }
327 
328  /// Returns a file path from the attribute, using the specified index and
329  /// tag filter. If a scheduler is supplied, the path is localized with the
330  /// scheduler. Only valid for files and strings. For string attributes the
331  /// tag is ignored and assumed to match
334  int index,
335  const UT_StringHolder& tag,
336  const PDG_Scheduler* scheduler,
337  bool localize)
338  {
339  if (myHolder->type() == PDG_AttributeType::eStringArray)
340  {
341  if (!myHolder->template attribute<PDG_AttributeString>()->value(
342  path, index))
343  {
345  }
346 
347  if (localize)
348  path = localizePath(path, scheduler);
349 
351  }
352  else if (myHolder->type() == PDG_AttributeType::eFileArray)
353  {
354  PDG_File file;
356  myHolder->template attribute<PDG_AttributeFile>()->valueForTag(
357  file, index, tag);
358  if (result != PDG_AttributeCast::eSuccess)
359  return result;
360 
361  if (localize)
362  path = file.localizePath(scheduler);
363  else
364  path = file.data();
365 
367  }
368 
370  }
371 
372  /// Returns a space-separate string of file path(s) from the attribute,
373  /// using all values in the attribute and the specified tag filter. If a
374  /// scheduler is supplied, the paths are localized with the scheduler. Only
375  /// valid for files and strings. For string attributes the tag is ignored
376  /// and assumed to match
379  const UT_StringHolder& tag,
380  const PDG_Scheduler* scheduler,
381  bool localize)
382  {
383  if (myHolder->type() == PDG_AttributeType::eStringArray)
384  {
385  auto&& values = myHolder->template
386  attribute<PDG_AttributeString>()->values();
387  for (auto&& value : values)
388  {
390  if (localize)
391  path = localizePath(value, scheduler);
392  else
393  path = value;
394 
395  UT_String wrap(path);
396  wrap.protectString();
397  buffer.appendSprintf("%s ", wrap.buffer());
398  }
399 
400  buffer.removeTrailingSpace();
402  }
403  else if (myHolder->type() == PDG_AttributeType::eFileArray)
404  {
405  auto&& values = myHolder->template
406  attribute<PDG_AttributeFile>()->values();
407  for (auto&& value : values)
408  {
410  if (localize)
411  path = value.localizePath(scheduler);
412  else
413  path = value.data();
414 
415  UT_String wrap(path);
416  wrap.protectString();
417  buffer.appendSprintf("%s ", wrap.buffer());
418  }
419 
420  buffer.removeTrailingSpace();
422  }
423 
425  }
426 
427  /// Casts the value contained in the attribute to a PDG_File object. Only
428  /// valid for string, file and PyObject attribute types
430  PDG_File& file,
431  int index,
432  const UT_StringHolder& tag =
434  PDG_File::Hash hash = 0,
435  bool own = false) const
436  {
437  UT_StringHolder file_path;
438  UT_StringHolder file_tag = tag;
439  PDG_File::Hash file_hash = hash;
440 
441  switch (myHolder->type())
442  {
444  {
445  if (!myHolder->template attribute<PDG_AttributePyObject>()->str(
446  file_path))
447  {
449  }
450 
451  break;
452  }
453 
455  {
456  if (!myHolder->template attribute<PDG_AttributeString>()->value(
457  file_path, index))
458  {
460  }
461 
462  break;
463  }
464 
466  {
468  if (myHolder->template attribute<PDG_AttributeFile>()->value(
469  temp, index))
470  {
471  file_path = temp.data();
472 
473  if (file_tag.isEmpty())
474  file_tag = temp.tag();
475 
476  if (!file_hash)
477  file_hash = temp.hash();
478 
479  break;
480  }
481 
483  }
484 
485  default:
487  }
488 
489  file = PDG_File(file_path, file_tag, file_hash, own);
491  }
492 
493  /// Casts the value contained in the attribute at the particular index to a
494  /// string value, by looking up the value with the query string. Falls
495  /// a regular cast if query strings aren't supported
497  exint& query_index,
498  const PDG_AttributeQuery& query,
499  int index,
500  int pad,
501  bool has_component) const
502  {
503  if (myHolder->type() == PDG_AttributeType::ePythonObject)
504  {
505  if (!has_component)
506  index = -1;
507  return myHolder->template attribute<PDG_AttributePyObject>()->query(
508  buffer, query, index);
509  }
510  else if (myHolder->type() == PDG_AttributeType::eDictArray)
511  {
512  if (!has_component)
513  index = 0;
514  return myHolder->template attribute<PDG_AttributeDictionary>()->query(
515  buffer, query, query_index, index);
516  }
517 
518  return asString(buffer, index, pad);
519  }
520 
521  /// Casts the value contained in the attribute at the particular index to a
522  /// string value, if possible.
524  int index,
525  int pad=0) const
526  {
527  switch (myHolder->type())
528  {
530  {
532  if (myHolder->template attribute<PDG_AttributeInteger>()->value(
533  temp, index))
534  {
535  buffer.sprintf("%0*" SYS_PRId64, pad, temp);
537  }
539  }
540 
542  {
544  if (myHolder->template attribute<PDG_AttributeFloat>()->value(
545  temp, index))
546  {
547  // If a padding was specified, round to the nearest int and
548  // pad the integer value. This is the same behavior as the
549  // padzero() HScript function. Otherwise, format the value
550  // as-is.
551  if (pad > 0)
552  buffer.sprintf("%0*d", pad, (int)SYSrint(temp));
553  else
554  buffer.sprintf("%g", temp);
556  }
558  }
559 
561  {
563  if (myHolder->template attribute<PDG_AttributeString>()->value(
564  temp, index))
565  {
566  buffer.sprintf("%s", temp.c_str());
568  }
570  }
571 
573  {
575  if (myHolder->template attribute<PDG_AttributeFile>()->value(
576  temp, index))
577  {
578  buffer.sprintf("%s", temp.data().c_str());
580  }
582  }
583 
585  {
586  if (myHolder->template attribute<PDG_AttributeDictionary>()->desc(
587  buffer, index, false))
588  {
590  }
591 
593  }
594 
596  {
597  UT_StringHolder temp;
598  if (myHolder->template attribute<PDG_AttributePyObject>()->str(
599  temp))
600  {
601  buffer.sprintf("%s", temp.c_str());
603  }
605  }
606 
607  default:
609  }
610  }
611 
612  /// Casts the value contained in the attribute to a string array, if
613  /// possible.
615  {
617  switch (myHolder->type())
618  {
620  {
621  auto&& attr =
622  myHolder->template attribute<PDG_AttributeInteger>();
623 
624  for (exint i = 0; i < attr->size(); i++)
625  {
626  buffer.format("{}", attr->value(i));
627  array.append(buffer.buffer());
628  }
629 
631  }
632 
634  {
635  auto&& attr =
636  myHolder->template attribute<PDG_AttributeFloat>();
637 
638  for (exint i = 0; i < attr->size(); i++)
639  {
640  buffer.format("{}", attr->value(i));
641  array.append(buffer.buffer());
642  }
643 
645  }
646 
648  {
649  auto&& attr =
650  myHolder->template attribute<PDG_AttributeString>();
651 
652  for (exint i = 0; i < attr->size(); i++)
653  array.append(attr->value(i));
654 
656  }
657 
659  {
660  auto&& attr =
661  myHolder->template attribute<PDG_AttributeFile>();
662 
663  for (exint i = 0; i < attr->size(); i++)
664  array.append(attr->value(i).data());
665 
667  }
668 
670  {
671  auto&& attr =
672  myHolder->template attribute<PDG_AttributeDictionary>();
673 
674  for (exint i = 0; i < attr->size(); i++)
675  {
676  attr->desc(buffer, i, false);
677  array.append(buffer.buffer());
678  }
679 
681  }
682 
683  default:
684  break;
685  }
686 
688  }
689 
690  /// Prints the values contained in the attribute to space-separated string
692  int pad=0) const
693  {
694  switch (myHolder->type())
695  {
697  {
698  auto&& values = myHolder->template
699  attribute<PDG_AttributeInteger>()->values();
700  for (auto&& value : values)
701  buffer.appendSprintf("%0*" SYS_PRId64 " ", pad, value);
702  buffer.removeTrailingSpace();
704  }
705 
707  {
708  auto&& values = myHolder->template
709  attribute<PDG_AttributeFloat>()->values();
710  for (auto&& value : values)
711  {
712  // If a padding was specified, round to the nearest int and
713  // pad the integer value. This is the same behavior as the
714  // padzero() HScript function. Otherwise, format the value
715  // as-is.
716  if (pad > 0)
717  buffer.appendSprintf("%0*d ", pad, (int)SYSrint(value));
718  else
719  buffer.appendSprintf("%g ", value);
720  }
721 
722  buffer.removeTrailingSpace();
724  }
725 
727  {
728  auto&& values = myHolder->template
729  attribute<PDG_AttributeString>()->values();
730  for (auto&& value : values)
731  {
732  UT_String wrap(value);
733  wrap.protectString();
734  buffer.appendSprintf("%s ", wrap.buffer());
735  }
736 
737  buffer.removeTrailingSpace();
739  }
740 
742  {
743  auto&& values = myHolder->template
744  attribute<PDG_AttributeFile>()->values();
745  for (auto&& value : values)
746  {
747  UT_String wrap(value.data());
748  wrap.protectString();
749  buffer.appendSprintf("%s ", wrap.buffer());
750  }
751 
752  buffer.removeTrailingSpace();
754  }
755 
757  {
758  if (myHolder->template attribute<PDG_AttributeDictionary>()->desc(
759  buffer))
760  {
762  }
764  }
765 
767  {
769  if (myHolder->template attribute<PDG_AttributePyObject>()->str(
770  value))
771  {
772  UT_String wrap(value);
773  wrap.protectString();
774  buffer.appendSprintf("%s", wrap.buffer());
776  }
778  }
779 
780  default:
782  }
783  }
784 
785  /// Imports the attribute data in the ref into a UT_Options instance
786  /// using the name of this attribute as the key string
788  UT_Options& options,
789  PDG_AttributeOverwrite overwrite) const
790  {
791  return asOptions(options, myName, overwrite);
792  }
793 
794  /// Imports the attribute data in the ref into an UT_Options instance
795  /// using the specified key string
797  UT_Options& options,
798  const UT_StringHolder& key,
799  PDG_AttributeOverwrite overwrite) const
800  {
801  UT_OptionType existing_type = options.getOptionType(key);
802  if ((existing_type != UT_OPTION_INVALID) &&
803  (overwrite == PDG_AttributeOverwrite::eNever))
804  {
806  }
807 
808  switch (myHolder->type())
809  {
811  {
812  if (overwrite == PDG_AttributeOverwrite::eAlways ||
813  existing_type == UT_OPTION_INVALID ||
814  existing_type == UT_OPTION_INT ||
815  existing_type == UT_OPTION_INTARRAY)
816  {
817  auto&& attr =
818  myHolder->template attribute<PDG_AttributeInteger>();
819  if (attr->size() == 1)
820  options.setOptionI(key, attr->value(0));
821  else
822  options.setOptionIArray(key, attr->values());
823  }
824 
826  }
827 
829  {
830  if (overwrite == PDG_AttributeOverwrite::eAlways ||
831  existing_type == UT_OPTION_INVALID ||
832  existing_type == UT_OPTION_FPREAL ||
833  existing_type == UT_OPTION_FPREALARRAY ||
834  existing_type == UT_OPTION_VECTOR2 ||
835  existing_type == UT_OPTION_VECTOR3 ||
836  existing_type == UT_OPTION_VECTOR4 ||
837  existing_type == UT_OPTION_QUATERNION ||
838  existing_type == UT_OPTION_MATRIX3 ||
839  existing_type == UT_OPTION_MATRIX4 ||
840  existing_type == UT_OPTION_UV ||
841  existing_type == UT_OPTION_UVW)
842  {
843  auto&& attr =
844  myHolder->template attribute<PDG_AttributeFloat>();
845  if (attr->size() == 1)
846  options.setOptionF(key, attr->value(0));
847  else
848  {
849  options.setOptionFArray(
850  key, attr->values().data(), attr->size());
851  }
852  }
853 
855  }
856 
858  {
859  if (overwrite == PDG_AttributeOverwrite::eAlways ||
860  existing_type == UT_OPTION_INVALID ||
861  existing_type == UT_OPTION_STRING ||
862  existing_type == UT_OPTION_STRINGARRAY)
863  {
864  auto&& attr =
865  myHolder->template attribute<PDG_AttributeString>();
866  if (attr->size() == 1)
867  options.setOptionS(key, attr->value(0));
868  else
869  options.setOptionSArray(key, attr->values());
870  }
871 
873  }
874 
876  {
877  if (overwrite == PDG_AttributeOverwrite::eAlways ||
878  existing_type == UT_OPTION_INVALID ||
879  existing_type == UT_OPTION_STRING ||
880  existing_type == UT_OPTION_STRINGARRAY)
881  {
882  auto&& attr =
883  myHolder->template attribute<PDG_AttributeFile>();
884  if (attr->size() == 1)
885  options.setOptionS(key, attr->value(0).data());
886  else
887  {
888  UT_StringArray values(attr->size());
889  for (auto&& value : attr->values())
890  values.append(value.data());
891  options.setOptionSArray(key, values);
892  }
893  }
894 
896  }
897 
899  {
900  if (overwrite == PDG_AttributeOverwrite::eAlways ||
901  existing_type == UT_OPTION_INVALID ||
902  existing_type == UT_OPTION_DICT ||
903  existing_type == UT_OPTION_DICTARRAY)
904  {
905  auto&& attr =
906  myHolder->template attribute<PDG_AttributeDictionary>();
907  if (attr->size() == 1)
908  options.setOptionDict(key, attr->value(0));
909  else
910  options.setOptionDictArray(key, attr->values());
911  }
912 
914  }
915 
916  default:
918  }
919  }
920 
921  /// Returns the size of the data stored in the attribute
922  inline int size() const
923  {
924  switch (myHolder->type())
925  {
927  {
928  return myHolder->template attribute<
930  }
931 
933  {
934  return myHolder->template attribute<
935  PDG_AttributeFloat>()->size();
936  }
937 
939  {
940  return myHolder->template attribute<
942  }
943 
945  {
946  return myHolder->template attribute<
947  PDG_AttributeFile>()->size();
948  }
949 
951  {
952  return myHolder->template attribute<
954  }
955 
957  {
958  return myHolder->template attribute<
960  }
961 
963  {
964  return myHolder->template attribute<
966  }
967 
968  default:
969  return 0;
970  }
971  }
972 
973 protected:
974  Holder* myHolder;
975 };
976 
977 /**
978  * Read-only, const attribute ref
979  */
980 template <typename Attribute>
982  public PDG_AttributeRefT<Attribute, const PDG_AttributeHolder>
983 {
984 public:
986  using Base::Base;
987 };
988 
989 /**
990  * Read/write attribute ref that permits modifications of holder flags as
991  * well as non-const access to the underlying data. Accessing the attribute
992  * using either the named accessor or the -> overload will result in a deep
993  * copy + ownership being taken, if the data is not already owned by the
994  * holder.
995  */
996 template <typename Attribute>
998  public PDG_AttributeRefT<Attribute, PDG_AttributeHolder>
999 {
1000 public:
1003 
1004  /// Constructs an uninitialized RW ref
1006  const PDG_AttributeOwner* owner)
1007  : Base(nullptr, name, owner, PDG_AttributeError::eUninitialized)
1008  , myModified(false)
1009  {
1010  }
1011 
1012  /// Constructs a ref that can modify attribute data. We store the work
1013  /// item so we can emit events.
1015  const UT_StringHolder& name,
1016  const PDG_AttributeOwner* owner,
1019  : Base(holder, name, owner, error)
1020  , myModified(false)
1021  {
1022  }
1023 
1024  /// Explicitly defined copy constructor, since we don't want to copy the
1025  /// myModified flag from the source reference. Doing so would mean that
1026  /// we'd potentially by emitting an extra data change event on destruction.
1027  PDG_RWAttributeRef(const Self& other)
1028  : Base(other)
1029  , myModified(false)
1030  {
1031  }
1032 
1033  /// Explicitly defined move constructor, since a copy constructor has been
1034  /// defined. When moving a ref we do want to preserve the myModified flag,
1035  /// unlike in the copy constructor.
1037  : Base(std::move(other))
1038  , myModified(other.myModified)
1039  {
1040  other.myModified = false;
1041  }
1042 
1043  /// Emits data changed events if this attribute ref recorded a modification
1045  {
1046  emitEvents();
1047  }
1048 
1049  /// Explicitly defined copy assignment operator, since the copy constructor
1050  /// is defined.
1051  Self& operator=(const Self& other)
1052  {
1053  if (this != &other)
1054  {
1055  emitEvents();
1056 
1057  myModified = false;
1058  Base::operator=(other);
1059  }
1060 
1061  return *this;
1062  }
1063 
1064  /// Explicitly defined move assignment operator, since the move constructor
1065  /// is defined.
1066  Self& operator=(Self&& other)
1067  {
1068  if (this != &other)
1069  {
1070  emitEvents();
1071 
1072  myModified = other.myModified;
1073  other.myModified = false;
1074 
1075  Base::operator=(std::move(other));
1076  }
1077 
1078  return *this;
1079  }
1080 
1081  /// Emits pending events from the ref
1082  inline void emitEvents()
1083  {
1084  if (Base::myOwner && myModified)
1085  Base::attributeModified(Base::myOwner, Base::type(), Base::myName);
1086 
1087  myModified = false;
1088  }
1089 
1090  /// Clears any pending events
1091  inline void clearEvents()
1092  {
1093  myModified = false;
1094  }
1095 
1096  /// Returns a non-const pointer to the underlying attribute instance. This
1097  /// induces a copy if the attribute is not already owned, and counts as a
1098  /// modification for the purpose of event handling.
1100  {
1101  Base::myHolder->own();
1102  Base::myHolder->setIsChanged(true);
1103 
1104  myModified = true;
1105  return Base::myHolder->template attribute<Attribute>();
1106  }
1107 
1108  /// Returns a non-const pointer to the underlying attribute instance
1110  {
1111  return attribute();
1112  }
1113 
1114  /// Sets the specific flag on or off, based on the set arugment, an
1115  /// returns whether or not the flag was changed.
1116  inline PDG_AttributeError
1118  bool set,
1119  bool& changed)
1120  {
1121  if (!Base::isValid())
1122  return Base::error();
1123 
1124  if (Base::myOwner && !Base::myOwner->isAttribFlagValid(flag))
1126 
1127  changed = Base::myHolder->setFlag(flag, set);
1129  }
1130 
1131  /// Sets the specific flag on or off
1132  inline PDG_AttributeError
1134  {
1135  bool discard;
1136  return setFlag(flag, set, discard);
1137  }
1138 
1139  /// Directly sets the flag bits to the specified flags
1140  inline PDG_AttributeError
1141  setFlags(uint16 flags, bool& changed)
1142  {
1143  if (!Base::isValid())
1144  return Base::error();
1145 
1146  if (Base::myOwner && !Base::myOwner->areAttribFlagsValid(flags))
1148 
1149  changed = Base::myHolder->setFlags(flags);
1151  }
1152 
1153  /// Sets all flags
1154  inline PDG_AttributeError
1156  {
1157  bool discard;
1158  return setFlags(flags, discard);
1159  }
1160 
1161  /// Truncates the array stored in the attribute
1162  inline void truncate(int length)
1163  {
1164  switch (Base::myHolder->type())
1165  {
1167  {
1168  return Base::myHolder->template attribute<
1169  PDG_AttributeInteger>()->truncate(length);
1170  }
1171 
1173  {
1174  return Base::myHolder->template attribute<
1175  PDG_AttributeFloat>()->truncate(length);
1176  }
1177 
1179  {
1180  return Base::myHolder->template attribute<
1181  PDG_AttributeString>()->truncate(length);
1182  }
1183 
1185  {
1186  return Base::myHolder->template attribute<
1187  PDG_AttributeFile>()->truncate(length);
1188  }
1189 
1191  {
1192  return Base::myHolder->template attribute<
1193  PDG_AttributeDictionary>()->truncate(length);
1194  }
1195 
1196  default:
1197  return;
1198  }
1199  }
1200 
1201 private:
1202  bool myModified;
1203 };
1204 
1205 #endif
type
Definition: core.h:556
PDG_AttributeError
GLenum query
Definition: glad.h:2772
UT_OptionType getOptionType(const UT_StringRef &name) const
GLbitfield flags
Definition: glcorearb.h:1596
Definition: ImfArray.h:45
unsigned short uint16
Definition: SYS_Types.h:38
const T * attributeT() const
PDG_AttributeError setFlags(uint16 flags)
Sets all flags.
static UT_StringHolder localizePath(const UT_StringHolder &path, const PDG_Scheduler *scheduler)
Localizes a path with the specified scheduler.
Never overwrite the attribute.
bool isOwner() const
Returns true if the contained attribute holder owns its data.
GLsizei const GLfloat * value
Definition: glcorearb.h:824
UT_Options & setOptionDictArray(const UT_StringHolder &name, const UT_OptionsHolder *values, size_t size)
Set dict array options.
const UT_StringHolder & name() const
Returns the name of the attribute referenced by this attrib ref.
#define PDG_API
Definition: PDG_API.h:23
GLsizei const GLchar *const * path
Definition: glcorearb.h:3341
bool isEmpty() const
Same as !isstring()
UT_OptionType
Definition: UT_Options.h:44
bool isArray() const
Returns true if the attribute is an array.
int64 exint
Definition: SYS_Types.h:125
GLint level
Definition: glcorearb.h:108
SYS_FORCE_INLINE const char * buffer() const
Attribute * attribute()
std::size_t SYS_HashType
Define the type for hash values.
Definition: SYS_Hash.h:19
GLuint GLsizei GLsizei * length
Definition: glcorearb.h:795
PDG_RWAttributeRef(PDG_AttributeHolder *holder, const UT_StringHolder &name, const PDG_AttributeOwner *owner, PDG_AttributeError error=PDG_AttributeError::eNone)
PDG_AttributeError setFlag(PDG_AttributeFlag flag, bool set, bool &changed)
**But if you need a result
Definition: thread.h:622
PDG_AttributeRefT(Holder *holder, const UT_StringHolder &name, const PDG_AttributeOwner *owner, PDG_AttributeError error=PDG_AttributeError::eNone)
GLuint buffer
Definition: glcorearb.h:660
OutGridT const XformOp bool bool
bool hash(SYS_HashType &result, exint index, bool include_value, bool include_name, bool include_flags, UT_WorkBuffer &errors) const
Returns a hash of the name, flags and values of the attribute.
SYS_FORCE_INLINE const char * data() const
void pad(T &out, int n)
Definition: ImfXdr.h:407
< returns > If no error
Definition: snippets.dox:2
UT_Options & setOptionIArray(const UT_StringHolder &name, const int32 *values, size_t size)
PDG_AttributeOverwrite
~PDG_RWAttributeRef()
Emits data changed events if this attribute ref recorded a modification.
bool hasAnyFlags(uint16 flags) const
Returns true if the contained holder has any of the specified flags set.
Cast failed due to a type mismatch (string vs. int)
bool hasFlag(PDG_AttributeFlag flag) const
Returns true if the contained holder has the specified flag set.
const char * buffer() const
Definition: UT_String.h:516
UT_Options & setOptionSArray(const UT_StringHolder &name, const UT_StringHolder *values, size_t size)
Set string array options.
A single PDG_ApplicationShim::Geometry instance.
Hash hash() const
Definition: PDG_File.h:102
No error was specified, i.e. the ref is valid.
void truncate(int length)
Truncates the array stored in the attribute.
PDG_AttributeErrorLevel
int64 Hash
The file hash/modtime type.
Definition: PDG_File.h:39
bool removeTrailingSpace()
Remove trailing whitespace, return true if whitespace was removed.
UT_Options & setOptionI(const UT_StringHolder &name, int64 value)
UT_StringHolder myName
PDG_AttributeCast asString(UT_WorkBuffer &buffer, exint &query_index, const PDG_AttributeQuery &query, int index, int pad, bool has_component) const
const UT_StringHolder & tag() const
Definition: PDG_File.h:99
UT_StringHolder localizePath(const PDG_Scheduler *scheduler) const
Updates and return the local_path.
bool hasAnyFlags() const
Returns true if the contained holder has any flags set.
void clearEvents()
Clears any pending events.
constexpr auto set(type rhs) -> int
Definition: core.h:610
static const UT_StringHolder theEmptyString
PDG_AttributeCast
Enumeration of attribute cast results.
PDG_AttributeCast asOptions(UT_Options &options, const UT_StringHolder &key, PDG_AttributeOverwrite overwrite) const
Attribute * operator->()
Returns a non-const pointer to the underlying attribute instance.
PDG_AttributeCast asNumber(fpreal &number, int index) const
PDG_AttributeCast asFile(PDG_File &file, int index, const UT_StringHolder &tag=UT_StringHolder::theEmptyString, PDG_File::Hash hash=0, bool own=false) const
bool hasData() const
Returns true if the contained attribute has any data.
#define PDG_API_TMPL
Definition: PDG_API.h:24
Holder * holder() const
Returns the underlying attribute holder.
PDG_AttributeType
Enumeration of possible attribute types.
PDG_AttributeError setFlag(PDG_AttributeFlag flag, bool set)
Sets the specific flag on or off.
SYS_FORCE_INLINE const char * c_str() const
PDG_RWAttributeRef(const UT_StringHolder &name, const PDG_AttributeOwner *owner)
Constructs an uninitialized RW ref.
const UT_StringHolder & data() const
Definition: PDG_File.h:96
static bool isArrayType(PDG_AttributeType type)
Returns true if the specified type is an array type.
An array of UT_StringHolder values.
GLuint const GLchar * name
Definition: glcorearb.h:786
const Attribute * attribute() const
Returns a const pointer to the underlying attribute instance.
const PDG_AttributeOwner * myOwner
PDG_AttributeFlag
Enumeration of extra attribute flags. Flags can be ORed together.
const PDG_AttributeOwner * owner() const
Returns the PDG_AttributeOwner that owns the underlying attribute.
An array of fpreal values.
fpreal32 SYSrint(fpreal32 val)
Definition: SYS_Floor.h:163
exint append()
Definition: UT_Array.h:142
PDG_AttributeCast asNumbers(Array &array) const
int sprintf(const char *fmt,...) SYS_PRINTF_CHECK_ATTRIBUTE(2
#define SYS_PRId64
Definition: SYS_Types.h:76
PDG_AttributeCast asFilePathValues(UT_WorkBuffer &buffer, const UT_StringHolder &tag, const PDG_Scheduler *scheduler, bool localize)
GLsizeiptr size
Definition: glcorearb.h:664
PDG_RWAttributeRef(const Self &other)
A map of string to various well defined value types.
Definition: UT_Options.h:84
size_t format(const char *fmt, const Args &...args)
int int appendSprintf(const char *fmt,...) SYS_PRINTF_CHECK_ATTRIBUTE(2
int size() const
Returns the size of the data stored in the attribute.
PDG_AttributeError setFlags(uint16 flags, bool &changed)
Directly sets the flag bits to the specified flags.
The ref is uninitialized and needs to be created at a later point.
GLenum GLsizei GLsizei GLint * values
Definition: glcorearb.h:1602
PDG_AttributeCast asStringValues(UT_WorkBuffer &buffer, int pad=0) const
Prints the values contained in the attribute to space-separated string.
PDG_AttributeType type() const
Returns the type of the contained attribute.
An array of PDG_File values, e.g. File info structs.
uint16 flags() const
Returns the flags on the contained holder.
fpreal64 fpreal
Definition: SYS_Types.h:278
bool isNumeric() const
Returns true if the attribute is numeric.
LeafData & operator=(const LeafData &)=delete
GLuint index
Definition: glcorearb.h:786
PDG_AttributeCast asString(UT_WorkBuffer &buffer, int index, int pad=0) const
PDG_AttributeCast asFilePath(UT_StringHolder &path, int index, const UT_StringHolder &tag, const PDG_Scheduler *scheduler, bool localize)
No cast error occured (success)
UT_Options & setOptionS(const UT_StringHolder &name, const UT_StringHolder &value)
PDG_RWAttributeRef(Self &&other)
OIIO_API bool attribute(string_view name, TypeDesc type, const void *val)
A single, opaque PyObject.
void protectString(bool protect_empty=false)
An array of int values.
PDG_AttributeCast asOptions(UT_Options &options, PDG_AttributeOverwrite overwrite) const
const Attribute * operator->() const
Returns a const pointer to the underlying attribute instance.
void emitEvents()
Emits pending events from the ref.
UT_Options & setOptionDict(const UT_StringHolder &name, const UT_OptionsHolder &value)
UT_Options & setOptionFArray(const UT_StringHolder &name, const fpreal32 *values, size_t size)
Cast failed due to an index being out of bounds.
Self & operator=(Self &&other)
Self & operator=(const Self &other)
UT_Options & setOptionF(const UT_StringHolder &name, fpreal64 value)
PDG_AttributeError error() const
Returns the error state of the handle.
PDG_AttributeCast asNumber(fpreal &number, exint &query_index, const PDG_AttributeQuery &query, int index, bool has_component) const
PDG_AttributeCast asStrings(UT_StringArray &array) const
An array of UT_OptionsHolder values.
PDG_AttributeRef(const UT_StringHolder &name, const PDG_AttributeOwner *owner, PDG_AttributeError error=PDG_AttributeError::eNone)
bool isValid() const
Returns true if the handle is valid.
bool hasFlags(uint16 flags) const
Returns true if the contained holder has all of the specified flags set.
PDG_AttributeError myError