LCOV - code coverage report
Current view: top level - Modules - _struct.c (source / functions) Hit Total Coverage
Test: CPython lcov report Lines: 158 859 18.4 %
Date: 2017-04-19 Functions: 13 88 14.8 %

          Line data    Source code
       1             : /* struct module -- pack values into and (out of) strings */
       2             : 
       3             : /* New version supporting byte order, alignment and size options,
       4             :    character strings, and unsigned numbers */
       5             : 
       6             : #define PY_SSIZE_T_CLEAN
       7             : 
       8             : #include "Python.h"
       9             : #include "structseq.h"
      10             : #include "structmember.h"
      11             : #include <ctype.h>
      12             : 
      13             : static PyTypeObject PyStructType;
      14             : 
      15             : /* compatibility macros */
      16             : #if (PY_VERSION_HEX < 0x02050000)
      17             : typedef int Py_ssize_t;
      18             : #endif
      19             : 
      20             : /* warning messages */
      21             : #define FLOAT_COERCE_WARN "integer argument expected, got float"
      22             : #define NON_INTEGER_WARN "integer argument expected, got non-integer " \
      23             :     "(implicit conversion using __int__ is deprecated)"
      24             : 
      25             : 
      26             : /* The translation function for each format character is table driven */
      27             : typedef struct _formatdef {
      28             :     char format;
      29             :     Py_ssize_t size;
      30             :     Py_ssize_t alignment;
      31             :     PyObject* (*unpack)(const char *,
      32             :                         const struct _formatdef *);
      33             :     int (*pack)(char *, PyObject *,
      34             :                 const struct _formatdef *);
      35             : } formatdef;
      36             : 
      37             : typedef struct _formatcode {
      38             :     const struct _formatdef *fmtdef;
      39             :     Py_ssize_t offset;
      40             :     Py_ssize_t size;
      41             : } formatcode;
      42             : 
      43             : /* Struct object interface */
      44             : 
      45             : typedef struct {
      46             :     PyObject_HEAD
      47             :     Py_ssize_t s_size;
      48             :     Py_ssize_t s_len;
      49             :     formatcode *s_codes;
      50             :     PyObject *s_format;
      51             :     PyObject *weakreflist; /* List of weak references */
      52             : } PyStructObject;
      53             : 
      54             : 
      55             : #define PyStruct_Check(op) PyObject_TypeCheck(op, &PyStructType)
      56             : #define PyStruct_CheckExact(op) (Py_TYPE(op) == &PyStructType)
      57             : 
      58             : 
      59             : /* Exception */
      60             : 
      61             : static PyObject *StructError;
      62             : 
      63             : 
      64             : /* Define various structs to figure out the alignments of types */
      65             : 
      66             : 
      67             : typedef struct { char c; short x; } st_short;
      68             : typedef struct { char c; int x; } st_int;
      69             : typedef struct { char c; long x; } st_long;
      70             : typedef struct { char c; float x; } st_float;
      71             : typedef struct { char c; double x; } st_double;
      72             : typedef struct { char c; void *x; } st_void_p;
      73             : 
      74             : #define SHORT_ALIGN (sizeof(st_short) - sizeof(short))
      75             : #define INT_ALIGN (sizeof(st_int) - sizeof(int))
      76             : #define LONG_ALIGN (sizeof(st_long) - sizeof(long))
      77             : #define FLOAT_ALIGN (sizeof(st_float) - sizeof(float))
      78             : #define DOUBLE_ALIGN (sizeof(st_double) - sizeof(double))
      79             : #define VOID_P_ALIGN (sizeof(st_void_p) - sizeof(void *))
      80             : 
      81             : /* We can't support q and Q in native mode unless the compiler does;
      82             :    in std mode, they're 8 bytes on all platforms. */
      83             : #ifdef HAVE_LONG_LONG
      84             : typedef struct { char c; PY_LONG_LONG x; } s_long_long;
      85             : #define LONG_LONG_ALIGN (sizeof(s_long_long) - sizeof(PY_LONG_LONG))
      86             : #endif
      87             : 
      88             : #ifdef HAVE_C99_BOOL
      89             : #define BOOL_TYPE _Bool
      90             : typedef struct { char c; _Bool x; } s_bool;
      91             : #define BOOL_ALIGN (sizeof(s_bool) - sizeof(BOOL_TYPE))
      92             : #else
      93             : #define BOOL_TYPE char
      94             : #define BOOL_ALIGN 0
      95             : #endif
      96             : 
      97             : #define STRINGIFY(x)    #x
      98             : 
      99             : #ifdef __powerc
     100             : #pragma options align=reset
     101             : #endif
     102             : 
     103             : static char *integer_codes = "bBhHiIlLqQ";
     104             : 
     105             : /* Helper to get a PyLongObject by hook or by crook.  Caller should decref. */
     106             : 
     107             : static PyObject *
     108           0 : get_pylong(PyObject *v)
     109             : {
     110             :     PyObject *r, *w;
     111           0 :     int converted = 0;
     112             :     assert(v != NULL);
     113           0 :     if (!PyInt_Check(v) && !PyLong_Check(v)) {
     114             :         PyNumberMethods *m;
     115             :         /* Not an integer; first try to use __index__ to
     116             :            convert to an integer.  If the __index__ method
     117             :            doesn't exist, or raises a TypeError, try __int__.
     118             :            Use of the latter is deprecated, and will fail in
     119             :            Python 3.x. */
     120             : 
     121           0 :         m = Py_TYPE(v)->tp_as_number;
     122           0 :         if (PyIndex_Check(v)) {
     123           0 :             w = PyNumber_Index(v);
     124           0 :             if (w != NULL) {
     125           0 :                 v = w;
     126             :                 /* successfully converted to an integer */
     127           0 :                 converted = 1;
     128             :             }
     129           0 :             else if (PyErr_ExceptionMatches(PyExc_TypeError)) {
     130           0 :                 PyErr_Clear();
     131             :             }
     132             :             else
     133           0 :                 return NULL;
     134             :         }
     135           0 :         if (!converted && m != NULL && m->nb_int != NULL) {
     136             :             /* Special case warning message for floats, for
     137             :                backwards compatibility. */
     138           0 :             if (PyFloat_Check(v)) {
     139           0 :                 if (PyErr_WarnEx(
     140             :                             PyExc_DeprecationWarning,
     141             :                             FLOAT_COERCE_WARN, 1))
     142           0 :                     return NULL;
     143             :             }
     144             :             else {
     145           0 :                 if (PyErr_WarnEx(
     146             :                             PyExc_DeprecationWarning,
     147             :                             NON_INTEGER_WARN, 1))
     148           0 :                     return NULL;
     149             :             }
     150           0 :             v = m->nb_int(v);
     151           0 :             if (v == NULL)
     152           0 :                 return NULL;
     153           0 :             if (!PyInt_Check(v) && !PyLong_Check(v)) {
     154           0 :                 PyErr_SetString(PyExc_TypeError,
     155             :                                 "__int__ method returned "
     156             :                                 "non-integer");
     157           0 :                 return NULL;
     158             :             }
     159           0 :             converted = 1;
     160             :         }
     161           0 :         if (!converted) {
     162           0 :             PyErr_SetString(StructError,
     163             :                             "cannot convert argument "
     164             :                             "to integer");
     165           0 :             return NULL;
     166             :         }
     167             :     }
     168             :     else
     169             :         /* Ensure we own a reference to v. */
     170           0 :         Py_INCREF(v);
     171             : 
     172             :     assert(PyInt_Check(v) || PyLong_Check(v));
     173           0 :     if (PyInt_Check(v)) {
     174           0 :         r = PyLong_FromLong(PyInt_AS_LONG(v));
     175           0 :         Py_DECREF(v);
     176             :     }
     177           0 :     else if (PyLong_Check(v)) {
     178             :         assert(PyLong_Check(v));
     179           0 :         r = v;
     180             :     }
     181             :     else {
     182           0 :         r = NULL;   /* silence compiler warning about
     183             :                        possibly uninitialized variable */
     184             :         assert(0);  /* shouldn't ever get here */
     185             :     }
     186             : 
     187           0 :     return r;
     188             : }
     189             : 
     190             : /* Helper to convert a Python object to a C long.  Sets an exception
     191             :    (struct.error for an inconvertible type, OverflowError for
     192             :    out-of-range values) and returns -1 on error. */
     193             : 
     194             : static int
     195           0 : get_long(PyObject *v, long *p)
     196             : {
     197             :     long x;
     198             : 
     199           0 :     v = get_pylong(v);
     200           0 :     if (v == NULL)
     201           0 :         return -1;
     202             :     assert(PyLong_Check(v));
     203           0 :     x = PyLong_AsLong(v);
     204           0 :     Py_DECREF(v);
     205           0 :     if (x == (long)-1 && PyErr_Occurred())
     206           0 :         return -1;
     207           0 :     *p = x;
     208           0 :     return 0;
     209             : }
     210             : 
     211             : /* Same, but handling unsigned long */
     212             : 
     213             : static int
     214           0 : get_ulong(PyObject *v, unsigned long *p)
     215             : {
     216             :     unsigned long x;
     217             : 
     218           0 :     v = get_pylong(v);
     219           0 :     if (v == NULL)
     220           0 :         return -1;
     221             :     assert(PyLong_Check(v));
     222           0 :     x = PyLong_AsUnsignedLong(v);
     223           0 :     Py_DECREF(v);
     224           0 :     if (x == (unsigned long)-1 && PyErr_Occurred())
     225           0 :         return -1;
     226           0 :     *p = x;
     227           0 :     return 0;
     228             : }
     229             : 
     230             : #ifdef HAVE_LONG_LONG
     231             : 
     232             : /* Same, but handling native long long. */
     233             : 
     234             : static int
     235           0 : get_longlong(PyObject *v, PY_LONG_LONG *p)
     236             : {
     237             :     PY_LONG_LONG x;
     238             : 
     239           0 :     v = get_pylong(v);
     240           0 :     if (v == NULL)
     241           0 :         return -1;
     242             :     assert(PyLong_Check(v));
     243           0 :     x = PyLong_AsLongLong(v);
     244           0 :     Py_DECREF(v);
     245           0 :     if (x == (PY_LONG_LONG)-1 && PyErr_Occurred())
     246           0 :         return -1;
     247           0 :     *p = x;
     248           0 :     return 0;
     249             : }
     250             : 
     251             : /* Same, but handling native unsigned long long. */
     252             : 
     253             : static int
     254           0 : get_ulonglong(PyObject *v, unsigned PY_LONG_LONG *p)
     255             : {
     256             :     unsigned PY_LONG_LONG x;
     257             : 
     258           0 :     v = get_pylong(v);
     259           0 :     if (v == NULL)
     260           0 :         return -1;
     261             :     assert(PyLong_Check(v));
     262           0 :     x = PyLong_AsUnsignedLongLong(v);
     263           0 :     Py_DECREF(v);
     264           0 :     if (x == (unsigned PY_LONG_LONG)-1 && PyErr_Occurred())
     265           0 :         return -1;
     266           0 :     *p = x;
     267           0 :     return 0;
     268             : }
     269             : 
     270             : #endif
     271             : 
     272             : /* Floating point helpers */
     273             : 
     274             : static PyObject *
     275           0 : unpack_float(const char *p,  /* start of 4-byte string */
     276             :          int le)             /* true for little-endian, false for big-endian */
     277             : {
     278             :     double x;
     279             : 
     280           0 :     x = _PyFloat_Unpack4((unsigned char *)p, le);
     281           0 :     if (x == -1.0 && PyErr_Occurred())
     282           0 :         return NULL;
     283           0 :     return PyFloat_FromDouble(x);
     284             : }
     285             : 
     286             : static PyObject *
     287           6 : unpack_double(const char *p,  /* start of 8-byte string */
     288             :           int le)         /* true for little-endian, false for big-endian */
     289             : {
     290             :     double x;
     291             : 
     292           6 :     x = _PyFloat_Unpack8((unsigned char *)p, le);
     293           6 :     if (x == -1.0 && PyErr_Occurred())
     294           0 :         return NULL;
     295           6 :     return PyFloat_FromDouble(x);
     296             : }
     297             : 
     298             : /* Helper to format the range error exceptions */
     299             : static int
     300           0 : _range_error(const formatdef *f, int is_unsigned)
     301             : {
     302             :     /* ulargest is the largest unsigned value with f->size bytes.
     303             :      * Note that the simpler:
     304             :      *     ((size_t)1 << (f->size * 8)) - 1
     305             :      * doesn't work when f->size == sizeof(size_t) because C doesn't
     306             :      * define what happens when a left shift count is >= the number of
     307             :      * bits in the integer being shifted; e.g., on some boxes it doesn't
     308             :      * shift at all when they're equal.
     309             :      */
     310           0 :     const size_t ulargest = (size_t)-1 >> ((SIZEOF_SIZE_T - f->size)*8);
     311             :     assert(f->size >= 1 && f->size <= SIZEOF_SIZE_T);
     312           0 :     if (is_unsigned)
     313           0 :         PyErr_Format(StructError,
     314             :             "'%c' format requires 0 <= number <= %zu",
     315           0 :             f->format,
     316             :             ulargest);
     317             :     else {
     318           0 :         const Py_ssize_t largest = (Py_ssize_t)(ulargest >> 1);
     319           0 :         PyErr_Format(StructError,
     320             :             "'%c' format requires %zd <= number <= %zd",
     321           0 :             f->format,
     322             :             ~ largest,
     323             :             largest);
     324             :     }
     325           0 :     return -1;
     326             : }
     327             : 
     328             : 
     329             : 
     330             : /* A large number of small routines follow, with names of the form
     331             : 
     332             :    [bln][up]_TYPE
     333             : 
     334             :    [bln] distiguishes among big-endian, little-endian and native.
     335             :    [pu] distiguishes between pack (to struct) and unpack (from struct).
     336             :    TYPE is one of char, byte, ubyte, etc.
     337             : */
     338             : 
     339             : /* Native mode routines. ****************************************************/
     340             : /* NOTE:
     341             :    In all n[up]_<type> routines handling types larger than 1 byte, there is
     342             :    *no* guarantee that the p pointer is properly aligned for each type,
     343             :    therefore memcpy is called.  An intermediate variable is used to
     344             :    compensate for big-endian architectures.
     345             :    Normally both the intermediate variable and the memcpy call will be
     346             :    skipped by C optimisation in little-endian architectures (gcc >= 2.91
     347             :    does this). */
     348             : 
     349             : static PyObject *
     350           0 : nu_char(const char *p, const formatdef *f)
     351             : {
     352           0 :     return PyString_FromStringAndSize(p, 1);
     353             : }
     354             : 
     355             : static PyObject *
     356           0 : nu_byte(const char *p, const formatdef *f)
     357             : {
     358           0 :     return PyInt_FromLong((long) *(signed char *)p);
     359             : }
     360             : 
     361             : static PyObject *
     362           0 : nu_ubyte(const char *p, const formatdef *f)
     363             : {
     364           0 :     return PyInt_FromLong((long) *(unsigned char *)p);
     365             : }
     366             : 
     367             : static PyObject *
     368           0 : nu_short(const char *p, const formatdef *f)
     369             : {
     370             :     short x;
     371           0 :     memcpy((char *)&x, p, sizeof x);
     372           0 :     return PyInt_FromLong((long)x);
     373             : }
     374             : 
     375             : static PyObject *
     376           0 : nu_ushort(const char *p, const formatdef *f)
     377             : {
     378             :     unsigned short x;
     379           0 :     memcpy((char *)&x, p, sizeof x);
     380           0 :     return PyInt_FromLong((long)x);
     381             : }
     382             : 
     383             : static PyObject *
     384           0 : nu_int(const char *p, const formatdef *f)
     385             : {
     386             :     int x;
     387           0 :     memcpy((char *)&x, p, sizeof x);
     388           0 :     return PyInt_FromLong((long)x);
     389             : }
     390             : 
     391             : static PyObject *
     392           0 : nu_uint(const char *p, const formatdef *f)
     393             : {
     394             :     unsigned int x;
     395           0 :     memcpy((char *)&x, p, sizeof x);
     396             : #if (SIZEOF_LONG > SIZEOF_INT)
     397           0 :     return PyInt_FromLong((long)x);
     398             : #else
     399             :     if (x <= ((unsigned int)LONG_MAX))
     400             :         return PyInt_FromLong((long)x);
     401             :     return PyLong_FromUnsignedLong((unsigned long)x);
     402             : #endif
     403             : }
     404             : 
     405             : static PyObject *
     406           0 : nu_long(const char *p, const formatdef *f)
     407             : {
     408             :     long x;
     409           0 :     memcpy((char *)&x, p, sizeof x);
     410           0 :     return PyInt_FromLong(x);
     411             : }
     412             : 
     413             : static PyObject *
     414           0 : nu_ulong(const char *p, const formatdef *f)
     415             : {
     416             :     unsigned long x;
     417           0 :     memcpy((char *)&x, p, sizeof x);
     418           0 :     if (x <= LONG_MAX)
     419           0 :         return PyInt_FromLong((long)x);
     420           0 :     return PyLong_FromUnsignedLong(x);
     421             : }
     422             : 
     423             : /* Native mode doesn't support q or Q unless the platform C supports
     424             :    long long (or, on Windows, __int64). */
     425             : 
     426             : #ifdef HAVE_LONG_LONG
     427             : 
     428             : static PyObject *
     429           0 : nu_longlong(const char *p, const formatdef *f)
     430             : {
     431             :     PY_LONG_LONG x;
     432           0 :     memcpy((char *)&x, p, sizeof x);
     433             :     if (x >= LONG_MIN && x <= LONG_MAX)
     434           0 :         return PyInt_FromLong(Py_SAFE_DOWNCAST(x, PY_LONG_LONG, long));
     435             :     return PyLong_FromLongLong(x);
     436             : }
     437             : 
     438             : static PyObject *
     439           0 : nu_ulonglong(const char *p, const formatdef *f)
     440             : {
     441             :     unsigned PY_LONG_LONG x;
     442           0 :     memcpy((char *)&x, p, sizeof x);
     443           0 :     if (x <= LONG_MAX)
     444           0 :         return PyInt_FromLong(Py_SAFE_DOWNCAST(x, unsigned PY_LONG_LONG, long));
     445           0 :     return PyLong_FromUnsignedLongLong(x);
     446             : }
     447             : 
     448             : #endif
     449             : 
     450             : static PyObject *
     451           0 : nu_bool(const char *p, const formatdef *f)
     452             : {
     453             :     BOOL_TYPE x;
     454           0 :     memcpy((char *)&x, p, sizeof x);
     455           0 :     return PyBool_FromLong(x != 0);
     456             : }
     457             : 
     458             : 
     459             : static PyObject *
     460           0 : nu_float(const char *p, const formatdef *f)
     461             : {
     462             :     float x;
     463           0 :     memcpy((char *)&x, p, sizeof x);
     464           0 :     return PyFloat_FromDouble((double)x);
     465             : }
     466             : 
     467             : static PyObject *
     468           0 : nu_double(const char *p, const formatdef *f)
     469             : {
     470             :     double x;
     471           0 :     memcpy((char *)&x, p, sizeof x);
     472           0 :     return PyFloat_FromDouble(x);
     473             : }
     474             : 
     475             : static PyObject *
     476           0 : nu_void_p(const char *p, const formatdef *f)
     477             : {
     478             :     void *x;
     479           0 :     memcpy((char *)&x, p, sizeof x);
     480           0 :     return PyLong_FromVoidPtr(x);
     481             : }
     482             : 
     483             : static int
     484           0 : np_byte(char *p, PyObject *v, const formatdef *f)
     485             : {
     486             :     long x;
     487           0 :     if (get_long(v, &x) < 0)
     488           0 :         return -1;
     489           0 :     if (x < -128 || x > 127){
     490           0 :         PyErr_SetString(StructError,
     491             :                         "byte format requires -128 <= number <= 127");
     492           0 :         return -1;
     493             :     }
     494           0 :     *p = (char)x;
     495           0 :     return 0;
     496             : }
     497             : 
     498             : static int
     499           0 : np_ubyte(char *p, PyObject *v, const formatdef *f)
     500             : {
     501             :     long x;
     502           0 :     if (get_long(v, &x) < 0)
     503           0 :         return -1;
     504           0 :     if (x < 0 || x > 255){
     505           0 :         PyErr_SetString(StructError,
     506             :                         "ubyte format requires 0 <= number <= 255");
     507           0 :         return -1;
     508             :     }
     509           0 :     *p = (char)x;
     510           0 :     return 0;
     511             : }
     512             : 
     513             : static int
     514           0 : np_char(char *p, PyObject *v, const formatdef *f)
     515             : {
     516           0 :     if (!PyString_Check(v) || PyString_Size(v) != 1) {
     517           0 :         PyErr_SetString(StructError,
     518             :                         "char format require string of length 1");
     519           0 :         return -1;
     520             :     }
     521           0 :     *p = *PyString_AsString(v);
     522           0 :     return 0;
     523             : }
     524             : 
     525             : static int
     526           0 : np_short(char *p, PyObject *v, const formatdef *f)
     527             : {
     528             :     long x;
     529             :     short y;
     530           0 :     if (get_long(v, &x) < 0)
     531           0 :         return -1;
     532           0 :     if (x < SHRT_MIN || x > SHRT_MAX){
     533           0 :         PyErr_SetString(StructError,
     534             :                         "short format requires " STRINGIFY(SHRT_MIN)
     535             :                         " <= number <= " STRINGIFY(SHRT_MAX));
     536           0 :         return -1;
     537             :     }
     538           0 :     y = (short)x;
     539           0 :     memcpy(p, (char *)&y, sizeof y);
     540           0 :     return 0;
     541             : }
     542             : 
     543             : static int
     544           0 : np_ushort(char *p, PyObject *v, const formatdef *f)
     545             : {
     546             :     long x;
     547             :     unsigned short y;
     548           0 :     if (get_long(v, &x) < 0)
     549           0 :         return -1;
     550           0 :     if (x < 0 || x > USHRT_MAX){
     551           0 :         PyErr_SetString(StructError,
     552             :                         "ushort format requires 0 <= number <= " STRINGIFY(USHRT_MAX));
     553           0 :         return -1;
     554             :     }
     555           0 :     y = (unsigned short)x;
     556           0 :     memcpy(p, (char *)&y, sizeof y);
     557           0 :     return 0;
     558             : }
     559             : 
     560             : static int
     561           0 : np_int(char *p, PyObject *v, const formatdef *f)
     562             : {
     563             :     long x;
     564             :     int y;
     565           0 :     if (get_long(v, &x) < 0)
     566           0 :         return -1;
     567             : #if (SIZEOF_LONG > SIZEOF_INT)
     568           0 :     if ((x < ((long)INT_MIN)) || (x > ((long)INT_MAX)))
     569           0 :         return _range_error(f, 0);
     570             : #endif
     571           0 :     y = (int)x;
     572           0 :     memcpy(p, (char *)&y, sizeof y);
     573           0 :     return 0;
     574             : }
     575             : 
     576             : static int
     577           0 : np_uint(char *p, PyObject *v, const formatdef *f)
     578             : {
     579             :     unsigned long x;
     580             :     unsigned int y;
     581           0 :     if (get_ulong(v, &x) < 0)
     582           0 :         return -1;
     583           0 :     y = (unsigned int)x;
     584             : #if (SIZEOF_LONG > SIZEOF_INT)
     585           0 :     if (x > ((unsigned long)UINT_MAX))
     586           0 :         return _range_error(f, 1);
     587             : #endif
     588           0 :     memcpy(p, (char *)&y, sizeof y);
     589           0 :     return 0;
     590             : }
     591             : 
     592             : static int
     593           0 : np_long(char *p, PyObject *v, const formatdef *f)
     594             : {
     595             :     long x;
     596           0 :     if (get_long(v, &x) < 0)
     597           0 :         return -1;
     598           0 :     memcpy(p, (char *)&x, sizeof x);
     599           0 :     return 0;
     600             : }
     601             : 
     602             : static int
     603           0 : np_ulong(char *p, PyObject *v, const formatdef *f)
     604             : {
     605             :     unsigned long x;
     606           0 :     if (get_ulong(v, &x) < 0)
     607           0 :         return -1;
     608           0 :     memcpy(p, (char *)&x, sizeof x);
     609           0 :     return 0;
     610             : }
     611             : 
     612             : #ifdef HAVE_LONG_LONG
     613             : 
     614             : static int
     615           0 : np_longlong(char *p, PyObject *v, const formatdef *f)
     616             : {
     617             :     PY_LONG_LONG x;
     618           0 :     if (get_longlong(v, &x) < 0)
     619           0 :         return -1;
     620           0 :     memcpy(p, (char *)&x, sizeof x);
     621           0 :     return 0;
     622             : }
     623             : 
     624             : static int
     625           0 : np_ulonglong(char *p, PyObject *v, const formatdef *f)
     626             : {
     627             :     unsigned PY_LONG_LONG x;
     628           0 :     if (get_ulonglong(v, &x) < 0)
     629           0 :         return -1;
     630           0 :     memcpy(p, (char *)&x, sizeof x);
     631           0 :     return 0;
     632             : }
     633             : #endif
     634             : 
     635             : 
     636             : static int
     637           0 : np_bool(char *p, PyObject *v, const formatdef *f)
     638             : {
     639             :     int y;
     640             :     BOOL_TYPE x;
     641           0 :     y = PyObject_IsTrue(v);
     642           0 :     if (y < 0)
     643           0 :         return -1;
     644           0 :     x = y;
     645           0 :     memcpy(p, (char *)&x, sizeof x);
     646           0 :     return 0;
     647             : }
     648             : 
     649             : static int
     650           0 : np_float(char *p, PyObject *v, const formatdef *f)
     651             : {
     652           0 :     float x = (float)PyFloat_AsDouble(v);
     653           0 :     if (x == -1 && PyErr_Occurred()) {
     654           0 :         PyErr_SetString(StructError,
     655             :                         "required argument is not a float");
     656           0 :         return -1;
     657             :     }
     658           0 :     memcpy(p, (char *)&x, sizeof x);
     659           0 :     return 0;
     660             : }
     661             : 
     662             : static int
     663           0 : np_double(char *p, PyObject *v, const formatdef *f)
     664             : {
     665           0 :     double x = PyFloat_AsDouble(v);
     666           0 :     if (x == -1 && PyErr_Occurred()) {
     667           0 :         PyErr_SetString(StructError,
     668             :                         "required argument is not a float");
     669           0 :         return -1;
     670             :     }
     671           0 :     memcpy(p, (char *)&x, sizeof(double));
     672           0 :     return 0;
     673             : }
     674             : 
     675             : static int
     676           0 : np_void_p(char *p, PyObject *v, const formatdef *f)
     677             : {
     678             :     void *x;
     679             : 
     680           0 :     v = get_pylong(v);
     681           0 :     if (v == NULL)
     682           0 :         return -1;
     683             :     assert(PyLong_Check(v));
     684           0 :     x = PyLong_AsVoidPtr(v);
     685           0 :     Py_DECREF(v);
     686           0 :     if (x == NULL && PyErr_Occurred())
     687           0 :         return -1;
     688           0 :     memcpy(p, (char *)&x, sizeof x);
     689           0 :     return 0;
     690             : }
     691             : 
     692             : static formatdef native_table[] = {
     693             :     {'x',       sizeof(char),   0,              NULL},
     694             :     {'b',       sizeof(char),   0,              nu_byte,        np_byte},
     695             :     {'B',       sizeof(char),   0,              nu_ubyte,       np_ubyte},
     696             :     {'c',       sizeof(char),   0,              nu_char,        np_char},
     697             :     {'s',       sizeof(char),   0,              NULL},
     698             :     {'p',       sizeof(char),   0,              NULL},
     699             :     {'h',       sizeof(short),  SHORT_ALIGN,    nu_short,       np_short},
     700             :     {'H',       sizeof(short),  SHORT_ALIGN,    nu_ushort,      np_ushort},
     701             :     {'i',       sizeof(int),    INT_ALIGN,      nu_int,         np_int},
     702             :     {'I',       sizeof(int),    INT_ALIGN,      nu_uint,        np_uint},
     703             :     {'l',       sizeof(long),   LONG_ALIGN,     nu_long,        np_long},
     704             :     {'L',       sizeof(long),   LONG_ALIGN,     nu_ulong,       np_ulong},
     705             : #ifdef HAVE_LONG_LONG
     706             :     {'q',       sizeof(PY_LONG_LONG), LONG_LONG_ALIGN, nu_longlong, np_longlong},
     707             :     {'Q',       sizeof(PY_LONG_LONG), LONG_LONG_ALIGN, nu_ulonglong,np_ulonglong},
     708             : #endif
     709             :     {'?',       sizeof(BOOL_TYPE),      BOOL_ALIGN,     nu_bool,        np_bool},
     710             :     {'f',       sizeof(float),  FLOAT_ALIGN,    nu_float,       np_float},
     711             :     {'d',       sizeof(double), DOUBLE_ALIGN,   nu_double,      np_double},
     712             :     {'P',       sizeof(void *), VOID_P_ALIGN,   nu_void_p,      np_void_p},
     713             :     {0}
     714             : };
     715             : 
     716             : /* Big-endian routines. *****************************************************/
     717             : 
     718             : static PyObject *
     719           0 : bu_int(const char *p, const formatdef *f)
     720             : {
     721           0 :     long x = 0;
     722           0 :     Py_ssize_t i = f->size;
     723           0 :     const unsigned char *bytes = (const unsigned char *)p;
     724             :     do {
     725           0 :         x = (x<<8) | *bytes++;
     726           0 :     } while (--i > 0);
     727             :     /* Extend the sign bit. */
     728           0 :     if (SIZEOF_LONG > f->size)
     729           0 :         x |= -(x & (1L << ((8 * f->size) - 1)));
     730           0 :     return PyInt_FromLong(x);
     731             : }
     732             : 
     733             : static PyObject *
     734           0 : bu_uint(const char *p, const formatdef *f)
     735             : {
     736           0 :     unsigned long x = 0;
     737           0 :     Py_ssize_t i = f->size;
     738           0 :     const unsigned char *bytes = (const unsigned char *)p;
     739             :     do {
     740           0 :         x = (x<<8) | *bytes++;
     741           0 :     } while (--i > 0);
     742           0 :     if (x <= LONG_MAX)
     743           0 :         return PyInt_FromLong((long)x);
     744           0 :     return PyLong_FromUnsignedLong(x);
     745             : }
     746             : 
     747             : static PyObject *
     748           0 : bu_longlong(const char *p, const formatdef *f)
     749             : {
     750             : #ifdef HAVE_LONG_LONG
     751           0 :     PY_LONG_LONG x = 0;
     752           0 :     Py_ssize_t i = f->size;
     753           0 :     const unsigned char *bytes = (const unsigned char *)p;
     754             :     do {
     755           0 :         x = (x<<8) | *bytes++;
     756           0 :     } while (--i > 0);
     757             :     /* Extend the sign bit. */
     758           0 :     if (SIZEOF_LONG_LONG > f->size)
     759           0 :         x |= -(x & ((PY_LONG_LONG)1 << ((8 * f->size) - 1)));
     760             :     if (x >= LONG_MIN && x <= LONG_MAX)
     761           0 :         return PyInt_FromLong(Py_SAFE_DOWNCAST(x, PY_LONG_LONG, long));
     762             :     return PyLong_FromLongLong(x);
     763             : #else
     764             :     return _PyLong_FromByteArray((const unsigned char *)p,
     765             :                                   8,
     766             :                                   0, /* little-endian */
     767             :                       1  /* signed */);
     768             : #endif
     769             : }
     770             : 
     771             : static PyObject *
     772           0 : bu_ulonglong(const char *p, const formatdef *f)
     773             : {
     774             : #ifdef HAVE_LONG_LONG
     775           0 :     unsigned PY_LONG_LONG x = 0;
     776           0 :     Py_ssize_t i = f->size;
     777           0 :     const unsigned char *bytes = (const unsigned char *)p;
     778             :     do {
     779           0 :         x = (x<<8) | *bytes++;
     780           0 :     } while (--i > 0);
     781           0 :     if (x <= LONG_MAX)
     782           0 :         return PyInt_FromLong(Py_SAFE_DOWNCAST(x, unsigned PY_LONG_LONG, long));
     783           0 :     return PyLong_FromUnsignedLongLong(x);
     784             : #else
     785             :     return _PyLong_FromByteArray((const unsigned char *)p,
     786             :                                   8,
     787             :                                   0, /* little-endian */
     788             :                       0  /* signed */);
     789             : #endif
     790             : }
     791             : 
     792             : static PyObject *
     793           0 : bu_float(const char *p, const formatdef *f)
     794             : {
     795           0 :     return unpack_float(p, 0);
     796             : }
     797             : 
     798             : static PyObject *
     799           6 : bu_double(const char *p, const formatdef *f)
     800             : {
     801           6 :     return unpack_double(p, 0);
     802             : }
     803             : 
     804             : static PyObject *
     805           0 : bu_bool(const char *p, const formatdef *f)
     806             : {
     807             :     char x;
     808           0 :     memcpy((char *)&x, p, sizeof x);
     809           0 :     return PyBool_FromLong(x != 0);
     810             : }
     811             : 
     812             : static int
     813           0 : bp_int(char *p, PyObject *v, const formatdef *f)
     814             : {
     815             :     long x;
     816             :     Py_ssize_t i;
     817           0 :     if (get_long(v, &x) < 0)
     818           0 :         return -1;
     819           0 :     i = f->size;
     820           0 :     if (i != SIZEOF_LONG) {
     821           0 :         if ((i == 2) && (x < -32768 || x > 32767))
     822           0 :             return _range_error(f, 0);
     823             : #if (SIZEOF_LONG != 4)
     824           0 :         else if ((i == 4) && (x < -2147483648L || x > 2147483647L))
     825           0 :             return _range_error(f, 0);
     826             : #endif
     827             :     }
     828             :     do {
     829           0 :         p[--i] = (char)x;
     830           0 :         x >>= 8;
     831           0 :     } while (i > 0);
     832           0 :     return 0;
     833             : }
     834             : 
     835             : static int
     836           0 : bp_uint(char *p, PyObject *v, const formatdef *f)
     837             : {
     838             :     unsigned long x;
     839             :     Py_ssize_t i;
     840           0 :     if (get_ulong(v, &x) < 0)
     841           0 :         return -1;
     842           0 :     i = f->size;
     843           0 :     if (i != SIZEOF_LONG) {
     844           0 :         unsigned long maxint = 1;
     845           0 :         maxint <<= (unsigned long)(i * 8);
     846           0 :         if (x >= maxint)
     847           0 :             return _range_error(f, 1);
     848             :     }
     849             :     do {
     850           0 :         p[--i] = (char)x;
     851           0 :         x >>= 8;
     852           0 :     } while (i > 0);
     853           0 :     return 0;
     854             : }
     855             : 
     856             : static int
     857           0 : bp_longlong(char *p, PyObject *v, const formatdef *f)
     858             : {
     859             :     int res;
     860           0 :     v = get_pylong(v);
     861           0 :     if (v == NULL)
     862           0 :         return -1;
     863           0 :     res = _PyLong_AsByteArray((PyLongObject *)v,
     864             :                               (unsigned char *)p,
     865             :                               8,
     866             :                               0, /* little_endian */
     867             :                   1  /* signed */);
     868           0 :     Py_DECREF(v);
     869           0 :     return res;
     870             : }
     871             : 
     872             : static int
     873           0 : bp_ulonglong(char *p, PyObject *v, const formatdef *f)
     874             : {
     875             :     int res;
     876           0 :     v = get_pylong(v);
     877           0 :     if (v == NULL)
     878           0 :         return -1;
     879           0 :     res = _PyLong_AsByteArray((PyLongObject *)v,
     880             :                               (unsigned char *)p,
     881             :                               8,
     882             :                               0, /* little_endian */
     883             :                   0  /* signed */);
     884           0 :     Py_DECREF(v);
     885           0 :     return res;
     886             : }
     887             : 
     888             : static int
     889           0 : bp_float(char *p, PyObject *v, const formatdef *f)
     890             : {
     891           0 :     double x = PyFloat_AsDouble(v);
     892           0 :     if (x == -1 && PyErr_Occurred()) {
     893           0 :         PyErr_SetString(StructError,
     894             :                         "required argument is not a float");
     895           0 :         return -1;
     896             :     }
     897           0 :     return _PyFloat_Pack4(x, (unsigned char *)p, 0);
     898             : }
     899             : 
     900             : static int
     901           0 : bp_double(char *p, PyObject *v, const formatdef *f)
     902             : {
     903           0 :     double x = PyFloat_AsDouble(v);
     904           0 :     if (x == -1 && PyErr_Occurred()) {
     905           0 :         PyErr_SetString(StructError,
     906             :                         "required argument is not a float");
     907           0 :         return -1;
     908             :     }
     909           0 :     return _PyFloat_Pack8(x, (unsigned char *)p, 0);
     910             : }
     911             : 
     912             : static int
     913           0 : bp_bool(char *p, PyObject *v, const formatdef *f)
     914             : {
     915             :     int y;
     916           0 :     y = PyObject_IsTrue(v);
     917           0 :     if (y < 0)
     918           0 :         return -1;
     919           0 :     *p = (char)y;
     920           0 :     return 0;
     921             : }
     922             : 
     923             : static formatdef bigendian_table[] = {
     924             :     {'x',       1,              0,              NULL},
     925             :     {'b',       1,              0,              nu_byte,        np_byte},
     926             :     {'B',       1,              0,              nu_ubyte,       np_ubyte},
     927             :     {'c',       1,              0,              nu_char,        np_char},
     928             :     {'s',       1,              0,              NULL},
     929             :     {'p',       1,              0,              NULL},
     930             :     {'h',       2,              0,              bu_int,         bp_int},
     931             :     {'H',       2,              0,              bu_uint,        bp_uint},
     932             :     {'i',       4,              0,              bu_int,         bp_int},
     933             :     {'I',       4,              0,              bu_uint,        bp_uint},
     934             :     {'l',       4,              0,              bu_int,         bp_int},
     935             :     {'L',       4,              0,              bu_uint,        bp_uint},
     936             :     {'q',       8,              0,              bu_longlong,    bp_longlong},
     937             :     {'Q',       8,              0,              bu_ulonglong,   bp_ulonglong},
     938             :     {'?',       1,              0,              bu_bool,        bp_bool},
     939             :     {'f',       4,              0,              bu_float,       bp_float},
     940             :     {'d',       8,              0,              bu_double,      bp_double},
     941             :     {0}
     942             : };
     943             : 
     944             : /* Little-endian routines. *****************************************************/
     945             : 
     946             : static PyObject *
     947           0 : lu_int(const char *p, const formatdef *f)
     948             : {
     949           0 :     long x = 0;
     950           0 :     Py_ssize_t i = f->size;
     951           0 :     const unsigned char *bytes = (const unsigned char *)p;
     952             :     do {
     953           0 :         x = (x<<8) | bytes[--i];
     954           0 :     } while (i > 0);
     955             :     /* Extend the sign bit. */
     956           0 :     if (SIZEOF_LONG > f->size)
     957           0 :         x |= -(x & (1L << ((8 * f->size) - 1)));
     958           0 :     return PyInt_FromLong(x);
     959             : }
     960             : 
     961             : static PyObject *
     962           0 : lu_uint(const char *p, const formatdef *f)
     963             : {
     964           0 :     unsigned long x = 0;
     965           0 :     Py_ssize_t i = f->size;
     966           0 :     const unsigned char *bytes = (const unsigned char *)p;
     967             :     do {
     968           0 :         x = (x<<8) | bytes[--i];
     969           0 :     } while (i > 0);
     970           0 :     if (x <= LONG_MAX)
     971           0 :         return PyInt_FromLong((long)x);
     972           0 :     return PyLong_FromUnsignedLong((long)x);
     973             : }
     974             : 
     975             : static PyObject *
     976           0 : lu_longlong(const char *p, const formatdef *f)
     977             : {
     978             : #ifdef HAVE_LONG_LONG
     979           0 :     PY_LONG_LONG x = 0;
     980           0 :     Py_ssize_t i = f->size;
     981           0 :     const unsigned char *bytes = (const unsigned char *)p;
     982             :     do {
     983           0 :         x = (x<<8) | bytes[--i];
     984           0 :     } while (i > 0);
     985             :     /* Extend the sign bit. */
     986           0 :     if (SIZEOF_LONG_LONG > f->size)
     987           0 :         x |= -(x & ((PY_LONG_LONG)1 << ((8 * f->size) - 1)));
     988             :     if (x >= LONG_MIN && x <= LONG_MAX)
     989           0 :         return PyInt_FromLong(Py_SAFE_DOWNCAST(x, PY_LONG_LONG, long));
     990             :     return PyLong_FromLongLong(x);
     991             : #else
     992             :     return _PyLong_FromByteArray((const unsigned char *)p,
     993             :                                   8,
     994             :                                   1, /* little-endian */
     995             :                       1  /* signed */);
     996             : #endif
     997             : }
     998             : 
     999             : static PyObject *
    1000           0 : lu_ulonglong(const char *p, const formatdef *f)
    1001             : {
    1002             : #ifdef HAVE_LONG_LONG
    1003           0 :     unsigned PY_LONG_LONG x = 0;
    1004           0 :     Py_ssize_t i = f->size;
    1005           0 :     const unsigned char *bytes = (const unsigned char *)p;
    1006             :     do {
    1007           0 :         x = (x<<8) | bytes[--i];
    1008           0 :     } while (i > 0);
    1009           0 :     if (x <= LONG_MAX)
    1010           0 :         return PyInt_FromLong(Py_SAFE_DOWNCAST(x, unsigned PY_LONG_LONG, long));
    1011           0 :     return PyLong_FromUnsignedLongLong(x);
    1012             : #else
    1013             :     return _PyLong_FromByteArray((const unsigned char *)p,
    1014             :                                   8,
    1015             :                                   1, /* little-endian */
    1016             :                       0  /* signed */);
    1017             : #endif
    1018             : }
    1019             : 
    1020             : static PyObject *
    1021           0 : lu_float(const char *p, const formatdef *f)
    1022             : {
    1023           0 :     return unpack_float(p, 1);
    1024             : }
    1025             : 
    1026             : static PyObject *
    1027           0 : lu_double(const char *p, const formatdef *f)
    1028             : {
    1029           0 :     return unpack_double(p, 1);
    1030             : }
    1031             : 
    1032             : static int
    1033           0 : lp_int(char *p, PyObject *v, const formatdef *f)
    1034             : {
    1035             :     long x;
    1036             :     Py_ssize_t i;
    1037           0 :     if (get_long(v, &x) < 0)
    1038           0 :         return -1;
    1039           0 :     i = f->size;
    1040           0 :     if (i != SIZEOF_LONG) {
    1041           0 :         if ((i == 2) && (x < -32768 || x > 32767))
    1042           0 :             return _range_error(f, 0);
    1043             : #if (SIZEOF_LONG != 4)
    1044           0 :         else if ((i == 4) && (x < -2147483648L || x > 2147483647L))
    1045           0 :             return _range_error(f, 0);
    1046             : #endif
    1047             :     }
    1048             :     do {
    1049           0 :         *p++ = (char)x;
    1050           0 :         x >>= 8;
    1051           0 :     } while (--i > 0);
    1052           0 :     return 0;
    1053             : }
    1054             : 
    1055             : static int
    1056           0 : lp_uint(char *p, PyObject *v, const formatdef *f)
    1057             : {
    1058             :     unsigned long x;
    1059             :     Py_ssize_t i;
    1060           0 :     if (get_ulong(v, &x) < 0)
    1061           0 :         return -1;
    1062           0 :     i = f->size;
    1063           0 :     if (i != SIZEOF_LONG) {
    1064           0 :         unsigned long maxint = 1;
    1065           0 :         maxint <<= (unsigned long)(i * 8);
    1066           0 :         if (x >= maxint)
    1067           0 :             return _range_error(f, 1);
    1068             :     }
    1069             :     do {
    1070           0 :         *p++ = (char)x;
    1071           0 :         x >>= 8;
    1072           0 :     } while (--i > 0);
    1073           0 :     return 0;
    1074             : }
    1075             : 
    1076             : static int
    1077           0 : lp_longlong(char *p, PyObject *v, const formatdef *f)
    1078             : {
    1079             :     int res;
    1080           0 :     v = get_pylong(v);
    1081           0 :     if (v == NULL)
    1082           0 :         return -1;
    1083           0 :     res = _PyLong_AsByteArray((PyLongObject*)v,
    1084             :                               (unsigned char *)p,
    1085             :                               8,
    1086             :                               1, /* little_endian */
    1087             :                   1  /* signed */);
    1088           0 :     Py_DECREF(v);
    1089           0 :     return res;
    1090             : }
    1091             : 
    1092             : static int
    1093           0 : lp_ulonglong(char *p, PyObject *v, const formatdef *f)
    1094             : {
    1095             :     int res;
    1096           0 :     v = get_pylong(v);
    1097           0 :     if (v == NULL)
    1098           0 :         return -1;
    1099           0 :     res = _PyLong_AsByteArray((PyLongObject*)v,
    1100             :                               (unsigned char *)p,
    1101             :                               8,
    1102             :                               1, /* little_endian */
    1103             :                   0  /* signed */);
    1104           0 :     Py_DECREF(v);
    1105           0 :     return res;
    1106             : }
    1107             : 
    1108             : static int
    1109           0 : lp_float(char *p, PyObject *v, const formatdef *f)
    1110             : {
    1111           0 :     double x = PyFloat_AsDouble(v);
    1112           0 :     if (x == -1 && PyErr_Occurred()) {
    1113           0 :         PyErr_SetString(StructError,
    1114             :                         "required argument is not a float");
    1115           0 :         return -1;
    1116             :     }
    1117           0 :     return _PyFloat_Pack4(x, (unsigned char *)p, 1);
    1118             : }
    1119             : 
    1120             : static int
    1121           0 : lp_double(char *p, PyObject *v, const formatdef *f)
    1122             : {
    1123           0 :     double x = PyFloat_AsDouble(v);
    1124           0 :     if (x == -1 && PyErr_Occurred()) {
    1125           0 :         PyErr_SetString(StructError,
    1126             :                         "required argument is not a float");
    1127           0 :         return -1;
    1128             :     }
    1129           0 :     return _PyFloat_Pack8(x, (unsigned char *)p, 1);
    1130             : }
    1131             : 
    1132             : static formatdef lilendian_table[] = {
    1133             :     {'x',       1,              0,              NULL},
    1134             :     {'b',       1,              0,              nu_byte,        np_byte},
    1135             :     {'B',       1,              0,              nu_ubyte,       np_ubyte},
    1136             :     {'c',       1,              0,              nu_char,        np_char},
    1137             :     {'s',       1,              0,              NULL},
    1138             :     {'p',       1,              0,              NULL},
    1139             :     {'h',       2,              0,              lu_int,         lp_int},
    1140             :     {'H',       2,              0,              lu_uint,        lp_uint},
    1141             :     {'i',       4,              0,              lu_int,         lp_int},
    1142             :     {'I',       4,              0,              lu_uint,        lp_uint},
    1143             :     {'l',       4,              0,              lu_int,         lp_int},
    1144             :     {'L',       4,              0,              lu_uint,        lp_uint},
    1145             :     {'q',       8,              0,              lu_longlong,    lp_longlong},
    1146             :     {'Q',       8,              0,              lu_ulonglong,   lp_ulonglong},
    1147             :     {'?',       1,              0,              bu_bool,        bp_bool}, /* Std rep not endian dep,
    1148             :         but potentially different from native rep -- reuse bx_bool funcs. */
    1149             :     {'f',       4,              0,              lu_float,       lp_float},
    1150             :     {'d',       8,              0,              lu_double,      lp_double},
    1151             :     {0}
    1152             : };
    1153             : 
    1154             : 
    1155             : static const formatdef *
    1156           3 : whichtable(char **pfmt)
    1157             : {
    1158           3 :     const char *fmt = (*pfmt)++; /* May be backed out of later */
    1159           3 :     switch (*fmt) {
    1160             :     case '<':
    1161           0 :         return lilendian_table;
    1162             :     case '>':
    1163             :     case '!': /* Network byte order is big-endian */
    1164           3 :         return bigendian_table;
    1165             :     case '=': { /* Host byte order -- different from native in alignment! */
    1166           0 :         int n = 1;
    1167           0 :         char *p = (char *) &n;
    1168           0 :         if (*p == 1)
    1169           0 :             return lilendian_table;
    1170             :         else
    1171           0 :             return bigendian_table;
    1172             :     }
    1173             :     default:
    1174           0 :         --*pfmt; /* Back out of pointer increment */
    1175             :         /* Fall through */
    1176             :     case '@':
    1177           0 :         return native_table;
    1178             :     }
    1179             : }
    1180             : 
    1181             : 
    1182             : /* Get the table entry for a format code */
    1183             : 
    1184             : static const formatdef *
    1185           6 : getentry(int c, const formatdef *f)
    1186             : {
    1187         102 :     for (; f->format != '\0'; f++) {
    1188         102 :         if (f->format == c) {
    1189           6 :             return f;
    1190             :         }
    1191             :     }
    1192           0 :     PyErr_SetString(StructError, "bad char in struct format");
    1193           0 :     return NULL;
    1194             : }
    1195             : 
    1196             : 
    1197             : /* Align a size according to a format code.  Return -1 on overflow. */
    1198             : 
    1199             : static Py_ssize_t
    1200           6 : align(Py_ssize_t size, char c, const formatdef *e)
    1201             : {
    1202             :     Py_ssize_t extra;
    1203             : 
    1204           6 :     if (e->format == c) {
    1205           6 :         if (e->alignment && size > 0) {
    1206           0 :             extra = (e->alignment - 1) - (size - 1) % (e->alignment);
    1207           0 :             if (extra > PY_SSIZE_T_MAX - size)
    1208           0 :                 return -1;
    1209           0 :             size += extra;
    1210             :         }
    1211             :     }
    1212           6 :     return size;
    1213             : }
    1214             : 
    1215             : 
    1216             : /* calculate the size of a format string */
    1217             : 
    1218             : static int
    1219           3 : prepare_s(PyStructObject *self)
    1220             : {
    1221             :     const formatdef *f;
    1222             :     const formatdef *e;
    1223             :     formatcode *codes;
    1224             : 
    1225             :     const char *s;
    1226             :     const char *fmt;
    1227             :     char c;
    1228             :     Py_ssize_t size, len, num, itemsize;
    1229             : 
    1230           3 :     fmt = PyString_AS_STRING(self->s_format);
    1231             : 
    1232           3 :     f = whichtable((char **)&fmt);
    1233             : 
    1234           3 :     s = fmt;
    1235           3 :     size = 0;
    1236           3 :     len = 0;
    1237           9 :     while ((c = *s++) != '\0') {
    1238           3 :         if (isspace(Py_CHARMASK(c)))
    1239           0 :             continue;
    1240           3 :         if ('0' <= c && c <= '9') {
    1241           0 :             num = c - '0';
    1242           0 :             while ('0' <= (c = *s++) && c <= '9') {
    1243             :                 /* overflow-safe version of
    1244             :                    if (num*10 + (c - '0') > PY_SSIZE_T_MAX) { ... } */
    1245           0 :                 if (num >= PY_SSIZE_T_MAX / 10 && (
    1246           0 :                         num > PY_SSIZE_T_MAX / 10 ||
    1247           0 :                         (c - '0') > PY_SSIZE_T_MAX % 10))
    1248             :                     goto overflow;
    1249           0 :                 num = num*10 + (c - '0');
    1250             :             }
    1251           0 :             if (c == '\0')
    1252           0 :                 break;
    1253             :         }
    1254             :         else
    1255           3 :             num = 1;
    1256             : 
    1257           3 :         e = getentry(c, f);
    1258           3 :         if (e == NULL)
    1259           0 :             return -1;
    1260             : 
    1261           3 :         switch (c) {
    1262             :             case 's': /* fall through */
    1263           0 :             case 'p': len++; break;
    1264           0 :             case 'x': break;
    1265           3 :             default: len += num; break;
    1266             :         }
    1267             : 
    1268           3 :         itemsize = e->size;
    1269           3 :         size = align(size, c, e);
    1270           3 :         if (size == -1)
    1271           0 :             goto overflow;
    1272             : 
    1273             :         /* if (size + num * itemsize > PY_SSIZE_T_MAX) { ... } */
    1274           3 :         if (num > (PY_SSIZE_T_MAX - size) / itemsize)
    1275           0 :             goto overflow;
    1276           3 :         size += num * itemsize;
    1277             :     }
    1278             : 
    1279             :     /* check for overflow */
    1280           3 :     if ((len + 1) > (PY_SSIZE_T_MAX / sizeof(formatcode))) {
    1281           0 :         PyErr_NoMemory();
    1282           0 :         return -1;
    1283             :     }
    1284             : 
    1285           3 :     self->s_size = size;
    1286           3 :     self->s_len = len;
    1287           3 :     codes = PyMem_MALLOC((len + 1) * sizeof(formatcode));
    1288           3 :     if (codes == NULL) {
    1289           0 :         PyErr_NoMemory();
    1290           0 :         return -1;
    1291             :     }
    1292             :     /* Free any s_codes value left over from a previous initialization. */
    1293           3 :     if (self->s_codes != NULL)
    1294           0 :         PyMem_FREE(self->s_codes);
    1295           3 :     self->s_codes = codes;
    1296             : 
    1297           3 :     s = fmt;
    1298           3 :     size = 0;
    1299           9 :     while ((c = *s++) != '\0') {
    1300           3 :         if (isspace(Py_CHARMASK(c)))
    1301           0 :             continue;
    1302           3 :         if ('0' <= c && c <= '9') {
    1303           0 :             num = c - '0';
    1304           0 :             while ('0' <= (c = *s++) && c <= '9')
    1305           0 :                 num = num*10 + (c - '0');
    1306           0 :             if (c == '\0')
    1307           0 :                 break;
    1308             :         }
    1309             :         else
    1310           3 :             num = 1;
    1311             : 
    1312           3 :         e = getentry(c, f);
    1313             : 
    1314           3 :         size = align(size, c, e);
    1315           3 :         if (c == 's' || c == 'p') {
    1316           0 :             codes->offset = size;
    1317           0 :             codes->size = num;
    1318           0 :             codes->fmtdef = e;
    1319           0 :             codes++;
    1320           0 :             size += num;
    1321           3 :         } else if (c == 'x') {
    1322           0 :             size += num;
    1323             :         } else {
    1324           9 :             while (--num >= 0) {
    1325           3 :                 codes->offset = size;
    1326           3 :                 codes->size = e->size;
    1327           3 :                 codes->fmtdef = e;
    1328           3 :                 codes++;
    1329           3 :                 size += e->size;
    1330             :             }
    1331             :         }
    1332             :     }
    1333           3 :     codes->fmtdef = NULL;
    1334           3 :     codes->offset = size;
    1335           3 :     codes->size = 0;
    1336             : 
    1337           3 :     return 0;
    1338             : 
    1339             :   overflow:
    1340           0 :     PyErr_SetString(StructError,
    1341             :                     "total struct size too long");
    1342           0 :     return -1;
    1343             : }
    1344             : 
    1345             : static PyObject *
    1346           3 : s_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
    1347             : {
    1348             :     PyObject *self;
    1349             : 
    1350             :     assert(type != NULL && type->tp_alloc != NULL);
    1351             : 
    1352           3 :     self = type->tp_alloc(type, 0);
    1353           3 :     if (self != NULL) {
    1354           3 :         PyStructObject *s = (PyStructObject*)self;
    1355           3 :         Py_INCREF(Py_None);
    1356           3 :         s->s_format = Py_None;
    1357           3 :         s->s_codes = NULL;
    1358           3 :         s->s_size = -1;
    1359           3 :         s->s_len = -1;
    1360             :     }
    1361           3 :     return self;
    1362             : }
    1363             : 
    1364             : static int
    1365           3 : s_init(PyObject *self, PyObject *args, PyObject *kwds)
    1366             : {
    1367           3 :     PyStructObject *soself = (PyStructObject *)self;
    1368           3 :     PyObject *o_format = NULL;
    1369           3 :     int ret = 0;
    1370             :     static char *kwlist[] = {"format", 0};
    1371             : 
    1372             :     assert(PyStruct_Check(self));
    1373             : 
    1374           3 :     if (!PyArg_ParseTupleAndKeywords(args, kwds, "O:Struct", kwlist,
    1375             :                                      &o_format))
    1376           0 :         return -1;
    1377             : 
    1378           3 :     if (PyString_Check(o_format)) {
    1379           3 :         Py_INCREF(o_format);
    1380           3 :         Py_XSETREF(soself->s_format, o_format);
    1381             :     }
    1382           0 :     else if (PyUnicode_Check(o_format)) {
    1383           0 :         PyObject *str = PyUnicode_AsEncodedString(o_format, "ascii", NULL);
    1384           0 :         if (str == NULL)
    1385           0 :             return -1;
    1386           0 :         Py_XSETREF(soself->s_format, str);
    1387             :     }
    1388             :     else {
    1389           0 :         PyErr_Format(PyExc_TypeError,
    1390             :                      "Struct() argument 1 must be string, not %s",
    1391           0 :                      Py_TYPE(o_format)->tp_name);
    1392           0 :         return -1;
    1393             :     }
    1394             : 
    1395           3 :     ret = prepare_s(soself);
    1396           3 :     return ret;
    1397             : }
    1398             : 
    1399             : static void
    1400           0 : s_dealloc(PyStructObject *s)
    1401             : {
    1402           0 :     if (s->weakreflist != NULL)
    1403           0 :         PyObject_ClearWeakRefs((PyObject *)s);
    1404           0 :     if (s->s_codes != NULL) {
    1405           0 :         PyMem_FREE(s->s_codes);
    1406             :     }
    1407           0 :     Py_XDECREF(s->s_format);
    1408           0 :     Py_TYPE(s)->tp_free((PyObject *)s);
    1409           0 : }
    1410             : 
    1411             : static PyObject *
    1412           6 : s_unpack_internal(PyStructObject *soself, char *startfrom) {
    1413             :     formatcode *code;
    1414           6 :     Py_ssize_t i = 0;
    1415           6 :     PyObject *result = PyTuple_New(soself->s_len);
    1416           6 :     if (result == NULL)
    1417           0 :         return NULL;
    1418             : 
    1419          12 :     for (code = soself->s_codes; code->fmtdef != NULL; code++) {
    1420             :         PyObject *v;
    1421           6 :         const formatdef *e = code->fmtdef;
    1422           6 :         const char *res = startfrom + code->offset;
    1423           6 :         if (e->format == 's') {
    1424           0 :             v = PyString_FromStringAndSize(res, code->size);
    1425           6 :         } else if (e->format == 'p') {
    1426           0 :             Py_ssize_t n = *(unsigned char*)res;
    1427           0 :             if (n >= code->size)
    1428           0 :                 n = code->size - 1;
    1429           0 :             v = PyString_FromStringAndSize(res + 1, n);
    1430             :         } else {
    1431           6 :             v = e->unpack(res, e);
    1432             :         }
    1433           6 :         if (v == NULL)
    1434           0 :             goto fail;
    1435           6 :         PyTuple_SET_ITEM(result, i++, v);
    1436             :     }
    1437             : 
    1438           6 :     return result;
    1439             : fail:
    1440           0 :     Py_DECREF(result);
    1441           0 :     return NULL;
    1442             : }
    1443             : 
    1444             : 
    1445             : PyDoc_STRVAR(s_unpack__doc__,
    1446             : "S.unpack(str) -> (v1, v2, ...)\n\
    1447             : \n\
    1448             : Return tuple containing values unpacked according to this Struct's format.\n\
    1449             : Requires len(str) == self.size. See struct.__doc__ for more on format\n\
    1450             : strings.");
    1451             : 
    1452             : static PyObject *
    1453           6 : s_unpack(PyObject *self, PyObject *inputstr)
    1454             : {
    1455             :     Py_buffer buf;
    1456             :     char *start;
    1457             :     Py_ssize_t len;
    1458           6 :     PyObject *args=NULL, *result;
    1459           6 :     PyStructObject *soself = (PyStructObject *)self;
    1460             :     assert(PyStruct_Check(self));
    1461             :     assert(soself->s_codes != NULL);
    1462           6 :     if (inputstr == NULL)
    1463           0 :         goto fail;
    1464          12 :     if (PyString_Check(inputstr) &&
    1465           6 :         PyString_GET_SIZE(inputstr) == soself->s_size) {
    1466           6 :             return s_unpack_internal(soself, PyString_AS_STRING(inputstr));
    1467             :     }
    1468           0 :     args = PyTuple_Pack(1, inputstr);
    1469           0 :     if (args == NULL)
    1470           0 :         return NULL;
    1471           0 :     if (!PyArg_ParseTuple(args, "s*:unpack", &buf))
    1472           0 :         goto fail;
    1473           0 :     start = buf.buf;
    1474           0 :     len = buf.len;
    1475           0 :     if (soself->s_size != len) {
    1476           0 :         PyBuffer_Release(&buf);
    1477           0 :         goto fail;
    1478             :     }
    1479           0 :     result = s_unpack_internal(soself, start);
    1480           0 :     Py_DECREF(args);
    1481           0 :     PyBuffer_Release(&buf);
    1482           0 :     return result;
    1483             : 
    1484             : fail:
    1485           0 :     Py_XDECREF(args);
    1486           0 :     PyErr_Format(StructError,
    1487             :         "unpack requires a string argument of length %zd",
    1488             :         soself->s_size);
    1489           0 :     return NULL;
    1490             : }
    1491             : 
    1492             : PyDoc_STRVAR(s_unpack_from__doc__,
    1493             : "S.unpack_from(buffer[, offset]) -> (v1, v2, ...)\n\
    1494             : \n\
    1495             : Return tuple containing values unpacked according to this Struct's format.\n\
    1496             : Unlike unpack, unpack_from can unpack values from any object supporting\n\
    1497             : the buffer API, not just str. Requires len(buffer[offset:]) >= self.size.\n\
    1498             : See struct.__doc__ for more on format strings.");
    1499             : 
    1500             : static PyObject *
    1501           0 : s_unpack_from(PyObject *self, PyObject *args, PyObject *kwds)
    1502             : {
    1503             :     static char *kwlist[] = {"buffer", "offset", 0};
    1504             :     static char *fmt = "z*|n:unpack_from";
    1505             :     Py_buffer buf;
    1506           0 :     Py_ssize_t buffer_len = 0, offset = 0;
    1507           0 :     char *buffer = NULL;
    1508           0 :     PyStructObject *soself = (PyStructObject *)self;
    1509             :     PyObject *result;
    1510             :     assert(PyStruct_Check(self));
    1511             :     assert(soself->s_codes != NULL);
    1512             : 
    1513           0 :     if (!PyArg_ParseTupleAndKeywords(args, kwds, fmt, kwlist,
    1514             :                                      &buf, &offset))
    1515           0 :         return NULL;
    1516           0 :     buffer = buf.buf;
    1517           0 :     buffer_len = buf.len;
    1518           0 :     if (buffer == NULL) {
    1519           0 :         PyErr_Format(StructError,
    1520             :             "unpack_from requires a buffer argument");
    1521           0 :         PyBuffer_Release(&buf);
    1522           0 :         return NULL;
    1523             :     }
    1524             : 
    1525           0 :     if (offset < 0)
    1526           0 :         offset += buffer_len;
    1527             : 
    1528           0 :     if (offset < 0 || (buffer_len - offset) < soself->s_size) {
    1529           0 :         PyErr_Format(StructError,
    1530             :             "unpack_from requires a buffer of at least %zd bytes",
    1531             :             soself->s_size);
    1532           0 :         PyBuffer_Release(&buf);
    1533           0 :         return NULL;
    1534             :     }
    1535           0 :     result = s_unpack_internal(soself, buffer + offset);
    1536           0 :     PyBuffer_Release(&buf);
    1537           0 :     return result;
    1538             : }
    1539             : 
    1540             : 
    1541             : /*
    1542             :  * Guts of the pack function.
    1543             :  *
    1544             :  * Takes a struct object, a tuple of arguments, and offset in that tuple of
    1545             :  * argument for where to start processing the arguments for packing, and a
    1546             :  * character buffer for writing the packed string.  The caller must insure
    1547             :  * that the buffer may contain the required length for packing the arguments.
    1548             :  * 0 is returned on success, 1 is returned if there is an error.
    1549             :  *
    1550             :  */
    1551             : static int
    1552           0 : s_pack_internal(PyStructObject *soself, PyObject *args, int offset, char* buf)
    1553             : {
    1554             :     formatcode *code;
    1555             :     /* XXX(nnorwitz): why does i need to be a local?  can we use
    1556             :        the offset parameter or do we need the wider width? */
    1557             :     Py_ssize_t i;
    1558             : 
    1559           0 :     memset(buf, '\0', soself->s_size);
    1560           0 :     i = offset;
    1561           0 :     for (code = soself->s_codes; code->fmtdef != NULL; code++) {
    1562             :         Py_ssize_t n;
    1563           0 :         PyObject *v = PyTuple_GET_ITEM(args, i++);
    1564           0 :         const formatdef *e = code->fmtdef;
    1565           0 :         char *res = buf + code->offset;
    1566           0 :         if (e->format == 's') {
    1567           0 :             if (!PyString_Check(v)) {
    1568           0 :                 PyErr_SetString(StructError,
    1569             :                                 "argument for 's' must "
    1570             :                                 "be a string");
    1571           0 :                 return -1;
    1572             :             }
    1573           0 :             n = PyString_GET_SIZE(v);
    1574           0 :             if (n > code->size)
    1575           0 :                 n = code->size;
    1576           0 :             if (n > 0)
    1577           0 :                 memcpy(res, PyString_AS_STRING(v), n);
    1578           0 :         } else if (e->format == 'p') {
    1579           0 :             if (!PyString_Check(v)) {
    1580           0 :                 PyErr_SetString(StructError,
    1581             :                                 "argument for 'p' must "
    1582             :                                 "be a string");
    1583           0 :                 return -1;
    1584             :             }
    1585           0 :             n = PyString_GET_SIZE(v);
    1586           0 :             if (n > (code->size - 1))
    1587           0 :                 n = code->size - 1;
    1588           0 :             if (n > 0)
    1589           0 :                 memcpy(res + 1, PyString_AS_STRING(v), n);
    1590           0 :             if (n > 255)
    1591           0 :                 n = 255;
    1592           0 :             *res = Py_SAFE_DOWNCAST(n, Py_ssize_t, unsigned char);
    1593           0 :         } else if (e->pack(res, v, e) < 0) {
    1594           0 :             if (strchr(integer_codes, e->format) != NULL &&
    1595           0 :                 PyErr_ExceptionMatches(PyExc_OverflowError))
    1596           0 :                 PyErr_Format(StructError,
    1597             :                              "integer out of range for "
    1598             :                              "'%c' format code",
    1599           0 :                              e->format);
    1600           0 :             return -1;
    1601             :         }
    1602             :     }
    1603             : 
    1604             :     /* Success */
    1605           0 :     return 0;
    1606             : }
    1607             : 
    1608             : 
    1609             : PyDoc_STRVAR(s_pack__doc__,
    1610             : "S.pack(v1, v2, ...) -> string\n\
    1611             : \n\
    1612             : Return a string containing values v1, v2, ... packed according to this\n\
    1613             : Struct's format. See struct.__doc__ for more on format strings.");
    1614             : 
    1615             : static PyObject *
    1616           0 : s_pack(PyObject *self, PyObject *args)
    1617             : {
    1618             :     PyStructObject *soself;
    1619             :     PyObject *result;
    1620             : 
    1621             :     /* Validate arguments. */
    1622           0 :     soself = (PyStructObject *)self;
    1623             :     assert(PyStruct_Check(self));
    1624             :     assert(soself->s_codes != NULL);
    1625           0 :     if (PyTuple_GET_SIZE(args) != soself->s_len)
    1626             :     {
    1627           0 :         PyErr_Format(StructError,
    1628             :             "pack expected %zd items for packing (got %zd)", soself->s_len, PyTuple_GET_SIZE(args));
    1629           0 :         return NULL;
    1630             :     }
    1631             : 
    1632             :     /* Allocate a new string */
    1633           0 :     result = PyString_FromStringAndSize((char *)NULL, soself->s_size);
    1634           0 :     if (result == NULL)
    1635           0 :         return NULL;
    1636             : 
    1637             :     /* Call the guts */
    1638           0 :     if ( s_pack_internal(soself, args, 0, PyString_AS_STRING(result)) != 0 ) {
    1639           0 :         Py_DECREF(result);
    1640           0 :         return NULL;
    1641             :     }
    1642             : 
    1643           0 :     return result;
    1644             : }
    1645             : 
    1646             : PyDoc_STRVAR(s_pack_into__doc__,
    1647             : "S.pack_into(buffer, offset, v1, v2, ...)\n\
    1648             : \n\
    1649             : Pack the values v1, v2, ... according to this Struct's format, write \n\
    1650             : the packed bytes into the writable buffer buf starting at offset.  Note\n\
    1651             : that the offset is not an optional argument.  See struct.__doc__ for \n\
    1652             : more on format strings.");
    1653             : 
    1654             : static PyObject *
    1655           0 : s_pack_into(PyObject *self, PyObject *args)
    1656             : {
    1657             :     PyStructObject *soself;
    1658             :     Py_buffer buf;
    1659             :     Py_ssize_t offset;
    1660             : 
    1661             :     /* Validate arguments.  +1 is for the first arg as buffer. */
    1662           0 :     soself = (PyStructObject *)self;
    1663             :     assert(PyStruct_Check(self));
    1664             :     assert(soself->s_codes != NULL);
    1665           0 :     if (PyTuple_GET_SIZE(args) != (soself->s_len + 2))
    1666             :     {
    1667           0 :         if (PyTuple_GET_SIZE(args) == 0) {
    1668           0 :             PyErr_Format(StructError,
    1669             :                         "pack_into expected buffer argument");
    1670             :         }
    1671           0 :         else if (PyTuple_GET_SIZE(args) == 1) {
    1672           0 :             PyErr_Format(StructError,
    1673             :                         "pack_into expected offset argument");
    1674             :         }
    1675             :         else {
    1676           0 :             PyErr_Format(StructError,
    1677             :                         "pack_into expected %zd items for packing (got %zd)",
    1678           0 :                         soself->s_len, (PyTuple_GET_SIZE(args) - 2));
    1679             :         }
    1680           0 :         return NULL;
    1681             :     }
    1682             : 
    1683             :     /* Extract a writable memory buffer from the first argument */
    1684           0 :     if (!PyArg_Parse(PyTuple_GET_ITEM(args, 0), "w*", &buf))
    1685           0 :         return NULL;
    1686             : 
    1687             :     /* Extract the offset from the first argument */
    1688           0 :     offset = PyInt_AsSsize_t(PyTuple_GET_ITEM(args, 1));
    1689           0 :     if (offset == -1 && PyErr_Occurred()) {
    1690           0 :         PyBuffer_Release(&buf);
    1691           0 :         return NULL;
    1692             :     }
    1693             : 
    1694             :     /* Support negative offsets. */
    1695           0 :     if (offset < 0)
    1696           0 :         offset += buf.len;
    1697             : 
    1698             :     /* Check boundaries */
    1699           0 :     if (offset < 0 || (buf.len - offset) < soself->s_size) {
    1700           0 :         PyErr_Format(StructError,
    1701             :                      "pack_into requires a buffer of at least %zd bytes",
    1702             :                      soself->s_size);
    1703           0 :         PyBuffer_Release(&buf);
    1704           0 :         return NULL;
    1705             :     }
    1706             : 
    1707             :     /* Call the guts */
    1708           0 :     if (s_pack_internal(soself, args, 2, (char *)buf.buf + offset) != 0) {
    1709           0 :         PyBuffer_Release(&buf);
    1710           0 :         return NULL;
    1711             :     }
    1712           0 :     PyBuffer_Release(&buf);
    1713             : 
    1714           0 :     Py_RETURN_NONE;
    1715             : }
    1716             : 
    1717             : static PyObject *
    1718           0 : s_get_format(PyStructObject *self, void *unused)
    1719             : {
    1720           0 :     Py_INCREF(self->s_format);
    1721           0 :     return self->s_format;
    1722             : }
    1723             : 
    1724             : static PyObject *
    1725           0 : s_get_size(PyStructObject *self, void *unused)
    1726             : {
    1727           0 :     return PyInt_FromSsize_t(self->s_size);
    1728             : }
    1729             : 
    1730             : PyDoc_STRVAR(s_sizeof__doc__,
    1731             : "S.__sizeof__() -> size of S in memory, in bytes");
    1732             : 
    1733             : static PyObject *
    1734           0 : s_sizeof(PyStructObject *self, void *unused)
    1735             : {
    1736             :     Py_ssize_t size;
    1737             : 
    1738           0 :     size = _PyObject_SIZE(Py_TYPE(self)) + sizeof(formatcode) * (self->s_len + 1);
    1739           0 :     return PyLong_FromSsize_t(size);
    1740             : }
    1741             : 
    1742             : /* List of functions */
    1743             : 
    1744             : static struct PyMethodDef s_methods[] = {
    1745             :     {"pack",            s_pack,         METH_VARARGS, s_pack__doc__},
    1746             :     {"pack_into",       s_pack_into,    METH_VARARGS, s_pack_into__doc__},
    1747             :     {"unpack",          s_unpack,       METH_O, s_unpack__doc__},
    1748             :     {"unpack_from",     (PyCFunction)s_unpack_from, METH_VARARGS|METH_KEYWORDS,
    1749             :                     s_unpack_from__doc__},
    1750             :     {"__sizeof__",      (PyCFunction)s_sizeof, METH_NOARGS, s_sizeof__doc__},
    1751             :     {NULL,       NULL}          /* sentinel */
    1752             : };
    1753             : 
    1754             : PyDoc_STRVAR(s__doc__, "Compiled struct object");
    1755             : 
    1756             : #define OFF(x) offsetof(PyStructObject, x)
    1757             : 
    1758             : static PyGetSetDef s_getsetlist[] = {
    1759             :     {"format", (getter)s_get_format, (setter)NULL, "struct format string", NULL},
    1760             :     {"size", (getter)s_get_size, (setter)NULL, "struct size in bytes", NULL},
    1761             :     {NULL} /* sentinel */
    1762             : };
    1763             : 
    1764             : static
    1765             : PyTypeObject PyStructType = {
    1766             :     PyVarObject_HEAD_INIT(NULL, 0)
    1767             :     "Struct",
    1768             :     sizeof(PyStructObject),
    1769             :     0,
    1770             :     (destructor)s_dealloc,      /* tp_dealloc */
    1771             :     0,                                          /* tp_print */
    1772             :     0,                                          /* tp_getattr */
    1773             :     0,                                          /* tp_setattr */
    1774             :     0,                                          /* tp_compare */
    1775             :     0,                                          /* tp_repr */
    1776             :     0,                                          /* tp_as_number */
    1777             :     0,                                          /* tp_as_sequence */
    1778             :     0,                                          /* tp_as_mapping */
    1779             :     0,                                          /* tp_hash */
    1780             :     0,                                          /* tp_call */
    1781             :     0,                                          /* tp_str */
    1782             :     PyObject_GenericGetAttr,            /* tp_getattro */
    1783             :     PyObject_GenericSetAttr,            /* tp_setattro */
    1784             :     0,                                          /* tp_as_buffer */
    1785             :     Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_WEAKREFS,/* tp_flags */
    1786             :     s__doc__,                           /* tp_doc */
    1787             :     0,                                          /* tp_traverse */
    1788             :     0,                                          /* tp_clear */
    1789             :     0,                                          /* tp_richcompare */
    1790             :     offsetof(PyStructObject, weakreflist),      /* tp_weaklistoffset */
    1791             :     0,                                          /* tp_iter */
    1792             :     0,                                          /* tp_iternext */
    1793             :     s_methods,                          /* tp_methods */
    1794             :     NULL,                               /* tp_members */
    1795             :     s_getsetlist,               /* tp_getset */
    1796             :     0,                                          /* tp_base */
    1797             :     0,                                          /* tp_dict */
    1798             :     0,                                          /* tp_descr_get */
    1799             :     0,                                          /* tp_descr_set */
    1800             :     0,                                          /* tp_dictoffset */
    1801             :     s_init,                             /* tp_init */
    1802             :     PyType_GenericAlloc,/* tp_alloc */
    1803             :     s_new,                              /* tp_new */
    1804             :     PyObject_Del,               /* tp_free */
    1805             : };
    1806             : 
    1807             : 
    1808             : /* ---- Standalone functions  ---- */
    1809             : 
    1810             : #define MAXCACHE 100
    1811             : static PyObject *cache = NULL;
    1812             : 
    1813             : static PyObject *
    1814           6 : cache_struct(PyObject *fmt)
    1815             : {
    1816             :     PyObject * s_object;
    1817             : 
    1818           6 :     if (cache == NULL) {
    1819           3 :         cache = PyDict_New();
    1820           3 :         if (cache == NULL)
    1821           0 :             return NULL;
    1822             :     }
    1823             : 
    1824           6 :     s_object = PyDict_GetItem(cache, fmt);
    1825           6 :     if (s_object != NULL) {
    1826           3 :         Py_INCREF(s_object);
    1827           3 :         return s_object;
    1828             :     }
    1829             : 
    1830           3 :     s_object = PyObject_CallFunctionObjArgs((PyObject *)(&PyStructType), fmt, NULL);
    1831           3 :     if (s_object != NULL) {
    1832           3 :         if (PyDict_Size(cache) >= MAXCACHE)
    1833           0 :             PyDict_Clear(cache);
    1834             :         /* Attempt to cache the result */
    1835           3 :         if (PyDict_SetItem(cache, fmt, s_object) == -1)
    1836           0 :             PyErr_Clear();
    1837             :     }
    1838           3 :     return s_object;
    1839             : }
    1840             : 
    1841             : PyDoc_STRVAR(clearcache_doc,
    1842             : "Clear the internal cache.");
    1843             : 
    1844             : static PyObject *
    1845           0 : clearcache(PyObject *self)
    1846             : {
    1847           0 :     Py_CLEAR(cache);
    1848           0 :     Py_RETURN_NONE;
    1849             : }
    1850             : 
    1851             : PyDoc_STRVAR(calcsize_doc,
    1852             : "Return size of C struct described by format string fmt.");
    1853             : 
    1854             : static PyObject *
    1855           0 : calcsize(PyObject *self, PyObject *fmt)
    1856             : {
    1857             :     Py_ssize_t n;
    1858           0 :     PyObject *s_object = cache_struct(fmt);
    1859           0 :     if (s_object == NULL)
    1860           0 :         return NULL;
    1861           0 :     n = ((PyStructObject *)s_object)->s_size;
    1862           0 :     Py_DECREF(s_object);
    1863           0 :     return PyInt_FromSsize_t(n);
    1864             : }
    1865             : 
    1866             : PyDoc_STRVAR(pack_doc,
    1867             : "Return string containing values v1, v2, ... packed according to fmt.");
    1868             : 
    1869             : static PyObject *
    1870           0 : pack(PyObject *self, PyObject *args)
    1871             : {
    1872             :     PyObject *s_object, *fmt, *newargs, *result;
    1873           0 :     Py_ssize_t n = PyTuple_GET_SIZE(args);
    1874             : 
    1875           0 :     if (n == 0) {
    1876           0 :         PyErr_SetString(PyExc_TypeError, "missing format argument");
    1877           0 :         return NULL;
    1878             :     }
    1879           0 :     fmt = PyTuple_GET_ITEM(args, 0);
    1880           0 :     newargs = PyTuple_GetSlice(args, 1, n);
    1881           0 :     if (newargs == NULL)
    1882           0 :         return NULL;
    1883             : 
    1884           0 :     s_object = cache_struct(fmt);
    1885           0 :     if (s_object == NULL) {
    1886           0 :         Py_DECREF(newargs);
    1887           0 :         return NULL;
    1888             :     }
    1889           0 :     result = s_pack(s_object, newargs);
    1890           0 :     Py_DECREF(newargs);
    1891           0 :     Py_DECREF(s_object);
    1892           0 :     return result;
    1893             : }
    1894             : 
    1895             : PyDoc_STRVAR(pack_into_doc,
    1896             : "Pack the values v1, v2, ... according to fmt.\n\
    1897             : Write the packed bytes into the writable buffer buf starting at offset.");
    1898             : 
    1899             : static PyObject *
    1900           0 : pack_into(PyObject *self, PyObject *args)
    1901             : {
    1902             :     PyObject *s_object, *fmt, *newargs, *result;
    1903           0 :     Py_ssize_t n = PyTuple_GET_SIZE(args);
    1904             : 
    1905           0 :     if (n == 0) {
    1906           0 :         PyErr_SetString(PyExc_TypeError, "missing format argument");
    1907           0 :         return NULL;
    1908             :     }
    1909           0 :     fmt = PyTuple_GET_ITEM(args, 0);
    1910           0 :     newargs = PyTuple_GetSlice(args, 1, n);
    1911           0 :     if (newargs == NULL)
    1912           0 :         return NULL;
    1913             : 
    1914           0 :     s_object = cache_struct(fmt);
    1915           0 :     if (s_object == NULL) {
    1916           0 :         Py_DECREF(newargs);
    1917           0 :         return NULL;
    1918             :     }
    1919           0 :     result = s_pack_into(s_object, newargs);
    1920           0 :     Py_DECREF(newargs);
    1921           0 :     Py_DECREF(s_object);
    1922           0 :     return result;
    1923             : }
    1924             : 
    1925             : PyDoc_STRVAR(unpack_doc,
    1926             : "Unpack the string containing packed C structure data, according to fmt.\n\
    1927             : Requires len(string) == calcsize(fmt).");
    1928             : 
    1929             : static PyObject *
    1930           6 : unpack(PyObject *self, PyObject *args)
    1931             : {
    1932             :     PyObject *s_object, *fmt, *inputstr, *result;
    1933             : 
    1934           6 :     if (!PyArg_UnpackTuple(args, "unpack", 2, 2, &fmt, &inputstr))
    1935           0 :         return NULL;
    1936             : 
    1937           6 :     s_object = cache_struct(fmt);
    1938           6 :     if (s_object == NULL)
    1939           0 :         return NULL;
    1940           6 :     result = s_unpack(s_object, inputstr);
    1941           6 :     Py_DECREF(s_object);
    1942           6 :     return result;
    1943             : }
    1944             : 
    1945             : PyDoc_STRVAR(unpack_from_doc,
    1946             : "Unpack the buffer, containing packed C structure data, according to\n\
    1947             : fmt, starting at offset. Requires len(buffer[offset:]) >= calcsize(fmt).");
    1948             : 
    1949             : static PyObject *
    1950           0 : unpack_from(PyObject *self, PyObject *args, PyObject *kwds)
    1951             : {
    1952             :     PyObject *s_object, *fmt, *newargs, *result;
    1953           0 :     Py_ssize_t n = PyTuple_GET_SIZE(args);
    1954             : 
    1955           0 :     if (n == 0) {
    1956           0 :         PyErr_SetString(PyExc_TypeError, "missing format argument");
    1957           0 :         return NULL;
    1958             :     }
    1959           0 :     fmt = PyTuple_GET_ITEM(args, 0);
    1960           0 :     newargs = PyTuple_GetSlice(args, 1, n);
    1961           0 :     if (newargs == NULL)
    1962           0 :         return NULL;
    1963             : 
    1964           0 :     s_object = cache_struct(fmt);
    1965           0 :     if (s_object == NULL) {
    1966           0 :         Py_DECREF(newargs);
    1967           0 :         return NULL;
    1968             :     }
    1969           0 :     result = s_unpack_from(s_object, newargs, kwds);
    1970           0 :     Py_DECREF(newargs);
    1971           0 :     Py_DECREF(s_object);
    1972           0 :     return result;
    1973             : }
    1974             : 
    1975             : static struct PyMethodDef module_functions[] = {
    1976             :     {"_clearcache",     (PyCFunction)clearcache,        METH_NOARGS,    clearcache_doc},
    1977             :     {"calcsize",        calcsize,       METH_O, calcsize_doc},
    1978             :     {"pack",            pack,           METH_VARARGS,   pack_doc},
    1979             :     {"pack_into",       pack_into,      METH_VARARGS,   pack_into_doc},
    1980             :     {"unpack",          unpack, METH_VARARGS,   unpack_doc},
    1981             :     {"unpack_from",     (PyCFunction)unpack_from,
    1982             :                     METH_VARARGS|METH_KEYWORDS,         unpack_from_doc},
    1983             :     {NULL,       NULL}          /* sentinel */
    1984             : };
    1985             : 
    1986             : 
    1987             : /* Module initialization */
    1988             : 
    1989             : PyDoc_STRVAR(module_doc,
    1990             : "Functions to convert between Python values and C structs represented\n\
    1991             : as Python strings. It uses format strings (explained below) as compact\n\
    1992             : descriptions of the lay-out of the C structs and the intended conversion\n\
    1993             : to/from Python values.\n\
    1994             : \n\
    1995             : The optional first format char indicates byte order, size and alignment:\n\
    1996             :   @: native order, size & alignment (default)\n\
    1997             :   =: native order, std. size & alignment\n\
    1998             :   <: little-endian, std. size & alignment\n\
    1999             :   >: big-endian, std. size & alignment\n\
    2000             :   !: same as >\n\
    2001             : \n\
    2002             : The remaining chars indicate types of args and must match exactly;\n\
    2003             : these can be preceded by a decimal repeat count:\n\
    2004             :   x: pad byte (no data); c:char; b:signed byte; B:unsigned byte;\n\
    2005             :   ?: _Bool (requires C99; if not available, char is used instead)\n\
    2006             :   h:short; H:unsigned short; i:int; I:unsigned int;\n\
    2007             :   l:long; L:unsigned long; f:float; d:double.\n\
    2008             : Special cases (preceding decimal count indicates length):\n\
    2009             :   s:string (array of char); p: pascal string (with count byte).\n\
    2010             : Special case (only available in native format):\n\
    2011             :   P:an integer type that is wide enough to hold a pointer.\n\
    2012             : Special case (not in native mode unless 'long long' in platform C):\n\
    2013             :   q:long long; Q:unsigned long long\n\
    2014             : Whitespace between formats is ignored.\n\
    2015             : \n\
    2016             : The variable struct.error is an exception raised on errors.\n");
    2017             : 
    2018             : PyMODINIT_FUNC
    2019           3 : init_struct(void)
    2020             : {
    2021             :     PyObject *ver, *m;
    2022             : 
    2023           3 :     ver = PyString_FromString("0.2");
    2024           3 :     if (ver == NULL)
    2025           0 :         return;
    2026             : 
    2027           3 :     m = Py_InitModule3("_struct", module_functions, module_doc);
    2028           3 :     if (m == NULL)
    2029           0 :         return;
    2030             : 
    2031           3 :     Py_TYPE(&PyStructType) = &PyType_Type;
    2032           3 :     if (PyType_Ready(&PyStructType) < 0)
    2033           0 :         return;
    2034             : 
    2035             :     /* This speed trick can't be used until overflow masking goes
    2036             :        away, because native endian always raises exceptions
    2037             :        instead of overflow masking. */
    2038             : 
    2039             :     /* Check endian and swap in faster functions */
    2040             :     {
    2041           3 :         int one = 1;
    2042           3 :         formatdef *native = native_table;
    2043             :         formatdef *other, *ptr;
    2044           3 :         if ((int)*(unsigned char*)&one)
    2045           3 :             other = lilendian_table;
    2046             :         else
    2047           0 :             other = bigendian_table;
    2048             :         /* Scan through the native table, find a matching
    2049             :            entry in the endian table and swap in the
    2050             :            native implementations whenever possible
    2051             :            (64-bit platforms may not have "standard" sizes) */
    2052          57 :         while (native->format != '\0' && other->format != '\0') {
    2053          51 :             ptr = other;
    2054         102 :             while (ptr->format != '\0') {
    2055          51 :                 if (ptr->format == native->format) {
    2056             :                     /* Match faster when formats are
    2057             :                        listed in the same order */
    2058          51 :                     if (ptr == other)
    2059          51 :                         other++;
    2060             :                     /* Only use the trick if the
    2061             :                        size matches */
    2062          51 :                     if (ptr->size != native->size)
    2063           6 :                         break;
    2064             :                     /* Skip float and double, could be
    2065             :                        "unknown" float format */
    2066          45 :                     if (ptr->format == 'd' || ptr->format == 'f')
    2067             :                         break;
    2068          39 :                     ptr->pack = native->pack;
    2069          39 :                     ptr->unpack = native->unpack;
    2070          39 :                     break;
    2071             :                 }
    2072           0 :                 ptr++;
    2073             :             }
    2074          51 :             native++;
    2075             :         }
    2076             :     }
    2077             : 
    2078             :     /* Add some symbolic constants to the module */
    2079           3 :     if (StructError == NULL) {
    2080           3 :         StructError = PyErr_NewException("struct.error", NULL, NULL);
    2081           3 :         if (StructError == NULL)
    2082           0 :             return;
    2083             :     }
    2084             : 
    2085           3 :     Py_INCREF(StructError);
    2086           3 :     PyModule_AddObject(m, "error", StructError);
    2087             : 
    2088           3 :     Py_INCREF((PyObject*)&PyStructType);
    2089           3 :     PyModule_AddObject(m, "Struct", (PyObject*)&PyStructType);
    2090             : 
    2091           3 :     PyModule_AddObject(m, "__version__", ver);
    2092             : 
    2093           3 :     PyModule_AddIntConstant(m, "_PY_STRUCT_RANGE_CHECKING", 1);
    2094           3 :     PyModule_AddIntConstant(m, "_PY_STRUCT_FLOAT_COERCE", 1);
    2095             : }

Generated by: LCOV version 1.10