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