|
12 | 12 |
|
13 | 13 | #include "Python.h" |
14 | 14 | #include "pycore_abstract.h" // _PyIndex_Check() |
| 15 | +#include "pycore_list.h" // _PyListWriter_ResetSize() |
15 | 16 | #include "pycore_memoryobject.h" // _PyManagedBuffer_Type |
16 | 17 | #include "pycore_object.h" // _PyObject_GC_UNTRACK() |
17 | 18 | #include "pycore_strhex.h" // _Py_strhex_with_sep() |
@@ -1842,7 +1843,9 @@ unpack_single(PyMemoryViewObject *self, const char *ptr, const char *fmt) |
1842 | 1843 | unsigned char uc; |
1843 | 1844 | void *p; |
1844 | 1845 |
|
1845 | | - CHECK_RELEASED_AGAIN(self); |
| 1846 | + if (self != NULL) { |
| 1847 | + CHECK_RELEASED_AGAIN(self); |
| 1848 | + } |
1846 | 1849 |
|
1847 | 1850 | #if PY_LITTLE_ENDIAN |
1848 | 1851 | int endian = 1; |
@@ -2303,24 +2306,6 @@ tolist_base(PyMemoryViewObject *self, const char *ptr, const Py_ssize_t *shape, |
2303 | 2306 | return lst; |
2304 | 2307 | } |
2305 | 2308 |
|
2306 | | -static int |
2307 | | -tolistwriter(PyListWriter *writer, PyMemoryViewObject *self, const char *ptr, |
2308 | | - const Py_ssize_t *shape, const Py_ssize_t *strides, |
2309 | | - const Py_ssize_t *suboffsets, const char *fmt) |
2310 | | -{ |
2311 | | - for (Py_ssize_t i = 0; i < shape[0]; ptr+=strides[0], i++) { |
2312 | | - const char *xptr = ADJUST_PTR(ptr, suboffsets, 0); |
2313 | | - PyObject *item = unpack_single(self, xptr, fmt); |
2314 | | - if (item == NULL) { |
2315 | | - return -1; |
2316 | | - } |
2317 | | - if (PyListWriter_AppendSteal(writer, item) < 0) { |
2318 | | - return -1; |
2319 | | - } |
2320 | | - } |
2321 | | - return 0; |
2322 | | -} |
2323 | | - |
2324 | 2309 | /* Unpack a multi-dimensional array into a nested list. |
2325 | 2310 | Assumption: ndim >= 1. */ |
2326 | 2311 | static PyObject * |
@@ -2394,21 +2379,54 @@ memoryview_tolist_impl(PyMemoryViewObject *self) |
2394 | 2379 |
|
2395 | 2380 |
|
2396 | 2381 | int |
2397 | | -_PyMemoryView_ToListWriter(PyObject *mview, PyListWriter *writer) |
| 2382 | +PyListWriter_FromBuffer(PyListWriter *writer, const Py_buffer *view) |
2398 | 2383 | { |
2399 | | - assert(PyMemoryView_Check(mview)); |
2400 | | - PyMemoryViewObject *self = (PyMemoryViewObject *)mview; |
2401 | | - const Py_buffer *view = &self->view; |
2402 | | - assert(view->ndim == 1); |
2403 | | - |
2404 | | - const char *fmt = adjust_fmt(view); |
2405 | | - if (fmt == NULL) { |
| 2384 | + if (view->ndim != 1) { |
| 2385 | + PyErr_Format(PyExc_ValueError, |
| 2386 | + "require a buffer of 1 dimension, got %i dimentions", |
| 2387 | + view->ndim); |
2406 | 2388 | return -1; |
2407 | 2389 | } |
2408 | 2390 |
|
2409 | | - return tolistwriter(writer, self, view->buf, view->shape, |
2410 | | - view->strides, view->suboffsets, |
2411 | | - fmt); |
| 2391 | + const char *fmt; |
| 2392 | + if (view->format != NULL) { |
| 2393 | + fmt = adjust_fmt(view); |
| 2394 | + if (fmt == NULL) { |
| 2395 | + return -1; |
| 2396 | + } |
| 2397 | + } |
| 2398 | + else { |
| 2399 | + // Same default value than init_shared_values() |
| 2400 | + fmt = "B"; |
| 2401 | + } |
| 2402 | + |
| 2403 | + PyListObject *list = _PyList_CAST(writer); |
| 2404 | + Py_ssize_t old_writer_size = Py_SIZE(list); |
| 2405 | + |
| 2406 | + const char *ptr = view->buf; |
| 2407 | + const Py_ssize_t shape = view->shape ? view->shape[0] : view->len; |
| 2408 | + const Py_ssize_t strides = view->strides ? view->strides[0] : view->itemsize; |
| 2409 | + const Py_ssize_t *suboffsets = view->suboffsets; |
| 2410 | + |
| 2411 | + for (Py_ssize_t i = 0; i < shape; ptr += strides, i++) { |
| 2412 | + const char *xptr = ADJUST_PTR(ptr, suboffsets, 0); |
| 2413 | + PyObject *item = unpack_single(NULL, xptr, fmt); |
| 2414 | + if (item == NULL) { |
| 2415 | + goto error; |
| 2416 | + } |
| 2417 | + if (PyListWriter_AppendSteal(writer, item) < 0) { |
| 2418 | + goto error; |
| 2419 | + } |
| 2420 | + } |
| 2421 | + return 0; |
| 2422 | + |
| 2423 | +error: |
| 2424 | + if (Py_SIZE(list) != old_writer_size) { |
| 2425 | + // On error, reset the writer to its previous state: |
| 2426 | + // discard added items |
| 2427 | + _PyListWriter_ResetSize(writer, old_writer_size); |
| 2428 | + } |
| 2429 | + return -1; |
2412 | 2430 | } |
2413 | 2431 |
|
2414 | 2432 |
|
|
0 commit comments