HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
APEX_ParmDict.h
Go to the documentation of this file.
1 /*
2  * PROPRIETARY INFORMATION. This software is proprietary to
3  * Side Effects Software Inc., and is not to be reproduced,
4  * transmitted, or disclosed in any way without written permission.
5  *
6  * NAME: APEX_ParmDict.h (APEX Library, C++)
7  *
8  * COMMENTS:
9  */
10 
11 #ifndef __APEX_FLEXIBLEDICT_H__
12 #define __APEX_FLEXIBLEDICT_H__
13 
14 #include "APEX_API.h"
15 #include "APEX_Buffer.h"
16 #include "APEX_COW.h" // IWYU pragma: export
17 #include "APEX_Include.h"
18 #include "APEX_Types.h"
19 #include <GU/GU_Detail.h>
20 #include <UT/UT_Array.h>
21 #include <UT/UT_ArrayMap.h>
22 #include <UT/UT_ArrayStringMap.h>
23 #include <UT/UT_Assert.h>
24 #include <UT/UT_Base64.h>
25 #include <UT/UT_Optional.h>
26 #include <UT/UT_OptionEntry.h>
27 #include <UT/UT_Options.h>
28 #include <UT/UT_StringArray.h>
29 #include <UT/UT_StringHolder.h>
30 #include <UT/UT_StringStream.h>
31 #include <UT/UT_UniquePtr.h>
32 #include <UT/UT_ValArray.h>
33 #include <UT/UT_WorkBuffer.h>
34 #include <SYS/SYS_Types.h>
35 
36 #include <new>
37 #include <typeindex>
38 #include <utility>
39 
40 #include <stddef.h>
41 
42 // For UT::ArraySet.
43 namespace UT
44 {
45 template <typename T>
47 
48 template <>
49 struct DefaultClearer<apex::APEX_TrackedArgument>
50 {
52  static bool isClear(const apex::APEX_TrackedArgument &v) { return v.offset == -1; }
54  {
55  new ((void *)p) apex::APEX_TrackedArgument();
56  }
57  static const bool clearNeedsDestruction = true;
58 };
59 
60 }; // namespace UT
61 
62 namespace apex
63 {
64 
65 class APEX_ParmDict;
68 
69 class APEX_Graph;
70 class APEX_Signature;
71 
73 {
74 public:
75  static constexpr UT_StringLit theTypeSuffix = ".__type__";
76 
78  : myBuffer(UTmakeUnique<APEX_Buffer>())
79  {
80  }
81 
82  explicit APEX_ParmDict(APEX_Buffer *external)
83  : myExternalBuffer(external)
84  {
85  }
86 
88  : myBuffer(UTmakeUnique<APEX_Buffer>())
89  {
90  mergeUtOptions(opt, true);
91  }
92 
94  : myExternalBuffer(other.myExternalBuffer)
95  , myDataId(other.myDataId)
96  {
97  if (myExternalBuffer)
98  {
99  myMap = other.myMap;
100  }
101  else
102  {
103  myBuffer = UTmakeUnique<APEX_Buffer>();
104  update(other, true);
105  }
106  }
107 
109  {
110  if (this == &other)
111  return *this;
112 
113  myExternalBuffer = other.myExternalBuffer;
114  myDataId = other.myDataId;
115 
116  if (myExternalBuffer)
117  {
118  myMap = other.myMap;
119  myBuffer = nullptr;
120  }
121  else
122  {
123  myMap.clear();
124  myBuffer = UTmakeUnique<APEX_Buffer>();
125  update(other, true);
126  }
127 
128  return *this;
129  }
130 
131  void operator=(const UT_OptionsHolder &opt)
132  {
133  myMap.clear();
134  myBuffer = UTmakeUnique<APEX_Buffer>();
135  myExternalBuffer = nullptr;
136  mergeUtOptions(opt, true);
137  }
138 
139  bool contains(const UT_StringRef &key) const
140  {
141  return myMap.contains(key);
142  }
143 
144  bool empty() const
145  {
146  return myMap.empty();
147  }
148 
149  exint size() const
150  {
151  return myMap.size();
152  }
153 
154  void bindGraphData(const APEX_Graph &graph, const APEX_PortIDRange &ports);
155  APEX_TrackedArgument *getHandle(const UT_StringRef &key);
156  const APEX_TrackedArgument *getHandle(const UT_StringRef &key) const;
157 
158  template <typename T>
159  const T *get(const UT_StringRef &key) const
160  {
161  auto it = myMap.find(key);
162  if (it.atEnd())
163  return nullptr;
164  return castArg<T>(&it->second);
165  }
166 
167  template <typename T>
168  T *get(const UT_StringRef &key)
169  {
170  auto it = myMap.find(key);
171  if (it.atEnd())
172  return nullptr;
173  return castArg<T>(&it->second);
174  }
175 
176  /// Helper function to extract a boolean value from either an int or bool dict value.
177  const UT_Optional<Bool>
178  getBoolOrInt(const UT_StringRef &key) const
179  {
180  if (const Bool *val = get<Bool>(key))
181  return UTmakeOptional<Bool>(*val);
182  else if (const Int *val = get<Int>(key))
183  return UTmakeOptional<Bool>(*val != 0);
184 
185  return UT_NULLOPT;
186  }
187 
188  template <typename T>
189  T getValueOr(const UT_StringRef &key, T defValue) const
190  {
191  auto value = get<T>(key);
192  if (value)
193  return *value;
194  return defValue;
195  }
196 
197  template <typename T>
198  void set(
199  const UT_StringRef &key,
200  const T &value,
201  bool add_missing = true,
202  bool allow_type_change = false,
203  bool bump_data_id = true)
204  {
205  if (!isValidKey(key))
206  {
207  UT_WorkBuffer msg;
208  msg.format("set() called with invalid key {}", key);
209  UT_ASSERT_MSG(false, msg.buffer());
210  return;
211  }
212 
213  auto it = myMap.find(key);
214  const APEX_TypeDefinitionBase *type_defn = findTypeDef<T>();
215  if (!type_defn)
216  {
217  UT_ASSERT_MSG(false, "set() called with unregistered type");
218  return;
219  }
221  if (it.atEnd())
222  {
223  if (!add_missing)
224  return;
225  myMap[key] = appendTrackedArgument(type_defn);
226  arg = &myMap[key];
227  }
228  else
229  {
230  arg = &it->second;
231  if (type_defn != arg->type_defn)
232  {
233  if (!allow_type_change)
234  return;
235  // playing it safe and not allowing type change on a buffer we
236  // don't own
237  // FIXME: currently not deallocating on the buffer if we change
238  // the type of any entry
239  else
240  it->second = appendTrackedArgument(type_defn);
241  }
242  }
243  T &dst = *castArg<T>(arg);
244  dst = value;
245  arg->bumpDataId();
246  if (bump_data_id)
247  bumpDataId();
248  // UTdebugPrint(key, arg->modCounter);
249  }
250 
251  bool set(
252  const UT_StringRef &key,
253  const APEX_Argument &arg,
254  bool add_missing = true,
255  bool allow_type_change = false,
256  bool force_update = false,
257  bool bump_data_id = true,
258  bool bump_data_id_on_conversion = true);
259 
260  bool set(
261  const UT_StringRef &key,
262  const APEX_TrackedArgument &arg,
263  bool add_missing = true,
264  bool allow_type_change = false,
265  bool force_update = false,
266  bool bump_data_id = true,
267  bool bump_data_id_on_conversion = true);
268 
269  void renameEntry(const UT_StringRef &key, const UT_StringRef &newname);
270 
271  bool sharesBuffer(const APEX_ParmDict &other) const;
272 
273  // void setPyDict(void *pydict);
274 
275  // void writeToUtOptions(UT_Options &opt);
276  // void writeToPyDict(void *pydict);
277 
278  // FIXME: No const-correctness here! As the buffer is pending a rewrite
279  // I won't clutter the current API
280  // APEX_Buffer *buffer();
281  APEX_Buffer *buffer() const;
282 
283  UT_StringArray compareDataIds(const APEX_ParmDict &other, bool check_missing = false);
284 
285  void update(
286  const APEX_ParmDict &other,
287  bool add_missing = false,
288  bool allow_type_change = false,
289  bool force_copy = false,
290  UT_StringArray *changelist = nullptr,
291  bool bump_data_id_on_conversion = true);
292  void mergeUtOptions(
293  const UT_OptionsHolder &opt_h,
294  bool clear = false,
295  bool add_missing = true,
296  bool allow_type_change = true,
297  const APEX_Signature *signature = nullptr);
298  void updateUtOptions(
299  UT_Options &opt_h,
300  bool clear = false,
301  bool include_geometry = false,
302  bool include_typeinfo = true) const;
303  void updateUtOptions(
304  UT_OptionsHolder &opt_h,
305  bool clear = false,
306  bool include_geometry = false,
307  bool include_typeinfo = true) const;
308 
310  const UT_ArrayStringMap<APEX_TrackedArgument> &map() const { return myMap; }
311 
312  void clear()
313  {
314  myMap.clear();
315  if (!myExternalBuffer)
316  myBuffer->clear();
317  bumpDataId();
318  }
319 
320  /// This function removes any previously set value such that subsequent
321  /// execution will act as if set() were never called on that key. It will
322  /// also reset the value back to its default state. However, the default
323  /// value will continue to occupy memory in the buffer until the entire
324  /// buffer is cleared using @ref clear().
325  bool remove(const UT_StringRef &key);
326 
327  APEX_DataID dataId() const { return myDataId; }
328  void bumpDataId() { myDataId = APEX_Buffer::nextDataId(); }
329  void copyDataId(const APEX_ParmDict &other) { myDataId = other.dataId(); }
330 
331  static bool isValidKey(const UT_StringRef &key,
332  UT_StringHolder *err_msg=nullptr);
333 
334  int64 getMemoryUsage() const;
335 
336 private:
337  template <typename T>
338  void setReinterpretFloatArray(
339  const UT_StringRef &name,
340  const UT_Array<Float> &src,
341  bool add_missing)
342  {
343  static_assert(std::is_same_v<typename T::value_type, Float>);
344  auto tmp = ApexArray<T>();
345  tmp->append((T *)src.data(), src.size() / T::tuple_size);
346  set<ApexArray<T>>(name, tmp, add_missing, false, false);
347  }
348 
349  APEX_TrackedArgument appendTrackedArgument(const APEX_TypeDefinitionBase *type_defn)
350  {
351  APEX_Argument arg = buffer()->append(type_defn);
352  return {{arg.buffer, arg.type_defn, arg.offset}, /*default*/};
353  }
354 
356  UT_UniquePtr<APEX_Buffer> myBuffer;
357  APEX_Buffer *myExternalBuffer = nullptr;
359 };
360 
361 // Overload for custom formatting with UTformat, must be in the same namespace
362 // as APEX_ParmDict in order to be found via ADL.
363 APEX_API size_t
364 UTformatBuffer(char *buffer, size_t buffer_size, const APEX_ParmDict &v);
365 
366 // Overload for custom formatting of Dict with UTformat.
367 APEX_API size_t
368 UTformatBuffer(char *buffer, size_t buffer_size, const Dict &v);
369 
370 // Specialization ApexArray<T> for custom formatting of ApexArray<Dict> with
371 // UTformat.
372 template <>
373 APEX_API size_t
375  char *buffer,
376  size_t bufsize,
377  const ApexArray<Dict> &v);
378 
379 template <typename T>
380 static std::type_index
381 typeIndexT()
382 {
383  return std::type_index(typeid(T));
384 }
385 
386 void
388  UT_Options &opt,
389  const UT_StringRef &key,
390  const APEX_Argument &arg,
391  bool include_geometry = false,
392  bool include_typeinfo = true);
393 
394 } // namespace apex
395 
396 #endif // header guard
GLenum GLuint GLsizei bufsize
Definition: glcorearb.h:1818
static APEX_DataID nextDataId()
Get a new unique data ID.
APEX_ParmDict(APEX_Buffer *external)
Definition: APEX_ParmDict.h:82
APEX_ParmDict & operator=(const APEX_ParmDict &other)
const GLdouble * v
Definition: glcorearb.h:837
GLsizei const GLfloat * value
Definition: glcorearb.h:824
APEX_ParmDict(const APEX_ParmDict &other)
Definition: APEX_ParmDict.h:93
#define APEX_API
Definition: APEX_API.h:21
size_t UTformatBuffer(char *buffer, size_t bufsize, const ApexArray< T > &v)
Definition: APEX_COW.h:138
bool empty() const
int64 exint
Definition: SYS_Types.h:125
SYS_FORCE_INLINE const char * buffer() const
void setUtOption(UT_Options &opt, const UT_StringRef &key, const APEX_Argument &arg, bool include_geometry=false, bool include_typeinfo=true)
bool contains(const UT_StringRef &key) const
#define UT_NULLOPT
Definition: UT_Optional.h:23
auto arg(const Char *name, const T &arg) -> detail::named_arg< Char, T >
Definition: core.h:1859
GLuint buffer
Definition: glcorearb.h:660
exint size() const
Definition: UT_Array.h:667
Holds all of the memory for execution state of a compiled APEX graph.
Definition: APEX_Buffer.h:97
std::optional< T > UT_Optional
Definition: UT_Optional.h:26
std::unique_ptr< T, Deleter > UT_UniquePtr
A smart pointer for unique ownership of dynamically allocated objects.
Definition: UT_UniquePtr.h:39
void operator=(const UT_OptionsHolder &opt)
#define UT_ASSERT_MSG(ZZ,...)
Definition: UT_Assert.h:168
const UT_ArrayStringMap< APEX_TrackedArgument > & map() const
APEX_COWHandle< APEX_ParmDict > Dict
Definition: APEX_ParmDict.h:66
static void clear(apex::APEX_TrackedArgument &v)
Definition: APEX_ParmDict.h:51
int64 APEX_DataID
Definition: APEX_Buffer.h:86
APEX_DataID dataId() const
static void clearConstruct(apex::APEX_TrackedArgument *p)
Definition: APEX_ParmDict.h:53
constexpr auto set(type rhs) -> int
Definition: core.h:610
const APEX_TypeDefinitionBase * type_defn
Definition: APEX_Buffer.h:181
UT_ArrayStringMap< APEX_TrackedArgument > & map()
long long int64
Definition: SYS_Types.h:116
exint append(const T &v)
Definition: APEX_COW.h:58
GLuint const GLchar * name
Definition: glcorearb.h:786
UT_UniquePtr< T > UTmakeUnique(REST &&...args)
Definition: UT_UniquePtr.h:50
GLenum GLenum dst
Definition: glcorearb.h:1793
A map of string to various well defined value types.
Definition: UT_Options.h:87
exint Int
Definition: APEX_Include.h:61
size_t format(const char *fmt, const Args &...args)
exint size() const
void copyDataId(const APEX_ParmDict &other)
void set(const UT_StringRef &key, const T &value, bool add_missing=true, bool allow_type_change=false, bool bump_data_id=true)
T * data()
Definition: UT_Array.h:866
T getValueOr(const UT_StringRef &key, T defValue) const
GLuint GLfloat * val
Definition: glcorearb.h:1608
APEX_ParmDict(const UT_OptionsHolder &opt)
Definition: APEX_ParmDict.h:87
bool Bool
Definition: APEX_Include.h:60
const UT_Optional< Bool > getBoolOrInt(const UT_StringRef &key) const
Helper function to extract a boolean value from either an int or bool dict value. ...
Represents a location for a single object inside of an APEX_Buffer.
Definition: APEX_Buffer.h:177
static bool isClear(const apex::APEX_TrackedArgument &v)
Definition: APEX_ParmDict.h:52
GLenum src
Definition: glcorearb.h:1793
APEX_API size_t UTformatBuffer< Dict >(char *buffer, size_t bufsize, const ApexArray< Dict > &v)