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 <hboost/call_traits.hpp>
35 #include <type_traits>
36 
37 // This file defines macros intended to reduce the amount of boilerplate code
38 // associated with adding new metadata to SdfSpec subclasses. There's still a
39 // lot of files to touch, but these at least reduce the copy/paste/edit load.
40 //
41 // Prior to using these macros in the SdfSpec implementation file, define the
42 // following symbols:
43 //
44 // #define SDF_ACCESSOR_CLASS SdfSomeSpec
45 // #define SDF_ACCESSOR_READ_PREDICATE(key_) _CanRead(key_)
46 // #define SDF_ACCESSOR_WRITE_PREDICATE(key_) _CanWrite(key_)
47 //
48 // ...where _CanRead and _CanWrite are member functions of the specified class,
49 // with the signature 'bool _fn_(const TfToken&)'. If either accessor predicate
50 // is unnecessary, #define the corresponding symbol to 'SDF_NO_PREDICATE'.
51 //
52 // Also, please observe good form and #undef the symbols after instancing the
53 // accessor macros.
54 
56 
57 // "Helper" macros
58 #define _GET_KEY_(key_) key_
59 #define SDF_NO_PREDICATE true
60 
61 #define _GET_WITH_FALLBACK(key_, heldType_) \
62  { \
63  typedef Sdf_AccessorHelpers<SDF_ACCESSOR_CLASS> _Helper; \
64  const VtValue& value = _Helper::GetField(this, key_); \
65  if (value.IsEmpty() || !value.IsHolding<heldType_>()) { \
66  const SdfSchemaBase& schema = _Helper::GetSchema(this); \
67  return schema.GetFallback(_GET_KEY_(key_)).Get<heldType_>(); \
68  } \
69  else { \
70  return value.Get<heldType_>(); \
71  } \
72  }
73 
74 // Accessor methods for "simple type" values: Get, Is, Set, Has, Clear
75 // Usually the client will utilize one of the combination macros (below).
76 
77 #define SDF_DEFINE_GET(name_, key_, heldType_) \
78 heldType_ \
79 SDF_ACCESSOR_CLASS::Get ## name_() const \
80 { \
81  if (SDF_ACCESSOR_READ_PREDICATE(_GET_KEY_(key_))) { \
82  /* Empty clause needed to prevent compiler complaints */ \
83  } \
84  \
85  _GET_WITH_FALLBACK(key_, heldType_); \
86 }
87 
88 #define SDF_DEFINE_IS(name_, key_) \
89 bool \
90 SDF_ACCESSOR_CLASS::Is ## name_() const \
91 { \
92  if (!SDF_ACCESSOR_READ_PREDICATE(_GET_KEY_(key_))) { \
93  return false; \
94  } \
95  \
96  _GET_WITH_FALLBACK(key_, bool); \
97 }
98 
99 #define SDF_DEFINE_SET(name_, key_, argType_) \
100 void \
101 SDF_ACCESSOR_CLASS::Set ## name_(argType_ value) \
102 { \
103  if (SDF_ACCESSOR_WRITE_PREDICATE(_GET_KEY_(key_))) { \
104  typedef Sdf_AccessorHelpers<SDF_ACCESSOR_CLASS> _Helper; \
105  _Helper::SetField(this, _GET_KEY_(key_), value); \
106  } \
107 }
108 
109 #define SDF_DEFINE_HAS(name_, key_) \
110 bool \
111 SDF_ACCESSOR_CLASS::Has ## name_() const \
112 { \
113  typedef Sdf_AccessorHelpers<SDF_ACCESSOR_CLASS> _Helper; \
114  return SDF_ACCESSOR_READ_PREDICATE(_GET_KEY_(key_)) ? \
115  _Helper::HasField(this, _GET_KEY_(key_)) : false; \
116 }
117 
118 #define SDF_DEFINE_CLEAR(name_, key_) \
119 void \
120 SDF_ACCESSOR_CLASS::Clear ## name_() \
121 { \
122  typedef Sdf_AccessorHelpers<SDF_ACCESSOR_CLASS> _Helper; \
123  if (SDF_ACCESSOR_WRITE_PREDICATE(_GET_KEY_(key_))) { \
124  _Helper::ClearField(this, _GET_KEY_(key_)); \
125  } \
126 }
127 
128 // Accessor methods similar to the above, but intended for private use in
129 // the SdSpec classes.
130 
131 #define SDF_DEFINE_GET_PRIVATE(name_, key_, heldType_) \
132 heldType_ \
133 SDF_ACCESSOR_CLASS::_Get ## name_() const \
134 { \
135  if (SDF_ACCESSOR_READ_PREDICATE(_GET_KEY_(key_))) { \
136  /* Empty clause needed to prevent compiler complaints */ \
137  } \
138  \
139  _GET_WITH_FALLBACK(key_, heldType_); \
140 }
141 
142 // Accessor methods for VtDictionary types, utilizing SdDictionaryProxy for the
143 // 'Get' accessors. Due to unusual naming in the original SdSpec API, these
144 // macros accept/require explicit accessor method names. Dammit.
145 #define SDF_DEFINE_DICTIONARY_GET(name_, key_) \
146 SdfDictionaryProxy \
147 SDF_ACCESSOR_CLASS::name_() const \
148 { \
149  typedef Sdf_AccessorHelpers<SDF_ACCESSOR_CLASS> _Helper; \
150  return SDF_ACCESSOR_READ_PREDICATE(_GET_KEY_(key_)) ? \
151  SdfDictionaryProxy(_Helper::GetSpecHandle(this), _GET_KEY_(key_)) : \
152  SdfDictionaryProxy(); \
153 }
154 
155 #define SDF_DEFINE_DICTIONARY_SET(name_, key_) \
156 void \
157 SDF_ACCESSOR_CLASS::name_( \
158  const std::string& name, \
159  const VtValue& value) \
160 { \
161  typedef Sdf_AccessorHelpers<SDF_ACCESSOR_CLASS> _Helper; \
162  if (SDF_ACCESSOR_WRITE_PREDICATE(_GET_KEY_(key_))) { \
163  SdfDictionaryProxy proxy( \
164  _Helper::GetSpecHandle(this), _GET_KEY_(key_)); \
165  if (value.IsEmpty()) { \
166  proxy.erase(name); \
167  } \
168  else { \
169  proxy[name] = value; \
170  } \
171  } \
172 }
173 
174 // Convenience macros to provide common combinations of value accessors
175 
176 #define SDF_DEFINE_TYPED_GET_SET(name_, key_, getType_, setType_) \
177 SDF_DEFINE_GET(name_, key_, getType_) \
178 SDF_DEFINE_SET(name_, key_, setType_)
179 
180 #define SDF_DEFINE_TYPED_GET_SET_HAS_CLEAR(name_, key_, getType_, setType_) \
181 SDF_DEFINE_TYPED_GET_SET(name_, key_, getType_, setType_) \
182 SDF_DEFINE_HAS(name_, key_) \
183 SDF_DEFINE_CLEAR(name_, key_)
184 
185 #define SDF_DEFINE_GET_SET(name_, key_, type_) \
186 SDF_DEFINE_TYPED_GET_SET(name_, key_, type_, \
187  hboost::call_traits<type_>::param_type)
188 
189 #define SDF_DEFINE_GET_SET_HAS_CLEAR(name_, key_, type_) \
190 SDF_DEFINE_TYPED_GET_SET_HAS_CLEAR(name_, key_, type_, \
191  hboost::call_traits<type_>::param_type)
192 
193 #define SDF_DEFINE_IS_SET(name_, key_) \
194 SDF_DEFINE_IS(name_, key_) \
195 SDF_DEFINE_SET(name_, key_, bool)
196 
197 #define SDF_DEFINE_DICTIONARY_GET_SET(getName_, setName_, key_) \
198 SDF_DEFINE_DICTIONARY_GET(getName_, key_) \
199 SDF_DEFINE_DICTIONARY_SET(setName_, key_)
200 
201 // Implementation details
202 // The helper macros above can be used in the implementation of a spec
203 // class or a spec API class (see declareSpec.h for details). Both cases
204 // access data in a different way -- spec classes can query their data
205 // members directly, while spec API classes need to query their associated
206 // spec. These templates capture those differences.
207 
208 template <class T,
209  bool IsForSpec = std::is_base_of<SdfSpec, T>::value>
211 
212 template <class T>
213 struct Sdf_AccessorHelpers<T, true>
214 {
215  static const SdfSchemaBase& GetSchema(const T* spec)
216  { return spec->GetSchema(); }
217 
218  static VtValue GetField(const T* spec, const TfToken& key)
219  { return spec->GetField(key); }
220 
221  template <class V>
222  static bool SetField(T* spec, const TfToken& key, const V& value)
223  { return spec->SetField(key, value); }
224 
225  static bool HasField(const T* spec, const TfToken& key)
226  { return spec->HasField(key); }
227 
228  static void ClearField(T* spec, const TfToken& key)
229  { spec->ClearField(key); }
230 
231  static SdfSpecHandle GetSpecHandle(const T* spec)
232  { return SdfCreateNonConstHandle(spec); }
233 };
234 
235 template <class T>
236 struct Sdf_AccessorHelpers<T, false>
237 {
238  static const SdfSchemaBase& GetSchema(const T* spec)
239  { return spec->_GetSpec().GetSchema(); }
240 
241  static VtValue GetField(const T* spec, const TfToken& key)
242  { return spec->_GetSpec().GetField(key); }
243 
244  template <class V>
245  static bool SetField(T* spec, const TfToken& key, const V& value)
246  { return spec->_GetSpec().SetField(key, value); }
247 
248  static bool HasField(const T* spec, const TfToken& key)
249  { return spec->_GetSpec().HasField(key); }
250 
251  static void ClearField(T* spec, const TfToken& key)
252  { spec->_GetSpec().ClearField(key); }
253 
254  static SdfSpecHandle GetSpecHandle(const T* spec)
255  { return SdfCreateNonConstHandle(&(spec->_GetSpec())); }
256 };
257 
259 
260 #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)
SdfHandleTo< T >::Handle SdfCreateNonConstHandle(T const *p)
PXR_NAMESPACE_CLOSE_SCOPE PXR_NAMESPACE_OPEN_SCOPE
Definition: path.h:1441
#define PXR_NAMESPACE_CLOSE_SCOPE
Definition: pxr.h:91
Definition: core.h:1131
Definition: value.h:167