All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
mapEditProxy.h
Go to the documentation of this file.
1 //
2 // Copyright 2016 Pixar
3 //
4 // Licensed under the Apache License, Version 2.0 (the "Apache License")
5 // with the following modification; you may not use this file except in
6 // compliance with the Apache License and the following modification to it:
7 // Section 6. Trademarks. is deleted and replaced with:
8 //
9 // 6. Trademarks. This License does not grant permission to use the trade
10 // names, trademarks, service marks, or product names of the Licensor
11 // and its affiliates, except as required to comply with Section 4(c) of
12 // the License and to reproduce the content of the NOTICE file.
13 //
14 // You may obtain a copy of the Apache License at
15 //
16 // http://www.apache.org/licenses/LICENSE-2.0
17 //
18 // Unless required by applicable law or agreed to in writing, software
19 // distributed under the Apache License with the above modification is
20 // distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
21 // KIND, either express or implied. See the Apache License for the specific
22 // language governing permissions and limitations under the Apache License.
23 //
24 #ifndef SDF_MAPEDITPROXY_H
25 #define SDF_MAPEDITPROXY_H
26 
28 
29 #include "pxr/pxr.h"
30 #include "pxr/usd/sdf/allowed.h"
31 #include "pxr/usd/sdf/changeBlock.h"
32 #include "pxr/usd/sdf/declareHandles.h"
33 #include "pxr/usd/sdf/mapEditor.h"
34 #include "pxr/usd/sdf/spec.h"
35 
36 #include "pxr/base/vt/value.h" // for Vt_DefaultValueFactory
37 #include "pxr/base/tf/diagnostic.h"
38 #include "pxr/base/tf/mallocTag.h"
39 #include <boost/iterator/iterator_facade.hpp>
40 #include <boost/iterator/reverse_iterator.hpp>
41 #include <boost/operators.hpp>
42 #include <iterator>
43 #include <utility>
44 
45 PXR_NAMESPACE_OPEN_SCOPE
46 
47 class TfToken;
48 
49 SDF_DECLARE_HANDLES(SdfSpec);
50 
63 template <class T>
65 public:
66  typedef T Type;
67  typedef typename Type::key_type key_type;
68  typedef typename Type::mapped_type mapped_type;
69  typedef typename Type::value_type value_type;
70 
74  static const Type& CanonicalizeType(const SdfSpecHandle&, const Type& x)
75  {
76  return x;
77  }
78 
81  static const key_type& CanonicalizeKey(const SdfSpecHandle&,
82  const key_type& x)
83  {
84  return x;
85  }
86 
89  static const mapped_type& CanonicalizeValue(const SdfSpecHandle&,
90  const mapped_type& x)
91  {
92  return x;
93  }
94 
98  static const value_type& CanonicalizePair(const SdfSpecHandle&,
99  const value_type& x)
100  {
101  return x;
102  }
103 };
104 
119 template <class T, class _ValuePolicy = SdfIdentityMapEditProxyValuePolicy<T> >
121  boost::totally_ordered<SdfMapEditProxy<T, _ValuePolicy>, T> {
122 public:
123  typedef T Type;
124  typedef _ValuePolicy ValuePolicy;
126  typedef typename Type::key_type key_type;
127  typedef typename Type::mapped_type mapped_type;
128  typedef typename Type::value_type value_type;
129 
130 private:
131  // Note: We're playing a dangerous game with copy-on-write and
132  // iterators. Our iterators wrap iterators on the proxied
133  // Type. When and if we copy-on-write then all of our
134  // existing iterators use the old proxied object's iterators
135  // and any new iterators will use the new proxied object's
136  // iterators. Therefore old and new iterators are no longer
137  // compatible and an old and new iterator that refer to the
138  // same key will not compare equal.
139  //
140  // It turns out that this is okay because we don't promise
141  // to keep iterators valid across an edit. However, we'd
142  // like dereferencing an old iterator to either report an
143  // error or yield the current state. We can do that by
144  // storing the Type* in use when the iterator was created
145  // and comparing it to the current Type*. If they're
146  // different we need to report an error or use the key from
147  // the old iterator and lookup that key in the new Type*.
148  // We currently choose to return the current state.
149 
150  typedef typename Type::iterator inner_iterator;
151  typedef typename Type::const_iterator const_inner_iterator;
152 
153  class _ValueProxy {
154  public:
155  _ValueProxy(This* owner, const Type* data, inner_iterator i) :
156  _owner(owner), _data(data), _pos(i)
157  {
158  // Do nothing
159  }
160 
161  template <class U>
162  _ValueProxy& operator=(const U& other)
163  {
164  if (!_owner) {
165  TF_CODING_ERROR("Assignment to invalid map proxy");
166  } else {
167  _owner->_Set(_data, _pos, other);
168  }
169  return *this;
170  }
171 
172  operator mapped_type() const
173  {
174  return Get();
175  }
176 
177  // Required for _PairProxy::operator value_type().
178  mapped_type Get() const
179  {
180  if (!_owner) {
181  TF_CODING_ERROR("Read from invalid map proxy");
182  return mapped_type();
183  }
184  return _owner->_Get(_data, _pos);
185  }
186 
187  private:
188  This* _owner;
189  const Type* _data;
190  inner_iterator _pos;
191  };
192 
193  class _PairProxy : boost::totally_ordered<_PairProxy> {
194  public:
195  explicit _PairProxy(This* owner, const Type* data, inner_iterator i) :
196  first(i->first), second(_ValueProxy(owner, data, i)) { }
197 
198  const key_type first;
199  _ValueProxy second;
200 
201  operator value_type() const
202  {
203  // Note that we cannot simply use 'second' or we'll use the
204  // mapped_type c'tor instead of the _ValueProxy implicit
205  // conversion if one is available. If mapped_type is VtValue
206  // then we'll type erase _ValueProxy instead of just getting
207  // the VtValue out of the _ValueProxy.
208  return value_type(first, second.Get());
209  }
210  };
211 
212  class Traits {
213  public:
214  static _PairProxy Dereference(This* owner,
215  const Type* data, inner_iterator i)
216  {
217  if (!owner) {
218  TF_FATAL_ERROR("Dereferenced an invalid map proxy iterator");
219  }
220  return _PairProxy(owner, data, i);
221  }
222 
223  static const value_type& Dereference(const This* owner,
224  const Type* data,
225  const_inner_iterator i)
226  {
227  if (!owner) {
228  TF_FATAL_ERROR("Dereferenced an invalid map proxy iterator");
229  }
230  return owner->_Get(data, i);
231  }
232  };
233 
234  template <class Owner, class I, class R>
235  class _Iterator :
236  public boost::iterator_facade<_Iterator<Owner, I, R>, R,
237  std::bidirectional_iterator_tag, R> {
238  public:
239  _Iterator() :
240  _owner(NULL), _data(NULL) { }
241 
242  _Iterator(Owner owner, const Type* data, I i) :
243  _owner(owner), _data(data), _pos(i)
244  {
245  // Do nothing
246  }
247 
248  template <class Owner2, class I2, class R2>
249  _Iterator(const _Iterator<Owner2, I2, R2>& other) :
250  _owner(other._owner), _data(other._data), _pos(other._pos)
251  {
252  // Do nothing
253  }
254 
255  const I& base() const
256  {
257  return _pos;
258  }
259 
260  private:
261  R dereference() const
262  {
263  return Traits::Dereference(_owner, _data, _pos);
264  }
265 
266  template <class Owner2, class I2, class R2>
267  bool equal(const _Iterator<Owner2, I2, R2>& other) const
268  {
269  if (_owner == other._owner && _pos == other._pos) {
270  return true;
271  }
272  else {
273  // All iterators at the end compare equal.
274  return atEnd() && other.atEnd();
275  }
276  }
277 
278  void increment() {
279  ++_pos;
280  }
281 
282  void decrement() {
283  --_pos;
284  }
285 
286  bool atEnd() const {
287  // We consider an iterator with no owner to be at the end.
288  return !_owner || _pos == _owner->_ConstData()->end();
289  }
290 
291  private:
292  Owner _owner;
293  const Type* _data;
294  I _pos;
295 
296  friend class boost::iterator_core_access;
297  template <class Owner2, class I2, class R2> friend class _Iterator;
298  };
299 
300 public:
301  typedef _ValueProxy reference;
302  typedef const value_type& const_reference;
303  typedef size_t size_type;
304  typedef ptrdiff_t difference_type;
305  typedef _Iterator<This*, inner_iterator, _PairProxy> iterator;
306  typedef _Iterator<const This*, const_inner_iterator,
307  const value_type&> const_iterator;
308  typedef boost::reverse_iterator<iterator> reverse_iterator;
309  typedef boost::reverse_iterator<const_iterator> const_reverse_iterator;
310 
311  explicit SdfMapEditProxy(const SdfSpecHandle& owner, const TfToken& field) :
312  _editor(Sdf_CreateMapEditor<T>(owner, field))
313  {
314  // Do nothing
315  }
316 
318  {
319  // Do nothing
320  }
321 
322  This& operator=(const This& other)
323  {
324  if (other._Validate()) {
325  _Copy(*other._ConstData());
326  }
327  return *this;
328  }
329 
330  template <class U, class UVP>
331  This& operator=(const SdfMapEditProxy<U, UVP>& other)
332  {
333  if (other._Validate()) {
334  _Copy(Type(other._ConstData()->begin(), other._ConstData()->end()));
335  }
336  return *this;
337  }
338 
339  This& operator=(const Type& data)
340  {
341  _Copy(data);
342  return *this;
343  }
344 
346  operator Type() const
347  {
348  return _Validate() ? *_ConstData() : Type();
349  }
350 
351  iterator begin()
352  {
353  return _Validate() ? iterator(this, _Data(), _Data()->begin()) :
354  iterator();
355  }
356  iterator end()
357  {
358  return _Validate() ? iterator(this, _Data(), _Data()->end()) :
359  iterator();
360  }
361  const_iterator begin() const
362  {
363  return _Validate() ?
364  const_iterator(this, _ConstData(), _ConstData()->begin()) :
365  const_iterator();
366  }
367  const_iterator end() const
368  {
369  return _Validate() ?
370  const_iterator(this, _ConstData(), _ConstData()->end()) :
371  const_iterator();
372  }
373 
374  reverse_iterator rbegin()
375  {
376  return reverse_iterator(end());
377  }
378  reverse_iterator rend()
379  {
380  return reverse_iterator(begin());
381  }
382  const_reverse_iterator rbegin() const
383  {
384  return const_reverse_iterator(end());
385  }
386  const_reverse_iterator rend() const
387  {
388  return const_reverse_iterator(begin());
389  }
390 
391  size_type size() const
392  {
393  return _Validate() ? _ConstData()->size() : 0;
394  }
395 
396  size_type max_size() const
397  {
398  return _Validate() ? _ConstData()->max_size() : 0;
399  }
400 
401  bool empty() const
402  {
403  return _Validate() ? _ConstData()->empty() : true;
404  }
405 
406  std::pair<iterator, bool> insert(const value_type& value)
407  {
408  return _Insert(value);
409  }
410 
411  iterator insert(iterator pos, const value_type& value)
412  {
413  return _Insert(value).first;
414  }
415 
416  template <class InputIterator>
417  void insert(InputIterator first, InputIterator last)
418  {
419  if (_Validate()) {
420  SdfChangeBlock block;
421  for (; first != last; ++first) {
422  const value_type& v =
423  ValuePolicy::CanonicalizePair(_Owner(), *first);
424 
425  if (_ValidateInsert(v)) {
426  _editor->Insert(v);
427  }
428  }
429  }
430  }
431 
432  void erase(iterator pos)
433  {
434  if (_Validate() && _ValidateErase(pos->first)) {
435  _Erase(pos->first);
436  }
437  }
438 
439  size_type erase(const key_type& key)
440  {
441  if (_Validate()) {
442  const key_type& k = ValuePolicy::CanonicalizeKey(_Owner(), key);
443  if (_ValidateErase(k)) {
444  return _editor->Erase(k) ? 1 : 0;
445  }
446  }
447  return 0;
448  }
449 
450  void erase(iterator first, iterator last)
451  {
452  if (_Validate()) {
453  SdfChangeBlock block;
454  while (first != last) {
455  const key_type& key = first->first;
456  ++first;
457  if (_ValidateErase(key)) {
458  _editor->Erase(key);
459  }
460  }
461  }
462  }
463 
464  void clear()
465  {
466  _Copy(Type());
467  }
468 
469  iterator find(const key_type& key)
470  {
471  return
472  _Validate() ?
473  iterator(this, _Data(),
474  _Data()->find(ValuePolicy::CanonicalizeKey(_Owner(), key))) :
475  iterator();
476  }
477 
478  const_iterator find(const key_type& key) const
479  {
480  return
481  _Validate() ?
482  const_iterator(this, _ConstData(),
483  _ConstData()->find(
484  ValuePolicy::CanonicalizeKey(_Owner(), key))) :
485  const_iterator();
486  }
487 
488  size_type count(const key_type& key) const
489  {
490  return
491  _Validate() ?
492  _ConstData()->count(
493  ValuePolicy::CanonicalizeKey(_Owner(), key)) :
494  0;
495  }
496 
497  iterator lower_bound(const key_type& key)
498  {
499  return
500  _Validate() ?
501  iterator(this, _Data(),
502  _Data()->lower_bound(
503  ValuePolicy::CanonicalizeKey(_Owner(), key))) :
504  iterator();
505  }
506 
507  const_iterator lower_bound(const key_type& key) const
508  {
509  return
510  _Validate() ?
511  const_iterator(this, _ConstData(),
512  _ConstData()->lower_bound(
513  ValuePolicy::CanonicalizeKey(_Owner(), key))) :
514  const_iterator();
515  }
516 
517  iterator upper_bound(const key_type& key)
518  {
519  return
520  _Validate() ?
521  iterator(this, _Data(),
522  _Data()->upper_bound(
523  ValuePolicy::CanonicalizeKey(_Owner(), key))) :
524  iterator();
525  }
526 
527  const_iterator upper_bound(const key_type& key) const
528  {
529  return
530  _Validate() ?
531  const_iterator(this, _ConstData(),
532  _ConstData()->upper_bound(
533  ValuePolicy::CanonicalizeKey(_Owner(), key))) :
534  const_iterator();
535  }
536 
537  std::pair<iterator, iterator> equal_range(const key_type& key)
538  {
539  if (_Validate()) {
540  std::pair<inner_iterator, inner_iterator> result =
541  _Data()->equal_range(
542  ValuePolicy::CanonicalizeKey(_Owner(), key));
543  return std::make_pair(iterator(this, _Data(), result.first),
544  iterator(this, _Data(), result.second));
545  }
546  else {
547  return std::make_pair(iterator(), iterator());
548  }
549  }
550 
551  std::pair<const_iterator,const_iterator>
552  equal_range(const key_type& key) const
553  {
554  if (_Validate()) {
555  std::pair<const_inner_iterator, const_inner_iterator> result =
556  _ConstData()->equal_range(
557  ValuePolicy::CanonicalizeKey(_Owner(), key));
558  return std::make_pair(
559  const_iterator(this, _ConstData(), result.first),
560  const_iterator(this, _ConstData(), result.second));
561  }
562  else {
563  return std::make_pair(const_iterator(), const_iterator());
564  }
565  }
566 
567  reference operator[](const key_type& key)
568  {
569  auto iter = _Insert(value_type(key, mapped_type())).first;
570  bool failed = iter == iterator();
571  return reference(failed ? nullptr : this,
572  failed ? nullptr : _Data(),
573  iter.base());
574  }
575 
576  bool operator==(const Type& other) const
577  {
578  return _Validate() ? _CompareEqual(other) : false;
579  }
580 
581  bool operator<(const Type& other) const
582  {
583  return _Validate() ? _Compare(other) < 0 : false;
584  }
585 
586  bool operator>(const Type& other) const
587  {
588  return _Validate() ? _Compare(other) > 0 : false;
589  }
590 
591  template <class U, class UVP>
592  bool operator==(const SdfMapEditProxy<U, UVP>& other) const
593  {
594  return _Validate() && other._Validate() ?
595  _CompareEqual(*other._ConstData()) : false;
596  }
597 
598  template <class U, class UVP>
599  bool operator!=(const SdfMapEditProxy<U, UVP>& other) const
600  {
601  return !(*this == other);
602  }
603 
604  template <class U, class UVP>
605  bool operator<(const SdfMapEditProxy<U, UVP>& other) const
606  {
607  return _Validate() && other._Validate() ?
608  _Compare(*other._ConstData()) < 0 : false;
609  }
610 
611  template <class U, class UVP>
612  bool operator<=(const SdfMapEditProxy<U, UVP>& other) const
613  {
614  return _Validate() && other._Validate() ?
615  _Compare(*other._ConstData()) <= 0 : false;
616  }
617 
618  template <class U, class UVP>
619  bool operator>(const SdfMapEditProxy<U, UVP>& other) const
620  {
621  return !(*this <= other);
622  }
623 
624  template <class U, class UVP>
625  bool operator>=(const SdfMapEditProxy<U, UVP>& other) const
626  {
627  return !(*this < other);
628  }
629 
632  bool IsExpired() const
633  {
634  return _editor && _editor->IsExpired();
635  }
636 
639  explicit operator bool() const
640  {
641  return _ConstData() && !IsExpired();
642  }
643 
644 private:
645  bool _Validate()
646  {
647  if (_ConstData() && !IsExpired()) {
648  return true;
649  }
650  else {
651  TF_CODING_ERROR("Editing an invalid map proxy");
652  return false;
653  }
654  }
655 
656  bool _Validate() const
657  {
658  if (_ConstData() && !IsExpired()) {
659  return true;
660  }
661  else {
662  TF_CODING_ERROR("Accessing an invalid map proxy");
663  return false;
664  }
665  }
666 
667  Type* _Data()
668  {
669  return _editor ? _editor->GetData() : NULL;
670  }
671 
672  const Type* _ConstData() const
673  {
674  return _editor ? _editor->GetData() : NULL;
675  }
676 
677  SdfSpecHandle _Owner() const
678  {
679  return _editor ? _editor->GetOwner() : SdfSpecHandle();
680  }
681 
682  std::string _Location() const
683  {
684  return _editor ? _editor->GetLocation() : std::string();
685  }
686 
687  bool _CompareEqual(const Type& other) const
688  {
689  if (_ConstData()->size() < other.size()) {
690  return false;
691  }
692  if (_ConstData()->size() > other.size()) {
693  return false;
694  }
695 
696  // Same size -- find the first mismatch.
697  const Type& x = ValuePolicy::CanonicalizeType(_Owner(), other);
698  std::pair<const_inner_iterator, const_inner_iterator> result =
699  std::mismatch(_ConstData()->begin(), _ConstData()->end(),
700  x.begin());
701  return result.first == _ConstData()->end();
702  }
703 
704  int _Compare(const Type& other) const
705  {
706  if (_ConstData()->size() < other.size()) {
707  return -1;
708  }
709  if (_ConstData()->size() > other.size()) {
710  return 1;
711  }
712 
713  // Same size -- find the first mismatch.
714  const Type& x = ValuePolicy::CanonicalizeType(_Owner(), other);
715  std::pair<const_inner_iterator, const_inner_iterator> result =
716  std::mismatch(_ConstData()->begin(), _ConstData()->end(),
717  x.begin());
718  if (*result.first < *result.second) {
719  return -1;
720  }
721  else if (*result.first > *result.second) {
722  return 1;
723  }
724  else {
725  return 0;
726  }
727  }
728 
729  template <class D>
730  bool _CompareEqual(const D& other) const
731  {
732  // This is expensive but yields reliable results.
733  return _CompareEqual(Type(other.begin(), other.end()));
734  }
735 
736  template <class D>
737  int _Compare(const D& other) const
738  {
739  // This is expensive but yields reliable ordering.
740  return _Compare(Type(other.begin(), other.end()));
741  }
742 
743  mapped_type _Get(const Type* data, const inner_iterator& i)
744  {
745  if (_Validate()) {
746  if (data == _ConstData()) {
747  return i->second;
748  }
749  else {
750  // Data has changed since we created the iterator.
751  // Look up same key in new data.
752  return _ConstData()->find(i->first)->second;
753  }
754  }
755  return mapped_type();
756  }
757 
758  const value_type& _Get(const Type* data,
759  const const_inner_iterator& i) const
760  {
761  // If data has changed since we created the iterator then look up
762  // the same key in the new data.
763  return (data == _ConstData()) ? *i : *_ConstData()->find(i->first);
764  }
765 
766  void _Copy(const Type& other)
767  {
768  if (_Validate()) {
769  // Canonicalize the given map before copying it into ourselves.
770  // If multiple keys in the given map would conflict with each
771  // other in the canonicalized map, we consider this an error.
772  // This is primarily to avoid confusing the consumer, who would
773  // otherwise observe a key/value pair to be missing entirely.
774  Type canonicalOther;
775  TF_FOR_ALL(it, other) {
776  const value_type canonicalValue =
777  ValuePolicy::CanonicalizePair(_Owner(), *it);
778  if (!canonicalOther.insert(canonicalValue).second) {
779  TF_CODING_ERROR("Can't copy to %s: Duplicate key '%s' "
780  "exists in map.",
781  _Location().c_str(),
782  TfStringify(canonicalValue.first).c_str());
783  return;
784  }
785  }
786 
787  if (_ValidateCopy(canonicalOther)) {
788  _editor->Copy(canonicalOther);
789  }
790  }
791  }
792 
793  bool _ValidateCopy(const Type& other)
794  {
795  SdfSpecHandle owner = _Owner();
796  if (owner && !owner->PermissionToEdit()) {
797  TF_CODING_ERROR("Can't copy to %s: Permission denied.",
798  _Location().c_str());
799  return false;
800  }
801 
802  if (other.empty()) {
803  return true;
804  }
805 
806  TF_FOR_ALL(it, other) {
807  if (!_ValidateInsert(*it)) {
808  return false;
809  }
810  }
811 
812  return true;
813  }
814 
815  template <class U>
816  void _Set(const Type* data, const inner_iterator& i, const U& value)
817  {
818  if (_Validate()) {
819  const mapped_type& x =
820  ValuePolicy::CanonicalizeValue(_Owner(), value);
821  if (_ValidateSet(i->first, x)) {
822  _editor->Set(i->first, x);
823  }
824  }
825  }
826 
827  bool _ValidateSet(const key_type& key, const mapped_type& value)
828  {
829  SdfSpecHandle owner = _Owner();
830  if (owner && !owner->PermissionToEdit()) {
831  TF_CODING_ERROR("Can't set value in %s: Permission denied.",
832  _Location().c_str());
833  return false;
834  }
835 
836  if (SdfAllowed allowed = _editor->IsValidValue(value)) {
837  // Do nothing
838  }
839  else {
840  TF_CODING_ERROR("Can't set value in %s: %s",
841  _Location().c_str(),
842  allowed.GetWhyNot().c_str());
843  return false;
844  }
845 
846  return true;
847  }
848 
849  std::pair<iterator, bool> _Insert(const value_type& value)
850  {
851  if (_Validate()) {
852  const value_type& v = ValuePolicy::CanonicalizePair(_Owner(), value);
853  if (_ValidateInsert(v)) {
854  std::pair<inner_iterator, bool> status = _editor->Insert(v);
855  return std::make_pair(iterator(this, _Data(), status.first),
856  status.second);
857  }
858  else {
859  return std::make_pair(iterator(), false);
860  }
861  }
862  return std::make_pair(iterator(), false);
863  }
864 
865  bool _ValidateInsert(const value_type& value)
866  {
867  SdfSpecHandle owner = _Owner();
868  if (owner && !owner->PermissionToEdit()) {
869  TF_CODING_ERROR("Can't insert value in %s: Permission denied.",
870  _Location().c_str());
871  return false;
872  }
873 
874  if (SdfAllowed allowed = _editor->IsValidKey(value.first)) {
875  // Do nothing
876  }
877  else {
878  TF_CODING_ERROR("Can't insert key in %s: %s",
879  _Location().c_str(),
880  allowed.GetWhyNot().c_str());
881  return false;
882  }
883 
884  if (SdfAllowed allowed = _editor->IsValidValue(value.second)) {
885  // Do nothing
886  }
887  else {
888  TF_CODING_ERROR("Can't insert value in %s: %s",
889  _Location().c_str(),
890  allowed.GetWhyNot().c_str());
891  return false;
892  }
893 
894  return true;
895  }
896 
897  void _Erase(const key_type& key)
898  {
899  if (_Validate() && _ValidateErase(key)) {
900  _editor->Erase(key);
901  }
902  }
903 
904  bool _ValidateErase(const key_type& key)
905  {
906  SdfSpecHandle owner = _Owner();
907  if (owner && !owner->PermissionToEdit()) {
908  TF_CODING_ERROR("Can't erase value from %s: Permission denied.",
909  _Location().c_str());
910  return false;
911  }
912 
913  return true;
914  }
915 
916 private:
917  template <class ProxyT> friend class SdfPyWrapMapEditProxy;
918 
919  boost::shared_ptr<Sdf_MapEditor<T> > _editor;
920 };
921 
922 // Cannot get from a VtValue except as the correct type.
923 template <class T, class _ValuePolicy>
924 struct Vt_DefaultValueFactory<SdfMapEditProxy<T, _ValuePolicy> > {
925  static Vt_DefaultValueHolder Invoke() = delete;
926 };
927 
928 PXR_NAMESPACE_CLOSE_SCOPE
929 
930 #endif // SDF_MAPEDITPROXY_H
static const value_type & CanonicalizePair(const SdfSpecHandle &, const value_type &x)
Canonicalize a key/value pair.
Definition: mapEditProxy.h:98
bool IsExpired() const
Returns true if the value is expired.
Definition: mapEditProxy.h:632
#define TF_CODING_ERROR(fmt, args)
Issue an internal programming error, but continue execution.
Definition: diagnostic.h:87
Base class for all Sdf spec classes.
Definition: spec.h:51
static const key_type & CanonicalizeKey(const SdfSpecHandle &, const key_type &x)
Canonicalize a key.
Definition: mapEditProxy.h:81
static const mapped_type & CanonicalizeValue(const SdfSpecHandle &, const mapped_type &x)
Canonicalize a value.
Definition: mapEditProxy.h:89
Token for efficient comparison, assignment, and hashing of known strings.
Definition: token.h:89
DANGER DANGER DANGER
Definition: changeBlock.h:72
Indicates if an operation is allowed and, if not, why not.
Definition: allowed.h:47
#define TF_FOR_ALL(iter, c)
Macro for iterating over a container.
Definition: iterator.h:390
A proxy for editing map-like values.
Definition: mapEditProxy.h:120
#define TF_FATAL_ERROR(fmt, args)
Issue a fatal error and end the program.
Definition: diagnostic.h:111
A value policy for SdfMapEditProxy that does nothing.
Definition: mapEditProxy.h:64
VT_API bool operator==(VtDictionary const &, VtDictionary const &)
Equality comparison.
static const Type & CanonicalizeType(const SdfSpecHandle &, const Type &x)
Canonicalize an entire Type object.
Definition: mapEditProxy.h:74
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:523