|
34 | 34 |
|
35 | 35 | #include "PyArray.hpp" |
36 | 36 | #include <pdal/io/MemoryViewReader.hpp> |
37 | | -#include <numpy/arrayobject.h> |
38 | 37 |
|
39 | 38 | namespace pdal |
40 | 39 | { |
@@ -94,7 +93,8 @@ std::string toString(PyObject *pname) |
94 | 93 | #define PyDataType_FIELDS(descr) ((descr)->fields) |
95 | 94 | #endif |
96 | 95 |
|
97 | | -Array::Array(PyArrayObject* array) : m_array(array), m_rowMajor(true) |
| 96 | +Array::Array(PyArrayObject* array, std::shared_ptr<ArrayStreamHandler> stream_handler) |
| 97 | + : m_array(array), m_rowMajor(true), m_stream_handler(std::move(stream_handler)) |
98 | 98 | { |
99 | 99 | Py_XINCREF(array); |
100 | 100 |
|
@@ -163,51 +163,85 @@ Array::~Array() |
163 | 163 | Py_XDECREF(m_array); |
164 | 164 | } |
165 | 165 |
|
166 | | - |
167 | | -ArrayIter& Array::iterator() |
| 166 | +std::shared_ptr<ArrayIter> Array::iterator() |
168 | 167 | { |
169 | | - ArrayIter *it = new ArrayIter(m_array); |
170 | | - m_iterators.emplace_back((it)); |
171 | | - return *it; |
| 168 | + return std::make_shared<ArrayIter>(m_array, m_stream_handler); |
172 | 169 | } |
173 | 170 |
|
| 171 | +ArrayIter::ArrayIter(PyArrayObject* np_array, std::shared_ptr<ArrayStreamHandler> stream_handler) |
| 172 | + : m_stream_handler(std::move(stream_handler)) |
| 173 | +{ |
| 174 | + resetIterator(np_array); |
| 175 | +} |
174 | 176 |
|
175 | | -ArrayIter::ArrayIter(PyArrayObject* np_array) |
| 177 | +void ArrayIter::resetIterator(std::optional<PyArrayObject*> np_array = {}) |
176 | 178 | { |
177 | | - m_iter = NpyIter_New(np_array, |
178 | | - NPY_ITER_EXTERNAL_LOOP | NPY_ITER_READONLY | NPY_ITER_REFS_OK, |
179 | | - NPY_KEEPORDER, NPY_NO_CASTING, NULL); |
180 | | - if (!m_iter) |
181 | | - throw pdal_error("Unable to create numpy iterator."); |
| 179 | + std::optional<int> stream_chunk_size = std::nullopt; |
| 180 | + if (m_stream_handler) { |
| 181 | + stream_chunk_size = (*m_stream_handler)(); |
| 182 | + if (*stream_chunk_size == 0) { |
| 183 | + m_done = true; |
| 184 | + return; |
| 185 | + } |
| 186 | + } |
| 187 | + |
| 188 | + if (np_array) { |
| 189 | + // Init iterator |
| 190 | + m_iter = NpyIter_New(np_array.value(), |
| 191 | + NPY_ITER_EXTERNAL_LOOP | NPY_ITER_READONLY | NPY_ITER_REFS_OK, |
| 192 | + NPY_KEEPORDER, NPY_NO_CASTING, NULL); |
| 193 | + if (!m_iter) |
| 194 | + throw pdal_error("Unable to create numpy iterator."); |
| 195 | + } else { |
| 196 | + // Otherwise, reset the iterator to the initial state |
| 197 | + if (NpyIter_Reset(m_iter, NULL) != NPY_SUCCEED) { |
| 198 | + NpyIter_Deallocate(m_iter); |
| 199 | + throw pdal_error("Unable to reset numpy iterator."); |
| 200 | + } |
| 201 | + } |
182 | 202 |
|
183 | 203 | char *itererr; |
184 | 204 | m_iterNext = NpyIter_GetIterNext(m_iter, &itererr); |
185 | 205 | if (!m_iterNext) |
186 | 206 | { |
187 | 207 | NpyIter_Deallocate(m_iter); |
188 | | - throw pdal_error(std::string("Unable to create numpy iterator: ") + |
189 | | - itererr); |
| 208 | + throw pdal_error(std::string("Unable to create numpy iterator: ") + itererr); |
190 | 209 | } |
191 | 210 | m_data = NpyIter_GetDataPtrArray(m_iter); |
192 | | - m_stride = NpyIter_GetInnerStrideArray(m_iter); |
193 | | - m_size = NpyIter_GetInnerLoopSizePtr(m_iter); |
| 211 | + m_stride = *NpyIter_GetInnerStrideArray(m_iter); |
| 212 | + m_size = *NpyIter_GetInnerLoopSizePtr(m_iter); |
| 213 | + if (stream_chunk_size) { |
| 214 | + if (0 <= *stream_chunk_size && *stream_chunk_size <= m_size) { |
| 215 | + m_size = *stream_chunk_size; |
| 216 | + } else { |
| 217 | + throw pdal_error(std::string("Stream chunk size not in the range of array length: ") + |
| 218 | + std::to_string(*stream_chunk_size)); |
| 219 | + } |
| 220 | + } |
194 | 221 | m_done = false; |
195 | 222 | } |
196 | 223 |
|
197 | 224 | ArrayIter::~ArrayIter() |
198 | 225 | { |
199 | | - NpyIter_Deallocate(m_iter); |
| 226 | + if (m_iter != nullptr) { |
| 227 | + NpyIter_Deallocate(m_iter); |
| 228 | + } |
200 | 229 | } |
201 | 230 |
|
202 | 231 | ArrayIter& ArrayIter::operator++() |
203 | 232 | { |
204 | 233 | if (m_done) |
205 | 234 | return *this; |
206 | 235 |
|
207 | | - if (--(*m_size)) |
208 | | - *m_data += *m_stride; |
209 | | - else if (!m_iterNext(m_iter)) |
210 | | - m_done = true; |
| 236 | + if (--m_size) { |
| 237 | + *m_data += m_stride; |
| 238 | + } else if (!m_iterNext(m_iter)) { |
| 239 | + if (m_stream_handler) { |
| 240 | + resetIterator(); |
| 241 | + } else { |
| 242 | + m_done = true; |
| 243 | + } |
| 244 | + } |
211 | 245 | return *this; |
212 | 246 | } |
213 | 247 |
|
|
0 commit comments