// // Copyright 2016 Pixar // // Licensed under the Apache License, Version 2.0 (the "Apache License") // with the following modification; you may not use this file except in // compliance with the Apache License and the following modification to it: // Section 6. Trademarks. is deleted and replaced with: // // 6. Trademarks. This License does not grant permission to use the trade // names, trademarks, service marks, or product names of the Licensor // and its affiliates, except as required to comply with Section 4(c) of // the License and to reproduce the content of the NOTICE file. // // You may obtain a copy of the Apache License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the Apache License with the above modification is // distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the Apache License for the specific // language governing permissions and limitations under the Apache License. // #ifndef PXR_USD_SDF_CHILDREN_PROXY_H #define PXR_USD_SDF_CHILDREN_PROXY_H /// \file sdf/childrenProxy.h #include "pxr/pxr.h" #include "pxr/usd/sdf/api.h" #include "pxr/usd/sdf/changeBlock.h" #include "pxr/base/vt/value.h" #include "pxr/base/tf/diagnostic.h" #include "pxr/base/tf/iterator.h" #include #include #include #include #include #include PXR_NAMESPACE_OPEN_SCOPE template class SdfChildrenProxy : boost::equality_comparable > { public: typedef _View View; typedef typename View::Adapter Adapter; typedef typename View::ChildPolicy ChildPolicy; typedef typename View::key_type key_type; typedef typename View::value_type mapped_type; typedef std::vector mapped_vector_type; typedef std::pair value_type; typedef std::map map_type; typedef typename View::size_type size_type; typedef SdfChildrenProxy This; private: typedef typename View::const_iterator _inner_iterator; class _ValueProxy { public: _ValueProxy() : _owner(NULL) { } _ValueProxy(This* owner, _inner_iterator i) : _owner(owner), _pos(i) { // Do nothing } operator mapped_type() const { return *_pos; } template _ValueProxy& operator=(const U& x) { _owner->_Set(*_pos, x); return *this; } bool operator==(const mapped_type& other) const { return *_pos == other; } private: This* _owner; _inner_iterator _pos; }; class _PairProxy { public: explicit _PairProxy(This* owner, _inner_iterator i) : first(owner->_view.key(i)), second(owner, i) { } const key_type first; _ValueProxy second; operator value_type() const { return value_type(first, second); } }; friend class _PairProxy; class _Traits { public: static value_type Dereference(const This* owner, _inner_iterator i) { return value_type(owner->_view.key(i), *i); } static _PairProxy Dereference(This* owner, _inner_iterator i) { return _PairProxy(owner, i); } }; template class _Iterator : public boost::iterator_facade< _Iterator<_Owner, _Iter, _Value>, _Value, std::bidirectional_iterator_tag, _Value> { public: _Iterator() { } _Iterator(_Owner owner, _inner_iterator i) : _owner(owner), _pos(i) { } template _Iterator(const _Iterator& other) : _owner(other._owner), _pos(other._pos) { } private: friend class boost::iterator_core_access; _Value dereference() const { return _Traits::Dereference(_owner, _pos); } template bool equal(const _Iterator& other) const { return _pos == other._pos; } void increment() { ++_pos; } void decrement() { --_pos; } private: _Owner _owner; _inner_iterator _pos; template friend class _Iterator; }; public: typedef _ValueProxy reference; typedef _Iterator iterator; typedef boost::reverse_iterator reverse_iterator; typedef _Iterator const_iterator; typedef boost::reverse_iterator const_reverse_iterator; static const int CanSet = 1; static const int CanInsert = 2; static const int CanErase = 4; SdfChildrenProxy(const View& view, const std::string& type, int permission = CanSet | CanInsert | CanErase) : _view(view), _type(type), _permission(permission) { // Do nothing } template SdfChildrenProxy(const SdfChildrenProxy& other) : _view(other._view), _type(other._type), _permission(other._permission) { // Do nothing } This& operator=(const This& other) { if (other._Validate()) { _Copy(other._view.values()); } return *this; } template This& operator=(const SdfChildrenProxy& other) { if (other._Validate()) { _Copy(other._view.values()); } return *this; } This& operator=(const mapped_vector_type& values) { _Copy(values); return *this; } operator mapped_vector_type() const { return _Validate() ? _view.values() : mapped_vector_type(); } map_type items() const { return _Validate() ? _view.template items_as() :map_type(); } iterator begin() { return iterator(_GetThis(), _view.begin()); } iterator end() { return iterator(_GetThis(), _view.end()); } const_iterator begin() const { return const_iterator(_GetThis(), _view.begin()); } const_iterator end() const { return const_iterator(_GetThis(), _view.end()); } reverse_iterator rbegin() { return reverse_iterator(end()); } reverse_iterator rend() { return reverse_iterator(begin()); } const_reverse_iterator rbegin() const { return reverse_iterator(end()); } const_reverse_iterator rend() const { return reverse_iterator(begin()); } size_type size() const { return _Validate() ? _view.size() : 0; } size_type max_size() const { return _view.max_size(); } bool empty() const { return _Validate() ? _view.empty() : true; } std::pair insert(const mapped_type& value) { if (_Validate(CanInsert)) { iterator i = find(_view.key(value)); if (i == end()) { if (_PrimInsert(value, size())) { return std::make_pair(find(_view.key(value)), true); } else { return std::make_pair(end(), false); } } else { return std::make_pair(i, false); } } else { return std::make_pair(iterator(), false); } } iterator insert(iterator pos, const mapped_type& value) { return insert(value).first; } template void insert(InputIterator first, InputIterator last) { if (_Validate(CanInsert)) { SdfChangeBlock block; for (; first != last; ++first) { _PrimInsert(*first, size()); } } } void erase(iterator pos) { _Erase(pos->first); } size_type erase(const key_type& key) { return _Erase(key) ? 1 : 0; } void erase(iterator first, iterator last) { if (_Validate(CanErase)) { SdfChangeBlock block; while (first != last) { const key_type& key = first->first; ++first; _PrimErase(key); } } } void clear() { _Copy(mapped_vector_type()); } iterator find(const key_type& key) { return _Validate() ? iterator(this, _view.find(key)) : iterator(); } const_iterator find(const key_type& key) const { return _Validate() ? const_iterator(this, _view.find(key)) : const_iterator(); } size_type count(const key_type& key) const { return _Validate() ? _view.count(key) : 0; } bool operator==(const This& other) const { return _view == other._view; } /// Explicit bool conversion operator. The proxy object converts to /// \c true if it is valid, \c false otherwise. explicit operator bool() const { return _view.IsValid(); } private: const std::string& _GetType() const { return _type; } int _GetPermission() const { return _permission; } This* _GetThis() { return _Validate() ? this : NULL; } const This* _GetThis() const { return _Validate() ? this : NULL; } bool _Validate() const { if (_view.IsValid()) { return true; } else { TF_CODING_ERROR("Accessing expired %s", _type.c_str()); return false; } } bool _Validate(int permission) { if (!_Validate()) { return false; } if ((_permission & permission) == permission) { return true; } const char* op = "edit"; if (~_permission & permission & CanSet) { op = "replace"; } else if (~_permission & permission & CanInsert) { op = "insert"; } else if (~_permission & permission & CanErase) { op = "remove"; } TF_CODING_ERROR("Cannot %s %s", op, _type.c_str()); return false; } bool _Copy(const mapped_vector_type& values) { return _Validate(CanSet) ? _PrimCopy(values) : false; } bool _Insert(const mapped_type& value, size_t index) { return _Validate(CanInsert) ? _PrimInsert(value, index) : false; } bool _Erase(const key_type& key) { return _Validate(CanErase) ? _PrimErase(key) : false; } bool _PrimCopy(const mapped_vector_type& values) { typedef std::vector ChildrenValueVector; ChildrenValueVector v; for (size_t i = 0; i < values.size(); ++i) v.push_back(Adapter::Convert(values[i])); return _view.GetChildren().Copy(v, _type); } bool _PrimInsert(const mapped_type& value, size_t index) { return _view.GetChildren().Insert( Adapter::Convert(value), index, _type); } bool _PrimErase(const key_type& key) { return _view.GetChildren().Erase(key, _type); } private: View _view; std::string _type; int _permission; template friend class SdfChildrenProxy; template friend class SdfPyChildrenProxy; }; // Allow TfIteration over children proxies. template struct Tf_ShouldIterateOverCopy > : boost::true_type { }; // Cannot get from a VtValue except as the correct type. template struct Vt_DefaultValueFactory > { static Vt_DefaultValueHolder Invoke() = delete; }; PXR_NAMESPACE_CLOSE_SCOPE #endif // PXR_USD_SDF_CHILDREN_PROXY_H