Loading...
Searching...
No Matches
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
28
29#include "pxr/pxr.h"
30#include "pxr/usd/sdf/allowed.h"
31#include "pxr/usd/sdf/changeBlock.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
40#include <iterator>
41#include <utility>
42
43PXR_NAMESPACE_OPEN_SCOPE
44
45class TfToken;
46
47SDF_DECLARE_HANDLES(SdfSpec);
48
61template <class T>
63public:
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
72 static const Type& CanonicalizeType(const SdfSpecHandle&, const Type& x)
73 {
74 return x;
75 }
76
79 static const key_type& CanonicalizeKey(const SdfSpecHandle&,
80 const key_type& x)
81 {
82 return x;
83 }
84
87 static const mapped_type& CanonicalizeValue(const SdfSpecHandle&,
88 const mapped_type& x)
89 {
90 return x;
91 }
92
96 static const value_type& CanonicalizePair(const SdfSpecHandle&,
97 const value_type& x)
98 {
99 return x;
100 }
101};
102
117template <class T, class _ValuePolicy = SdfIdentityMapEditProxyValuePolicy<T> >
119public:
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
127private:
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;
247 using pointer = std::conditional_t<std::is_lvalue_reference<R>::value,
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<
274 std::is_pointer<PointerType>::value, int> = 0>
275 pointer operator->() const { return std::addressof(dereference()); }
276 template <typename PointerType=pointer,
277 typename std::enable_if_t<
278 !std::is_pointer<PointerType>::value, int> = 0>
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
358public:
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,
365 const value_type&> const_iterator;
366 typedef Tf_ProxyReferenceReverseIterator<iterator> reverse_iterator;
367 typedef Tf_ProxyReferenceReverseIterator<const_iterator> const_reverse_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>
389 This& operator=(const SdfMapEditProxy<U, UVP>& other)
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
404 operator Type() const
405 {
406 return _Validate() ? *_ConstData() : Type();
407 }
408
409 iterator begin()
410 {
411 return _Validate() ? iterator(this, _Data(), _Data()->begin()) :
412 iterator();
413 }
414 iterator end()
415 {
416 return _Validate() ? iterator(this, _Data(), _Data()->end()) :
417 iterator();
418 }
419 const_iterator begin() const
420 {
421 return _Validate() ?
422 const_iterator(this, _ConstData(), _ConstData()->begin()) :
423 const_iterator();
424 }
425 const_iterator end() const
426 {
427 return _Validate() ?
428 const_iterator(this, _ConstData(), _ConstData()->end()) :
429 const_iterator();
430 }
431
432 reverse_iterator rbegin()
433 {
434 return reverse_iterator(end());
435 }
436 reverse_iterator rend()
437 {
438 return reverse_iterator(begin());
439 }
440 const_reverse_iterator rbegin() const
441 {
442 return const_reverse_iterator(end());
443 }
444 const_reverse_iterator rend() const
445 {
446 return const_reverse_iterator(begin());
447 }
448
449 size_type size() const
450 {
451 return _Validate() ? _ConstData()->size() : 0;
452 }
453
454 size_type max_size() const
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
469 iterator insert(iterator pos, const value_type& value)
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
497 size_type erase(const key_type& key)
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
508 void erase(iterator first, iterator last)
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
555 iterator lower_bound(const key_type& key)
556 {
557 return
558 _Validate() ?
559 iterator(this, _Data(),
560 _Data()->lower_bound(
561 ValuePolicy::CanonicalizeKey(_Owner(), key))) :
562 iterator();
563 }
564
565 const_iterator lower_bound(const key_type& key) const
566 {
567 return
568 _Validate() ?
569 const_iterator(this, _ConstData(),
570 _ConstData()->lower_bound(
571 ValuePolicy::CanonicalizeKey(_Owner(), key))) :
572 const_iterator();
573 }
574
575 iterator upper_bound(const key_type& key)
576 {
577 return
578 _Validate() ?
579 iterator(this, _Data(),
580 _Data()->upper_bound(
581 ValuePolicy::CanonicalizeKey(_Owner(), key))) :
582 iterator();
583 }
584
585 const_iterator upper_bound(const key_type& key) const
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
625 reference operator[](const key_type& key)
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
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
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
742 bool IsExpired() const
743 {
744 return _editor && _editor->IsExpired();
745 }
746
749 explicit operator bool() const
750 {
751 return _ConstData() && !IsExpired();
752 }
753
754private:
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
1026private:
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.
1033template <class T, class _ValuePolicy>
1034struct Vt_DefaultValueFactory<SdfMapEditProxy<T, _ValuePolicy> > {
1035 static Vt_DefaultValueHolder Invoke() = delete;
1036};
1037
1038PXR_NAMESPACE_CLOSE_SCOPE
1039
1040#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:46
DANGER DANGER DANGER
Definition: changeBlock.h:73
A value policy for SdfMapEditProxy that does nothing.
Definition: mapEditProxy.h:62
static const value_type & CanonicalizePair(const SdfSpecHandle &, const value_type &x)
Canonicalize a key/value pair.
Definition: mapEditProxy.h:96
static const mapped_type & CanonicalizeValue(const SdfSpecHandle &, const mapped_type &x)
Canonicalize a value.
Definition: mapEditProxy.h:87
static const key_type & CanonicalizeKey(const SdfSpecHandle &, const key_type &x)
Canonicalize a key.
Definition: mapEditProxy.h:79
static const Type & CanonicalizeType(const SdfSpecHandle &, const Type &x)
Canonicalize an entire Type object.
Definition: mapEditProxy.h:72
A proxy for editing map-like values.
Definition: mapEditProxy.h:118
bool IsExpired() const
Returns true if the value is expired.
Definition: mapEditProxy.h:742
bool operator<(const Type &other) const
Invalid SdfMapEditProxy objects will compare less to an object of their map type.
Definition: mapEditProxy.h:656
bool operator==(const SdfMapEditProxy< U, UVP > &other) const
Comparison operator with another proxy Two invalid proxy objects will compare equal.
Definition: mapEditProxy.h:699
Base class for all Sdf spec classes.
Definition: spec.h:50
Token for efficient comparison, assignment, and hashing of known strings.
Definition: token.h:88
#define TF_FOR_ALL(iter, c)
Macro for iterating over a container.
Definition: iterator.h:390
#define TF_FATAL_ERROR(fmt, args)
Issue a fatal error and end the program.
Definition: diagnostic.h:108
#define TF_CODING_ERROR(fmt, args)
Issue an internal programming error, but continue execution.
Definition: diagnostic.h:85
std::string TfStringify(const T &v)
Convert an arbitrary type into a string.
Definition: stringUtils.h:572