/* * check whether arrays with datatype dtype might have object fields. This will * only happen for structured dtypes (which may have hidden objects even if the * HASOBJECT flag is false), object dtypes, or subarray dtypes whose base type * is either of these. */ NPY_NO_EXPORT int _may_have_objects(PyArray_Descr *dtype) { PyArray_Descr *base = dtype; if (PyDataType_HASSUBARRAY(dtype)) { base = dtype->subarray->base; } return (PyDataType_HASFIELDS(base) || PyDataType_FLAGCHK(base, NPY_ITEM_HASOBJECT) ); }
static PyObject * reorderdtype(PyObject * self, PyObject * args, PyObject * kwds) { PyObject *order = NULL; PyArray_Descr *newd, *dtype; static char *kwlist[] = {"dtype", "order", NULL}; if (!PyArg_ParseTupleAndKeywords(args, kwds, "O!O", kwlist, &PyArrayDescr_Type, &dtype, &order)) { return NULL; } printf("compare, %p argsort %p %p %p\n", dtype->f->compare, dtype->f->argsort[0], dtype->f->argsort[1], dtype->f->argsort[2] ); PyObject *new_name; PyObject *_numpy_internal; if (!PyDataType_HASFIELDS(dtype)) { PyErr_SetString(PyExc_ValueError, "Cannot specify " "order when the array has no fields."); return NULL; } _numpy_internal = PyImport_ImportModule("numpy.core._internal"); if (_numpy_internal == NULL) { return NULL; } new_name = PyObject_CallMethod(_numpy_internal, "_newnames", "OO", dtype, order); Py_DECREF(_numpy_internal); if (new_name == NULL) { return NULL; } newd = PyArray_DescrNew(dtype); newd->names = new_name; return newd; }
static int _buffer_format_string(PyArray_Descr *descr, _tmp_string_t *str, PyArrayObject* arr, Py_ssize_t *offset, char *active_byteorder) { int k; char _active_byteorder = '@'; Py_ssize_t _offset = 0; if (active_byteorder == NULL) { active_byteorder = &_active_byteorder; } if (offset == NULL) { offset = &_offset; } if (descr->subarray) { PyObject *item, *subarray_tuple; Py_ssize_t total_count = 1; Py_ssize_t dim_size; char buf[128]; int old_offset; int ret; if (PyTuple_Check(descr->subarray->shape)) { subarray_tuple = descr->subarray->shape; Py_INCREF(subarray_tuple); } else { subarray_tuple = Py_BuildValue("(O)", descr->subarray->shape); } _append_char(str, '('); for (k = 0; k < PyTuple_GET_SIZE(subarray_tuple); ++k) { if (k > 0) { _append_char(str, ','); } item = PyTuple_GET_ITEM(subarray_tuple, k); dim_size = PyNumber_AsSsize_t(item, NULL); PyOS_snprintf(buf, sizeof(buf), "%ld", (long)dim_size); _append_str(str, buf); total_count *= dim_size; } _append_char(str, ')'); Py_DECREF(subarray_tuple); old_offset = *offset; ret = _buffer_format_string(descr->subarray->base, str, arr, offset, active_byteorder); *offset = old_offset + (*offset - old_offset) * total_count; return ret; } else if (PyDataType_HASFIELDS(descr)) { int base_offset = *offset; _append_str(str, "T{"); for (k = 0; k < PyTuple_GET_SIZE(descr->names); ++k) { PyObject *name, *item, *offset_obj, *tmp; PyArray_Descr *child; char *p; Py_ssize_t len; int new_offset; name = PyTuple_GET_ITEM(descr->names, k); item = PyDict_GetItem(descr->fields, name); child = (PyArray_Descr*)PyTuple_GetItem(item, 0); offset_obj = PyTuple_GetItem(item, 1); new_offset = base_offset + PyInt_AsLong(offset_obj); /* Insert padding manually */ if (*offset > new_offset) { PyErr_SetString(PyExc_RuntimeError, "This should never happen: Invalid offset in " "buffer format string generation. Please " "report a bug to the Numpy developers."); return -1; } while (*offset < new_offset) { _append_char(str, 'x'); ++*offset; } /* Insert child item */ _buffer_format_string(child, str, arr, offset, active_byteorder); /* Insert field name */ #if defined(NPY_PY3K) /* FIXME: XXX -- should it use UTF-8 here? */ tmp = PyUnicode_AsUTF8String(name); #else tmp = name; #endif if (tmp == NULL || PyBytes_AsStringAndSize(tmp, &p, &len) < 0) { PyErr_SetString(PyExc_ValueError, "invalid field name"); return -1; } _append_char(str, ':'); while (len > 0) { if (*p == ':') { Py_DECREF(tmp); PyErr_SetString(PyExc_ValueError, "':' is not an allowed character in buffer " "field names"); return -1; } _append_char(str, *p); ++p; --len; } _append_char(str, ':'); #if defined(NPY_PY3K) Py_DECREF(tmp); #endif } _append_char(str, '}'); } else { int is_standard_size = 1; int is_native_only_type = (descr->type_num == NPY_LONGDOUBLE || descr->type_num == NPY_CLONGDOUBLE); #if NPY_SIZEOF_LONG_LONG != 8 is_native_only_type = is_native_only_type || ( descr->type_num == NPY_LONGLONG || descr->type_num == NPY_ULONGLONG); #endif *offset += descr->elsize; if (descr->byteorder == '=' && _is_natively_aligned_at(descr, arr, *offset)) { /* Prefer native types, to cater for Cython */ is_standard_size = 0; if (*active_byteorder != '@') { _append_char(str, '@'); *active_byteorder = '@'; } } else if (descr->byteorder == '=' && is_native_only_type) { /* Data types that have no standard size */ is_standard_size = 0; if (*active_byteorder != '^') { _append_char(str, '^'); *active_byteorder = '^'; } } else if (descr->byteorder == '<' || descr->byteorder == '>' || descr->byteorder == '=') { is_standard_size = 1; if (*active_byteorder != descr->byteorder) { _append_char(str, descr->byteorder); *active_byteorder = descr->byteorder; } if (is_native_only_type) { /* * It's not possible to express native-only data types * in non-native npy_byte orders */ PyErr_Format(PyExc_ValueError, "cannot expose native-only dtype '%c' in " "non-native byte order '%c' via buffer interface", descr->type, descr->byteorder); } } switch (descr->type_num) { case NPY_BOOL: if (_append_char(str, '?')) return -1; break; case NPY_BYTE: if (_append_char(str, 'b')) return -1; break; case NPY_UBYTE: if (_append_char(str, 'B')) return -1; break; case NPY_SHORT: if (_append_char(str, 'h')) return -1; break; case NPY_USHORT: if (_append_char(str, 'H')) return -1; break; case NPY_INT: if (_append_char(str, 'i')) return -1; break; case NPY_UINT: if (_append_char(str, 'I')) return -1; break; case NPY_LONG: if (is_standard_size && (NPY_SIZEOF_LONG == 8)) { if (_append_char(str, 'q')) return -1; } else { if (_append_char(str, 'l')) return -1; } break; case NPY_ULONG: if (is_standard_size && (NPY_SIZEOF_LONG == 8)) { if (_append_char(str, 'Q')) return -1; } else { if (_append_char(str, 'L')) return -1; } break; case NPY_LONGLONG: if (_append_char(str, 'q')) return -1; break; case NPY_ULONGLONG: if (_append_char(str, 'Q')) return -1; break; case NPY_HALF: if (_append_char(str, 'e')) return -1; break; case NPY_FLOAT: if (_append_char(str, 'f')) return -1; break; case NPY_DOUBLE: if (_append_char(str, 'd')) return -1; break; case NPY_LONGDOUBLE: if (_append_char(str, 'g')) return -1; break; case NPY_CFLOAT: if (_append_str(str, "Zf")) return -1; break; case NPY_CDOUBLE: if (_append_str(str, "Zd")) return -1; break; case NPY_CLONGDOUBLE: if (_append_str(str, "Zg")) return -1; break; /* XXX: datetime */ /* XXX: timedelta */ case NPY_OBJECT: if (_append_char(str, 'O')) return -1; break; case NPY_STRING: { char buf[128]; PyOS_snprintf(buf, sizeof(buf), "%ds", descr->elsize); if (_append_str(str, buf)) return -1; break; } case NPY_UNICODE: { /* Numpy Unicode is always 4-byte */ char buf[128]; assert(descr->elsize % 4 == 0); PyOS_snprintf(buf, sizeof(buf), "%dw", descr->elsize / 4); if (_append_str(str, buf)) return -1; break; } case NPY_VOID: { /* Insert padding bytes */ char buf[128]; PyOS_snprintf(buf, sizeof(buf), "%dx", descr->elsize); if (_append_str(str, buf)) return -1; break; } default: PyErr_Format(PyExc_ValueError, "cannot include dtype '%c' in a buffer", descr->type); return -1; } } return 0; }
/* * Fill in str with an appropriate PEP 3118 format string, based on * descr. For structured dtypes, calls itself recursively. Each call extends * str at offset then updates offset, and uses descr->byteorder, (and * possibly the byte order in obj) to determine the byte-order char. * * Returns 0 for success, -1 for failure */ static int _buffer_format_string(PyArray_Descr *descr, _tmp_string_t *str, PyObject* obj, Py_ssize_t *offset, char *active_byteorder) { int k; char _active_byteorder = '@'; Py_ssize_t _offset = 0; if (active_byteorder == NULL) { active_byteorder = &_active_byteorder; } if (offset == NULL) { offset = &_offset; } if (descr->subarray) { PyObject *item, *subarray_tuple; Py_ssize_t total_count = 1; Py_ssize_t dim_size; Py_ssize_t old_offset; char buf[128]; int ret; if (PyTuple_Check(descr->subarray->shape)) { subarray_tuple = descr->subarray->shape; Py_INCREF(subarray_tuple); } else { subarray_tuple = Py_BuildValue("(O)", descr->subarray->shape); } if (_append_char(str, '(') < 0) { ret = -1; goto subarray_fail; } for (k = 0; k < PyTuple_GET_SIZE(subarray_tuple); ++k) { if (k > 0) { if (_append_char(str, ',') < 0) { ret = -1; goto subarray_fail; } } item = PyTuple_GET_ITEM(subarray_tuple, k); dim_size = PyNumber_AsSsize_t(item, NULL); PyOS_snprintf(buf, sizeof(buf), "%ld", (long)dim_size); if (_append_str(str, buf) < 0) { ret = -1; goto subarray_fail; } total_count *= dim_size; } if (_append_char(str, ')') < 0) { ret = -1; goto subarray_fail; } old_offset = *offset; ret = _buffer_format_string(descr->subarray->base, str, obj, offset, active_byteorder); *offset = old_offset + (*offset - old_offset) * total_count; subarray_fail: Py_DECREF(subarray_tuple); return ret; } else if (PyDataType_HASFIELDS(descr)) { Py_ssize_t base_offset = *offset; if (_append_str(str, "T{") < 0) return -1; for (k = 0; k < PyTuple_GET_SIZE(descr->names); ++k) { PyObject *name, *item, *offset_obj; PyArray_Descr *child; Py_ssize_t new_offset; int ret; name = PyTuple_GET_ITEM(descr->names, k); item = PyDict_GetItem(descr->fields, name); child = (PyArray_Descr*)PyTuple_GetItem(item, 0); offset_obj = PyTuple_GetItem(item, 1); new_offset = PyInt_AsLong(offset_obj); if (error_converting(new_offset)) { return -1; } new_offset += base_offset; /* Insert padding manually */ if (*offset > new_offset) { PyErr_SetString( PyExc_ValueError, "dtypes with overlapping or out-of-order fields are not " "representable as buffers. Consider reordering the fields." ); return -1; } while (*offset < new_offset) { if (_append_char(str, 'x') < 0) return -1; ++*offset; } /* Insert child item */ ret = _buffer_format_string(child, str, obj, offset, active_byteorder); if (ret < 0) { return -1; } /* Insert field name */ if (_append_field_name(str, name) < 0) return -1; } if (_append_char(str, '}') < 0) return -1; } else { int is_standard_size = 1; int is_natively_aligned; int is_native_only_type = (descr->type_num == NPY_LONGDOUBLE || descr->type_num == NPY_CLONGDOUBLE); if (sizeof(npy_longlong) != 8) { is_native_only_type = is_native_only_type || ( descr->type_num == NPY_LONGLONG || descr->type_num == NPY_ULONGLONG); } *offset += descr->elsize; if (PyArray_IsScalar(obj, Generic)) { /* scalars are always natively aligned */ is_natively_aligned = 1; } else { is_natively_aligned = _is_natively_aligned_at(descr, (PyArrayObject*)obj, *offset); } if (descr->byteorder == '=' && is_natively_aligned) { /* Prefer native types, to cater for Cython */ is_standard_size = 0; if (*active_byteorder != '@') { if (_append_char(str, '@') < 0) return -1; *active_byteorder = '@'; } } else if (descr->byteorder == '=' && is_native_only_type) { /* Data types that have no standard size */ is_standard_size = 0; if (*active_byteorder != '^') { if (_append_char(str, '^') < 0) return -1; *active_byteorder = '^'; } } else if (descr->byteorder == '<' || descr->byteorder == '>' || descr->byteorder == '=') { is_standard_size = 1; if (*active_byteorder != descr->byteorder) { if (_append_char(str, descr->byteorder) < 0) return -1; *active_byteorder = descr->byteorder; } if (is_native_only_type) { /* * It's not possible to express native-only data types * in non-native npy_byte orders */ PyErr_Format(PyExc_ValueError, "cannot expose native-only dtype '%c' in " "non-native byte order '%c' via buffer interface", descr->type, descr->byteorder); return -1; } } switch (descr->type_num) { case NPY_BOOL: if (_append_char(str, '?') < 0) return -1; break; case NPY_BYTE: if (_append_char(str, 'b') < 0) return -1; break; case NPY_UBYTE: if (_append_char(str, 'B') < 0) return -1; break; case NPY_SHORT: if (_append_char(str, 'h') < 0) return -1; break; case NPY_USHORT: if (_append_char(str, 'H') < 0) return -1; break; case NPY_INT: if (_append_char(str, 'i') < 0) return -1; break; case NPY_UINT: if (_append_char(str, 'I') < 0) return -1; break; case NPY_LONG: if (is_standard_size && (NPY_SIZEOF_LONG == 8)) { if (_append_char(str, 'q') < 0) return -1; } else { if (_append_char(str, 'l') < 0) return -1; } break; case NPY_ULONG: if (is_standard_size && (NPY_SIZEOF_LONG == 8)) { if (_append_char(str, 'Q') < 0) return -1; } else { if (_append_char(str, 'L') < 0) return -1; } break; case NPY_LONGLONG: if (_append_char(str, 'q') < 0) return -1; break; case NPY_ULONGLONG: if (_append_char(str, 'Q') < 0) return -1; break; case NPY_HALF: if (_append_char(str, 'e') < 0) return -1; break; case NPY_FLOAT: if (_append_char(str, 'f') < 0) return -1; break; case NPY_DOUBLE: if (_append_char(str, 'd') < 0) return -1; break; case NPY_LONGDOUBLE: if (_append_char(str, 'g') < 0) return -1; break; case NPY_CFLOAT: if (_append_str(str, "Zf") < 0) return -1; break; case NPY_CDOUBLE: if (_append_str(str, "Zd") < 0) return -1; break; case NPY_CLONGDOUBLE: if (_append_str(str, "Zg") < 0) return -1; break; /* XXX NPY_DATETIME */ /* XXX NPY_TIMEDELTA */ case NPY_OBJECT: if (_append_char(str, 'O') < 0) return -1; break; case NPY_STRING: { char buf[128]; PyOS_snprintf(buf, sizeof(buf), "%ds", descr->elsize); if (_append_str(str, buf) < 0) return -1; break; } case NPY_UNICODE: { /* NumPy Unicode is always 4-byte */ char buf[128]; assert(descr->elsize % 4 == 0); PyOS_snprintf(buf, sizeof(buf), "%dw", descr->elsize / 4); if (_append_str(str, buf) < 0) return -1; break; } case NPY_VOID: { /* Insert padding bytes */ char buf[128]; PyOS_snprintf(buf, sizeof(buf), "%dx", descr->elsize); if (_append_str(str, buf) < 0) return -1; break; } default: PyErr_Format(PyExc_ValueError, "cannot include dtype '%c' in a buffer", descr->type); return -1; } } return 0; }