HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
attrdelegate.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
4 
5 
6 #pragma once
7 
8 #include <memory>
9 #include <vector>
10 
11 #include <OpenImageIO/export.h>
13 #include <OpenImageIO/typedesc.h>
14 #include <OpenImageIO/ustring.h>
15 
16 
18 
19 
20 namespace pvt {
21 
22 // Helper template to detect if a type is one if the string types that
23 // OIIO tends to use.
24 // clang-format off
25 template<typename T> struct is_string : std::false_type {};
26 template<> struct is_string<ustring> : std::true_type {};
27 template<> struct is_string<string_view> : std::true_type {};
28 template<> struct is_string<std::string> : std::true_type {};
29 // clang-format on
30 
31 } // namespace pvt
32 
33 
34 
35 // AttrDelegate should not be used directly in user code!
36 //
37 // This is a helper template that allows the notation
38 // Class object;
39 // object["name"] = value;
40 // to work as a shorthand for
41 // object.attribute ("name", TypeDesc_of_value, &value);
42 // and for
43 // value = object["name"].get<type>();
44 // to work as a shorthand for extracting the named attribute via
45 // object.getattribute() and assigning it to the result.
46 //
47 // Basically, the class in question needs to posess these three methods,
48 // working in the usual idiomatic way for OIIO:
49 //
50 // void attribute (string_view name, TypeDesc type, void* data);
51 // bool getattribute (string_view name, TypeDesc type, void *data);
52 // TypeDesc getattributetype (string_view name);
53 //
54 // Then the array access notation can be added with the following members
55 // of the class C:
56 //
57 // AttrDelegate<const C> operator[](string_view name) const
58 // {
59 // return { this, name };
60 // }
61 // AttrDelegate<C> operator[](string_view name) {
62 // return { this, name };
63 // }
64 //
65 // This allows the following convenient notation:
66 //
67 // 1. Adding attributes, type implied by the C++ type of what's assigned:
68 // C obj;
69 // obj["foo"] = 42; // adds integer
70 // obj["bar"] = 39.8f; // adds float
71 // obj["baz"] = "hello"; // adds string
72 // 2. Retrieving attributes:
73 // int i = obj["foo"].get<int>();
74 // float f = obj["bar"].get<float>();
75 // std::string s = obj["baz"].get<std::string>();
76 // If the object does not posess an attribute of that name (and/or of
77 // that type), it will instead return the default value for that type.
78 // A specific default value override may be provided as an argument to
79 // the get() method:
80 // float aspect = obj["aspectratio"].get<float>(1.0f);
81 //
82 
83 template<class C> class AttrDelegate {
84 public:
86  : m_obj(obj)
87  , m_name(name)
88  , m_readonly(std::is_const<C>::value)
89  {
90  }
91 
92  // Assignment to a delegate should copy the value into an attribute,
93  // calling attribute(name,typedesc,&data). Except for strings, which are
94  // handled separately.
95  template<typename T,
97  inline const T& operator=(const T& val)
98  {
99  if (!m_readonly)
100  const_cast<C*>(m_obj)->attribute(m_name, TypeDescFromC<T>::value(),
101  &val);
102  return val;
103  }
104 
105  // String types are a special case because we don't directly copy their
106  // data, instead call the attribute(name,string_view) variant.
107  template<typename T,
109  inline const T& operator=(const T& val)
110  {
111  if (!m_readonly)
112  const_cast<C*>(m_obj)->attribute(m_name, string_view(val));
113  return val;
114  }
115  // char arrays are special
116  inline const char* operator=(const char* val)
117  {
118  if (!m_readonly)
119  const_cast<C*>(m_obj)->attribute(m_name, string_view(val));
120  return val;
121  }
122 
123 
124  // `Delegate->type()` returns the TypeDesc describing the data, or
125  // TypeUnknown if no such attribute exists.
126  TypeDesc type() const { return m_obj->getattributetype(m_name); }
127 
128  // `Delegate->get<T>(defaultval=T())` retrieves the data as type T,
129  // or the defaultval if no such named data exists or is not the
130  // designated type.
131  template<typename T,
133  inline T get(const T& defaultval = T()) const
134  {
135  T result;
136  if (!m_obj->getattribute(m_name, TypeDescFromC<T>::value(), &result))
137  result = defaultval;
138  return result;
139  }
140 
141  // Using enable_if, make a slightly different version of get<> for
142  // strings, which need to do some ustring magic because we can't
143  // directly store in a std::string or string_view.
144  template<typename T = string_view,
146  inline T get(const T& defaultval = T()) const
147  {
148  ustring s;
149  return m_obj->getattribute(m_name, TypeString, &s) ? T(s) : defaultval;
150  }
151 
152  // `Delegate->get_indexed<T>(int index, defaultval=T())` retrieves the
153  // index-th base value in the data as type T, or the defaultval if no
154  // such named data exists or is not the designated type.
155  template<typename T,
157  inline T get_indexed(int index, const T& defaultval = T()) const
158  {
159  T result;
160  if (!m_obj->getattribute_indexed(m_name, index,
161  TypeDescFromC<T>::value(), &result))
162  result = defaultval;
163  return result;
164  }
165 
166  // Using enable_if, make a slightly different version of get_indexed<>
167  // for strings, which need to do some ustring magic because we can't
168  // directly store in a std::string or string_view.
169  template<typename T = string_view,
171  inline T get_indexed(int index, const T& defaultval = T()) const
172  {
173  ustring s;
174  return m_obj->getattribute_indexed(m_name, index, TypeString, &s)
175  ? T(s)
176  : defaultval;
177  }
178 
179  // `Delegate->as_string(defaultval="")` returns the data, no matter its
180  // type, as a string. Returns the defaultval if no such data exists at
181  // all.
182  inline std::string as_string(const std::string& defaultval = std::string())
183  {
184  std::string s;
185  TypeDesc t = m_obj->getattributetype(m_name);
186  if (t == TypeString) { // Attrib is a string? Return it.
187  s = get<std::string>();
188  } else if (t != TypeUnknown) { // Non-string attrib? Convert.
189  const int localsize = 64; // Small types copy to stack, avoid new
190  char localbuffer[localsize];
191  char* buffer = localbuffer;
192  std::unique_ptr<char[]> allocbuffer;
193  if (t.size() > localsize) {
194  allocbuffer.reset(new char[t.size()]);
195  buffer = allocbuffer.get();
196  }
197  if (m_obj->getattribute(m_name, t, buffer))
198  s = tostring(t, buffer);
199  else
200  s = defaultval;
201  } else { // No attrib? Return default.
202  s = defaultval;
203  }
204  return s;
205  }
206 
207  // Return the entire attribute (even if an array or aggregate) as a
208  // `std::vector<T>`, calling `get_indexed` on each base element.
209  template<typename T, typename Allocator = std::allocator<T>>
210  inline std::vector<T, Allocator> as_vec() const
211  {
212  TypeDesc t = m_obj->getattributetype(m_name);
213  size_t basevals = t.basevalues();
214  using Vec = std::vector<T, Allocator>;
215  Vec result;
216  result.reserve(basevals);
217  for (size_t i = 0; i < basevals; ++i)
218  result.push_back(get_indexed<T>(int(i)));
219  return result;
220  }
221 
222  // Allow direct assignment to string, equivalent to calling as_string().
223  inline operator std::string() { return as_string(); }
224 
225 protected:
226  C* m_obj;
228  bool m_readonly = false;
229 };
230 
231 
TypeDesc type() const
Definition: attrdelegate.h:126
GLsizei const GLchar *const * string
Definition: glcorearb.h:814
GLsizei const GLfloat * value
Definition: glcorearb.h:824
GLdouble s
Definition: glad.h:3009
**But if you need a result
Definition: thread.h:613
OIIO_UTIL_API std::string tostring(TypeDesc type, const void *data, const char *float_fmt, const char *string_fmt="%s", const char aggregate_delim[2]="()", const char *aggregate_sep=",", const char array_delim[2]="{}", const char *array_sep=",")
basic_string_view< char > string_view
Definition: core.h:522
AttrDelegate(C *obj, string_view name)
Definition: attrdelegate.h:85
OIIO_HOSTDEVICE OIIO_CONSTEXPR14 size_t basevalues() const noexcept
Definition: typedesc.h:191
Definition: core.h:760
std::vector< T, Allocator > as_vec() const
Definition: attrdelegate.h:210
GLuint const GLchar * name
Definition: glcorearb.h:786
OIIO_HOSTDEVICE size_t size() const noexcept
Definition: typedesc.h:207
GLdouble t
Definition: glad.h:2397
GLuint index
Definition: glcorearb.h:786
GLuint GLfloat * val
Definition: glcorearb.h:1608
OIIO_API bool attribute(string_view name, TypeDesc type, const void *val)
const T & operator=(const T &val)
Definition: attrdelegate.h:97
Definition: core.h:1131
T get_indexed(int index, const T &defaultval=T()) const
Definition: attrdelegate.h:157
#define OIIO_NAMESPACE_END
Definition: oiioversion.h:94
type
Definition: core.h:1059
const char * operator=(const char *val)
Definition: attrdelegate.h:116
string_view m_name
Definition: attrdelegate.h:227
std::string as_string(const std::string &defaultval=std::string())
Definition: attrdelegate.h:182
#define OIIO_NAMESPACE_BEGIN
Definition: oiioversion.h:93