HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
accessorHelpers.h
Go to the documentation of this file.
1 //
2 // Copyright 2016 Pixar
3 //
4 // Licensed under the Apache License, Version 2.0 (the "Apache License")
5 // with the following modification; you may not use this file except in
6 // compliance with the Apache License and the following modification to it:
7 // Section 6. Trademarks. is deleted and replaced with:
8 //
9 // 6. Trademarks. This License does not grant permission to use the trade
10 // names, trademarks, service marks, or product names of the Licensor
11 // and its affiliates, except as required to comply with Section 4(c) of
12 // the License and to reproduce the content of the NOTICE file.
13 //
14 // You may obtain a copy of the Apache License at
15 //
16 // http://www.apache.org/licenses/LICENSE-2.0
17 //
18 // Unless required by applicable law or agreed to in writing, software
19 // distributed under the Apache License with the above modification is
20 // distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
21 // KIND, either express or implied. See the Apache License for the specific
22 // language governing permissions and limitations under the Apache License.
23 //
24 #ifndef PXR_USD_SDF_ACCESSOR_HELPERS_H
25 #define PXR_USD_SDF_ACCESSOR_HELPERS_H
26 
27 /// \file sdf/accessorHelpers.h
28 
29 #include "pxr/pxr.h"
30 #include "pxr/usd/sdf/schema.h"
31 #include "pxr/usd/sdf/spec.h"
32 #include "pxr/usd/sdf/types.h"
33 
34 #include <type_traits>
35 
36 // This file defines macros intended to reduce the amount of boilerplate code
37 // associated with adding new metadata to SdfSpec subclasses. There's still a
38 // lot of files to touch, but these at least reduce the copy/paste/edit load.
39 //
40 // Prior to using these macros in the SdfSpec implementation file, define the
41 // following symbols:
42 //
43 // #define SDF_ACCESSOR_CLASS SdfSomeSpec
44 // #define SDF_ACCESSOR_READ_PREDICATE(key_) _CanRead(key_)
45 // #define SDF_ACCESSOR_WRITE_PREDICATE(key_) _CanWrite(key_)
46 //
47 // ...where _CanRead and _CanWrite are member functions of the specified class,
48 // with the signature 'bool _fn_(const TfToken&)'. If either accessor predicate
49 // is unnecessary, #define the corresponding symbol to 'SDF_NO_PREDICATE'.
50 //
51 // Also, please observe good form and #undef the symbols after instancing the
52 // accessor macros.
53 
55 
56 // "Helper" macros
57 #define _GET_KEY_(key_) key_
58 #define SDF_NO_PREDICATE true
59 
60 #define _GET_WITH_FALLBACK(key_, heldType_) \
61  { \
62  typedef Sdf_AccessorHelpers<SDF_ACCESSOR_CLASS> _Helper; \
63  const VtValue& value = _Helper::GetField(this, key_); \
64  if (value.IsEmpty() || !value.IsHolding<heldType_>()) { \
65  const SdfSchemaBase& schema = _Helper::GetSchema(this); \
66  return schema.GetFallback(_GET_KEY_(key_)).Get<heldType_>(); \
67  } \
68  else { \
69  return value.Get<heldType_>(); \
70  } \
71  }
72 
73 // Accessor methods for "simple type" values: Get, Is, Set, Has, Clear
74 // Usually the client will utilize one of the combination macros (below).
75 
76 #define SDF_DEFINE_GET(name_, key_, heldType_) \
77 heldType_ \
78 SDF_ACCESSOR_CLASS::Get ## name_() const \
79 { \
80  if (SDF_ACCESSOR_READ_PREDICATE(_GET_KEY_(key_))) { \
81  /* Empty clause needed to prevent compiler complaints */ \
82  } \
83  \
84  _GET_WITH_FALLBACK(key_, heldType_); \
85 }
86 
87 #define SDF_DEFINE_IS(name_, key_) \
88 bool \
89 SDF_ACCESSOR_CLASS::Is ## name_() const \
90 { \
91  if (!SDF_ACCESSOR_READ_PREDICATE(_GET_KEY_(key_))) { \
92  return false; \
93  } \
94  \
95  _GET_WITH_FALLBACK(key_, bool); \
96 }
97 
98 #define SDF_DEFINE_SET(name_, key_, argType_) \
99 void \
100 SDF_ACCESSOR_CLASS::Set ## name_(argType_ value) \
101 { \
102  if (SDF_ACCESSOR_WRITE_PREDICATE(_GET_KEY_(key_))) { \
103  typedef Sdf_AccessorHelpers<SDF_ACCESSOR_CLASS> _Helper; \
104  _Helper::SetField(this, _GET_KEY_(key_), value); \
105  } \
106 }
107 
108 #define SDF_DEFINE_HAS(name_, key_) \
109 bool \
110 SDF_ACCESSOR_CLASS::Has ## name_() const \
111 { \
112  typedef Sdf_AccessorHelpers<SDF_ACCESSOR_CLASS> _Helper; \
113  return SDF_ACCESSOR_READ_PREDICATE(_GET_KEY_(key_)) ? \
114  _Helper::HasField(this, _GET_KEY_(key_)) : false; \
115 }
116 
117 #define SDF_DEFINE_CLEAR(name_, key_) \
118 void \
119 SDF_ACCESSOR_CLASS::Clear ## name_() \
120 { \
121  typedef Sdf_AccessorHelpers<SDF_ACCESSOR_CLASS> _Helper; \
122  if (SDF_ACCESSOR_WRITE_PREDICATE(_GET_KEY_(key_))) { \
123  _Helper::ClearField(this, _GET_KEY_(key_)); \
124  } \
125 }
126 
127 // Accessor methods similar to the above, but intended for private use in
128 // the SdSpec classes.
129 
130 #define SDF_DEFINE_GET_PRIVATE(name_, key_, heldType_) \
131 heldType_ \
132 SDF_ACCESSOR_CLASS::_Get ## name_() const \
133 { \
134  if (SDF_ACCESSOR_READ_PREDICATE(_GET_KEY_(key_))) { \
135  /* Empty clause needed to prevent compiler complaints */ \
136  } \
137  \
138  _GET_WITH_FALLBACK(key_, heldType_); \
139 }
140 
141 // Accessor methods for VtDictionary types, utilizing SdDictionaryProxy for the
142 // 'Get' accessors. Due to unusual naming in the original SdSpec API, these
143 // macros accept/require explicit accessor method names. Dammit.
144 #define SDF_DEFINE_DICTIONARY_GET(name_, key_) \
145 SdfDictionaryProxy \
146 SDF_ACCESSOR_CLASS::name_() const \
147 { \
148  typedef Sdf_AccessorHelpers<SDF_ACCESSOR_CLASS> _Helper; \
149  return SDF_ACCESSOR_READ_PREDICATE(_GET_KEY_(key_)) ? \
150  SdfDictionaryProxy(_Helper::GetSpecHandle(this), _GET_KEY_(key_)) : \
151  SdfDictionaryProxy(); \
152 }
153 
154 #define SDF_DEFINE_DICTIONARY_SET(name_, key_) \
155 void \
156 SDF_ACCESSOR_CLASS::name_( \
157  const std::string& name, \
158  const VtValue& value) \
159 { \
160  typedef Sdf_AccessorHelpers<SDF_ACCESSOR_CLASS> _Helper; \
161  if (SDF_ACCESSOR_WRITE_PREDICATE(_GET_KEY_(key_))) { \
162  SdfDictionaryProxy proxy( \
163  _Helper::GetSpecHandle(this), _GET_KEY_(key_)); \
164  if (value.IsEmpty()) { \
165  proxy.erase(name); \
166  } \
167  else { \
168  proxy[name] = value; \
169  } \
170  } \
171 }
172 
173 // Convenience macros to provide common combinations of value accessors
174 
175 // Convert non-trivial types like `std::string` to `const std::string&` while
176 // preserving the type for `int`, `bool`, `char`, etc.
177 template <typename T>
178 using Sdf_SetParameter = std::conditional<
179  std::is_arithmetic<T>::value, std::add_const_t<T>,
180  std::add_lvalue_reference_t<std::add_const_t<T>>>;
181 
182 #define SDF_DEFINE_TYPED_GET_SET(name_, key_, getType_, setType_) \
183 SDF_DEFINE_GET(name_, key_, getType_) \
184 SDF_DEFINE_SET(name_, key_, setType_)
185 
186 #define SDF_DEFINE_TYPED_GET_SET_HAS_CLEAR(name_, key_, getType_, setType_) \
187 SDF_DEFINE_TYPED_GET_SET(name_, key_, getType_, setType_) \
188 SDF_DEFINE_HAS(name_, key_) \
189 SDF_DEFINE_CLEAR(name_, key_)
190 
191 #define SDF_DEFINE_GET_SET(name_, key_, type_) \
192 SDF_DEFINE_TYPED_GET_SET(name_, key_, type_, \
193  Sdf_SetParameter<type_>::type)
194 
195 #define SDF_DEFINE_GET_SET_HAS_CLEAR(name_, key_, type_) \
196 SDF_DEFINE_TYPED_GET_SET_HAS_CLEAR(name_, key_, type_, \
197  Sdf_SetParameter<type_>::type)
198 
199 #define SDF_DEFINE_IS_SET(name_, key_) \
200 SDF_DEFINE_IS(name_, key_) \
201 SDF_DEFINE_SET(name_, key_, bool)
202 
203 #define SDF_DEFINE_DICTIONARY_GET_SET(getName_, setName_, key_) \
204 SDF_DEFINE_DICTIONARY_GET(getName_, key_) \
205 SDF_DEFINE_DICTIONARY_SET(setName_, key_)
206 
207 // Implementation details
208 // The helper macros above can be used in the implementation of a spec
209 // class or a spec API class (see declareSpec.h for details). Both cases
210 // access data in a different way -- spec classes can query their data
211 // members directly, while spec API classes need to query their associated
212 // spec. These templates capture those differences.
213 
214 template <class T,
215  bool IsForSpec = std::is_base_of<SdfSpec, T>::value>
217 
218 template <class T>
219 struct Sdf_AccessorHelpers<T, true>
220 {
221  static const SdfSchemaBase& GetSchema(const T* spec)
222  { return spec->GetSchema(); }
223 
224  static VtValue GetField(const T* spec, const TfToken& key)
225  { return spec->GetField(key); }
226 
227  template <class V>
228  static bool SetField(T* spec, const TfToken& key, const V& value)
229  { return spec->SetField(key, value); }
230 
231  static bool HasField(const T* spec, const TfToken& key)
232  { return spec->HasField(key); }
233 
234  static void ClearField(T* spec, const TfToken& key)
235  { spec->ClearField(key); }
236 
237  static SdfSpecHandle GetSpecHandle(const T* spec)
238  { return SdfCreateNonConstHandle(spec); }
239 };
240 
241 template <class T>
242 struct Sdf_AccessorHelpers<T, false>
243 {
244  static const SdfSchemaBase& GetSchema(const T* spec)
245  { return spec->_GetSpec().GetSchema(); }
246 
247  static VtValue GetField(const T* spec, const TfToken& key)
248  { return spec->_GetSpec().GetField(key); }
249 
250  template <class V>
251  static bool SetField(T* spec, const TfToken& key, const V& value)
252  { return spec->_GetSpec().SetField(key, value); }
253 
254  static bool HasField(const T* spec, const TfToken& key)
255  { return spec->_GetSpec().HasField(key); }
256 
257  static void ClearField(T* spec, const TfToken& key)
258  { spec->_GetSpec().ClearField(key); }
259 
260  static SdfSpecHandle GetSpecHandle(const T* spec)
261  { return SdfCreateNonConstHandle(&(spec->_GetSpec())); }
262 };
263 
265 
266 #endif // #ifndef PXR_USD_SDF_ACCESSOR_HELPERS_H
static SdfSpecHandle GetSpecHandle(const T *spec)
static VtValue GetField(const T *spec, const TfToken &key)
static bool HasField(const T *spec, const TfToken &key)
static const SdfSchemaBase & GetSchema(const T *spec)
GLsizei const GLfloat * value
Definition: glcorearb.h:824
static void ClearField(T *spec, const TfToken &key)
static void ClearField(T *spec, const TfToken &key)
static VtValue GetField(const T *spec, const TfToken &key)
static bool SetField(T *spec, const TfToken &key, const V &value)
static SdfSpecHandle GetSpecHandle(const T *spec)
static bool SetField(T *spec, const TfToken &key, const V &value)
Definition: token.h:87
static bool HasField(const T *spec, const TfToken &key)
static const SdfSchemaBase & GetSchema(const T *spec)
std::conditional< std::is_arithmetic< T >::value, std::add_const_t< T >, std::add_lvalue_reference_t< std::add_const_t< T >>> Sdf_SetParameter
SdfHandleTo< T >::Handle SdfCreateNonConstHandle(T const *p)
PXR_NAMESPACE_CLOSE_SCOPE PXR_NAMESPACE_OPEN_SCOPE
Definition: path.h:1432
#define PXR_NAMESPACE_CLOSE_SCOPE
Definition: pxr.h:91
Definition: core.h:1131
Definition: value.h:164