HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
resolverContext.h
Go to the documentation of this file.
1 //
2 // Copyright 2020 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_AR_RESOLVER_CONTEXT_H
25 #define PXR_USD_AR_RESOLVER_CONTEXT_H
26 
27 /// \file ar/resolverContext.h
28 
29 #include "pxr/pxr.h"
30 #include "pxr/usd/ar/api.h"
31 #include "pxr/usd/ar/ar.h"
32 
33 #include "pxr/base/tf/hash.h"
35 
36 #ifdef PXR_PYTHON_SUPPORT_ENABLED
37 // XXX: This include is a hack to avoid build errors due to
38 // incompatible macro definitions in pyport.h on macOS.
39 #include <locale>
40 #include "pxr/base/tf/pyLock.h"
41 #endif
42 
44 
45 #include <algorithm>
46 #include <memory>
47 #include <string>
48 #include <type_traits>
49 #include <typeinfo>
50 #include <vector>
51 
53 
54 /// \class ArIsContextObject
55 ///
56 /// Metafunction to determine whether the templated object type is a
57 /// valid context object.
58 ///
59 template <class T>
61 {
62  static const bool value = false;
63 };
64 
65 /// Default implementation for providing debug info on the contained context.
66 template <class Context>
67 std::string ArGetDebugString(const Context& context);
68 
69 // Metafunctions for determining if a variadic list of objects
70 // are valid for use with the ArResolverContext c'tor.
71 class ArResolverContext;
72 
73 template <class ...Objects> struct Ar_AllValidForContext;
74 
75 template <class Object, class ...Other>
76 struct Ar_AllValidForContext<Object, Other...>
77 {
78  static const bool value =
82 };
83 
84 template <>
86 {
87  static const bool value = true;
88 };
89 
90 /// \class ArResolverContext
91 ///
92 /// An asset resolver context allows clients to provide additional data
93 /// to the resolver for use during resolution. Clients may provide this
94 /// data via context objects of their own (subject to restrictions below).
95 /// An ArResolverContext is simply a wrapper around these objects that
96 /// allows it to be treated as a single type. Note that an ArResolverContext
97 /// may not hold multiple context objects with the same type.
98 ///
99 /// A client-defined context object must provide the following:
100 /// - Default and copy constructors
101 /// - operator<
102 /// - operator==
103 /// - An overload for size_t hash_value(const T&)
104 ///
105 /// Note that the user may define a free function:
106 ///
107 /// std::string ArGetDebugString(const Context& ctx);
108 /// (Where Context is the type of the user's path resolver context.)
109 ///
110 /// This is optional; a default generic implementation has been predefined.
111 /// This function should return a string representation of the context
112 /// to be utilized for debugging purposes(such as in TF_DEBUG statements).
113 ///
114 /// The ArIsContextObject template must also be specialized for this
115 /// object to declare that it can be used as a context object. This is to
116 /// avoid accidental use of an unexpected object as a context object.
117 /// The AR_DECLARE_RESOLVER_CONTEXT macro can be used to do this
118 /// as a convenience.
119 ///
120 /// \sa AR_DECLARE_RESOLVER_CONTEXT
121 /// \sa ArResolver::BindContext
122 /// \sa ArResolver::UnbindContext
123 /// \sa ArResolverContextBinder
125 {
126 public:
127  /// Construct an empty asset resolver context.
129  {
130  }
131 
132  /// Construct a resolver context using the given objects \p objs.
133  ///
134  /// Each argument must either be an ArResolverContext or a registered
135  /// context object. See class documentation for requirements on context
136  /// objects.
137  ///
138  /// If an argument is a context object, it will be added to the
139  /// constructed ArResolverContext. If an argument is an ArResolverContext,
140  /// all of the context objects it holds will be added to the constructed
141  /// ArResolverContext.
142  ///
143  /// Arguments are ordered from strong-to-weak. If a context object is
144  /// encountered with the same type as a previously-added object, the
145  /// previously-added object will remain and the other context object
146  /// will be ignored.
147  template <
148  class ...Objects,
149  typename std::enable_if<Ar_AllValidForContext<Objects...>::value>::type*
150  = nullptr>
151  ArResolverContext(const Objects&... objs)
152  {
153  _AddObjects(objs...);
154  }
155 
156  /// Construct a resolver context using the ArResolverContexts in \p ctxs.
157  ///
158  /// All of the context objects held by each ArResolverContext in \p ctxs
159  /// will be added to the constructed ArResolverContext.
160  ///
161  /// Arguments are ordered from strong-to-weak. If a context object is
162  /// encountered with the same type as a previously-added object, the
163  /// previously-added object will remain and the other context object
164  /// will be ignored.
165  AR_API
166  explicit ArResolverContext(const std::vector<ArResolverContext>& ctxs);
167 
168  /// Returns whether this resolver context is empty.
169  bool IsEmpty() const
170  {
171  return _contexts.empty();
172  }
173 
174  /// Returns pointer to the context object of the given type
175  /// held in this resolver context. Returns NULL if this resolver
176  /// context is not holding an object of the requested type.
177  template <class ContextObj>
178  const ContextObj* Get() const
179  {
180  for (const auto& context : _contexts) {
181  if (context->IsHolding(typeid(ContextObj))) {
182  return &_GetTyped<ContextObj>(*context)._context;
183  }
184  }
185  return nullptr;
186  }
187 
188  /// Returns a debug string representing the contained context objects.
189  AR_API
190  std::string GetDebugString() const;
191 
192  /// \name Operators
193  /// @{
194  AR_API
195  bool operator==(const ArResolverContext& rhs) const;
196 
197  bool operator!=(const ArResolverContext& rhs) const
198  {
199  return !(*this == rhs);
200  }
201 
202  AR_API
203  bool operator<(const ArResolverContext& rhs) const;
204 
205  /// @}
206 
207  /// Returns hash value for this asset resolver context.
208  friend size_t hash_value(const ArResolverContext& context)
209  {
210  return TfHash()(context._contexts);
211  }
212 
213 private:
214  // Type-erased storage for context objects.
215  struct _Untyped;
216  template <class Context> struct _Typed;
217 
218  void _AddObjects()
219  {
220  // Empty base case for unpacking parameter pack
221  }
222 
223  template <class Object, class ...Other>
224  void _AddObjects(const Object& obj, const Other&... other)
225  {
226  _Add(obj);
227  _AddObjects(other...);
228  }
229 
230  AR_API
231  void _Add(const ArResolverContext& ctx);
232 
233  template <class Object>
234  void _Add(const Object& obj)
235  {
236  _Add(std::shared_ptr<_Untyped>(new _Typed<Object>(obj)));
237  }
238 
239  AR_API
240  void _Add(std::shared_ptr<_Untyped>&& context);
241 
242  template <class Context>
243  static const _Typed<Context>& _GetTyped(const _Untyped& untyped)
244  {
245  return static_cast<const _Typed<Context>&>(untyped);
246  }
247 
248  struct _Untyped
249  {
250  AR_API
251  virtual ~_Untyped();
252 
253  bool IsHolding(const std::type_info& ti) const
254  {
255  return TfSafeTypeCompare(ti, GetTypeid());
256  }
257 
258  virtual _Untyped* Clone() const = 0;
259  virtual const std::type_info& GetTypeid() const = 0;
260  virtual bool LessThan(const _Untyped& rhs) const = 0;
261  virtual bool Equals(const _Untyped& rhs) const = 0;
262  virtual size_t Hash() const = 0;
263  virtual std::string GetDebugString() const = 0;
264  virtual TfPyObjWrapper GetPythonObj() const = 0;
265  };
266 
267  template <class Context>
268  struct _Typed : public _Untyped
269  {
270  virtual ~_Typed() { }
271 
272  _Typed(const Context& context) : _context(context)
273  {
274  }
275 
276  virtual _Untyped* Clone() const
277  {
278  return new _Typed<Context>(_context);
279  }
280 
281  virtual const std::type_info& GetTypeid() const
282  {
283  return typeid(Context);
284  }
285 
286  virtual bool LessThan(const _Untyped& rhs) const
287  {
288  return _context < _GetTyped<Context>(rhs)._context;
289  }
290 
291  virtual bool Equals(const _Untyped& rhs) const
292  {
293  return _context == _GetTyped<Context>(rhs)._context;
294  }
295 
296  virtual size_t Hash() const
297  {
298  return hash_value(_context);
299  }
300 
301  virtual std::string GetDebugString() const
302  {
303  return ArGetDebugString(_context);
304  }
305 
306  virtual TfPyObjWrapper GetPythonObj() const
307  {
308  #ifdef PXR_PYTHON_SUPPORT_ENABLED
309  TfPyLock lock;
310  return hboost::python::object(_context);
311 #else
312  return {};
313 #endif
314  }
315 
316  Context _context;
317  };
318 
319  template <class HashState>
320  friend void TfHashAppend(
321  HashState& h, const std::shared_ptr<_Untyped>& context)
322  {
323  h.Append(context->Hash());
324  }
325 
326 #ifdef PXR_PYTHON_SUPPORT_ENABLED
327  friend class Ar_ResolverContextPythonAccess;
328 #endif
329 
330  std::vector<std::shared_ptr<_Untyped>> _contexts;
331 };
332 
333 
334 // Default implementation for streaming out held contexts.
335 AR_API
336 std::string Ar_GetDebugString(const std::type_info&, void const*);
337 
338 template <class Context>
340 {
341  return Ar_GetDebugString(typeid(Context),
342  static_cast<void const*>(&context));
343 }
344 
346 
347 #endif
friend size_t hash_value(const ArResolverContext &context)
Returns hash value for this asset resolver context.
AR_API bool operator==(const ArResolverContext &rhs) const
bool operator!=(const ArResolverContext &rhs) const
STATIC_INLINE size_t Hash(const char *s, size_t len)
Definition: farmhash.h:2038
const ContextObj * Get() const
GLsizei const GLchar *const * string
Definition: glcorearb.h:814
GLsizei const GLfloat * value
Definition: glcorearb.h:824
AR_API std::string Ar_GetDebugString(const std::type_info &, void const *)
AR_API std::string GetDebugString() const
Returns a debug string representing the contained context objects.
#define AR_API
Definition: api.h:40
AR_API bool operator<(const ArResolverContext &rhs) const
Definition: hash.h:504
class OCIOEXPORT Context
ArResolverContext(const Objects &...objs)
bool IsEmpty() const
Returns whether this resolver context is empty.
std::string ArGetDebugString(const Context &context)
Default implementation for providing debug info on the contained context.
ArResolverContext()
Construct an empty asset resolver context.
GLfloat GLfloat GLfloat GLfloat h
Definition: glcorearb.h:2002
friend void TfHashAppend(HashState &h, const std::shared_ptr< _Untyped > &context)
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
PXR_NAMESPACE_OPEN_SCOPE bool TfSafeTypeCompare(const std::type_info &t1, const std::type_info &t2)
type
Definition: core.h:1059