HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
UN_GenericData.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: UN_GenericData.h ( UN Library, C++)
7  *
8  * COMMENTS:
9  * Container for dynamically added data buffers of known types.
10  */
11 
12 #ifndef __UN_GenericData_h__
13 #define __UN_GenericData_h__
14 
15 #include "UN_API.h"
16 #include "UN_DataBuffer.h"
17 #include "UN_Include.h"
18 #include <UT/UT_ArrayMap.h>
19 #include <variant>
20 
21 class UN_DataMergeInfo;
22 
23 
24 // ============================================================================
25 /// Supported types for generic data buffers.
27 {
28  String, // UT_StringHolder
29  StringArray, // UT_StringArray
30  Bool, // bool (via UN_BoolDataBuffer)
31  Int, // exint
32  Float, // float
33  Vector2D, // UT_Vector2D
34  Color // UT_Color
35 };
36 
37 
38 // ============================================================================
39 /// A strongly-typed identifier for a generic data buffer.
40 /// Returned by UN_GenericData::addBuffer() and used to access
41 /// data in that buffer.
42 
44 {
45 public:
46  UN_GenericBufferID() = default;
47  explicit UN_GenericBufferID(exint v) : myValue(v) {}
48 
49  bool isValid() const { return myValue >= 0; }
50  exint value() const { return myValue; }
51  explicit operator bool() const { return isValid(); }
52 
53 private:
54  exint myValue = -1;
55 };
56 
57 
58 // ============================================================================
59 /// A lightweight reference to a generic data buffer within a container.
60 /// Wraps a container pointer and a UN_GenericBufferID, forwarding
61 /// data access calls (set, get, steal, update) to the container.
62 ///
63 /// Template parameters:
64 /// ContainerT - The data container type (e.g., UN_NodeData).
65 /// DataIDT - The strongly-typed ID for data items (e.g., UN_NodeID).
66 
67 template<typename ContainerT, typename DataIDT>
69 {
70 public:
71  UN_GenericDataBufferRef() = default;
73  ContainerT &container,
74  UN_GenericBufferID buf_id)
75  : myContainer(&container), myBufferID(buf_id) {}
76 
77  bool isValid() const { return myBufferID.isValid(); }
78  explicit operator bool() const { return isValid(); }
79 
80  UN_GenericBufferID bufferID() const { return myBufferID; }
81  ContainerT & container() const
82  {
83  UT_ASSERT(myContainer);
84  return *myContainer;
85  }
86 
87  /// Returns the data buffer type.
89  {
90  return myContainer->bufferType(myBufferID);
91  }
92 
93  /// Returns the name of the data buffer.
95  {
96  return myContainer->bufferName(myBufferID);
97  }
98 
99  /// Sets the data value for a given data ID.
100  template<typename T>
101  void setData(DataIDT id, T &&value)
102  {
103  myContainer->setGenericData(myBufferID, id, std::forward<T>(value));
104  }
105 
106  /// Returns a const ref to the data value for a given data ID.
107  template<typename T>
108  const T & dataRef(DataIDT id) const
109  {
110  return myContainer->template genericDataRef<T>(myBufferID, id);
111  }
112 
113  /// Returns a copy of the data value for a given data ID.
114  template<typename T>
115  T dataVal(DataIDT id) const
116  {
117  return myContainer->template genericDataVal<T>(myBufferID, id);
118  }
119 
120  /// Moves the data value out of the buffer for a given data ID.
121  template<typename T>
122  T stealData(DataIDT id)
123  {
124  return myContainer->template stealGenericData<T>(myBufferID, id);
125  }
126 
127  /// Updates the data value in-place via a callable.
128  template<typename T, typename OP>
129  void updateData(DataIDT id, const OP &op)
130  {
131  myContainer->template updateGenericData<T>(myBufferID, id, op);
132  }
133 
134 private:
135  ContainerT *myContainer = nullptr;
136  UN_GenericBufferID myBufferID;
137 };
138 
139 
140 // ============================================================================
141 /// Compile-time mapping from C++ type to UN_GenericBufferType enum value.
142 /// Used by template accessors to assert type correctness at runtime.
143 
144 template<typename T>
146 
147 template<>
149 { static constexpr auto type = UN_GenericBufferType::String; };
150 
151 template<>
153 { static constexpr auto type = UN_GenericBufferType::StringArray; };
154 
155 template<>
157 { static constexpr auto type = UN_GenericBufferType::Bool; };
158 
159 template<>
161 { static constexpr auto type = UN_GenericBufferType::Int; };
162 
163 template<>
165 { static constexpr auto type = UN_GenericBufferType::Float; };
166 
167 template<>
169 { static constexpr auto type = UN_GenericBufferType::Vector2D; };
170 
171 template<>
173 { static constexpr auto type = UN_GenericBufferType::Color; };
174 
175 
176 // ============================================================================
177 /// Pairs a data buffer with its per-buffer default value.
178 /// When getDataRef() is called for an invalid index, the stored default is
179 /// returned instead of requiring callers to pass one at every call site.
180 
181 template<typename T>
183 {
186 
188  : myBuffer(size), myDefault{} {}
189 
190  template<typename D>
191  UN_GenericBuffer(UN_DataSize size, D &&default_value)
192  : myBuffer(size), myDefault(std::forward<D>(default_value)) {}
193 };
194 
195 
196 // ============================================================================
197 /// Variant holding all supported buffer types. No inheritance or virtual
198 /// dispatch — template accessors use std::get<>() for zero-overhead access.
199 
200 using UN_GenericBufferVariant = std::variant<
202  UN_GenericBuffer<UT_StringArray>, // StringArray
203  UN_GenericBuffer<bool>, // Bool
205  UN_GenericBuffer<float>, // Float
206  UN_GenericBuffer<UT_Vector2D>, // Vector2D
208 >;
209 
210 
211 // ============================================================================
212 /// Container for dynamically added data buffers of known types.
213 ///
214 /// Unlike the built-in buffers in UN_NodeData or UN_PortData, which are
215 /// fixed at compile time, this class allows buffers to be added on demand
216 /// at runtime by specifying a desired data type. Each buffer is identified
217 /// by a UN_GenericBufferID returned from addBuffer().
218 ///
219 /// Data access uses template methods (setData<T>, getDataRef<T>) that compile
220 /// down to direct buffer access via std::get<>() — no virtual dispatch.
221 /// Lifecycle operations (addData, clearData, etc.) use std::visit.
222 
224 {
225 public:
226  /// Adds a new named data buffer with a caller-specified default value.
227  /// If a buffer with the same name already exists and the type matches,
228  /// its existing ID is returned. If the name exists but the type
229  /// conflicts, an invalid ID is returned.
230  template<typename D>
233  const D &default_value,
234  UN_DataSize buffer_size)
235  {
236  // Check for an existing buffer with this name.
237  auto it = myBufferIndexFromName.find( name );
238  if( it != myBufferIndexFromName.end() )
239  {
240  if( myBuffers[it->second].myType == type )
241  return UN_GenericBufferID( it->second );
242  return UN_GenericBufferID(); // type conflict
243  }
244 
245  auto id = addBuffer( name, type, buffer_size );
246  if( !id )
247  return id;
248 
249  std::visit( [&default_value]( auto &buf )
250  {
251  using T = std::decay_t<decltype(buf.myDefault)>;
252  if constexpr( std::is_constructible_v<T, const D &> )
253  buf.myDefault = T(default_value);
254  else
255  UT_ASSERT( !"Incompatible default value type" );
256  }, myBuffers[id.value()].myBuffer );
257 
258  return id;
259  }
260 
261  /// Returns the type of the buffer identified by the given ID.
263  { return myBuffers[id.value()].myType; }
264 
265  /// Returns the number of generic buffers.
267  { return myBuffers.size(); }
268 
269  /// Returns the ID of the buffer with the given name, or an invalid
270  /// ID if no such buffer exists.
271  UN_GenericBufferID findBuffer( const UT_StringRef &name ) const;
272 
273  /// Returns the name of the buffer identified by the given ID.
275  { return myBuffers[id.value()].myName; }
276 
277  /// Sets the data value for a given buffer and index.
278  template<typename T>
280  const T &value )
281  {
282  UT_ASSERT( myBuffers[buf_id.value()].myType
284  auto &buf = std::get<UN_GenericBuffer<T>>(
285  myBuffers[buf_id.value()].myBuffer );
286  UN_DataBufferUtils::setData( buf.myBuffer, index, value );
287  }
288 
289  /// Sets the data value via move for a given buffer and index.
290  template<typename T>
292  T &&value )
293  {
294  UT_ASSERT( myBuffers[buf_id.value()].myType
296  auto &buf = std::get<UN_GenericBuffer<std::decay_t<T>>>(
297  myBuffers[buf_id.value()].myBuffer );
298  UN_DataBufferUtils::setData( buf.myBuffer, index,
299  std::forward<T>(value) );
300  }
301 
302  /// Returns a const ref to the data value for a given buffer and index.
303  /// Returns the buffer's stored default for invalid indices.
304  template<typename T>
305  const T & getDataRef( UN_GenericBufferID buf_id,
306  UN_DataIndex index ) const
307  {
308  UT_ASSERT( myBuffers[buf_id.value()].myType
310  auto &buf = std::get<UN_GenericBuffer<T>>(
311  myBuffers[buf_id.value()].myBuffer );
312  return UN_DataBufferUtils::getDataRef( buf.myBuffer, index,
313  buf.myDefault );
314  }
315 
316  /// Returns a copy of the data value for a given buffer and index.
317  /// Returns a copy of the buffer's stored default for invalid indices.
318  /// Useful when cannot call getDataRef() for types that cannot
319  /// return by reference (eg, bool with bit-packed UN_DataBuffer<bool>).
320  template<typename T>
322  {
323  UT_ASSERT( myBuffers[buf_id.value()].myType
325  auto &buf = std::get<UN_GenericBuffer<T>>(
326  myBuffers[buf_id.value()].myBuffer );
327  return UN_DataBufferUtils::getDataVal( buf.myBuffer, index,
328  buf.myDefault );
329  }
330 
331  /// Moves the data value out of a given buffer and index.
332  /// Returns a copy of the buffer's stored default for invalid indices.
333  template<typename T>
335  {
336  UT_ASSERT( myBuffers[buf_id.value()].myType
338  auto &buf = std::get<UN_GenericBuffer<T>>(
339  myBuffers[buf_id.value()].myBuffer );
340  return UN_DataBufferUtils::stealData(
341  buf.myBuffer, index, buf.myDefault );
342  }
343 
344  /// Updates the data value in-place via a callable.
345  /// Usage: updateData<T>(buf_id, index, [](auto &v) { v = ...; });
346  template<typename T, typename OP>
348  const OP &op )
349  {
350  UT_ASSERT( myBuffers[buf_id.value()].myType
352  auto &buf = std::get<UN_GenericBuffer<T>>(
353  myBuffers[buf_id.value()].myBuffer );
354  UN_DataBufferUtils::updateData( buf.myBuffer, index, op );
355  }
356 
357 
358 
359  /// Adds a data slot at the given index to all generic buffers.
360  void addData( UN_DataIndex index );
361 
362  /// Clears the data at the given index to defaults in all generic buffers.
363  void clearData( UN_DataIndex index );
364 
365  /// Removes all data from all generic buffers.
366  void removeAllData();
367 
368  /// Grows all generic buffers to the given minimum capacity if needed.
369  void setCapacityIfNeeded( UN_DataSize min_capacity );
370 
371  /// Merges data from another UN_GenericData container.
372  void mergeData( const UN_GenericData &src,
373  const UN_DataMergeInfo &merge_info );
374 
375  /// @{ Returns true if all buffers have the expected size.
376  bool isDataSizeConsistent(
377  UN_DataSize expected_size ) const;
378  bool isDataSizeConsistent() const;
379  /// @}
380 
381 private:
382  /// Adds a named buffer with a default-constructed default value.
383  /// Used internally by the public template addBuffer() overload.
384  UN_GenericBufferID addBuffer(const UT_StringHolder &name,
386  UN_DataSize buffer_size = UN_DataSize(0));
387 
388  /// Returns the current size of the internals data buffers.
389  /// The number of valid entries (slots) in data buffers is less than
390  /// or equal to that number, since some data slots may be free.
391  UN_DataSize dataBufferSize() const;
392  UN_DataSize dataBufferSizeImpl() const;
393 
394 private:
395  /// Info about a generic buffer within this generic data container.
396  struct BufferEntry
397  {
398  UT_StringHolder myName;
399  UN_GenericBufferType myType;
400  UN_GenericBufferVariant myBuffer;
401  };
402 
403  /// The array of generic buffers added with addBuffer().
404  UT_Array<BufferEntry> myBuffers;
405 
406  /// Fast lookup from buffer name to index in myBuffers.
407  UT_ArrayMap<UT_StringHolder, exint> myBufferIndexFromName;
408 };
409 
410 #endif
type
Definition: core.h:556
UN_GenericBufferType
Supported types for generic data buffers.
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: glcorearb.h:2540
V getDataVal(const B &buffer, UN_DataIndex index, const V &default_value)
UN_GenericDataBufferRef(ContainerT &container, UN_GenericBufferID buf_id)
T getDataVal(UN_GenericBufferID buf_id, UN_DataIndex index) const
UN_DataBuffer< T > myBuffer
UN_GenericBufferType bufferType(UN_GenericBufferID id) const
Returns the type of the buffer identified by the given ID.
UN_GenericDataBufferRef()=default
void updateData(DataIDT id, const OP &op)
Updates the data value in-place via a callable.
const GLdouble * v
Definition: glcorearb.h:837
GLsizei const GLfloat * value
Definition: glcorearb.h:824
T dataVal(DataIDT id) const
Returns a copy of the data value for a given data ID.
std::variant< UN_GenericBuffer< UT_StringHolder >, UN_GenericBuffer< UT_StringArray >, UN_GenericBuffer< bool >, UN_GenericBuffer< exint >, UN_GenericBuffer< float >, UN_GenericBuffer< UT_Vector2D >, UN_GenericBuffer< UT_Color > > UN_GenericBufferVariant
int64 exint
Definition: SYS_Types.h:125
void setData(DataIDT id, T &&value)
Sets the data value for a given data ID.
#define UN_API
Definition: UN_API.h:11
ContainerT & container() const
UN_GenericBufferType bufferType(UN_GenericBufferID id) const
Returns the data buffer type.
T stealData(DataIDT id)
Moves the data value out of the buffer for a given data ID.
OutGridT const XformOp bool bool
void setData(UN_GenericBufferID buf_id, UN_DataIndex index, T &&value)
Sets the data value via move for a given buffer and index.
bool isValid() const
const UT_StringHolder & bufferName(UN_GenericBufferID id) const
Returns the name of the buffer identified by the given ID.
GLint GLint GLsizei GLint GLenum GLenum type
Definition: glcorearb.h:108
UN_GenericBufferID bufferID() const
const T & getDataRef(UN_GenericBufferID buf_id, UN_DataIndex index) const
UN_GenericBuffer(UN_DataSize size, D &&default_value)
GLuint id
Definition: glcorearb.h:655
GLuint const GLchar * name
Definition: glcorearb.h:786
exint numBuffers() const
Returns the number of generic buffers.
const T & dataRef(DataIDT id) const
Returns a const ref to the data value for a given data ID.
GLsizeiptr size
Definition: glcorearb.h:664
IMATH_NAMESPACE::V2f IMATH_NAMESPACE::Box2i std::string this attribute is obsolete as of OpenEXR v3 float
void setData(UN_GenericBufferID buf_id, UN_DataIndex index, const T &value)
Sets the data value for a given buffer and index.
UN_GenericBufferID(exint v)
GLuint index
Definition: glcorearb.h:786
UN_GenericBuffer(UN_DataSize size=UN_DataSize(0))
UN_GenericBufferID()=default
UN_GenericBufferID addBuffer(const UT_StringRef &name, UN_GenericBufferType type, const D &default_value, UN_DataSize buffer_size)
exint value() const
#define UT_ASSERT(ZZ)
Definition: UT_Assert.h:165
void updateData(UN_GenericBufferID buf_id, UN_DataIndex index, const OP &op)
const UT_StringHolder & bufferName(UN_GenericBufferID id) const
Returns the name of the data buffer.
T stealData(UN_GenericBufferID buf_id, UN_DataIndex index)
GLenum src
Definition: glcorearb.h:1793