1 // 2 // SPDX-License-Identifier: BSD-3-Clause 3 // Copyright Contributors to the OpenEXR Project. 4 // 5 6 // clang-format off 7 8 #ifndef _PyImathFixedVArray_h_ 9 #define _PyImathFixedVArray_h_ 10 11 #include <boost/python.hpp> 12 #include <boost/any.hpp> 13 #include <vector> 14 #include "PyImathFixedArray.h" 15 16 namespace PyImath { 17 18 template <class T> 19 class FixedVArray 20 { 21 // This class (at least for now) holds a std::vector of 'T' types. 22 // This will give us the 'variable' part of the array. Generally, 23 // we will initially support only a very small subset of accessor 24 // methods before the semantics are fully defined. Currently, the 25 // VArray semantics are defined in the 'varraySemantics.txt' file. 26 27 std::vector<T> * _ptr; 28 size_t _length; 29 size_t _stride; 30 bool _writable; 31 32 // This handle optionally stores a shared_array to allocated array data 33 // so that everything is freed properly on exit. 34 boost::any _handle; 35 36 boost::shared_array<size_t> _indices; // non-NULL if we're a masked reference 37 size_t _unmaskedLength; 38 39 public: 40 typedef T BaseType; 41 42 FixedVArray (std::vector<T>* ptr, Py_ssize_t length, 43 Py_ssize_t stride = 1, bool writable = true); 44 45 FixedVArray (std::vector<T>* ptr, Py_ssize_t length, 46 Py_ssize_t stride, boost::any handle, bool writable = true); 47 48 FixedVArray (const std::vector<T>* ptr, Py_ssize_t length, 49 Py_ssize_t stride = 1); 50 51 FixedVArray (const std::vector<T>* ptr, Py_ssize_t length, 52 Py_ssize_t stride, boost::any handle); 53 54 explicit FixedVArray (Py_ssize_t length); 55 56 FixedVArray (const T& initialValue, Py_ssize_t length); 57 58 FixedVArray (FixedVArray<T>& f, const FixedArray<int>& mask); 59 60 FixedVArray (const FixedArray<int>& size, const T& initialValue); 61 62 FixedVArray (const FixedVArray<T>& other); 63 64 const FixedVArray& operator = (const FixedVArray<T>& other); 65 66 ~FixedVArray(); 67 68 // ---------------- 69 handle()70 const boost::any& handle() { return _handle; } 71 len()72 Py_ssize_t len() const { return _length; } stride()73 size_t stride() const { return _stride; } writable()74 bool writable() const { return _writable; } 75 76 // This method is mainly here for use in confidence tests, but there may 77 // be other use-cases where a writable array needs to be made read-only. 78 // Note that we do not provide a 'makeWritable' method here, because that 79 // type of operation shouldn't be allowed. makeReadOnly()80 void makeReadOnly() { _writable = false; } 81 isMaskedReference()82 bool isMaskedReference() const { return _indices.get() != 0; } unmaskedLength()83 size_t unmaskedLength() const { return _unmaskedLength; } 84 85 std::vector<T>& operator [] (size_t i); 86 const std::vector<T>& operator [] (size_t i) const; 87 88 // ---------------- 89 90 FixedArray<T> getitem (Py_ssize_t index); 91 FixedVArray<T> getslice (PyObject* index) const; 92 FixedVArray<T> getslice_mask (const FixedArray<int>& mask); 93 94 void setitem_scalar (PyObject* index, const FixedArray<T>& data); 95 void setitem_scalar_mask (const FixedArray<int>& mask, const FixedArray<T>& data); 96 void setitem_vector (PyObject* index, const FixedVArray<T>& data); 97 void setitem_vector_mask (const FixedArray<int>& mask, const FixedVArray<T>& data); 98 99 struct SizeHelper 100 { SizeHelperSizeHelper101 SizeHelper(FixedVArray &a) : _a(a) {} 102 103 int getitem(Py_ssize_t index) const; 104 FixedArray<int> getitem_slice(PyObject* index) const; 105 FixedArray<int> getitem_mask(const FixedArray<int>& mask) const; 106 107 void setitem_scalar (PyObject* index, size_t size); 108 void setitem_scalar_mask (const FixedArray<int>& mask, size_t size); 109 void setitem_vector (PyObject* index, const FixedArray<int>& size); 110 void setitem_vector_mask (const FixedArray<int>& mask, const FixedArray<int>& size); 111 112 private: 113 114 FixedVArray &_a; 115 }; 116 117 boost::shared_ptr<SizeHelper> getSizeHelper(); 118 119 friend struct SizeHelper; 120 121 // ---------------- 122 123 static boost::python::class_<FixedVArray<T> > register_(const char* doc); 124 125 // Instantiations of fixed variable arrays must implement this static member. 126 static const char* name(); 127 128 template <class T2> 129 size_t match_dimension (const FixedArray<T2>& mask, 130 bool strictComparison = true) const 131 { 132 if (len() == mask.len()) 133 { 134 return len(); 135 } 136 137 bool throwExc = false; 138 if (strictComparison) 139 { 140 throwExc = true; 141 } 142 else if (_indices) 143 { 144 if (_unmaskedLength != (size_t) mask.len()) 145 { 146 throwExc = true; 147 } 148 } 149 else 150 { 151 throwExc = true; 152 } 153 154 if (throwExc) 155 { 156 throw std::invalid_argument("Dimensions of source do not match destination"); 157 } 158 159 return len(); 160 } 161 162 size_t match_dimension (const FixedVArray<T>& other, 163 bool strictComparison = true) const 164 { 165 if (len() == other.len()) 166 { 167 return len(); 168 } 169 170 bool throwExc = false; 171 if (strictComparison) 172 { 173 throwExc = true; 174 } 175 else if (_indices) 176 { 177 if (_unmaskedLength != (size_t) other.len()) 178 { 179 throwExc = true; 180 } 181 } 182 else 183 { 184 throwExc = true; 185 } 186 187 if (throwExc) 188 { 189 throw std::invalid_argument("Dimensions of source do not match destination"); 190 } 191 192 return len(); 193 } 194 195 protected: 196 size_t raw_ptr_index (size_t i) const; 197 198 }; 199 200 } // namespace PyImath 201 202 #endif // _PyImathFixedVArray_h_ 203