Loading...
Searching...
No Matches
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:562