7#ifndef PXR_BASE_VT_DICTIONARY_H
8#define PXR_BASE_VT_DICTIONARY_H
13#include "pxr/base/vt/api.h"
15#include "pxr/base/vt/value.h"
18#include "pxr/base/tf/functionRef.h"
22#include <initializer_list>
28PXR_NAMESPACE_OPEN_SCOPE
53 typedef std::map<std::string, VtValue, std::less<>> _Map;
54 std::unique_ptr<_Map> _dictMap;
66 template<
class UnderlyingMapPtr,
class UnderlyingIterator>
69 using iterator_category = std::bidirectional_iterator_tag;
70 using value_type =
typename UnderlyingIterator::value_type;
71 using reference =
typename UnderlyingIterator::reference;
72 using pointer =
typename UnderlyingIterator::pointer;
73 using difference_type =
typename UnderlyingIterator::difference_type;
81 template <
class OtherUnderlyingMapPtr,
class OtherUnderlyingIterator>
82 Iterator(Iterator<OtherUnderlyingMapPtr,
83 OtherUnderlyingIterator>
const &other)
84 : _underlyingIterator(other._underlyingIterator),
85 _underlyingMap(other._underlyingMap) {}
87 reference operator*()
const {
return *_underlyingIterator; }
88 pointer operator->()
const {
return _underlyingIterator.operator->(); }
90 Iterator& operator++() {
95 Iterator operator++(
int) {
96 Iterator result = *
this;
101 Iterator& operator--() {
102 --_underlyingIterator;
106 Iterator operator--(
int) {
107 Iterator result = *
this;
108 --_underlyingIterator;
112 template <
class OtherUnderlyingMapPtr,
class OtherUnderlyingIterator>
113 bool operator==(
const Iterator<OtherUnderlyingMapPtr,
114 OtherUnderlyingIterator>& other)
const {
118 template <
class OtherUnderlyingMapPtr,
class OtherUnderlyingIterator>
119 bool operator!=(
const Iterator<OtherUnderlyingMapPtr,
120 OtherUnderlyingIterator>& other)
const {
121 return !equal(other);
128 Iterator(UnderlyingMapPtr m, UnderlyingIterator i)
129 : _underlyingIterator(i),
131 if (m && i == m->end())
132 _underlyingMap =
nullptr;
137 UnderlyingIterator GetUnderlyingIterator(UnderlyingMapPtr map)
139 TF_AXIOM(!_underlyingMap || _underlyingMap == map);
140 return (!_underlyingMap) ? map->end() : _underlyingIterator;
150 if (!_underlyingMap) {
152 "VtDictionary iterator");
155 if (++_underlyingIterator == _underlyingMap->end()) {
156 _underlyingMap =
nullptr;
167 template <
class OtherUnderlyingMapPtr,
class OtherUnderlyingIterator>
168 bool equal(Iterator<OtherUnderlyingMapPtr,
169 OtherUnderlyingIterator>
const& other)
const {
170 if (_underlyingMap == other._underlyingMap)
171 if (!_underlyingMap ||
172 (_underlyingIterator == other._underlyingIterator))
177 UnderlyingIterator _underlyingIterator;
178 UnderlyingMapPtr _underlyingMap =
nullptr;
183 typedef _Map::key_type key_type;
184 typedef _Map::mapped_type mapped_type;
185 typedef _Map::value_type value_type;
186 typedef _Map::allocator_type allocator_type;
187 typedef _Map::size_type size_type;
189 typedef Iterator<_Map*, _Map::iterator> iterator;
190 typedef Iterator<_Map const*, _Map::const_iterator> const_iterator;
199 template<
class _InputIterator>
232 size_type
count(
const std::string& key)
const;
236 size_type
count(
const char* key)
const;
240 size_type
erase(
const std::string& key);
248 iterator
erase(iterator f, iterator l);
256 iterator
find(
const std::string& key);
260 iterator
find(
const char* key);
264 const_iterator
find(
const std::string& key)
const;
268 const_iterator
find(
const char* key)
const;
284 const_iterator
end()
const;
308 return TfHash()(*dict._dictMap);
312 template<
class _InputIterator>
313 void insert(_InputIterator f, _InputIterator l) {
316 _CreateDictIfNeeded();
317 _dictMap->insert(f, l);
323 std::pair<iterator, bool>
insert(
const value_type& obj);
326 template<
class... Args>
327 std::pair<iterator, bool>
332 _CreateDictIfNeeded();
333 std::pair<_Map::iterator, bool> inserted =
334 _dictMap->try_emplace(key, std::forward<Args>(args)...);
335 return {iterator(_dictMap.get(), inserted.first), inserted.second};
339 template<
class... Args>
340 std::pair<iterator, bool>
345 _CreateDictIfNeeded();
346 std::pair<_Map::iterator, bool> inserted =
347 _dictMap->try_emplace(std::move(key), std::forward<Args>(args)...);
348 return {iterator(_dictMap.get(), inserted.first), inserted.second};
352 template<
class... Args>
353 std::pair<iterator, bool>
358 _CreateDictIfNeeded();
359 std::pair<_Map::iterator, bool> inserted =
360 _dictMap->insert_or_assign(key, std::forward<Args>(args)...);
361 return {iterator(_dictMap.get(), inserted.first), inserted.second};
365 template<
class... Args>
366 std::pair<iterator, bool>
371 _CreateDictIfNeeded();
372 std::pair<_Map::iterator, bool> inserted =
373 _dictMap->insert_or_assign(
374 std::move(key), std::forward<Args>(args)...);
375 return {iterator(_dictMap.get(), inserted.first), inserted.second};
386 char const *delimiters =
":")
const;
403 VtValue const &value,
char const *delimiters =
":");
420 char const *delimiters =
":");
430 _SetValueAtPathImpl(std::vector<std::string>::const_iterator curKeyElem,
431 std::vector<std::string>::const_iterator keyElemEnd,
434 void _EraseValueAtPathImpl(
435 std::vector<std::string>::const_iterator curKeyElem,
436 std::vector<std::string>::const_iterator keyElemEnd);
439 void _CreateDictIfNeeded();
463 const std::string &key )
465 VtDictionary::const_iterator i = dictionary.
find(key);
466 if ( i == dictionary.
end() ) {
470 return i->second.IsHolding<T>();
479 VtDictionary::const_iterator i = dictionary.
find(key);
480 if ( i == dictionary.
end() ) {
484 return i->second.IsHolding<T>();
501 const std::string &key )
503 VtDictionary::const_iterator i = dictionary.
find(key);
504 if (ARCH_UNLIKELY(i == dictionary.
end())) {
506 "', which is not in the dictionary.");
509 return i->second.Get<T>();
518 VtDictionary::const_iterator i = dictionary.
find(key);
519 if (ARCH_UNLIKELY(i == dictionary.
end())) {
521 "which is not in the dictionary.", key);
524 return i->second.Get<T>();
531struct Vt_DefaultHolder {
532 explicit Vt_DefaultHolder(T
const &t) : val(t) {}
539struct Vt_DefaultGenerator {
541 Vt_DefaultHolder<T> operator=(T
const &t) {
542 return Vt_DefaultHolder<T>(t);
548extern VT_API Vt_DefaultGenerator VtDefault;
562template <
class T,
class U>
564 const std::string &key,
565 Vt_DefaultHolder<U>
const &def )
567 VtDictionary::const_iterator i = dictionary.
find(key);
568 if (i == dictionary.
end() || !i->second.IsHolding<T>())
570 return i->second.UncheckedGet<T>();
574template <
class T,
class U>
577 Vt_DefaultHolder<U>
const &def )
579 VtDictionary::const_iterator i = dictionary.
find(key);
580 if (i == dictionary.
end() || !i->second.IsHolding<T>())
582 return i->second.UncheckedGet<T>();
600 bool coerceToWeakerOpinionType =
false);
615 bool coerceToWeakerOpinionType =
false);
630 bool coerceToWeakerOpinionType =
false);
684struct VtDictionaryHash {
685 inline size_t operator()(
VtDictionary const &dict)
const {
690PXR_NAMESPACE_CLOSE_SCOPE
Low-level utilities for informing users of various internal and external diagnostic conditions.
#define VT_VALUE_TYPE_CAN_TRANSFORM(T)
A helper for specializing the above trait.
#define VT_VALUE_TYPE_CAN_COMPOSE(T)
A helper for specializing the above trait.
A user-extensible hashing mechanism for use with runtime hash tables.
A map with string keys and VtValue values.
VT_API void SetValueAtPath(std::string const &keyPath, VtValue const &value, char const *delimiters=":")
Set the value at keyPath to value.
VT_API size_type size() const
Returns the size of the VtDictionary.
VT_API VtValue const * GetValueAtPath(std::string const &keyPath, char const *delimiters=":") const
Return a pointer to the value at keyPath if one exists.
VT_API size_type count(const std::string &key) const
Counts the number of elements whose key is key.
VT_API const_iterator end() const
Returns an iterator pointing to the end of the VtDictionary.
VT_API void clear()
Erases all of the elements.
VT_API void SetValueAtPath(std::vector< std::string > const &keyPath, VtValue const &value)
Set the value at keyPath to value.
std::pair< iterator, bool > insert_or_assign(key_type &&key, Args &&... args)
Inserts or assigns value into the VtDictionary at key.
VT_API iterator begin()
Returns an iterator pointing to the beginning of the VtDictionary.
VT_API std::pair< iterator, bool > insert(const value_type &obj)
Inserts obj into the VtDictionary.
VT_API VtDictionary(std::initializer_list< value_type > init)
Creates a new VtDictionary from a braced initializer list.
std::pair< iterator, bool > try_emplace(const key_type &key, Args &&... args)
Attempts to insert value into the VtDictionary at key.
VT_API void swap(VtDictionary &dict)
Swaps the contents of two VtDictionaries.
VT_API iterator erase(iterator f, iterator l)
Erases all elements in a range.
VtDictionary()
Creates an empty VtDictionary.
VtDictionary(_InputIterator f, _InputIterator l)
Creates a VtDictionary with a copy of a range.
std::pair< iterator, bool > try_emplace(key_type &&key, Args &&... args)
Attempts to insert value into the VtDictionary at key.
VT_API void EraseValueAtPath(std::string const &keyPath, char const *delimiters=":")
Erase the value at keyPath.
VT_API iterator find(const char *key)
Finds an element whose key is key.
void insert(_InputIterator f, _InputIterator l)
Inserts a range into the VtDictionary.
VT_API iterator end()
Returns an iterator pointing to the end of the VtDictionary.
VT_API const_iterator find(const std::string &key) const
Finds an element whose key is key.
VT_API size_type erase(const std::string &key)
Erases the element whose key is key.
std::pair< iterator, bool > insert_or_assign(const key_type &key, Args &&... args)
Inserts or assigns value into the VtDictionary at key.
VT_API void EraseValueAtPath(std::vector< std::string > const &keyPath)
Erase the value at keyPath.
VT_API iterator find(const std::string &key)
Finds an element whose key is key.
VT_API VtDictionary(VtDictionary const &other)
Creates a copy of the supplied VtDictionary.
VT_API iterator erase(iterator it)
Erases the element pointed to by it.
VtDictionary(int size)
Creates an empty VtDictionary with at least size buckets.
VT_API bool empty() const
true if the VtDictionary's size is 0.
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 count(const char *key) const
Counts the number of elements whose key is key.
VT_API VtDictionary & operator=(VtDictionary const &other)
Copy assignment operator.
VT_API VtDictionary(VtDictionary &&other)=default
Creates a new VtDictionary by moving the supplied VtDictionary.
VT_API const_iterator begin() const
Returns an iterator pointing to the beginning of the VtDictionary.
VT_API const_iterator find(const char *key) const
Finds an element whose key is key.
VT_API VtDictionary & operator=(VtDictionary &&other)=default
Move assignment operator.
VT_API VtValue const * GetValueAtPath(std::vector< std::string > const &keyPath) const
Return a pointer to the value at keyPath if one exists.
Provides a container which may hold any type, and provides introspection and iteration over array typ...
VT_API std::ostream & operator<<(std::ostream &, VtDictionary const &)
Write the contents of a VtDictionary to a stream, formatted like "{ 'key1':value1,...
VT_API bool operator==(VtDictionary const &, VtDictionary const &)
Equality comparison.
#define TF_AXIOM(cond)
Aborts if the condition cond is not met.
#define TF_FATAL_ERROR(fmt, args)
Issue a fatal error and end the program.
VT_API VtDictionary VtDictionaryOverRecursive(const VtDictionary &strong, const VtDictionary &weak)
Returns a dictionary containing strong recursively composed over weak.
const T & VtDictionaryGet(const VtDictionary &dictionary, const std::string &key)
Return a value held in a VtDictionary by reference.
VT_API VtDictionary VtDictionaryOver(const VtDictionary &strong, const VtDictionary &weak, bool coerceToWeakerOpinionType=false)
Creates a dictionary containing strong composed over weak.
bool VtDictionaryIsHolding(const VtDictionary &dictionary, const std::string &key)
Returns true if dictionary contains key and the corresponding value is of type T.
#define TF_MALLOC_TAG_NEW(name1, name2)
Enable lib/tf memory management.
size_t hash_value(const TfToken &x)
Overload hash_value for TfToken.