HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
mapEditProxy.h
Go to the documentation of this file.
1 //
2 // Copyright 2016 Pixar
3 //
4 // Licensed under the terms set forth in the LICENSE.txt file available at
5 // https://openusd.org/license.
6 //
7 #ifndef PXR_USD_SDF_MAP_EDIT_PROXY_H
8 #define PXR_USD_SDF_MAP_EDIT_PROXY_H
9 
10 /// \file sdf/mapEditProxy.h
11 
12 #include "pxr/pxr.h"
13 #include "pxr/usd/sdf/allowed.h"
16 #include "pxr/usd/sdf/mapEditor.h"
17 #include "pxr/usd/sdf/spec.h"
18 
19 #include "pxr/base/vt/value.h" // for Vt_DefaultValueFactory
20 #include "pxr/base/tf/diagnostic.h"
21 #include "pxr/base/tf/iterator.h"
22 #include "pxr/base/tf/mallocTag.h"
23 #include <iterator>
24 #include <utility>
25 
27 
28 class TfToken;
29 
31 
32 /// \class SdfIdentityMapEditProxyValuePolicy
33 ///
34 /// A value policy for \c SdfMapEditProxy that does nothing.
35 ///
36 /// A \c SdfMapEditProxy value policy converts incoming keys and values
37 /// into a canonical form used for storage. This is useful if you have
38 /// a key where multiple values are equivalent for the purposes of the
39 /// map but don't compare equal and you can store any one of the
40 /// equivalent values. Note that the policy is only used on inputs to
41 /// the map proxy; it's never used when returning keys or values from
42 /// the proxy.
43 ///
44 template <class T>
46 public:
47  typedef T Type;
48  typedef typename Type::key_type key_type;
49  typedef typename Type::mapped_type mapped_type;
50  typedef typename Type::value_type value_type;
51 
52  /// Canonicalize an entire \c Type object. \c Type must be convertible
53  /// to the type of \p x. The return value must be convertible to a
54  /// \c Type.
55  static const Type& CanonicalizeType(const SdfSpecHandle&, const Type& x)
56  {
57  return x;
58  }
59 
60  /// Canonicalize a key. \c key_type must be convertible to the type of
61  /// \p x. The return value must be convertible to a \c key_type.
62  static const key_type& CanonicalizeKey(const SdfSpecHandle&,
63  const key_type& x)
64  {
65  return x;
66  }
67 
68  /// Canonicalize a value. \c mapped_type must be convertible to the type
69  /// of \p x. The return value must be convertible to a \c mapped_type.
70  static const mapped_type& CanonicalizeValue(const SdfSpecHandle&,
71  const mapped_type& x)
72  {
73  return x;
74  }
75 
76  /// Canonicalize a key/value pair. \c value_type must be convertible
77  /// to the type of \p x. The return value must be convertible to a
78  /// \c value_type.
79  static const value_type& CanonicalizePair(const SdfSpecHandle&,
80  const value_type& x)
81  {
82  return x;
83  }
84 };
85 
86 /// \class SdfMapEditProxy
87 ///
88 /// A proxy for editing map-like values.
89 ///
90 /// A \c SdfMapEditProxy provides an interface for editing fields
91 /// containing map-like values. The proxy allows consumers to
92 /// interact with these values like a typical std::map while
93 /// taking into account additional editing and validation policies.
94 ///
95 /// The \c _ValuePolicy is used to canonicalize keys and values before
96 /// storage or comparison.
97 ///
98 /// \sa SdfIdentityMapEditProxyValuePolicy
99 ///
100 template <class T, class _ValuePolicy = SdfIdentityMapEditProxyValuePolicy<T> >
102 public:
103  typedef T Type;
104  typedef _ValuePolicy ValuePolicy;
106  typedef typename Type::key_type key_type;
107  typedef typename Type::mapped_type mapped_type;
108  typedef typename Type::value_type value_type;
109 
110 private:
111  // Note: We're playing a dangerous game with copy-on-write and
112  // iterators. Our iterators wrap iterators on the proxied
113  // Type. When and if we copy-on-write then all of our
114  // existing iterators use the old proxied object's iterators
115  // and any new iterators will use the new proxied object's
116  // iterators. Therefore old and new iterators are no longer
117  // compatible and an old and new iterator that refer to the
118  // same key will not compare equal.
119  //
120  // It turns out that this is okay because we don't promise
121  // to keep iterators valid across an edit. However, we'd
122  // like dereferencing an old iterator to either report an
123  // error or yield the current state. We can do that by
124  // storing the Type* in use when the iterator was created
125  // and comparing it to the current Type*. If they're
126  // different we need to report an error or use the key from
127  // the old iterator and lookup that key in the new Type*.
128  // We currently choose to return the current state.
129 
130  typedef typename Type::iterator inner_iterator;
131  typedef typename Type::const_iterator const_inner_iterator;
132 
133  class _ValueProxy {
134  public:
135  _ValueProxy(This* owner, const Type* data, inner_iterator i) :
136  _owner(owner), _data(data), _pos(i)
137  {
138  // Do nothing
139  }
140 
141  template <class U>
142  _ValueProxy& operator=(const U& other)
143  {
144  if (!_owner) {
145  TF_CODING_ERROR("Assignment to invalid map proxy");
146  } else {
147  _owner->_Set(_data, _pos, other);
148  }
149  return *this;
150  }
151 
152  operator mapped_type() const
153  {
154  return Get();
155  }
156 
157  // Required for _PairProxy::operator value_type().
158  mapped_type Get() const
159  {
160  if (!_owner) {
161  TF_CODING_ERROR("Read from invalid map proxy");
162  return mapped_type();
163  }
164  return _owner->_Get(_data, _pos);
165  }
166 
167  private:
168  This* _owner;
169  const Type* _data;
170  inner_iterator _pos;
171  };
172 
173  class _PairProxy {
174  public:
175  explicit _PairProxy(This* owner, const Type* data, inner_iterator i) :
176  first(i->first), second(_ValueProxy(owner, data, i)) { }
177 
178  const key_type first;
179  _ValueProxy second;
180 
181  operator value_type() const
182  {
183  // Note that we cannot simply use 'second' or we'll use the
184  // mapped_type c'tor instead of the _ValueProxy implicit
185  // conversion if one is available. If mapped_type is VtValue
186  // then we'll type erase _ValueProxy instead of just getting
187  // the VtValue out of the _ValueProxy.
188  return value_type(first, second.Get());
189  }
190  };
191 
192  class Traits {
193  public:
194  static _PairProxy Dereference(This* owner,
195  const Type* data, inner_iterator i)
196  {
197  if (!owner) {
198  TF_FATAL_ERROR("Dereferenced an invalid map proxy iterator");
199  }
200  return _PairProxy(owner, data, i);
201  }
202 
203  static const value_type& Dereference(const This* owner,
204  const Type* data,
205  const_inner_iterator i)
206  {
207  if (!owner) {
208  TF_FATAL_ERROR("Dereferenced an invalid map proxy iterator");
209  }
210  return owner->_Get(data, i);
211  }
212  };
213 
214  template <class Owner, class I, class R>
215  class _Iterator {
216  class _PtrProxy {
217  public:
218  std::add_pointer_t<R> operator->() {
219  return std::addressof(_result);
220  }
221  private:
222  friend class _Iterator;
223  explicit _PtrProxy(const R& result) : _result(result) {}
224  R _result;
225  };
226  public:
227  using iterator_category = std::bidirectional_iterator_tag;
228  using value_type = R;
229  using reference = R;
231  std::add_pointer_t<R>, _PtrProxy>;
232  using difference_type = std::ptrdiff_t;
233 
234  _Iterator() = default;
235 
236  _Iterator(Owner owner, const Type* data, I i) :
237  _owner(owner), _data(data), _pos(i)
238  {
239  // Do nothing
240  }
241 
242  template <class Owner2, class I2, class R2>
243  _Iterator(const _Iterator<Owner2, I2, R2>& other) :
244  _owner(other._owner), _data(other._data), _pos(other._pos)
245  {
246  // Do nothing
247  }
248 
249  reference operator*() const { return dereference(); }
250 
251  // In C++20, when pointer can be `void` and `operator->` elided,
252  // this conditional behavior may be deprecated. The `operator->`
253  // implementation is keyed off of whether the underlying pointer
254  // requires a proxy type
255  template <typename PointerType=pointer,
256  typename std::enable_if_t<
258  pointer operator->() const { return std::addressof(dereference()); }
259  template <typename PointerType=pointer,
260  typename std::enable_if_t<
262  pointer operator->() const { return pointer(dereference()); }
263 
264 
265  const I& base() const
266  {
267  return _pos;
268  }
269 
270  _Iterator& operator++() {
271  increment();
272  return *this;
273  }
274 
275  _Iterator& operator--() {
276  decrement();
277  return *this;
278  }
279 
280  _Iterator operator++(int) {
281  _Iterator result(*this);
282  increment();
283  return result;
284  }
285 
286  _Iterator operator--(int) {
287  _Iterator result(*this);
288  decrement();
289  return result;
290  }
291 
292  template <class Owner2, class I2, class R2>
293  bool operator==(const _Iterator<Owner2, I2, R2>& other) const {
294  return equal(other);
295  }
296 
297  template <class Owner2, class I2, class R2>
298  bool operator!=(const _Iterator<Owner2, I2, R2>& other) const {
299  return !equal(other);
300  }
301 
302  private:
303  R dereference() const
304  {
305  return Traits::Dereference(_owner, _data, _pos);
306  }
307 
308  template <class Owner2, class I2, class R2>
309  bool equal(const _Iterator<Owner2, I2, R2>& other) const
310  {
311  if (_owner == other._owner && _pos == other._pos) {
312  return true;
313  }
314  else {
315  // All iterators at the end compare equal.
316  return atEnd() && other.atEnd();
317  }
318  }
319 
320  void increment() {
321  ++_pos;
322  }
323 
324  void decrement() {
325  --_pos;
326  }
327 
328  bool atEnd() const {
329  // We consider an iterator with no owner to be at the end.
330  return !_owner || _pos == _owner->_ConstData()->end();
331  }
332 
333  private:
334  Owner _owner = nullptr;
335  const Type* _data = nullptr;
336  I _pos;
337 
338  template <class Owner2, class I2, class R2> friend class _Iterator;
339  };
340 
341 public:
342  typedef _ValueProxy reference;
343  typedef const value_type& const_reference;
344  typedef size_t size_type;
345  typedef ptrdiff_t difference_type;
346  typedef _Iterator<This*, inner_iterator, _PairProxy> iterator;
347  typedef _Iterator<const This*, const_inner_iterator,
351 
352  explicit SdfMapEditProxy(const SdfSpecHandle& owner, const TfToken& field) :
353  _editor(Sdf_CreateMapEditor<T>(owner, field))
354  {
355  // Do nothing
356  }
357 
359  {
360  // Do nothing
361  }
362 
363  This& operator=(const This& other)
364  {
365  if (other._Validate()) {
366  _Copy(*other._ConstData());
367  }
368  return *this;
369  }
370 
371  template <class U, class UVP>
373  {
374  if (other._Validate()) {
375  _Copy(Type(other._ConstData()->begin(), other._ConstData()->end()));
376  }
377  return *this;
378  }
379 
380  This& operator=(const Type& data)
381  {
382  _Copy(data);
383  return *this;
384  }
385 
386  /// Returns a copy of the value.
387  operator Type() const
388  {
389  return _Validate() ? *_ConstData() : Type();
390  }
391 
393  {
394  return _Validate() ? iterator(this, _Data(), _Data()->begin()) :
395  iterator();
396  }
398  {
399  return _Validate() ? iterator(this, _Data(), _Data()->end()) :
400  iterator();
401  }
403  {
404  return _Validate() ?
405  const_iterator(this, _ConstData(), _ConstData()->begin()) :
406  const_iterator();
407  }
409  {
410  return _Validate() ?
411  const_iterator(this, _ConstData(), _ConstData()->end()) :
412  const_iterator();
413  }
414 
416  {
417  return reverse_iterator(end());
418  }
420  {
421  return reverse_iterator(begin());
422  }
424  {
425  return const_reverse_iterator(end());
426  }
428  {
429  return const_reverse_iterator(begin());
430  }
431 
432  size_type size() const
433  {
434  return _Validate() ? _ConstData()->size() : 0;
435  }
436 
438  {
439  return _Validate() ? _ConstData()->max_size() : 0;
440  }
441 
442  bool empty() const
443  {
444  return _Validate() ? _ConstData()->empty() : true;
445  }
446 
447  std::pair<iterator, bool> insert(const value_type& value)
448  {
449  return _Insert(value);
450  }
451 
453  {
454  return _Insert(value).first;
455  }
456 
457  template <class InputIterator>
458  void insert(InputIterator first, InputIterator last)
459  {
460  if (_Validate()) {
461  SdfChangeBlock block;
462  for (; first != last; ++first) {
463  const value_type& v =
464  ValuePolicy::CanonicalizePair(_Owner(), *first);
465 
466  if (_ValidateInsert(v)) {
467  _editor->Insert(v);
468  }
469  }
470  }
471  }
472 
473  void erase(iterator pos)
474  {
475  if (_Validate() && _ValidateErase(pos->first)) {
476  _Erase(pos->first);
477  }
478  }
479 
481  {
482  if (_Validate()) {
483  const key_type& k = ValuePolicy::CanonicalizeKey(_Owner(), key);
484  if (_ValidateErase(k)) {
485  return _editor->Erase(k) ? 1 : 0;
486  }
487  }
488  return 0;
489  }
490 
492  {
493  if (_Validate()) {
494  SdfChangeBlock block;
495  while (first != last) {
496  const key_type& key = first->first;
497  ++first;
498  if (_ValidateErase(key)) {
499  _editor->Erase(key);
500  }
501  }
502  }
503  }
504 
505  void clear()
506  {
507  _Copy(Type());
508  }
509 
510  iterator find(const key_type& key)
511  {
512  return
513  _Validate() ?
514  iterator(this, _Data(),
515  _Data()->find(ValuePolicy::CanonicalizeKey(_Owner(), key))) :
516  iterator();
517  }
518 
519  const_iterator find(const key_type& key) const
520  {
521  return
522  _Validate() ?
523  const_iterator(this, _ConstData(),
524  _ConstData()->find(
525  ValuePolicy::CanonicalizeKey(_Owner(), key))) :
526  const_iterator();
527  }
528 
529  size_type count(const key_type& key) const
530  {
531  return
532  _Validate() ?
533  _ConstData()->count(
534  ValuePolicy::CanonicalizeKey(_Owner(), key)) :
535  0;
536  }
537 
539  {
540  return
541  _Validate() ?
542  iterator(this, _Data(),
543  _Data()->lower_bound(
544  ValuePolicy::CanonicalizeKey(_Owner(), key))) :
545  iterator();
546  }
547 
549  {
550  return
551  _Validate() ?
552  const_iterator(this, _ConstData(),
553  _ConstData()->lower_bound(
554  ValuePolicy::CanonicalizeKey(_Owner(), key))) :
555  const_iterator();
556  }
557 
559  {
560  return
561  _Validate() ?
562  iterator(this, _Data(),
563  _Data()->upper_bound(
564  ValuePolicy::CanonicalizeKey(_Owner(), key))) :
565  iterator();
566  }
567 
569  {
570  return
571  _Validate() ?
572  const_iterator(this, _ConstData(),
573  _ConstData()->upper_bound(
574  ValuePolicy::CanonicalizeKey(_Owner(), key))) :
575  const_iterator();
576  }
577 
578  std::pair<iterator, iterator> equal_range(const key_type& key)
579  {
580  if (_Validate()) {
581  std::pair<inner_iterator, inner_iterator> result =
582  _Data()->equal_range(
583  ValuePolicy::CanonicalizeKey(_Owner(), key));
584  return std::make_pair(iterator(this, _Data(), result.first),
585  iterator(this, _Data(), result.second));
586  }
587  else {
588  return std::make_pair(iterator(), iterator());
589  }
590  }
591 
592  std::pair<const_iterator,const_iterator>
593  equal_range(const key_type& key) const
594  {
595  if (_Validate()) {
596  std::pair<const_inner_iterator, const_inner_iterator> result =
597  _ConstData()->equal_range(
598  ValuePolicy::CanonicalizeKey(_Owner(), key));
599  return std::make_pair(
600  const_iterator(this, _ConstData(), result.first),
601  const_iterator(this, _ConstData(), result.second));
602  }
603  else {
604  return std::make_pair(const_iterator(), const_iterator());
605  }
606  }
607 
609  {
610  auto iter = _Insert(value_type(key, mapped_type())).first;
611  bool failed = iter == iterator();
612  return reference(failed ? nullptr : this,
613  failed ? nullptr : _Data(),
614  iter.base());
615  }
616 
617  bool operator==(const Type& other) const
618  {
619  return _Validate() ? _CompareEqual(other) : false;
620  }
621 
622  bool operator!=(const Type& other) const
623  {
624  return !(*this == other);
625  }
626 
627  friend bool operator==(const Type& lhs, const SdfMapEditProxy& rhs)
628  {
629  return rhs == lhs;
630  }
631 
632  friend bool operator!=(const Type& lhs, const SdfMapEditProxy& rhs)
633  {
634  return rhs != lhs;
635  }
636 
637  /// Invalid SdfMapEditProxy objects will compare less to an object
638  /// of their map type
639  bool operator<(const Type& other) const
640  {
641  return !_Validate() || _Compare(other) < 0;
642  }
643 
644  bool operator>(const Type& other) const
645  {
646  return _Validate() ? _Compare(other) > 0 : false;
647  }
648 
649  bool operator>=(const Type& other) const
650  {
651  return !(*this < other);
652  }
653 
654  bool operator<=(const Type& other) const
655  {
656  return !(*this > other);
657  }
658 
659  friend bool operator<(const Type& lhs, const SdfMapEditProxy& rhs)
660  {
661  return rhs > lhs;
662  }
663 
664  friend bool operator>(const Type& lhs, const SdfMapEditProxy& rhs)
665  {
666  return rhs < lhs;
667  }
668 
669  friend bool operator<=(const Type& lhs, const SdfMapEditProxy& rhs)
670  {
671  return rhs >= lhs;
672  }
673 
674  friend bool operator>=(const Type& lhs, const SdfMapEditProxy& rhs)
675  {
676  return rhs <= lhs;
677  }
678 
679  /// Comparison operator with another proxy
680  /// Two invalid proxy objects will compare equal.
681  template <class U, class UVP>
682  bool operator==(const SdfMapEditProxy<U, UVP>& other) const
683  {
684  const bool isValid = _Validate();
685  const bool otherIsValid = other._Validate();
686 
687  return isValid && otherIsValid ?
688  _CompareEqual(*other._ConstData()) : isValid == otherIsValid;
689  }
690 
691  template <class U, class UVP>
692  bool operator!=(const SdfMapEditProxy<U, UVP>& other) const
693  {
694  return !(*this == other);
695  }
696 
697  template <class U, class UVP>
698  bool operator<(const SdfMapEditProxy<U, UVP>& other) const
699  {
700  return _Validate() && other._Validate() ?
701  _Compare(*other._ConstData()) < 0 : false;
702  }
703 
704  template <class U, class UVP>
705  bool operator<=(const SdfMapEditProxy<U, UVP>& other) const
706  {
707  return _Validate() && other._Validate() ?
708  _Compare(*other._ConstData()) <= 0 : false;
709  }
710 
711  template <class U, class UVP>
712  bool operator>(const SdfMapEditProxy<U, UVP>& other) const
713  {
714  return !(*this <= other);
715  }
716 
717  template <class U, class UVP>
718  bool operator>=(const SdfMapEditProxy<U, UVP>& other) const
719  {
720  return !(*this < other);
721  }
722 
723  /// Returns true if the value is expired. Note this a default-constructed
724  /// MapEditProxy is considered to be invalid but *not* expired.
725  bool IsExpired() const
726  {
727  return _editor && _editor->IsExpired();
728  }
729 
730  /// Explicit bool conversion operator. Returns \c true if the value is
731  /// valid, \c false otherwise.
732  explicit operator bool() const
733  {
734  return _ConstData() && !IsExpired();
735  }
736 
737 private:
738  bool _Validate()
739  {
740  if (_ConstData() && !IsExpired()) {
741  return true;
742  }
743  else {
744  TF_CODING_ERROR("Editing an invalid map proxy");
745  return false;
746  }
747  }
748 
749  bool _Validate() const
750  {
751  if (_ConstData() && !IsExpired()) {
752  return true;
753  }
754  else {
755  TF_CODING_ERROR("Accessing an invalid map proxy");
756  return false;
757  }
758  }
759 
760  Type* _Data()
761  {
762  return _editor ? _editor->GetData() : NULL;
763  }
764 
765  const Type* _ConstData() const
766  {
767  return _editor ? _editor->GetData() : NULL;
768  }
769 
770  SdfSpecHandle _Owner() const
771  {
772  return _editor ? _editor->GetOwner() : SdfSpecHandle();
773  }
774 
775  std::string _Location() const
776  {
777  return _editor ? _editor->GetLocation() : std::string();
778  }
779 
780  bool _CompareEqual(const Type& other) const
781  {
782  if (_ConstData()->size() < other.size()) {
783  return false;
784  }
785  if (_ConstData()->size() > other.size()) {
786  return false;
787  }
788 
789  // Same size -- find the first mismatch.
790  const Type& x = ValuePolicy::CanonicalizeType(_Owner(), other);
791  std::pair<const_inner_iterator, const_inner_iterator> result =
792  std::mismatch(_ConstData()->begin(), _ConstData()->end(),
793  x.begin());
794  return result.first == _ConstData()->end();
795  }
796 
797  int _Compare(const Type& other) const
798  {
799  if (_ConstData()->size() < other.size()) {
800  return -1;
801  }
802  if (_ConstData()->size() > other.size()) {
803  return 1;
804  }
805 
806  // Same size -- find the first mismatch.
807  const Type& x = ValuePolicy::CanonicalizeType(_Owner(), other);
808  std::pair<const_inner_iterator, const_inner_iterator> result =
809  std::mismatch(_ConstData()->begin(), _ConstData()->end(),
810  x.begin());
811  if (*result.first < *result.second) {
812  return -1;
813  }
814  else if (*result.first > *result.second) {
815  return 1;
816  }
817  else {
818  return 0;
819  }
820  }
821 
822  template <class D>
823  bool _CompareEqual(const D& other) const
824  {
825  // This is expensive but yields reliable results.
826  return _CompareEqual(Type(other.begin(), other.end()));
827  }
828 
829  template <class D>
830  int _Compare(const D& other) const
831  {
832  // This is expensive but yields reliable ordering.
833  return _Compare(Type(other.begin(), other.end()));
834  }
835 
836  mapped_type _Get(const Type* data, const inner_iterator& i)
837  {
838  if (_Validate()) {
839  if (data == _ConstData()) {
840  return i->second;
841  }
842  else {
843  // Data has changed since we created the iterator.
844  // Look up same key in new data.
845  return _ConstData()->find(i->first)->second;
846  }
847  }
848  return mapped_type();
849  }
850 
851  const value_type& _Get(const Type* data,
852  const const_inner_iterator& i) const
853  {
854  // If data has changed since we created the iterator then look up
855  // the same key in the new data.
856  return (data == _ConstData()) ? *i : *_ConstData()->find(i->first);
857  }
858 
859  void _Copy(const Type& other)
860  {
861  if (_Validate()) {
862  // Canonicalize the given map before copying it into ourselves.
863  // If multiple keys in the given map would conflict with each
864  // other in the canonicalized map, we consider this an error.
865  // This is primarily to avoid confusing the consumer, who would
866  // otherwise observe a key/value pair to be missing entirely.
867  Type canonicalOther;
868  TF_FOR_ALL(it, other) {
869  const value_type canonicalValue =
870  ValuePolicy::CanonicalizePair(_Owner(), *it);
871  if (!canonicalOther.insert(canonicalValue).second) {
872  TF_CODING_ERROR("Can't copy to %s: Duplicate key '%s' "
873  "exists in map.",
874  _Location().c_str(),
875  TfStringify(canonicalValue.first).c_str());
876  return;
877  }
878  }
879 
880  if (_ValidateCopy(canonicalOther)) {
881  _editor->Copy(canonicalOther);
882  }
883  }
884  }
885 
886  bool _ValidateCopy(const Type& other)
887  {
888  SdfSpecHandle owner = _Owner();
889  if (owner && !owner->PermissionToEdit()) {
890  TF_CODING_ERROR("Can't copy to %s: Permission denied.",
891  _Location().c_str());
892  return false;
893  }
894 
895  if (other.empty()) {
896  return true;
897  }
898 
899  TF_FOR_ALL(it, other) {
900  if (!_ValidateInsert(*it)) {
901  return false;
902  }
903  }
904 
905  return true;
906  }
907 
908  template <class U>
909  void _Set(const Type* data, const inner_iterator& i, const U& value)
910  {
911  if (_Validate()) {
912  const mapped_type& x =
913  ValuePolicy::CanonicalizeValue(_Owner(), value);
914  if (_ValidateSet(i->first, x)) {
915  _editor->Set(i->first, x);
916  }
917  }
918  }
919 
920  bool _ValidateSet(const key_type& key, const mapped_type& value)
921  {
922  SdfSpecHandle owner = _Owner();
923  if (owner && !owner->PermissionToEdit()) {
924  TF_CODING_ERROR("Can't set value in %s: Permission denied.",
925  _Location().c_str());
926  return false;
927  }
928 
929  if (SdfAllowed allowed = _editor->IsValidValue(value)) {
930  // Do nothing
931  }
932  else {
933  TF_CODING_ERROR("Can't set value in %s: %s",
934  _Location().c_str(),
935  allowed.GetWhyNot().c_str());
936  return false;
937  }
938 
939  return true;
940  }
941 
942  std::pair<iterator, bool> _Insert(const value_type& value)
943  {
944  if (_Validate()) {
945  const value_type& v = ValuePolicy::CanonicalizePair(_Owner(), value);
946  if (_ValidateInsert(v)) {
947  std::pair<inner_iterator, bool> status = _editor->Insert(v);
948  return std::make_pair(iterator(this, _Data(), status.first),
949  status.second);
950  }
951  else {
952  return std::make_pair(iterator(), false);
953  }
954  }
955  return std::make_pair(iterator(), false);
956  }
957 
958  bool _ValidateInsert(const value_type& value)
959  {
960  SdfSpecHandle owner = _Owner();
961  if (owner && !owner->PermissionToEdit()) {
962  TF_CODING_ERROR("Can't insert value in %s: Permission denied.",
963  _Location().c_str());
964  return false;
965  }
966 
967  if (SdfAllowed allowed = _editor->IsValidKey(value.first)) {
968  // Do nothing
969  }
970  else {
971  TF_CODING_ERROR("Can't insert key in %s: %s",
972  _Location().c_str(),
973  allowed.GetWhyNot().c_str());
974  return false;
975  }
976 
977  if (SdfAllowed allowed = _editor->IsValidValue(value.second)) {
978  // Do nothing
979  }
980  else {
981  TF_CODING_ERROR("Can't insert value in %s: %s",
982  _Location().c_str(),
983  allowed.GetWhyNot().c_str());
984  return false;
985  }
986 
987  return true;
988  }
989 
990  void _Erase(const key_type& key)
991  {
992  if (_Validate() && _ValidateErase(key)) {
993  _editor->Erase(key);
994  }
995  }
996 
997  bool _ValidateErase(const key_type& key)
998  {
999  SdfSpecHandle owner = _Owner();
1000  if (owner && !owner->PermissionToEdit()) {
1001  TF_CODING_ERROR("Can't erase value from %s: Permission denied.",
1002  _Location().c_str());
1003  return false;
1004  }
1005 
1006  return true;
1007  }
1008 
1009 private:
1010  template <class ProxyT> friend class SdfPyWrapMapEditProxy;
1011 
1012  std::shared_ptr<Sdf_MapEditor<T> > _editor;
1013 };
1014 
1015 // Cannot get from a VtValue except as the correct type.
1016 template <class T, class _ValuePolicy>
1017 struct Vt_DefaultValueFactory<SdfMapEditProxy<T, _ValuePolicy> > {
1018  static Vt_DefaultValueHolder Invoke() = delete;
1019 };
1020 
1022 
1023 #endif // PXR_USD_SDF_MAP_EDIT_PROXY_H
void insert(InputIterator first, InputIterator last)
Definition: mapEditProxy.h:458
static const key_type & CanonicalizeKey(const SdfSpecHandle &, const key_type &x)
Definition: mapEditProxy.h:62
GLint first
Definition: glcorearb.h:405
typename std::enable_if< B, T >::type enable_if_t
Define Imath::enable_if_t to be std for C++14, equivalent for C++11.
bool operator>=(const SdfMapEditProxy< U, UVP > &other) const
Definition: mapEditProxy.h:718
friend bool operator!=(const Type &lhs, const SdfMapEditProxy &rhs)
Definition: mapEditProxy.h:632
size_type size() const
Definition: mapEditProxy.h:432
size_type erase(const key_type &key)
Definition: mapEditProxy.h:480
iterator end()
Definition: mapEditProxy.h:397
bool IsExpired() const
Definition: mapEditProxy.h:725
_ValueProxy reference
Definition: mapEditProxy.h:342
reverse_iterator rend()
Definition: mapEditProxy.h:419
const GLdouble * v
Definition: glcorearb.h:837
bool empty() const
Definition: mapEditProxy.h:442
bool operator<(const Type &other) const
Definition: mapEditProxy.h:639
GLsizei const GLfloat * value
Definition: glcorearb.h:824
bool operator>=(const Type &other) const
Definition: mapEditProxy.h:649
#define TF_CODING_ERROR
Definition: spec.h:32
ptrdiff_t difference_type
Definition: mapEditProxy.h:345
static const value_type & CanonicalizePair(const SdfSpecHandle &, const value_type &x)
Definition: mapEditProxy.h:79
std::pair< const_iterator, const_iterator > equal_range(const key_type &key) const
Definition: mapEditProxy.h:593
IMATH_HOSTDEVICE constexpr bool equal(T1 a, T2 b, T3 t) IMATH_NOEXCEPT
Definition: ImathFun.h:105
**But if you need a result
Definition: thread.h:622
friend bool operator<(const Type &lhs, const SdfMapEditProxy &rhs)
Definition: mapEditProxy.h:659
Type::value_type value_type
Definition: mapEditProxy.h:108
Type::key_type key_type
Definition: mapEditProxy.h:106
bool operator>(const Type &other) const
Definition: mapEditProxy.h:644
const_iterator lower_bound(const key_type &key) const
Definition: mapEditProxy.h:548
friend bool operator<=(const Type &lhs, const SdfMapEditProxy &rhs)
Definition: mapEditProxy.h:669
const_iterator begin() const
Definition: mapEditProxy.h:402
uint64 value_type
Definition: GA_PrimCompat.h:29
OutGridT const XformOp bool bool
Type::mapped_type mapped_type
Definition: mapEditProxy.h:107
const_reverse_iterator rend() const
Definition: mapEditProxy.h:427
size_type max_size() const
Definition: mapEditProxy.h:437
friend bool operator>=(const Type &lhs, const SdfMapEditProxy &rhs)
Definition: mapEditProxy.h:674
void erase(iterator pos)
Definition: mapEditProxy.h:473
const_reverse_iterator rbegin() const
Definition: mapEditProxy.h:423
iterator lower_bound(const key_type &key)
Definition: mapEditProxy.h:538
Definition: token.h:70
iterator insert(iterator pos, const value_type &value)
Definition: mapEditProxy.h:452
SDF_DECLARE_HANDLES(SdfSpec)
const_iterator upper_bound(const key_type &key) const
Definition: mapEditProxy.h:568
void erase(iterator first, iterator last)
Definition: mapEditProxy.h:491
bool operator==(const SdfMapEditProxy< U, UVP > &other) const
Definition: mapEditProxy.h:682
bool operator<=(const Type &other) const
Definition: mapEditProxy.h:654
SdfMapEditProxy< Type, ValuePolicy > This
Definition: mapEditProxy.h:105
std::pair< iterator, bool > insert(const value_type &value)
Definition: mapEditProxy.h:447
_Iterator< const This *, const_inner_iterator, const value_type & > const_iterator
Definition: mapEditProxy.h:348
std::pair< iterator, iterator > equal_range(const key_type &key)
Definition: mapEditProxy.h:578
friend bool operator==(const Type &lhs, const SdfMapEditProxy &rhs)
Definition: mapEditProxy.h:627
#define TF_FATAL_ERROR
reference operator[](const key_type &key)
Definition: mapEditProxy.h:608
std::string TfStringify(const T &v)
Definition: stringUtils.h:556
IMATH_HOSTDEVICE constexpr Color4< T > operator*(S a, const Color4< T > &v) IMATH_NOEXCEPT
Reverse multiplication: S * Color4.
Definition: ImathColor.h:732
_Iterator< This *, inner_iterator, _PairProxy > iterator
Definition: mapEditProxy.h:346
SdfMapEditProxy(const SdfSpecHandle &owner, const TfToken &field)
Definition: mapEditProxy.h:352
const_iterator end() const
Definition: mapEditProxy.h:408
GLint GLenum GLint x
Definition: glcorearb.h:409
iterator find(const key_type &key)
Definition: mapEditProxy.h:510
iterator begin()
Definition: mapEditProxy.h:392
Tf_ProxyReferenceReverseIterator< const_iterator > const_reverse_iterator
Definition: mapEditProxy.h:350
__hostdev__ uint64_t last(uint32_t i) const
Definition: NanoVDB.h:5976
static const mapped_type & CanonicalizeValue(const SdfSpecHandle &, const mapped_type &x)
Definition: mapEditProxy.h:70
GLenum void ** pointer
Definition: glcorearb.h:810
size_type count(const key_type &key) const
Definition: mapEditProxy.h:529
bool operator!=(const SdfMapEditProxy< U, UVP > &other) const
Definition: mapEditProxy.h:692
bool operator==(const Type &other) const
Definition: mapEditProxy.h:617
PXR_NAMESPACE_CLOSE_SCOPE PXR_NAMESPACE_OPEN_SCOPE
Definition: path.h:1425
friend bool operator>(const Type &lhs, const SdfMapEditProxy &rhs)
Definition: mapEditProxy.h:664
const_iterator find(const key_type &key) const
Definition: mapEditProxy.h:519
This & operator=(const SdfMapEditProxy< U, UVP > &other)
Definition: mapEditProxy.h:372
This & operator=(const Type &data)
Definition: mapEditProxy.h:380
#define PXR_NAMESPACE_CLOSE_SCOPE
Definition: pxr.h:74
std::unique_ptr< Sdf_MapEditor< T > > Sdf_CreateMapEditor(const SdfSpecHandle &owner, const TfToken &field)
bool operator>(const SdfMapEditProxy< U, UVP > &other) const
Definition: mapEditProxy.h:712
This & operator=(const This &other)
Definition: mapEditProxy.h:363
OIIO_UTIL_API const char * c_str(string_view str)
_ValuePolicy ValuePolicy
Definition: mapEditProxy.h:104
#define TF_FOR_ALL(iter, c)
Definition: iterator.h:373
static const Type & CanonicalizeType(const SdfSpecHandle &, const Type &x)
Definition: mapEditProxy.h:55
iterator upper_bound(const key_type &key)
Definition: mapEditProxy.h:558
reverse_iterator rbegin()
Definition: mapEditProxy.h:415
Tf_ProxyReferenceReverseIterator< iterator > reverse_iterator
Definition: mapEditProxy.h:349
bool operator!=(const Type &other) const
Definition: mapEditProxy.h:622
static Vt_DefaultValueHolder Invoke()
Definition: value.h:1512
Definition: format.h:1821
const value_type & const_reference
Definition: mapEditProxy.h:343