All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
listProxy.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_LIST_PROXY_H
8#define PXR_USD_SDF_LIST_PROXY_H
9
11
12#include "pxr/pxr.h"
13#include "pxr/usd/sdf/allowed.h"
14#include "pxr/usd/sdf/listEditor.h"
15#include "pxr/usd/sdf/listOp.h"
16#include "pxr/usd/sdf/path.h"
17
21
22#include <memory>
23#include <optional>
24#include <type_traits>
25
26PXR_NAMESPACE_OPEN_SCOPE
27
36template <class _TypePolicy>
38public:
39 typedef _TypePolicy TypePolicy;
41 typedef typename TypePolicy::value_type value_type;
42 typedef std::vector<value_type> value_vector_type;
43
46 static const size_t invalidIndex = -1;
47
48private:
49 // Proxies an item in a list editor list.
50 class _ItemProxy {
51 public:
52 explicit _ItemProxy(This* owner, size_t index) :
53 _owner(owner), _index(index)
54 {
55 // Do nothing
56 }
57
58 _ItemProxy& operator=(const _ItemProxy& x) {
59 _owner->_Edit(_index, 1, value_vector_type(1, x));
60 return *this;
61 }
62
63 _ItemProxy& operator=(const value_type& x) {
64 _owner->_Edit(_index, 1, value_vector_type(1, x));
65 return *this;
66 }
67
68 operator value_type() const {
69 return _owner->_Get(_index);
70 }
71
72 // Operators rely on implicit conversion to value_type
73 // for comparing two _ItemProxy instances
74 bool operator==(const value_type& x) const {
75 return _owner->_Get(_index) == x;
76 }
77
78 bool operator!=(const value_type& x) const {
79 return !(*this == x);
80 }
81
82 bool operator<(const value_type& x) const {
83 return _owner->_Get(_index) < x;
84 }
85
86 bool operator>(const value_type& x) const {
87 return x < value_type(*this);
88 }
89
90 bool operator>=(const value_type& x) const {
91 return !(*this < x);
92 }
93
94 bool operator<=(const value_type& x) const {
95 return !(x < value_type(*this));
96 }
97
98 private:
99 This* _owner;
100 size_t _index;
101 };
102 friend class _ItemProxy;
103
104 class _GetHelper {
105 public:
106 typedef _ItemProxy result_type;
107
108 result_type operator()(This* owner, size_t index) const {
109 return _ItemProxy(owner, index);
110 }
111 };
112 class _ConstGetHelper {
113 public:
114 typedef value_type result_type;
115
116 result_type operator()(const This* owner, size_t index) const {
117 return owner->_Get(index);
118 }
119 };
120 friend class _GetHelper;
121 friend class _ConstGetHelper;
122
123 template <class Owner, class GetItem>
124 class _Iterator {
125 class _PtrProxy {
126 public:
127 std::add_pointer_t<typename GetItem::result_type> operator->() {
128 return std::addressof(_result);
129 }
130 private:
131 friend class _Iterator;
132 explicit _PtrProxy(
133 std::add_const_t<
134 std::add_lvalue_reference_t<
135 typename GetItem::result_type>
136 > result) : _result(result) {}
137 typename GetItem::result_type _result;
138 };
139 public:
140 using This = _Iterator<Owner, GetItem>;
141 using iterator_category = std::random_access_iterator_tag;
142 using value_type = std::remove_cv_t<
143 std::remove_reference_t<
144 typename GetItem::result_type
145 >
146 >;
147 using reference = typename GetItem::result_type;
148 using pointer = _PtrProxy;
149 using difference_type = std::ptrdiff_t;
150
151 static_assert(!std::is_lvalue_reference<reference>::value,
152 "reference is an lvalue_reference and usage of "
153 "this class unnecessarily instantiates a _PtrProxy.");
154
155 _Iterator() = default;
156
157 _Iterator(Owner owner, size_t index) : _owner(owner), _index(index)
158 {
159 // Do nothing
160 }
161
162 reference operator*() const { return dereference(); }
163 pointer operator->() const { return pointer(dereference()); }
164 reference operator[](const difference_type index) const {
165 This advanced(*this);
166 advanced.advance(index);
167 return advanced.dereference();
168 }
169
170 difference_type operator-(const This& other) const {
171 return -distance_to(other);
172 }
173
174 This& operator++() {
175 increment();
176 return *this;
177 }
178
179 This& operator--() {
180 decrement();
181 return *this;
182 }
183
184 This operator++(int) {
185 This result(*this);
186 increment();
187 return result;
188 }
189
190 This operator--(int) {
191 This result(*this);
192 decrement();
193 return result;
194 }
195
196 This operator+(const difference_type increment) const {
197 This result(*this);
198 result.advance(increment);
199 return result;
200 }
201
202 This operator-(const difference_type decrement) const {
203 This result(*this);
204 result.advance(-decrement);
205 return result;
206 }
207
208 This& operator+=(const difference_type increment) {
209 advance(increment);
210 return *this;
211 }
212
213 This& operator-=(const difference_type decrement) {
214 advance(-decrement);
215 return *this;
216 }
217
218 bool operator==(const This& other) const {
219 return equal(other);
220 }
221
222 bool operator!=(const This& other) const {
223 return !equal(other);
224 }
225
226 bool operator<(const This& other) const {
227 TF_DEV_AXIOM(_owner == other._owner);
228 return _index < other._index;
229 }
230
231 bool operator<=(const This& other) const {
232 TF_DEV_AXIOM(_owner == other._owner);
233 return _index <= other._index;
234 }
235
236 bool operator>(const This& other) const {
237 TF_DEV_AXIOM(_owner == other._owner);
238 return _index > other._index;
239 }
240
241 bool operator>=(const This& other) const {
242 TF_DEV_AXIOM(_owner == other._owner);
243 return _index >= other._index;
244 }
245
246 private:
247
248 reference dereference() const {
249 return _getItem(_owner, _index);
250 }
251
252 bool equal(const This& other) const {
253 if (_owner != other._owner) {
254 TF_CODING_ERROR("Comparing SdfListProxy iterators from "
255 "different proxies!");
256 return false;
257 }
258 return _index == other._index;
259 }
260
261 void increment() {
262 ++_index;
263 }
264
265 void decrement() {
266 --_index;
267 }
268
269 void advance(difference_type n) {
270 _index += n;
271 }
272
273 difference_type distance_to(const This& other) const {
274 return other._index - _index;
275 }
276
277 private:
278 GetItem _getItem;
279 Owner _owner = nullptr;
280 size_t _index = 0;
281 };
282
283public:
284 typedef _ItemProxy reference;
285 typedef _Iterator<This*, _GetHelper> iterator;
286 typedef _Iterator<const This*, _ConstGetHelper> const_iterator;
287 typedef Tf_ProxyReferenceReverseIterator<iterator> reverse_iterator;
288 typedef Tf_ProxyReferenceReverseIterator<const_iterator> const_reverse_iterator;
289
293 SdfListProxy(SdfListOpType op) :
294 _op(op)
295 {
296 }
297
300 SdfListProxy(const std::shared_ptr<Sdf_ListEditor<TypePolicy> >& editor,
301 SdfListOpType op) :
302 _listEditor(editor),
303 _op(op)
304 {
305 }
306
308 iterator begin() {
309 return iterator(_GetThis(), 0);
310 }
312 iterator end() {
313 return iterator(_GetThis(), _GetSize());
314 }
315
317 reverse_iterator rbegin() {
318 return reverse_iterator(end());
319 }
321 reverse_iterator rend() {
322 return reverse_iterator(begin());
323 }
324
326 const_iterator begin() const {
327 return const_iterator(_GetThis(), 0);
328 }
330 const_iterator end() const {
331 return const_iterator(_GetThis(), _GetSize());
332 }
333
335 const_reverse_iterator rbegin() const {
336 return const_reverse_iterator(end());
337 }
340 const_reverse_iterator rend() const {
341 return const_reverse_iterator(begin());
342 }
343
345 size_t size() const {
346 return _Validate() ? _GetSize() : 0;
347 }
348
350 bool empty() const {
351 return size() == 0;
352 }
353
355 reference operator[](size_t n) {
356 return reference(_GetThis(), n);
357 }
358
360 value_type operator[](size_t n) const {
361 return _Get(n);
362 }
363
365 reference front() {
366 return reference(_GetThis(), 0);
367 }
368
370 reference back() {
371 return reference(_GetThis(), _GetSize() - 1);
372 }
373
375 value_type front() const {
376 return _Get(0);
377 }
378
380 value_type back() const {
381 return _Get(_GetSize() - 1);
382 }
383
385 void push_back(const value_type& elem) {
386 _Edit(_GetSize(), 0, value_vector_type(1, elem));
387 }
388
390 void pop_back() {
391 _Edit(_GetSize() - 1, 1, value_vector_type());
392 }
393
395 iterator insert(iterator pos, const value_type& x) {
396 _Edit(pos - iterator(this, 0), 0, value_vector_type(1, x));
397 return pos;
398 }
399
402 template <class InputIterator>
403 void insert(iterator pos, InputIterator f, InputIterator l) {
404 _Edit(pos - iterator(this, 0), 0, value_vector_type(f, l));
405 }
406
408 void erase(iterator pos) {
409 _Edit(pos - iterator(this, 0), 1, value_vector_type());
410 }
411
413 void erase(iterator f, iterator l) {
414 _Edit(f - iterator(this, 0), l - f, value_vector_type());
415 }
416
418 void clear() {
419 _Edit(0, _GetSize(), value_vector_type());
420 }
421
426 void resize(size_t n, const value_type& t = value_type()) {
427 size_t s = _GetSize();
428 if (n > s) {
429 _Edit(s, 0, value_vector_type(n - s, t));
430 }
431 else if (n < s) {
432 _Edit(n, s - n, value_vector_type());
433 }
434 }
435
437 operator value_vector_type() const {
438 return _listEditor ? _listEditor->GetVector(_op) : value_vector_type();
439 }
440
443 template <class T2>
445 _Edit(0, _GetSize(), static_cast<value_vector_type>(other));
446 return *this;
447 }
448
450 This& operator=(const value_vector_type& other) {
451 _Edit(0, _GetSize(), other);
452 return *this;
453 }
454
456 template <class Y>
457 This& operator=(const std::vector<Y>& v) {
458 _Edit(0, _GetSize(), value_vector_type(v.begin(), v.end()));
459 return *this;
460 }
461
463 template <class T2>
464 bool operator==(const SdfListProxy<T2>& y) const {
465 return value_vector_type(*this) == value_vector_type(y);
466 }
467
469 template <class T2>
470 bool operator!=(const SdfListProxy<T2>& y) const {
471 return !(*this == y);
472 }
473
475 template <class T2>
476 bool operator<(const SdfListProxy<T2>& y) const {
477 return value_vector_type(*this) < value_vector_type(y);
478 }
479
481 template <class T2>
482 bool operator<=(const SdfListProxy<T2>& y) const {
483 return value_vector_type(*this) <= value_vector_type(y);
484 }
485
487 template <class T2>
488 bool operator>(const SdfListProxy<T2>& y) const {
489 return !(*this <= y);
490 }
491
493 template <class T2>
494 bool operator>=(const SdfListProxy<T2>& y) const {
495 return !(*this < y);
496 }
497
499 bool operator==(const value_vector_type& y) const {
500 return value_vector_type(*this) == y;
501 }
502
504 friend bool operator==(const value_vector_type& x, const SdfListProxy& y) {
505 return y == x;
506 }
507
509 bool operator!=(const value_vector_type& y) const {
510 return !(*this == y);
511 }
512
514 friend bool operator!=(const value_vector_type& x, const SdfListProxy& y) {
515 return y != x;
516 }
517
519 bool operator<(const value_vector_type& y) const {
520 return value_vector_type(*this) < y;
521 }
522
524 friend bool operator<(const value_vector_type& x, const SdfListProxy& y) {
525 return x < value_vector_type(y);
526 }
527
529 bool operator>(const value_vector_type& y) const {
530 return value_vector_type(*this) > y;
531 }
532
534 friend bool operator>(const value_vector_type& x, const SdfListProxy& y) {
535 return x > value_vector_type(y);
536 }
537
539 bool operator<=(const value_vector_type& y) const {
540 return !(*this > y);
541 }
542
544 friend bool operator<=(const value_vector_type& x, const SdfListProxy& y) {
545 return x <= value_vector_type(y);
546 }
547
549 bool operator>=(const value_vector_type& y) const {
550 return !(*this < y);
551 }
552
554 friend bool operator>=(const value_vector_type& x, const SdfListProxy& y) {
555 return x >= value_vector_type(y);
556 }
557
560 explicit operator bool() const
561 {
562 return _listEditor && _listEditor->IsValid() && _IsRelevant();
563 }
564
565 // Extensions
566
568 SdfLayerHandle GetLayer() const
569 {
570 return _listEditor ? _listEditor->GetLayer() : SdfLayerHandle();
571 }
572
575 {
576 return _listEditor ? _listEditor->GetPath() : SdfPath();
577 }
578
580 bool IsExpired() const
581 {
582 return _listEditor && _listEditor->IsExpired();
583 }
584
585 size_t Count(const value_type& value) const
586 {
587 return (_Validate() ? _listEditor->Count(_op, value) : 0);
588 }
589
592 size_t Find(const value_type& value) const
593 {
594 return (_Validate() ? _listEditor->Find(_op, value) : invalidIndex);
595 }
596
597 void Insert(int index, const value_type& value)
598 {
599 if (index == -1) {
600 index = static_cast<int>(_GetSize());
601 }
602 _Edit(index, 0, value_vector_type(1, value));
603 }
604
605 void Remove(const value_type& value)
606 {
607 size_t index = Find(value);
608 if (index != invalidIndex) {
609 Erase(index);
610 }
611 else {
612 // Allow policy to raise an error even though we're not
613 // doing anything.
614 _Edit(_GetSize(), 0, value_vector_type());
615 }
616 }
617
618 void Replace(const value_type& oldValue, const value_type& newValue)
619 {
620 size_t index = Find(oldValue);
621 if (index != size_t(-1)) {
622 _Edit(index, 1, value_vector_type(1, newValue));
623 }
624 else {
625 // Allow policy to raise an error even though we're not
626 // doing anything.
627 _Edit(_GetSize(), 0, value_vector_type());
628 }
629 }
630
631 void Erase(size_t index)
632 {
633 _Edit(index, 1, value_vector_type());
634 }
635
637 void ApplyList(const SdfListProxy &list)
638 {
639 if (_Validate() && list._Validate()) {
640 _listEditor->ApplyList(_op, *list._listEditor);
641 }
642 }
643
645 void ApplyEditsToList(value_vector_type* vec)
646 {
647 if (_Validate()) {
648 _listEditor->ApplyEditsToList(vec);
649 }
650 }
651
662 template <class CB>
663 void ModifyItemEdits(CB callback)
664 {
665 if (_Validate()) {
666 _listEditor->ModifyItemEdits(std::forward<CB>(callback));
667 }
668 }
669
670private:
671 bool _Validate()
672 {
673 if (!_listEditor) {
674 return false;
675 }
676
677 if (IsExpired()) {
678 TF_CODING_ERROR("Accessing expired list editor");
679 return false;
680 }
681 return true;
682 }
683
684 bool _Validate() const
685 {
686 if (!_listEditor) {
687 return false;
688 }
689
690 if (IsExpired()) {
691 TF_CODING_ERROR("Accessing expired list editor");
692 return false;
693 }
694 return true;
695 }
696
697 This* _GetThis()
698 {
699 return _Validate() ? this : NULL;
700 }
701
702 const This* _GetThis() const
703 {
704 return _Validate() ? this : NULL;
705 }
706
707 bool _IsRelevant() const
708 {
709 if (_listEditor->IsExplicit()) {
710 return _op == SdfListOpTypeExplicit;
711 }
712 else if (_listEditor->IsOrderedOnly()) {
713 return _op == SdfListOpTypeOrdered;
714 }
715 else {
716 return _op != SdfListOpTypeExplicit;
717 }
718 }
719
720 size_t _GetSize() const
721 {
722 return _listEditor ? _listEditor->GetSize(_op) : 0;
723 }
724
725 value_type _Get(size_t n) const
726 {
727 return _Validate() ? _listEditor->Get(_op, n) : value_type();
728 }
729
730 void _Edit(size_t index, size_t n, const value_vector_type& elems)
731 {
732 if (_Validate()) {
733 // Allow policy to raise an error even if we're not
734 // doing anything.
735 if (n == 0 && elems.empty()) {
736 SdfAllowed canEdit = _listEditor->PermissionToEdit(_op);
737 if (!canEdit) {
738 TF_CODING_ERROR("Editing list: %s",
739 canEdit.GetWhyNot().c_str());
740 }
741 return;
742 }
743
744 bool valid =
745 _listEditor->ReplaceEdits(_op, index, n, elems);
746 if (!valid) {
747 TF_CODING_ERROR("Inserting invalid value into list editor");
748 }
749 }
750 }
751
752private:
753 std::shared_ptr<Sdf_ListEditor<TypePolicy> > _listEditor;
754 SdfListOpType _op;
755
756 template <class> friend class SdfPyWrapListProxy;
757};
758
759// Allow TfIteration over list proxies.
760template <typename T>
761struct Tf_ShouldIterateOverCopy<SdfListProxy<T> > : std::true_type
762{
763};
764
765PXR_NAMESPACE_CLOSE_SCOPE
766
767#endif // PXR_USD_SDF_LIST_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
SDF_API const std::string & GetWhyNot() const
Returns the reason why the operation is not allowed.
Represents a single list of list editing operations.
Definition: listProxy.h:37
void pop_back()
Remove the last element from this sequence.
Definition: listProxy.h:390
value_type operator[](size_t n) const
Return a copy of the item at index n.
Definition: listProxy.h:360
const_reverse_iterator rend() const
Return a const reverse iterator past the start item of the sequence.
Definition: listProxy.h:340
void push_back(const value_type &elem)
Append elem to this sequence.
Definition: listProxy.h:385
friend bool operator<=(const value_vector_type &x, const SdfListProxy &y)
Less-than or equal to comparison.
Definition: listProxy.h:544
void ApplyList(const SdfListProxy &list)
Applies the edits in the given list to this one.
Definition: listProxy.h:637
value_type front() const
Return a copy of the item at the front of the sequence.
Definition: listProxy.h:375
bool operator<=(const value_vector_type &y) const
Less-than or equal to comparison.
Definition: listProxy.h:539
friend bool operator<(const value_vector_type &x, const SdfListProxy &y)
Less-than comparison.
Definition: listProxy.h:524
void ApplyEditsToList(value_vector_type *vec)
Apply the edits in this list to the given vec.
Definition: listProxy.h:645
size_t size() const
Return the size of the sequence.
Definition: listProxy.h:345
const_iterator begin() const
Return a const iterator to the start of the sequence.
Definition: listProxy.h:326
void resize(size_t n, const value_type &t=value_type())
Resize the contents of the sequence.
Definition: listProxy.h:426
void insert(iterator pos, InputIterator f, InputIterator l)
Insert copies of the elements in [f, l) into this sequence starting at position pos.
Definition: listProxy.h:403
size_t Find(const value_type &value) const
Returns the index of value in the list of operations.
Definition: listProxy.h:592
bool operator>(const SdfListProxy< T2 > &y) const
Greater-than comparison.
Definition: listProxy.h:488
bool operator<=(const SdfListProxy< T2 > &y) const
Less-than-or-equal comparison.
Definition: listProxy.h:482
bool operator<(const SdfListProxy< T2 > &y) const
Less-than comparison.
Definition: listProxy.h:476
SdfListProxy(const std::shared_ptr< Sdf_ListEditor< TypePolicy > > &editor, SdfListOpType op)
Create a new proxy wrapping the list operation vector specified by op in the underlying listEditor.
Definition: listProxy.h:300
bool operator!=(const SdfListProxy< T2 > &y) const
Inequality comparison.
Definition: listProxy.h:470
bool empty() const
Return true if size() == 0.
Definition: listProxy.h:350
friend bool operator!=(const value_vector_type &x, const SdfListProxy &y)
Inequality comparision.
Definition: listProxy.h:514
reverse_iterator rend()
Return a reverse iterator past the start item of the sequence.
Definition: listProxy.h:321
reference front()
Return a reference to the item at the front of the sequence.
Definition: listProxy.h:365
SdfLayerHandle GetLayer() const
Returns the layer that this list editor belongs to.
Definition: listProxy.h:568
bool operator>=(const SdfListProxy< T2 > &y) const
Greater-than-or-equal comparison.
Definition: listProxy.h:494
value_type back() const
Return a copy of the item at the back of the sequence.
Definition: listProxy.h:380
friend bool operator>(const value_vector_type &x, const SdfListProxy &y)
Greater-than comparison.
Definition: listProxy.h:534
static const size_t invalidIndex
Returned from Find when a value could not be located in the list of operations.
Definition: listProxy.h:46
bool operator>(const value_vector_type &y) const
Greater-than comparison.
Definition: listProxy.h:529
reference operator[](size_t n)
Return a reference to the item at index n.
Definition: listProxy.h:355
SdfListProxy(SdfListOpType op)
Creates a default list proxy object for list operation vector specified op.
Definition: listProxy.h:293
This & operator=(const std::vector< Y > &v)
Replace all elements in this sequence with the given vector.
Definition: listProxy.h:457
void ModifyItemEdits(CB callback)
Modify all edits in this list.
Definition: listProxy.h:663
void erase(iterator f, iterator l)
Erase all the elements in the range [f, l).
Definition: listProxy.h:413
SdfPath GetPath() const
Returns the path to this list editor's value.
Definition: listProxy.h:574
friend bool operator==(const value_vector_type &x, const SdfListProxy &y)
Equality comparision.
Definition: listProxy.h:504
bool operator<(const value_vector_type &y) const
Less-than comparison.
Definition: listProxy.h:519
bool operator==(const value_vector_type &y) const
Equality comparison.
Definition: listProxy.h:499
iterator insert(iterator pos, const value_type &x)
Insert x into this sequence at position pos.
Definition: listProxy.h:395
bool IsExpired() const
Returns true if the list editor is expired.
Definition: listProxy.h:580
bool operator!=(const value_vector_type &y) const
Inequality comparison.
Definition: listProxy.h:509
bool operator>=(const value_vector_type &y) const
Greater-than or equal to comparison.
Definition: listProxy.h:549
void clear()
Clear the contents of the sequence.
Definition: listProxy.h:418
iterator end()
Return an iterator to the end of the sequence.
Definition: listProxy.h:312
const_iterator end() const
Return a const iterator to the end of the sequence.
Definition: listProxy.h:330
void erase(iterator pos)
Erase the element at pos.
Definition: listProxy.h:408
reverse_iterator rbegin()
Return a reverse iterator to the last item of the sequence.
Definition: listProxy.h:317
iterator begin()
Return an iterator to the start of the sequence.
Definition: listProxy.h:308
This & operator=(const SdfListProxy< T2 > &other)
Replace all elements in this sequence with the elements in the other sequence.
Definition: listProxy.h:444
const_reverse_iterator rbegin() const
Return a const reverse iterator to the last item of the sequence.
Definition: listProxy.h:335
reference back()
Return a reference to the item at the back of the sequence.
Definition: listProxy.h:370
This & operator=(const value_vector_type &other)
Replace all elements in this sequence with the given vector.
Definition: listProxy.h:450
bool operator==(const SdfListProxy< T2 > &y) const
Equality comparison.
Definition: listProxy.h:464
friend bool operator>=(const value_vector_type &x, const SdfListProxy &y)
Greater-than or equal to comparison.
Definition: listProxy.h:554
A path value used to locate objects in layers or scenegraphs.
Definition: path.h:274
#define TF_DEV_AXIOM(cond)
The same as TF_AXIOM, but compiled only in dev builds.
Definition: diagnostic.h:205
#define TF_CODING_ERROR(fmt, args)
Issue an internal programming error, but continue execution.
Definition: diagnostic.h:68