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
childrenProxy.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_CHILDREN_PROXY_H
8#define PXR_USD_SDF_CHILDREN_PROXY_H
9
11
12#include "pxr/pxr.h"
13#include "pxr/usd/sdf/api.h"
14#include "pxr/usd/sdf/changeBlock.h"
15#include "pxr/base/vt/value.h"
18
19#include <iterator>
20#include <map>
21#include <utility>
22
23PXR_NAMESPACE_OPEN_SCOPE
24
25template <class _View>
26class SdfChildrenProxy {
27public:
28 typedef _View View;
29 typedef typename View::Adapter Adapter;
30 typedef typename View::ChildPolicy ChildPolicy;
31 typedef typename View::key_type key_type;
32 typedef typename View::value_type mapped_type;
33 typedef std::vector<mapped_type> mapped_vector_type;
34 typedef std::pair<const key_type, mapped_type> value_type;
35 typedef std::map<key_type, mapped_type> map_type;
36 typedef typename View::size_type size_type;
37 typedef SdfChildrenProxy<View> This;
38
39private:
40 typedef typename View::const_iterator _inner_iterator;
41
42 class _ValueProxy {
43 public:
44 _ValueProxy() : _owner(NULL) { }
45 _ValueProxy(This* owner, _inner_iterator i) : _owner(owner), _pos(i)
46 {
47 // Do nothing
48 }
49
50 operator mapped_type() const
51 {
52 return *_pos;
53 }
54
55 template <class U>
56 _ValueProxy& operator=(const U& x)
57 {
58 _owner->_Set(*_pos, x);
59 return *this;
60 }
61
62 bool operator==(const mapped_type& other) const
63 {
64 return *_pos == other;
65 }
66
67 private:
68 This* _owner;
69 _inner_iterator _pos;
70 };
71
72 class _PairProxy {
73 public:
74 explicit _PairProxy(This* owner, _inner_iterator i) :
75 first(owner->_view.key(i)), second(owner, i) { }
76
77 const key_type first;
78 _ValueProxy second;
79
80 operator value_type() const
81 {
82 return value_type(first, second);
83 }
84 };
85 friend class _PairProxy;
86
87 class _Traits {
88 public:
89 static value_type Dereference(const This* owner, _inner_iterator i)
90 {
91 return value_type(owner->_view.key(i), *i);
92 }
93
94 static _PairProxy Dereference(This* owner, _inner_iterator i)
95 {
96 return _PairProxy(owner, i);
97 }
98 };
99
100 template <class _Owner, class _Iter, class _Value>
101 class _Iterator {
102 class _PtrProxy {
103 public:
104 _Value* operator->() { return &_value; }
105 private:
106 friend class _Iterator;
107 explicit _PtrProxy(const _Value& value) : _value(value) {}
108 _Value _value;
109 };
110 public:
111 static_assert(!std::is_reference<_Value>::value &&
112 !std::is_pointer<_Value>::value,
113 "_Value cannot be a pointer or reference type.");
114 using iterator_category = std::bidirectional_iterator_tag;
115 using value_type = _Value;
116 using reference = _Value;
117 using pointer = _PtrProxy;
118 using difference_type = std::ptrdiff_t;
119
120 _Iterator() = default;
121 _Iterator(_Owner owner, _inner_iterator i) : _owner(owner), _pos(i) { }
122 template <class O2, class I2, class V2>
123 _Iterator(const _Iterator<O2, I2, V2>& other) :
124 _owner(other._owner), _pos(other._pos) { }
125
126 reference operator*() const { return dereference(); }
127 pointer operator->() const { return pointer(dereference()); }
128
129 _Iterator& operator++() {
130 increment();
131 return *this;
132 }
133
134 _Iterator& operator--() {
135 decrement();
136 return *this;
137 }
138
139 _Iterator operator++(int) {
140 _Iterator result(*this);
141 increment();
142 return result;
143 }
144
145 _Iterator operator--(int) {
146 _Iterator result(*this);
147 decrement();
148 return result;
149 }
150
151 template <class O2, class I2, class V2>
152 bool operator==(const _Iterator<O2, I2, V2>& other) const {
153 return equal(other);
154 }
155
156 template <class O2, class I2, class V2>
157 bool operator!=(const _Iterator<O2, I2, V2>& other) const {
158 return !equal(other);
159 }
160
161 private:
162 _Value dereference() const
163 {
164 return _Traits::Dereference(_owner, _pos);
165 }
166
167 template <class O2, class I2, class V2>
168 bool equal(const _Iterator<O2, I2, V2>& other) const
169 {
170 return _pos == other._pos;
171 }
172
173 void increment() {
174 ++_pos;
175 }
176
177 void decrement() {
178 --_pos;
179 }
180
181 private:
182 _Owner _owner;
183 _inner_iterator _pos;
184
185 template <class O2, class I2, class V2>
186 friend class _Iterator;
187 };
188
189public:
190 typedef _ValueProxy reference;
191 typedef _Iterator<This*, _inner_iterator, _PairProxy> iterator;
192 typedef Tf_ProxyReferenceReverseIterator<iterator> reverse_iterator;
193 typedef _Iterator<const This*, _inner_iterator, value_type> const_iterator;
194 typedef Tf_ProxyReferenceReverseIterator<const_iterator> const_reverse_iterator;
195
196 static const int CanSet = 1;
197 static const int CanInsert = 2;
198 static const int CanErase = 4;
199
200 SdfChildrenProxy(const View& view, const std::string& type,
201 int permission = CanSet | CanInsert | CanErase) :
202 _view(view), _type(type), _permission(permission)
203 {
204 // Do nothing
205 }
206
207 template <class U>
208 SdfChildrenProxy(const SdfChildrenProxy<U>& other) :
209 _view(other._view), _type(other._type), _permission(other._permission)
210 {
211 // Do nothing
212 }
213
214 This& operator=(const This& other)
215 {
216 if (other._Validate()) {
217 _Copy(other._view.values());
218 }
219 return *this;
220 }
221
222 template <class U>
223 This& operator=(const SdfChildrenProxy<U>& other)
224 {
225 if (other._Validate()) {
226 _Copy(other._view.values());
227 }
228 return *this;
229 }
230
231 This& operator=(const mapped_vector_type& values)
232 {
233 _Copy(values);
234 return *this;
235 }
236
237 operator mapped_vector_type() const
238 {
239 return _Validate() ? _view.values() : mapped_vector_type();
240 }
241
242 map_type items() const
243 {
244 return _Validate() ? _view.template items_as<map_type>() :map_type();
245 }
246
247 iterator begin()
248 {
249 return iterator(_GetThis(), _view.begin());
250 }
251 iterator end()
252 {
253 return iterator(_GetThis(), _view.end());
254 }
255 const_iterator begin() const
256 {
257 return const_iterator(_GetThis(), _view.begin());
258 }
259 const_iterator end() const
260 {
261 return const_iterator(_GetThis(), _view.end());
262 }
263
264 reverse_iterator rbegin()
265 {
266 return reverse_iterator(end());
267 }
268 reverse_iterator rend()
269 {
270 return reverse_iterator(begin());
271 }
272 const_reverse_iterator rbegin() const
273 {
274 return reverse_iterator(end());
275 }
276 const_reverse_iterator rend() const
277 {
278 return reverse_iterator(begin());
279 }
280
281 size_type size() const
282 {
283 return _Validate() ? _view.size() : 0;
284 }
285
286 size_type max_size() const
287 {
288 return _view.max_size();
289 }
290
291 bool empty() const
292 {
293 return _Validate() ? _view.empty() : true;
294 }
295
296 std::pair<iterator, bool> insert(const mapped_type& value)
297 {
298 if (_Validate(CanInsert)) {
299 iterator i = find(_view.key(value));
300 if (i == end()) {
301 if (_PrimInsert(value, size())) {
302 return std::make_pair(find(_view.key(value)), true);
303 }
304 else {
305 return std::make_pair(end(), false);
306 }
307 }
308 else {
309 return std::make_pair(i, false);
310 }
311 }
312 else {
313 return std::make_pair(iterator(), false);
314 }
315 }
316
317 iterator insert(iterator pos, const mapped_type& value)
318 {
319 return insert(value).first;
320 }
321
322 template <class InputIterator>
323 void insert(InputIterator first, InputIterator last)
324 {
325 if (_Validate(CanInsert)) {
326 SdfChangeBlock block;
327 for (; first != last; ++first) {
328 _PrimInsert(*first, size());
329 }
330 }
331 }
332
333 void erase(iterator pos)
334 {
335 _Erase(pos->first);
336 }
337
338 size_type erase(const key_type& key)
339 {
340 return _Erase(key) ? 1 : 0;
341 }
342
343 void erase(iterator first, iterator last)
344 {
345 if (_Validate(CanErase)) {
346 SdfChangeBlock block;
347 while (first != last) {
348 const key_type& key = first->first;
349 ++first;
350 _PrimErase(key);
351 }
352 }
353 }
354
355 void clear()
356 {
357 _Copy(mapped_vector_type());
358 }
359
360 iterator find(const key_type& key)
361 {
362 return _Validate() ? iterator(this, _view.find(key)) : iterator();
363 }
364
365 const_iterator find(const key_type& key) const
366 {
367 return _Validate() ? const_iterator(this, _view.find(key)) :
368 const_iterator();
369 }
370
371 size_type count(const key_type& key) const
372 {
373 return _Validate() ? _view.count(key) : 0;
374 }
375
376 bool operator==(const This& other) const
377 {
378 return _view == other._view;
379 }
380
381 bool operator!=(const This& other) const
382 {
383 return !(*this == other);
384 }
385
388 explicit operator bool() const
389 {
390 return _view.IsValid();
391 }
392
393private:
394 const std::string& _GetType() const
395 {
396 return _type;
397 }
398
399 int _GetPermission() const
400 {
401 return _permission;
402 }
403
404 This* _GetThis()
405 {
406 return _Validate() ? this : NULL;
407 }
408
409 const This* _GetThis() const
410 {
411 return _Validate() ? this : NULL;
412 }
413
414 bool _Validate() const
415 {
416 if (_view.IsValid()) {
417 return true;
418 }
419 else {
420 TF_CODING_ERROR("Accessing expired %s", _type.c_str());
421 return false;
422 }
423 }
424
425 bool _Validate(int permission)
426 {
427 if (!_Validate()) {
428 return false;
429 }
430 if ((_permission & permission) == permission) {
431 return true;
432 }
433 const char* op = "edit";
434 if (~_permission & permission & CanSet) {
435 op = "replace";
436 }
437 else if (~_permission & permission & CanInsert) {
438 op = "insert";
439 }
440 else if (~_permission & permission & CanErase) {
441 op = "remove";
442 }
443 TF_CODING_ERROR("Cannot %s %s", op, _type.c_str());
444 return false;
445 }
446
447 bool _Copy(const mapped_vector_type& values)
448 {
449 return _Validate(CanSet) ? _PrimCopy(values) : false;
450 }
451
452 bool _Insert(const mapped_type& value, size_t index)
453 {
454 return _Validate(CanInsert) ? _PrimInsert(value, index) : false;
455 }
456
457 bool _Erase(const key_type& key)
458 {
459 return _Validate(CanErase) ? _PrimErase(key) : false;
460 }
461
462 bool _PrimCopy(const mapped_vector_type& values)
463 {
464 typedef std::vector<typename ChildPolicy::ValueType>
465 ChildrenValueVector;
466
467 ChildrenValueVector v;
468 for (size_t i = 0; i < values.size(); ++i)
469 v.push_back(Adapter::Convert(values[i]));
470
471 return _view.GetChildren().Copy(v, _type);
472 }
473
474 bool _PrimInsert(const mapped_type& value, size_t index)
475 {
476 return _view.GetChildren().Insert(
477 Adapter::Convert(value), index, _type);
478 }
479
480 bool _PrimErase(const key_type& key)
481 {
482 return _view.GetChildren().Erase(key, _type);
483 }
484
485private:
486 View _view;
487 std::string _type;
488 int _permission;
489
490 template <class V> friend class SdfChildrenProxy;
491 template <class V> friend class SdfPyChildrenProxy;
492};
493
494// Allow TfIteration over children proxies.
495template <typename _View>
496struct Tf_ShouldIterateOverCopy<SdfChildrenProxy<_View> > : std::true_type
497{
498};
499
500// Cannot get from a VtValue except as the correct type.
501template <class _View>
502struct Vt_DefaultValueFactory<SdfChildrenProxy<_View> > {
503 static Vt_DefaultValueHolder Invoke() = delete;
504};
505
506PXR_NAMESPACE_CLOSE_SCOPE
507
508#endif // PXR_USD_SDF_CHILDREN_PROXY_H
Low-level utilities for informing users of various internal and external diagnostic conditions.
A simple iterator adapter for STL containers.
DANGER DANGER DANGER
Definition: changeBlock.h:56
#define TF_CODING_ERROR(fmt, args)
Issue an internal programming error, but continue execution.
Definition: diagnostic.h:68