1
#define PY_SSIZE_T_CLEAN
2
#include <Python.h>
3
#include "structmember.h"
4

5
#define NPY_NO_DEPRECATED_API NPY_API_VERSION
6
#define _MULTIARRAYMODULE
7
#include "numpy/arrayobject.h"
8
#include "numpy/arrayscalars.h"
9

10
#include "npy_config.h"
11

12
#include "npy_pycompat.h"
13

14
#include "npy_buffer.h"
15
#include "common.h"
16
#include "numpyos.h"
17
#include "arrayobject.h"
18
#include "scalartypes.h"
19

20
/*************************************************************************
21
 ****************   Implement Buffer Protocol ****************************
22
 *************************************************************************/
23

24
/*************************************************************************
25
 * PEP 3118 buffer protocol
26
 *
27
 * Implementing PEP 3118 is somewhat convoluted because of the desirata:
28
 *
29
 * - Don't add new members to ndarray or descr structs, to preserve binary
30
 *   compatibility. (Also, adding the items is actually not very useful,
31
 *   since mutability issues prevent an 1 to 1 relationship between arrays
32
 *   and buffer views.)
33
 *
34
 * - Don't use bf_releasebuffer, because it prevents PyArg_ParseTuple("s#", ...
35
 *   from working. Breaking this would cause several backward compatibility
36
 *   issues already on Python 2.6.
37
 *
38
 * - Behave correctly when array is reshaped in-place, or it's dtype is
39
 *   altered.
40
 *
41
 * The solution taken below is to manually track memory allocated for
42
 * Py_buffers.
43
 *************************************************************************/
44

45
/*
46
 * Format string translator
47
 *
48
 * Translate PyArray_Descr to a PEP 3118 format string.
49
 */
50

51
/* Fast string 'class' */
52
typedef struct {
53
    char *s;
54
    size_t allocated;
55
    size_t pos;
56
} _tmp_string_t;
57

58
#define INIT_SIZE   16
59

60
static int
61 1
_append_char(_tmp_string_t *s, char c)
62
{
63 1
    if (s->pos >= s->allocated) {
64
        char *p;
65 1
        size_t to_alloc = (s->allocated == 0) ? INIT_SIZE : (2 * s->allocated);
66

67 1
        p = PyObject_Realloc(s->s, to_alloc);
68 1
        if (p == NULL) {
69 0
            PyErr_SetString(PyExc_MemoryError, "memory allocation failed");
70 0
            return -1;
71
        }
72 1
        s->s = p;
73 1
        s->allocated = to_alloc;
74
    }
75 1
    s->s[s->pos] = c;
76 1
    ++s->pos;
77 1
    return 0;
78
}
79

80
static int
81
_append_str(_tmp_string_t *s, char const *p)
82
{
83 1
    for (; *p != '\0'; p++) {
84 1
        if (_append_char(s, *p) < 0) {
85
            return -1;
86
        }
87
    }
88
    return 0;
89
}
90

91
/*
92
 * Append a PEP3118-formatted field name, ":name:", to str
93
 */
94
static int
95 1
_append_field_name(_tmp_string_t *str, PyObject *name)
96
{
97 1
    int ret = -1;
98
    char *p;
99
    Py_ssize_t len;
100
    PyObject *tmp;
101
    /* FIXME: XXX -- should it use UTF-8 here? */
102 1
    tmp = PyUnicode_AsUTF8String(name);
103 1
    if (tmp == NULL || PyBytes_AsStringAndSize(tmp, &p, &len) < 0) {
104 0
        PyErr_Clear();
105 0
        PyErr_SetString(PyExc_ValueError, "invalid field name");
106 0
        goto fail;
107
    }
108 1
    if (_append_char(str, ':') < 0) {
109
        goto fail;
110
    }
111 1
    while (len > 0) {
112 1
        if (*p == ':') {
113 0
            PyErr_SetString(PyExc_ValueError,
114
                            "':' is not an allowed character in buffer "
115
                            "field names");
116 0
            goto fail;
117
        }
118 1
        if (_append_char(str, *p) < 0) {
119
            goto fail;
120
        }
121 1
        ++p;
122 1
        --len;
123
    }
124 1
    if (_append_char(str, ':') < 0) {
125
        goto fail;
126
    }
127 1
    ret = 0;
128 1
fail:
129 1
    Py_XDECREF(tmp);
130 1
    return ret;
131
}
132

133
/*
134
 * Return non-zero if a type is aligned in each item in the given array,
135
 * AND, the descr element size is a multiple of the alignment,
136
 * AND, the array data is positioned to alignment granularity.
137
 */
138
static NPY_INLINE int
139 1
_is_natively_aligned_at(PyArray_Descr *descr,
140
                        PyArrayObject *arr, Py_ssize_t offset)
141
{
142
    int k;
143

144 1
    if (NPY_LIKELY(descr == PyArray_DESCR(arr))) {
145
        /*
146
         * If the descriptor is the arrays descriptor we can assume the
147
         * array's alignment is correct.
148
         */
149
        assert(offset == 0);
150 1
        if (PyArray_ISALIGNED(arr)) {
151
            assert(descr->elsize % descr->alignment == 0);
152
            return 1;
153
        }
154 0
        return 0;
155
    }
156

157 1
    if ((Py_ssize_t)(PyArray_DATA(arr)) % descr->alignment != 0) {
158
        return 0;
159
    }
160

161 1
    if (offset % descr->alignment != 0) {
162
        return 0;
163
    }
164

165 1
    if (descr->elsize % descr->alignment) {
166
        return 0;
167
    }
168

169 1
    for (k = 0; k < PyArray_NDIM(arr); ++k) {
170 1
        if (PyArray_DIM(arr, k) > 1) {
171 1
            if (PyArray_STRIDE(arr, k) % descr->alignment != 0) {
172
                return 0;
173
            }
174
        }
175
    }
176

177
    return 1;
178
}
179

180
/*
181
 * Fill in str with an appropriate PEP 3118 format string, based on
182
 * descr. For structured dtypes, calls itself recursively. Each call extends
183
 * str at offset then updates offset, and uses  descr->byteorder, (and
184
 * possibly the byte order in obj) to determine the byte-order char.
185
 *
186
 * Returns 0 for success, -1 for failure
187
 */
188
static int
189 1
_buffer_format_string(PyArray_Descr *descr, _tmp_string_t *str,
190
                      PyObject* obj, Py_ssize_t *offset,
191
                      char *active_byteorder)
192
{
193
    int k;
194 1
    char _active_byteorder = '@';
195 1
    Py_ssize_t _offset = 0;
196

197 1
    if (active_byteorder == NULL) {
198 1
        active_byteorder = &_active_byteorder;
199
    }
200 1
    if (offset == NULL) {
201 1
        offset = &_offset;
202
    }
203

204 1
    if (descr->subarray) {
205
        PyObject *item, *subarray_tuple;
206 1
        Py_ssize_t total_count = 1;
207
        Py_ssize_t dim_size;
208
        Py_ssize_t old_offset;
209
        char buf[128];
210
        int ret;
211

212 1
        if (PyTuple_Check(descr->subarray->shape)) {
213 1
            subarray_tuple = descr->subarray->shape;
214 1
            Py_INCREF(subarray_tuple);
215
        }
216
        else {
217 0
            subarray_tuple = Py_BuildValue("(O)", descr->subarray->shape);
218
        }
219

220 1
        if (_append_char(str, '(') < 0) {
221
            ret = -1;
222
            goto subarray_fail;
223
        }
224 1
        for (k = 0; k < PyTuple_GET_SIZE(subarray_tuple); ++k) {
225 1
            if (k > 0) {
226 1
                if (_append_char(str, ',') < 0) {
227
                    ret = -1;
228
                    goto subarray_fail;
229
                }
230
            }
231 1
            item = PyTuple_GET_ITEM(subarray_tuple, k);
232 1
            dim_size = PyNumber_AsSsize_t(item, NULL);
233

234 1
            PyOS_snprintf(buf, sizeof(buf), "%ld", (long)dim_size);
235 1
            if (_append_str(str, buf) < 0) {
236
                ret = -1;
237
                goto subarray_fail;
238
            }
239 1
            total_count *= dim_size;
240
        }
241 1
        if (_append_char(str, ')') < 0) {
242
            ret = -1;
243
            goto subarray_fail;
244
        }
245

246 1
        old_offset = *offset;
247 1
        ret = _buffer_format_string(descr->subarray->base, str, obj, offset,
248
                                    active_byteorder);
249 1
        *offset = old_offset + (*offset - old_offset) * total_count;
250

251 1
    subarray_fail:
252 1
        Py_DECREF(subarray_tuple);
253
        return ret;
254
    }
255 1
    else if (PyDataType_HASFIELDS(descr)) {
256 1
        Py_ssize_t base_offset = *offset;
257

258 1
        if (_append_str(str, "T{") < 0) return -1;
259 1
        for (k = 0; k < PyTuple_GET_SIZE(descr->names); ++k) {
260
            PyObject *name, *item, *offset_obj;
261
            PyArray_Descr *child;
262
            Py_ssize_t new_offset;
263
            int ret;
264

265 1
            name = PyTuple_GET_ITEM(descr->names, k);
266 1
            item = PyDict_GetItem(descr->fields, name);
267

268 1
            child = (PyArray_Descr*)PyTuple_GetItem(item, 0);
269 1
            offset_obj = PyTuple_GetItem(item, 1);
270 1
            new_offset = PyLong_AsLong(offset_obj);
271 1
            if (error_converting(new_offset)) {
272
                return -1;
273
            }
274 1
            new_offset += base_offset;
275

276
            /* Insert padding manually */
277 1
            if (*offset > new_offset) {
278 1
                PyErr_SetString(
279
                    PyExc_ValueError,
280
                    "dtypes with overlapping or out-of-order fields are not "
281
                    "representable as buffers. Consider reordering the fields."
282
                );
283 1
                return -1;
284
            }
285 1
            while (*offset < new_offset) {
286 1
                if (_append_char(str, 'x') < 0) return -1;
287 1
                ++*offset;
288
            }
289

290
            /* Insert child item */
291 1
            ret = _buffer_format_string(child, str, obj, offset,
292
                                  active_byteorder);
293 1
            if (ret < 0) {
294
                return -1;
295
            }
296

297
            /* Insert field name */
298 1
            if (_append_field_name(str, name) < 0) return -1;
299
        }
300 1
        if (_append_char(str, '}') < 0) return -1;
301
    }
302
    else {
303 1
        int is_standard_size = 1;
304
        int is_natively_aligned;
305 1
        int is_native_only_type = (descr->type_num == NPY_LONGDOUBLE ||
306
                                   descr->type_num == NPY_CLONGDOUBLE);
307
        if (sizeof(npy_longlong) != 8) {
308
            is_native_only_type = is_native_only_type || (
309
                descr->type_num == NPY_LONGLONG ||
310
                descr->type_num == NPY_ULONGLONG);
311
        }
312

313 1
        if (PyArray_IsScalar(obj, Generic)) {
314
            /* scalars are always natively aligned */
315
            is_natively_aligned = 1;
316
        }
317
        else {
318 1
            is_natively_aligned = _is_natively_aligned_at(descr,
319
                                              (PyArrayObject*)obj, *offset);
320
        }
321

322 1
        *offset += descr->elsize;
323

324 1
        if (descr->byteorder == '=' && is_natively_aligned) {
325
            /* Prefer native types, to cater for Cython */
326 1
            is_standard_size = 0;
327 1
            if (*active_byteorder != '@') {
328 1
                if (_append_char(str, '@') < 0) return -1;
329 1
                *active_byteorder = '@';
330
            }
331
        }
332 1
        else if (descr->byteorder == '=' && is_native_only_type) {
333
            /* Data types that have no standard size */
334 1
            is_standard_size = 0;
335 1
            if (*active_byteorder != '^') {
336 1
                if (_append_char(str, '^') < 0) return -1;
337 1
                *active_byteorder = '^';
338
            }
339
        }
340 1
        else if (descr->byteorder == '<' || descr->byteorder == '>' ||
341
                 descr->byteorder == '=') {
342 1
            is_standard_size = 1;
343 1
            if (*active_byteorder != descr->byteorder) {
344 1
                if (_append_char(str, descr->byteorder) < 0) return -1;
345 1
                *active_byteorder = descr->byteorder;
346
            }
347

348 1
            if (is_native_only_type) {
349
                /*
350
                 * It's not possible to express native-only data types
351
                 * in non-native npy_byte orders
352
                 */
353 1
                PyErr_Format(PyExc_ValueError,
354
                             "cannot expose native-only dtype '%c' in "
355
                             "non-native byte order '%c' via buffer interface",
356 1
                             descr->type, descr->byteorder);
357 1
                return -1;
358
            }
359
        }
360

361 1
        switch (descr->type_num) {
362 1
        case NPY_BOOL:         if (_append_char(str, '?') < 0) return -1; break;
363 1
        case NPY_BYTE:         if (_append_char(str, 'b') < 0) return -1; break;
364 1
        case NPY_UBYTE:        if (_append_char(str, 'B') < 0) return -1; break;
365 1
        case NPY_SHORT:        if (_append_char(str, 'h') < 0) return -1; break;
366 1
        case NPY_USHORT:       if (_append_char(str, 'H') < 0) return -1; break;
367 1
        case NPY_INT:          if (_append_char(str, 'i') < 0) return -1; break;
368 1
        case NPY_UINT:         if (_append_char(str, 'I') < 0) return -1; break;
369 1
        case NPY_LONG:
370 1
            if (is_standard_size && (NPY_SIZEOF_LONG == 8)) {
371 1
                if (_append_char(str, 'q') < 0) return -1;
372
            }
373
            else {
374 1
                if (_append_char(str, 'l') < 0) return -1;
375
            }
376
            break;
377 1
        case NPY_ULONG:
378 1
            if (is_standard_size && (NPY_SIZEOF_LONG == 8)) {
379 1
                if (_append_char(str, 'Q') < 0) return -1;
380
            }
381
            else {
382 1
                if (_append_char(str, 'L') < 0) return -1;
383
            }
384
            break;
385 1
        case NPY_LONGLONG:     if (_append_char(str, 'q') < 0) return -1; break;
386 1
        case NPY_ULONGLONG:    if (_append_char(str, 'Q') < 0) return -1; break;
387 1
        case NPY_HALF:         if (_append_char(str, 'e') < 0) return -1; break;
388 1
        case NPY_FLOAT:        if (_append_char(str, 'f') < 0) return -1; break;
389 1
        case NPY_DOUBLE:       if (_append_char(str, 'd') < 0) return -1; break;
390 1
        case NPY_LONGDOUBLE:   if (_append_char(str, 'g') < 0) return -1; break;
391 1
        case NPY_CFLOAT:       if (_append_str(str, "Zf") < 0) return -1; break;
392 1
        case NPY_CDOUBLE:      if (_append_str(str, "Zd") < 0) return -1; break;
393 1
        case NPY_CLONGDOUBLE:  if (_append_str(str, "Zg") < 0) return -1; break;
394
        /* XXX NPY_DATETIME */
395
        /* XXX NPY_TIMEDELTA */
396 1
        case NPY_OBJECT:       if (_append_char(str, 'O') < 0) return -1; break;
397 1
        case NPY_STRING: {
398
            char buf[128];
399 1
            PyOS_snprintf(buf, sizeof(buf), "%ds", descr->elsize);
400 1
            if (_append_str(str, buf) < 0) return -1;
401 1
            break;
402
        }
403 1
        case NPY_UNICODE: {
404
            /* NumPy Unicode is always 4-byte */
405
            char buf[128];
406
            assert(descr->elsize % 4 == 0);
407 1
            PyOS_snprintf(buf, sizeof(buf), "%dw", descr->elsize / 4);
408 1
            if (_append_str(str, buf) < 0) return -1;
409 1
            break;
410
        }
411 1
        case NPY_VOID: {
412
            /* Insert padding bytes */
413
            char buf[128];
414 1
            PyOS_snprintf(buf, sizeof(buf), "%dx", descr->elsize);
415 1
            if (_append_str(str, buf) < 0) return -1;
416 1
            break;
417
        }
418 1
        default:
419 1
            PyErr_Format(PyExc_ValueError,
420
                         "cannot include dtype '%c' in a buffer",
421 1
                         descr->type);
422 1
            return -1;
423
        }
424
    }
425

426
    return 0;
427
}
428

429

430
/*
431
 * Global information about all active buffers
432
 *
433
 * Note: because for backward compatibility we cannot define bf_releasebuffer,
434
 * we must manually keep track of the additional data required by the buffers.
435
 */
436

437
/* Additional per-array data required for providing the buffer interface */
438
typedef struct {
439
    char *format;
440
    int ndim;
441
    Py_ssize_t *strides;
442
    Py_ssize_t *shape;
443
} _buffer_info_t;
444

445
/*
446
 * { id(array): [list of pointers to _buffer_info_t, the last one is latest] }
447
 *
448
 * Because shape, strides, and format can be different for different buffers,
449
 * we may need to keep track of multiple buffer infos for each array.
450
 *
451
 * However, when none of them has changed, the same buffer info may be reused.
452
 *
453
 * Thread-safety is provided by GIL.
454
 */
455
static PyObject *_buffer_info_cache = NULL;
456

457
/* Fill in the info structure */
458
static _buffer_info_t*
459 1
_buffer_info_new(PyObject *obj)
460
{
461
    /*
462
     * Note that the buffer info is cached as PyLongObjects making them appear
463
     * like unreachable lost memory to valgrind.
464
     */
465
    _buffer_info_t *info;
466 1
    _tmp_string_t fmt = {NULL, 0, 0};
467
    int k;
468 1
    PyArray_Descr *descr = NULL;
469 1
    int err = 0;
470

471 1
    if (PyArray_IsScalar(obj, Void)) {
472 1
        info = PyObject_Malloc(sizeof(_buffer_info_t));
473 1
        if (info == NULL) {
474 0
            PyErr_NoMemory();
475 0
            goto fail;
476
        }
477 1
        descr = PyArray_DescrFromScalar(obj);
478 1
        if (descr == NULL) {
479
            goto fail;
480
        }
481 1
        info->ndim = 0;
482 1
        info->shape = NULL;
483 1
        info->strides = NULL;
484
    }
485
    else {
486
        assert(PyArray_Check(obj));
487 1
        PyArrayObject * arr = (PyArrayObject *)obj;
488 1
        descr = PyArray_DESCR(arr);
489

490 1
        info = PyObject_Malloc(sizeof(_buffer_info_t) +
491 1
                               sizeof(Py_ssize_t) * PyArray_NDIM(arr) * 2);
492 1
        if (info == NULL) {
493 0
            PyErr_NoMemory();
494 0
            goto fail;
495
        }
496
        /* Fill in shape and strides */
497 1
        info->ndim = PyArray_NDIM(arr);
498

499 1
        if (info->ndim == 0) {
500 1
            info->shape = NULL;
501 1
            info->strides = NULL;
502
        }
503
        else {
504 1
            info->shape = (npy_intp *)((char *)info + sizeof(_buffer_info_t));
505
            assert((size_t)info->shape % sizeof(npy_intp) == 0);
506 1
            info->strides = info->shape + PyArray_NDIM(arr);
507 1
            for (k = 0; k < PyArray_NDIM(arr); ++k) {
508 1
                info->shape[k] = PyArray_DIMS(arr)[k];
509 1
                info->strides[k] = PyArray_STRIDES(arr)[k];
510
            }
511
        }
512 1
        Py_INCREF(descr);
513
    }
514

515
    /* Fill in format */
516 1
    err = _buffer_format_string(descr, &fmt, obj, NULL, NULL);
517 1
    Py_DECREF(descr);
518 1
    if (err != 0) {
519
        goto fail;
520
    }
521 1
    if (_append_char(&fmt, '\0') < 0) {
522
        goto fail;
523
    }
524 1
    info->format = fmt.s;
525

526 1
    return info;
527

528 1
fail:
529 1
    PyObject_Free(fmt.s);
530 1
    PyObject_Free(info);
531 1
    return NULL;
532
}
533

534
/* Compare two info structures */
535
static Py_ssize_t
536 1
_buffer_info_cmp(_buffer_info_t *a, _buffer_info_t *b)
537
{
538
    Py_ssize_t c;
539
    int k;
540

541 1
    c = strcmp(a->format, b->format);
542 1
    if (c != 0) return c;
543

544 1
    c = a->ndim - b->ndim;
545 1
    if (c != 0) return c;
546

547 1
    for (k = 0; k < a->ndim; ++k) {
548 1
        c = a->shape[k] - b->shape[k];
549 1
        if (c != 0) return c;
550 1
        c = a->strides[k] - b->strides[k];
551 1
        if (c != 0) return c;
552
    }
553

554
    return 0;
555
}
556

557
static void
558 1
_buffer_info_free(_buffer_info_t *info)
559
{
560 1
    if (info->format) {
561 1
        PyObject_Free(info->format);
562
    }
563 1
    PyObject_Free(info);
564
}
565

566
/* Get buffer info from the global dictionary */
567
static _buffer_info_t*
568 1
_buffer_get_info(PyObject *obj)
569
{
570 1
    PyObject *key = NULL, *item_list = NULL, *item = NULL;
571 1
    _buffer_info_t *info = NULL, *old_info = NULL;
572

573 1
    if (_buffer_info_cache == NULL) {
574 1
        _buffer_info_cache = PyDict_New();
575 1
        if (_buffer_info_cache == NULL) {
576
            return NULL;
577
        }
578
    }
579

580
    /* Compute information */
581 1
    info = _buffer_info_new(obj);
582 1
    if (info == NULL) {
583
        return NULL;
584
    }
585

586
    /* Check if it is identical with an old one; reuse old one, if yes */
587 1
    key = PyLong_FromVoidPtr((void*)obj);
588 1
    if (key == NULL) {
589
        goto fail;
590
    }
591 1
    item_list = PyDict_GetItem(_buffer_info_cache, key);
592

593 1
    if (item_list != NULL) {
594 1
        Py_INCREF(item_list);
595 1
        if (PyList_GET_SIZE(item_list) > 0) {
596 1
            item = PyList_GetItem(item_list, PyList_GET_SIZE(item_list) - 1);
597 1
            old_info = (_buffer_info_t*)PyLong_AsVoidPtr(item);
598

599 1
            if (_buffer_info_cmp(info, old_info) == 0) {
600 1
                _buffer_info_free(info);
601 1
                info = old_info;
602
            }
603
        }
604
    }
605
    else {
606 1
        item_list = PyList_New(0);
607 1
        if (item_list == NULL) {
608
            goto fail;
609
        }
610 1
        if (PyDict_SetItem(_buffer_info_cache, key, item_list) != 0) {
611
            goto fail;
612
        }
613
    }
614

615 1
    if (info != old_info) {
616
        /* Needs insertion */
617 1
        item = PyLong_FromVoidPtr((void*)info);
618 1
        if (item == NULL) {
619
            goto fail;
620
        }
621 1
        PyList_Append(item_list, item);
622 1
        Py_DECREF(item);
623
    }
624

625 1
    Py_DECREF(item_list);
626 1
    Py_DECREF(key);
627
    return info;
628

629 0
fail:
630 0
    if (info != NULL && info != old_info) {
631 0
        _buffer_info_free(info);
632
    }
633 0
    Py_XDECREF(item_list);
634 0
    Py_XDECREF(key);
635
    return NULL;
636
}
637

638
/* Clear buffer info from the global dictionary */
639
static void
640 1
_buffer_clear_info(PyObject *arr)
641
{
642
    PyObject *key, *item_list, *item;
643
    _buffer_info_t *info;
644
    int k;
645

646 1
    if (_buffer_info_cache == NULL) {
647
        return;
648
    }
649

650 1
    key = PyLong_FromVoidPtr((void*)arr);
651 1
    item_list = PyDict_GetItem(_buffer_info_cache, key);
652 1
    if (item_list != NULL) {
653 1
        for (k = 0; k < PyList_GET_SIZE(item_list); ++k) {
654 1
            item = PyList_GET_ITEM(item_list, k);
655 1
            info = (_buffer_info_t*)PyLong_AsVoidPtr(item);
656 1
            _buffer_info_free(info);
657
        }
658 1
        PyDict_DelItem(_buffer_info_cache, key);
659
    }
660

661 1
    Py_DECREF(key);
662
}
663

664
/*
665
 * Retrieving buffers for ndarray
666
 */
667
static int
668 1
array_getbuffer(PyObject *obj, Py_buffer *view, int flags)
669
{
670
    PyArrayObject *self;
671 1
    _buffer_info_t *info = NULL;
672

673 1
    self = (PyArrayObject*)obj;
674

675
    /* Check whether we can provide the wanted properties */
676 1
    if ((flags & PyBUF_C_CONTIGUOUS) == PyBUF_C_CONTIGUOUS &&
677 1
            !PyArray_CHKFLAGS(self, NPY_ARRAY_C_CONTIGUOUS)) {
678 0
        PyErr_SetString(PyExc_ValueError, "ndarray is not C-contiguous");
679 0
        goto fail;
680
    }
681 1
    if ((flags & PyBUF_F_CONTIGUOUS) == PyBUF_F_CONTIGUOUS &&
682 1
            !PyArray_CHKFLAGS(self, NPY_ARRAY_F_CONTIGUOUS)) {
683 0
        PyErr_SetString(PyExc_ValueError, "ndarray is not Fortran contiguous");
684 0
        goto fail;
685
    }
686 1
    if ((flags & PyBUF_ANY_CONTIGUOUS) == PyBUF_ANY_CONTIGUOUS
687 1
            && !PyArray_ISONESEGMENT(self)) {
688 0
        PyErr_SetString(PyExc_ValueError, "ndarray is not contiguous");
689 0
        goto fail;
690
    }
691 1
    if ((flags & PyBUF_STRIDES) != PyBUF_STRIDES &&
692 1
            !PyArray_CHKFLAGS(self, NPY_ARRAY_C_CONTIGUOUS)) {
693
        /* Non-strided N-dim buffers must be C-contiguous */
694 1
        PyErr_SetString(PyExc_ValueError, "ndarray is not C-contiguous");
695 1
        goto fail;
696
    }
697 1
    if ((flags & PyBUF_WRITEABLE) == PyBUF_WRITEABLE) {
698 1
        if (PyArray_FailUnlessWriteable(self, "buffer source array") < 0) {
699
            goto fail;
700
        }
701
    }
702

703 1
    if (view == NULL) {
704 0
        PyErr_SetString(PyExc_ValueError, "NULL view in getbuffer");
705 0
        goto fail;
706
    }
707

708
    /* Fill in information */
709 1
    info = _buffer_get_info(obj);
710 1
    if (info == NULL) {
711
        goto fail;
712
    }
713

714 1
    view->buf = PyArray_DATA(self);
715 1
    view->suboffsets = NULL;
716 1
    view->itemsize = PyArray_ITEMSIZE(self);
717
    /*
718
     * If a read-only buffer is requested on a read-write array, we return a
719
     * read-write buffer as per buffer protocol.
720
     * We set a requested buffer to readonly also if the array will be readonly
721
     * after a deprecation. This jumps the deprecation, but avoiding the
722
     * warning is not convenient here. A warning is given if a writeable
723
     * buffer is requested since `PyArray_FailUnlessWriteable` is called above
724
     * (and clears the `NPY_ARRAY_WARN_ON_WRITE` flag).
725
     */
726 1
    view->readonly = (!PyArray_ISWRITEABLE(self) ||
727 1
                      PyArray_CHKFLAGS(self, NPY_ARRAY_WARN_ON_WRITE));
728 1
    view->internal = NULL;
729 1
    view->len = PyArray_NBYTES(self);
730 1
    if ((flags & PyBUF_FORMAT) == PyBUF_FORMAT) {
731 1
        view->format = info->format;
732
    } else {
733 1
        view->format = NULL;
734
    }
735 1
    if ((flags & PyBUF_ND) == PyBUF_ND) {
736 1
        view->ndim = info->ndim;
737 1
        view->shape = info->shape;
738
    }
739
    else {
740 1
        view->ndim = 0;
741 1
        view->shape = NULL;
742
    }
743 1
    if ((flags & PyBUF_STRIDES) == PyBUF_STRIDES) {
744 1
        view->strides = info->strides;
745

746
#ifdef NPY_RELAXED_STRIDES_CHECKING
747
        /*
748
         * If NPY_RELAXED_STRIDES_CHECKING is on, the array may be
749
         * contiguous, but it won't look that way to Python when it
750
         * tries to determine contiguity by looking at the strides
751
         * (since one of the elements may be -1).  In that case, just
752
         * regenerate strides from shape.
753
         */
754 1
        if (PyArray_CHKFLAGS(self, NPY_ARRAY_C_CONTIGUOUS) &&
755
                !((flags & PyBUF_F_CONTIGUOUS) == PyBUF_F_CONTIGUOUS)) {
756 1
            Py_ssize_t sd = view->itemsize;
757
            int i;
758

759 1
            for (i = view->ndim-1; i >= 0; --i) {
760 1
                view->strides[i] = sd;
761 1
                sd *= view->shape[i];
762
            }
763
        }
764 1
        else if (PyArray_CHKFLAGS(self, NPY_ARRAY_F_CONTIGUOUS)) {
765 1
            Py_ssize_t sd = view->itemsize;
766
            int i;
767

768 1
            for (i = 0; i < view->ndim; ++i) {
769 1
                view->strides[i] = sd;
770 1
                sd *= view->shape[i];
771
            }
772
        }
773
#endif
774
    }
775
    else {
776 1
        view->strides = NULL;
777
    }
778 1
    view->obj = (PyObject*)self;
779

780 1
    Py_INCREF(self);
781 1
    return 0;
782

783 1
fail:
784
    return -1;
785
}
786

787
/*
788
 * Retrieving buffers for scalars
789
 */
790
int
791 1
void_getbuffer(PyObject *self, Py_buffer *view, int flags)
792
{
793 1
    _buffer_info_t *info = NULL;
794 1
    PyArray_Descr *descr = NULL;
795
    int elsize;
796

797 1
    if (flags & PyBUF_WRITABLE) {
798 0
        PyErr_SetString(PyExc_BufferError, "scalar buffer is readonly");
799 0
        goto fail;
800
    }
801

802
    /* Fill in information */
803 1
    info = _buffer_get_info(self);
804 1
    if (info == NULL) {
805
        goto fail;
806
    }
807

808 1
    view->ndim = info->ndim;
809 1
    view->shape = info->shape;
810 1
    view->strides = info->strides;
811

812 1
    if ((flags & PyBUF_FORMAT) == PyBUF_FORMAT) {
813 1
        view->format = info->format;
814
    } else {
815 1
        view->format = NULL;
816
    }
817

818 1
    descr = PyArray_DescrFromScalar(self);
819 1
    view->buf = (void *)scalar_value(self, descr);
820 1
    elsize = descr->elsize;
821 1
    view->len = elsize;
822 1
    if (PyArray_IsScalar(self, Datetime) || PyArray_IsScalar(self, Timedelta)) {
823
        elsize = 1; /* descr->elsize,char is 8,'M', but we return 1,'B' */
824
    }
825 1
    view->itemsize = elsize;
826

827 1
    Py_DECREF(descr);
828

829 1
    view->readonly = 1;
830 1
    view->suboffsets = NULL;
831 1
    view->obj = self;
832 1
    Py_INCREF(self);
833 1
    return 0;
834

835 1
fail:
836 1
    view->obj = NULL;
837 1
    return -1;
838
}
839

840
/*
841
 * NOTE: for backward compatibility (esp. with PyArg_ParseTuple("s#", ...))
842
 * we do *not* define bf_releasebuffer at all.
843
 *
844
 * Instead, any extra data allocated with the buffer is released only in
845
 * array_dealloc.
846
 *
847
 * Ensuring that the buffer stays in place is taken care by refcounting;
848
 * ndarrays do not reallocate if there are references to them, and a buffer
849
 * view holds one reference.
850
 */
851

852
NPY_NO_EXPORT void
853 1
_dealloc_cached_buffer_info(PyObject *self)
854
{
855 1
    int reset_error_state = 0;
856
    PyObject *ptype, *pvalue, *ptraceback;
857

858
    /* This function may be called when processing an exception --
859
     * we need to stash the error state to avoid confusing PyDict
860
     */
861

862 1
    if (PyErr_Occurred()) {
863 1
        reset_error_state = 1;
864 1
        PyErr_Fetch(&ptype, &pvalue, &ptraceback);
865
    }
866

867 1
    _buffer_clear_info(self);
868

869 1
    if (reset_error_state) {
870 1
        PyErr_Restore(ptype, pvalue, ptraceback);
871
    }
872
}
873

874

875
/*************************************************************************/
876

877
NPY_NO_EXPORT PyBufferProcs array_as_buffer = {
878
    (getbufferproc)array_getbuffer,
879
    (releasebufferproc)0,
880
};
881

882

883
/*************************************************************************
884
 * Convert PEP 3118 format string to PyArray_Descr
885
 */
886

887
static int
888
_descriptor_from_pep3118_format_fast(char const *s, PyObject **result);
889

890
static int
891
_pep3118_letter_to_type(char letter, int native, int complex);
892

893
NPY_NO_EXPORT PyArray_Descr*
894 1
_descriptor_from_pep3118_format(char const *s)
895
{
896
    char *buf, *p;
897 1
    int in_name = 0;
898
    int obtained;
899
    PyObject *descr;
900
    PyObject *str;
901
    PyObject *_numpy_internal;
902

903 1
    if (s == NULL) {
904 0
        return PyArray_DescrNewFromType(NPY_BYTE);
905
    }
906

907
    /* Fast path */
908 1
    obtained = _descriptor_from_pep3118_format_fast(s, &descr);
909 1
    if (obtained) {
910 1
        return (PyArray_Descr*)descr;
911
    }
912

913
    /* Strip whitespace, except from field names */
914 1
    buf = malloc(strlen(s) + 1);
915 1
    if (buf == NULL) {
916 0
        PyErr_NoMemory();
917 0
        return NULL;
918
    }
919
    p = buf;
920 1
    while (*s != '\0') {
921 1
        if (*s == ':') {
922 1
            in_name = !in_name;
923 1
            *p = *s;
924 1
            p++;
925
        }
926 1
        else if (in_name || !NumPyOS_ascii_isspace(*s)) {
927 1
            *p = *s;
928 1
            p++;
929
        }
930 1
        s++;
931
    }
932 1
    *p = '\0';
933

934 1
    str = PyUnicode_FromStringAndSize(buf, strlen(buf));
935 1
    if (str == NULL) {
936 0
        free(buf);
937 0
        return NULL;
938
    }
939

940
    /* Convert */
941 1
    _numpy_internal = PyImport_ImportModule("numpy.core._internal");
942 1
    if (_numpy_internal == NULL) {
943 0
        Py_DECREF(str);
944 0
        free(buf);
945 0
        return NULL;
946
    }
947 1
    descr = PyObject_CallMethod(
948
        _numpy_internal, "_dtype_from_pep3118", "O", str);
949 1
    Py_DECREF(str);
950 1
    Py_DECREF(_numpy_internal);
951 1
    if (descr == NULL) {
952
        PyObject *exc, *val, *tb;
953 1
        PyErr_Fetch(&exc, &val, &tb);
954 1
        PyErr_Format(PyExc_ValueError,
955
                     "'%s' is not a valid PEP 3118 buffer format string", buf);
956 1
        npy_PyErr_ChainExceptionsCause(exc, val, tb);
957 1
        free(buf);
958
        return NULL;
959
    }
960 1
    if (!PyArray_DescrCheck(descr)) {
961 0
        PyErr_Format(PyExc_RuntimeError,
962
                     "internal error: numpy.core._internal._dtype_from_pep3118 "
963
                     "did not return a valid dtype, got %s", buf);
964 0
        Py_DECREF(descr);
965 0
        free(buf);
966 0
        return NULL;
967
    }
968 1
    free(buf);
969 1
    return (PyArray_Descr*)descr;
970
}
971

972
/*
973
 * Fast path for parsing buffer strings corresponding to simple types.
974
 *
975
 * Currently, this deals only with single-element data types.
976
 */
977

978
static int
979 1
_descriptor_from_pep3118_format_fast(char const *s, PyObject **result)
980
{
981
    PyArray_Descr *descr;
982

983 1
    int is_standard_size = 0;
984 1
    char byte_order = '=';
985 1
    int is_complex = 0;
986

987 1
    int type_num = NPY_BYTE;
988 1
    int item_seen = 0;
989

990 1
    for (; *s != '\0'; ++s) {
991 1
        is_complex = 0;
992 1
        switch (*s) {
993
        case '@':
994
        case '^':
995
            /* ^ means no alignment; doesn't matter for a single element */
996
            byte_order = '=';
997
            is_standard_size = 0;
998
            break;
999 1
        case '<':
1000 1
            byte_order = '<';
1001 1
            is_standard_size = 1;
1002 1
            break;
1003 1
        case '>':
1004
        case '!':
1005 1
            byte_order = '>';
1006 1
            is_standard_size = 1;
1007 1
            break;
1008 0
        case '=':
1009 0
            byte_order = '=';
1010 0
            is_standard_size = 1;
1011 0
            break;
1012 1
        case 'Z':
1013 1
            is_complex = 1;
1014 1
            ++s;
1015 1
        default:
1016 1
            if (item_seen) {
1017
                /* Not a single-element data type */
1018
                return 0;
1019
            }
1020 1
            type_num = _pep3118_letter_to_type(*s, !is_standard_size,
1021
                                               is_complex);
1022 1
            if (type_num < 0) {
1023
                /* Something unknown */
1024
                return 0;
1025
            }
1026
            item_seen = 1;
1027
            break;
1028
        }
1029
    }
1030

1031 1
    if (!item_seen) {
1032
        return 0;
1033
    }
1034

1035 1
    descr = PyArray_DescrFromType(type_num);
1036 1
    if (byte_order == '=') {
1037 1
        *result = (PyObject*)descr;
1038
    }
1039
    else {
1040 1
        *result = (PyObject*)PyArray_DescrNewByteorder(descr, byte_order);
1041 1
        Py_DECREF(descr);
1042
    }
1043

1044
    return 1;
1045
}
1046

1047
static int
1048 1
_pep3118_letter_to_type(char letter, int native, int complex)
1049
{
1050 1
    switch (letter)
1051
    {
1052
    case '?': return NPY_BOOL;
1053 1
    case 'b': return NPY_BYTE;
1054 1
    case 'B': return NPY_UBYTE;
1055 1
    case 'h': return native ? NPY_SHORT : NPY_INT16;
1056 1
    case 'H': return native ? NPY_USHORT : NPY_UINT16;
1057 1
    case 'i': return native ? NPY_INT : NPY_INT32;
1058 1
    case 'I': return native ? NPY_UINT : NPY_UINT32;
1059 1
    case 'l': return native ? NPY_LONG : NPY_INT32;
1060 1
    case 'L': return native ? NPY_ULONG : NPY_UINT32;
1061 1
    case 'q': return native ? NPY_LONGLONG : NPY_INT64;
1062 1
    case 'Q': return native ? NPY_ULONGLONG : NPY_UINT64;
1063 1
    case 'e': return NPY_HALF;
1064 1
    case 'f': return complex ? NPY_CFLOAT : NPY_FLOAT;
1065 1
    case 'd': return complex ? NPY_CDOUBLE : NPY_DOUBLE;
1066 1
    case 'g': return native ? (complex ? NPY_CLONGDOUBLE : NPY_LONGDOUBLE) : -1;
1067 1
    default:
1068
        /* Other unhandled cases */
1069 1
        return -1;
1070
    }
1071
    return -1;
1072
}

Read our documentation on viewing source code .

Loading