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