-: 0:Source:Objects/memoryobject.c -: 0:Graph:memoryobject.gcno -: 0:Data:memoryobject.gcda -: 0:Runs:761 -: 0:Programs:2 -: 1:/* Memoryview object implementation */ -: 2: -: 3:#include "Python.h" -: 4:#include -: 5: -: 6: -: 7:/****************************************************************************/ -: 8:/* ManagedBuffer Object */ -: 9:/****************************************************************************/ -: 10: -: 11:/* -: 12: ManagedBuffer Object: -: 13: --------------------- -: 14: -: 15: The purpose of this object is to facilitate the handling of chained -: 16: memoryviews that have the same underlying exporting object. PEP-3118 -: 17: allows the underlying object to change while a view is exported. This -: 18: could lead to unexpected results when constructing a new memoryview -: 19: from an existing memoryview. -: 20: -: 21: Rather than repeatedly redirecting buffer requests to the original base -: 22: object, all chained memoryviews use a single buffer snapshot. This -: 23: snapshot is generated by the constructor _PyManagedBuffer_FromObject(). -: 24: -: 25: Ownership rules: -: 26: ---------------- -: 27: -: 28: The master buffer inside a managed buffer is filled in by the original -: 29: base object. shape, strides, suboffsets and format are read-only for -: 30: all consumers. -: 31: -: 32: A memoryview's buffer is a private copy of the exporter's buffer. shape, -: 33: strides and suboffsets belong to the memoryview and are thus writable. -: 34: -: 35: If a memoryview itself exports several buffers via memory_getbuf(), all -: 36: buffer copies share shape, strides and suboffsets. In this case, the -: 37: arrays are NOT writable. -: 38: -: 39: Reference count assumptions: -: 40: ---------------------------- -: 41: -: 42: The 'obj' member of a Py_buffer must either be NULL or refer to the -: 43: exporting base object. In the Python codebase, all getbufferprocs -: 44: return a new reference to view.obj (example: bytes_buffer_getbuffer()). -: 45: -: 46: PyBuffer_Release() decrements view.obj (if non-NULL), so the -: 47: releasebufferprocs must NOT decrement view.obj. -: 48:*/ -: 49: -: 50: -: 51:#define XSTRINGIZE(v) #v -: 52:#define STRINGIZE(v) XSTRINGIZE(v) -: 53: -: 54:#define CHECK_MBUF_RELEASED(mbuf) \ -: 55: if (((_PyManagedBufferObject *)mbuf)->flags&_Py_MANAGED_BUFFER_RELEASED) { \ -: 56: PyErr_SetString(PyExc_ValueError, \ -: 57: "operation forbidden on released memoryview object"); \ -: 58: return NULL; \ -: 59: } -: 60: -: 61: -: 62:Py_LOCAL_INLINE(_PyManagedBufferObject *) 66024943: 63:mbuf_alloc(void) -: 64:{ -: 65: _PyManagedBufferObject *mbuf; -: 66: 132056770: 67: mbuf = (_PyManagedBufferObject *) 132056770: 68: PFUNC(PyObject_GC_New(_PyManagedBufferObject, &_PyManagedBuffer_Type)); 66024943: 69: if (mbuf == NULL) 6884: 70: return NULL; 66018059: 71: mbuf->flags = 0; 66018059: 72: mbuf->exports = 0; 66018059: 73: mbuf->master.obj = NULL; 66018059: 74: _PyObject_GC_TRACK(mbuf); -: 75: 66018059: 76: return mbuf; -: 77:} -: 78: -: 79:static PyObject * 21594304: 80:_PyManagedBuffer_FromObject(PyObject *base) -: 81:{ -: 82: _PyManagedBufferObject *mbuf; -: 83: 21594304: 84: mbuf = mbuf_alloc(); 21594304: 85: if (mbuf == NULL) 2152: 86: return NULL; -: 87: 21592152: 88: if (PyObject_GetBuffer(base, &mbuf->master, PyBUF_FULL_RO) < 0) { 566: 89: mbuf->master.obj = NULL; 566: 90: Py_DECREF(mbuf); 566: 91: return NULL; -: 92: } -: 93: 21591586: 94: return (PyObject *)mbuf; -: 95:} -: 96: -: 97:static void 132028454: 98:mbuf_release(_PyManagedBufferObject *self) -: 99:{ 132028454: 100: if (self->flags&_Py_MANAGED_BUFFER_RELEASED) 66010395: 101: return; -: 102: -: 103: /* NOTE: at this point self->exports can still be > 0 if this function -: 104: is called from mbuf_clear() to break up a reference cycle. */ 66018059: 105: self->flags |= _Py_MANAGED_BUFFER_RELEASED; -: 106: -: 107: /* PyBuffer_Release() decrements master->obj and sets it to NULL. */ 66018059: 108: _PyObject_GC_UNTRACK(self); 66018059: 109: PyBuffer_Release(&self->master); -: 110:} -: 111: -: 112:static void 66018059: 113:mbuf_dealloc(_PyManagedBufferObject *self) -: 114:{ -: 115: assert(self->exports == 0); 66018059: 116: mbuf_release(self); 66018059: 117: if (self->flags&_Py_MANAGED_BUFFER_FREE_FORMAT) 1958028: 118: PyMem_Free(self->master.format); 66018059: 119: PyObject_GC_Del(self); 66018059: 120:} -: 121: -: 122:static int 9944: 123:mbuf_traverse(_PyManagedBufferObject *self, visitproc visit, void *arg) -: 124:{ 9944: 125: Py_VISIT(self->master.obj); 9944: 126: return 0; -: 127:} -: 128: -: 129:static int #####: 130:mbuf_clear(_PyManagedBufferObject *self) -: 131:{ -: 132: assert(self->exports >= 0); #####: 133: mbuf_release(self); #####: 134: return 0; -: 135:} -: 136: -: 137:PyTypeObject _PyManagedBuffer_Type = { -: 138: PyVarObject_HEAD_INIT(&PyType_Type, 0) -: 139: "managedbuffer", -: 140: sizeof(_PyManagedBufferObject), -: 141: 0, -: 142: (destructor)mbuf_dealloc, /* tp_dealloc */ -: 143: 0, /* tp_print */ -: 144: 0, /* tp_getattr */ -: 145: 0, /* tp_setattr */ -: 146: 0, /* tp_reserved */ -: 147: 0, /* tp_repr */ -: 148: 0, /* tp_as_number */ -: 149: 0, /* tp_as_sequence */ -: 150: 0, /* tp_as_mapping */ -: 151: 0, /* tp_hash */ -: 152: 0, /* tp_call */ -: 153: 0, /* tp_str */ -: 154: PyObject_GenericGetAttr, /* tp_getattro */ -: 155: 0, /* tp_setattro */ -: 156: 0, /* tp_as_buffer */ -: 157: Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */ -: 158: 0, /* tp_doc */ -: 159: (traverseproc)mbuf_traverse, /* tp_traverse */ -: 160: (inquiry)mbuf_clear /* tp_clear */ -: 161:}; -: 162: -: 163: -: 164:/****************************************************************************/ -: 165:/* MemoryView Object */ -: 166:/****************************************************************************/ -: 167: -: 168:/* In the process of breaking reference cycles mbuf_release() can be -: 169: called before memory_release(). */ -: 170:#define BASE_INACCESSIBLE(mv) \ -: 171: (((PyMemoryViewObject *)mv)->flags&_Py_MEMORYVIEW_RELEASED || \ -: 172: ((PyMemoryViewObject *)mv)->mbuf->flags&_Py_MANAGED_BUFFER_RELEASED) -: 173: -: 174:#define CHECK_RELEASED(mv) \ -: 175: if (BASE_INACCESSIBLE(mv)) { \ -: 176: PyErr_SetString(PyExc_ValueError, \ -: 177: "operation forbidden on released memoryview object"); \ -: 178: return NULL; \ -: 179: } -: 180: -: 181:#define CHECK_RELEASED_INT(mv) \ -: 182: if (BASE_INACCESSIBLE(mv)) { \ -: 183: PyErr_SetString(PyExc_ValueError, \ -: 184: "operation forbidden on released memoryview object"); \ -: 185: return -1; \ -: 186: } -: 187: -: 188:#define CHECK_LIST_OR_TUPLE(v) \ -: 189: if (!PyList_Check(v) && !PyTuple_Check(v)) { \ -: 190: PyErr_SetString(PyExc_TypeError, \ -: 191: #v " must be a list or a tuple"); \ -: 192: return NULL; \ -: 193: } -: 194: -: 195:#define VIEW_ADDR(mv) (&((PyMemoryViewObject *)mv)->view) -: 196: -: 197:/* Check for the presence of suboffsets in the first dimension. */ -: 198:#define HAVE_PTR(suboffsets) (suboffsets && suboffsets[0] >= 0) -: 199:/* Adjust ptr if suboffsets are present. */ -: 200:#define ADJUST_PTR(ptr, suboffsets) \ -: 201: (HAVE_PTR(suboffsets) ? *((char**)ptr) + suboffsets[0] : ptr) -: 202: -: 203:/* Memoryview buffer properties */ -: 204:#define MV_C_CONTIGUOUS(flags) (flags&(_Py_MEMORYVIEW_SCALAR|_Py_MEMORYVIEW_C)) -: 205:#define MV_F_CONTIGUOUS(flags) \ -: 206: (flags&(_Py_MEMORYVIEW_SCALAR|_Py_MEMORYVIEW_FORTRAN)) -: 207:#define MV_ANY_CONTIGUOUS(flags) \ -: 208: (flags&(_Py_MEMORYVIEW_SCALAR|_Py_MEMORYVIEW_C|_Py_MEMORYVIEW_FORTRAN)) -: 209: -: 210:/* Fast contiguity test. Caller must ensure suboffsets==NULL and ndim==1. */ -: 211:#define MV_CONTIGUOUS_NDIM1(view) \ -: 212: ((view)->shape[0] == 1 || (view)->strides[0] == (view)->itemsize) -: 213: -: 214:/* getbuffer() requests */ -: 215:#define REQ_INDIRECT(flags) ((flags&PyBUF_INDIRECT) == PyBUF_INDIRECT) -: 216:#define REQ_C_CONTIGUOUS(flags) ((flags&PyBUF_C_CONTIGUOUS) == PyBUF_C_CONTIGUOUS) -: 217:#define REQ_F_CONTIGUOUS(flags) ((flags&PyBUF_F_CONTIGUOUS) == PyBUF_F_CONTIGUOUS) -: 218:#define REQ_ANY_CONTIGUOUS(flags) ((flags&PyBUF_ANY_CONTIGUOUS) == PyBUF_ANY_CONTIGUOUS) -: 219:#define REQ_STRIDES(flags) ((flags&PyBUF_STRIDES) == PyBUF_STRIDES) -: 220:#define REQ_SHAPE(flags) ((flags&PyBUF_ND) == PyBUF_ND) -: 221:#define REQ_WRITABLE(flags) (flags&PyBUF_WRITABLE) -: 222:#define REQ_FORMAT(flags) (flags&PyBUF_FORMAT) -: 223: -: 224: -: 225:PyDoc_STRVAR(memory_doc, -: 226:"memoryview(object)\n\ -: 227:\n\ -: 228:Create a new memoryview object which references the given object."); -: 229: -: 230: -: 231:/**************************************************************************/ -: 232:/* Copy memoryview buffers */ -: 233:/**************************************************************************/ -: 234: -: 235:/* The functions in this section take a source and a destination buffer -: 236: with the same logical structure: format, itemsize, ndim and shape -: 237: are identical, with ndim > 0. -: 238: -: 239: NOTE: All buffers are assumed to have PyBUF_FULL information, which -: 240: is the case for memoryviews! */ -: 241: -: 242: -: 243:/* Assumptions: ndim >= 1. The macro tests for a corner case that should -: 244: perhaps be explicitly forbidden in the PEP. */ -: 245:#define HAVE_SUBOFFSETS_IN_LAST_DIM(view) \ -: 246: (view->suboffsets && view->suboffsets[dest->ndim-1] >= 0) -: 247: -: 248:Py_LOCAL_INLINE(int) 8042414: 249:last_dim_is_contiguous(const Py_buffer *dest, const Py_buffer *src) -: 250:{ -: 251: assert(dest->ndim > 0 && src->ndim > 0); 20244699: 252: return (!HAVE_SUBOFFSETS_IN_LAST_DIM(dest) && 3973999: 253: !HAVE_SUBOFFSETS_IN_LAST_DIM(src) && 4278911: 254: dest->strides[dest->ndim-1] == dest->itemsize && 3949375: 255: src->strides[src->ndim-1] == src->itemsize); -: 256:} -: 257: -: 258:/* This is not a general function for determining format equivalence. -: 259: It is used in copy_single() and copy_buffer() to weed out non-matching -: 260: formats. Skipping the '@' character is specifically used in slice -: 261: assignments, where the lvalue is already known to have a single character -: 262: format. This is a performance hack that could be rewritten (if properly -: 263: benchmarked). */ -: 264:Py_LOCAL_INLINE(int) 8043108: 265:equiv_format(const Py_buffer *dest, const Py_buffer *src) -: 266:{ -: 267: const char *dfmt, *sfmt; -: 268: -: 269: assert(dest->format && src->format); 8043108: 270: dfmt = dest->format[0] == '@' ? dest->format+1 : dest->format; 8043108: 271: sfmt = src->format[0] == '@' ? src->format+1 : src->format; -: 272: 16085627: 273: if (strcmp(dfmt, sfmt) != 0 || 8042519: 274: dest->itemsize != src->itemsize) { 589: 275: return 0; -: 276: } -: 277: 8042519: 278: return 1; -: 279:} -: 280: -: 281:/* Two shapes are equivalent if they are either equal or identical up -: 282: to a zero element at the same position. For example, in NumPy arrays -: 283: the shapes [1, 0, 5] and [1, 0, 7] are equivalent. */ -: 284:Py_LOCAL_INLINE(int) 16361609: 285:equiv_shape(const Py_buffer *dest, const Py_buffer *src) -: 286:{ -: 287: int i; -: 288: 16361609: 289: if (dest->ndim != src->ndim) 6663: 290: return 0; -: 291: 37449447: 292: for (i = 0; i < dest->ndim; i++) { 21151904: 293: if (dest->shape[i] != src->shape[i]) 12184: 294: return 0; 21139720: 295: if (dest->shape[i] == 0) 45219: 296: break; -: 297: } -: 298: 16342762: 299: return 1; -: 300:} -: 301: -: 302:/* Check that the logical structure of the destination and source buffers -: 303: is identical. */ -: 304:static int 8043108: 305:equiv_structure(const Py_buffer *dest, const Py_buffer *src) -: 306:{ 16085627: 307: if (!equiv_format(dest, src) || 8042519: 308: !equiv_shape(dest, src)) { 694: 309: PyErr_SetString(PyExc_ValueError, -: 310: "ndarray assignment: lvalue and rvalue have different structures"); 694: 311: return 0; -: 312: } -: 313: 8042414: 314: return 1; -: 315:} -: 316: -: 317:/* Base case for recursive multi-dimensional copying. Contiguous arrays are -: 318: copied with very little overhead. Assumptions: ndim == 1, mem == NULL or -: 319: sizeof(mem) == shape[0] * itemsize. */ -: 320:static void 32305912: 321:copy_base(const Py_ssize_t *shape, Py_ssize_t itemsize, -: 322: char *dptr, const Py_ssize_t *dstrides, const Py_ssize_t *dsuboffsets, -: 323: char *sptr, const Py_ssize_t *sstrides, const Py_ssize_t *ssuboffsets, -: 324: char *mem) -: 325:{ 32305912: 326: if (mem == NULL) { /* contiguous */ 4980751: 327: Py_ssize_t size = shape[0] * itemsize; 9961336: 328: if (dptr + size < sptr || sptr + size < dptr) 4980585: 329: memcpy(dptr, sptr, size); /* no overlapping */ -: 330: else 166: 331: memmove(dptr, sptr, size); -: 332: } -: 333: else { -: 334: char *p; -: 335: Py_ssize_t i; 117723874: 336: for (i=0, p=mem; i < shape[0]; p+=itemsize, sptr+=sstrides[0], i++) { 90398713: 337: char *xsptr = ADJUST_PTR(sptr, ssuboffsets); 90398713: 338: memcpy(p, xsptr, itemsize); -: 339: } 117723874: 340: for (i=0, p=mem; i < shape[0]; p+=itemsize, dptr+=dstrides[0], i++) { 90398713: 341: char *xdptr = ADJUST_PTR(dptr, dsuboffsets); 90398713: 342: memcpy(xdptr, p, itemsize); -: 343: } -: 344: } -: 345: 32305912: 346:} -: 347: -: 348:/* Recursively copy a source buffer to a destination buffer. The two buffers -: 349: have the same ndim, shape and itemsize. */ -: 350:static void 36548646: 351:copy_rec(const Py_ssize_t *shape, Py_ssize_t ndim, Py_ssize_t itemsize, -: 352: char *dptr, const Py_ssize_t *dstrides, const Py_ssize_t *dsuboffsets, -: 353: char *sptr, const Py_ssize_t *sstrides, const Py_ssize_t *ssuboffsets, -: 354: char *mem) -: 355:{ -: 356: Py_ssize_t i; -: 357: -: 358: assert(ndim >= 1); -: 359: 36548646: 360: if (ndim == 1) { 32304547: 361: copy_base(shape, itemsize, -: 362: dptr, dstrides, dsuboffsets, -: 363: sptr, sstrides, ssuboffsets, -: 364: mem); 32304547: 365: return; -: 366: } -: 367: 32752297: 368: for (i = 0; i < shape[0]; dptr+=dstrides[0], sptr+=sstrides[0], i++) { 28508198: 369: char *xdptr = ADJUST_PTR(dptr, dsuboffsets); 28508198: 370: char *xsptr = ADJUST_PTR(sptr, ssuboffsets); -: 371: 28508198: 372: copy_rec(shape+1, ndim-1, itemsize, -: 373: xdptr, dstrides+1, dsuboffsets ? dsuboffsets+1 : NULL, -: 374: xsptr, sstrides+1, ssuboffsets ? ssuboffsets+1 : NULL, -: 375: mem); -: 376: } -: 377:} -: 378: -: 379:/* Faster copying of one-dimensional arrays. */ -: 380:static int 2125: 381:copy_single(Py_buffer *dest, Py_buffer *src) -: 382:{ 2125: 383: char *mem = NULL; -: 384: -: 385: assert(dest->ndim == 1); -: 386: 2125: 387: if (!FFUNC(0, equiv_structure(dest, src))) 753: 388: return -1; -: 389: 1372: 390: if (!last_dim_is_contiguous(dest, src)) { 663: 391: mem = PFUNC_NOEX(PyMem_Malloc(dest->shape[0] * dest->itemsize)); 663: 392: if (mem == NULL) { 7: 393: PyErr_SetString(PyExc_FailAPIError, "failapi"); 7: 394: return -1; -: 395: } -: 396: } -: 397: 2730: 398: copy_base(dest->shape, dest->itemsize, 1365: 399: dest->buf, dest->strides, dest->suboffsets, 1365: 400: src->buf, src->strides, src->suboffsets, -: 401: mem); -: 402: 1365: 403: if (mem) 656: 404: PyMem_Free(mem); -: 405: 1365: 406: return 0; -: 407:} -: 408: -: 409:/* Recursively copy src to dest. Both buffers must have the same basic -: 410: structure. Copying is atomic, the function never fails with a partial -: 411: copy. */ -: 412:static int 8041666: 413:copy_buffer(Py_buffer *dest, Py_buffer *src) -: 414:{ 8041666: 415: char *mem = NULL; -: 416: -: 417: assert(dest->ndim > 0); -: 418: 8041666: 419: if (!FFUNC(0, equiv_structure(dest, src))) 624: 420: return -1; -: 421: 8041042: 422: if (!last_dim_is_contiguous(dest, src)) { 7926828: 423: mem = PFUNC_NOEX(PyMem_Malloc(dest->shape[dest->ndim-1] * dest->itemsize)); 7926828: 424: if (mem == NULL) { 594: 425: PyErr_SetString(PyExc_FailAPIError, "failapi"); 594: 426: return -1; -: 427: } -: 428: } -: 429: 16080896: 430: copy_rec(dest->shape, dest->ndim, dest->itemsize, 8040448: 431: dest->buf, dest->strides, dest->suboffsets, 8040448: 432: src->buf, src->strides, src->suboffsets, -: 433: mem); -: 434: 8040448: 435: if (mem) 7926234: 436: PyMem_Free(mem); -: 437: 8040448: 438: return 0; -: 439:} -: 440: -: 441:/* Initialize strides for a C-contiguous array. */ -: 442:Py_LOCAL_INLINE(void) 5300757: 443:init_strides_from_shape(Py_buffer *view) -: 444:{ -: 445: Py_ssize_t i; -: 446: -: 447: assert(view->ndim > 0); -: 448: 5300757: 449: view->strides[view->ndim-1] = view->itemsize; 6135369: 450: for (i = view->ndim-2; i >= 0; i--) 834612: 451: view->strides[i] = view->strides[i+1] * view->shape[i+1]; 5300757: 452:} -: 453: -: 454:/* Initialize strides for a Fortran-contiguous array. */ -: 455:Py_LOCAL_INLINE(void) 2764420: 456:init_fortran_strides_from_shape(Py_buffer *view) -: 457:{ -: 458: Py_ssize_t i; -: 459: -: 460: assert(view->ndim > 0); -: 461: 2764420: 462: view->strides[0] = view->itemsize; 3414516: 463: for (i = 1; i < view->ndim; i++) 650096: 464: view->strides[i] = view->strides[i-1] * view->shape[i-1]; 2764420: 465:} -: 466: -: 467:/* Copy src to a contiguous representation. order is one of 'C', 'F' (Fortran) -: 468: or 'A' (Any). Assumptions: src has PyBUF_FULL information, src->ndim >= 1, -: 469: len(mem) == src->len. */ -: 470:static int 6084262: 471:buffer_to_contiguous(char *mem, Py_buffer *src, char order) -: 472:{ -: 473: Py_buffer dest; -: 474: Py_ssize_t *strides; -: 475: int ret; -: 476: -: 477: assert(src->ndim >= 1); -: 478: assert(src->shape != NULL); -: 479: assert(src->strides != NULL); -: 480: 6084262: 481: strides = PFUNC_NOEX(PyMem_Malloc(src->ndim * (sizeof *src->strides))); 6084262: 482: if (strides == NULL) { 480: 483: PyErr_SetString(PyExc_FailAPIError, "failapi"); 480: 484: return -1; -: 485: } -: 486: -: 487: /* initialize dest */ 6083782: 488: dest = *src; 6083782: 489: dest.buf = mem; -: 490: /* shape is constant and shared: the logical representation of the -: 491: array is unaltered. */ -: 492: -: 493: /* The physical representation determined by strides (and possibly -: 494: suboffsets) may change. */ 6083782: 495: dest.strides = strides; 10081984: 496: if (order == 'C' || order == 'A') { 3998202: 497: init_strides_from_shape(&dest); -: 498: } -: 499: else { 2085580: 500: init_fortran_strides_from_shape(&dest); -: 501: } -: 502: 6083782: 503: dest.suboffsets = NULL; -: 504: 6083782: 505: ret = copy_buffer(&dest, src); -: 506: 6083782: 507: PyMem_Free(strides); 6083782: 508: return ret; -: 509:} -: 510: -: 511: -: 512:/****************************************************************************/ -: 513:/* Constructors */ -: 514:/****************************************************************************/ -: 515: -: 516:/* Initialize values that are shared with the managed buffer. */ -: 517:Py_LOCAL_INLINE(void) 77472533: 518:init_shared_values(Py_buffer *dest, const Py_buffer *src) -: 519:{ 77472533: 520: dest->obj = src->obj; 77472533: 521: dest->buf = src->buf; 77472533: 522: dest->len = src->len; 77472533: 523: dest->itemsize = src->itemsize; 77472533: 524: dest->readonly = src->readonly; 77472533: 525: dest->format = src->format ? src->format : "B"; 77472533: 526: dest->internal = src->internal; 77472533: 527:} -: 528: -: 529:/* Copy shape and strides. Reconstruct missing values. */ -: 530:static void 72052473: 531:init_shape_strides(Py_buffer *dest, const Py_buffer *src) -: 532:{ -: 533: Py_ssize_t i; -: 534: 72052473: 535: if (src->ndim == 0) { 275202: 536: dest->shape = NULL; 275202: 537: dest->strides = NULL; 275202: 538: return; -: 539: } 71777271: 540: if (src->ndim == 1) { 68875702: 541: dest->shape[0] = src->shape ? src->shape[0] : src->len / src->itemsize; 68875702: 542: dest->strides[0] = src->strides ? src->strides[0] : src->itemsize; 68875702: 543: return; -: 544: } -: 545: 11834047: 546: for (i = 0; i < src->ndim; i++) 8932478: 547: dest->shape[i] = src->shape[i]; 2901569: 548: if (src->strides) { 11750842: 549: for (i = 0; i < src->ndim; i++) 8870448: 550: dest->strides[i] = src->strides[i]; -: 551: } -: 552: else { 21175: 553: init_strides_from_shape(dest); -: 554: } -: 555:} -: 556: -: 557:Py_LOCAL_INLINE(void) 72052473: 558:init_suboffsets(Py_buffer *dest, const Py_buffer *src) -: 559:{ -: 560: Py_ssize_t i; -: 561: 72052473: 562: if (src->suboffsets == NULL) { 65029371: 563: dest->suboffsets = NULL; 65029371: 564: return; -: 565: } 14786315: 566: for (i = 0; i < src->ndim; i++) 7763213: 567: dest->suboffsets[i] = src->suboffsets[i]; -: 568:} -: 569: -: 570:/* len = product(shape) * itemsize */ -: 571:Py_LOCAL_INLINE(void) 16144: 572:init_len(Py_buffer *view) -: 573:{ -: 574: Py_ssize_t i, len; -: 575: 16144: 576: len = 1; 32298: 577: for (i = 0; i < view->ndim; i++) 16154: 578: len *= view->shape[i]; 16144: 579: len *= view->itemsize; -: 580: 16144: 581: view->len = len; 16144: 582:} -: 583: -: 584:/* Initialize memoryview buffer properties. */ -: 585:static void 68138911: 586:init_flags(PyMemoryViewObject *mv) -: 587:{ 68138911: 588: const Py_buffer *view = &mv->view; 68138911: 589: int flags = 0; -: 590: 68138911: 591: switch (view->ndim) { -: 592: case 0: 275558: 593: flags |= (_Py_MEMORYVIEW_SCALAR|_Py_MEMORYVIEW_C| -: 594: _Py_MEMORYVIEW_FORTRAN); 275558: 595: break; -: 596: case 1: 65269534: 597: if (MV_CONTIGUOUS_NDIM1(view)) 57955807: 598: flags |= (_Py_MEMORYVIEW_C|_Py_MEMORYVIEW_FORTRAN); 65269534: 599: break; -: 600: default: 2593819: 601: if (PyBuffer_IsContiguous(view, 'C')) 1461114: 602: flags |= _Py_MEMORYVIEW_C; 2593819: 603: if (PyBuffer_IsContiguous(view, 'F')) 894894: 604: flags |= _Py_MEMORYVIEW_FORTRAN; -: 605: break; -: 606: } -: 607: 68138911: 608: if (view->suboffsets) { 4058953: 609: flags |= _Py_MEMORYVIEW_PIL; 4058953: 610: flags &= ~(_Py_MEMORYVIEW_C|_Py_MEMORYVIEW_FORTRAN); -: 611: } -: 612: 68138911: 613: mv->flags = flags; 68138911: 614:} -: 615: -: 616:/* Allocate a new memoryview and perform basic initialization. New memoryviews -: 617: are exclusively created through the mbuf_add functions. */ -: 618:Py_LOCAL_INLINE(PyMemoryViewObject *) 71543581: 619:memory_alloc(int ndim) -: 620:{ -: 621: PyMemoryViewObject *mv; -: 622: 214630743: 623: mv = (PyMemoryViewObject *) 214630743: 624: PFUNC(PyObject_GC_NewVar(PyMemoryViewObject, &PyMemoryView_Type, 3*ndim)); 71543581: 625: if (mv == NULL) 7732: 626: return NULL; -: 627: 71535849: 628: mv->mbuf = NULL; 71535849: 629: mv->hash = -1; 71535849: 630: mv->flags = 0; 71535849: 631: mv->exports = 0; 71535849: 632: mv->view.ndim = ndim; 71535849: 633: mv->view.shape = mv->ob_array; 71535849: 634: mv->view.strides = mv->ob_array + ndim; 71535849: 635: mv->view.suboffsets = mv->ob_array + 2 * ndim; 71535849: 636: mv->weakreflist = NULL; -: 637: 71535849: 638: _PyObject_GC_TRACK(mv); 71535849: 639: return mv; -: 640:} -: 641: -: 642:/* -: 643: Return a new memoryview that is registered with mbuf. If src is NULL, -: 644: use mbuf->master as the underlying buffer. Otherwise, use src. -: 645: -: 646: The new memoryview has full buffer information: shape and strides -: 647: are always present, suboffsets as needed. Arrays are copied to -: 648: the memoryview's ob_array field. -: 649: */ -: 650:static PyObject * 66123201: 651:mbuf_add_view(_PyManagedBufferObject *mbuf, const Py_buffer *src) -: 652:{ -: 653: PyMemoryViewObject *mv; -: 654: Py_buffer *dest; -: 655: 66123201: 656: if (src == NULL) 64059321: 657: src = &mbuf->master; -: 658: 66123201: 659: if (src->ndim > PyBUF_MAX_NDIM) { 80: 660: PyErr_SetString(PyExc_ValueError, -: 661: "memoryview: number of dimensions must not exceed " -: 662: STRINGIZE(PyBUF_MAX_NDIM)); 80: 663: return NULL; -: 664: } -: 665: 66123121: 666: mv = memory_alloc(src->ndim); 66123121: 667: if (mv == NULL) 7332: 668: return NULL; -: 669: 66115789: 670: dest = &mv->view; 66115789: 671: init_shared_values(dest, src); 66115789: 672: init_shape_strides(dest, src); 66115789: 673: init_suboffsets(dest, src); 66115789: 674: init_flags(mv); -: 675: 66115789: 676: mv->mbuf = mbuf; 66115789: 677: Py_INCREF(mbuf); 66115789: 678: mbuf->exports++; -: 679: 66115789: 680: return (PyObject *)mv; -: 681:} -: 682: -: 683:/* Register an incomplete view: shape, strides, suboffsets and flags still -: 684: need to be initialized. Use 'ndim' instead of src->ndim to determine the -: 685: size of the memoryview's ob_array. -: 686: -: 687: Assumption: ndim <= PyBUF_MAX_NDIM. */ -: 688:static PyObject * 5420460: 689:mbuf_add_incomplete_view(_PyManagedBufferObject *mbuf, const Py_buffer *src, -: 690: int ndim) -: 691:{ -: 692: PyMemoryViewObject *mv; -: 693: Py_buffer *dest; -: 694: 5420460: 695: if (src == NULL) 1958028: 696: src = &mbuf->master; -: 697: -: 698: assert(ndim <= PyBUF_MAX_NDIM); -: 699: 5420460: 700: mv = memory_alloc(ndim); 5420460: 701: if (mv == NULL) 400: 702: return NULL; -: 703: 5420060: 704: dest = &mv->view; 5420060: 705: init_shared_values(dest, src); -: 706: 5420060: 707: mv->mbuf = mbuf; 5420060: 708: Py_INCREF(mbuf); 5420060: 709: mbuf->exports++; -: 710: 5420060: 711: return (PyObject *)mv; -: 712:} -: 713: -: 714:/* Expose a raw memory area as a view of contiguous bytes. flags can be -: 715: PyBUF_READ or PyBUF_WRITE. view->format is set to "B" (unsigned bytes). -: 716: The memoryview has complete buffer information. */ -: 717:PyObject * 29904752: 718:PyMemoryView_FromMemory(char *mem, Py_ssize_t size, int flags) -: 719:{ -: 720: _PyManagedBufferObject *mbuf; -: 721: PyObject *mv; -: 722: int readonly; -: 723: -: 724: assert(mem != NULL); -: 725: assert(flags == PyBUF_READ || flags == PyBUF_WRITE); -: 726: 29904752: 727: mbuf = mbuf_alloc(); 29904752: 728: if (mbuf == NULL) 3175: 729: return NULL; -: 730: 29901577: 731: readonly = (flags == PyBUF_WRITE) ? 0 : 1; 29901577: 732: (void)PyBuffer_FillInfo(&mbuf->master, NULL, mem, size, readonly, -: 733: PyBUF_FULL_RO); -: 734: 29901577: 735: mv = mbuf_add_view(mbuf, NULL); 29901577: 736: Py_DECREF(mbuf); -: 737: 29901577: 738: return mv; -: 739:} -: 740: -: 741:/* Create a memoryview from a given Py_buffer. For simple byte views, -: 742: PyMemoryView_FromMemory() should be used instead. -: 743: This function is the only entry point that can create a master buffer -: 744: without full information. Because of this fact init_shape_strides() -: 745: must be able to reconstruct missing values. */ -: 746:PyObject * 14525888: 747:PyMemoryView_FromBuffer(Py_buffer *info) -: 748:{ -: 749: _PyManagedBufferObject *mbuf; -: 750: PyObject *mv; -: 751: 14525888: 752: if (info->buf == NULL) { 1: 753: PyErr_SetString(PyExc_ValueError, -: 754: "PyMemoryView_FromBuffer(): info->buf must not be NULL"); 1: 755: return NULL; -: 756: } -: 757: 14525887: 758: mbuf = mbuf_alloc(); 14525887: 759: if (mbuf == NULL) 1557: 760: return NULL; -: 761: -: 762: /* info->obj is either NULL or a borrowed reference. This reference -: 763: should not be decremented in PyBuffer_Release(). */ 14524330: 764: mbuf->master = *info; 14524330: 765: mbuf->master.obj = NULL; -: 766: 14524330: 767: mv = mbuf_add_view(mbuf, NULL); 14524330: 768: Py_DECREF(mbuf); -: 769: 14524330: 770: return mv; -: 771:} -: 772: -: 773:/* Create a memoryview from an object that implements the buffer protocol. -: 774: If the object is a memoryview, the new memoryview must be registered -: 775: with the same managed buffer. Otherwise, a new managed buffer is created. */ -: 776:PyObject * 21684079: 777:PyMemoryView_FromObject(PyObject *v) -: 778:{ -: 779: _PyManagedBufferObject *mbuf; -: 780: 21684079: 781: if (PyMemoryView_Check(v)) { 2046655: 782: PyMemoryViewObject *mv = (PyMemoryViewObject *)v; 2046655: 783: CHECK_RELEASED(mv); 2046649: 784: return mbuf_add_view(mv->mbuf, &mv->view); -: 785: } 19637424: 786: else if (PyObject_CheckBuffer(v)) { -: 787: PyObject *ret; 19635988: 788: mbuf = (_PyManagedBufferObject *)_PyManagedBuffer_FromObject(v); 19635988: 789: if (mbuf == NULL) 2574: 790: return NULL; 19633414: 791: ret = mbuf_add_view(mbuf, NULL); 19633414: 792: Py_DECREF(mbuf); 19633414: 793: return ret; -: 794: } -: 795: 1436: 796: PyErr_Format(PyExc_TypeError, -: 797: "memoryview: %.200s object does not have the buffer interface", 1436: 798: Py_TYPE(v)->tp_name); 1436: 799: return NULL; -: 800:} -: 801: -: 802:/* Copy the format string from a base object that might vanish. */ -: 803:static int 1958172: 804:mbuf_copy_format(_PyManagedBufferObject *mbuf, const char *fmt) -: 805:{ 1958172: 806: if (fmt != NULL) { 1958172: 807: char *cp = PFUNC_NOEX(PyMem_Malloc(strlen(fmt)+1)); 1958172: 808: if (cp == NULL) { 144: 809: PyErr_SetString(PyExc_FailAPIError, "failapi"); 144: 810: return -1; -: 811: } 1958028: 812: mbuf->master.format = strcpy(cp, fmt); 1958028: 813: mbuf->flags |= _Py_MANAGED_BUFFER_FREE_FORMAT; -: 814: } -: 815: 1958028: 816: return 0; -: 817:} -: 818: -: 819:/* -: 820: Return a memoryview that is based on a contiguous copy of src. -: 821: Assumptions: src has PyBUF_FULL_RO information, src->ndim > 0. -: 822: -: 823: Ownership rules: -: 824: 1) As usual, the returned memoryview has a private copy -: 825: of src->shape, src->strides and src->suboffsets. -: 826: 2) src->format is copied to the master buffer and released -: 827: in mbuf_dealloc(). The releasebufferproc of the bytes -: 828: object is NULL, so it does not matter that mbuf_release() -: 829: passes the altered format pointer to PyBuffer_Release(). -: 830:*/ -: 831:static PyObject * 1958460: 832:memory_from_contiguous_copy(Py_buffer *src, char order) -: 833:{ -: 834: _PyManagedBufferObject *mbuf; -: 835: PyMemoryViewObject *mv; -: 836: PyObject *bytes; -: 837: Py_buffer *dest; -: 838: int i; -: 839: -: 840: assert(src->ndim > 0); -: 841: assert(src->shape != NULL); -: 842: 1958460: 843: bytes = PFUNC(PyBytes_FromStringAndSize(NULL, src->len)); 1958460: 844: if (bytes == NULL) 144: 845: return NULL; -: 846: 1958316: 847: mbuf = (_PyManagedBufferObject *)_PyManagedBuffer_FromObject(bytes); 1958316: 848: Py_DECREF(bytes); 1958316: 849: if (mbuf == NULL) 144: 850: return NULL; -: 851: 1958172: 852: if (mbuf_copy_format(mbuf, src->format) < 0) { 144: 853: Py_DECREF(mbuf); 144: 854: return NULL; -: 855: } -: 856: 1958028: 857: mv = (PyMemoryViewObject *)mbuf_add_incomplete_view(mbuf, NULL, src->ndim); 1958028: 858: Py_DECREF(mbuf); 1958028: 859: if (mv == NULL) 144: 860: return NULL; -: 861: 1957884: 862: dest = &mv->view; -: 863: -: 864: /* shared values are initialized correctly except for itemsize */ 1957884: 865: dest->itemsize = src->itemsize; -: 866: -: 867: /* shape and strides */ 4194910: 868: for (i = 0; i < src->ndim; i++) { 2237026: 869: dest->shape[i] = src->shape[i]; -: 870: } 3236928: 871: if (order == 'C' || order == 'A') { 1279044: 872: init_strides_from_shape(dest); -: 873: } -: 874: else { 678840: 875: init_fortran_strides_from_shape(dest); -: 876: } -: 877: /* suboffsets */ 1957884: 878: dest->suboffsets = NULL; -: 879: -: 880: /* flags */ 1957884: 881: init_flags(mv); -: 882: 1957884: 883: if (copy_buffer(dest, src) < 0) { 280: 884: Py_DECREF(mv); 280: 885: return NULL; -: 886: } -: 887: 1957604: 888: return (PyObject *)mv; -: 889:} -: 890: -: 891:/* -: 892: Return a new memoryview object based on a contiguous exporter with -: 893: buffertype={PyBUF_READ, PyBUF_WRITE} and order={'C', 'F'ortran, or 'A'ny}. -: 894: The logical structure of the input and output buffers is the same -: 895: (i.e. tolist(input) == tolist(output)), but the physical layout in -: 896: memory can be explicitly chosen. -: 897: -: 898: As usual, if buffertype=PyBUF_WRITE, the exporter's buffer must be writable, -: 899: otherwise it may be writable or read-only. -: 900: -: 901: If the exporter is already contiguous with the desired target order, -: 902: the memoryview will be directly based on the exporter. -: 903: -: 904: Otherwise, if the buffertype is PyBUF_READ, the memoryview will be -: 905: based on a new bytes object. If order={'C', 'A'ny}, use 'C' order, -: 906: 'F'ortran order otherwise. -: 907:*/ -: 908:PyObject * 2685784: 909:PyMemoryView_GetContiguous(PyObject *obj, int buffertype, char order) -: 910:{ -: 911: PyMemoryViewObject *mv; -: 912: PyObject *ret; -: 913: Py_buffer *view; -: 914: -: 915: assert(buffertype == PyBUF_READ || buffertype == PyBUF_WRITE); -: 916: assert(order == 'C' || order == 'F' || order == 'A'); -: 917: 2685784: 918: mv = (PyMemoryViewObject *)PyMemoryView_FromObject(obj); 2685784: 919: if (mv == NULL) 1586: 920: return NULL; -: 921: 2684198: 922: view = &mv->view; 2684198: 923: if (buffertype == PyBUF_WRITE && view->readonly) { 2219: 924: PyErr_SetString(PyExc_BufferError, -: 925: "underlying buffer is not writable"); 2219: 926: Py_DECREF(mv); 2219: 927: return NULL; -: 928: } -: 929: 2681979: 930: if (PyBuffer_IsContiguous(view, order)) 722311: 931: return (PyObject *)mv; -: 932: 1959668: 933: if (buffertype == PyBUF_WRITE) { 1208: 934: PyErr_SetString(PyExc_BufferError, -: 935: "writable contiguous buffer requested " -: 936: "for a non-contiguous object."); 1208: 937: Py_DECREF(mv); 1208: 938: return NULL; -: 939: } -: 940: 1958460: 941: ret = memory_from_contiguous_copy(view, order); 1958460: 942: Py_DECREF(mv); 1958460: 943: return ret; -: 944:} -: 945: -: 946: -: 947:static PyObject * 18998609: 948:memory_new(PyTypeObject *subtype, PyObject *args, PyObject *kwds) -: 949:{ -: 950: PyObject *obj; -: 951: static char *kwlist[] = {"object", NULL}; -: 952: 18998609: 953: if (!PyArg_ParseTupleAndKeywords(args, kwds, "O:memoryview", kwlist, -: 954: &obj)) { 314: 955: return NULL; -: 956: } -: 957: 18998295: 958: return PyMemoryView_FromObject(obj); -: 959:} -: 960: -: 961: -: 962:/****************************************************************************/ -: 963:/* Previously in abstract.c */ -: 964:/****************************************************************************/ -: 965: -: 966:typedef struct { -: 967: Py_buffer view; -: 968: Py_ssize_t array[1]; -: 969:} Py_buffer_full; -: 970: -: 971:int 8407368: 972:PyBuffer_ToContiguous(void *buf, Py_buffer *src, Py_ssize_t len, char order) -: 973:{ 8407368: 974: Py_buffer_full *fb = NULL; -: 975: int ret; -: 976: -: 977: assert(order == 'C' || order == 'F' || order == 'A'); -: 978: 8407368: 979: if (FFUNC_NOEX(-1, len) != src->len) { 1055: 980: PyErr_SetString(PyExc_FailAPIError, -: 981: "PyBuffer_ToContiguous: len != view->len"); 1055: 982: return -1; -: 983: } -: 984: 8406313: 985: if (PyBuffer_IsContiguous(src, order)) { 2469173: 986: memcpy((char *)buf, src->buf, len); 2469173: 987: return 0; -: 988: } -: 989: -: 990: /* buffer_to_contiguous() assumes PyBUF_FULL */ 5937140: 991: fb = PFUNC_NOEX(PyMem_Malloc(sizeof *fb + 3 * src->ndim * (sizeof *fb->array))); 5937140: 992: if (fb == NULL) { 456: 993: PyErr_SetString(PyExc_FailAPIError, "failapi"); 456: 994: return -1; -: 995: } 5936684: 996: fb->view.ndim = src->ndim; 5936684: 997: fb->view.shape = fb->array; 5936684: 998: fb->view.strides = fb->array + src->ndim; 5936684: 999: fb->view.suboffsets = fb->array + 2 * src->ndim; -: 1000: 5936684: 1001: init_shared_values(&fb->view, src); 5936684: 1002: init_shape_strides(&fb->view, src); 5936684: 1003: init_suboffsets(&fb->view, src); -: 1004: 5936684: 1005: src = &fb->view; -: 1006: 5936684: 1007: ret = buffer_to_contiguous(buf, src, order); 5936684: 1008: PyMem_Free(fb); 5936684: 1009: return ret; -: 1010:} -: 1011: -: 1012: -: 1013:/****************************************************************************/ -: 1014:/* Release/GC management */ -: 1015:/****************************************************************************/ -: 1016: -: 1017:/* Inform the managed buffer that this particular memoryview will not access -: 1018: the underlying buffer again. If no other memoryviews are registered with -: 1019: the managed buffer, the underlying buffer is released instantly and -: 1020: marked as inaccessible for both the memoryview and the managed buffer. -: 1021: -: 1022: This function fails if the memoryview itself has exported buffers. */ -: 1023:static int 71538726: 1024:_memory_release(PyMemoryViewObject *self) -: 1025:{ 71538726: 1026: if (self->flags & _Py_MEMORYVIEW_RELEASED) 2310: 1027: return 0; -: 1028: 71536416: 1029: if (self->exports == 0) { 71535849: 1030: self->flags |= _Py_MEMORYVIEW_RELEASED; -: 1031: assert(self->mbuf->exports > 0); 71535849: 1032: if (--self->mbuf->exports == 0) 66010395: 1033: mbuf_release(self->mbuf); 71535849: 1034: return 0; -: 1035: } 567: 1036: if (self->exports > 0) { 567: 1037: PyErr_Format(PyExc_BufferError, -: 1038: "memoryview has %zd exported buffer%s", self->exports, 567: 1039: self->exports==1 ? "" : "s"); 567: 1040: return -1; -: 1041: } -: 1042: #####: 1043: Py_FatalError("_memory_release(): negative export count"); #####: 1044: return -1; -: 1045:} -: 1046: -: 1047:static PyObject * 2877: 1048:memory_release(PyMemoryViewObject *self, PyObject *noargs) -: 1049:{ 2877: 1050: if (_memory_release(self) < 0) 567: 1051: return NULL; 2310: 1052: Py_RETURN_NONE; -: 1053:} -: 1054: -: 1055:static void 71535849: 1056:memory_dealloc(PyMemoryViewObject *self) -: 1057:{ -: 1058: assert(self->exports == 0); 71535849: 1059: _PyObject_GC_UNTRACK(self); 71535849: 1060: (void)_memory_release(self); 71535849: 1061: Py_CLEAR(self->mbuf); 71535849: 1062: if (self->weakreflist != NULL) 19: 1063: PyObject_ClearWeakRefs((PyObject *) self); 71535849: 1064: PyObject_GC_Del(self); 71535849: 1065:} -: 1066: -: 1067:static int 9944: 1068:memory_traverse(PyMemoryViewObject *self, visitproc visit, void *arg) -: 1069:{ 9944: 1070: Py_VISIT(self->mbuf); 9944: 1071: return 0; -: 1072:} -: 1073: -: 1074:static int #####: 1075:memory_clear(PyMemoryViewObject *self) -: 1076:{ #####: 1077: (void)_memory_release(self); #####: 1078: Py_CLEAR(self->mbuf); #####: 1079: return 0; -: 1080:} -: 1081: -: 1082:static PyObject * 426: 1083:memory_enter(PyObject *self, PyObject *args) -: 1084:{ 426: 1085: CHECK_RELEASED(self); 225: 1086: Py_INCREF(self); 225: 1087: return self; -: 1088:} -: 1089: -: 1090:static PyObject * 225: 1091:memory_exit(PyObject *self, PyObject *args) -: 1092:{ 225: 1093: return memory_release((PyMemoryViewObject *)self, NULL); -: 1094:} -: 1095: -: 1096: -: 1097:/****************************************************************************/ -: 1098:/* Casting format and shape */ -: 1099:/****************************************************************************/ -: 1100: -: 1101:#define IS_BYTE_FORMAT(f) (f == 'b' || f == 'B' || f == 'c') -: 1102: -: 1103:Py_LOCAL_INLINE(Py_ssize_t) 23489904: 1104:get_native_fmtchar(char *result, const char *fmt) -: 1105:{ 23489904: 1106: Py_ssize_t size = -1; -: 1107: 23489904: 1108: if (fmt[0] == '@') fmt++; -: 1109: 23489904: 1110: switch (fmt[0]) { 3175562: 1111: case 'c': case 'b': case 'B': size = sizeof(char); break; 1271110: 1112: case 'h': case 'H': size = sizeof(short); break; 1026382: 1113: case 'i': case 'I': size = sizeof(int); break; 1055765: 1114: case 'l': case 'L': size = sizeof(long); break; -: 1115: #ifdef HAVE_LONG_LONG 762170: 1116: case 'q': case 'Q': size = sizeof(PY_LONG_LONG); break; -: 1117: #endif 1083985: 1118: case 'n': case 'N': size = sizeof(Py_ssize_t); break; 474526: 1119: case 'f': size = sizeof(float); break; 500924: 1120: case 'd': size = sizeof(double); break; -: 1121: #ifdef HAVE_C99_BOOL 438767: 1122: case '?': size = sizeof(_Bool); break; -: 1123: #else -: 1124: case '?': size = sizeof(char); break; -: 1125: #endif 428388: 1126: case 'P': size = sizeof(void *); break; -: 1127: } -: 1128: 23489904: 1129: if (size > 0 && fmt[1] == '\0') { 10190854: 1130: *result = fmt[0]; 10190854: 1131: return size; -: 1132: } -: 1133: 13299050: 1134: return -1; -: 1135:} -: 1136: -: 1137:/* Cast a memoryview's data type to 'format'. The input array must be -: 1138: C-contiguous. At least one of input-format, output-format must have -: 1139: byte size. The output array is 1-D, with the same byte length as the -: 1140: input array. Thus, view->len must be a multiple of the new itemsize. */ -: 1141:static int 3462176: 1142:cast_to_1D(PyMemoryViewObject *mv, PyObject *format) -: 1143:{ 3462176: 1144: Py_buffer *view = &mv->view; -: 1145: PyObject *asciifmt; -: 1146: char srcchar, destchar; -: 1147: Py_ssize_t itemsize; 3462176: 1148: int ret = -1; -: 1149: -: 1150: assert(view->ndim >= 1); -: 1151: assert(Py_SIZE(mv) == 3*view->ndim); -: 1152: assert(view->shape == mv->ob_array); -: 1153: assert(view->strides == mv->ob_array + view->ndim); -: 1154: assert(view->suboffsets == mv->ob_array + 2*view->ndim); -: 1155: 3462176: 1156: if (get_native_fmtchar(&srcchar, view->format) < 0) { 34892: 1157: PyErr_SetString(PyExc_ValueError, -: 1158: "memoryview: source format must be a native single character " -: 1159: "format prefixed with an optional '@'"); 34892: 1160: return ret; -: 1161: } -: 1162: 3427284: 1163: asciifmt = PFUNC(PyUnicode_AsASCIIString(format)); 3427284: 1164: if (asciifmt == NULL) 252: 1165: return ret; -: 1166: 3427032: 1167: itemsize = get_native_fmtchar(&destchar, PyBytes_AS_STRING(asciifmt)); 3427032: 1168: if (itemsize < 0) { 75276: 1169: PyErr_SetString(PyExc_ValueError, -: 1170: "memoryview: destination format must be a native single " -: 1171: "character format prefixed with an optional '@'"); 75276: 1172: goto out; -: 1173: } -: 1174: 3351756: 1175: if (!IS_BYTE_FORMAT(srcchar) && !IS_BYTE_FORMAT(destchar)) { 3301914: 1176: PyErr_SetString(PyExc_TypeError, -: 1177: "memoryview: cannot cast between two non-byte formats"); 3301914: 1178: goto out; -: 1179: } 49842: 1180: if (view->len % itemsize) { 2882: 1181: PyErr_SetString(PyExc_TypeError, -: 1182: "memoryview: length is not a multiple of itemsize"); 2882: 1183: goto out; -: 1184: } -: 1185: 46960: 1186: strncpy(mv->format, PyBytes_AS_STRING(asciifmt), -: 1187: _Py_MEMORYVIEW_MAX_FORMAT); 46960: 1188: mv->format[_Py_MEMORYVIEW_MAX_FORMAT-1] = '\0'; 46960: 1189: view->format = mv->format; 46960: 1190: view->itemsize = itemsize; -: 1191: 46960: 1192: view->ndim = 1; 46960: 1193: view->shape[0] = view->len / view->itemsize; 46960: 1194: view->strides[0] = view->itemsize; 46960: 1195: view->suboffsets = NULL; -: 1196: 46960: 1197: init_flags(mv); -: 1198: 46960: 1199: ret = 0; -: 1200: -: 1201:out: 3427032: 1202: Py_DECREF(asciifmt); 3427032: 1203: return ret; -: 1204:} -: 1205: -: 1206:/* The memoryview must have space for 3*len(seq) elements. */ -: 1207:static Py_ssize_t 41415: 1208:copy_shape(Py_ssize_t *shape, const PyObject *seq, Py_ssize_t ndim, -: 1209: Py_ssize_t itemsize) -: 1210:{ -: 1211: Py_ssize_t x, i; 41415: 1212: Py_ssize_t len = itemsize; -: 1213: 187432: 1214: for (i = 0; i < ndim; i++) { 185096: 1215: PyObject *tmp = PySequence_Fast_GET_ITEM(seq, i); 185096: 1216: if (!PyLong_Check(tmp)) { 7811: 1217: PyErr_SetString(PyExc_TypeError, -: 1218: "memoryview.cast(): elements of shape must be integers"); 7811: 1219: return -1; -: 1220: } 177285: 1221: x = PyLong_AsSsize_t(tmp); 177285: 1222: if (x == -1 && PyErr_Occurred()) { 7819: 1223: return -1; -: 1224: } 169466: 1225: if (x <= 0) { -: 1226: /* In general elements of shape may be 0, but not for casting. */ 23445: 1227: PyErr_Format(PyExc_ValueError, -: 1228: "memoryview.cast(): elements of shape must be integers > 0"); 23445: 1229: return -1; -: 1230: } 146021: 1231: if (x > PY_SSIZE_T_MAX / len) { 4: 1232: PyErr_Format(PyExc_ValueError, -: 1233: "memoryview.cast(): product(shape) > SSIZE_MAX"); 4: 1234: return -1; -: 1235: } 146017: 1236: len *= x; 146017: 1237: shape[i] = x; -: 1238: } -: 1239: 2336: 1240: return len; -: 1241:} -: 1242: -: 1243:/* Cast a 1-D array to a new shape. The result array will be C-contiguous. -: 1244: If the result array does not have exactly the same byte length as the -: 1245: input array, raise ValueError. */ -: 1246:static int 41771: 1247:cast_to_ND(PyMemoryViewObject *mv, const PyObject *shape, int ndim) -: 1248:{ 41771: 1249: Py_buffer *view = &mv->view; -: 1250: Py_ssize_t len; -: 1251: -: 1252: assert(view->ndim == 1); /* ndim from cast_to_1D() */ -: 1253: assert(Py_SIZE(mv) == 3*(ndim==0?1:ndim)); /* ndim of result array */ -: 1254: assert(view->shape == mv->ob_array); -: 1255: assert(view->strides == mv->ob_array + (ndim==0?1:ndim)); -: 1256: assert(view->suboffsets == NULL); -: 1257: 41771: 1258: view->ndim = ndim; 41771: 1259: if (view->ndim == 0) { 356: 1260: view->shape = NULL; 356: 1261: view->strides = NULL; 356: 1262: len = view->itemsize; -: 1263: } -: 1264: else { 41415: 1265: len = copy_shape(view->shape, shape, ndim, view->itemsize); 41415: 1266: if (len < 0) 39079: 1267: return -1; 2336: 1268: init_strides_from_shape(view); -: 1269: } -: 1270: 2692: 1271: if (view->len != len) { 558: 1272: PyErr_SetString(PyExc_TypeError, -: 1273: "memoryview: product(shape) * itemsize != buffer size"); 558: 1274: return -1; -: 1275: } -: 1276: 2134: 1277: init_flags(mv); -: 1278: 2134: 1279: return 0; -: 1280:} -: 1281: -: 1282:static int 3490843: 1283:zero_in_shape(PyMemoryViewObject *mv) -: 1284:{ 3490843: 1285: Py_buffer *view = &mv->view; -: 1286: Py_ssize_t i; -: 1287: 7355196: 1288: for (i = 0; i < view->ndim; i++) 3864428: 1289: if (view->shape[i] == 0) 75: 1290: return 1; -: 1291: 3490768: 1292: return 0; -: 1293:} -: 1294: -: 1295:/* -: 1296: Cast a copy of 'self' to a different view. The input view must -: 1297: be C-contiguous. The function always casts the input view to a -: 1298: 1-D output according to 'format'. At least one of input-format, -: 1299: output-format must have byte size. -: 1300: -: 1301: If 'shape' is given, the 1-D view from the previous step will -: 1302: be cast to a C-contiguous view with new shape and strides. -: 1303: -: 1304: All casts must result in views that will have the exact byte -: 1305: size of the original input. Otherwise, an error is raised. -: 1306:*/ -: 1307:static PyObject * 3515972: 1308:memory_cast(PyMemoryViewObject *self, PyObject *args, PyObject *kwds) -: 1309:{ -: 1310: static char *kwlist[] = {"format", "shape", NULL}; 3515972: 1311: PyMemoryViewObject *mv = NULL; 3515972: 1312: PyObject *shape = NULL; -: 1313: PyObject *format; 3515972: 1314: Py_ssize_t ndim = 1; -: 1315: 3515972: 1316: CHECK_RELEASED(self); -: 1317: 3515966: 1318: if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|O", kwlist, -: 1319: &format, &shape)) { 16748: 1320: return NULL; -: 1321: } 3499218: 1322: if (!PyUnicode_Check(format)) { 8374: 1323: PyErr_SetString(PyExc_TypeError, -: 1324: "memoryview: format argument must be a string"); 8374: 1325: return NULL; -: 1326: } 3490844: 1327: if (!MV_C_CONTIGUOUS(self->flags)) { 1: 1328: PyErr_SetString(PyExc_TypeError, -: 1329: "memoryview: casts are restricted to C-contiguous views"); 1: 1330: return NULL; -: 1331: } 3490843: 1332: if (zero_in_shape(self)) { 75: 1333: PyErr_SetString(PyExc_TypeError, -: 1334: "memoryview: cannot cast view with zeros in shape or strides"); 75: 1335: return NULL; -: 1336: } 3490768: 1337: if (shape) { 3410223: 1338: CHECK_LIST_OR_TUPLE(shape) 3402145: 1339: ndim = PySequence_Fast_GET_SIZE(shape); 3402145: 1340: if (ndim > PyBUF_MAX_NDIM) { 5211: 1341: PyErr_SetString(PyExc_ValueError, -: 1342: "memoryview: number of dimensions must not exceed " -: 1343: STRINGIZE(PyBUF_MAX_NDIM)); 5211: 1344: return NULL; -: 1345: } 3396934: 1346: if (self->view.ndim != 1 && ndim != 1) { 15047: 1347: PyErr_SetString(PyExc_TypeError, -: 1348: "memoryview: cast must be 1D -> ND or ND -> 1D"); 15047: 1349: return NULL; -: 1350: } -: 1351: } -: 1352: 6924864: 1353: mv = (PyMemoryViewObject *) 3462432: 1354: mbuf_add_incomplete_view(self->mbuf, &self->view, ndim==0 ? 1 : (int)ndim); 3462432: 1355: if (mv == NULL) 256: 1356: return NULL; -: 1357: 3462176: 1358: if (cast_to_1D(mv, format) < 0) 3415216: 1359: goto error; 46960: 1360: if (shape && cast_to_ND(mv, shape, (int)ndim) < 0) 39637: 1361: goto error; -: 1362: 7323: 1363: return (PyObject *)mv; -: 1364: -: 1365:error: 3454853: 1366: Py_DECREF(mv); 3454853: 1367: return NULL; -: 1368:} -: 1369: -: 1370: -: 1371:/**************************************************************************/ -: 1372:/* getbuffer */ -: 1373:/**************************************************************************/ -: 1374: -: 1375:static int 630061511: 1376:memory_getbuf(PyMemoryViewObject *self, Py_buffer *view, int flags) -: 1377:{ 630061511: 1378: Py_buffer *base = &self->view; 630061511: 1379: int baseflags = self->flags; -: 1380: 630061511: 1381: CHECK_RELEASED_INT(self); -: 1382: -: 1383: /* start with complete information */ 630061305: 1384: *view = *base; 630061305: 1385: view->obj = NULL; -: 1386: 630061305: 1387: if (REQ_WRITABLE(flags) && base->readonly) { 264: 1388: PyErr_SetString(PyExc_BufferError, -: 1389: "memoryview: underlying buffer is not writable"); 264: 1390: return -1; -: 1391: } 630061041: 1392: if (!REQ_FORMAT(flags)) { -: 1393: /* NULL indicates that the buffer's data type has been cast to 'B'. -: 1394: view->itemsize is the _previous_ itemsize. If shape is present, -: 1395: the equality product(shape) * itemsize = len still holds at this -: 1396: point. The equality calcsize(format) = itemsize does _not_ hold -: 1397: from here on! */ 622435292: 1398: view->format = NULL; -: 1399: } -: 1400: 630061041: 1401: if (REQ_C_CONTIGUOUS(flags) && !MV_C_CONTIGUOUS(baseflags)) { 218: 1402: PyErr_SetString(PyExc_BufferError, -: 1403: "memoryview: underlying buffer is not C-contiguous"); 218: 1404: return -1; -: 1405: } 630060823: 1406: if (REQ_F_CONTIGUOUS(flags) && !MV_F_CONTIGUOUS(baseflags)) { 175: 1407: PyErr_SetString(PyExc_BufferError, -: 1408: "memoryview: underlying buffer is not Fortran contiguous"); 175: 1409: return -1; -: 1410: } 630060648: 1411: if (REQ_ANY_CONTIGUOUS(flags) && !MV_ANY_CONTIGUOUS(baseflags)) { 132: 1412: PyErr_SetString(PyExc_BufferError, -: 1413: "memoryview: underlying buffer is not contiguous"); 132: 1414: return -1; -: 1415: } 630060516: 1416: if (!REQ_INDIRECT(flags) && (baseflags & _Py_MEMORYVIEW_PIL)) { 87: 1417: PyErr_SetString(PyExc_BufferError, -: 1418: "memoryview: underlying buffer requires suboffsets"); 87: 1419: return -1; -: 1420: } 630060429: 1421: if (!REQ_STRIDES(flags)) { 622434681: 1422: if (!MV_C_CONTIGUOUS(baseflags)) { 44: 1423: PyErr_SetString(PyExc_BufferError, -: 1424: "memoryview: underlying buffer is not C-contiguous"); 44: 1425: return -1; -: 1426: } 622434637: 1427: view->strides = NULL; -: 1428: } 630060385: 1429: if (!REQ_SHAPE(flags)) { -: 1430: /* PyBUF_SIMPLE or PyBUF_WRITABLE: at this point buf is C-contiguous, -: 1431: so base->buf = ndbuf->data. */ 622434594: 1432: if (view->format != NULL) { -: 1433: /* PyBUF_SIMPLE|PyBUF_FORMAT and PyBUF_WRITABLE|PyBUF_FORMAT do -: 1434: not make sense. */ 1: 1435: PyErr_Format(PyExc_BufferError, -: 1436: "ndarray: cannot cast to unsigned bytes if the format flag " -: 1437: "is present"); 1: 1438: return -1; -: 1439: } -: 1440: /* product(shape) * itemsize = len and calcsize(format) = itemsize -: 1441: do _not_ hold from here on! */ 622434593: 1442: view->ndim = 1; 622434593: 1443: view->shape = NULL; -: 1444: } -: 1445: -: 1446: 630060384: 1447: view->obj = (PyObject *)self; 630060384: 1448: Py_INCREF(view->obj); 630060384: 1449: self->exports++; -: 1450: 630060384: 1451: return 0; -: 1452:} -: 1453: -: 1454:static void 630060384: 1455:memory_releasebuf(PyMemoryViewObject *self, Py_buffer *view) -: 1456:{ 630060384: 1457: self->exports--; -: 1458: return; -: 1459: /* PyBuffer_Release() decrements view->obj after this function returns. */ -: 1460:} -: 1461: -: 1462:/* Buffer methods */ -: 1463:static PyBufferProcs memory_as_buffer = { -: 1464: (getbufferproc)memory_getbuf, /* bf_getbuffer */ -: 1465: (releasebufferproc)memory_releasebuf, /* bf_releasebuffer */ -: 1466:}; -: 1467: -: 1468: -: 1469:/****************************************************************************/ -: 1470:/* Optimized pack/unpack for all native format specifiers */ -: 1471:/****************************************************************************/ -: 1472: -: 1473:/* -: 1474: Fix exceptions: -: 1475: 1) Include format string in the error message. -: 1476: 2) OverflowError -> ValueError. -: 1477: 3) The error message from PyNumber_Index() is not ideal. -: 1478:*/ -: 1479:static int 1940: 1480:type_error_int(const char *fmt) -: 1481:{ 1940: 1482: PyErr_Format(PyExc_TypeError, -: 1483: "memoryview: invalid type for format '%s'", fmt); 1940: 1484: return -1; -: 1485:} -: 1486: -: 1487:static int 2929: 1488:value_error_int(const char *fmt) -: 1489:{ 2929: 1490: PyErr_Format(PyExc_ValueError, -: 1491: "memoryview: invalid value for format '%s'", fmt); 2929: 1492: return -1; -: 1493:} -: 1494: -: 1495:static int 3478: 1496:fix_error_int(const char *fmt) -: 1497:{ -: 1498: assert(PyErr_Occurred()); 3478: 1499: if (PyErr_ExceptionMatches(PyExc_TypeError)) { 1570: 1500: PyErr_Clear(); 1570: 1501: return type_error_int(fmt); -: 1502: } 1908: 1503: else if (PyErr_ExceptionMatches(PyExc_OverflowError) || #####: 1504: PyErr_ExceptionMatches(PyExc_ValueError)) { 1908: 1505: PyErr_Clear(); 1908: 1506: return value_error_int(fmt); -: 1507: } -: 1508: #####: 1509: return -1; -: 1510:} -: 1511: -: 1512:/* Accept integer objects or objects with an __index__() method. */ -: 1513:static long 4255: 1514:pylong_as_ld(PyObject *item) -: 1515:{ -: 1516: PyObject *tmp; -: 1517: long ld; -: 1518: 4255: 1519: tmp = PyNumber_Index(item); 4255: 1520: if (tmp == NULL) 430: 1521: return -1; -: 1522: 3825: 1523: ld = PyLong_AsLong(tmp); 3825: 1524: Py_DECREF(tmp); 3825: 1525: return ld; -: 1526:} -: 1527: -: 1528:static unsigned long 8416: 1529:pylong_as_lu(PyObject *item) -: 1530:{ -: 1531: PyObject *tmp; -: 1532: unsigned long lu; -: 1533: 8416: 1534: tmp = PyNumber_Index(item); 8416: 1535: if (tmp == NULL) 574: 1536: return (unsigned long)-1; -: 1537: 7842: 1538: lu = PyLong_AsUnsignedLong(tmp); 7842: 1539: Py_DECREF(tmp); 7842: 1540: return lu; -: 1541:} -: 1542: -: 1543:#ifdef HAVE_LONG_LONG -: 1544:static PY_LONG_LONG 687: 1545:pylong_as_lld(PyObject *item) -: 1546:{ -: 1547: PyObject *tmp; -: 1548: PY_LONG_LONG lld; -: 1549: 687: 1550: tmp = PyNumber_Index(item); 687: 1551: if (tmp == NULL) 82: 1552: return -1; -: 1553: 605: 1554: lld = PyLong_AsLongLong(tmp); 605: 1555: Py_DECREF(tmp); 605: 1556: return lld; -: 1557:} -: 1558: -: 1559:static unsigned PY_LONG_LONG 2215: 1560:pylong_as_llu(PyObject *item) -: 1561:{ -: 1562: PyObject *tmp; -: 1563: unsigned PY_LONG_LONG llu; -: 1564: 2215: 1565: tmp = PyNumber_Index(item); 2215: 1566: if (tmp == NULL) 84: 1567: return (unsigned PY_LONG_LONG)-1; -: 1568: 2131: 1569: llu = PyLong_AsUnsignedLongLong(tmp); 2131: 1570: Py_DECREF(tmp); 2131: 1571: return llu; -: 1572:} -: 1573:#endif -: 1574: -: 1575:static Py_ssize_t 1031: 1576:pylong_as_zd(PyObject *item) -: 1577:{ -: 1578: PyObject *tmp; -: 1579: Py_ssize_t zd; -: 1580: 1031: 1581: tmp = PyNumber_Index(item); 1031: 1582: if (tmp == NULL) 103: 1583: return -1; -: 1584: 928: 1585: zd = PyLong_AsSsize_t(tmp); 928: 1586: Py_DECREF(tmp); 928: 1587: return zd; -: 1588:} -: 1589: -: 1590:static size_t 1065: 1591:pylong_as_zu(PyObject *item) -: 1592:{ -: 1593: PyObject *tmp; -: 1594: size_t zu; -: 1595: 1065: 1596: tmp = PyNumber_Index(item); 1065: 1597: if (tmp == NULL) 105: 1598: return (size_t)-1; -: 1599: 960: 1600: zu = PyLong_AsSize_t(tmp); 960: 1601: Py_DECREF(tmp); 960: 1602: return zu; -: 1603:} -: 1604: -: 1605:/* Timings with the ndarray from _testbuffer.c indicate that using the -: 1606: struct module is around 15x slower than the two functions below. */ -: 1607: -: 1608:#define UNPACK_SINGLE(dest, ptr, type) \ -: 1609: do { \ -: 1610: type x; \ -: 1611: memcpy((char *)&x, ptr, sizeof x); \ -: 1612: dest = x; \ -: 1613: } while (0) -: 1614: -: 1615:/* Unpack a single item. 'fmt' can be any native format character in struct -: 1616: module syntax. This function is very sensitive to small changes. With this -: 1617: layout gcc automatically generates a fast jump table. */ -: 1618:Py_LOCAL_INLINE(PyObject *) 12817332: 1619:unpack_single(const char *ptr, const char *fmt) -: 1620:{ -: 1621: unsigned PY_LONG_LONG llu; -: 1622: unsigned long lu; -: 1623: size_t zu; -: 1624: PY_LONG_LONG lld; -: 1625: long ld; -: 1626: Py_ssize_t zd; -: 1627: double d; -: 1628: unsigned char uc; -: 1629: void *p; -: 1630: 12817332: 1631: switch (fmt[0]) { -: 1632: -: 1633: /* signed integers and fast path for 'B' */ 4034573: 1634: case 'B': uc = *((unsigned char *)ptr); goto convert_uc; 257133: 1635: case 'b': ld = *((signed char *)ptr); goto convert_ld; 137540: 1636: case 'h': UNPACK_SINGLE(ld, ptr, short); goto convert_ld; 1895: 1637: case 'i': UNPACK_SINGLE(ld, ptr, int); goto convert_ld; 1565: 1638: case 'l': UNPACK_SINGLE(ld, ptr, long); goto convert_ld; -: 1639: -: 1640: /* boolean */ -: 1641: #ifdef HAVE_C99_BOOL 38317: 1642: case '?': UNPACK_SINGLE(ld, ptr, _Bool); goto convert_bool; -: 1643: #else -: 1644: case '?': UNPACK_SINGLE(ld, ptr, char); goto convert_bool; -: 1645: #endif -: 1646: -: 1647: /* unsigned integers */ 5691: 1648: case 'H': UNPACK_SINGLE(lu, ptr, unsigned short); goto convert_lu; 2099: 1649: case 'I': UNPACK_SINGLE(lu, ptr, unsigned int); goto convert_lu; 7907215: 1650: case 'L': UNPACK_SINGLE(lu, ptr, unsigned long); goto convert_lu; -: 1651: -: 1652: /* native 64-bit */ -: 1653: #ifdef HAVE_LONG_LONG 1602: 1654: case 'q': UNPACK_SINGLE(lld, ptr, PY_LONG_LONG); goto convert_lld; 5129: 1655: case 'Q': UNPACK_SINGLE(llu, ptr, unsigned PY_LONG_LONG); goto convert_llu; -: 1656: #endif -: 1657: -: 1658: /* ssize_t and size_t */ 21237: 1659: case 'n': UNPACK_SINGLE(zd, ptr, Py_ssize_t); goto convert_zd; 4831: 1660: case 'N': UNPACK_SINGLE(zu, ptr, size_t); goto convert_zu; -: 1661: -: 1662: /* floats */ 37236: 1663: case 'f': UNPACK_SINGLE(d, ptr, float); goto convert_double; 1493: 1664: case 'd': UNPACK_SINGLE(d, ptr, double); goto convert_double; -: 1665: -: 1666: /* bytes object */ 358637: 1667: case 'c': goto convert_bytes; -: 1668: -: 1669: /* pointer */ 1106: 1670: case 'P': UNPACK_SINGLE(p, ptr, void *); goto convert_pointer; -: 1671: -: 1672: /* default */ 33: 1673: default: goto err_format; -: 1674: } -: 1675: -: 1676:convert_uc: -: 1677: /* PyLong_FromUnsignedLong() is slower */ 4034573: 1678: return PyLong_FromLong(uc); -: 1679:convert_ld: 398133: 1680: return PyLong_FromLong(ld); -: 1681:convert_lu: 7915005: 1682: return PyLong_FromUnsignedLong(lu); -: 1683:convert_lld: 1602: 1684: return PyLong_FromLongLong(lld); -: 1685:convert_llu: 5129: 1686: return PyLong_FromUnsignedLongLong(llu); -: 1687:convert_zd: 21237: 1688: return PyLong_FromSsize_t(zd); -: 1689:convert_zu: 4831: 1690: return PyLong_FromSize_t(zu); -: 1691:convert_double: 38729: 1692: return PyFloat_FromDouble(d); -: 1693:convert_bool: 38317: 1694: return PyBool_FromLong(ld); -: 1695:convert_bytes: 358637: 1696: return PyBytes_FromStringAndSize(ptr, 1); -: 1697:convert_pointer: 1106: 1698: return PyLong_FromVoidPtr(p); -: 1699:err_format: 33: 1700: PyErr_Format(PyExc_NotImplementedError, -: 1701: "memoryview: format %s not supported", fmt); 33: 1702: return NULL; -: 1703:} -: 1704: -: 1705:#define PACK_SINGLE(ptr, src, type) \ -: 1706: do { \ -: 1707: type x; \ -: 1708: x = (type)src; \ -: 1709: memcpy(ptr, (char *)&x, sizeof x); \ -: 1710: } while (0) -: 1711: -: 1712:/* Pack a single item. 'fmt' can be any native format character in -: 1713: struct module syntax. */ -: 1714:static int 23295: 1715:pack_single(char *ptr, PyObject *item, const char *fmt) -: 1716:{ -: 1717: unsigned PY_LONG_LONG llu; -: 1718: unsigned long lu; -: 1719: size_t zu; -: 1720: PY_LONG_LONG lld; -: 1721: long ld; -: 1722: Py_ssize_t zd; -: 1723: double d; -: 1724: void *p; -: 1725: 23295: 1726: switch (fmt[0]) { -: 1727: /* signed integers */ -: 1728: case 'b': case 'h': case 'i': case 'l': 4255: 1729: ld = pylong_as_ld(item); 4255: 1730: if (ld == -1 && PyErr_Occurred()) 644: 1731: goto err_occurred; 3611: 1732: switch (fmt[0]) { -: 1733: case 'b': 972: 1734: if (ld < SCHAR_MIN || ld > SCHAR_MAX) goto err_range; 774: 1735: *((signed char *)ptr) = (signed char)ld; break; -: 1736: case 'h': 1056: 1737: if (ld < SHRT_MIN || ld > SHRT_MAX) goto err_range; 834: 1738: PACK_SINGLE(ptr, ld, short); break; -: 1739: case 'i': 805: 1740: if (ld < INT_MIN || ld > INT_MAX) goto err_range; 619: 1741: PACK_SINGLE(ptr, ld, int); break; -: 1742: default: /* 'l' */ 778: 1743: PACK_SINGLE(ptr, ld, long); break; -: 1744: } 3005: 1745: break; -: 1746: -: 1747: /* unsigned integers */ -: 1748: case 'B': case 'H': case 'I': case 'L': 8416: 1749: lu = pylong_as_lu(item); 8416: 1750: if (lu == (unsigned long)-1 && PyErr_Occurred()) 1046: 1751: goto err_occurred; 7370: 1752: switch (fmt[0]) { -: 1753: case 'B': 1339: 1754: if (lu > UCHAR_MAX) goto err_range; 1214: 1755: *((unsigned char *)ptr) = (unsigned char)lu; break; -: 1756: case 'H': 915: 1757: if (lu > USHRT_MAX) goto err_range; 806: 1758: PACK_SINGLE(ptr, lu, unsigned short); break; -: 1759: case 'I': 795: 1760: if (lu > UINT_MAX) goto err_range; 694: 1761: PACK_SINGLE(ptr, lu, unsigned int); break; -: 1762: default: /* 'L' */ 4321: 1763: PACK_SINGLE(ptr, lu, unsigned long); break; -: 1764: } 7035: 1765: break; -: 1766: -: 1767: /* native 64-bit */ -: 1768: #ifdef HAVE_LONG_LONG -: 1769: case 'q': 687: 1770: lld = pylong_as_lld(item); 687: 1771: if (lld == -1 && PyErr_Occurred()) 246: 1772: goto err_occurred; 441: 1773: PACK_SINGLE(ptr, lld, PY_LONG_LONG); 441: 1774: break; -: 1775: case 'Q': 2215: 1776: llu = pylong_as_llu(item); 2215: 1777: if (llu == (unsigned PY_LONG_LONG)-1 && PyErr_Occurred()) 252: 1778: goto err_occurred; 1963: 1779: PACK_SINGLE(ptr, llu, unsigned PY_LONG_LONG); 1963: 1780: break; -: 1781: #endif -: 1782: -: 1783: /* ssize_t and size_t */ -: 1784: case 'n': 1031: 1785: zd = pylong_as_zd(item); 1031: 1786: if (zd == -1 && PyErr_Occurred()) 309: 1787: goto err_occurred; 722: 1788: PACK_SINGLE(ptr, zd, Py_ssize_t); 722: 1789: break; -: 1790: case 'N': 1065: 1791: zu = pylong_as_zu(item); 1065: 1792: if (zu == (size_t)-1 && PyErr_Occurred()) 315: 1793: goto err_occurred; 750: 1794: PACK_SINGLE(ptr, zu, size_t); 750: 1795: break; -: 1796: -: 1797: /* floats */ -: 1798: case 'f': case 'd': 3686: 1799: d = PyFloat_AsDouble(item); 3686: 1800: if (d == -1.0 && PyErr_Occurred()) 576: 1801: goto err_occurred; 3110: 1802: if (fmt[0] == 'f') { 2472: 1803: PACK_SINGLE(ptr, d, float); -: 1804: } -: 1805: else { 638: 1806: PACK_SINGLE(ptr, d, double); -: 1807: } 3110: 1808: break; -: 1809: -: 1810: /* bool */ -: 1811: case '?': 390: 1812: ld = IFUNC(PyObject_IsTrue(item)); 390: 1813: if (ld < 0) 1: 1814: return -1; /* preserve original error */ -: 1815: #ifdef HAVE_C99_BOOL 389: 1816: PACK_SINGLE(ptr, ld, _Bool); -: 1817: #else -: 1818: PACK_SINGLE(ptr, ld, char); -: 1819: #endif 389: 1820: break; -: 1821: -: 1822: /* bytes object */ -: 1823: case 'c': 863: 1824: if (!PyBytes_Check(item)) 370: 1825: return type_error_int(fmt); 493: 1826: if (PyBytes_GET_SIZE(item) != 1) 80: 1827: return value_error_int(fmt); 413: 1828: *ptr = PyBytes_AS_STRING(item)[0]; 413: 1829: break; -: 1830: -: 1831: /* pointer */ -: 1832: case 'P': 645: 1833: p = PFUNC(PyLong_AsVoidPtr(item)); 645: 1834: if (p == NULL && PyErr_Occurred()) 92: 1835: goto err_occurred; 553: 1836: PACK_SINGLE(ptr, p, void *); 553: 1837: break; -: 1838: -: 1839: /* default */ 42: 1840: default: goto err_format; -: 1841: } -: 1842: 18381: 1843: return 0; -: 1844: -: 1845:err_occurred: 3480: 1846: if (PyErr_Occurred() == PyExc_FailAPIError) 2: 1847: return -1; 3478: 1848: return fix_error_int(fmt); -: 1849:err_range: 941: 1850: return value_error_int(fmt); -: 1851:err_format: 42: 1852: PyErr_Format(PyExc_NotImplementedError, -: 1853: "memoryview: format %s not supported", fmt); 42: 1854: return -1; -: 1855:} -: 1856: -: 1857: -: 1858:/****************************************************************************/ -: 1859:/* unpack using the struct module */ -: 1860:/****************************************************************************/ -: 1861: -: 1862:/* For reasonable performance it is necessary to cache all objects required -: 1863: for unpacking. An unpacker can handle the format passed to unpack_from(). -: 1864: Invariant: All pointer fields of the struct should either be NULL or valid -: 1865: pointers. */ -: 1866:struct unpacker { -: 1867: PyObject *unpack_from; /* Struct.unpack_from(format) */ -: 1868: PyObject *mview; /* cached memoryview */ -: 1869: char *item; /* buffer for mview */ -: 1870: Py_ssize_t itemsize; /* len(item) */ -: 1871:}; -: 1872: -: 1873:static struct unpacker * 13190752: 1874:unpacker_new(void) -: 1875:{ 13190752: 1876: struct unpacker *x = PFUNC_NOEX(PyMem_Malloc(sizeof *x)); -: 1877: 13190752: 1878: if (x == NULL) { 1109: 1879: PyErr_SetString(PyExc_FailAPIError, "failapi"); 1109: 1880: return NULL; -: 1881: } -: 1882: 13189643: 1883: x->unpack_from = NULL; 13189643: 1884: x->mview = NULL; 13189643: 1885: x->item = NULL; 13189643: 1886: x->itemsize = 0; -: 1887: 13189643: 1888: return x; -: 1889:} -: 1890: -: 1891:static void 16649970: 1892:unpacker_free(struct unpacker *x) -: 1893:{ 16649970: 1894: if (x) { 13189643: 1895: Py_XDECREF(x->unpack_from); 13189643: 1896: Py_XDECREF(x->mview); 13189643: 1897: PyMem_Free(x->item); 13189643: 1898: PyMem_Free(x); -: 1899: } 16649970: 1900:} -: 1901: -: 1902:/* Return a new unpacker for the given format. */ -: 1903:static struct unpacker * 13192970: 1904:struct_get_unpacker(const char *fmt, Py_ssize_t itemsize) -: 1905:{ -: 1906: PyObject *structmodule; /* XXX cache these two */ 13192970: 1907: PyObject *Struct = NULL; /* XXX in globals? */ 13192970: 1908: PyObject *structobj = NULL; 13192970: 1909: PyObject *format = NULL; 13192970: 1910: struct unpacker *x = NULL; -: 1911: 13192970: 1912: structmodule = PFUNC(PyImport_ImportModule("struct")); 13192970: 1913: if (structmodule == NULL) 1109: 1914: return NULL; -: 1915: 13191861: 1916: Struct = PFUNC(PyObject_GetAttrString(structmodule, "Struct")); 13191861: 1917: Py_DECREF(structmodule); 13191861: 1918: if (Struct == NULL) 1109: 1919: return NULL; -: 1920: 13190752: 1921: x = unpacker_new(); 13190752: 1922: if (x == NULL) 1109: 1923: goto error; -: 1924: 13189643: 1925: format = PFUNC(PyBytes_FromString(fmt)); 13189643: 1926: if (format == NULL) 1109: 1927: goto error; -: 1928: 13188534: 1929: structobj = PFUNC(PyObject_CallFunctionObjArgs(Struct, format, NULL)); 13188534: 1930: if (structobj == NULL) 1172: 1931: goto error; -: 1932: 13187362: 1933: x->unpack_from = PFUNC(PyObject_GetAttrString(structobj, "unpack_from")); 13187362: 1934: if (x->unpack_from == NULL) 1104: 1935: goto error; -: 1936: 13186258: 1937: x->item = PFUNC_NOEX(PyMem_Malloc(itemsize)); 13186258: 1938: if (x->item == NULL) { 1104: 1939: PyErr_SetString(PyExc_FailAPIError, "failapi"); 1104: 1940: goto error; -: 1941: } 13185154: 1942: x->itemsize = itemsize; -: 1943: 13185154: 1944: x->mview = PyMemoryView_FromMemory(x->item, itemsize, PyBUF_WRITE); 13185154: 1945: if (x->mview == NULL) 2208: 1946: goto error; -: 1947: -: 1948: -: 1949:out: 13190752: 1950: Py_XDECREF(Struct); 13190752: 1951: Py_XDECREF(format); 13190752: 1952: Py_XDECREF(structobj); 13190752: 1953: return x; -: 1954: -: 1955:error: 7806: 1956: unpacker_free(x); 7806: 1957: x = NULL; 7806: 1958: goto out; -: 1959:} -: 1960: -: 1961:/* unpack a single item */ -: 1962:static PyObject * 271574343: 1963:struct_unpack_single(const char *ptr, struct unpacker *x) -: 1964:{ -: 1965: PyObject *v; -: 1966: 271574343: 1967: memcpy(x->item, ptr, x->itemsize); 271574343: 1968: v = PFUNC(PyObject_CallFunctionObjArgs(x->unpack_from, x->mview, NULL)); 271574343: 1969: if (v == NULL) 24586: 1970: return NULL; -: 1971: 271549757: 1972: if (PyTuple_GET_SIZE(v) == 1) { 158094425: 1973: PyObject *tmp = PyTuple_GET_ITEM(v, 0); 158094425: 1974: Py_INCREF(tmp); 158094425: 1975: Py_DECREF(v); 158094425: 1976: return tmp; -: 1977: } -: 1978: 113455332: 1979: return v; -: 1980:} -: 1981: -: 1982: -: 1983:/****************************************************************************/ -: 1984:/* Representations */ -: 1985:/****************************************************************************/ -: 1986: -: 1987:/* allow explicit form of native format */ -: 1988:Py_LOCAL_INLINE(const char *) 592032: 1989:adjust_fmt(const Py_buffer *view) -: 1990:{ -: 1991: const char *fmt; -: 1992: 592032: 1993: fmt = (view->format[0] == '@') ? view->format+1 : view->format; 592032: 1994: if (fmt[0] && fmt[1] == '\0') 566840: 1995: return fmt; -: 1996: 25192: 1997: PyErr_Format(PyExc_NotImplementedError, -: 1998: "memoryview: unsupported format %s", view->format); 25192: 1999: return NULL; -: 2000:} -: 2001: -: 2002:/* Base case for multi-dimensional unpacking. Assumption: ndim == 1. */ -: 2003:static PyObject * 2352006: 2004:tolist_base(const char *ptr, const Py_ssize_t *shape, -: 2005: const Py_ssize_t *strides, const Py_ssize_t *suboffsets, -: 2006: const char *fmt) -: 2007:{ -: 2008: PyObject *lst, *item; -: 2009: Py_ssize_t i; -: 2010: 2352006: 2011: lst = PFUNC(PyList_New(shape[0])); 2352006: 2012: if (lst == NULL) 918: 2013: return NULL; -: 2014: 14972556: 2015: for (i = 0; i < shape[0]; ptr+=strides[0], i++) { 12621501: 2016: const char *xptr = ADJUST_PTR(ptr, suboffsets); 12621501: 2017: item = unpack_single(xptr, fmt); 12621501: 2018: if (item == NULL) { 33: 2019: Py_DECREF(lst); 33: 2020: return NULL; -: 2021: } 12621468: 2022: PyList_SET_ITEM(lst, i, item); -: 2023: } -: 2024: 2351055: 2025: return lst; -: 2026:} -: 2027: -: 2028:/* Unpack a multi-dimensional array into a nested list. -: 2029: Assumption: ndim >= 1. */ -: 2030:static PyObject * 3016394: 2031:tolist_rec(const char *ptr, Py_ssize_t ndim, const Py_ssize_t *shape, -: 2032: const Py_ssize_t *strides, const Py_ssize_t *suboffsets, -: 2033: const char *fmt) -: 2034:{ -: 2035: PyObject *lst, *item; -: 2036: Py_ssize_t i; -: 2037: -: 2038: assert(ndim >= 1); -: 2039: assert(shape != NULL); -: 2040: assert(strides != NULL); -: 2041: 3016394: 2042: if (ndim == 1) 2116120: 2043: return tolist_base(ptr, shape, strides, suboffsets, fmt); -: 2044: 900274: 2045: lst = PFUNC(PyList_New(shape[0])); 900274: 2046: if (lst == NULL) 310: 2047: return NULL; -: 2048: 3820092: 2049: for (i = 0; i < shape[0]; ptr+=strides[0], i++) { 2923148: 2050: const char *xptr = ADJUST_PTR(ptr, suboffsets); 2923148: 2051: item = tolist_rec(xptr, ndim-1, shape+1, -: 2052: strides+1, suboffsets ? suboffsets+1 : NULL, -: 2053: fmt); 2923148: 2054: if (item == NULL) { 3020: 2055: Py_DECREF(lst); 3020: 2056: return NULL; -: 2057: } 2920128: 2058: PyList_SET_ITEM(lst, i, item); -: 2059: } -: 2060: 896944: 2061: return lst; -: 2062:} -: 2063: -: 2064:/* Return a list representation of the memoryview. Currently only buffers -: 2065: with native format strings are supported. */ -: 2066:static PyObject * 442788: 2067:memory_tolist(PyMemoryViewObject *mv, PyObject *noargs) -: 2068:{ 442788: 2069: const Py_buffer *view = &(mv->view); -: 2070: const char *fmt; -: 2071: 442788: 2072: CHECK_RELEASED(mv); -: 2073: 442582: 2074: fmt = adjust_fmt(view); 442582: 2075: if (fmt == NULL) 8388: 2076: return NULL; 434194: 2077: if (view->ndim == 0) { 105062: 2078: return unpack_single(view->buf, fmt); -: 2079: } 329132: 2080: else if (view->ndim == 1) { 235886: 2081: return tolist_base(view->buf, view->shape, 235886: 2082: view->strides, view->suboffsets, -: 2083: fmt); -: 2084: } -: 2085: else { 93246: 2086: return tolist_rec(view->buf, view->ndim, view->shape, 93246: 2087: view->strides, view->suboffsets, -: 2088: fmt); -: 2089: } -: 2090:} -: 2091: -: 2092:static PyObject * 2851328: 2093:memory_tobytes(PyMemoryViewObject *self, PyObject *dummy) -: 2094:{ 2851328: 2095: Py_buffer *src = VIEW_ADDR(self); 2851328: 2096: PyObject *bytes = NULL; -: 2097: 2851328: 2098: CHECK_RELEASED(self); -: 2099: 2851122: 2100: if (MV_C_CONTIGUOUS(self->flags)) { 2704485: 2101: return PyBytes_FromStringAndSize(src->buf, src->len); -: 2102: } -: 2103: 146637: 2104: bytes = PFUNC(PyBytes_FromStringAndSize(NULL, src->len)); 146637: 2105: if (bytes == NULL) 20: 2106: return NULL; -: 2107: 146617: 2108: if (buffer_to_contiguous(PyBytes_AS_STRING(bytes), src, 'C') < 0) { 58: 2109: Py_DECREF(bytes); 58: 2110: return NULL; -: 2111: } -: 2112: 146559: 2113: return bytes; -: 2114:} -: 2115: -: 2116:static PyObject * 404: 2117:memory_repr(PyMemoryViewObject *self) -: 2118:{ 404: 2119: if (self->flags & _Py_MEMORYVIEW_RELEASED) 403: 2120: return PyUnicode_FromFormat("", self); -: 2121: else 1: 2122: return PyUnicode_FromFormat("", self); -: 2123:} -: 2124: -: 2125: -: 2126:/**************************************************************************/ -: 2127:/* Indexing and slicing */ -: 2128:/**************************************************************************/ -: 2129: -: 2130:/* Get the pointer to the item at index. */ -: 2131:static char * 99144: 2132:ptr_from_index(Py_buffer *view, Py_ssize_t index) -: 2133:{ -: 2134: char *ptr; -: 2135: Py_ssize_t nitems; /* items in the first dimension */ -: 2136: -: 2137: assert(view->shape); -: 2138: assert(view->strides); -: 2139: 99144: 2140: nitems = view->shape[0]; 99144: 2141: if (index < 0) { 14365: 2142: index += nitems; -: 2143: } 99144: 2144: if (index < 0 || index >= nitems) { 5013: 2145: PyErr_SetString(PyExc_IndexError, "index out of bounds"); 5013: 2146: return NULL; -: 2147: } -: 2148: 94131: 2149: ptr = (char *)view->buf; 94131: 2150: ptr += view->strides[0] * index; -: 2151: 94131: 2152: ptr = ADJUST_PTR(ptr, view->suboffsets); -: 2153: 94131: 2154: return ptr; -: 2155:} -: 2156: -: 2157:/* Return the item at index. In a one-dimensional view, this is an object -: 2158: with the type specified by view->format. Otherwise, the item is a sub-view. -: 2159: The function is used in memory_subscript() and memory_as_sequence. */ -: 2160:static PyObject * 87950: 2161:memory_item(PyMemoryViewObject *self, Py_ssize_t index) -: 2162:{ 87950: 2163: Py_buffer *view = &(self->view); -: 2164: const char *fmt; -: 2165: 87950: 2166: CHECK_RELEASED(self); -: 2167: 87945: 2168: fmt = adjust_fmt(view); 87945: 2169: if (fmt == NULL) 8335: 2170: return NULL; -: 2171: 79610: 2172: if (view->ndim == 0) { 252: 2173: PyErr_SetString(PyExc_TypeError, "invalid indexing of 0-dim memory"); 252: 2174: return NULL; -: 2175: } 79358: 2176: if (view->ndim == 1) { 79356: 2177: char *ptr = ptr_from_index(view, index); 79356: 2178: if (ptr == NULL) 3131: 2179: return NULL; 76225: 2180: return unpack_single(ptr, fmt); -: 2181: } -: 2182: 2: 2183: PyErr_SetString(PyExc_NotImplementedError, -: 2184: "multi-dimensional sub-views are not implemented"); 2: 2185: return NULL; -: 2186:} -: 2187: -: 2188:Py_LOCAL_INLINE(int) 19467: 2189:init_slice(Py_buffer *base, PyObject *key, int dim) -: 2190:{ -: 2191: Py_ssize_t start, stop, step, slicelength; -: 2192: 19467: 2193: if (PySlice_GetIndicesEx(key, base->shape[dim], -: 2194: &start, &stop, &step, &slicelength) < 0) { 1198: 2195: return -1; -: 2196: } -: 2197: -: 2198: 36538: 2199: if (base->suboffsets == NULL || dim == 0) { -: 2200: adjust_buf: 18269: 2201: base->buf = (char *)base->buf + base->strides[dim] * start; -: 2202: } -: 2203: else { #####: 2204: Py_ssize_t n = dim-1; #####: 2205: while (n >= 0 && base->suboffsets[n] < 0) #####: 2206: n--; #####: 2207: if (n < 0) #####: 2208: goto adjust_buf; /* all suboffsets are negative */ #####: 2209: base->suboffsets[n] = base->suboffsets[n] + base->strides[dim] * start; -: 2210: } 18269: 2211: base->shape[dim] = slicelength; 18269: 2212: base->strides[dim] = base->strides[dim] * step; -: 2213: 18269: 2214: return 0; -: 2215:} -: 2216: -: 2217:static int 4568: 2218:is_multislice(PyObject *key) -: 2219:{ -: 2220: Py_ssize_t size, i; -: 2221: 4568: 2222: if (!PyTuple_Check(key)) 2349: 2223: return 0; 2219: 2224: size = PyTuple_GET_SIZE(key); 2219: 2225: if (size == 0) 360: 2226: return 0; -: 2227: 4716: 2228: for (i = 0; i < size; i++) { 3623: 2229: PyObject *x = PyTuple_GET_ITEM(key, i); 3623: 2230: if (!PySlice_Check(x)) 766: 2231: return 0; -: 2232: } 1093: 2233: return 1; -: 2234:} -: 2235: -: 2236:/* mv[obj] returns an object holding the data for one element if obj -: 2237: fully indexes the memoryview or another memoryview object if it -: 2238: does not. -: 2239: -: 2240: 0-d memoryview objects can be referenced using mv[...] or mv[()] -: 2241: but not with anything else. */ -: 2242:static PyObject * 121871: 2243:memory_subscript(PyMemoryViewObject *self, PyObject *key) -: 2244:{ -: 2245: Py_buffer *view; 121871: 2246: view = &(self->view); -: 2247: 121871: 2248: CHECK_RELEASED(self); -: 2249: 121665: 2250: if (view->ndim == 0) { 14984: 2251: if (PyTuple_Check(key) && PyTuple_GET_SIZE(key) == 0) { 14617: 2252: const char *fmt = adjust_fmt(view); 14617: 2253: if (fmt == NULL) 73: 2254: return NULL; 14544: 2255: return unpack_single(view->buf, fmt); -: 2256: } 367: 2257: else if (key == Py_Ellipsis) { 233: 2258: Py_INCREF(self); 233: 2259: return (PyObject *)self; -: 2260: } -: 2261: else { 134: 2262: PyErr_SetString(PyExc_TypeError, -: 2263: "invalid indexing of 0-dim memory"); 134: 2264: return NULL; -: 2265: } -: 2266: } -: 2267: 106681: 2268: if (PyIndex_Check(key)) { -: 2269: Py_ssize_t index; 87451: 2270: index = PyNumber_AsSsize_t(key, PyExc_IndexError); 87451: 2271: if (index == -1 && PyErr_Occurred()) 131: 2272: return NULL; 87320: 2273: return memory_item(self, index); -: 2274: } 19230: 2275: else if (PySlice_Check(key)) { -: 2276: PyMemoryViewObject *sliced; -: 2277: 17231: 2278: sliced = (PyMemoryViewObject *)mbuf_add_view(self->mbuf, view); 17231: 2279: if (sliced == NULL) 249: 2280: return NULL; -: 2281: 16982: 2282: if (init_slice(&sliced->view, key, 0) < 0) { 838: 2283: Py_DECREF(sliced); 838: 2284: return NULL; -: 2285: } 16144: 2286: init_len(&sliced->view); 16144: 2287: init_flags(sliced); -: 2288: 16144: 2289: return (PyObject *)sliced; -: 2290: } 1999: 2291: else if (is_multislice(key)) { 749: 2292: PyErr_SetString(PyExc_NotImplementedError, -: 2293: "multi-dimensional slicing is not implemented"); 749: 2294: return NULL; -: 2295: } -: 2296: 1250: 2297: PyErr_SetString(PyExc_TypeError, "memoryview: invalid slice key"); 1250: 2298: return NULL; -: 2299:} -: 2300: -: 2301:static int 47094: 2302:memory_ass_sub(PyMemoryViewObject *self, PyObject *key, PyObject *value) -: 2303:{ 47094: 2304: Py_buffer *view = &(self->view); -: 2305: Py_buffer src; -: 2306: const char *fmt; -: 2307: char *ptr; -: 2308: 47094: 2309: CHECK_RELEASED_INT(self); -: 2310: 46888: 2311: fmt = adjust_fmt(view); 46888: 2312: if (fmt == NULL) 8396: 2313: return -1; -: 2314: 38492: 2315: if (view->readonly) { 5175: 2316: PyErr_SetString(PyExc_TypeError, "cannot modify read-only memory"); 5175: 2317: return -1; -: 2318: } 33317: 2319: if (value == NULL) { 122: 2320: PyErr_SetString(PyExc_TypeError, "cannot delete memory"); 122: 2321: return -1; -: 2322: } 33195: 2323: if (view->ndim == 0) { 16251: 2324: if (key == Py_Ellipsis || 9900: 2325: (PyTuple_Check(key) && PyTuple_GET_SIZE(key)==0)) { 5389: 2326: ptr = (char *)view->buf; 5389: 2327: return pack_single(ptr, value, fmt); -: 2328: } -: 2329: else { 962: 2330: PyErr_SetString(PyExc_TypeError, -: 2331: "invalid indexing of 0-dim memory"); 962: 2332: return -1; -: 2333: } -: 2334: } 26844: 2335: if (view->ndim != 1) { 159: 2336: PyErr_SetString(PyExc_NotImplementedError, -: 2337: "memoryview assignments are currently restricted to ndim = 1"); 159: 2338: return -1; -: 2339: } -: 2340: 26685: 2341: if (PyIndex_Check(key)) { 20734: 2342: Py_ssize_t index = PyNumber_AsSsize_t(key, PyExc_IndexError); 20734: 2343: if (index == -1 && PyErr_Occurred()) 946: 2344: return -1; 19788: 2345: ptr = ptr_from_index(view, index); 19788: 2346: if (ptr == NULL) 1882: 2347: return -1; 17906: 2348: return pack_single(ptr, value, fmt); -: 2349: } -: 2350: /* one-dimensional: fast path */ 5951: 2351: if (PySlice_Check(key) && view->ndim == 1) { -: 2352: Py_buffer dest; /* sliced view */ -: 2353: Py_ssize_t arrays[3]; 3382: 2354: int ret = -1; -: 2355: -: 2356: /* rvalue must be an exporter */ 3382: 2357: if (PyObject_GetBuffer(value, &src, PyBUF_FULL_RO) < 0) 897: 2358: return ret; -: 2359: 2485: 2360: dest = *view; 2485: 2361: dest.shape = &arrays[0]; dest.shape[0] = view->shape[0]; 2485: 2362: dest.strides = &arrays[1]; dest.strides[0] = view->strides[0]; 2485: 2363: if (view->suboffsets) { 75: 2364: dest.suboffsets = &arrays[2]; dest.suboffsets[0] = view->suboffsets[0]; -: 2365: } -: 2366: 2485: 2367: if (init_slice(&dest, key, 0) < 0) 360: 2368: goto end_block; 2125: 2369: dest.len = dest.shape[0] * dest.itemsize; -: 2370: 2125: 2371: ret = copy_single(&dest, &src); -: 2372: -: 2373: end_block: 2485: 2374: PyBuffer_Release(&src); 2485: 2375: return ret; -: 2376: } 2569: 2377: else if (PySlice_Check(key) || is_multislice(key)) { -: 2378: /* Call memory_subscript() to produce a sliced lvalue, then copy -: 2379: rvalue into lvalue. This is already implemented in _testbuffer.c. */ 344: 2380: PyErr_SetString(PyExc_NotImplementedError, -: 2381: "memoryview slice assignments are currently restricted " -: 2382: "to ndim = 1"); 344: 2383: return -1; -: 2384: } -: 2385: 2225: 2386: PyErr_SetString(PyExc_TypeError, "memoryview: invalid slice key"); 2225: 2387: return -1; -: 2388:} -: 2389: -: 2390:static Py_ssize_t 187780: 2391:memory_length(PyMemoryViewObject *self) -: 2392:{ 187780: 2393: CHECK_RELEASED_INT(self); 187579: 2394: return self->view.ndim == 0 ? 1 : self->view.shape[0]; -: 2395:} -: 2396: -: 2397:/* As mapping */ -: 2398:static PyMappingMethods memory_as_mapping = { -: 2399: (lenfunc)memory_length, /* mp_length */ -: 2400: (binaryfunc)memory_subscript, /* mp_subscript */ -: 2401: (objobjargproc)memory_ass_sub, /* mp_ass_subscript */ -: 2402:}; -: 2403: -: 2404:/* As sequence */ -: 2405:static PySequenceMethods memory_as_sequence = { -: 2406: 0, /* sq_length */ -: 2407: 0, /* sq_concat */ -: 2408: 0, /* sq_repeat */ -: 2409: (ssizeargfunc)memory_item, /* sq_item */ -: 2410:}; -: 2411: -: 2412: -: 2413:/**************************************************************************/ -: 2414:/* Comparisons */ -: 2415:/**************************************************************************/ -: 2416: -: 2417:#define MV_COMPARE_EX -1 /* exception */ -: 2418:#define MV_COMPARE_NOT_IMPL -2 /* not implemented */ -: 2419: -: 2420:/* Translate a StructError to "not equal". Preserve other exceptions. */ -: 2421:static int 10024: 2422:fix_struct_error_int(void) -: 2423:{ -: 2424: assert(PyErr_Occurred()); -: 2425: /* XXX Cannot get at StructError directly? */ 10150: 2426: if (PyErr_ExceptionMatches(PyExc_FailAPIError) || 63: 2427: PyErr_ExceptionMatches(PyExc_ImportError) || 63: 2428: PyErr_ExceptionMatches(PyExc_MemoryError)) { 9961: 2429: return MV_COMPARE_EX; -: 2430: } -: 2431: /* StructError: invalid or unknown format -> not equal */ 63: 2432: PyErr_Clear(); 63: 2433: return 0; -: 2434:} -: 2435: -: 2436:/* Unpack and compare single items of p and q using the struct module. */ -: 2437:static int 135793318: 2438:struct_unpack_cmp(const char *p, const char *q, -: 2439: struct unpacker *unpack_p, struct unpacker *unpack_q) -: 2440:{ -: 2441: PyObject *v, *w; -: 2442: int ret; -: 2443: -: 2444: /* At this point any exception from the struct module should not be -: 2445: StructError, since both formats have been accepted already. */ 135793318: 2446: v = struct_unpack_single(p, unpack_p); 135793318: 2447: if (v == NULL) 12293: 2448: return MV_COMPARE_EX; -: 2449: 135781025: 2450: w = struct_unpack_single(q, unpack_q); 135781025: 2451: if (w == NULL) { 12293: 2452: Py_DECREF(v); 12293: 2453: return MV_COMPARE_EX; -: 2454: } -: 2455: -: 2456: /* MV_COMPARE_EX == -1: exceptions are preserved */ 135768732: 2457: ret = IFUNC(PyObject_RichCompareBool(v, w, Py_EQ)); 135768732: 2458: Py_DECREF(v); 135768732: 2459: Py_DECREF(w); -: 2460: 135768732: 2461: return ret; -: 2462:} -: 2463: -: 2464:/* Unpack and compare single items of p and q. If both p and q have the same -: 2465: single element native format, the comparison uses a fast path (gcc creates -: 2466: a jump table and converts memcpy into simple assignments on x86/x64). -: 2467: -: 2468: Otherwise, the comparison is delegated to the struct module, which is -: 2469: 30-60x slower. */ -: 2470:#define CMP_SINGLE(p, q, type) \ -: 2471: do { \ -: 2472: type x; \ -: 2473: type y; \ -: 2474: memcpy((char *)&x, p, sizeof x); \ -: 2475: memcpy((char *)&y, q, sizeof y); \ -: 2476: equal = (x == y); \ -: 2477: } while (0) -: 2478: -: 2479:Py_LOCAL_INLINE(int) 156212405: 2480:unpack_cmp(const char *p, const char *q, char fmt, -: 2481: struct unpacker *unpack_p, struct unpacker *unpack_q) -: 2482:{ -: 2483: int equal; -: 2484: 156212405: 2485: switch (fmt) { -: 2486: -: 2487: /* signed integers and fast path for 'B' */ 18279951: 2488: case 'B': return *((unsigned char *)p) == *((unsigned char *)q); 193091: 2489: case 'b': return *((signed char *)p) == *((signed char *)q); 383125: 2490: case 'h': CMP_SINGLE(p, q, short); return equal; 63932: 2491: case 'i': CMP_SINGLE(p, q, int); return equal; 300780: 2492: case 'l': CMP_SINGLE(p, q, long); return equal; -: 2493: -: 2494: /* boolean */ -: 2495: #ifdef HAVE_C99_BOOL 37224: 2496: case '?': CMP_SINGLE(p, q, _Bool); return equal; -: 2497: #else -: 2498: case '?': CMP_SINGLE(p, q, char); return equal; -: 2499: #endif -: 2500: -: 2501: /* unsigned integers */ 73964: 2502: case 'H': CMP_SINGLE(p, q, unsigned short); return equal; 138955: 2503: case 'I': CMP_SINGLE(p, q, unsigned int); return equal; 361042: 2504: case 'L': CMP_SINGLE(p, q, unsigned long); return equal; -: 2505: -: 2506: /* native 64-bit */ -: 2507: #ifdef HAVE_LONG_LONG 34796: 2508: case 'q': CMP_SINGLE(p, q, PY_LONG_LONG); return equal; 60786: 2509: case 'Q': CMP_SINGLE(p, q, unsigned PY_LONG_LONG); return equal; -: 2510: #endif -: 2511: -: 2512: /* ssize_t and size_t */ 57708: 2513: case 'n': CMP_SINGLE(p, q, Py_ssize_t); return equal; 66456: 2514: case 'N': CMP_SINGLE(p, q, size_t); return equal; -: 2515: -: 2516: /* floats */ -: 2517: /* XXX DBL_EPSILON? */ 40306: 2518: case 'f': CMP_SINGLE(p, q, float); return equal; 43999: 2519: case 'd': CMP_SINGLE(p, q, double); return equal; -: 2520: -: 2521: /* bytes object */ 221388: 2522: case 'c': return *p == *q; -: 2523: -: 2524: /* pointer */ 61584: 2525: case 'P': CMP_SINGLE(p, q, void *); return equal; -: 2526: -: 2527: /* use the struct module */ -: 2528: case '_': -: 2529: assert(unpack_p); -: 2530: assert(unpack_q); 135793318: 2531: return struct_unpack_cmp(p, q, unpack_p, unpack_q); -: 2532: } -: 2533: -: 2534: /* NOT REACHED */ #####: 2535: PyErr_SetString(PyExc_RuntimeError, -: 2536: "memoryview: internal error in richcompare"); #####: 2537: return MV_COMPARE_EX; -: 2538:} -: 2539: -: 2540:/* Base case for recursive array comparisons. Assumption: ndim == 1. */ -: 2541:static int 58056932: 2542:cmp_base(const char *p, const char *q, const Py_ssize_t *shape, -: 2543: const Py_ssize_t *pstrides, const Py_ssize_t *psuboffsets, -: 2544: const Py_ssize_t *qstrides, const Py_ssize_t *qsuboffsets, -: 2545: char fmt, struct unpacker *unpack_p, struct unpacker *unpack_q) -: 2546:{ -: 2547: Py_ssize_t i; -: 2548: int equal; -: 2549: 213926749: 2550: for (i = 0; i < shape[0]; p+=pstrides[0], q+=qstrides[0], i++) { 156140648: 2551: const char *xp = ADJUST_PTR(p, psuboffsets); 156140648: 2552: const char *xq = ADJUST_PTR(q, qsuboffsets); 156140648: 2553: equal = unpack_cmp(xp, xq, fmt, unpack_p, unpack_q); 156140648: 2554: if (equal <= 0) 270831: 2555: return equal; -: 2556: } -: 2557: 57786101: 2558: return 1; -: 2559:} -: 2560: -: 2561:/* Recursively compare two multi-dimensional arrays that have the same -: 2562: logical structure. Assumption: ndim >= 1. */ -: 2563:static int 73841548: 2564:cmp_rec(const char *p, const char *q, -: 2565: Py_ssize_t ndim, const Py_ssize_t *shape, -: 2566: const Py_ssize_t *pstrides, const Py_ssize_t *psuboffsets, -: 2567: const Py_ssize_t *qstrides, const Py_ssize_t *qsuboffsets, -: 2568: char fmt, struct unpacker *unpack_p, struct unpacker *unpack_q) -: 2569:{ -: 2570: Py_ssize_t i; -: 2571: int equal; -: 2572: -: 2573: assert(ndim >= 1); -: 2574: assert(shape != NULL); -: 2575: assert(pstrides != NULL); -: 2576: assert(qstrides != NULL); -: 2577: 73841548: 2578: if (ndim == 1) { 51240450: 2579: return cmp_base(p, q, shape, -: 2580: pstrides, psuboffsets, -: 2581: qstrides, qsuboffsets, -: 2582: fmt, unpack_p, unpack_q); -: 2583: } -: 2584: 94097694: 2585: for (i = 0; i < shape[0]; p+=pstrides[0], q+=qstrides[0], i++) { 72439463: 2586: const char *xp = ADJUST_PTR(p, psuboffsets); 72439463: 2587: const char *xq = ADJUST_PTR(q, qsuboffsets); 72439463: 2588: equal = cmp_rec(xp, xq, ndim-1, shape+1, -: 2589: pstrides+1, psuboffsets ? psuboffsets+1 : NULL, -: 2590: qstrides+1, qsuboffsets ? qsuboffsets+1 : NULL, -: 2591: fmt, unpack_p, unpack_q); 72439463: 2592: if (equal <= 0) 942867: 2593: return equal; -: 2594: } -: 2595: 21658231: 2596: return 1; -: 2597:} -: 2598: -: 2599:static PyObject * 8321082: 2600:memory_richcompare(PyObject *v, PyObject *w, int op) -: 2601:{ -: 2602: PyObject *res; -: 2603: Py_buffer wbuf, *vv; 8321082: 2604: Py_buffer *ww = NULL; 8321082: 2605: struct unpacker *unpack_v = NULL; 8321082: 2606: struct unpacker *unpack_w = NULL; -: 2607: char vfmt, wfmt; 8321082: 2608: int equal = MV_COMPARE_NOT_IMPL; -: 2609: 8321082: 2610: if (op != Py_EQ && op != Py_NE) 824: 2611: goto result; /* Py_NotImplemented */ -: 2612: -: 2613: assert(PyMemoryView_Check(v)); 8320258: 2614: if (BASE_INACCESSIBLE(v)) { 848: 2615: equal = (v == w); 848: 2616: goto result; -: 2617: } 8319410: 2618: vv = VIEW_ADDR(v); -: 2619: 8319410: 2620: if (PyMemoryView_Check(w)) { 7730896: 2621: if (BASE_INACCESSIBLE(w)) { 83: 2622: equal = (v == w); 83: 2623: goto result; -: 2624: } 7730813: 2625: ww = VIEW_ADDR(w); -: 2626: } -: 2627: else { 588514: 2628: if (PyObject_GetBuffer(w, &wbuf, PyBUF_FULL_RO) < 0) { 237: 2629: PyErr_Clear(); 237: 2630: goto result; /* Py_NotImplemented */ -: 2631: } 588277: 2632: ww = &wbuf; -: 2633: } -: 2634: 8319090: 2635: if (!equiv_shape(vv, ww)) { 18742: 2636: PyErr_Clear(); 18742: 2637: equal = 0; 18742: 2638: goto result; -: 2639: } -: 2640: -: 2641: /* Use fast unpacking for identical primitive C type formats. */ 8300348: 2642: if (get_native_fmtchar(&vfmt, vv->format) < 0) 6594441: 2643: vfmt = '_'; 8300348: 2644: if (get_native_fmtchar(&wfmt, ww->format) < 0) 6594441: 2645: wfmt = '_'; 8300348: 2646: if (vfmt == '_' || wfmt == '_' || vfmt != wfmt) { -: 2647: /* Use struct module unpacking. NOTE: Even for equal format strings, -: 2648: memcmp() cannot be used for item comparison since it would give -: 2649: incorrect results in the case of NaNs or uninitialized padding -: 2650: bytes. */ 6599013: 2651: vfmt = '_'; 6599013: 2652: unpack_v = struct_get_unpacker(vv->format, vv->itemsize); 6599013: 2653: if (unpack_v == NULL) { 5056: 2654: equal = fix_struct_error_int(); 5056: 2655: goto result; -: 2656: } 6593957: 2657: unpack_w = struct_get_unpacker(ww->format, ww->itemsize); 6593957: 2658: if (unpack_w == NULL) { 4968: 2659: equal = fix_struct_error_int(); 4968: 2660: goto result; -: 2661: } -: 2662: } -: 2663: 8290324: 2664: if (vv->ndim == 0) { 71757: 2665: equal = unpack_cmp(vv->buf, ww->buf, -: 2666: vfmt, unpack_v, unpack_w); -: 2667: } 8218567: 2668: else if (vv->ndim == 1) { 13632964: 2669: equal = cmp_base(vv->buf, ww->buf, vv->shape, 6816482: 2670: vv->strides, vv->suboffsets, 6816482: 2671: ww->strides, ww->suboffsets, -: 2672: vfmt, unpack_v, unpack_w); -: 2673: } -: 2674: else { 2804170: 2675: equal = cmp_rec(vv->buf, ww->buf, vv->ndim, vv->shape, 1402085: 2676: vv->strides, vv->suboffsets, 1402085: 2677: ww->strides, ww->suboffsets, -: 2678: vfmt, unpack_v, unpack_w); -: 2679: } -: 2680: -: 2681:result: 8321082: 2682: if (equal < 0) { 47901: 2683: if (equal == MV_COMPARE_NOT_IMPL) 1061: 2684: res = Py_NotImplemented; -: 2685: else /* exception */ 46840: 2686: res = NULL; -: 2687: } 16544060: 2688: else if ((equal && op == Py_EQ) || (!equal && op == Py_NE)) 8270879: 2689: res = Py_True; -: 2690: else 2302: 2691: res = Py_False; -: 2692: 8321082: 2693: if (ww == &wbuf) 588277: 2694: PyBuffer_Release(ww); -: 2695: 8321082: 2696: unpacker_free(unpack_v); 8321082: 2697: unpacker_free(unpack_w); -: 2698: 8321082: 2699: Py_XINCREF(res); 8321082: 2700: return res; -: 2701:} -: 2702: -: 2703:/**************************************************************************/ -: 2704:/* Hash */ -: 2705:/**************************************************************************/ -: 2706: -: 2707:static Py_hash_t 1829: 2708:memory_hash(PyMemoryViewObject *self) -: 2709:{ 1829: 2710: if (self->hash == -1) { 1819: 2711: Py_buffer *view = &self->view; 1819: 2712: char *mem = view->buf; -: 2713: 1819: 2714: CHECK_RELEASED_INT(self); -: 2715: 1816: 2716: if (!view->readonly) { 7: 2717: PyErr_SetString(PyExc_ValueError, -: 2718: "cannot hash writable memoryview object"); 7: 2719: return -1; -: 2720: } 1809: 2721: if (view->obj != NULL && IFUNC(PyObject_Hash(view->obj)) == -1) { -: 2722: /* Keep the original error message */ 27: 2723: return -1; -: 2724: } -: 2725: 1782: 2726: if (!MV_C_CONTIGUOUS(self->flags)) { 965: 2727: mem = PFUNC_NOEX(PyMem_Malloc(view->len)); 965: 2728: if (mem == NULL) { 4: 2729: PyErr_SetString(PyExc_FailAPIError, "failapi"); 4: 2730: return -1; -: 2731: } 961: 2732: if (buffer_to_contiguous(mem, view, 'C') < 0) { 12: 2733: PyMem_Free(mem); 12: 2734: return -1; -: 2735: } -: 2736: } -: 2737: -: 2738: /* Can't fail */ 1766: 2739: self->hash = _Py_HashBytes((unsigned char *)mem, view->len); -: 2740: 1766: 2741: if (mem != view->buf) 949: 2742: PyMem_Free(mem); -: 2743: } -: 2744: 1776: 2745: return self->hash; -: 2746:} -: 2747: -: 2748: -: 2749:/**************************************************************************/ -: 2750:/* getters */ -: 2751:/**************************************************************************/ -: 2752: -: 2753:static PyObject * 1375674: 2754:_IntTupleFromSsizet(int len, Py_ssize_t *vals) -: 2755:{ -: 2756: int i; -: 2757: PyObject *o; -: 2758: PyObject *intTuple; -: 2759: 1375674: 2760: if (vals == NULL) 772803: 2761: return PyTuple_New(0); -: 2762: 602871: 2763: intTuple = PFUNC(PyTuple_New(len)); 602871: 2764: if (!intTuple) 194: 2765: return NULL; 1559940: 2766: for (i=0; iview; -: 2781: 585701: 2782: CHECK_RELEASED(self); 585696: 2783: if (view->obj == NULL) { 195437: 2784: Py_RETURN_NONE; -: 2785: } 390259: 2786: Py_INCREF(view->obj); 390259: 2787: return view->obj; -: 2788:} -: 2789: -: 2790:static PyObject * 390959: 2791:memory_nbytes_get(PyMemoryViewObject *self) -: 2792:{ 390959: 2793: CHECK_RELEASED(self); 390954: 2794: return PyLong_FromSsize_t(self->view.len); -: 2795:} -: 2796: -: 2797:static PyObject * 391223: 2798:memory_format_get(PyMemoryViewObject *self) -: 2799:{ 391223: 2800: CHECK_RELEASED(self); 391017: 2801: return PyUnicode_FromString(self->view.format); -: 2802:} -: 2803: -: 2804:static PyObject * 391198: 2805:memory_itemsize_get(PyMemoryViewObject *self) -: 2806:{ 391198: 2807: CHECK_RELEASED(self); 390992: 2808: return PyLong_FromSsize_t(self->view.itemsize); -: 2809:} -: 2810: -: 2811:static PyObject * 391198: 2812:memory_shape_get(PyMemoryViewObject *self) -: 2813:{ 391198: 2814: CHECK_RELEASED(self); 390992: 2815: return _IntTupleFromSsizet(self->view.ndim, self->view.shape); -: 2816:} -: 2817: -: 2818:static PyObject * 390982: 2819:memory_strides_get(PyMemoryViewObject *self) -: 2820:{ 390982: 2821: CHECK_RELEASED(self); 390776: 2822: return _IntTupleFromSsizet(self->view.ndim, self->view.strides); -: 2823:} -: 2824: -: 2825:static PyObject * 593911: 2826:memory_suboffsets_get(PyMemoryViewObject *self) -: 2827:{ 593911: 2828: CHECK_RELEASED(self); 593906: 2829: return _IntTupleFromSsizet(self->view.ndim, self->view.suboffsets); -: 2830:} -: 2831: -: 2832:static PyObject * 391170: 2833:memory_readonly_get(PyMemoryViewObject *self) -: 2834:{ 391170: 2835: CHECK_RELEASED(self); 390964: 2836: return PyBool_FromLong(self->view.readonly); -: 2837:} -: 2838: -: 2839:static PyObject * 391198: 2840:memory_ndim_get(PyMemoryViewObject *self) -: 2841:{ 391198: 2842: CHECK_RELEASED(self); 390992: 2843: return PyLong_FromLong(self->view.ndim); -: 2844:} -: 2845: -: 2846:static PyObject * 36550: 2847:memory_c_contiguous(PyMemoryViewObject *self, PyObject *dummy) -: 2848:{ 36550: 2849: CHECK_RELEASED(self); 36545: 2850: return PyBool_FromLong(MV_C_CONTIGUOUS(self->flags)); -: 2851:} -: 2852: -: 2853:static PyObject * 19354: 2854:memory_f_contiguous(PyMemoryViewObject *self, PyObject *dummy) -: 2855:{ 19354: 2856: CHECK_RELEASED(self); 19349: 2857: return PyBool_FromLong(MV_F_CONTIGUOUS(self->flags)); -: 2858:} -: 2859: -: 2860:static PyObject * 55898: 2861:memory_contiguous(PyMemoryViewObject *self, PyObject *dummy) -: 2862:{ 55898: 2863: CHECK_RELEASED(self); 55893: 2864: return PyBool_FromLong(MV_ANY_CONTIGUOUS(self->flags)); -: 2865:} -: 2866: -: 2867:static PyGetSetDef memory_getsetlist[] = { -: 2868: {"obj", (getter)memory_obj_get, NULL, NULL}, -: 2869: {"nbytes", (getter)memory_nbytes_get, NULL, NULL}, -: 2870: {"readonly", (getter)memory_readonly_get, NULL, NULL}, -: 2871: {"itemsize", (getter)memory_itemsize_get, NULL, NULL}, -: 2872: {"format", (getter)memory_format_get, NULL, NULL}, -: 2873: {"ndim", (getter)memory_ndim_get, NULL, NULL}, -: 2874: {"shape", (getter)memory_shape_get, NULL, NULL}, -: 2875: {"strides", (getter)memory_strides_get, NULL, NULL}, -: 2876: {"suboffsets", (getter)memory_suboffsets_get, NULL, NULL}, -: 2877: {"c_contiguous", (getter)memory_c_contiguous, NULL, NULL}, -: 2878: {"f_contiguous", (getter)memory_f_contiguous, NULL, NULL}, -: 2879: {"contiguous", (getter)memory_contiguous, NULL, NULL}, -: 2880: {NULL, NULL, NULL, NULL}, -: 2881:}; -: 2882: -: 2883: -: 2884:static PyMethodDef memory_methods[] = { -: 2885: {"release", (PyCFunction)memory_release, METH_NOARGS, NULL}, -: 2886: {"tobytes", (PyCFunction)memory_tobytes, METH_NOARGS, NULL}, -: 2887: {"tolist", (PyCFunction)memory_tolist, METH_NOARGS, NULL}, -: 2888: {"cast", (PyCFunction)memory_cast, METH_VARARGS|METH_KEYWORDS, NULL}, -: 2889: {"__enter__", memory_enter, METH_NOARGS, NULL}, -: 2890: {"__exit__", memory_exit, METH_VARARGS, NULL}, -: 2891: {NULL, NULL} -: 2892:}; -: 2893: -: 2894: -: 2895:PyTypeObject PyMemoryView_Type = { -: 2896: PyVarObject_HEAD_INIT(&PyType_Type, 0) -: 2897: "memoryview", /* tp_name */ -: 2898: offsetof(PyMemoryViewObject, ob_array), /* tp_basicsize */ -: 2899: sizeof(Py_ssize_t), /* tp_itemsize */ -: 2900: (destructor)memory_dealloc, /* tp_dealloc */ -: 2901: 0, /* tp_print */ -: 2902: 0, /* tp_getattr */ -: 2903: 0, /* tp_setattr */ -: 2904: 0, /* tp_reserved */ -: 2905: (reprfunc)memory_repr, /* tp_repr */ -: 2906: 0, /* tp_as_number */ -: 2907: &memory_as_sequence, /* tp_as_sequence */ -: 2908: &memory_as_mapping, /* tp_as_mapping */ -: 2909: (hashfunc)memory_hash, /* tp_hash */ -: 2910: 0, /* tp_call */ -: 2911: 0, /* tp_str */ -: 2912: PyObject_GenericGetAttr, /* tp_getattro */ -: 2913: 0, /* tp_setattro */ -: 2914: &memory_as_buffer, /* tp_as_buffer */ -: 2915: Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */ -: 2916: memory_doc, /* tp_doc */ -: 2917: (traverseproc)memory_traverse, /* tp_traverse */ -: 2918: (inquiry)memory_clear, /* tp_clear */ -: 2919: memory_richcompare, /* tp_richcompare */ -: 2920: offsetof(PyMemoryViewObject, weakreflist),/* tp_weaklistoffset */ -: 2921: 0, /* tp_iter */ -: 2922: 0, /* tp_iternext */ -: 2923: memory_methods, /* tp_methods */ -: 2924: 0, /* tp_members */ -: 2925: memory_getsetlist, /* tp_getset */ -: 2926: 0, /* tp_base */ -: 2927: 0, /* tp_dict */ -: 2928: 0, /* tp_descr_get */ -: 2929: 0, /* tp_descr_set */ -: 2930: 0, /* tp_dictoffset */ -: 2931: 0, /* tp_init */ -: 2932: 0, /* tp_alloc */ -: 2933: memory_new, /* tp_new */ -: 2934:};