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
|
|
}
|