listProxy.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_LIST_PROXY_H
25 #define PXR_USD_SDF_LIST_PROXY_H
26 
28 
29 #include "pxr/pxr.h"
30 #include "pxr/usd/sdf/allowed.h"
31 #include "pxr/usd/sdf/listEditor.h"
32 #include "pxr/usd/sdf/listOp.h"
33 #include "pxr/usd/sdf/path.h"
34 
35 #include "pxr/base/tf/diagnostic.h"
36 #include "pxr/base/tf/errorMark.h"
37 #include "pxr/base/tf/iterator.h"
38 #include <boost/iterator/iterator_facade.hpp>
39 #include <boost/iterator/reverse_iterator.hpp>
40 #include <boost/operators.hpp>
41 #include <boost/optional.hpp>
42 #include <boost/type_traits/is_base_of.hpp>
43 #include <boost/type_traits/remove_cv.hpp>
44 #include <boost/type_traits/remove_reference.hpp>
45 
46 #include <memory>
47 
48 PXR_NAMESPACE_OPEN_SCOPE
49 
58 template <class _TypePolicy>
59 class SdfListProxy :
60  boost::totally_ordered<SdfListProxy<_TypePolicy>,
61  std::vector<typename _TypePolicy::value_type> > {
62 public:
63  typedef _TypePolicy TypePolicy;
65  typedef typename TypePolicy::value_type value_type;
66  typedef std::vector<value_type> value_vector_type;
67 
68 private:
69  // Proxies an item in a list editor list.
70  class _ItemProxy : boost::totally_ordered<_ItemProxy> {
71  public:
72  explicit _ItemProxy(This* owner, size_t index) :
73  _owner(owner), _index(index)
74  {
75  // Do nothing
76  }
77 
78  _ItemProxy& operator=(const _ItemProxy& x) {
79  _owner->_Edit(_index, 1, value_vector_type(1, x));
80  return *this;
81  }
82 
83  _ItemProxy& operator=(const value_type& x) {
84  _owner->_Edit(_index, 1, value_vector_type(1, x));
85  return *this;
86  }
87 
88  operator value_type() const {
89  return _owner->_Get(_index);
90  }
91 
92  bool operator==(const value_type& x) const {
93  return _owner->_Get(_index) == x;
94  }
95 
96  bool operator<(const value_type& x) const {
97  return _owner->_Get(_index) < x;
98  }
99 
100  private:
101  This* _owner;
102  size_t _index;
103  };
104  friend class _ItemProxy;
105 
106  class _GetHelper {
107  public:
108  typedef _ItemProxy result_type;
109 
110  result_type operator()(This* owner, size_t index) const {
111  return _ItemProxy(owner, index);
112  }
113  };
114  class _ConstGetHelper {
115  public:
116  typedef value_type result_type;
117 
118  result_type operator()(const This* owner, size_t index) const {
119  return owner->_Get(index);
120  }
121  };
122  friend class _GetHelper;
123  friend class _ConstGetHelper;
124 
125  template <class Owner, class GetItem>
126  class _Iterator :
127  public boost::iterator_facade<
128  _Iterator<Owner, GetItem>,
129  typename boost::remove_cv<
130  typename boost::remove_reference<
131  typename GetItem::result_type
132  >::type
133  >::type,
134  std::random_access_iterator_tag,
135  typename GetItem::result_type> {
136  public:
137  typedef _Iterator<Owner, GetItem> This;
138  typedef
139  boost::iterator_facade<
140  _Iterator<Owner, GetItem>,
141  typename boost::remove_cv<
142  typename boost::remove_reference<
143  typename GetItem::result_type
144  >::type
145  >::type,
146  std::random_access_iterator_tag,
147  typename GetItem::result_type> Parent;
148  typedef typename Parent::reference reference;
149  typedef typename Parent::difference_type difference_type;
150 
151  _Iterator() : _owner(NULL), _index(0)
152  {
153  // Do nothing
154  }
155 
156  _Iterator(Owner owner, size_t index) : _owner(owner), _index(index)
157  {
158  // Do nothing
159  }
160 
161  private:
162  friend class boost::iterator_core_access;
163 
164  reference dereference() const {
165  return _getItem(_owner, _index);
166  }
167 
168  bool equal(const This& other) const {
169  if (_owner != other._owner) {
170  TF_CODING_ERROR("Comparing SdfListProxy iterators from "
171  "different proxies!");
172  return false;
173  }
174  return _index == other._index;
175  }
176 
177  void increment() {
178  ++_index;
179  }
180 
181  void decrement() {
182  --_index;
183  }
184 
185  void advance(difference_type n) {
186  _index += n;
187  }
188 
189  difference_type distance_to(const This& other) const {
190  return other._index - _index;
191  }
192 
193  private:
194  GetItem _getItem;
195  Owner _owner;
196  size_t _index;
197  };
198 
199 public:
200  typedef _ItemProxy reference;
201  typedef _Iterator<This*, _GetHelper> iterator;
202  typedef _Iterator<const This*, _ConstGetHelper> const_iterator;
203  typedef boost::reverse_iterator<iterator> reverse_iterator;
204  typedef boost::reverse_iterator<const_iterator> const_reverse_iterator;
205 
209  SdfListProxy(SdfListOpType op) :
210  _op(op)
211  {
212  }
213 
216  SdfListProxy(const std::shared_ptr<Sdf_ListEditor<TypePolicy> >& editor,
217  SdfListOpType op) :
218  _listEditor(editor),
219  _op(op)
220  {
221  }
222 
224  iterator begin() {
225  return iterator(_GetThis(), 0);
226  }
228  iterator end() {
229  return iterator(_GetThis(), _GetSize());
230  }
231 
233  reverse_iterator rbegin() {
234  return reverse_iterator(end());
235  }
237  reverse_iterator rend() {
238  return reverse_iterator(begin());
239  }
240 
242  const_iterator begin() const {
243  return const_iterator(_GetThis(), 0);
244  }
246  const_iterator end() const {
247  return const_iterator(_GetThis(), _GetSize());
248  }
249 
251  const_reverse_iterator rbegin() const {
252  return const_reverse_iterator(end());
253  }
256  const_reverse_iterator rend() const {
257  return const_reverse_iterator(begin());
258  }
259 
261  size_t size() const {
262  return _Validate() ? _GetSize() : 0;
263  }
264 
266  bool empty() const {
267  return size() == 0;
268  }
269 
271  reference operator[](size_t n) {
272  return reference(_GetThis(), n);
273  }
274 
276  value_type operator[](size_t n) const {
277  return _Get(n);
278  }
279 
281  reference front() {
282  return reference(_GetThis(), 0);
283  }
284 
286  reference back() {
287  return reference(_GetThis(), _GetSize() - 1);
288  }
289 
291  value_type front() const {
292  return _Get(0);
293  }
294 
296  value_type back() const {
297  return _Get(_GetSize() - 1);
298  }
299 
301  void push_back(const value_type& elem) {
302  _Edit(_GetSize(), 0, value_vector_type(1, elem));
303  }
304 
306  void pop_back() {
307  _Edit(_GetSize() - 1, 1, value_vector_type());
308  }
309 
311  iterator insert(iterator pos, const value_type& x) {
312  _Edit(pos - iterator(this, 0), 0, value_vector_type(1, x));
313  return pos;
314  }
315 
318  template <class InputIterator>
319  void insert(iterator pos, InputIterator f, InputIterator l) {
320  _Edit(pos - iterator(this, 0), 0, value_vector_type(f, l));
321  }
322 
324  void erase(iterator pos) {
325  _Edit(pos - iterator(this, 0), 1, value_vector_type());
326  }
327 
329  void erase(iterator f, iterator l) {
330  _Edit(f - iterator(this, 0), l - f, value_vector_type());
331  }
332 
334  void clear() {
335  _Edit(0, _GetSize(), value_vector_type());
336  }
337 
342  void resize(size_t n, const value_type& t = value_type()) {
343  size_t s = _GetSize();
344  if (n > s) {
345  _Edit(s, 0, value_vector_type(n - s, t));
346  }
347  else if (n < s) {
348  _Edit(n, s - n, value_vector_type());
349  }
350  }
351 
353  operator value_vector_type() const {
354  return _listEditor ? _listEditor->GetVector(_op) : value_vector_type();
355  }
356 
359  template <class T2>
360  This& operator=(const SdfListProxy<T2>& other) {
361  _Edit(0, _GetSize(), static_cast<value_vector_type>(other));
362  return *this;
363  }
364 
366  This& operator=(const value_vector_type& other) {
367  _Edit(0, _GetSize(), other);
368  return *this;
369  }
370 
372  template <class Y>
373  This& operator=(const std::vector<Y>& v) {
374  _Edit(0, _GetSize(), value_vector_type(v.begin(), v.end()));
375  return *this;
376  }
377 
379  template <class T2>
380  bool operator==(const SdfListProxy<T2>& y) const {
381  return value_vector_type(*this) == value_vector_type(y);
382  }
383 
385  template <class T2>
386  bool operator!=(const SdfListProxy<T2>& y) const {
387  return !(*this == y);
388  }
389 
391  template <class T2>
392  bool operator<(const SdfListProxy<T2>& y) const {
393  return value_vector_type(*this) < value_vector_type(y);
394  }
395 
397  template <class T2>
398  bool operator<=(const SdfListProxy<T2>& y) const {
399  return value_vector_type(*this) <= value_vector_type(y);
400  }
401 
403  template <class T2>
404  bool operator>(const SdfListProxy<T2>& y) const {
405  return !(*this <= y);
406  }
407 
409  template <class T2>
410  bool operator>=(const SdfListProxy<T2>& y) const {
411  return !(*this < y);
412  }
413 
415  bool operator==(const value_vector_type& y) const {
416  return value_vector_type(*this) == y;
417  }
418 
420  bool operator<(const value_vector_type& y) const {
421  return value_vector_type(*this) < y;
422  }
423 
425  bool operator>(const value_vector_type& y) const {
426  return value_vector_type(*this) > y;
427  }
428 
431  explicit operator bool() const
432  {
433  return _listEditor && _listEditor->IsValid() && _IsRelevant();
434  }
435 
436  // Extensions
437 
439  SdfLayerHandle GetLayer() const
440  {
441  return _listEditor ? _listEditor->GetLayer() : SdfLayerHandle();
442  }
443 
445  SdfPath GetPath() const
446  {
447  return _listEditor ? _listEditor->GetPath() : SdfPath();
448  }
449 
451  bool IsExpired() const
452  {
453  return _listEditor && _listEditor->IsExpired();
454  }
455 
456  size_t Count(const value_type& value) const
457  {
458  return (_Validate() ? _listEditor->Count(_op, value) : 0);
459  }
460 
461  size_t Find(const value_type& value) const
462  {
463  return (_Validate() ? _listEditor->Find(_op, value) : size_t(-1));
464  }
465 
466  void Insert(int index, const value_type& value)
467  {
468  if (index == -1) {
469  index = static_cast<int>(_GetSize());
470  }
471  _Edit(index, 0, value_vector_type(1, value));
472  }
473 
474  void Remove(const value_type& value)
475  {
476  size_t index = Find(value);
477  if (index != size_t(-1)) {
478  Erase(index);
479  }
480  else {
481  // Allow policy to raise an error even though we're not
482  // doing anything.
483  _Edit(_GetSize(), 0, value_vector_type());
484  }
485  }
486 
487  void Replace(const value_type& oldValue, const value_type& newValue)
488  {
489  size_t index = Find(oldValue);
490  if (index != size_t(-1)) {
491  _Edit(index, 1, value_vector_type(1, newValue));
492  }
493  else {
494  // Allow policy to raise an error even though we're not
495  // doing anything.
496  _Edit(_GetSize(), 0, value_vector_type());
497  }
498  }
499 
500  void Erase(size_t index)
501  {
502  _Edit(index, 1, value_vector_type());
503  }
504 
506  void ApplyList(const SdfListProxy &list)
507  {
508  if (_Validate() && list._Validate()) {
509  _listEditor->ApplyList(_op, *list._listEditor);
510  }
511  }
512 
514  void ApplyEditsToList(value_vector_type* vec)
515  {
516  if (_Validate()) {
517  _listEditor->ApplyEditsToList(vec);
518  }
519  }
520 
521 private:
522  bool _Validate()
523  {
524  if (!_listEditor) {
525  return false;
526  }
527 
528  if (IsExpired()) {
529  TF_CODING_ERROR("Accessing expired list editor");
530  return false;
531  }
532  return true;
533  }
534 
535  bool _Validate() const
536  {
537  if (!_listEditor) {
538  return false;
539  }
540 
541  if (IsExpired()) {
542  TF_CODING_ERROR("Accessing expired list editor");
543  return false;
544  }
545  return true;
546  }
547 
548  This* _GetThis()
549  {
550  return _Validate() ? this : NULL;
551  }
552 
553  const This* _GetThis() const
554  {
555  return _Validate() ? this : NULL;
556  }
557 
558  bool _IsRelevant() const
559  {
560  if (_listEditor->IsExplicit()) {
561  return _op == SdfListOpTypeExplicit;
562  }
563  else if (_listEditor->IsOrderedOnly()) {
564  return _op == SdfListOpTypeOrdered;
565  }
566  else {
567  return _op != SdfListOpTypeExplicit;
568  }
569  }
570 
571  size_t _GetSize() const
572  {
573  return _listEditor ? _listEditor->GetSize(_op) : 0;
574  }
575 
576  value_type _Get(size_t n) const
577  {
578  return _Validate() ? _listEditor->Get(_op, n) : value_type();
579  }
580 
581  void _Edit(size_t index, size_t n, const value_vector_type& elems)
582  {
583  if (_Validate()) {
584  // Allow policy to raise an error even if we're not
585  // doing anything.
586  if (n == 0 && elems.empty()) {
587  SdfAllowed canEdit = _listEditor->PermissionToEdit(_op);
588  if (!canEdit) {
589  TF_CODING_ERROR("Editing list: %s",
590  canEdit.GetWhyNot().c_str());
591  }
592  return;
593  }
594 
595  bool valid =
596  _listEditor->ReplaceEdits(_op, index, n, elems);
597  if (!valid) {
598  TF_CODING_ERROR("Inserting invalid value into list editor");
599  }
600  }
601  }
602 
603 private:
604  std::shared_ptr<Sdf_ListEditor<TypePolicy> > _listEditor;
605  SdfListOpType _op;
606 
607  template <class> friend class SdfPyWrapListProxy;
608 };
609 
610 // Allow TfIteration over list proxies.
611 template <typename T>
612 struct Tf_ShouldIterateOverCopy<SdfListProxy<T> > : boost::true_type
613 {
614 };
615 
616 PXR_NAMESPACE_CLOSE_SCOPE
617 
618 #endif // PXR_USD_SDF_LIST_PROXY_H
reference operator[](size_t n)
Return a reference to the item at index n.
Definition: listProxy.h:271
const_reverse_iterator rend() const
Return a const reverse iterator past the start item of the sequence.
Definition: listProxy.h:256
void clear()
Clear the contents of the sequence.
Definition: listProxy.h:334
SdfPath GetPath() const
Returns the path to this list editor's value.
Definition: listProxy.h:445
This & operator=(const value_vector_type &other)
Replace all elements in this sequence with the given vector.
Definition: listProxy.h:366
void resize(size_t n, const value_type &t=value_type())
Resize the contents of the sequence.
Definition: listProxy.h:342
bool empty() const
Return true if size() == 0.
Definition: listProxy.h:266
reference back()
Return a reference to the item at the back of the sequence.
Definition: listProxy.h:286
This & operator=(const SdfListProxy< T2 > &other)
Replace all elements in this sequence with the elements in the other sequence.
Definition: listProxy.h:360
void push_back(const value_type &elem)
Append elem to this sequence.
Definition: listProxy.h:301
value_type back() const
Return a copy of the item at the back of the sequence.
Definition: listProxy.h:296
A simple iterator adapter for STL containers.
reverse_iterator rbegin()
Return a reverse iterator to the last item of the sequence.
Definition: listProxy.h:233
bool operator==(const SdfListProxy< T2 > &y) const
Equality comparison.
Definition: listProxy.h:380
This & operator=(const std::vector< Y > &v)
Replace all elements in this sequence with the given vector.
Definition: listProxy.h:373
reference front()
Return a reference to the item at the front of the sequence.
Definition: listProxy.h:281
#define TF_CODING_ERROR(fmt, args)
Issue an internal programming error, but continue execution.
Definition: diagnostic.h:85
bool operator<(const value_vector_type &y) const
Less-than comparison.
Definition: listProxy.h:420
value_type operator[](size_t n) const
Return a copy of the item at index n.
Definition: listProxy.h:276
bool IsExpired() const
Returns true if the list editor is expired.
Definition: listProxy.h:451
Low-level utilities for informing users of various internal and external diagnostic conditions.
SDF_API const std::string & GetWhyNot() const
Returns the reason why the operation is not allowed.
bool operator>=(const SdfListProxy< T2 > &y) const
Greater-than-or-equal comparison.
Definition: listProxy.h:410
SdfLayerHandle GetLayer() const
Returns the layer that this list editor belongs to.
Definition: listProxy.h:439
value_type front() const
Return a copy of the item at the front of the sequence.
Definition: listProxy.h:291
bool operator>(const value_vector_type &y) const
Greater-than comparison.
Definition: listProxy.h:425
void erase(iterator pos)
Erase the element at pos.
Definition: listProxy.h:324
void pop_back()
Remove the last element from this sequence.
Definition: listProxy.h:306
iterator begin()
Return an iterator to the start of the sequence.
Definition: listProxy.h:224
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:216
Indicates if an operation is allowed and, if not, why not.
Definition: allowed.h:47
Represents a single list of list editing operations.
Definition: listProxy.h:59
void ApplyList(const SdfListProxy &list)
Applies the edits in the given list to this one.
Definition: listProxy.h:506
bool operator<(const SdfListProxy< T2 > &y) const
Less-than comparison.
Definition: listProxy.h:392
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:319
iterator end()
Return an iterator to the end of the sequence.
Definition: listProxy.h:228
A path value used to locate objects in layers or scenegraphs.
Definition: path.h:290
size_t size() const
Return the size of the sequence.
Definition: listProxy.h:261
bool operator>(const SdfListProxy< T2 > &y) const
Greater-than comparison.
Definition: listProxy.h:404
iterator insert(iterator pos, const value_type &x)
Insert x into this sequence at position pos.
Definition: listProxy.h:311
bool operator<=(const SdfListProxy< T2 > &y) const
Less-than-or-equal comparison.
Definition: listProxy.h:398
const_iterator begin() const
Return a const iterator to the start of the sequence.
Definition: listProxy.h:242
const_iterator end() const
Return a const iterator to the end of the sequence.
Definition: listProxy.h:246
bool operator!=(const SdfListProxy< T2 > &y) const
Inequality comparison.
Definition: listProxy.h:386
void erase(iterator f, iterator l)
Erase all the elements in the range [f, l).
Definition: listProxy.h:329
void ApplyEditsToList(value_vector_type *vec)
Apply the edits in this list to the given vec.
Definition: listProxy.h:514
bool operator==(const value_vector_type &y) const
Equality comparison.
Definition: listProxy.h:415
reverse_iterator rend()
Return a reverse iterator past the start item of the sequence.
Definition: listProxy.h:237
const_reverse_iterator rbegin() const
Return a const reverse iterator to the last item of the sequence.
Definition: listProxy.h:251
SdfListProxy(SdfListOpType op)
Creates a default list proxy object for list operation vector specified op.
Definition: listProxy.h:209