This document is for a version of USD that is under development. See this page for the current release.
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules 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
11
12#include "pxr/pxr.h"
13#include "pxr/usd/sdf/allowed.h"
14#include "pxr/usd/sdf/changeBlock.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
23#include <iterator>
24#include <utility>
25
26PXR_NAMESPACE_OPEN_SCOPE
27
28class TfToken;
29
30SDF_DECLARE_HANDLES(SdfSpec);
31
44template <class T>
46public:
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
55 static const Type& CanonicalizeType(const SdfSpecHandle&, const Type& x)
56 {
57 return x;
58 }
59
62 static const key_type& CanonicalizeKey(const SdfSpecHandle&,
63 const key_type& x)
64 {
65 return x;
66 }
67
70 static const mapped_type& CanonicalizeValue(const SdfSpecHandle&,
71 const mapped_type& x)
72 {
73 return x;
74 }
75
79 static const value_type& CanonicalizePair(const SdfSpecHandle&,
80 const value_type& x)
81 {
82 return x;
83 }
84};
85
100template <class T, class _ValuePolicy = SdfIdentityMapEditProxyValuePolicy<T> >
102public:
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
110private:
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;
230 using pointer = std::conditional_t<std::is_lvalue_reference<R>::value,
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<
257 std::is_pointer<PointerType>::value, int> = 0>
258 pointer operator->() const { return std::addressof(dereference()); }
259 template <typename PointerType=pointer,
260 typename std::enable_if_t<
261 !std::is_pointer<PointerType>::value, int> = 0>
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
341public:
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,
348 const value_type&> const_iterator;
349 typedef Tf_ProxyReferenceReverseIterator<iterator> reverse_iterator;
350 typedef Tf_ProxyReferenceReverseIterator<const_iterator> const_reverse_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>
372 This& operator=(const SdfMapEditProxy<U, UVP>& other)
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
387 operator Type() const
388 {
389 return _Validate() ? *_ConstData() : Type();
390 }
391
392 iterator begin()
393 {
394 return _Validate() ? iterator(this, _Data(), _Data()->begin()) :
395 iterator();
396 }
397 iterator end()
398 {
399 return _Validate() ? iterator(this, _Data(), _Data()->end()) :
400 iterator();
401 }
402 const_iterator begin() const
403 {
404 return _Validate() ?
405 const_iterator(this, _ConstData(), _ConstData()->begin()) :
406 const_iterator();
407 }
408 const_iterator end() const
409 {
410 return _Validate() ?
411 const_iterator(this, _ConstData(), _ConstData()->end()) :
412 const_iterator();
413 }
414
415 reverse_iterator rbegin()
416 {
417 return reverse_iterator(end());
418 }
419 reverse_iterator rend()
420 {
421 return reverse_iterator(begin());
422 }
423 const_reverse_iterator rbegin() const
424 {
425 return const_reverse_iterator(end());
426 }
427 const_reverse_iterator rend() const
428 {
429 return const_reverse_iterator(begin());
430 }
431
432 size_type size() const
433 {
434 return _Validate() ? _ConstData()->size() : 0;
435 }
436
437 size_type max_size() const
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
452 iterator insert(iterator pos, const value_type& value)
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
480 size_type erase(const key_type& key)
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
491 void erase(iterator first, iterator last)
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
538 iterator lower_bound(const key_type& key)
539 {
540 return
541 _Validate() ?
542 iterator(this, _Data(),
543 _Data()->lower_bound(
544 ValuePolicy::CanonicalizeKey(_Owner(), key))) :
545 iterator();
546 }
547
548 const_iterator lower_bound(const key_type& key) const
549 {
550 return
551 _Validate() ?
552 const_iterator(this, _ConstData(),
553 _ConstData()->lower_bound(
554 ValuePolicy::CanonicalizeKey(_Owner(), key))) :
555 const_iterator();
556 }
557
558 iterator upper_bound(const key_type& key)
559 {
560 return
561 _Validate() ?
562 iterator(this, _Data(),
563 _Data()->upper_bound(
564 ValuePolicy::CanonicalizeKey(_Owner(), key))) :
565 iterator();
566 }
567
568 const_iterator upper_bound(const key_type& key) const
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
608 reference operator[](const key_type& key)
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
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
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
725 bool IsExpired() const
726 {
727 return _editor && _editor->IsExpired();
728 }
729
732 explicit operator bool() const
733 {
734 return _ConstData() && !IsExpired();
735 }
736
737private:
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
1009private:
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.
1016template <class T, class _ValuePolicy>
1017struct Vt_DefaultValueFactory<SdfMapEditProxy<T, _ValuePolicy> > {
1018 static Vt_DefaultValueHolder Invoke() = delete;
1019};
1020
1021PXR_NAMESPACE_CLOSE_SCOPE
1022
1023#endif // PXR_USD_SDF_MAP_EDIT_PROXY_H
Low-level utilities for informing users of various internal and external diagnostic conditions.
A simple iterator adapter for STL containers.
Indicates if an operation is allowed and, if not, why not.
Definition: allowed.h:29
DANGER DANGER DANGER
Definition: changeBlock.h:56
A value policy for SdfMapEditProxy that does nothing.
Definition: mapEditProxy.h:45
static const value_type & CanonicalizePair(const SdfSpecHandle &, const value_type &x)
Canonicalize a key/value pair.
Definition: mapEditProxy.h:79
static const mapped_type & CanonicalizeValue(const SdfSpecHandle &, const mapped_type &x)
Canonicalize a value.
Definition: mapEditProxy.h:70
static const key_type & CanonicalizeKey(const SdfSpecHandle &, const key_type &x)
Canonicalize a key.
Definition: mapEditProxy.h:62
static const Type & CanonicalizeType(const SdfSpecHandle &, const Type &x)
Canonicalize an entire Type object.
Definition: mapEditProxy.h:55
A proxy for editing map-like values.
Definition: mapEditProxy.h:101
bool IsExpired() const
Returns true if the value is expired.
Definition: mapEditProxy.h:725
bool operator<(const Type &other) const
Invalid SdfMapEditProxy objects will compare less to an object of their map type.
Definition: mapEditProxy.h:639
bool operator==(const SdfMapEditProxy< U, UVP > &other) const
Comparison operator with another proxy Two invalid proxy objects will compare equal.
Definition: mapEditProxy.h:682
Base class for all Sdf spec classes.
Definition: spec.h:33
Token for efficient comparison, assignment, and hashing of known strings.
Definition: token.h:71
#define TF_FOR_ALL(iter, c)
Macro for iterating over a container.
Definition: iterator.h:373
#define TF_FATAL_ERROR(fmt, args)
Issue a fatal error and end the program.
Definition: diagnostic.h:91
#define TF_CODING_ERROR(fmt, args)
Issue an internal programming error, but continue execution.
Definition: diagnostic.h:68
std::string TfStringify(const T &v)
Convert an arbitrary type into a string.
Definition: stringUtils.h:555