HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
paramlist.h
Go to the documentation of this file.
1 // Copyright 2008-present Contributors to the OpenImageIO project.
2 // SPDX-License-Identifier: BSD-3-Clause
3 // https://github.com/OpenImageIO/oiio/blob/master/LICENSE.md
4 
5 
6 /// \file
7 ///
8 /// Define the ParamValue and ParamValueList classes, which are used to
9 /// store lists of arbitrary name/data pairs for internal storage of
10 /// parameter lists, attributes, geometric primitive data, etc.
11 
12 
13 #pragma once
14 
15 #include <vector>
16 
18 #include <OpenImageIO/export.h>
19 #include <OpenImageIO/typedesc.h>
20 #include <OpenImageIO/ustring.h>
21 
22 
24 
25 /// ParamValue holds a parameter and a pointer to its value(s)
26 ///
27 /// Nomenclature: if you have an array of 4 colors for each of 15 points...
28 /// - There are 15 VALUES
29 /// - Each value has an array of 4 ELEMENTS, each of which is a color
30 /// - A color has 3 COMPONENTS (R, G, B)
31 ///
33 public:
34  /// Interpolation types
35  ///
36  enum Interp {
37  INTERP_CONSTANT = 0, ///< Constant for all pieces/faces
38  INTERP_PERPIECE = 1, ///< Piecewise constant per piece/face
39  INTERP_LINEAR = 2, ///< Linearly interpolated across each piece/face
40  INTERP_VERTEX = 3 ///< Interpolated like vertices
41  };
42 
43  ParamValue() noexcept { m_data.ptr = nullptr; }
44  ParamValue(const ustring& _name, TypeDesc _type, int _nvalues,
45  const void* _value, bool _copy = true) noexcept
46  {
47  init_noclear(_name, _type, _nvalues, _value, _copy);
48  }
49  ParamValue(const ustring& _name, TypeDesc _type, int _nvalues,
50  Interp _interp, const void* _value, bool _copy = true) noexcept
51  {
52  init_noclear(_name, _type, _nvalues, _interp, _value, _copy);
53  }
54  ParamValue(string_view _name, TypeDesc _type, int _nvalues,
55  const void* _value, bool _copy = true) noexcept
56  {
57  init_noclear(ustring(_name), _type, _nvalues, _value, _copy);
58  }
59  ParamValue(string_view _name, TypeDesc _type, int _nvalues, Interp _interp,
60  const void* _value, bool _copy = true) noexcept
61  {
62  init_noclear(ustring(_name), _type, _nvalues, _interp, _value, _copy);
63  }
64  ParamValue(string_view _name, int value) noexcept
65  {
66  init_noclear(ustring(_name), TypeDesc::INT, 1, &value);
67  }
68  ParamValue(string_view _name, float value) noexcept
69  {
70  init_noclear(ustring(_name), TypeDesc::FLOAT, 1, &value);
71  }
73  {
74  init_noclear(ustring(_name), TypeDesc::STRING, 1, &value);
75  }
77  {
78  ustring u(value);
79  init_noclear(ustring(_name), TypeDesc::STRING, 1, &u);
80  }
81 
82  // Set from string -- parse
84 
85  // Copy constructor
86  ParamValue(const ParamValue& p) noexcept
87  {
88  init_noclear(p.name(), p.type(), p.nvalues(), p.interp(), p.data(),
89  true);
90  }
91  ParamValue(const ParamValue& p, bool _copy) noexcept
92  {
93  init_noclear(p.name(), p.type(), p.nvalues(), p.interp(), p.data(),
94  _copy);
95  }
96 
97  // Rvalue (move) constructor
98  ParamValue(ParamValue&& p) noexcept
99  {
100  init_noclear(p.name(), p.type(), p.nvalues(), p.interp(), p.data(),
101  false);
102  m_copy = p.m_copy;
103  m_nonlocal = p.m_nonlocal;
104  p.m_data.ptr = nullptr; // make sure the old one won't free
105  }
106 
107  ~ParamValue() noexcept { clear_value(); }
108 
109  void init(ustring _name, TypeDesc _type, int _nvalues, Interp _interp,
110  const void* _value, bool _copy = true) noexcept
111  {
112  clear_value();
113  init_noclear(_name, _type, _nvalues, _interp, _value, _copy);
114  }
115  void init(ustring _name, TypeDesc _type, int _nvalues, const void* _value,
116  bool _copy = true) noexcept
117  {
118  init(_name, _type, _nvalues, INTERP_CONSTANT, _value, _copy);
119  }
120  void init(string_view _name, TypeDesc _type, int _nvalues,
121  const void* _value, bool _copy = true) noexcept
122  {
123  init(ustring(_name), _type, _nvalues, _value, _copy);
124  }
125  void init(string_view _name, TypeDesc _type, int _nvalues, Interp _interp,
126  const void* _value, bool _copy = true) noexcept
127  {
128  init(ustring(_name), _type, _nvalues, _interp, _value, _copy);
129  }
130 
131  // Assignment
132  const ParamValue& operator=(const ParamValue& p) noexcept
133  {
134  if (this != &p)
135  init(p.name(), p.type(), p.nvalues(), p.interp(), p.data(),
136  p.m_copy);
137  return *this;
138  }
139  const ParamValue& operator=(ParamValue&& p) noexcept
140  {
141  if (this != &p) {
142  init(p.name(), p.type(), p.nvalues(), p.interp(), p.data(), false);
143  m_copy = p.m_copy;
144  m_nonlocal = p.m_nonlocal;
145  p.m_data.ptr = nullptr;
146  }
147  return *this;
148  }
149 
150  // FIXME -- some time in the future (after more cleanup), we should make
151  // name() return a string_view, and use uname() for the rare time when
152  // the caller truly requires the ustring.
153  const ustring& name() const noexcept { return m_name; }
154  const ustring& uname() const noexcept { return m_name; }
155  TypeDesc type() const noexcept { return m_type; }
156  int nvalues() const noexcept { return m_nvalues; }
157  const void* data() const noexcept
158  {
159  return m_nonlocal ? m_data.ptr : &m_data;
160  }
161  int datasize() const noexcept
162  {
163  return m_nvalues * static_cast<int>(m_type.size());
164  }
165  Interp interp() const noexcept { return (Interp)m_interp; }
166  void interp(Interp i) noexcept { m_interp = (unsigned char)i; }
167  bool is_nonlocal() const noexcept { return m_nonlocal; }
168 
169  friend void swap(ParamValue& a, ParamValue& b) noexcept
170  {
171  auto tmp = std::move(a);
172  a = std::move(b);
173  b = std::move(tmp);
174  }
175 
176  // Use with extreme caution! This is just doing a cast. You'd better
177  // be really sure you are asking for the right type. Note that for
178  // "string" data, you can get<ustring> or get<char*>, but it's not
179  // a std::string.
180  template<typename T> const T& get(int i = 0) const noexcept
181  {
182  return (reinterpret_cast<const T*>(data()))[i];
183  }
184 
185  /// Retrive an integer, with converstions from a wide variety of type
186  /// cases, including unsigned, short, byte. Not float. It will retrive
187  /// from a string, but only if the string is entirely a valid int
188  /// format. Unconvertible types return the default value.
189  int get_int(int defaultval = 0) const;
190  int get_int_indexed(int index, int defaultval = 0) const;
191 
192  /// Retrive a float, with converstions from a wide variety of type
193  /// cases, including integers. It will retrive from a string, but only
194  /// if the string is entirely a valid float format. Unconvertible types
195  /// return the default value.
196  float get_float(float defaultval = 0) const;
197  float get_float_indexed(int index, float defaultval = 0) const;
198 
199  /// Convert any type to a string value. An optional maximum number of
200  /// elements is also passed. In the case of a single string, just the
201  /// string directly is returned. But for an array of strings, the array
202  /// is returned as one string that's a comma-separated list of double-
203  /// quoted, escaped strings.
204  std::string get_string(int maxsize = 64) const;
205  std::string get_string_indexed(int index) const;
206  /// Convert any type to a ustring value. An optional maximum number of
207  /// elements is also passed. Same behavior as get_string, but returning
208  /// a ustring.
209  ustring get_ustring(int maxsize = 64) const;
210  ustring get_ustring_indexed(int index) const;
211 
212 private:
213  ustring m_name; ///< data name
214  TypeDesc m_type; ///< data type, which may itself be an array
215  union {
216  char localval[16];
217  const void* ptr;
218  } m_data; ///< Our data, either a pointer or small local value
219  int m_nvalues = 0; ///< number of values of the given type
220  unsigned char m_interp = INTERP_CONSTANT; ///< Interpolation type
221  bool m_copy = false;
222  bool m_nonlocal = false;
223 
224  void init_noclear(ustring _name, TypeDesc _type, int _nvalues,
225  const void* _value, bool _copy = true) noexcept;
226  void init_noclear(ustring _name, TypeDesc _type, int _nvalues,
227  Interp _interp, const void* _value,
228  bool _copy = true) noexcept;
229  void clear_value() noexcept;
230 };
231 
232 
233 
234 /// A list of ParamValue entries, that can be iterated over or searched.
235 /// It's really just a std::vector<ParamValue>, but with a few more handy
236 /// methods.
237 class OIIO_API ParamValueList : public std::vector<ParamValue> {
238 public:
240 
241  /// Add space for one more ParamValue to the list, and return a
242  /// reference to its slot.
244  {
245  resize(size() + 1);
246  return back();
247  }
248 
249  /// Find the first entry with matching name, and if type != UNKNOWN,
250  /// then also with matching type. The name search is case sensitive if
251  /// casesensitive == true.
253  bool casesensitive = true);
255  bool casesensitive = true);
257  bool casesensitive = true) const;
258  const_iterator find(ustring name, TypeDesc type = TypeDesc::UNKNOWN,
259  bool casesensitive = true) const;
260 
261  /// Search for the first entry with matching name, etc., and return
262  /// a pointer to it, or nullptr if it is not found.
264  bool casesensitive = true)
265  {
266  iterator f = find(name, type, casesensitive);
267  return f != end() ? &(*f) : nullptr;
268  }
269  const ParamValue* find_pv(string_view name,
271  bool casesensitive = true) const
272  {
273  const_iterator f = find(name, type, casesensitive);
274  return f != cend() ? &(*f) : nullptr;
275  }
276 
277  /// Case insensitive search for an integer, with default if not found.
278  /// Automatically will return an int even if the data is really
279  /// unsigned, short, or byte, but not float. It will retrive from a
280  /// string, but only if the string is entirely a valid int format.
281  int get_int(string_view name, int defaultval = 0,
282  bool casesensitive = false, bool convert = true) const;
283 
284  /// Case insensitive search for a float, with default if not found.
285  /// Automatically will return a float even if the data is really double
286  /// or half. It will retrive from a string, but only if the string is
287  /// entirely a valid float format.
288  float get_float(string_view name, float defaultval = 0,
289  bool casesensitive = false, bool convert = true) const;
290 
291  /// Simple way to get a string attribute, with default provided.
292  /// If the value is another type, it will be turned into a string.
293  string_view get_string(string_view name,
294  string_view defaultval = string_view(),
295  bool casesensitive = false,
296  bool convert = true) const;
297  ustring get_ustring(string_view name,
298  string_view defaultval = string_view(),
299  bool casesensitive = false, bool convert = true) const;
300 
301  /// Remove the named parameter, if it is in the list.
303  bool casesensitive = true);
304 
305  /// Does the list contain the named attribute?
307  bool casesensitive = true) const;
308 
309  // Add the param to the list, replacing in-place any existing one with
310  // the same name.
311  void add_or_replace(const ParamValue& pv, bool casesensitive = true);
312  void add_or_replace(ParamValue&& pv, bool casesensitive = true);
313 
314  /// Add (or replace) a value in the list.
315  void attribute(string_view name, TypeDesc type, int nvalues,
316  const void* value)
317  {
318  if (!name.empty())
319  add_or_replace(ParamValue(name, type, nvalues, value));
320  }
321 
322  void attribute(string_view name, TypeDesc type, const void* value)
323  {
324  attribute(name, type, 1, value);
325  }
326 
327  /// Set directly from string -- parse if type is non-string.
329  {
330  if (!name.empty())
331  add_or_replace(ParamValue(name, type, value));
332  }
333 
334  // Shortcuts for single value of common types.
335  void attribute(string_view name, int value)
336  {
337  attribute(name, TypeInt, 1, &value);
338  }
339  void attribute(string_view name, unsigned int value)
340  {
341  attribute(name, TypeUInt, 1, &value);
342  }
343  void attribute(string_view name, float value)
344  {
345  attribute(name, TypeFloat, 1, &value);
346  }
348  {
349  ustring v(value);
350  attribute(name, TypeString, 1, &v);
351  }
352 
353  /// Search list for named item, return its type or TypeUnknown if not
354  /// found.
356  bool casesensitive = false) const
357  {
358  auto p = find(name, TypeUnknown, casesensitive);
359  return p != cend() ? p->type() : TypeUnknown;
360  }
361 
362  /// Retrieve from list: If found its data type is reasonably convertible
363  /// to `type`, copy/convert the value into val[...] and return true.
364  /// Otherwise, return false and don't modify what val points to.
365  bool getattribute(string_view name, TypeDesc type, void* value,
366  bool casesensitive = false) const;
367  /// Shortcut for retrieving a single string via getattribute.
369  bool casesensitive = false) const;
370 
371  /// Retrieve from list: If found its data type is reasonably convertible
372  /// to `type`, copy/convert the value into val[...] and return true.
373  /// Otherwise, return false and don't modify what val points to.
374  bool getattribute_indexed(string_view name, int index, TypeDesc type,
375  void* value, bool casesensitive = false) const;
376  /// Shortcut for retrieving a single string via getattribute.
377  bool getattribute_indexed(string_view name, int index, std::string& value,
378  bool casesensitive = false) const;
379 
380  /// Sort alphabetically, optionally case-insensitively, locale-
381  /// independently, and with all the "un-namespaced" items appearing
382  /// first, followed by items with "prefixed namespaces" (e.g. "z" comes
383  /// before "foo:a").
384  void sort(bool casesensitive = true);
385 
386  /// Merge items from PVL `other` into `*this`. Note how this differs
387  /// from `operator=` : assignment completely replaces the list with
388  /// the contents of another. But merge() adds the other items without
389  /// erasing any items already in this list.
390  ///
391  /// @param other
392  /// The ParamValueList whose entries will be merged into this one.
393  /// @param override
394  /// If true, `other` attributes will replace any identically-named
395  /// attributes already in this list. If false, only attributes whose
396  /// names are not already in this list will be appended.
397  void merge(const ParamValueList& other, bool override = false);
398 
399  /// Even more radical than clear, free ALL memory associated with the
400  /// list itself.
401  void free()
402  {
403  clear();
404  shrink_to_fit();
405  }
406 
407  /// Array indexing by integer will return a reference to the ParamValue
408  /// in that position of the list.
409  ParamValue& operator[](int index)
410  {
411  return std::vector<ParamValue>::operator[](index);
412  }
413  const ParamValue& operator[](int index) const
414  {
415  return std::vector<ParamValue>::operator[](index);
416  }
417 
418  /// Array indexing by string will create a "Delegate" that enables a
419  /// convenient shorthand for adding and retrieving values from the list:
420  ///
421  /// 1. Assigning to the delegate adds a ParamValue to the list:
422  /// ParamValueList list;
423  /// list["foo"] = 42; // adds integer
424  /// list["bar"] = 39.8f; // adds float
425  /// list["baz"] = "hello"; // adds string
426  /// Be very careful, the attribute's type will be implied by the C++
427  /// type of what you assign.
428  ///
429  /// 2. The delegate supports a get<T>() that retrieves an item of type T:
430  /// int i = list["foo"].get<int>();
431  /// std::string s = list["baz"].get<std::string>();
432  ///
434  {
435  return { this, name };
436  }
438  {
439  return { this, name };
440  }
441 };
442 
443 
444 
~ParamValue() noexcept
Definition: paramlist.h:107
AttrDelegate< const ParamValueList > operator[](string_view name) const
Definition: paramlist.h:433
GLboolean GLboolean GLboolean b
Definition: glcorearb.h:1221
int datasize() const noexcept
Definition: paramlist.h:161
void init(string_view _name, TypeDesc _type, int _nvalues, const void *_value, bool _copy=true) noexcept
Definition: paramlist.h:120
void init(ustring _name, TypeDesc _type, int _nvalues, const void *_value, bool _copy=true) noexcept
Definition: paramlist.h:115
ParamValue(string_view _name, TypeDesc _type, int _nvalues, const void *_value, bool _copy=true) noexcept
Definition: paramlist.h:54
32-bit IEEE floating point values, (C/C++ float).
Definition: typedesc.h:82
void init(string_view _name, TypeDesc _type, int _nvalues, Interp _interp, const void *_value, bool _copy=true) noexcept
Definition: paramlist.h:125
void attribute(string_view name, string_view value)
Definition: paramlist.h:347
reference grow()
Definition: paramlist.h:243
*get result *(waiting if necessary)*A common idiom is to fire a bunch of sub tasks at the and then *wait for them to all complete We provide a helper class
Definition: thread.h:629
unknown type
Definition: typedesc.h:57
void attribute(string_view name, TypeDesc type, string_view value)
Set directly from string – parse if type is non-string.
Definition: paramlist.h:328
void init(ustring _name, TypeDesc _type, int _nvalues, Interp _interp, const void *_value, bool _copy=true) noexcept
Definition: paramlist.h:109
GLenum const void GLuint GLint reference
Definition: glew.h:13927
ParamValue(string_view _name, ustring value) noexcept
Definition: paramlist.h:72
const ustring & name() const noexcept
Definition: paramlist.h:153
ParamValue * find_pv(string_view name, TypeDesc type=TypeDesc::UNKNOWN, bool casesensitive=true)
Definition: paramlist.h:263
Character string.
Definition: typedesc.h:84
Tto convert(const Tfrom &source)
ParamValue(string_view _name, int value) noexcept
Definition: paramlist.h:64
GLuint const GLchar * name
Definition: glcorearb.h:785
ParamValue(const ustring &_name, TypeDesc _type, int _nvalues, Interp _interp, const void *_value, bool _copy=true) noexcept
Definition: paramlist.h:49
void attribute(string_view name, int value)
Definition: paramlist.h:335
basic_string_view< char > string_view
Definition: core.h:440
GLsizeiptr size
Definition: glcorearb.h:663
const ParamValue * find_pv(string_view name, TypeDesc type=TypeDesc::UNKNOWN, bool casesensitive=true) const
Definition: paramlist.h:269
void attribute(string_view name, unsigned int value)
Definition: paramlist.h:339
void attribute(string_view name, TypeDesc type, int nvalues, const void *value)
Add (or replace) a value in the list.
Definition: paramlist.h:315
int nvalues() const noexcept
Definition: paramlist.h:156
GLint GLint GLsizei GLint GLenum GLenum type
Definition: glcorearb.h:107
ParamValue(ParamValue &&p) noexcept
Definition: paramlist.h:98
FMT_CONSTEXPR bool find(Ptr first, Ptr last, T value, Ptr &out)
Definition: format.h:2929
const GLdouble * v
Definition: glcorearb.h:836
GLboolean GLboolean GLboolean GLboolean a
Definition: glcorearb.h:1221
GLuint GLuint end
Definition: glcorearb.h:474
friend void swap(ParamValue &a, ParamValue &b) noexcept
Definition: paramlist.h:169
GLsizei const GLchar *const * string
Definition: glcorearb.h:813
ParamValue(const ParamValue &p, bool _copy) noexcept
Definition: paramlist.h:91
const ParamValue & operator=(const ParamValue &p) noexcept
Definition: paramlist.h:132
GLfloat GLfloat p
Definition: glew.h:16656
const void * data() const noexcept
Definition: paramlist.h:157
ParamValue(string_view _name, string_view value) noexcept
Definition: paramlist.h:76
const ParamValue & operator[](int index) const
Definition: paramlist.h:413
ParamValue & operator[](int index)
Definition: paramlist.h:409
void attribute(string_view name, TypeDesc type, const void *value)
Definition: paramlist.h:322
ParamValue(string_view _name, TypeDesc _type, int _nvalues, Interp _interp, const void *_value, bool _copy=true) noexcept
Definition: paramlist.h:59
TypeDesc getattributetype(string_view name, bool casesensitive=false) const
Definition: paramlist.h:355
const ustring & uname() const noexcept
Definition: paramlist.h:154
bool OIIO_API contains(string_view a, string_view b)
Does 'a' contain the string 'b' within it?
GLboolean * data
Definition: glcorearb.h:130
OIIO_API bool getattribute(string_view name, TypeDesc type, void *val)
bool is_nonlocal() const noexcept
Definition: paramlist.h:167
ImageBuf OIIO_API resize(const ImageBuf &src, string_view filtername="", float filterwidth=0.0f, ROI roi={}, int nthreads=0)
ParamValue(string_view _name, float value) noexcept
Definition: paramlist.h:68
void attribute(string_view name, float value)
Definition: paramlist.h:343
TypeDesc type() const noexcept
Definition: paramlist.h:155
ParamValue() noexcept
Definition: paramlist.h:43
void interp(Interp i) noexcept
Definition: paramlist.h:166
GLuint index
Definition: glcorearb.h:785
AttrDelegate< ParamValueList > operator[](string_view name)
Definition: paramlist.h:437
ParamValue(const ustring &_name, TypeDesc _type, int _nvalues, const void *_value, bool _copy=true) noexcept
Definition: paramlist.h:44
GLsizei const GLfloat * value
Definition: glcorearb.h:823
OIIO_API bool attribute(string_view name, TypeDesc type, const void *val)
GLfloat f
Definition: glcorearb.h:1925
ParamValue(const ParamValue &p) noexcept
Definition: paramlist.h:86
#define const
Definition: zconf.h:214
#define OIIO_NAMESPACE_END
Definition: oiioversion.h:94
const void * ptr
Definition: paramlist.h:217
void sort(I begin, I end, const Pred &pred)
Definition: pugixml.cpp:7334
const ParamValue & operator=(ParamValue &&p) noexcept
Definition: paramlist.h:139
constexpr bool empty() const noexcept
Is the string_view empty, containing no characters?
Definition: string_view.h:146
Interp interp() const noexcept
Definition: paramlist.h:165
#define OIIO_NAMESPACE_BEGIN
Definition: oiioversion.h:93
#define OIIO_API
Definition: export.h:65