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
654 bool operator<(const Type& other) const
655 {
656 return _Validate() ? _Compare(other) < 0 : false;
657 }
658
659 bool operator>(const Type& other) const
660 {
661 return _Validate() ? _Compare(other) > 0 : false;
662 }
663
664 bool operator>=(const Type& other) const
665 {
666 return !(*this < other);
667 }
668
669 bool operator<=(const Type& other) const
670 {
671 return !(*this > other);
672 }
673
674 friend bool operator<(const Type& lhs, const SdfMapEditProxy& rhs)
675 {
676 return rhs > lhs;
677 }
678
679 friend bool operator>(const Type& lhs, const SdfMapEditProxy& rhs)
680 {
681 return rhs < lhs;
682 }
683
684 friend bool operator<=(const Type& lhs, const SdfMapEditProxy& rhs)
685 {
686 return rhs >= lhs;
687 }
688
689 friend bool operator>=(const Type& lhs, const SdfMapEditProxy& rhs)
690 {
691 return rhs <= lhs;
692 }
693
694 template <class U, class UVP>
695 bool operator==(const SdfMapEditProxy<U, UVP>& other) const
696 {
697 return _Validate() && other._Validate() ?
698 _CompareEqual(*other._ConstData()) : false;
699 }
700
701 template <class U, class UVP>
702 bool operator!=(const SdfMapEditProxy<U, UVP>& other) const
703 {
704 return !(*this == other);
705 }
706
707 template <class U, class UVP>
708 bool operator<(const SdfMapEditProxy<U, UVP>& other) const
709 {
710 return _Validate() && other._Validate() ?
711 _Compare(*other._ConstData()) < 0 : false;
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 !(*this <= other);
725 }
726
727 template <class U, class UVP>
728 bool operator>=(const SdfMapEditProxy<U, UVP>& other) const
729 {
730 return !(*this < other);
731 }
732
735 bool IsExpired() const
736 {
737 return _editor && _editor->IsExpired();
738 }
739
742 explicit operator bool() const
743 {
744 return _ConstData() && !IsExpired();
745 }
746
747private:
748 bool _Validate()
749 {
750 if (_ConstData() && !IsExpired()) {
751 return true;
752 }
753 else {
754 TF_CODING_ERROR("Editing an invalid map proxy");
755 return false;
756 }
757 }
758
759 bool _Validate() const
760 {
761 if (_ConstData() && !IsExpired()) {
762 return true;
763 }
764 else {
765 TF_CODING_ERROR("Accessing an invalid map proxy");
766 return false;
767 }
768 }
769
770 Type* _Data()
771 {
772 return _editor ? _editor->GetData() : NULL;
773 }
774
775 const Type* _ConstData() const
776 {
777 return _editor ? _editor->GetData() : NULL;
778 }
779
780 SdfSpecHandle _Owner() const
781 {
782 return _editor ? _editor->GetOwner() : SdfSpecHandle();
783 }
784
785 std::string _Location() const
786 {
787 return _editor ? _editor->GetLocation() : std::string();
788 }
789
790 bool _CompareEqual(const Type& other) const
791 {
792 if (_ConstData()->size() < other.size()) {
793 return false;
794 }
795 if (_ConstData()->size() > other.size()) {
796 return false;
797 }
798
799 // Same size -- find the first mismatch.
800 const Type& x = ValuePolicy::CanonicalizeType(_Owner(), other);
801 std::pair<const_inner_iterator, const_inner_iterator> result =
802 std::mismatch(_ConstData()->begin(), _ConstData()->end(),
803 x.begin());
804 return result.first == _ConstData()->end();
805 }
806
807 int _Compare(const Type& other) const
808 {
809 if (_ConstData()->size() < other.size()) {
810 return -1;
811 }
812 if (_ConstData()->size() > other.size()) {
813 return 1;
814 }
815
816 // Same size -- find the first mismatch.
817 const Type& x = ValuePolicy::CanonicalizeType(_Owner(), other);
818 std::pair<const_inner_iterator, const_inner_iterator> result =
819 std::mismatch(_ConstData()->begin(), _ConstData()->end(),
820 x.begin());
821 if (*result.first < *result.second) {
822 return -1;
823 }
824 else if (*result.first > *result.second) {
825 return 1;
826 }
827 else {
828 return 0;
829 }
830 }
831
832 template <class D>
833 bool _CompareEqual(const D& other) const
834 {
835 // This is expensive but yields reliable results.
836 return _CompareEqual(Type(other.begin(), other.end()));
837 }
838
839 template <class D>
840 int _Compare(const D& other) const
841 {
842 // This is expensive but yields reliable ordering.
843 return _Compare(Type(other.begin(), other.end()));
844 }
845
846 mapped_type _Get(const Type* data, const inner_iterator& i)
847 {
848 if (_Validate()) {
849 if (data == _ConstData()) {
850 return i->second;
851 }
852 else {
853 // Data has changed since we created the iterator.
854 // Look up same key in new data.
855 return _ConstData()->find(i->first)->second;
856 }
857 }
858 return mapped_type();
859 }
860
861 const value_type& _Get(const Type* data,
862 const const_inner_iterator& i) const
863 {
864 // If data has changed since we created the iterator then look up
865 // the same key in the new data.
866 return (data == _ConstData()) ? *i : *_ConstData()->find(i->first);
867 }
868
869 void _Copy(const Type& other)
870 {
871 if (_Validate()) {
872 // Canonicalize the given map before copying it into ourselves.
873 // If multiple keys in the given map would conflict with each
874 // other in the canonicalized map, we consider this an error.
875 // This is primarily to avoid confusing the consumer, who would
876 // otherwise observe a key/value pair to be missing entirely.
877 Type canonicalOther;
878 TF_FOR_ALL(it, other) {
879 const value_type canonicalValue =
880 ValuePolicy::CanonicalizePair(_Owner(), *it);
881 if (!canonicalOther.insert(canonicalValue).second) {
882 TF_CODING_ERROR("Can't copy to %s: Duplicate key '%s' "
883 "exists in map.",
884 _Location().c_str(),
885 TfStringify(canonicalValue.first).c_str());
886 return;
887 }
888 }
889
890 if (_ValidateCopy(canonicalOther)) {
891 _editor->Copy(canonicalOther);
892 }
893 }
894 }
895
896 bool _ValidateCopy(const Type& other)
897 {
898 SdfSpecHandle owner = _Owner();
899 if (owner && !owner->PermissionToEdit()) {
900 TF_CODING_ERROR("Can't copy to %s: Permission denied.",
901 _Location().c_str());
902 return false;
903 }
904
905 if (other.empty()) {
906 return true;
907 }
908
909 TF_FOR_ALL(it, other) {
910 if (!_ValidateInsert(*it)) {
911 return false;
912 }
913 }
914
915 return true;
916 }
917
918 template <class U>
919 void _Set(const Type* data, const inner_iterator& i, const U& value)
920 {
921 if (_Validate()) {
922 const mapped_type& x =
923 ValuePolicy::CanonicalizeValue(_Owner(), value);
924 if (_ValidateSet(i->first, x)) {
925 _editor->Set(i->first, x);
926 }
927 }
928 }
929
930 bool _ValidateSet(const key_type& key, const mapped_type& value)
931 {
932 SdfSpecHandle owner = _Owner();
933 if (owner && !owner->PermissionToEdit()) {
934 TF_CODING_ERROR("Can't set value in %s: Permission denied.",
935 _Location().c_str());
936 return false;
937 }
938
939 if (SdfAllowed allowed = _editor->IsValidValue(value)) {
940 // Do nothing
941 }
942 else {
943 TF_CODING_ERROR("Can't set value in %s: %s",
944 _Location().c_str(),
945 allowed.GetWhyNot().c_str());
946 return false;
947 }
948
949 return true;
950 }
951
952 std::pair<iterator, bool> _Insert(const value_type& value)
953 {
954 if (_Validate()) {
955 const value_type& v = ValuePolicy::CanonicalizePair(_Owner(), value);
956 if (_ValidateInsert(v)) {
957 std::pair<inner_iterator, bool> status = _editor->Insert(v);
958 return std::make_pair(iterator(this, _Data(), status.first),
959 status.second);
960 }
961 else {
962 return std::make_pair(iterator(), false);
963 }
964 }
965 return std::make_pair(iterator(), false);
966 }
967
968 bool _ValidateInsert(const value_type& value)
969 {
970 SdfSpecHandle owner = _Owner();
971 if (owner && !owner->PermissionToEdit()) {
972 TF_CODING_ERROR("Can't insert value in %s: Permission denied.",
973 _Location().c_str());
974 return false;
975 }
976
977 if (SdfAllowed allowed = _editor->IsValidKey(value.first)) {
978 // Do nothing
979 }
980 else {
981 TF_CODING_ERROR("Can't insert key in %s: %s",
982 _Location().c_str(),
983 allowed.GetWhyNot().c_str());
984 return false;
985 }
986
987 if (SdfAllowed allowed = _editor->IsValidValue(value.second)) {
988 // Do nothing
989 }
990 else {
991 TF_CODING_ERROR("Can't insert value in %s: %s",
992 _Location().c_str(),
993 allowed.GetWhyNot().c_str());
994 return false;
995 }
996
997 return true;
998 }
999
1000 void _Erase(const key_type& key)
1001 {
1002 if (_Validate() && _ValidateErase(key)) {
1003 _editor->Erase(key);
1004 }
1005 }
1006
1007 bool _ValidateErase(const key_type& key)
1008 {
1009 SdfSpecHandle owner = _Owner();
1010 if (owner && !owner->PermissionToEdit()) {
1011 TF_CODING_ERROR("Can't erase value from %s: Permission denied.",
1012 _Location().c_str());
1013 return false;
1014 }
1015
1016 return true;
1017 }
1018
1019private:
1020 template <class ProxyT> friend class SdfPyWrapMapEditProxy;
1021
1022 std::shared_ptr<Sdf_MapEditor<T> > _editor;
1023};
1024
1025// Cannot get from a VtValue except as the correct type.
1026template <class T, class _ValuePolicy>
1027struct Vt_DefaultValueFactory<SdfMapEditProxy<T, _ValuePolicy> > {
1028 static Vt_DefaultValueHolder Invoke() = delete;
1029};
1030
1031PXR_NAMESPACE_CLOSE_SCOPE
1032
1033#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:735
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::enable_if<!std::is_enum< T >::value, std::string >::type TfStringify(const T &v)
Convert an arbitrary type into a string.
Definition: stringUtils.h:541