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