This document is for a version of USD that is under development. See this page for the current release.
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