* Validates that any field of the structured array 'dtype' which has * the NPY_ITEM_HASOBJECT flag set does not overlap with another field. * * This algorithm is worst case O(n^2). It could be done with a sort * and sweep algorithm, but the structured dtype representation is * rather ugly right now, so writing something better can wait until * that representation is made sane. * * Returns
| 917 | * Returns 0 on success, -1 if an exception is raised. |
| 918 | */ |
| 919 | static int |
| 920 | _validate_object_field_overlap(PyArray_Descr *dtype) |
| 921 | { |
| 922 | PyObject *names, *fields, *key, *tup, *title; |
| 923 | Py_ssize_t i, j, names_size; |
| 924 | PyArray_Descr *fld_dtype, *fld2_dtype; |
| 925 | int fld_offset, fld2_offset; |
| 926 | |
| 927 | /* Get some properties from the dtype */ |
| 928 | names = dtype->names; |
| 929 | names_size = PyTuple_GET_SIZE(names); |
| 930 | fields = dtype->fields; |
| 931 | |
| 932 | for (i = 0; i < names_size; ++i) { |
| 933 | key = PyTuple_GET_ITEM(names, i); |
| 934 | if (key == NULL) { |
| 935 | return -1; |
| 936 | } |
| 937 | tup = PyDict_GetItemWithError(fields, key); |
| 938 | if (tup == NULL) { |
| 939 | if (!PyErr_Occurred()) { |
| 940 | /* fields was missing the name it claimed to contain */ |
| 941 | PyErr_BadInternalCall(); |
| 942 | } |
| 943 | return -1; |
| 944 | } |
| 945 | if (!PyArg_ParseTuple(tup, "Oi|O", &fld_dtype, &fld_offset, &title)) { |
| 946 | return -1; |
| 947 | } |
| 948 | |
| 949 | /* If this field has objects, check for overlaps */ |
| 950 | if (PyDataType_REFCHK(fld_dtype)) { |
| 951 | for (j = 0; j < names_size; ++j) { |
| 952 | if (i != j) { |
| 953 | key = PyTuple_GET_ITEM(names, j); |
| 954 | if (key == NULL) { |
| 955 | return -1; |
| 956 | } |
| 957 | tup = PyDict_GetItemWithError(fields, key); |
| 958 | if (tup == NULL) { |
| 959 | if (!PyErr_Occurred()) { |
| 960 | /* fields was missing the name it claimed to contain */ |
| 961 | PyErr_BadInternalCall(); |
| 962 | } |
| 963 | return -1; |
| 964 | } |
| 965 | if (!PyArg_ParseTuple(tup, "Oi|O", &fld2_dtype, |
| 966 | &fld2_offset, &title)) { |
| 967 | return -1; |
| 968 | } |
| 969 | /* Raise an exception if it overlaps */ |
| 970 | if (fld_offset < fld2_offset + fld2_dtype->elsize && |
| 971 | fld2_offset < fld_offset + fld_dtype->elsize) { |
| 972 | PyErr_SetString(PyExc_TypeError, |
| 973 | "Cannot create a NumPy dtype with overlapping " |
| 974 | "object fields"); |
| 975 | return -1; |
| 976 | } |
no outgoing calls
no test coverage detected