HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
UN_DataBuffer.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_DataBuffer.h ( UN Library, C++)
7  *
8  * COMMENTS:
9  * Core functionality for a utility-based node.
10  */
11 
12 #ifndef __UN_DataBuffer_h__
13 #define __UN_DataBuffer_h__
14 
15 #include "UN_API.h"
16 #include "UN_Include.h"
17 
18 
19 // ============================================================================
20 /// Vectorized memory buffer that contains data entries for a particular
21 /// aspect for a group of items of the same kind in the graph.
22 /// Each entry in the buffer holds a piece of data for a single item.
23 /// For example, a buffer may hold names for the nodes, so each buffer entry
24 /// holds a name for a single node.
25 /// This class is templated on the type of the entries it stores.
26 template <typename T>
28 {
29 public:
30  // Default constructor. Constructs an empty buffer.
31  UN_DataBuffer() = default;
32 
33  // Constructs a buffer and sets its entry (slot) size to the given number.
35  {
36  myBuffer.bumpSize(size);
37  }
38 
39  /// @{ Sets the data value for the entry at a given index.
40  void setData( UN_DataIndex index, const T &value )
41  { myBuffer[ index ] = value; }
43  { myBuffer[ index ] = std::move(value); }
44  /// @}
45 
46  /// @{ Returns the data value for the entry at a given index.
47  /// Note, this buffer class does not provide a getter method that
48  /// returns a mutable (non-const) reference to the underlying data
49  /// to avoid aliasing, which is problematic for threading.
50  /// However, it provides stealData() to move the value out of buffer.
51  const T & getDataRef( UN_DataIndex index ) const
52  { return myBuffer[ index ]; }
53  const T & operator[]( UN_DataIndex index) const
54  { return getDataRef( index ); }
55  /// @}
56 
57  /// Returns a moved value from an entry in a data buffer.
59  { return std::move( myBuffer[ index ] ); }
60 
61  /// Updates a data entry value in-place inside the data buffer.
62  /// For complex data types (eg, dictionaries or arrays) it is faster
63  /// than getting and setting the value (although stealing and setting
64  /// back a moved value is comparable).
65  /// This is a convenient and useful idiom, that tries to avoid the buffer
66  /// aliasing issues, that cause problems in multithreading.
67  /// Intended usage:
68  /// updateData(index, [&key, &value](auto &dict) { dict[key] = value; });
69  template<typename OP>
70  void updateData( UN_DataIndex index, const OP &op )
71  { op( myBuffer[ index ] ); }
72 
73  /// Adds an entry slot to the data buffer.
74  void addData( UN_DataIndex index, const T& init_value = T() )
75  {
76  // Note, currently UN appends to the buffer to extend
77  // it, but this may change in the future.
78  // This assert is to alert to such change, but can be
79  // safely ignored and removed for this particular
80  // implementation since UT_Array supports insertions.
81  UT_ASSERT( index == myBuffer.size() );
82  myBuffer.insert( init_value, index );
83  }
84 
85  /// Appends count copies of the given value.
86  void appendData( const T &value, exint count )
87  {
88  myBuffer.appendMultiple( value, count );
89  }
90 
91  /// Appends a span of entries from another buffer.
95  {
96  UT_ASSERT( start >= 0 && size >= 0 &&
97  start + size <= src.size() );
98  myBuffer.append( src.myBuffer.data() + start, size );
99  }
100 
101  /// Resets the data to an empty buffer.
102  void clear()
103  { myBuffer.clear(); }
104 
105  /// Returns the number of elements held in the data buffer.
107  { return UN_DataSize( myBuffer.size() ); }
108 
109  // Grow the buffer if the given size is larger than the current one.
110  // Copies the entries if that occurs.
111  void setCapacityIfNeeded( UN_DataSize min_capacity )
112  { myBuffer.setCapacityIfNeeded( min_capacity ); }
113 
114  /// Return true if given index is valid.
115  bool isValidIndex( UN_DataIndex index ) const
116  { return myBuffer.isValidIndex( index ); }
117 
118 private:
119  /// The underlying buffer wrapped by this class.
120  UT_Array<T> myBuffer;
121 };
122 
123 
124 // ============================================================================
125 // Data buffer for string data.
126 #include <UT/UT_StringArray.h>
127 
130 
131 // ============================================================================
132 // Data buffer for numeric data.
136 
137 // ============================================================================
138 // Data buffer for vector data.
139 #include <UT/UT_Color.h>
140 #include <UT/UT_Vector3.h>
141 #include <UT/UT_VectorTypes.h>
142 //using UN_Vector2FDataBuffer = UN_DataBuffer<UT_Vector2F>;
145 //using UN_Vector3FDataBuffer = UN_DataBuffer<UT_Vector3F>;
146 //using UN_Vector3DDataBuffer = UN_DataBuffer<UT_Vector3D>;
147 //using UN_Vector3RDataBuffer = UN_DataBuffer<UT_Vector3R>;
148 
150 
151 
152 // ============================================================================
153 /// Data buffer specialization for boolean (bit) values.
154 // Loosely based on UT_BitArray, but with interface adjusted to UN data buffers.
155 template <>
157 {
158 public:
159  // Default constructor. Constructs an empty buffer.
160  UN_DataBuffer() = default;
161 
162  // Constructs a buffer and sets its entry (slot) size to the given number.
164  {
165  exint word_size = wordCapacity( size );
166  myWordBuffer.bumpSize( word_size );
167  myWordBuffer.constant( myZero );
168  mySize = size;
169  }
170 
171  /// Sets the data value for the entry at a given index.
173  {
174  UT_ASSERT_P( index >= 0 && index < mySize );
175  BlockType &word = myWordBuffer[ wordIndex(index) ];
176  int bit = index.exintValue() & myWordMask;
177  word = (BlockType(value) << bit) | (word & ~(BlockType(1) << bit));
178  }
179 
180  /// Returns the data value for the entry at a given index.
182  {
183  UT_ASSERT_P( index >= 0 && index < mySize );
184  BlockType word = myWordBuffer[ wordIndex(index) ];
185  int bit = index.exintValue() & myWordMask;
186  return (word >> bit) & BlockType(1);
187  }
188 
189  /// Returns the data value for the entry at a given index.
190  /// Just a convenience operator that calls the official API method.
192  {
193  return getDataVal( index );
194  }
195 
196  /// Adds an entry slot to the data buffer.
197  void addData( UN_DataIndex index, bool init_value = false )
198  {
199  // Note, UN always appends new entry slots to the buffer,
200  // so we can simplify the implementation here.
201  UT_ASSERT( index == mySize );
202  if( wordIndex( index ) >= myWordBuffer.size() )
203  myWordBuffer.append();
204  mySize++;
205 
206  setData( index, init_value );
207  }
208 
209  /// Appends count copies of the given value.
210  void appendData( bool value, exint count )
211  {
212  for( exint i = 0; i < count; i++ )
213  addData( UN_DataIndex(mySize), value );
214  }
215 
216  /// Appends a span of entries from another buffer.
219  {
220  // TODO: FIXME: optimize this method by copying the whole words,
221  // after shifting them appropriately.
222  // TODO: FIXME: look at geo lib and GA_ElementGroup
223  // Groups a bit fields so resemble bool data array
224  for( exint i = start, n = start + size; i < n; i++ )
225  addData( UN_DataIndex(mySize), src.getDataVal( UN_DataIndex(i) ));
226  }
227 
228  /// Resets the data to an empty buffer.
229  void clear()
230  {
231  mySize = 0;
232  myWordBuffer.clear();
233  }
234 
235  /// Returns the number of bits held in the data buffer.
237  {
238  return UN_DataSize( mySize );
239  }
240 
241  // Grow the buffer if the given size is larger than the current one.
242  // Copies the entries if that occurs.
243  void setCapacityIfNeeded( UN_DataSize min_capacity )
244  {
245  myWordBuffer.setCapacityIfNeeded( wordCapacity( min_capacity ));
246  }
247 
248  /// Return true if given index is valid.
250  {
251  return index >= 0 && index < mySize;
252  }
253 
254 
255 private:
256  using BlockType = uint32;
257  static constexpr int myBitsPerWord = sizeof(BlockType)*8;
258  static constexpr int myWordShift = SYS_LOG2F(myBitsPerWord);
259  static constexpr int myWordMask = (1 << myWordShift) - 1;
260  static constexpr BlockType myZero = 0;
261 
262  // Returns the word number in which the given bit would be.
263  static inline exint wordIndex(exint bit_index)
264  { return (bit_index >> myWordShift); }
265 
266  // Retusns the word capacity given the bit capacity.
267  exint wordCapacity( UN_DataSize bit_capacity )
268  {
269  return (bit_capacity > 0) ?
270  (bit_capacity.exintValue() - 1) / myBitsPerWord + 1 : 0;
271  }
272 
273 private:
274  UT_Array<BlockType> myWordBuffer;
275  exint mySize = 0;
276 };
277 
279 
280 
281 // ============================================================================
282 // Data buffer for generic values.
283 #include <UT/UT_OptionEntry.h>
284 
286 {
287 public:
288  UN_ValueHandle() = default;
289  ~UN_ValueHandle() = default;
291  : myOptionPtr( other.valuePtr() ?
292  other.valuePtr()->clone() : UT_OptionEntryPtr() ) {}
293  UN_ValueHandle( UN_ValueHandle && other ) = default;
295  : myOptionPtr( std::move(value) ) {}
296 
298  {
299  myOptionPtr = other.valuePtr() ?
300  other.valuePtr()->clone() : UT_OptionEntryPtr();
301  return *this;
302  }
303  UN_ValueHandle& operator=( UN_ValueHandle && other ) = default;
304 
305  const UT_OptionEntryPtr & valuePtr() const { return myOptionPtr; }
306  UT_OptionEntryPtr & valuePtr() { return myOptionPtr; }
307 
308 private:
309  UT_OptionEntryPtr myOptionPtr;
310 };
311 
313 
314 
315 // ============================================================================
316 // Data buffer for metadata dictionaries.
317 #include <UT/UT_Options.h>
318 
321 
322 // ============================================================================
323 // Data buffer for ID lists.
324 #include "UN_Include.h"
325 
328 
329 // ============================================================================
330 /// Utility functions that operate on data buffers.
331 namespace UN_DataBufferUtils
332 {
333  /// Sets the value of the data entry in the buffer.
334  template<typename V, typename B>
335  static inline void
336  setData( B &buffer, UN_DataIndex index, const V &value )
337  {
338  if( index )
339  buffer.setData( index, value );
340  }
341 
342  /// Sets the value of the data entry in the buffer,
343  /// allowing for move-assign optimization.
344  template<typename V, typename B>
345  static inline void
346  setData( B &buffer, UN_DataIndex index, V &&value )
347  {
348  if( index )
349  buffer.setData( index, std::forward<V>(value) );
350  }
351 
352  /// Returns a const ref to an entry in the data buffer.
353  template<typename V, typename B>
354  static inline const V &
355  getDataRef( const B &buffer, UN_DataIndex index, const V &default_value )
356  {
357  if( index )
358  return buffer.getDataRef( index );
359 
360  return default_value;
361  }
362 
363  /// Returns a value constructed from an entry in the data buffer.
364  /// This is useful when the type returned here differs from
365  /// the underlying entry type.
366  /// In particular, this is needed for UN_BoolDataBuffer whose underlying
367  /// entries are bits (for which we can't return a const reference)
368  /// while here we are returning bool (byte).
369  template<typename V, typename B>
370  inline V
371  getDataVal( const B &buffer, UN_DataIndex index, const V &default_value )
372  {
373  if( index )
374  return V(buffer.getDataVal( index ));
375 
376  return V(default_value);
377  }
378 
379  /// Helper function to return a value moved from an entry in a data buffer.
380  template<typename V, typename B>
381  static inline V
382  stealData( B &buffer, UN_DataIndex index, const V &default_value )
383  {
384  if( index )
385  return buffer.stealData( index );
386 
387  return V( default_value );
388  }
389 
390  /// Helper function to update an entry value in the data buffer.
391  /// It updates a data value in-place in the data buffer,
392  /// which for complex data values (eg, dictionaries or arrays) is faster
393  /// than getting and setting the value (although stealing and setting
394  /// may be comparable). This is a convenient and useful idiom, that
395  /// tries to avoid the buffer data aliasing issues.
396  /// Intended usage:
397  /// updateData(buff, id, [&key, &value](auto &x) { x[key] = value; });
398  template<typename OP, typename B>
399  static inline void
400  updateData( B &buffer, UN_DataIndex index, const OP &op )
401  {
402  if( index )
403  buffer.updateData( index, op );
404  }
405 };
406 
407 // ============================================================================
408 #endif
409 
constexpr exint exintValue() const
Returns an exint value of this number.
Definition: UN_Include.h:77
UT_OptionEntryPtr & valuePtr()
void setData(UN_DataIndex index, const T &value)
Sets the data value for the entry at a given index.
Definition: UN_DataBuffer.h:40
V getDataVal(const B &buffer, UN_DataIndex index, const V &default_value)
UN_DataBuffer()=default
void setCapacityIfNeeded(UN_DataSize min_capacity)
void appendData(const UN_DataBuffer< bool > &src, UN_DataIndex start, UN_DataSize size)
Appends a span of entries from another buffer.
void setData(UN_DataIndex index, bool value)
Sets the data value for the entry at a given index.
UN_ValueHandle()=default
GLuint start
Definition: glcorearb.h:475
GLsizei const GLfloat * value
Definition: glcorearb.h:824
bool getDataVal(UN_DataIndex index) const
Returns the data value for the entry at a given index.
int64 exint
Definition: SYS_Types.h:125
void addData(UN_DataIndex index, bool init_value=false)
Adds an entry slot to the data buffer.
GLuint buffer
Definition: glcorearb.h:660
void setData(UN_DataIndex index, T &&value)
Sets the data value for the entry at a given index.
Definition: UN_DataBuffer.h:42
OutGridT const XformOp bool bool
const T & operator[](UN_DataIndex index) const
Definition: UN_DataBuffer.h:53
#define SYS_LOG2F(x)
Definition: SYS_BitUtil.h:299
UN_ValueHandle & operator=(UN_ValueHandle const &other)
void clear()
Resets the data to an empty buffer.
UN_DataBuffer(UN_DataSize size)
bool isValidIndex(UN_DataIndex index) const
Return true if given index is valid.
GLdouble n
Definition: glcorearb.h:2008
#define UT_ASSERT_P(ZZ)
Definition: UT_Assert.h:164
UN_DataBuffer(UN_DataSize size)
Definition: UN_DataBuffer.h:34
void setCapacityIfNeeded(UN_DataSize min_capacity)
void clear()
Resets the data to an empty buffer.
void addData(UN_DataIndex index, const T &init_value=T())
Adds an entry slot to the data buffer.
Definition: UN_DataBuffer.h:74
Data buffer specialization for boolean (bit) values.
T stealData(UN_DataIndex index)
Returns a moved value from an entry in a data buffer.
Definition: UN_DataBuffer.h:58
void appendData(const T &value, exint count)
Appends count copies of the given value.
Definition: UN_DataBuffer.h:86
bool operator[](UN_DataIndex index) const
const UT_OptionEntryPtr & valuePtr() const
UN_ValueHandle(UN_ValueHandle const &other)
bool isValidIndex(UN_DataIndex index) const
Return true if given index is valid.
GLsizeiptr size
Definition: glcorearb.h:664
void updateData(UN_DataIndex index, const OP &op)
Definition: UN_DataBuffer.h:70
void appendData(const UN_DataBuffer< T > &src, UN_DataIndex start, UN_DataSize size)
Appends a span of entries from another buffer.
Definition: UN_DataBuffer.h:92
UN_ValueHandle(UT_OptionEntryPtr &&value)
GLuint index
Definition: glcorearb.h:786
UN_DataSize size() const
Returns the number of elements held in the data buffer.
unsigned int uint32
Definition: SYS_Types.h:40
#define UT_ASSERT(ZZ)
Definition: UT_Assert.h:165
~UN_ValueHandle()=default
void appendData(bool value, exint count)
Appends count copies of the given value.
UN_DataSize size() const
Returns the number of bits held in the data buffer.
GLint GLsizei count
Definition: glcorearb.h:405
UT_UniquePtr< UT_OptionEntry > UT_OptionEntryPtr
const T & getDataRef(UN_DataIndex index) const
Definition: UN_DataBuffer.h:51
GLenum src
Definition: glcorearb.h:1793