[Numpy-svn] r8136 - in trunk/numpy/core: . src/multiarray

numpy-svn@scip... numpy-svn@scip...
Sat Feb 20 12:05:03 CST 2010


Author: ptvirtan
Date: 2010-02-20 12:05:03 -0600 (Sat, 20 Feb 2010)
New Revision: 8136

Modified:
   trunk/numpy/core/_internal.py
   trunk/numpy/core/src/multiarray/buffer.c
   trunk/numpy/core/src/multiarray/buffer.h
   trunk/numpy/core/src/multiarray/numpyos.c
   trunk/numpy/core/src/multiarray/numpyos.h
Log:
ENH: core: add some support routines needed for consuming PEP 3118 buffers

Modified: trunk/numpy/core/_internal.py
===================================================================
--- trunk/numpy/core/_internal.py	2010-02-20 18:04:43 UTC (rev 8135)
+++ trunk/numpy/core/_internal.py	2010-02-20 18:05:03 UTC (rev 8136)
@@ -347,3 +347,125 @@
 
     return newarray
     
+# Given a string containing a PEP 3118 format specifier,
+# construct a Numpy dtype
+
+_pep3118_map = {
+    'b': 'b',
+    'B': 'B',
+    'h': 'h',
+    'H': 'H',
+    'i': 'i',
+    'I': 'I',
+    'l': 'l',
+    'L': 'L',
+    'q': 'q',
+    'Q': 'Q',
+    'f': 'f',
+    'd': 'd',
+    'g': 'g',
+    'Q': 'Q',
+    'Zf': 'F',
+    'Zd': 'D',
+    'Zg': 'G',
+    's': 'S',
+    'w': 'U',
+    'O': 'O',
+    'x': 'V', # padding
+}
+
+def _dtype_from_pep3118(spec, byteorder='=', is_subdtype=False):
+    from numpy.core.multiarray import dtype
+
+    fields = {}
+    offset = 0
+    findex = 0
+    explicit_name = False
+
+    while spec:
+        value = None
+
+        # End of structure, bail out to upper level
+        if spec[0] == '}':
+            spec = spec[1:]
+            break
+
+        # Sub-arrays (1)
+        shape = None
+        if spec[0] == '(':
+            j = spec.index(')')
+            shape = tuple(map(int, spec[1:j].split(',')))
+            spec = spec[j+1:]
+
+        # Byte order
+        if spec[0] in ('=', '<', '>'):
+            byteorder = spec[0]
+            spec = spec[1:]
+
+        # Item sizes
+        itemsize = 1
+        if spec[0].isdigit():
+            j = 1
+            for j in xrange(1, len(spec)):
+                if not spec[j].isdigit():
+                    break
+            itemsize = int(spec[:j])
+            spec = spec[j:]
+
+        # Data types
+        is_padding = False
+
+        if spec[:2] == 'T{':
+            value, spec = _dtype_from_pep3118(spec[2:], byteorder=byteorder,
+                                              is_subdtype=True)
+            if itemsize != 1:
+                # Not supported
+                raise ValueError("Non item-size 1 structures not supported")
+        elif spec[0].isalpha():
+            j = 1
+            for j in xrange(1, len(spec)):
+                if not spec[j].isalpha():
+                    break
+            typechar = spec[:j]
+            spec = spec[j:]
+            is_padding = (typechar == 'x')
+            dtypechar = _pep3118_map[typechar]
+            if dtypechar in 'USV':
+                dtypechar += '%d' % itemsize
+                itemsize = 1
+            value = dtype(byteorder + dtypechar)
+        else:
+            raise ValueError("Unknown PEP 3118 data type specifier %r" % spec)
+
+        # Convert itemsize to sub-array
+        if itemsize != 1:
+            value = dtype((value, (itemsize,)))
+
+        # Sub-arrays (2)
+        if shape is not None:
+            value = dtype((value, shape))
+
+        # Field name
+        if spec and spec.startswith(':'):
+            i = spec[1:].index(':') + 1
+            name = spec[1:i]
+            spec = spec[i+1:]
+            explicit_name = True
+        else:
+            name = 'f%d' % findex
+            findex += 1
+
+        if not is_padding:
+            fields[name] = (value, offset)
+        offset += value.itemsize
+
+
+    if len(fields.keys()) == 1 and not explicit_name and fields['f0'][1] == 0:
+        ret = fields['f0'][0]
+    else:
+        ret = dtype(fields)
+
+    if is_subdtype:
+        return ret, spec
+    else:
+        return ret

Modified: trunk/numpy/core/src/multiarray/buffer.c
===================================================================
--- trunk/numpy/core/src/multiarray/buffer.c	2010-02-20 18:04:43 UTC (rev 8135)
+++ trunk/numpy/core/src/multiarray/buffer.c	2010-02-20 18:05:03 UTC (rev 8136)
@@ -594,3 +594,67 @@
     (releasebufferproc)0,
 #endif
 };
+
+
+/*************************************************************************
+ * Convert PEP 3118 format string to PyArray_Descr
+ */
+#if PY_VERSION_HEX >= 0x02060000
+
+NPY_NO_EXPORT PyArray_Descr*
+_descriptor_from_pep3118_format(char *s)
+{
+    char *buf, *p;
+    int in_name = 0;
+    PyArray_Descr *descr;
+    PyObject *str;
+    PyObject *_numpy_internal;
+
+    if (s == NULL) {
+        return PyArray_DescrNewFromType(PyArray_BYTE);
+    }
+
+    /* Strip whitespace, except from field names */
+    buf = (char*)malloc(strlen(s) + 1);
+    p = buf;
+    while (*s != '\0') {
+        if (*s == ':') {
+            in_name = !in_name;
+            *p = *s;
+        }
+        else if (in_name || !NumPyOS_ascii_isspace(*s)) {
+            *p = *s;
+        }
+        ++p;
+        ++s;
+    }
+    *p = '\0';
+
+    /* Convert */
+    _numpy_internal = PyImport_ImportModule("numpy.core._internal");
+    if (_numpy_internal == NULL) {
+        return NULL;
+    }
+    str = PyUString_FromStringAndSize(buf, strlen(buf));
+    descr = PyObject_CallMethod(_numpy_internal, "_dtype_from_pep3118",
+                                "O", str);
+    Py_DECREF(str);
+    if (descr == NULL) {
+        PyErr_Format(PyExc_ValueError,
+                     "'%s' is not a valid PEP 3118 buffer format string", buf);
+    }
+    free(buf);
+    return descr;
+}
+
+#else
+
+NPY_NO_EXPORT PyArray_Descr*
+_descriptor_from_pep3118_format(char *s)
+{
+    PyErr_SetString(PyExc_RuntimeError,
+                    "PEP 3118 is not supported on Python versions < 2.6");
+    return NULL;
+}
+
+#endif

Modified: trunk/numpy/core/src/multiarray/buffer.h
===================================================================
--- trunk/numpy/core/src/multiarray/buffer.h	2010-02-20 18:04:43 UTC (rev 8135)
+++ trunk/numpy/core/src/multiarray/buffer.h	2010-02-20 18:05:03 UTC (rev 8136)
@@ -10,4 +10,7 @@
 NPY_NO_EXPORT void
 _array_dealloc_buffer_info(PyArrayObject *self);
 
+NPY_NO_EXPORT PyArray_Descr*
+_descriptor_from_pep3118_format(char *s);
+
 #endif

Modified: trunk/numpy/core/src/multiarray/numpyos.c
===================================================================
--- trunk/numpy/core/src/multiarray/numpyos.c	2010-02-20 18:04:43 UTC (rev 8135)
+++ trunk/numpy/core/src/multiarray/numpyos.c	2010-02-20 18:05:03 UTC (rev 8136)
@@ -336,7 +336,7 @@
  *
  * Same as isspace under C locale
  */
-static int
+NPY_NO_EXPORT int
 NumPyOS_ascii_isspace(char c)
 {
     return c == ' ' || c == '\f' || c == '\n' || c == '\r' || c == '\t'

Modified: trunk/numpy/core/src/multiarray/numpyos.h
===================================================================
--- trunk/numpy/core/src/multiarray/numpyos.h	2010-02-20 18:04:43 UTC (rev 8135)
+++ trunk/numpy/core/src/multiarray/numpyos.h	2010-02-20 18:05:03 UTC (rev 8136)
@@ -22,4 +22,7 @@
 NPY_NO_EXPORT int
 NumPyOS_ascii_ftolf(FILE *fp, double *value);
 
+NPY_NO_EXPORT int
+NumPyOS_ascii_isspace(char c);
+
 #endif



More information about the Numpy-svn mailing list