All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
dictionary.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 VT_DICTIONARY_H
25 #define VT_DICTIONARY_H
26 
28 
29 #include "pxr/pxr.h"
30 #include "pxr/base/vt/api.h"
31 #include "pxr/base/vt/value.h"
32 
33 #include "pxr/base/tf/hash.h"
34 #include "pxr/base/tf/mallocTag.h"
35 
36 #include <boost/functional/hash.hpp>
37 #include <boost/iterator/iterator_adaptor.hpp>
38 
39 #include <initializer_list>
40 #include <iosfwd>
41 #include <memory>
42 
43 PXR_NAMESPACE_OPEN_SCOPE
44 
47 
61 class VtDictionary {
62  typedef std::map<std::string, VtValue> _Map;
63  std::unique_ptr<_Map> _dictMap;
64 
65 public:
66  // The iterator class, used to make both const and non-const iterators.
67  // Currently only forward traversal is supported. In order to support lazy
68  // allocation, VtDictionary's Map pointer (_dictMap) must be nullable,
69  // but that would break the VtDictionary iterators. So instead, VtDictionary
70  // uses this Iterator class, which considers an iterator to an empty
71  // VtDictionary to be the same as an iterator at the end of a VtDictionary
72  // (i.e. if Iterator's _dictMap pointer is null, that either means that the
73  // VtDictionary is empty, or the Iterator is at the end of a VtDictionary
74  // that contains values).
75  template<class UnderlyingMapPtr, class UnderlyingIterator>
76  class Iterator : public boost::iterator_adaptor<Iterator<UnderlyingMapPtr,
77  UnderlyingIterator>, UnderlyingIterator> {
78  public:
79  // Default constructor creates an Iterator equivalent to end() (i.e.
80  // UnderlyingMapPtr is null)
81  Iterator()
82  : Iterator::iterator_adaptor_(UnderlyingIterator())
83  , _underlyingMap(0) {}
84 
85  // Copy constructor (also allows for converting non-const to const).
86  template <class OtherUnderlyingMapPtr, class OtherUnderlyingIterator>
87  Iterator(Iterator<OtherUnderlyingMapPtr,
88  OtherUnderlyingIterator> const &other)
89  : Iterator::iterator_adaptor_(other.base())
90  , _underlyingMap(other._underlyingMap) {}
91 
92  private:
93  // Private constructor allowing the find, begin and insert methods
94  // to create and return the proper Iterator.
95  Iterator(UnderlyingMapPtr m, UnderlyingIterator i)
96  : Iterator::iterator_adaptor_(i)
97  , _underlyingMap(m) {
98  if (m && i == m->end())
99  _underlyingMap = 0;
100  }
101 
102  friend class boost::iterator_core_access;
103  friend class VtDictionary;
104 
105  UnderlyingIterator GetUnderlyingIterator(UnderlyingMapPtr map)
106  const {
107  TF_AXIOM(!_underlyingMap || _underlyingMap == map);
108  return (!_underlyingMap) ? map->end() : this->base();
109  }
110 
111  // Fundamental functionality to implement the iterator.
112  // boost::iterator_adaptor will invoke these as necessary to implement
113  // the full iterator public interface.
114 
115  // Increments the underlying iterator, and sets the underlying map to
116  // null when the iterator reaches the end of the map.
117  void increment() {
118  if (!_underlyingMap) {
119  TF_FATAL_ERROR("Attempted invalid increment operation on a "
120  "VtDictionary iterator");
121  return;
122  }
123  if (++this->base_reference() == _underlyingMap->end()) {
124  _underlyingMap = 0;
125  }
126  }
127 
128  // Equality comparison. Iterators are considered equal if:
129  // 1) They both point to empty VtDictionaries
130  // 2) They both point to the end() of a VtDictionary
131  // - or-
132  // 3) They both point to the same VtDictionary and their
133  // boost::iterator_adaptors' base() iterators are the same
134  // In cases 1 and 2 above, _underlyingMap will be null
135  template <class OtherUnderlyingMapPtr, class OtherUnderlyingIterator>
136  bool equal(Iterator<OtherUnderlyingMapPtr,
137  OtherUnderlyingIterator> const& i) const {
138  if (_underlyingMap == i._underlyingMap)
139  if (!_underlyingMap || this->base() == i.base())
140  return true;
141  return false;
142  }
143 
144  UnderlyingMapPtr _underlyingMap;
145  };
146 
147  TF_MALLOC_TAG_NEW("Vt", "VtDictionary");
148 
149  typedef _Map::key_type key_type;
150  typedef _Map::mapped_type mapped_type;
151  typedef _Map::value_type value_type;
152  typedef _Map::allocator_type allocator_type;
153  typedef _Map::size_type size_type;
154 
155  typedef Iterator<_Map*, _Map::iterator> iterator;
156  typedef Iterator<_Map const*, _Map::const_iterator> const_iterator;
157 
160 
162  explicit VtDictionary(int size) {}
163 
165  template<class _InputIterator>
166  VtDictionary(_InputIterator f, _InputIterator l){
167  TfAutoMallocTag2 tag("Vt", "VtDictionary::VtDictionary (range)");
168  insert(f, l);
169  }
170 
172  VT_API
173  VtDictionary(VtDictionary const& other);
174 
176  VT_API
177  VtDictionary(VtDictionary && other) = default;
178 
180  VT_API
181  VtDictionary(std::initializer_list<value_type> init);
182 
184  VT_API
185  VtDictionary& operator=(VtDictionary const& other);
186 
188  VT_API
189  VtDictionary& operator=(VtDictionary && other) = default;
190 
193  VT_API
194  VtValue& operator[](const std::string& key);
195 
197  VT_API
198  size_type count(const std::string& key) const;
199 
201  VT_API
202  size_type erase(const std::string& key);
203 
205  VT_API
206  void erase(iterator it);
207 
209  VT_API
210  void erase(iterator f, iterator l);
211 
213  VT_API
214  void clear();
215 
217  VT_API
218  iterator find(const std::string& key);
219 
221  VT_API
222  const_iterator find(const std::string& key) const;
223 
225  VT_API
226  iterator begin();
227 
229  VT_API
230  const_iterator begin() const;
231 
233  VT_API
234  iterator end();
235 
237  VT_API
238  const_iterator end() const;
239 
241  VT_API
242  size_type size() const;
243 
245  VT_API
246  bool empty() const;
247 
249  VT_API
250  void swap(VtDictionary& dict);
251 
252  // Global overload for swap for unqualified calls in generic code.
253  friend void swap(VtDictionary &lhs, VtDictionary &rhs) {
254  lhs.swap(rhs);
255  }
256 
257  friend size_t hash_value(VtDictionary const &dict) {
258  // Hash empty dict as zero.
259  if (dict.empty())
260  return 0;
261  // Otherwise hash the map.
262  return boost::hash_value(*dict._dictMap);
263  }
264 
266  template<class _InputIterator>
267  void insert(_InputIterator f, _InputIterator l) {
268  TfAutoMallocTag2 tag("Vt", "VtDictionary::insert (range)");
269  if (f != l) {
270  _CreateDictIfNeeded();
271  _dictMap->insert(f, l);
272  }
273  }
274 
276  VT_API
277  std::pair<iterator, bool> insert(const value_type& obj);
278 
284  VT_API
285  VtValue const *
286  GetValueAtPath(std::string const &keyPath,
287  char const *delimiters = ":") const;
288 
292  VT_API
293  VtValue const *
294  GetValueAtPath(std::vector<std::string> const &keyPath) const;
295 
302  VT_API
303  void SetValueAtPath(std::string const &keyPath,
304  VtValue const &value, char const *delimiters = ":");
305 
310  VT_API
311  void SetValueAtPath(std::vector<std::string> const &keyPath,
312  VtValue const &value);
313 
319  VT_API
320  void EraseValueAtPath(std::string const &keyPath,
321  char const *delimiters = ":");
322 
326  VT_API
327  void EraseValueAtPath(std::vector<std::string> const &keyPath);
328 
329 private:
330  void
331  _SetValueAtPathImpl(std::vector<std::string>::const_iterator curKeyElem,
332  std::vector<std::string>::const_iterator keyElemEnd,
333  VtValue const &value);
334 
335  void _EraseValueAtPathImpl(
336  std::vector<std::string>::const_iterator curKeyElem,
337  std::vector<std::string>::const_iterator keyElemEnd);
338 
339  void _CreateDictIfNeeded();
340 
341 };
342 
344 VT_API bool operator==(VtDictionary const &, VtDictionary const &);
345 VT_API bool operator!=(VtDictionary const &, VtDictionary const &);
346 
349 VT_API std::ostream &operator<<(std::ostream &, VtDictionary const &);
350 
351 //
352 // Return a const reference to an empty VtDictionary.
353 //
354 VT_API VtDictionary const &VtGetEmptyDictionary();
355 
360 template <typename T>
361 bool
363  const std::string &key )
364 {
365  VtDictionary::const_iterator i = dictionary.find(key);
366  if ( i == dictionary.end() ) {
367  return false;
368  }
369 
370  return i->second.IsHolding<T>();
371 }
372 
373 
384 template <typename T>
385 const T &
386 VtDictionaryGet( const VtDictionary &dictionary,
387  const std::string &key )
388 {
389  VtDictionary::const_iterator i = dictionary.find(key);
390  if (ARCH_UNLIKELY(i == dictionary.end())) {
391  TF_FATAL_ERROR("Attempted to get value for key '" + key +
392  "', which is not in the dictionary.");
393  }
394 
395  return i->second.Get<T>();
396 }
397 
398 
399 // This is an internal holder class that is used in the version of
400 // VtDictionaryGet that takes a default.
401 template <class T>
402 struct Vt_DefaultHolder {
403  explicit Vt_DefaultHolder(T const &t) : val(t) {}
404  T const &val;
405 };
406 
407 // This internal class has a very unusual assignment operator that returns an
408 // instance of Vt_DefaultHolder, holding any type T. This is used to get the
409 // "VtDefault = X" syntax for VtDictionaryGet.
410 struct Vt_DefaultGenerator {
411  template <class T>
412  Vt_DefaultHolder<T> operator=(T const &t) {
413  return Vt_DefaultHolder<T>(t);
414  }
415 };
416 
417 // This is a global stateless variable used to get the VtDefault = X syntax in
418 // VtDictionaryGet.
419 extern VT_API Vt_DefaultGenerator VtDefault;
420 
433 template <class T, class U>
434 T VtDictionaryGet( const VtDictionary &dictionary,
435  const std::string &key,
436  Vt_DefaultHolder<U> const &def )
437 {
438  VtDictionary::const_iterator i = dictionary.find(key);
439  if (i == dictionary.end() || !i->second.IsHolding<T>())
440  return def.val;
441  return i->second.Get<T>();
442 }
443 
444 
445 
457 VT_API VtDictionary
458 VtDictionaryOver(const VtDictionary &strong, const VtDictionary &weak,
459  bool coerceToWeakerOpinionType = false);
460 
472 VT_API void
473 VtDictionaryOver(VtDictionary *strong, const VtDictionary &weak,
474  bool coerceToWeakerOpinionType = false);
475 
487 VT_API void
488 VtDictionaryOver(const VtDictionary &strong, VtDictionary *weak,
489  bool coerceToWeakerOpinionType = false);
490 
509 VT_API VtDictionary
510 VtDictionaryOverRecursive(const VtDictionary &strong, const VtDictionary &weak,
511  bool coerceToWeakerOpinionType = false);
512 
530 VT_API void
532  bool coerceToWeakerOpinionType = false);
533 
554 VT_API void
556  bool coerceToWeakerOpinionType = false);
557 
558 
559 struct VtDictionaryHash {
560  inline size_t operator()(VtDictionary const &dict) const {
561  return hash_value(dict);
562  }
563 };
564 
565 PXR_NAMESPACE_CLOSE_SCOPE
566 
567 #endif /* VT_DICTIONARY_H */
VT_API iterator end()
Returns an iterator pointing to the end of the VtDictionary.
VT_API VtDictionary VtDictionaryOverRecursive(const VtDictionary &strong, const VtDictionary &weak, bool coerceToWeakerOpinionType=false)
Returns a dictionary containing strong recursively composed over weak.
VT_API void swap(VtDictionary &dict)
Swaps the contents of two VtDictionaries.
VT_API VtValue & operator[](const std::string &key)
Returns a reference to the VtValue that is associated with a particular key.
VT_API size_type size() const
Returns the size of the VtDictionary.
VT_API iterator find(const std::string &key)
Finds an element whose key is key.
A map with string keys and VtValue values.
Definition: dictionary.h:61
AR_API bool operator!=(const ArAssetInfo &lhs, const ArAssetInfo &rhs)
AR_API bool operator==(const ArAssetInfo &lhs, const ArAssetInfo &rhs)
VT_API iterator begin()
Returns an iterator pointing to the beginning of the VtDictionary.
VT_API size_type erase(const std::string &key)
Erases the element whose key is key.
void insert(_InputIterator f, _InputIterator l)
Inserts a range into the VtDictionary.
Definition: dictionary.h:267
VtDictionary(int size)
Creates an empty VtDictionary with at least size buckets.
Definition: dictionary.h:162
Scoped (i.e.
Definition: mallocTag.h:349
const T & VtDictionaryGet(const VtDictionary &dictionary, const std::string &key)
Return a value held in a VtDictionary by reference.
Definition: dictionary.h:386
VT_API size_type count(const std::string &key) const
Counts the number of elements whose key is key.
#define TF_FATAL_ERROR(fmt, args)
Issue a fatal error and end the program.
Definition: diagnostic.h:111
VtDictionary()
Creates an empty VtDictionary.
Definition: dictionary.h:159
VT_API VtDictionary VtDictionaryOver(const VtDictionary &strong, const VtDictionary &weak, bool coerceToWeakerOpinionType=false)
Creates a dictionary containing strong composed over weak.
GF_API std::ostream & operator<<(std::ostream &, const GfBBox3d &)
Output a GfBBox3d using the format [(range) matrix zeroArea].
VT_API VtValue const * GetValueAtPath(std::string const &keyPath, char const *delimiters=":") const
Return a pointer to the value at keyPath if one exists.
#define TF_AXIOM(cond)
Aborts if the condition cond is not met.
Definition: diagnostic.h:215
VT_API void EraseValueAtPath(std::string const &keyPath, char const *delimiters=":")
Erase the value at keyPath.
VtDictionary(_InputIterator f, _InputIterator l)
Creates a VtDictionary with a copy of a range.
Definition: dictionary.h:166
VT_API void clear()
Erases all of the elements.
VT_API void SetValueAtPath(std::string const &keyPath, VtValue const &value, char const *delimiters=":")
Set the value at keyPath to value.
Provides a container which may hold any type, and provides introspection and iteration over array typ...
Definition: value.h:182
VT_API VtDictionary & operator=(VtDictionary const &other)
Copy assignment operator.
bool VtDictionaryIsHolding(const VtDictionary &dictionary, const std::string &key)
Returns true if dictionary contains key and the corresponding value is of type T. ...
Definition: dictionary.h:362
VT_API bool empty() const
true if the VtDictionary&#39;s size is 0.