All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
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 SDF_LISTPROXY_H
25 #define SDF_LISTPROXY_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 PXR_NAMESPACE_OPEN_SCOPE
47 
56 template <class _TypePolicy>
57 class SdfListProxy :
58  boost::totally_ordered<SdfListProxy<_TypePolicy>,
59  std::vector<typename _TypePolicy::value_type> > {
60 public:
61  typedef _TypePolicy TypePolicy;
63  typedef typename TypePolicy::value_type value_type;
64  typedef std::vector<value_type> value_vector_type;
65 
66 private:
67  // Proxies an item in a list editor list.
68  class _ItemProxy : boost::totally_ordered<_ItemProxy> {
69  public:
70  explicit _ItemProxy(This* owner, size_t index) :
71  _owner(owner), _index(index)
72  {
73  // Do nothing
74  }
75 
76  _ItemProxy& operator=(const _ItemProxy& x) {
77  _owner->_Edit(_index, 1, value_vector_type(1, x));
78  return *this;
79  }
80 
81  _ItemProxy& operator=(const value_type& x) {
82  _owner->_Edit(_index, 1, value_vector_type(1, x));
83  return *this;
84  }
85 
86  operator value_type() const {
87  return _owner->_Get(_index);
88  }
89 
90  bool operator==(const value_type& x) const {
91  return _owner->_Get(_index) == x;
92  }
93 
94  bool operator<(const value_type& x) const {
95  return _owner->_Get(_index) < x;
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  public boost::iterator_facade<
126  _Iterator<Owner, GetItem>,
127  typename boost::remove_cv<
128  typename boost::remove_reference<
129  typename GetItem::result_type
130  >::type
131  >::type,
132  std::random_access_iterator_tag,
133  typename GetItem::result_type> {
134  public:
135  typedef _Iterator<Owner, GetItem> This;
136  typedef
137  boost::iterator_facade<
138  _Iterator<Owner, GetItem>,
139  typename boost::remove_cv<
140  typename boost::remove_reference<
141  typename GetItem::result_type
142  >::type
143  >::type,
144  std::random_access_iterator_tag,
145  typename GetItem::result_type> Parent;
146  typedef typename Parent::reference reference;
147  typedef typename Parent::difference_type difference_type;
148 
149  _Iterator() : _owner(NULL), _index(0)
150  {
151  // Do nothing
152  }
153 
154  _Iterator(Owner owner, size_t index) : _owner(owner), _index(index)
155  {
156  // Do nothing
157  }
158 
159  private:
160  friend class boost::iterator_core_access;
161 
162  reference dereference() const {
163  return _getItem(_owner, _index);
164  }
165 
166  bool equal(const This& other) const {
167  if (_owner != other._owner) {
168  TF_CODING_ERROR("Comparing SdfListProxy iterators from "
169  "different proxies!");
170  return false;
171  }
172  return _index == other._index;
173  }
174 
175  void increment() {
176  ++_index;
177  }
178 
179  void decrement() {
180  --_index;
181  }
182 
183  void advance(difference_type n) {
184  _index += n;
185  }
186 
187  difference_type distance_to(const This& other) const {
188  return other._index - _index;
189  }
190 
191  private:
192  GetItem _getItem;
193  Owner _owner;
194  size_t _index;
195  };
196 
197 public:
198  typedef _ItemProxy reference;
199  typedef _Iterator<This*, _GetHelper> iterator;
200  typedef _Iterator<const This*, _ConstGetHelper> const_iterator;
201  typedef boost::reverse_iterator<iterator> reverse_iterator;
202  typedef boost::reverse_iterator<const_iterator> const_reverse_iterator;
203 
207  SdfListProxy(SdfListOpType op) :
208  _op(op)
209  {
210  }
211 
214  SdfListProxy(const boost::shared_ptr<Sdf_ListEditor<TypePolicy> >& editor,
215  SdfListOpType op) :
216  _listEditor(editor),
217  _op(op)
218  {
219  }
220 
222  iterator begin() {
223  return iterator(_GetThis(), 0);
224  }
226  iterator end() {
227  return iterator(_GetThis(), _GetSize());
228  }
229 
231  reverse_iterator rbegin() {
232  return reverse_iterator(end());
233  }
235  reverse_iterator rend() {
236  return reverse_iterator(begin());
237  }
238 
240  const_iterator begin() const {
241  return const_iterator(_GetThis(), 0);
242  }
244  const_iterator end() const {
245  return const_iterator(_GetThis(), _GetSize());
246  }
247 
249  const_reverse_iterator rbegin() const {
250  return const_reverse_iterator(end());
251  }
254  const_reverse_iterator rend() const {
255  return const_reverse_iterator(begin());
256  }
257 
259  size_t size() const {
260  return _Validate() ? _GetSize() : 0;
261  }
262 
264  bool empty() const {
265  return size() == 0;
266  }
267 
269  reference operator[](size_t n) {
270  return reference(_GetThis(), n);
271  }
272 
274  value_type operator[](size_t n) const {
275  return _Get(n);
276  }
277 
279  reference front() {
280  return reference(_GetThis(), 0);
281  }
282 
284  reference back() {
285  return reference(_GetThis(), _GetSize() - 1);
286  }
287 
289  value_type front() const {
290  return _Get(0);
291  }
292 
294  value_type back() const {
295  return _Get(_GetSize() - 1);
296  }
297 
299  void push_back(const value_type& elem) {
300  _Edit(_GetSize(), 0, value_vector_type(1, elem));
301  }
302 
304  void pop_back() {
305  _Edit(_GetSize() - 1, 1, value_vector_type());
306  }
307 
309  iterator insert(iterator pos, const value_type& x) {
310  _Edit(pos - iterator(this, 0), 0, value_vector_type(1, x));
311  return pos;
312  }
313 
316  template <class InputIterator>
317  void insert(iterator pos, InputIterator f, InputIterator l) {
318  _Edit(pos - iterator(this, 0), 0, value_vector_type(f, l));
319  }
320 
322  void erase(iterator pos) {
323  _Edit(pos - iterator(this, 0), 1, value_vector_type());
324  }
325 
327  void erase(iterator f, iterator l) {
328  _Edit(f - iterator(this, 0), l - f, value_vector_type());
329  }
330 
332  void clear() {
333  _Edit(0, _GetSize(), value_vector_type());
334  }
335 
340  void resize(size_t n, const value_type& t = value_type()) {
341  size_t s = _GetSize();
342  if (n > s) {
343  _Edit(s, 0, value_vector_type(n - s, t));
344  }
345  else if (n < s) {
346  _Edit(n, s - n, value_vector_type());
347  }
348  }
349 
351  operator value_vector_type() const {
352  return _listEditor ? _listEditor->GetVector(_op) : value_vector_type();
353  }
354 
357  template <class T2>
358  This& operator=(const SdfListProxy<T2>& other) {
359  _Edit(0, _GetSize(), static_cast<value_vector_type>(other));
360  return *this;
361  }
362 
364  This& operator=(const value_vector_type& other) {
365  _Edit(0, _GetSize(), other);
366  return *this;
367  }
368 
370  template <class Y>
371  This& operator=(const std::vector<Y>& v) {
372  _Edit(0, _GetSize(), value_vector_type(v.begin(), v.end()));
373  return *this;
374  }
375 
377  template <class T2>
378  bool operator==(const SdfListProxy<T2>& y) const {
379  return value_vector_type(*this) == value_vector_type(y);
380  }
381 
383  template <class T2>
384  bool operator!=(const SdfListProxy<T2>& y) const {
385  return !(*this == y);
386  }
387 
389  template <class T2>
390  bool operator<(const SdfListProxy<T2>& y) const {
391  return value_vector_type(*this) < value_vector_type(y);
392  }
393 
395  template <class T2>
396  bool operator<=(const SdfListProxy<T2>& y) const {
397  return value_vector_type(*this) <= value_vector_type(y);
398  }
399 
401  template <class T2>
402  bool operator>(const SdfListProxy<T2>& y) const {
403  return !(*this <= y);
404  }
405 
407  template <class T2>
408  bool operator>=(const SdfListProxy<T2>& y) const {
409  return !(*this < y);
410  }
411 
413  bool operator==(const value_vector_type& y) const {
414  return value_vector_type(*this) == y;
415  }
416 
418  bool operator<(const value_vector_type& y) const {
419  return value_vector_type(*this) < y;
420  }
421 
423  bool operator>(const value_vector_type& y) const {
424  return value_vector_type(*this) > y;
425  }
426 
429  explicit operator bool() const
430  {
431  return _listEditor && _listEditor->IsValid() && _IsRelevant();
432  }
433 
434  // Extensions
435 
437  SdfLayerHandle GetLayer() const
438  {
439  return _listEditor ? _listEditor->GetLayer() : SdfLayerHandle();
440  }
441 
443  SdfPath GetPath() const
444  {
445  return _listEditor ? _listEditor->GetPath() : SdfPath();
446  }
447 
449  bool IsExpired() const
450  {
451  return _listEditor && _listEditor->IsExpired();
452  }
453 
454  size_t Count(const value_type& value) const
455  {
456  return (_Validate() ? _listEditor->Count(_op, value) : 0);
457  }
458 
459  size_t Find(const value_type& value) const
460  {
461  return (_Validate() ? _listEditor->Find(_op, value) : size_t(-1));
462  }
463 
464  void Insert(int index, const value_type& value)
465  {
466  if (index == -1) {
467  index = static_cast<int>(_GetSize());
468  }
469  _Edit(index, 0, value_vector_type(1, value));
470  }
471 
472  void Remove(const value_type& value)
473  {
474  size_t index = Find(value);
475  if (index != size_t(-1)) {
476  Erase(index);
477  }
478  else {
479  // Allow policy to raise an error even though we're not
480  // doing anything.
481  _Edit(_GetSize(), 0, value_vector_type());
482  }
483  }
484 
485  void Replace(const value_type& oldValue, const value_type& newValue)
486  {
487  size_t index = Find(oldValue);
488  if (index != size_t(-1)) {
489  _Edit(index, 1, value_vector_type(1, newValue));
490  }
491  else {
492  // Allow policy to raise an error even though we're not
493  // doing anything.
494  _Edit(_GetSize(), 0, value_vector_type());
495  }
496  }
497 
498  void Erase(size_t index)
499  {
500  _Edit(index, 1, value_vector_type());
501  }
502 
504  void ApplyList(const SdfListProxy &list)
505  {
506  if (_Validate() && list._Validate()) {
507  _listEditor->ApplyList(_op, *list._listEditor);
508  }
509  }
510 
512  void ApplyEditsToList(value_vector_type* vec)
513  {
514  if (_Validate()) {
515  _listEditor->ApplyEditsToList(vec);
516  }
517  }
518 
519 private:
520  bool _Validate()
521  {
522  if (!_listEditor) {
523  return false;
524  }
525 
526  if (IsExpired()) {
527  TF_CODING_ERROR("Accessing expired list editor");
528  return false;
529  }
530  return true;
531  }
532 
533  bool _Validate() const
534  {
535  if (!_listEditor) {
536  return false;
537  }
538 
539  if (IsExpired()) {
540  TF_CODING_ERROR("Accessing expired list editor");
541  return false;
542  }
543  return true;
544  }
545 
546  This* _GetThis()
547  {
548  return _Validate() ? this : NULL;
549  }
550 
551  const This* _GetThis() const
552  {
553  return _Validate() ? this : NULL;
554  }
555 
556  bool _IsRelevant() const
557  {
558  if (_listEditor->IsExplicit()) {
559  return _op == SdfListOpTypeExplicit;
560  }
561  else if (_listEditor->IsOrderedOnly()) {
562  return _op == SdfListOpTypeOrdered;
563  }
564  else {
565  return _op != SdfListOpTypeExplicit;
566  }
567  }
568 
569  size_t _GetSize() const
570  {
571  return _listEditor ? _listEditor->GetSize(_op) : 0;
572  }
573 
574  value_type _Get(size_t n) const
575  {
576  return _Validate() ? _listEditor->Get(_op, n) : value_type();
577  }
578 
579  void _Edit(size_t index, size_t n, const value_vector_type& elems)
580  {
581  if (_Validate()) {
582  // Allow policy to raise an error even if we're not
583  // doing anything.
584  if (n == 0 && elems.empty()) {
585  SdfAllowed canEdit = _listEditor->PermissionToEdit(_op);
586  if (!canEdit) {
587  TF_CODING_ERROR("Editing list: %s",
588  canEdit.GetWhyNot().c_str());
589  }
590  return;
591  }
592 
593  bool valid =
594  _listEditor->ReplaceEdits(_op, index, n, elems);
595  if (!valid) {
596  TF_CODING_ERROR("Inserting invalid value into list editor");
597  }
598  }
599  }
600 
601 private:
602  boost::shared_ptr<Sdf_ListEditor<TypePolicy> > _listEditor;
603  SdfListOpType _op;
604 
605  template <class> friend class SdfPyWrapListProxy;
606 };
607 
608 // Allow TfIteration over list proxies.
609 template <typename T>
610 struct Tf_ShouldIterateOverCopy<SdfListProxy<T> > : boost::true_type
611 {
612 };
613 
614 PXR_NAMESPACE_CLOSE_SCOPE
615 
616 #endif // SDF_LISTPROXY_H
reference operator[](size_t n)
Return a reference to the item at index n.
Definition: listProxy.h:269
void clear()
Clear the contents of the sequence.
Definition: listProxy.h:332
This & operator=(const value_vector_type &other)
Replace all elements in this sequence with the given vector.
Definition: listProxy.h:364
value_type operator[](size_t n) const
Return a copy of the item at index n.
Definition: listProxy.h:274
void resize(size_t n, const value_type &t=value_type())
Resize the contents of the sequence.
Definition: listProxy.h:340
reference back()
Return a reference to the item at the back of the sequence.
Definition: listProxy.h:284
This & operator=(const SdfListProxy< T2 > &other)
Replace all elements in this sequence with the elements in the other sequence.
Definition: listProxy.h:358
void push_back(const value_type &elem)
Append elem to this sequence.
Definition: listProxy.h:299
bool operator<(const SdfListProxy< T2 > &y) const
Less-than comparison.
Definition: listProxy.h:390
reverse_iterator rbegin()
Return a reverse iterator to the last item of the sequence.
Definition: listProxy.h:231
bool operator<(const value_vector_type &y) const
Less-than comparison.
Definition: listProxy.h:418
This & operator=(const std::vector< Y > &v)
Replace all elements in this sequence with the given vector.
Definition: listProxy.h:371
reference front()
Return a reference to the item at the front of the sequence.
Definition: listProxy.h:279
bool operator>(const SdfListProxy< T2 > &y) const
Greater-than comparison.
Definition: listProxy.h:402
#define TF_CODING_ERROR(fmt, args)
Issue an internal programming error, but continue execution.
Definition: diagnostic.h:87
const_reverse_iterator rend() const
Return a const reverse iterator past the start item of the sequence.
Definition: listProxy.h:254
void erase(iterator pos)
Erase the element at pos.
Definition: listProxy.h:322
void pop_back()
Remove the last element from this sequence.
Definition: listProxy.h:304
SDF_API const std::string & GetWhyNot() const
Returns the reason why the operation is not allowed.
iterator begin()
Return an iterator to the start of the sequence.
Definition: listProxy.h:222
value_type front() const
Return a copy of the item at the front of the sequence.
Definition: listProxy.h:289
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:57
void ApplyList(const SdfListProxy &list)
Applies the edits in the given list to this one.
Definition: listProxy.h:504
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:317
const_iterator begin() const
Return a const iterator to the start of the sequence.
Definition: listProxy.h:240
iterator end()
Return an iterator to the end of the sequence.
Definition: listProxy.h:226
bool operator==(const SdfListProxy< T2 > &y) const
Equality comparison.
Definition: listProxy.h:378
A path value used to locate objects in layers or scenegraphs.
Definition: path.h:287
bool operator!=(const SdfListProxy< T2 > &y) const
Inequality comparison.
Definition: listProxy.h:384
const_iterator end() const
Return a const iterator to the end of the sequence.
Definition: listProxy.h:244
iterator insert(iterator pos, const value_type &x)
Insert x into this sequence at position pos.
Definition: listProxy.h:309
value_type back() const
Return a copy of the item at the back of the sequence.
Definition: listProxy.h:294
bool operator==(const value_vector_type &y) const
Equality comparison.
Definition: listProxy.h:413
bool empty() const
Return true if size() == 0.
Definition: listProxy.h:264
bool operator>=(const SdfListProxy< T2 > &y) const
Greater-than-or-equal comparison.
Definition: listProxy.h:408
SdfLayerHandle GetLayer() const
Returns the layer that this list editor belongs to.
Definition: listProxy.h:437
void erase(iterator f, iterator l)
Erase all the elements in the range [f, l).
Definition: listProxy.h:327
void ApplyEditsToList(value_vector_type *vec)
Apply the edits in this list to the given vec.
Definition: listProxy.h:512
reverse_iterator rend()
Return a reverse iterator past the start item of the sequence.
Definition: listProxy.h:235
bool operator>(const value_vector_type &y) const
Greater-than comparison.
Definition: listProxy.h:423
bool IsExpired() const
Returns true if the list editor is expired.
Definition: listProxy.h:449
SdfPath GetPath() const
Returns the path to this list editor&#39;s value.
Definition: listProxy.h:443
size_t size() const
Return the size of the sequence.
Definition: listProxy.h:259
SdfListProxy(const boost::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:214
SdfListProxy(SdfListOpType op)
Creates a default list proxy object for list operation vector specified op.
Definition: listProxy.h:207
const_reverse_iterator rbegin() const
Return a const reverse iterator to the last item of the sequence.
Definition: listProxy.h:249