Skip to content

Commit

Permalink
Fix byte-order problems in comma-string formats and size-specified fi…
Browse files Browse the repository at this point in the history
…elds.
  • Loading branch information
teoliphant committed Aug 10, 2006
1 parent 217ae0e commit 8959e33
Show file tree
Hide file tree
Showing 2 changed files with 54 additions and 24 deletions.
29 changes: 27 additions & 2 deletions numpy/core/_internal.py
Expand Up @@ -4,6 +4,12 @@

import re
from multiarray import dtype, ndarray
import sys

if (sys.byteorder == 'little'):
_nbo = '<'
else:
_nbo = '>'

def _makenames_list(adict):
allfields = []
Expand Down Expand Up @@ -141,10 +147,15 @@ def _split(input):

return newlist

format_re = re.compile(r'(?P<repeat> *[(]?[ ,0-9]*[)]? *)(?P<dtype>[><|A-Za-z0-9.]*)')
format_re = re.compile(r'(?P<order1>[<>|=]?)(?P<repeats> *[(]?[ ,0-9]*[)]? *)(?P<order2>[<>|=]?)(?P<dtype>[A-Za-z0-9.]*)')

# astr is a string (perhaps comma separated)

_convorder = {'=': _nbo,
'|': '|',
'>': '>',
'<': '<'}

def _commastring(astr):
res = _split(astr)
if (len(res)) < 1:
Expand All @@ -153,10 +164,24 @@ def _commastring(astr):
for k,item in enumerate(res):
# convert item
try:
(repeats, dtype) = format_re.match(item).groups()
(order1, repeats, order2, dtype) = format_re.match(item).groups()
except (TypeError, AttributeError):
raise ValueError('format %s is not recognized' % item)

if order2 == '':
order = order1
elif order1 == '':
order = order2
else:
order1 = _convorder[order1]
order2 = _convorder[order2]
if (order1 != order2):
raise ValueError('in-consistent byte-order specification %s and %s' % (order1, order2))
order = order1

if order in ['|', '=', _nbo]:
order = ''
dtype = '%s%s' % (order, dtype)
if (repeats == ''):
newitem = dtype
else:
Expand Down
49 changes: 27 additions & 22 deletions numpy/core/src/multiarraymodule.c
Expand Up @@ -4193,13 +4193,19 @@ _convert_from_dict(PyObject *obj, int align)
}

static int
_could_be_commastring(char *type, int len)
_check_for_commastring(char *type, int len)
{
int i;
if (type[0] >= '1' && type[0] <= '9') return 1;

if ((type[0] >= '0' && type[0] <= '9') ||
((len > 1) && (type[0] == '>' || type[0] == '<' || \
type[0] == '|' || type[0] == '=') && \
(type[1] >= '0' && type[1] <= '9')))
return 1;
for (i=1;i<len;i++)
if (type[i] == ',') return 1;
return 0;

return 0;
}

/*
Expand Down Expand Up @@ -4303,26 +4309,25 @@ PyArray_DescrConverter(PyObject *obj, PyArray_Descr **at)
type = PyString_AS_STRING(obj);
len = PyString_GET_SIZE(obj);
if (len <= 0) goto fail;
check_num = (int) type[0];
if ((char) check_num == '>' || (char) check_num == '<' || \
(char) check_num == '|' || (char) check_num == '=') {
if (len <= 1) goto fail;
endian = (char) check_num;
type++; len--;
check_num = (int) type[0];
if (endian == '|') endian = '=';
}
if (len > 1) {

/* check for commas present
or first (or second) element a digit */
if (_check_for_commastring(type, len)) {
*at = _convert_from_commastring(obj, 0);
if (*at) return PY_SUCCEED;
return PY_FAIL;
}
check_num = (int) type[0];
if ((char) check_num == '>' || (char) check_num == '<' || \
(char) check_num == '|' || (char) check_num == '=') {
if (len <= 1) goto fail;
endian = (char) check_num;
type++; len--;
check_num = (int) type[0];
if (endian == '|') endian = '=';
}
if (len > 1) {
elsize = atoi(type+1);
/* check for commas present
or first element a digit */
if (_could_be_commastring(type, len)) {
/* see if it can be converted from
a comma-separated string */
*at = _convert_from_commastring(obj, 0);
if (*at) return PY_SUCCEED;
else return PY_FAIL;
}
if (elsize == 0) {
check_num = PyArray_NOTYPE+10;
}
Expand Down

0 comments on commit 8959e33

Please sign in to comment.