17db96d56Sopenharmony_ci/* struct module -- pack values into and (out of) bytes objects */
27db96d56Sopenharmony_ci
37db96d56Sopenharmony_ci/* New version supporting byte order, alignment and size options,
47db96d56Sopenharmony_ci   character strings, and unsigned numbers */
57db96d56Sopenharmony_ci
67db96d56Sopenharmony_ci#ifndef Py_BUILD_CORE_BUILTIN
77db96d56Sopenharmony_ci#  define Py_BUILD_CORE_MODULE 1
87db96d56Sopenharmony_ci#endif
97db96d56Sopenharmony_ci
107db96d56Sopenharmony_ci#define PY_SSIZE_T_CLEAN
117db96d56Sopenharmony_ci
127db96d56Sopenharmony_ci#include "Python.h"
137db96d56Sopenharmony_ci#include "pycore_moduleobject.h"  // _PyModule_GetState()
147db96d56Sopenharmony_ci#include "structmember.h"         // PyMemberDef
157db96d56Sopenharmony_ci#include <ctype.h>
167db96d56Sopenharmony_ci
177db96d56Sopenharmony_ci/*[clinic input]
187db96d56Sopenharmony_ciclass Struct "PyStructObject *" "&PyStructType"
197db96d56Sopenharmony_ci[clinic start generated code]*/
207db96d56Sopenharmony_ci/*[clinic end generated code: output=da39a3ee5e6b4b0d input=9b032058a83ed7c3]*/
217db96d56Sopenharmony_ci
227db96d56Sopenharmony_citypedef struct {
237db96d56Sopenharmony_ci    PyObject *cache;
247db96d56Sopenharmony_ci    PyObject *PyStructType;
257db96d56Sopenharmony_ci    PyObject *unpackiter_type;
267db96d56Sopenharmony_ci    PyObject *StructError;
277db96d56Sopenharmony_ci} _structmodulestate;
287db96d56Sopenharmony_ci
297db96d56Sopenharmony_cistatic inline _structmodulestate*
307db96d56Sopenharmony_ciget_struct_state(PyObject *module)
317db96d56Sopenharmony_ci{
327db96d56Sopenharmony_ci    void *state = _PyModule_GetState(module);
337db96d56Sopenharmony_ci    assert(state != NULL);
347db96d56Sopenharmony_ci    return (_structmodulestate *)state;
357db96d56Sopenharmony_ci}
367db96d56Sopenharmony_ci
377db96d56Sopenharmony_cistatic struct PyModuleDef _structmodule;
387db96d56Sopenharmony_ci
397db96d56Sopenharmony_ci#define get_struct_state_structinst(self) \
407db96d56Sopenharmony_ci    (get_struct_state(PyType_GetModuleByDef(Py_TYPE(self), &_structmodule)))
417db96d56Sopenharmony_ci#define get_struct_state_iterinst(self) \
427db96d56Sopenharmony_ci    (get_struct_state(PyType_GetModule(Py_TYPE(self))))
437db96d56Sopenharmony_ci
447db96d56Sopenharmony_ci/* The translation function for each format character is table driven */
457db96d56Sopenharmony_citypedef struct _formatdef {
467db96d56Sopenharmony_ci    char format;
477db96d56Sopenharmony_ci    Py_ssize_t size;
487db96d56Sopenharmony_ci    Py_ssize_t alignment;
497db96d56Sopenharmony_ci    PyObject* (*unpack)(_structmodulestate *, const char *,
507db96d56Sopenharmony_ci                        const struct _formatdef *);
517db96d56Sopenharmony_ci    int (*pack)(_structmodulestate *, char *, PyObject *,
527db96d56Sopenharmony_ci                const struct _formatdef *);
537db96d56Sopenharmony_ci} formatdef;
547db96d56Sopenharmony_ci
557db96d56Sopenharmony_citypedef struct _formatcode {
567db96d56Sopenharmony_ci    const struct _formatdef *fmtdef;
577db96d56Sopenharmony_ci    Py_ssize_t offset;
587db96d56Sopenharmony_ci    Py_ssize_t size;
597db96d56Sopenharmony_ci    Py_ssize_t repeat;
607db96d56Sopenharmony_ci} formatcode;
617db96d56Sopenharmony_ci
627db96d56Sopenharmony_ci/* Struct object interface */
637db96d56Sopenharmony_ci
647db96d56Sopenharmony_citypedef struct {
657db96d56Sopenharmony_ci    PyObject_HEAD
667db96d56Sopenharmony_ci    Py_ssize_t s_size;
677db96d56Sopenharmony_ci    Py_ssize_t s_len;
687db96d56Sopenharmony_ci    formatcode *s_codes;
697db96d56Sopenharmony_ci    PyObject *s_format;
707db96d56Sopenharmony_ci    PyObject *weakreflist; /* List of weak references */
717db96d56Sopenharmony_ci} PyStructObject;
727db96d56Sopenharmony_ci
737db96d56Sopenharmony_ci#define PyStruct_Check(op, state) PyObject_TypeCheck(op, (PyTypeObject *)(state)->PyStructType)
747db96d56Sopenharmony_ci
757db96d56Sopenharmony_ci/* Define various structs to figure out the alignments of types */
767db96d56Sopenharmony_ci
777db96d56Sopenharmony_ci
787db96d56Sopenharmony_citypedef struct { char c; short x; } st_short;
797db96d56Sopenharmony_citypedef struct { char c; int x; } st_int;
807db96d56Sopenharmony_citypedef struct { char c; long x; } st_long;
817db96d56Sopenharmony_citypedef struct { char c; float x; } st_float;
827db96d56Sopenharmony_citypedef struct { char c; double x; } st_double;
837db96d56Sopenharmony_citypedef struct { char c; void *x; } st_void_p;
847db96d56Sopenharmony_citypedef struct { char c; size_t x; } st_size_t;
857db96d56Sopenharmony_citypedef struct { char c; _Bool x; } st_bool;
867db96d56Sopenharmony_ci
877db96d56Sopenharmony_ci#define SHORT_ALIGN (sizeof(st_short) - sizeof(short))
887db96d56Sopenharmony_ci#define INT_ALIGN (sizeof(st_int) - sizeof(int))
897db96d56Sopenharmony_ci#define LONG_ALIGN (sizeof(st_long) - sizeof(long))
907db96d56Sopenharmony_ci#define FLOAT_ALIGN (sizeof(st_float) - sizeof(float))
917db96d56Sopenharmony_ci#define DOUBLE_ALIGN (sizeof(st_double) - sizeof(double))
927db96d56Sopenharmony_ci#define VOID_P_ALIGN (sizeof(st_void_p) - sizeof(void *))
937db96d56Sopenharmony_ci#define SIZE_T_ALIGN (sizeof(st_size_t) - sizeof(size_t))
947db96d56Sopenharmony_ci#define BOOL_ALIGN (sizeof(st_bool) - sizeof(_Bool))
957db96d56Sopenharmony_ci
967db96d56Sopenharmony_ci/* We can't support q and Q in native mode unless the compiler does;
977db96d56Sopenharmony_ci   in std mode, they're 8 bytes on all platforms. */
987db96d56Sopenharmony_citypedef struct { char c; long long x; } s_long_long;
997db96d56Sopenharmony_ci#define LONG_LONG_ALIGN (sizeof(s_long_long) - sizeof(long long))
1007db96d56Sopenharmony_ci
1017db96d56Sopenharmony_ci#ifdef __powerc
1027db96d56Sopenharmony_ci#pragma options align=reset
1037db96d56Sopenharmony_ci#endif
1047db96d56Sopenharmony_ci
1057db96d56Sopenharmony_ci/*[python input]
1067db96d56Sopenharmony_ciclass cache_struct_converter(CConverter):
1077db96d56Sopenharmony_ci    type = 'PyStructObject *'
1087db96d56Sopenharmony_ci    converter = 'cache_struct_converter'
1097db96d56Sopenharmony_ci    c_default = "NULL"
1107db96d56Sopenharmony_ci
1117db96d56Sopenharmony_ci    def parse_arg(self, argname, displayname):
1127db96d56Sopenharmony_ci        return """
1137db96d56Sopenharmony_ci            if (!{converter}(module, {argname}, &{paramname})) {{{{
1147db96d56Sopenharmony_ci                goto exit;
1157db96d56Sopenharmony_ci            }}}}
1167db96d56Sopenharmony_ci            """.format(argname=argname, paramname=self.name,
1177db96d56Sopenharmony_ci                       converter=self.converter)
1187db96d56Sopenharmony_ci
1197db96d56Sopenharmony_ci    def cleanup(self):
1207db96d56Sopenharmony_ci        return "Py_XDECREF(%s);\n" % self.name
1217db96d56Sopenharmony_ci[python start generated code]*/
1227db96d56Sopenharmony_ci/*[python end generated code: output=da39a3ee5e6b4b0d input=d6746621c2fb1a7d]*/
1237db96d56Sopenharmony_ci
1247db96d56Sopenharmony_cistatic int cache_struct_converter(PyObject *, PyObject *, PyStructObject **);
1257db96d56Sopenharmony_ci
1267db96d56Sopenharmony_ci#include "clinic/_struct.c.h"
1277db96d56Sopenharmony_ci
1287db96d56Sopenharmony_ci/* Helper for integer format codes: converts an arbitrary Python object to a
1297db96d56Sopenharmony_ci   PyLongObject if possible, otherwise fails.  Caller should decref. */
1307db96d56Sopenharmony_ci
1317db96d56Sopenharmony_cistatic PyObject *
1327db96d56Sopenharmony_ciget_pylong(_structmodulestate *state, PyObject *v)
1337db96d56Sopenharmony_ci{
1347db96d56Sopenharmony_ci    assert(v != NULL);
1357db96d56Sopenharmony_ci    if (!PyLong_Check(v)) {
1367db96d56Sopenharmony_ci        /* Not an integer;  try to use __index__ to convert. */
1377db96d56Sopenharmony_ci        if (PyIndex_Check(v)) {
1387db96d56Sopenharmony_ci            v = _PyNumber_Index(v);
1397db96d56Sopenharmony_ci            if (v == NULL)
1407db96d56Sopenharmony_ci                return NULL;
1417db96d56Sopenharmony_ci        }
1427db96d56Sopenharmony_ci        else {
1437db96d56Sopenharmony_ci            PyErr_SetString(state->StructError,
1447db96d56Sopenharmony_ci                            "required argument is not an integer");
1457db96d56Sopenharmony_ci            return NULL;
1467db96d56Sopenharmony_ci        }
1477db96d56Sopenharmony_ci    }
1487db96d56Sopenharmony_ci    else
1497db96d56Sopenharmony_ci        Py_INCREF(v);
1507db96d56Sopenharmony_ci
1517db96d56Sopenharmony_ci    assert(PyLong_Check(v));
1527db96d56Sopenharmony_ci    return v;
1537db96d56Sopenharmony_ci}
1547db96d56Sopenharmony_ci
1557db96d56Sopenharmony_ci/* Helper routine to get a C long and raise the appropriate error if it isn't
1567db96d56Sopenharmony_ci   one */
1577db96d56Sopenharmony_ci
1587db96d56Sopenharmony_cistatic int
1597db96d56Sopenharmony_ciget_long(_structmodulestate *state, PyObject *v, long *p)
1607db96d56Sopenharmony_ci{
1617db96d56Sopenharmony_ci    long x;
1627db96d56Sopenharmony_ci
1637db96d56Sopenharmony_ci    v = get_pylong(state, v);
1647db96d56Sopenharmony_ci    if (v == NULL)
1657db96d56Sopenharmony_ci        return -1;
1667db96d56Sopenharmony_ci    assert(PyLong_Check(v));
1677db96d56Sopenharmony_ci    x = PyLong_AsLong(v);
1687db96d56Sopenharmony_ci    Py_DECREF(v);
1697db96d56Sopenharmony_ci    if (x == (long)-1 && PyErr_Occurred()) {
1707db96d56Sopenharmony_ci        if (PyErr_ExceptionMatches(PyExc_OverflowError))
1717db96d56Sopenharmony_ci            PyErr_SetString(state->StructError,
1727db96d56Sopenharmony_ci                            "argument out of range");
1737db96d56Sopenharmony_ci        return -1;
1747db96d56Sopenharmony_ci    }
1757db96d56Sopenharmony_ci    *p = x;
1767db96d56Sopenharmony_ci    return 0;
1777db96d56Sopenharmony_ci}
1787db96d56Sopenharmony_ci
1797db96d56Sopenharmony_ci
1807db96d56Sopenharmony_ci/* Same, but handling unsigned long */
1817db96d56Sopenharmony_ci
1827db96d56Sopenharmony_cistatic int
1837db96d56Sopenharmony_ciget_ulong(_structmodulestate *state, PyObject *v, unsigned long *p)
1847db96d56Sopenharmony_ci{
1857db96d56Sopenharmony_ci    unsigned long x;
1867db96d56Sopenharmony_ci
1877db96d56Sopenharmony_ci    v = get_pylong(state, v);
1887db96d56Sopenharmony_ci    if (v == NULL)
1897db96d56Sopenharmony_ci        return -1;
1907db96d56Sopenharmony_ci    assert(PyLong_Check(v));
1917db96d56Sopenharmony_ci    x = PyLong_AsUnsignedLong(v);
1927db96d56Sopenharmony_ci    Py_DECREF(v);
1937db96d56Sopenharmony_ci    if (x == (unsigned long)-1 && PyErr_Occurred()) {
1947db96d56Sopenharmony_ci        if (PyErr_ExceptionMatches(PyExc_OverflowError))
1957db96d56Sopenharmony_ci            PyErr_SetString(state->StructError,
1967db96d56Sopenharmony_ci                            "argument out of range");
1977db96d56Sopenharmony_ci        return -1;
1987db96d56Sopenharmony_ci    }
1997db96d56Sopenharmony_ci    *p = x;
2007db96d56Sopenharmony_ci    return 0;
2017db96d56Sopenharmony_ci}
2027db96d56Sopenharmony_ci
2037db96d56Sopenharmony_ci/* Same, but handling native long long. */
2047db96d56Sopenharmony_ci
2057db96d56Sopenharmony_cistatic int
2067db96d56Sopenharmony_ciget_longlong(_structmodulestate *state, PyObject *v, long long *p)
2077db96d56Sopenharmony_ci{
2087db96d56Sopenharmony_ci    long long x;
2097db96d56Sopenharmony_ci
2107db96d56Sopenharmony_ci    v = get_pylong(state, v);
2117db96d56Sopenharmony_ci    if (v == NULL)
2127db96d56Sopenharmony_ci        return -1;
2137db96d56Sopenharmony_ci    assert(PyLong_Check(v));
2147db96d56Sopenharmony_ci    x = PyLong_AsLongLong(v);
2157db96d56Sopenharmony_ci    Py_DECREF(v);
2167db96d56Sopenharmony_ci    if (x == (long long)-1 && PyErr_Occurred()) {
2177db96d56Sopenharmony_ci        if (PyErr_ExceptionMatches(PyExc_OverflowError))
2187db96d56Sopenharmony_ci            PyErr_SetString(state->StructError,
2197db96d56Sopenharmony_ci                            "argument out of range");
2207db96d56Sopenharmony_ci        return -1;
2217db96d56Sopenharmony_ci    }
2227db96d56Sopenharmony_ci    *p = x;
2237db96d56Sopenharmony_ci    return 0;
2247db96d56Sopenharmony_ci}
2257db96d56Sopenharmony_ci
2267db96d56Sopenharmony_ci/* Same, but handling native unsigned long long. */
2277db96d56Sopenharmony_ci
2287db96d56Sopenharmony_cistatic int
2297db96d56Sopenharmony_ciget_ulonglong(_structmodulestate *state, PyObject *v, unsigned long long *p)
2307db96d56Sopenharmony_ci{
2317db96d56Sopenharmony_ci    unsigned long long x;
2327db96d56Sopenharmony_ci
2337db96d56Sopenharmony_ci    v = get_pylong(state, v);
2347db96d56Sopenharmony_ci    if (v == NULL)
2357db96d56Sopenharmony_ci        return -1;
2367db96d56Sopenharmony_ci    assert(PyLong_Check(v));
2377db96d56Sopenharmony_ci    x = PyLong_AsUnsignedLongLong(v);
2387db96d56Sopenharmony_ci    Py_DECREF(v);
2397db96d56Sopenharmony_ci    if (x == (unsigned long long)-1 && PyErr_Occurred()) {
2407db96d56Sopenharmony_ci        if (PyErr_ExceptionMatches(PyExc_OverflowError))
2417db96d56Sopenharmony_ci            PyErr_SetString(state->StructError,
2427db96d56Sopenharmony_ci                            "argument out of range");
2437db96d56Sopenharmony_ci        return -1;
2447db96d56Sopenharmony_ci    }
2457db96d56Sopenharmony_ci    *p = x;
2467db96d56Sopenharmony_ci    return 0;
2477db96d56Sopenharmony_ci}
2487db96d56Sopenharmony_ci
2497db96d56Sopenharmony_ci/* Same, but handling Py_ssize_t */
2507db96d56Sopenharmony_ci
2517db96d56Sopenharmony_cistatic int
2527db96d56Sopenharmony_ciget_ssize_t(_structmodulestate *state, PyObject *v, Py_ssize_t *p)
2537db96d56Sopenharmony_ci{
2547db96d56Sopenharmony_ci    Py_ssize_t x;
2557db96d56Sopenharmony_ci
2567db96d56Sopenharmony_ci    v = get_pylong(state, v);
2577db96d56Sopenharmony_ci    if (v == NULL)
2587db96d56Sopenharmony_ci        return -1;
2597db96d56Sopenharmony_ci    assert(PyLong_Check(v));
2607db96d56Sopenharmony_ci    x = PyLong_AsSsize_t(v);
2617db96d56Sopenharmony_ci    Py_DECREF(v);
2627db96d56Sopenharmony_ci    if (x == (Py_ssize_t)-1 && PyErr_Occurred()) {
2637db96d56Sopenharmony_ci        if (PyErr_ExceptionMatches(PyExc_OverflowError))
2647db96d56Sopenharmony_ci            PyErr_SetString(state->StructError,
2657db96d56Sopenharmony_ci                            "argument out of range");
2667db96d56Sopenharmony_ci        return -1;
2677db96d56Sopenharmony_ci    }
2687db96d56Sopenharmony_ci    *p = x;
2697db96d56Sopenharmony_ci    return 0;
2707db96d56Sopenharmony_ci}
2717db96d56Sopenharmony_ci
2727db96d56Sopenharmony_ci/* Same, but handling size_t */
2737db96d56Sopenharmony_ci
2747db96d56Sopenharmony_cistatic int
2757db96d56Sopenharmony_ciget_size_t(_structmodulestate *state, PyObject *v, size_t *p)
2767db96d56Sopenharmony_ci{
2777db96d56Sopenharmony_ci    size_t x;
2787db96d56Sopenharmony_ci
2797db96d56Sopenharmony_ci    v = get_pylong(state, v);
2807db96d56Sopenharmony_ci    if (v == NULL)
2817db96d56Sopenharmony_ci        return -1;
2827db96d56Sopenharmony_ci    assert(PyLong_Check(v));
2837db96d56Sopenharmony_ci    x = PyLong_AsSize_t(v);
2847db96d56Sopenharmony_ci    Py_DECREF(v);
2857db96d56Sopenharmony_ci    if (x == (size_t)-1 && PyErr_Occurred()) {
2867db96d56Sopenharmony_ci        if (PyErr_ExceptionMatches(PyExc_OverflowError))
2877db96d56Sopenharmony_ci            PyErr_SetString(state->StructError,
2887db96d56Sopenharmony_ci                            "argument out of range");
2897db96d56Sopenharmony_ci        return -1;
2907db96d56Sopenharmony_ci    }
2917db96d56Sopenharmony_ci    *p = x;
2927db96d56Sopenharmony_ci    return 0;
2937db96d56Sopenharmony_ci}
2947db96d56Sopenharmony_ci
2957db96d56Sopenharmony_ci
2967db96d56Sopenharmony_ci#define RANGE_ERROR(state, x, f, flag, mask) return _range_error(state, f, flag)
2977db96d56Sopenharmony_ci
2987db96d56Sopenharmony_ci
2997db96d56Sopenharmony_ci/* Floating point helpers */
3007db96d56Sopenharmony_ci
3017db96d56Sopenharmony_cistatic PyObject *
3027db96d56Sopenharmony_ciunpack_halffloat(const char *p,  /* start of 2-byte string */
3037db96d56Sopenharmony_ci                 int le)         /* true for little-endian, false for big-endian */
3047db96d56Sopenharmony_ci{
3057db96d56Sopenharmony_ci    double x = PyFloat_Unpack2(p, le);
3067db96d56Sopenharmony_ci    if (x == -1.0 && PyErr_Occurred()) {
3077db96d56Sopenharmony_ci        return NULL;
3087db96d56Sopenharmony_ci    }
3097db96d56Sopenharmony_ci    return PyFloat_FromDouble(x);
3107db96d56Sopenharmony_ci}
3117db96d56Sopenharmony_ci
3127db96d56Sopenharmony_cistatic int
3137db96d56Sopenharmony_cipack_halffloat(_structmodulestate *state,
3147db96d56Sopenharmony_ci               char *p,      /* start of 2-byte string */
3157db96d56Sopenharmony_ci               PyObject *v,  /* value to pack */
3167db96d56Sopenharmony_ci               int le)       /* true for little-endian, false for big-endian */
3177db96d56Sopenharmony_ci{
3187db96d56Sopenharmony_ci    double x = PyFloat_AsDouble(v);
3197db96d56Sopenharmony_ci    if (x == -1.0 && PyErr_Occurred()) {
3207db96d56Sopenharmony_ci        PyErr_SetString(state->StructError,
3217db96d56Sopenharmony_ci                        "required argument is not a float");
3227db96d56Sopenharmony_ci        return -1;
3237db96d56Sopenharmony_ci    }
3247db96d56Sopenharmony_ci    return PyFloat_Pack2(x, p, le);
3257db96d56Sopenharmony_ci}
3267db96d56Sopenharmony_ci
3277db96d56Sopenharmony_cistatic PyObject *
3287db96d56Sopenharmony_ciunpack_float(const char *p,  /* start of 4-byte string */
3297db96d56Sopenharmony_ci         int le)             /* true for little-endian, false for big-endian */
3307db96d56Sopenharmony_ci{
3317db96d56Sopenharmony_ci    double x;
3327db96d56Sopenharmony_ci
3337db96d56Sopenharmony_ci    x = PyFloat_Unpack4(p, le);
3347db96d56Sopenharmony_ci    if (x == -1.0 && PyErr_Occurred())
3357db96d56Sopenharmony_ci        return NULL;
3367db96d56Sopenharmony_ci    return PyFloat_FromDouble(x);
3377db96d56Sopenharmony_ci}
3387db96d56Sopenharmony_ci
3397db96d56Sopenharmony_cistatic PyObject *
3407db96d56Sopenharmony_ciunpack_double(const char *p,  /* start of 8-byte string */
3417db96d56Sopenharmony_ci          int le)         /* true for little-endian, false for big-endian */
3427db96d56Sopenharmony_ci{
3437db96d56Sopenharmony_ci    double x;
3447db96d56Sopenharmony_ci
3457db96d56Sopenharmony_ci    x = PyFloat_Unpack8(p, le);
3467db96d56Sopenharmony_ci    if (x == -1.0 && PyErr_Occurred())
3477db96d56Sopenharmony_ci        return NULL;
3487db96d56Sopenharmony_ci    return PyFloat_FromDouble(x);
3497db96d56Sopenharmony_ci}
3507db96d56Sopenharmony_ci
3517db96d56Sopenharmony_ci/* Helper to format the range error exceptions */
3527db96d56Sopenharmony_cistatic int
3537db96d56Sopenharmony_ci_range_error(_structmodulestate *state, const formatdef *f, int is_unsigned)
3547db96d56Sopenharmony_ci{
3557db96d56Sopenharmony_ci    /* ulargest is the largest unsigned value with f->size bytes.
3567db96d56Sopenharmony_ci     * Note that the simpler:
3577db96d56Sopenharmony_ci     *     ((size_t)1 << (f->size * 8)) - 1
3587db96d56Sopenharmony_ci     * doesn't work when f->size == sizeof(size_t) because C doesn't
3597db96d56Sopenharmony_ci     * define what happens when a left shift count is >= the number of
3607db96d56Sopenharmony_ci     * bits in the integer being shifted; e.g., on some boxes it doesn't
3617db96d56Sopenharmony_ci     * shift at all when they're equal.
3627db96d56Sopenharmony_ci     */
3637db96d56Sopenharmony_ci    const size_t ulargest = (size_t)-1 >> ((SIZEOF_SIZE_T - f->size)*8);
3647db96d56Sopenharmony_ci    assert(f->size >= 1 && f->size <= SIZEOF_SIZE_T);
3657db96d56Sopenharmony_ci    if (is_unsigned)
3667db96d56Sopenharmony_ci        PyErr_Format(state->StructError,
3677db96d56Sopenharmony_ci            "'%c' format requires 0 <= number <= %zu",
3687db96d56Sopenharmony_ci            f->format,
3697db96d56Sopenharmony_ci            ulargest);
3707db96d56Sopenharmony_ci    else {
3717db96d56Sopenharmony_ci        const Py_ssize_t largest = (Py_ssize_t)(ulargest >> 1);
3727db96d56Sopenharmony_ci        PyErr_Format(state->StructError,
3737db96d56Sopenharmony_ci            "'%c' format requires %zd <= number <= %zd",
3747db96d56Sopenharmony_ci            f->format,
3757db96d56Sopenharmony_ci            ~ largest,
3767db96d56Sopenharmony_ci            largest);
3777db96d56Sopenharmony_ci    }
3787db96d56Sopenharmony_ci
3797db96d56Sopenharmony_ci    return -1;
3807db96d56Sopenharmony_ci}
3817db96d56Sopenharmony_ci
3827db96d56Sopenharmony_ci
3837db96d56Sopenharmony_ci
3847db96d56Sopenharmony_ci/* A large number of small routines follow, with names of the form
3857db96d56Sopenharmony_ci
3867db96d56Sopenharmony_ci   [bln][up]_TYPE
3877db96d56Sopenharmony_ci
3887db96d56Sopenharmony_ci   [bln] distinguishes among big-endian, little-endian and native.
3897db96d56Sopenharmony_ci   [pu] distinguishes between pack (to struct) and unpack (from struct).
3907db96d56Sopenharmony_ci   TYPE is one of char, byte, ubyte, etc.
3917db96d56Sopenharmony_ci*/
3927db96d56Sopenharmony_ci
3937db96d56Sopenharmony_ci/* Native mode routines. ****************************************************/
3947db96d56Sopenharmony_ci/* NOTE:
3957db96d56Sopenharmony_ci   In all n[up]_<type> routines handling types larger than 1 byte, there is
3967db96d56Sopenharmony_ci   *no* guarantee that the p pointer is properly aligned for each type,
3977db96d56Sopenharmony_ci   therefore memcpy is called.  An intermediate variable is used to
3987db96d56Sopenharmony_ci   compensate for big-endian architectures.
3997db96d56Sopenharmony_ci   Normally both the intermediate variable and the memcpy call will be
4007db96d56Sopenharmony_ci   skipped by C optimisation in little-endian architectures (gcc >= 2.91
4017db96d56Sopenharmony_ci   does this). */
4027db96d56Sopenharmony_ci
4037db96d56Sopenharmony_cistatic PyObject *
4047db96d56Sopenharmony_cinu_char(_structmodulestate *state, const char *p, const formatdef *f)
4057db96d56Sopenharmony_ci{
4067db96d56Sopenharmony_ci    return PyBytes_FromStringAndSize(p, 1);
4077db96d56Sopenharmony_ci}
4087db96d56Sopenharmony_ci
4097db96d56Sopenharmony_cistatic PyObject *
4107db96d56Sopenharmony_cinu_byte(_structmodulestate *state, const char *p, const formatdef *f)
4117db96d56Sopenharmony_ci{
4127db96d56Sopenharmony_ci    return PyLong_FromLong((long) *(signed char *)p);
4137db96d56Sopenharmony_ci}
4147db96d56Sopenharmony_ci
4157db96d56Sopenharmony_cistatic PyObject *
4167db96d56Sopenharmony_cinu_ubyte(_structmodulestate *state, const char *p, const formatdef *f)
4177db96d56Sopenharmony_ci{
4187db96d56Sopenharmony_ci    return PyLong_FromLong((long) *(unsigned char *)p);
4197db96d56Sopenharmony_ci}
4207db96d56Sopenharmony_ci
4217db96d56Sopenharmony_cistatic PyObject *
4227db96d56Sopenharmony_cinu_short(_structmodulestate *state, const char *p, const formatdef *f)
4237db96d56Sopenharmony_ci{
4247db96d56Sopenharmony_ci    short x;
4257db96d56Sopenharmony_ci    memcpy((char *)&x, p, sizeof x);
4267db96d56Sopenharmony_ci    return PyLong_FromLong((long)x);
4277db96d56Sopenharmony_ci}
4287db96d56Sopenharmony_ci
4297db96d56Sopenharmony_cistatic PyObject *
4307db96d56Sopenharmony_cinu_ushort(_structmodulestate *state, const char *p, const formatdef *f)
4317db96d56Sopenharmony_ci{
4327db96d56Sopenharmony_ci    unsigned short x;
4337db96d56Sopenharmony_ci    memcpy((char *)&x, p, sizeof x);
4347db96d56Sopenharmony_ci    return PyLong_FromLong((long)x);
4357db96d56Sopenharmony_ci}
4367db96d56Sopenharmony_ci
4377db96d56Sopenharmony_cistatic PyObject *
4387db96d56Sopenharmony_cinu_int(_structmodulestate *state, const char *p, const formatdef *f)
4397db96d56Sopenharmony_ci{
4407db96d56Sopenharmony_ci    int x;
4417db96d56Sopenharmony_ci    memcpy((char *)&x, p, sizeof x);
4427db96d56Sopenharmony_ci    return PyLong_FromLong((long)x);
4437db96d56Sopenharmony_ci}
4447db96d56Sopenharmony_ci
4457db96d56Sopenharmony_cistatic PyObject *
4467db96d56Sopenharmony_cinu_uint(_structmodulestate *state, const char *p, const formatdef *f)
4477db96d56Sopenharmony_ci{
4487db96d56Sopenharmony_ci    unsigned int x;
4497db96d56Sopenharmony_ci    memcpy((char *)&x, p, sizeof x);
4507db96d56Sopenharmony_ci    return PyLong_FromUnsignedLong((unsigned long)x);
4517db96d56Sopenharmony_ci}
4527db96d56Sopenharmony_ci
4537db96d56Sopenharmony_cistatic PyObject *
4547db96d56Sopenharmony_cinu_long(_structmodulestate *state, const char *p, const formatdef *f)
4557db96d56Sopenharmony_ci{
4567db96d56Sopenharmony_ci    long x;
4577db96d56Sopenharmony_ci    memcpy((char *)&x, p, sizeof x);
4587db96d56Sopenharmony_ci    return PyLong_FromLong(x);
4597db96d56Sopenharmony_ci}
4607db96d56Sopenharmony_ci
4617db96d56Sopenharmony_cistatic PyObject *
4627db96d56Sopenharmony_cinu_ulong(_structmodulestate *state, const char *p, const formatdef *f)
4637db96d56Sopenharmony_ci{
4647db96d56Sopenharmony_ci    unsigned long x;
4657db96d56Sopenharmony_ci    memcpy((char *)&x, p, sizeof x);
4667db96d56Sopenharmony_ci    return PyLong_FromUnsignedLong(x);
4677db96d56Sopenharmony_ci}
4687db96d56Sopenharmony_ci
4697db96d56Sopenharmony_cistatic PyObject *
4707db96d56Sopenharmony_cinu_ssize_t(_structmodulestate *state, const char *p, const formatdef *f)
4717db96d56Sopenharmony_ci{
4727db96d56Sopenharmony_ci    Py_ssize_t x;
4737db96d56Sopenharmony_ci    memcpy((char *)&x, p, sizeof x);
4747db96d56Sopenharmony_ci    return PyLong_FromSsize_t(x);
4757db96d56Sopenharmony_ci}
4767db96d56Sopenharmony_ci
4777db96d56Sopenharmony_cistatic PyObject *
4787db96d56Sopenharmony_cinu_size_t(_structmodulestate *state, const char *p, const formatdef *f)
4797db96d56Sopenharmony_ci{
4807db96d56Sopenharmony_ci    size_t x;
4817db96d56Sopenharmony_ci    memcpy((char *)&x, p, sizeof x);
4827db96d56Sopenharmony_ci    return PyLong_FromSize_t(x);
4837db96d56Sopenharmony_ci}
4847db96d56Sopenharmony_ci
4857db96d56Sopenharmony_cistatic PyObject *
4867db96d56Sopenharmony_cinu_longlong(_structmodulestate *state, const char *p, const formatdef *f)
4877db96d56Sopenharmony_ci{
4887db96d56Sopenharmony_ci    long long x;
4897db96d56Sopenharmony_ci    memcpy((char *)&x, p, sizeof x);
4907db96d56Sopenharmony_ci    return PyLong_FromLongLong(x);
4917db96d56Sopenharmony_ci}
4927db96d56Sopenharmony_ci
4937db96d56Sopenharmony_cistatic PyObject *
4947db96d56Sopenharmony_cinu_ulonglong(_structmodulestate *state, const char *p, const formatdef *f)
4957db96d56Sopenharmony_ci{
4967db96d56Sopenharmony_ci    unsigned long long x;
4977db96d56Sopenharmony_ci    memcpy((char *)&x, p, sizeof x);
4987db96d56Sopenharmony_ci    return PyLong_FromUnsignedLongLong(x);
4997db96d56Sopenharmony_ci}
5007db96d56Sopenharmony_ci
5017db96d56Sopenharmony_cistatic PyObject *
5027db96d56Sopenharmony_cinu_bool(_structmodulestate *state, const char *p, const formatdef *f)
5037db96d56Sopenharmony_ci{
5047db96d56Sopenharmony_ci    _Bool x;
5057db96d56Sopenharmony_ci    memcpy((char *)&x, p, sizeof x);
5067db96d56Sopenharmony_ci    return PyBool_FromLong(x != 0);
5077db96d56Sopenharmony_ci}
5087db96d56Sopenharmony_ci
5097db96d56Sopenharmony_ci
5107db96d56Sopenharmony_cistatic PyObject *
5117db96d56Sopenharmony_cinu_halffloat(_structmodulestate *state, const char *p, const formatdef *f)
5127db96d56Sopenharmony_ci{
5137db96d56Sopenharmony_ci#if PY_LITTLE_ENDIAN
5147db96d56Sopenharmony_ci    return unpack_halffloat(p, 1);
5157db96d56Sopenharmony_ci#else
5167db96d56Sopenharmony_ci    return unpack_halffloat(p, 0);
5177db96d56Sopenharmony_ci#endif
5187db96d56Sopenharmony_ci}
5197db96d56Sopenharmony_ci
5207db96d56Sopenharmony_cistatic PyObject *
5217db96d56Sopenharmony_cinu_float(_structmodulestate *state, const char *p, const formatdef *f)
5227db96d56Sopenharmony_ci{
5237db96d56Sopenharmony_ci    float x;
5247db96d56Sopenharmony_ci    memcpy((char *)&x, p, sizeof x);
5257db96d56Sopenharmony_ci    return PyFloat_FromDouble((double)x);
5267db96d56Sopenharmony_ci}
5277db96d56Sopenharmony_ci
5287db96d56Sopenharmony_cistatic PyObject *
5297db96d56Sopenharmony_cinu_double(_structmodulestate *state, const char *p, const formatdef *f)
5307db96d56Sopenharmony_ci{
5317db96d56Sopenharmony_ci    double x;
5327db96d56Sopenharmony_ci    memcpy((char *)&x, p, sizeof x);
5337db96d56Sopenharmony_ci    return PyFloat_FromDouble(x);
5347db96d56Sopenharmony_ci}
5357db96d56Sopenharmony_ci
5367db96d56Sopenharmony_cistatic PyObject *
5377db96d56Sopenharmony_cinu_void_p(_structmodulestate *state, const char *p, const formatdef *f)
5387db96d56Sopenharmony_ci{
5397db96d56Sopenharmony_ci    void *x;
5407db96d56Sopenharmony_ci    memcpy((char *)&x, p, sizeof x);
5417db96d56Sopenharmony_ci    return PyLong_FromVoidPtr(x);
5427db96d56Sopenharmony_ci}
5437db96d56Sopenharmony_ci
5447db96d56Sopenharmony_cistatic int
5457db96d56Sopenharmony_cinp_byte(_structmodulestate *state, char *p, PyObject *v, const formatdef *f)
5467db96d56Sopenharmony_ci{
5477db96d56Sopenharmony_ci    long x;
5487db96d56Sopenharmony_ci    if (get_long(state, v, &x) < 0)
5497db96d56Sopenharmony_ci        return -1;
5507db96d56Sopenharmony_ci    if (x < -128 || x > 127) {
5517db96d56Sopenharmony_ci        PyErr_SetString(state->StructError,
5527db96d56Sopenharmony_ci                        "byte format requires -128 <= number <= 127");
5537db96d56Sopenharmony_ci        return -1;
5547db96d56Sopenharmony_ci    }
5557db96d56Sopenharmony_ci    *p = (char)x;
5567db96d56Sopenharmony_ci    return 0;
5577db96d56Sopenharmony_ci}
5587db96d56Sopenharmony_ci
5597db96d56Sopenharmony_cistatic int
5607db96d56Sopenharmony_cinp_ubyte(_structmodulestate *state, char *p, PyObject *v, const formatdef *f)
5617db96d56Sopenharmony_ci{
5627db96d56Sopenharmony_ci    long x;
5637db96d56Sopenharmony_ci    if (get_long(state, v, &x) < 0)
5647db96d56Sopenharmony_ci        return -1;
5657db96d56Sopenharmony_ci    if (x < 0 || x > 255) {
5667db96d56Sopenharmony_ci        PyErr_SetString(state->StructError,
5677db96d56Sopenharmony_ci                        "ubyte format requires 0 <= number <= 255");
5687db96d56Sopenharmony_ci        return -1;
5697db96d56Sopenharmony_ci    }
5707db96d56Sopenharmony_ci    *(unsigned char *)p = (unsigned char)x;
5717db96d56Sopenharmony_ci    return 0;
5727db96d56Sopenharmony_ci}
5737db96d56Sopenharmony_ci
5747db96d56Sopenharmony_cistatic int
5757db96d56Sopenharmony_cinp_char(_structmodulestate *state, char *p, PyObject *v, const formatdef *f)
5767db96d56Sopenharmony_ci{
5777db96d56Sopenharmony_ci    if (!PyBytes_Check(v) || PyBytes_Size(v) != 1) {
5787db96d56Sopenharmony_ci        PyErr_SetString(state->StructError,
5797db96d56Sopenharmony_ci                        "char format requires a bytes object of length 1");
5807db96d56Sopenharmony_ci        return -1;
5817db96d56Sopenharmony_ci    }
5827db96d56Sopenharmony_ci    *p = *PyBytes_AS_STRING(v);
5837db96d56Sopenharmony_ci    return 0;
5847db96d56Sopenharmony_ci}
5857db96d56Sopenharmony_ci
5867db96d56Sopenharmony_cistatic int
5877db96d56Sopenharmony_cinp_short(_structmodulestate *state, char *p, PyObject *v, const formatdef *f)
5887db96d56Sopenharmony_ci{
5897db96d56Sopenharmony_ci    long x;
5907db96d56Sopenharmony_ci    short y;
5917db96d56Sopenharmony_ci    if (get_long(state, v, &x) < 0)
5927db96d56Sopenharmony_ci        return -1;
5937db96d56Sopenharmony_ci    if (x < SHRT_MIN || x > SHRT_MAX) {
5947db96d56Sopenharmony_ci        PyErr_Format(state->StructError,
5957db96d56Sopenharmony_ci                     "short format requires %d <= number <= %d",
5967db96d56Sopenharmony_ci                     (int)SHRT_MIN, (int)SHRT_MAX);
5977db96d56Sopenharmony_ci        return -1;
5987db96d56Sopenharmony_ci    }
5997db96d56Sopenharmony_ci    y = (short)x;
6007db96d56Sopenharmony_ci    memcpy(p, (char *)&y, sizeof y);
6017db96d56Sopenharmony_ci    return 0;
6027db96d56Sopenharmony_ci}
6037db96d56Sopenharmony_ci
6047db96d56Sopenharmony_cistatic int
6057db96d56Sopenharmony_cinp_ushort(_structmodulestate *state, char *p, PyObject *v, const formatdef *f)
6067db96d56Sopenharmony_ci{
6077db96d56Sopenharmony_ci    long x;
6087db96d56Sopenharmony_ci    unsigned short y;
6097db96d56Sopenharmony_ci    if (get_long(state, v, &x) < 0)
6107db96d56Sopenharmony_ci        return -1;
6117db96d56Sopenharmony_ci    if (x < 0 || x > USHRT_MAX) {
6127db96d56Sopenharmony_ci        PyErr_Format(state->StructError,
6137db96d56Sopenharmony_ci                     "ushort format requires 0 <= number <= %u",
6147db96d56Sopenharmony_ci                     (unsigned int)USHRT_MAX);
6157db96d56Sopenharmony_ci        return -1;
6167db96d56Sopenharmony_ci    }
6177db96d56Sopenharmony_ci    y = (unsigned short)x;
6187db96d56Sopenharmony_ci    memcpy(p, (char *)&y, sizeof y);
6197db96d56Sopenharmony_ci    return 0;
6207db96d56Sopenharmony_ci}
6217db96d56Sopenharmony_ci
6227db96d56Sopenharmony_cistatic int
6237db96d56Sopenharmony_cinp_int(_structmodulestate *state, char *p, PyObject *v, const formatdef *f)
6247db96d56Sopenharmony_ci{
6257db96d56Sopenharmony_ci    long x;
6267db96d56Sopenharmony_ci    int y;
6277db96d56Sopenharmony_ci    if (get_long(state, v, &x) < 0)
6287db96d56Sopenharmony_ci        return -1;
6297db96d56Sopenharmony_ci#if (SIZEOF_LONG > SIZEOF_INT)
6307db96d56Sopenharmony_ci    if ((x < ((long)INT_MIN)) || (x > ((long)INT_MAX)))
6317db96d56Sopenharmony_ci        RANGE_ERROR(state, x, f, 0, -1);
6327db96d56Sopenharmony_ci#endif
6337db96d56Sopenharmony_ci    y = (int)x;
6347db96d56Sopenharmony_ci    memcpy(p, (char *)&y, sizeof y);
6357db96d56Sopenharmony_ci    return 0;
6367db96d56Sopenharmony_ci}
6377db96d56Sopenharmony_ci
6387db96d56Sopenharmony_cistatic int
6397db96d56Sopenharmony_cinp_uint(_structmodulestate *state, char *p, PyObject *v, const formatdef *f)
6407db96d56Sopenharmony_ci{
6417db96d56Sopenharmony_ci    unsigned long x;
6427db96d56Sopenharmony_ci    unsigned int y;
6437db96d56Sopenharmony_ci    if (get_ulong(state, v, &x) < 0)
6447db96d56Sopenharmony_ci        return -1;
6457db96d56Sopenharmony_ci    y = (unsigned int)x;
6467db96d56Sopenharmony_ci#if (SIZEOF_LONG > SIZEOF_INT)
6477db96d56Sopenharmony_ci    if (x > ((unsigned long)UINT_MAX))
6487db96d56Sopenharmony_ci        RANGE_ERROR(state, y, f, 1, -1);
6497db96d56Sopenharmony_ci#endif
6507db96d56Sopenharmony_ci    memcpy(p, (char *)&y, sizeof y);
6517db96d56Sopenharmony_ci    return 0;
6527db96d56Sopenharmony_ci}
6537db96d56Sopenharmony_ci
6547db96d56Sopenharmony_cistatic int
6557db96d56Sopenharmony_cinp_long(_structmodulestate *state, char *p, PyObject *v, const formatdef *f)
6567db96d56Sopenharmony_ci{
6577db96d56Sopenharmony_ci    long x;
6587db96d56Sopenharmony_ci    if (get_long(state, v, &x) < 0)
6597db96d56Sopenharmony_ci        return -1;
6607db96d56Sopenharmony_ci    memcpy(p, (char *)&x, sizeof x);
6617db96d56Sopenharmony_ci    return 0;
6627db96d56Sopenharmony_ci}
6637db96d56Sopenharmony_ci
6647db96d56Sopenharmony_cistatic int
6657db96d56Sopenharmony_cinp_ulong(_structmodulestate *state, char *p, PyObject *v, const formatdef *f)
6667db96d56Sopenharmony_ci{
6677db96d56Sopenharmony_ci    unsigned long x;
6687db96d56Sopenharmony_ci    if (get_ulong(state, v, &x) < 0)
6697db96d56Sopenharmony_ci        return -1;
6707db96d56Sopenharmony_ci    memcpy(p, (char *)&x, sizeof x);
6717db96d56Sopenharmony_ci    return 0;
6727db96d56Sopenharmony_ci}
6737db96d56Sopenharmony_ci
6747db96d56Sopenharmony_cistatic int
6757db96d56Sopenharmony_cinp_ssize_t(_structmodulestate *state, char *p, PyObject *v, const formatdef *f)
6767db96d56Sopenharmony_ci{
6777db96d56Sopenharmony_ci    Py_ssize_t x;
6787db96d56Sopenharmony_ci    if (get_ssize_t(state, v, &x) < 0)
6797db96d56Sopenharmony_ci        return -1;
6807db96d56Sopenharmony_ci    memcpy(p, (char *)&x, sizeof x);
6817db96d56Sopenharmony_ci    return 0;
6827db96d56Sopenharmony_ci}
6837db96d56Sopenharmony_ci
6847db96d56Sopenharmony_cistatic int
6857db96d56Sopenharmony_cinp_size_t(_structmodulestate *state, char *p, PyObject *v, const formatdef *f)
6867db96d56Sopenharmony_ci{
6877db96d56Sopenharmony_ci    size_t x;
6887db96d56Sopenharmony_ci    if (get_size_t(state, v, &x) < 0)
6897db96d56Sopenharmony_ci        return -1;
6907db96d56Sopenharmony_ci    memcpy(p, (char *)&x, sizeof x);
6917db96d56Sopenharmony_ci    return 0;
6927db96d56Sopenharmony_ci}
6937db96d56Sopenharmony_ci
6947db96d56Sopenharmony_cistatic int
6957db96d56Sopenharmony_cinp_longlong(_structmodulestate *state, char *p, PyObject *v, const formatdef *f)
6967db96d56Sopenharmony_ci{
6977db96d56Sopenharmony_ci    long long x;
6987db96d56Sopenharmony_ci    if (get_longlong(state, v, &x) < 0)
6997db96d56Sopenharmony_ci        return -1;
7007db96d56Sopenharmony_ci    memcpy(p, (char *)&x, sizeof x);
7017db96d56Sopenharmony_ci    return 0;
7027db96d56Sopenharmony_ci}
7037db96d56Sopenharmony_ci
7047db96d56Sopenharmony_cistatic int
7057db96d56Sopenharmony_cinp_ulonglong(_structmodulestate *state, char *p, PyObject *v, const formatdef *f)
7067db96d56Sopenharmony_ci{
7077db96d56Sopenharmony_ci    unsigned long long x;
7087db96d56Sopenharmony_ci    if (get_ulonglong(state, v, &x) < 0)
7097db96d56Sopenharmony_ci        return -1;
7107db96d56Sopenharmony_ci    memcpy(p, (char *)&x, sizeof x);
7117db96d56Sopenharmony_ci    return 0;
7127db96d56Sopenharmony_ci}
7137db96d56Sopenharmony_ci
7147db96d56Sopenharmony_ci
7157db96d56Sopenharmony_cistatic int
7167db96d56Sopenharmony_cinp_bool(_structmodulestate *state, char *p, PyObject *v, const formatdef *f)
7177db96d56Sopenharmony_ci{
7187db96d56Sopenharmony_ci    int y;
7197db96d56Sopenharmony_ci    _Bool x;
7207db96d56Sopenharmony_ci    y = PyObject_IsTrue(v);
7217db96d56Sopenharmony_ci    if (y < 0)
7227db96d56Sopenharmony_ci        return -1;
7237db96d56Sopenharmony_ci    x = y;
7247db96d56Sopenharmony_ci    memcpy(p, (char *)&x, sizeof x);
7257db96d56Sopenharmony_ci    return 0;
7267db96d56Sopenharmony_ci}
7277db96d56Sopenharmony_ci
7287db96d56Sopenharmony_cistatic int
7297db96d56Sopenharmony_cinp_halffloat(_structmodulestate *state, char *p, PyObject *v, const formatdef *f)
7307db96d56Sopenharmony_ci{
7317db96d56Sopenharmony_ci#if PY_LITTLE_ENDIAN
7327db96d56Sopenharmony_ci    return pack_halffloat(state, p, v, 1);
7337db96d56Sopenharmony_ci#else
7347db96d56Sopenharmony_ci    return pack_halffloat(state, p, v, 0);
7357db96d56Sopenharmony_ci#endif
7367db96d56Sopenharmony_ci}
7377db96d56Sopenharmony_ci
7387db96d56Sopenharmony_cistatic int
7397db96d56Sopenharmony_cinp_float(_structmodulestate *state, char *p, PyObject *v, const formatdef *f)
7407db96d56Sopenharmony_ci{
7417db96d56Sopenharmony_ci    float x = (float)PyFloat_AsDouble(v);
7427db96d56Sopenharmony_ci    if (x == -1 && PyErr_Occurred()) {
7437db96d56Sopenharmony_ci        PyErr_SetString(state->StructError,
7447db96d56Sopenharmony_ci                        "required argument is not a float");
7457db96d56Sopenharmony_ci        return -1;
7467db96d56Sopenharmony_ci    }
7477db96d56Sopenharmony_ci    memcpy(p, (char *)&x, sizeof x);
7487db96d56Sopenharmony_ci    return 0;
7497db96d56Sopenharmony_ci}
7507db96d56Sopenharmony_ci
7517db96d56Sopenharmony_cistatic int
7527db96d56Sopenharmony_cinp_double(_structmodulestate *state, char *p, PyObject *v, const formatdef *f)
7537db96d56Sopenharmony_ci{
7547db96d56Sopenharmony_ci    double x = PyFloat_AsDouble(v);
7557db96d56Sopenharmony_ci    if (x == -1 && PyErr_Occurred()) {
7567db96d56Sopenharmony_ci        PyErr_SetString(state->StructError,
7577db96d56Sopenharmony_ci                        "required argument is not a float");
7587db96d56Sopenharmony_ci        return -1;
7597db96d56Sopenharmony_ci    }
7607db96d56Sopenharmony_ci    memcpy(p, (char *)&x, sizeof(double));
7617db96d56Sopenharmony_ci    return 0;
7627db96d56Sopenharmony_ci}
7637db96d56Sopenharmony_ci
7647db96d56Sopenharmony_cistatic int
7657db96d56Sopenharmony_cinp_void_p(_structmodulestate *state, char *p, PyObject *v, const formatdef *f)
7667db96d56Sopenharmony_ci{
7677db96d56Sopenharmony_ci    void *x;
7687db96d56Sopenharmony_ci
7697db96d56Sopenharmony_ci    v = get_pylong(state, v);
7707db96d56Sopenharmony_ci    if (v == NULL)
7717db96d56Sopenharmony_ci        return -1;
7727db96d56Sopenharmony_ci    assert(PyLong_Check(v));
7737db96d56Sopenharmony_ci    x = PyLong_AsVoidPtr(v);
7747db96d56Sopenharmony_ci    Py_DECREF(v);
7757db96d56Sopenharmony_ci    if (x == NULL && PyErr_Occurred())
7767db96d56Sopenharmony_ci        return -1;
7777db96d56Sopenharmony_ci    memcpy(p, (char *)&x, sizeof x);
7787db96d56Sopenharmony_ci    return 0;
7797db96d56Sopenharmony_ci}
7807db96d56Sopenharmony_ci
7817db96d56Sopenharmony_cistatic const formatdef native_table[] = {
7827db96d56Sopenharmony_ci    {'x',       sizeof(char),   0,              NULL},
7837db96d56Sopenharmony_ci    {'b',       sizeof(char),   0,              nu_byte,        np_byte},
7847db96d56Sopenharmony_ci    {'B',       sizeof(char),   0,              nu_ubyte,       np_ubyte},
7857db96d56Sopenharmony_ci    {'c',       sizeof(char),   0,              nu_char,        np_char},
7867db96d56Sopenharmony_ci    {'s',       sizeof(char),   0,              NULL},
7877db96d56Sopenharmony_ci    {'p',       sizeof(char),   0,              NULL},
7887db96d56Sopenharmony_ci    {'h',       sizeof(short),  SHORT_ALIGN,    nu_short,       np_short},
7897db96d56Sopenharmony_ci    {'H',       sizeof(short),  SHORT_ALIGN,    nu_ushort,      np_ushort},
7907db96d56Sopenharmony_ci    {'i',       sizeof(int),    INT_ALIGN,      nu_int,         np_int},
7917db96d56Sopenharmony_ci    {'I',       sizeof(int),    INT_ALIGN,      nu_uint,        np_uint},
7927db96d56Sopenharmony_ci    {'l',       sizeof(long),   LONG_ALIGN,     nu_long,        np_long},
7937db96d56Sopenharmony_ci    {'L',       sizeof(long),   LONG_ALIGN,     nu_ulong,       np_ulong},
7947db96d56Sopenharmony_ci    {'n',       sizeof(size_t), SIZE_T_ALIGN,   nu_ssize_t,     np_ssize_t},
7957db96d56Sopenharmony_ci    {'N',       sizeof(size_t), SIZE_T_ALIGN,   nu_size_t,      np_size_t},
7967db96d56Sopenharmony_ci    {'q',       sizeof(long long), LONG_LONG_ALIGN, nu_longlong, np_longlong},
7977db96d56Sopenharmony_ci    {'Q',       sizeof(long long), LONG_LONG_ALIGN, nu_ulonglong,np_ulonglong},
7987db96d56Sopenharmony_ci    {'?',       sizeof(_Bool),      BOOL_ALIGN,     nu_bool,        np_bool},
7997db96d56Sopenharmony_ci    {'e',       sizeof(short),  SHORT_ALIGN,    nu_halffloat,   np_halffloat},
8007db96d56Sopenharmony_ci    {'f',       sizeof(float),  FLOAT_ALIGN,    nu_float,       np_float},
8017db96d56Sopenharmony_ci    {'d',       sizeof(double), DOUBLE_ALIGN,   nu_double,      np_double},
8027db96d56Sopenharmony_ci    {'P',       sizeof(void *), VOID_P_ALIGN,   nu_void_p,      np_void_p},
8037db96d56Sopenharmony_ci    {0}
8047db96d56Sopenharmony_ci};
8057db96d56Sopenharmony_ci
8067db96d56Sopenharmony_ci/* Big-endian routines. *****************************************************/
8077db96d56Sopenharmony_ci
8087db96d56Sopenharmony_cistatic PyObject *
8097db96d56Sopenharmony_cibu_int(_structmodulestate *state, const char *p, const formatdef *f)
8107db96d56Sopenharmony_ci{
8117db96d56Sopenharmony_ci    long x = 0;
8127db96d56Sopenharmony_ci    Py_ssize_t i = f->size;
8137db96d56Sopenharmony_ci    const unsigned char *bytes = (const unsigned char *)p;
8147db96d56Sopenharmony_ci    do {
8157db96d56Sopenharmony_ci        x = (x<<8) | *bytes++;
8167db96d56Sopenharmony_ci    } while (--i > 0);
8177db96d56Sopenharmony_ci    /* Extend the sign bit. */
8187db96d56Sopenharmony_ci    if (SIZEOF_LONG > f->size)
8197db96d56Sopenharmony_ci        x |= -(x & (1L << ((8 * f->size) - 1)));
8207db96d56Sopenharmony_ci    return PyLong_FromLong(x);
8217db96d56Sopenharmony_ci}
8227db96d56Sopenharmony_ci
8237db96d56Sopenharmony_cistatic PyObject *
8247db96d56Sopenharmony_cibu_uint(_structmodulestate *state, const char *p, const formatdef *f)
8257db96d56Sopenharmony_ci{
8267db96d56Sopenharmony_ci    unsigned long x = 0;
8277db96d56Sopenharmony_ci    Py_ssize_t i = f->size;
8287db96d56Sopenharmony_ci    const unsigned char *bytes = (const unsigned char *)p;
8297db96d56Sopenharmony_ci    do {
8307db96d56Sopenharmony_ci        x = (x<<8) | *bytes++;
8317db96d56Sopenharmony_ci    } while (--i > 0);
8327db96d56Sopenharmony_ci    return PyLong_FromUnsignedLong(x);
8337db96d56Sopenharmony_ci}
8347db96d56Sopenharmony_ci
8357db96d56Sopenharmony_cistatic PyObject *
8367db96d56Sopenharmony_cibu_longlong(_structmodulestate *state, const char *p, const formatdef *f)
8377db96d56Sopenharmony_ci{
8387db96d56Sopenharmony_ci    long long x = 0;
8397db96d56Sopenharmony_ci    Py_ssize_t i = f->size;
8407db96d56Sopenharmony_ci    const unsigned char *bytes = (const unsigned char *)p;
8417db96d56Sopenharmony_ci    do {
8427db96d56Sopenharmony_ci        x = (x<<8) | *bytes++;
8437db96d56Sopenharmony_ci    } while (--i > 0);
8447db96d56Sopenharmony_ci    /* Extend the sign bit. */
8457db96d56Sopenharmony_ci    if (SIZEOF_LONG_LONG > f->size)
8467db96d56Sopenharmony_ci        x |= -(x & ((long long)1 << ((8 * f->size) - 1)));
8477db96d56Sopenharmony_ci    return PyLong_FromLongLong(x);
8487db96d56Sopenharmony_ci}
8497db96d56Sopenharmony_ci
8507db96d56Sopenharmony_cistatic PyObject *
8517db96d56Sopenharmony_cibu_ulonglong(_structmodulestate *state, const char *p, const formatdef *f)
8527db96d56Sopenharmony_ci{
8537db96d56Sopenharmony_ci    unsigned long long x = 0;
8547db96d56Sopenharmony_ci    Py_ssize_t i = f->size;
8557db96d56Sopenharmony_ci    const unsigned char *bytes = (const unsigned char *)p;
8567db96d56Sopenharmony_ci    do {
8577db96d56Sopenharmony_ci        x = (x<<8) | *bytes++;
8587db96d56Sopenharmony_ci    } while (--i > 0);
8597db96d56Sopenharmony_ci    return PyLong_FromUnsignedLongLong(x);
8607db96d56Sopenharmony_ci}
8617db96d56Sopenharmony_ci
8627db96d56Sopenharmony_cistatic PyObject *
8637db96d56Sopenharmony_cibu_halffloat(_structmodulestate *state, const char *p, const formatdef *f)
8647db96d56Sopenharmony_ci{
8657db96d56Sopenharmony_ci    return unpack_halffloat(p, 0);
8667db96d56Sopenharmony_ci}
8677db96d56Sopenharmony_ci
8687db96d56Sopenharmony_cistatic PyObject *
8697db96d56Sopenharmony_cibu_float(_structmodulestate *state, const char *p, const formatdef *f)
8707db96d56Sopenharmony_ci{
8717db96d56Sopenharmony_ci    return unpack_float(p, 0);
8727db96d56Sopenharmony_ci}
8737db96d56Sopenharmony_ci
8747db96d56Sopenharmony_cistatic PyObject *
8757db96d56Sopenharmony_cibu_double(_structmodulestate *state, const char *p, const formatdef *f)
8767db96d56Sopenharmony_ci{
8777db96d56Sopenharmony_ci    return unpack_double(p, 0);
8787db96d56Sopenharmony_ci}
8797db96d56Sopenharmony_ci
8807db96d56Sopenharmony_cistatic PyObject *
8817db96d56Sopenharmony_cibu_bool(_structmodulestate *state, const char *p, const formatdef *f)
8827db96d56Sopenharmony_ci{
8837db96d56Sopenharmony_ci    return PyBool_FromLong(*p != 0);
8847db96d56Sopenharmony_ci}
8857db96d56Sopenharmony_ci
8867db96d56Sopenharmony_cistatic int
8877db96d56Sopenharmony_cibp_int(_structmodulestate *state, char *p, PyObject *v, const formatdef *f)
8887db96d56Sopenharmony_ci{
8897db96d56Sopenharmony_ci    long x;
8907db96d56Sopenharmony_ci    Py_ssize_t i;
8917db96d56Sopenharmony_ci    unsigned char *q = (unsigned char *)p;
8927db96d56Sopenharmony_ci    if (get_long(state, v, &x) < 0)
8937db96d56Sopenharmony_ci        return -1;
8947db96d56Sopenharmony_ci    i = f->size;
8957db96d56Sopenharmony_ci    if (i != SIZEOF_LONG) {
8967db96d56Sopenharmony_ci        if ((i == 2) && (x < -32768 || x > 32767))
8977db96d56Sopenharmony_ci            RANGE_ERROR(state, x, f, 0, 0xffffL);
8987db96d56Sopenharmony_ci#if (SIZEOF_LONG != 4)
8997db96d56Sopenharmony_ci        else if ((i == 4) && (x < -2147483648L || x > 2147483647L))
9007db96d56Sopenharmony_ci            RANGE_ERROR(state, x, f, 0, 0xffffffffL);
9017db96d56Sopenharmony_ci#endif
9027db96d56Sopenharmony_ci    }
9037db96d56Sopenharmony_ci    do {
9047db96d56Sopenharmony_ci        q[--i] = (unsigned char)(x & 0xffL);
9057db96d56Sopenharmony_ci        x >>= 8;
9067db96d56Sopenharmony_ci    } while (i > 0);
9077db96d56Sopenharmony_ci    return 0;
9087db96d56Sopenharmony_ci}
9097db96d56Sopenharmony_ci
9107db96d56Sopenharmony_cistatic int
9117db96d56Sopenharmony_cibp_uint(_structmodulestate *state, char *p, PyObject *v, const formatdef *f)
9127db96d56Sopenharmony_ci{
9137db96d56Sopenharmony_ci    unsigned long x;
9147db96d56Sopenharmony_ci    Py_ssize_t i;
9157db96d56Sopenharmony_ci    unsigned char *q = (unsigned char *)p;
9167db96d56Sopenharmony_ci    if (get_ulong(state, v, &x) < 0)
9177db96d56Sopenharmony_ci        return -1;
9187db96d56Sopenharmony_ci    i = f->size;
9197db96d56Sopenharmony_ci    if (i != SIZEOF_LONG) {
9207db96d56Sopenharmony_ci        unsigned long maxint = 1;
9217db96d56Sopenharmony_ci        maxint <<= (unsigned long)(i * 8);
9227db96d56Sopenharmony_ci        if (x >= maxint)
9237db96d56Sopenharmony_ci            RANGE_ERROR(state, x, f, 1, maxint - 1);
9247db96d56Sopenharmony_ci    }
9257db96d56Sopenharmony_ci    do {
9267db96d56Sopenharmony_ci        q[--i] = (unsigned char)(x & 0xffUL);
9277db96d56Sopenharmony_ci        x >>= 8;
9287db96d56Sopenharmony_ci    } while (i > 0);
9297db96d56Sopenharmony_ci    return 0;
9307db96d56Sopenharmony_ci}
9317db96d56Sopenharmony_ci
9327db96d56Sopenharmony_cistatic int
9337db96d56Sopenharmony_cibp_longlong(_structmodulestate *state, char *p, PyObject *v, const formatdef *f)
9347db96d56Sopenharmony_ci{
9357db96d56Sopenharmony_ci    int res;
9367db96d56Sopenharmony_ci    v = get_pylong(state, v);
9377db96d56Sopenharmony_ci    if (v == NULL)
9387db96d56Sopenharmony_ci        return -1;
9397db96d56Sopenharmony_ci    res = _PyLong_AsByteArray((PyLongObject *)v,
9407db96d56Sopenharmony_ci                              (unsigned char *)p,
9417db96d56Sopenharmony_ci                              8,
9427db96d56Sopenharmony_ci                              0, /* little_endian */
9437db96d56Sopenharmony_ci                              1  /* signed */);
9447db96d56Sopenharmony_ci    Py_DECREF(v);
9457db96d56Sopenharmony_ci    return res;
9467db96d56Sopenharmony_ci}
9477db96d56Sopenharmony_ci
9487db96d56Sopenharmony_cistatic int
9497db96d56Sopenharmony_cibp_ulonglong(_structmodulestate *state, char *p, PyObject *v, const formatdef *f)
9507db96d56Sopenharmony_ci{
9517db96d56Sopenharmony_ci    int res;
9527db96d56Sopenharmony_ci    v = get_pylong(state, v);
9537db96d56Sopenharmony_ci    if (v == NULL)
9547db96d56Sopenharmony_ci        return -1;
9557db96d56Sopenharmony_ci    res = _PyLong_AsByteArray((PyLongObject *)v,
9567db96d56Sopenharmony_ci                              (unsigned char *)p,
9577db96d56Sopenharmony_ci                              8,
9587db96d56Sopenharmony_ci                              0, /* little_endian */
9597db96d56Sopenharmony_ci                              0  /* signed */);
9607db96d56Sopenharmony_ci    Py_DECREF(v);
9617db96d56Sopenharmony_ci    return res;
9627db96d56Sopenharmony_ci}
9637db96d56Sopenharmony_ci
9647db96d56Sopenharmony_cistatic int
9657db96d56Sopenharmony_cibp_halffloat(_structmodulestate *state, char *p, PyObject *v, const formatdef *f)
9667db96d56Sopenharmony_ci{
9677db96d56Sopenharmony_ci    return pack_halffloat(state, p, v, 0);
9687db96d56Sopenharmony_ci}
9697db96d56Sopenharmony_ci
9707db96d56Sopenharmony_cistatic int
9717db96d56Sopenharmony_cibp_float(_structmodulestate *state, char *p, PyObject *v, const formatdef *f)
9727db96d56Sopenharmony_ci{
9737db96d56Sopenharmony_ci    double x = PyFloat_AsDouble(v);
9747db96d56Sopenharmony_ci    if (x == -1 && PyErr_Occurred()) {
9757db96d56Sopenharmony_ci        PyErr_SetString(state->StructError,
9767db96d56Sopenharmony_ci                        "required argument is not a float");
9777db96d56Sopenharmony_ci        return -1;
9787db96d56Sopenharmony_ci    }
9797db96d56Sopenharmony_ci    return PyFloat_Pack4(x, p, 0);
9807db96d56Sopenharmony_ci}
9817db96d56Sopenharmony_ci
9827db96d56Sopenharmony_cistatic int
9837db96d56Sopenharmony_cibp_double(_structmodulestate *state, char *p, PyObject *v, const formatdef *f)
9847db96d56Sopenharmony_ci{
9857db96d56Sopenharmony_ci    double x = PyFloat_AsDouble(v);
9867db96d56Sopenharmony_ci    if (x == -1 && PyErr_Occurred()) {
9877db96d56Sopenharmony_ci        PyErr_SetString(state->StructError,
9887db96d56Sopenharmony_ci                        "required argument is not a float");
9897db96d56Sopenharmony_ci        return -1;
9907db96d56Sopenharmony_ci    }
9917db96d56Sopenharmony_ci    return PyFloat_Pack8(x, p, 0);
9927db96d56Sopenharmony_ci}
9937db96d56Sopenharmony_ci
9947db96d56Sopenharmony_cistatic int
9957db96d56Sopenharmony_cibp_bool(_structmodulestate *state, char *p, PyObject *v, const formatdef *f)
9967db96d56Sopenharmony_ci{
9977db96d56Sopenharmony_ci    int y;
9987db96d56Sopenharmony_ci    y = PyObject_IsTrue(v);
9997db96d56Sopenharmony_ci    if (y < 0)
10007db96d56Sopenharmony_ci        return -1;
10017db96d56Sopenharmony_ci    *p = (char)y;
10027db96d56Sopenharmony_ci    return 0;
10037db96d56Sopenharmony_ci}
10047db96d56Sopenharmony_ci
10057db96d56Sopenharmony_cistatic formatdef bigendian_table[] = {
10067db96d56Sopenharmony_ci    {'x',       1,              0,              NULL},
10077db96d56Sopenharmony_ci    {'b',       1,              0,              nu_byte,        np_byte},
10087db96d56Sopenharmony_ci    {'B',       1,              0,              nu_ubyte,       np_ubyte},
10097db96d56Sopenharmony_ci    {'c',       1,              0,              nu_char,        np_char},
10107db96d56Sopenharmony_ci    {'s',       1,              0,              NULL},
10117db96d56Sopenharmony_ci    {'p',       1,              0,              NULL},
10127db96d56Sopenharmony_ci    {'h',       2,              0,              bu_int,         bp_int},
10137db96d56Sopenharmony_ci    {'H',       2,              0,              bu_uint,        bp_uint},
10147db96d56Sopenharmony_ci    {'i',       4,              0,              bu_int,         bp_int},
10157db96d56Sopenharmony_ci    {'I',       4,              0,              bu_uint,        bp_uint},
10167db96d56Sopenharmony_ci    {'l',       4,              0,              bu_int,         bp_int},
10177db96d56Sopenharmony_ci    {'L',       4,              0,              bu_uint,        bp_uint},
10187db96d56Sopenharmony_ci    {'q',       8,              0,              bu_longlong,    bp_longlong},
10197db96d56Sopenharmony_ci    {'Q',       8,              0,              bu_ulonglong,   bp_ulonglong},
10207db96d56Sopenharmony_ci    {'?',       1,              0,              bu_bool,        bp_bool},
10217db96d56Sopenharmony_ci    {'e',       2,              0,              bu_halffloat,   bp_halffloat},
10227db96d56Sopenharmony_ci    {'f',       4,              0,              bu_float,       bp_float},
10237db96d56Sopenharmony_ci    {'d',       8,              0,              bu_double,      bp_double},
10247db96d56Sopenharmony_ci    {0}
10257db96d56Sopenharmony_ci};
10267db96d56Sopenharmony_ci
10277db96d56Sopenharmony_ci/* Little-endian routines. *****************************************************/
10287db96d56Sopenharmony_ci
10297db96d56Sopenharmony_cistatic PyObject *
10307db96d56Sopenharmony_cilu_int(_structmodulestate *state, const char *p, const formatdef *f)
10317db96d56Sopenharmony_ci{
10327db96d56Sopenharmony_ci    long x = 0;
10337db96d56Sopenharmony_ci    Py_ssize_t i = f->size;
10347db96d56Sopenharmony_ci    const unsigned char *bytes = (const unsigned char *)p;
10357db96d56Sopenharmony_ci    do {
10367db96d56Sopenharmony_ci        x = (x<<8) | bytes[--i];
10377db96d56Sopenharmony_ci    } while (i > 0);
10387db96d56Sopenharmony_ci    /* Extend the sign bit. */
10397db96d56Sopenharmony_ci    if (SIZEOF_LONG > f->size)
10407db96d56Sopenharmony_ci        x |= -(x & (1L << ((8 * f->size) - 1)));
10417db96d56Sopenharmony_ci    return PyLong_FromLong(x);
10427db96d56Sopenharmony_ci}
10437db96d56Sopenharmony_ci
10447db96d56Sopenharmony_cistatic PyObject *
10457db96d56Sopenharmony_cilu_uint(_structmodulestate *state, const char *p, const formatdef *f)
10467db96d56Sopenharmony_ci{
10477db96d56Sopenharmony_ci    unsigned long x = 0;
10487db96d56Sopenharmony_ci    Py_ssize_t i = f->size;
10497db96d56Sopenharmony_ci    const unsigned char *bytes = (const unsigned char *)p;
10507db96d56Sopenharmony_ci    do {
10517db96d56Sopenharmony_ci        x = (x<<8) | bytes[--i];
10527db96d56Sopenharmony_ci    } while (i > 0);
10537db96d56Sopenharmony_ci    return PyLong_FromUnsignedLong(x);
10547db96d56Sopenharmony_ci}
10557db96d56Sopenharmony_ci
10567db96d56Sopenharmony_cistatic PyObject *
10577db96d56Sopenharmony_cilu_longlong(_structmodulestate *state, const char *p, const formatdef *f)
10587db96d56Sopenharmony_ci{
10597db96d56Sopenharmony_ci    long long x = 0;
10607db96d56Sopenharmony_ci    Py_ssize_t i = f->size;
10617db96d56Sopenharmony_ci    const unsigned char *bytes = (const unsigned char *)p;
10627db96d56Sopenharmony_ci    do {
10637db96d56Sopenharmony_ci        x = (x<<8) | bytes[--i];
10647db96d56Sopenharmony_ci    } while (i > 0);
10657db96d56Sopenharmony_ci    /* Extend the sign bit. */
10667db96d56Sopenharmony_ci    if (SIZEOF_LONG_LONG > f->size)
10677db96d56Sopenharmony_ci        x |= -(x & ((long long)1 << ((8 * f->size) - 1)));
10687db96d56Sopenharmony_ci    return PyLong_FromLongLong(x);
10697db96d56Sopenharmony_ci}
10707db96d56Sopenharmony_ci
10717db96d56Sopenharmony_cistatic PyObject *
10727db96d56Sopenharmony_cilu_ulonglong(_structmodulestate *state, const char *p, const formatdef *f)
10737db96d56Sopenharmony_ci{
10747db96d56Sopenharmony_ci    unsigned long long x = 0;
10757db96d56Sopenharmony_ci    Py_ssize_t i = f->size;
10767db96d56Sopenharmony_ci    const unsigned char *bytes = (const unsigned char *)p;
10777db96d56Sopenharmony_ci    do {
10787db96d56Sopenharmony_ci        x = (x<<8) | bytes[--i];
10797db96d56Sopenharmony_ci    } while (i > 0);
10807db96d56Sopenharmony_ci    return PyLong_FromUnsignedLongLong(x);
10817db96d56Sopenharmony_ci}
10827db96d56Sopenharmony_ci
10837db96d56Sopenharmony_cistatic PyObject *
10847db96d56Sopenharmony_cilu_halffloat(_structmodulestate *state, const char *p, const formatdef *f)
10857db96d56Sopenharmony_ci{
10867db96d56Sopenharmony_ci    return unpack_halffloat(p, 1);
10877db96d56Sopenharmony_ci}
10887db96d56Sopenharmony_ci
10897db96d56Sopenharmony_cistatic PyObject *
10907db96d56Sopenharmony_cilu_float(_structmodulestate *state, const char *p, const formatdef *f)
10917db96d56Sopenharmony_ci{
10927db96d56Sopenharmony_ci    return unpack_float(p, 1);
10937db96d56Sopenharmony_ci}
10947db96d56Sopenharmony_ci
10957db96d56Sopenharmony_cistatic PyObject *
10967db96d56Sopenharmony_cilu_double(_structmodulestate *state, const char *p, const formatdef *f)
10977db96d56Sopenharmony_ci{
10987db96d56Sopenharmony_ci    return unpack_double(p, 1);
10997db96d56Sopenharmony_ci}
11007db96d56Sopenharmony_ci
11017db96d56Sopenharmony_cistatic int
11027db96d56Sopenharmony_cilp_int(_structmodulestate *state, char *p, PyObject *v, const formatdef *f)
11037db96d56Sopenharmony_ci{
11047db96d56Sopenharmony_ci    long x;
11057db96d56Sopenharmony_ci    Py_ssize_t i;
11067db96d56Sopenharmony_ci    unsigned char *q = (unsigned char *)p;
11077db96d56Sopenharmony_ci    if (get_long(state, v, &x) < 0)
11087db96d56Sopenharmony_ci        return -1;
11097db96d56Sopenharmony_ci    i = f->size;
11107db96d56Sopenharmony_ci    if (i != SIZEOF_LONG) {
11117db96d56Sopenharmony_ci        if ((i == 2) && (x < -32768 || x > 32767))
11127db96d56Sopenharmony_ci            RANGE_ERROR(state, x, f, 0, 0xffffL);
11137db96d56Sopenharmony_ci#if (SIZEOF_LONG != 4)
11147db96d56Sopenharmony_ci        else if ((i == 4) && (x < -2147483648L || x > 2147483647L))
11157db96d56Sopenharmony_ci            RANGE_ERROR(state, x, f, 0, 0xffffffffL);
11167db96d56Sopenharmony_ci#endif
11177db96d56Sopenharmony_ci    }
11187db96d56Sopenharmony_ci    do {
11197db96d56Sopenharmony_ci        *q++ = (unsigned char)(x & 0xffL);
11207db96d56Sopenharmony_ci        x >>= 8;
11217db96d56Sopenharmony_ci    } while (--i > 0);
11227db96d56Sopenharmony_ci    return 0;
11237db96d56Sopenharmony_ci}
11247db96d56Sopenharmony_ci
11257db96d56Sopenharmony_cistatic int
11267db96d56Sopenharmony_cilp_uint(_structmodulestate *state, char *p, PyObject *v, const formatdef *f)
11277db96d56Sopenharmony_ci{
11287db96d56Sopenharmony_ci    unsigned long x;
11297db96d56Sopenharmony_ci    Py_ssize_t i;
11307db96d56Sopenharmony_ci    unsigned char *q = (unsigned char *)p;
11317db96d56Sopenharmony_ci    if (get_ulong(state, v, &x) < 0)
11327db96d56Sopenharmony_ci        return -1;
11337db96d56Sopenharmony_ci    i = f->size;
11347db96d56Sopenharmony_ci    if (i != SIZEOF_LONG) {
11357db96d56Sopenharmony_ci        unsigned long maxint = 1;
11367db96d56Sopenharmony_ci        maxint <<= (unsigned long)(i * 8);
11377db96d56Sopenharmony_ci        if (x >= maxint)
11387db96d56Sopenharmony_ci            RANGE_ERROR(state, x, f, 1, maxint - 1);
11397db96d56Sopenharmony_ci    }
11407db96d56Sopenharmony_ci    do {
11417db96d56Sopenharmony_ci        *q++ = (unsigned char)(x & 0xffUL);
11427db96d56Sopenharmony_ci        x >>= 8;
11437db96d56Sopenharmony_ci    } while (--i > 0);
11447db96d56Sopenharmony_ci    return 0;
11457db96d56Sopenharmony_ci}
11467db96d56Sopenharmony_ci
11477db96d56Sopenharmony_cistatic int
11487db96d56Sopenharmony_cilp_longlong(_structmodulestate *state, char *p, PyObject *v, const formatdef *f)
11497db96d56Sopenharmony_ci{
11507db96d56Sopenharmony_ci    int res;
11517db96d56Sopenharmony_ci    v = get_pylong(state, v);
11527db96d56Sopenharmony_ci    if (v == NULL)
11537db96d56Sopenharmony_ci        return -1;
11547db96d56Sopenharmony_ci    res = _PyLong_AsByteArray((PyLongObject*)v,
11557db96d56Sopenharmony_ci                              (unsigned char *)p,
11567db96d56Sopenharmony_ci                              8,
11577db96d56Sopenharmony_ci                              1, /* little_endian */
11587db96d56Sopenharmony_ci                              1  /* signed */);
11597db96d56Sopenharmony_ci    Py_DECREF(v);
11607db96d56Sopenharmony_ci    return res;
11617db96d56Sopenharmony_ci}
11627db96d56Sopenharmony_ci
11637db96d56Sopenharmony_cistatic int
11647db96d56Sopenharmony_cilp_ulonglong(_structmodulestate *state, char *p, PyObject *v, const formatdef *f)
11657db96d56Sopenharmony_ci{
11667db96d56Sopenharmony_ci    int res;
11677db96d56Sopenharmony_ci    v = get_pylong(state, v);
11687db96d56Sopenharmony_ci    if (v == NULL)
11697db96d56Sopenharmony_ci        return -1;
11707db96d56Sopenharmony_ci    res = _PyLong_AsByteArray((PyLongObject*)v,
11717db96d56Sopenharmony_ci                              (unsigned char *)p,
11727db96d56Sopenharmony_ci                              8,
11737db96d56Sopenharmony_ci                              1, /* little_endian */
11747db96d56Sopenharmony_ci                              0  /* signed */);
11757db96d56Sopenharmony_ci    Py_DECREF(v);
11767db96d56Sopenharmony_ci    return res;
11777db96d56Sopenharmony_ci}
11787db96d56Sopenharmony_ci
11797db96d56Sopenharmony_cistatic int
11807db96d56Sopenharmony_cilp_halffloat(_structmodulestate *state, char *p, PyObject *v, const formatdef *f)
11817db96d56Sopenharmony_ci{
11827db96d56Sopenharmony_ci    return pack_halffloat(state, p, v, 1);
11837db96d56Sopenharmony_ci}
11847db96d56Sopenharmony_ci
11857db96d56Sopenharmony_cistatic int
11867db96d56Sopenharmony_cilp_float(_structmodulestate *state, char *p, PyObject *v, const formatdef *f)
11877db96d56Sopenharmony_ci{
11887db96d56Sopenharmony_ci    double x = PyFloat_AsDouble(v);
11897db96d56Sopenharmony_ci    if (x == -1 && PyErr_Occurred()) {
11907db96d56Sopenharmony_ci        PyErr_SetString(state->StructError,
11917db96d56Sopenharmony_ci                        "required argument is not a float");
11927db96d56Sopenharmony_ci        return -1;
11937db96d56Sopenharmony_ci    }
11947db96d56Sopenharmony_ci    return PyFloat_Pack4(x, p, 1);
11957db96d56Sopenharmony_ci}
11967db96d56Sopenharmony_ci
11977db96d56Sopenharmony_cistatic int
11987db96d56Sopenharmony_cilp_double(_structmodulestate *state, char *p, PyObject *v, const formatdef *f)
11997db96d56Sopenharmony_ci{
12007db96d56Sopenharmony_ci    double x = PyFloat_AsDouble(v);
12017db96d56Sopenharmony_ci    if (x == -1 && PyErr_Occurred()) {
12027db96d56Sopenharmony_ci        PyErr_SetString(state->StructError,
12037db96d56Sopenharmony_ci                        "required argument is not a float");
12047db96d56Sopenharmony_ci        return -1;
12057db96d56Sopenharmony_ci    }
12067db96d56Sopenharmony_ci    return PyFloat_Pack8(x, p, 1);
12077db96d56Sopenharmony_ci}
12087db96d56Sopenharmony_ci
12097db96d56Sopenharmony_cistatic formatdef lilendian_table[] = {
12107db96d56Sopenharmony_ci    {'x',       1,              0,              NULL},
12117db96d56Sopenharmony_ci    {'b',       1,              0,              nu_byte,        np_byte},
12127db96d56Sopenharmony_ci    {'B',       1,              0,              nu_ubyte,       np_ubyte},
12137db96d56Sopenharmony_ci    {'c',       1,              0,              nu_char,        np_char},
12147db96d56Sopenharmony_ci    {'s',       1,              0,              NULL},
12157db96d56Sopenharmony_ci    {'p',       1,              0,              NULL},
12167db96d56Sopenharmony_ci    {'h',       2,              0,              lu_int,         lp_int},
12177db96d56Sopenharmony_ci    {'H',       2,              0,              lu_uint,        lp_uint},
12187db96d56Sopenharmony_ci    {'i',       4,              0,              lu_int,         lp_int},
12197db96d56Sopenharmony_ci    {'I',       4,              0,              lu_uint,        lp_uint},
12207db96d56Sopenharmony_ci    {'l',       4,              0,              lu_int,         lp_int},
12217db96d56Sopenharmony_ci    {'L',       4,              0,              lu_uint,        lp_uint},
12227db96d56Sopenharmony_ci    {'q',       8,              0,              lu_longlong,    lp_longlong},
12237db96d56Sopenharmony_ci    {'Q',       8,              0,              lu_ulonglong,   lp_ulonglong},
12247db96d56Sopenharmony_ci    {'?',       1,              0,              bu_bool,        bp_bool}, /* Std rep not endian dep,
12257db96d56Sopenharmony_ci        but potentially different from native rep -- reuse bx_bool funcs. */
12267db96d56Sopenharmony_ci    {'e',       2,              0,              lu_halffloat,   lp_halffloat},
12277db96d56Sopenharmony_ci    {'f',       4,              0,              lu_float,       lp_float},
12287db96d56Sopenharmony_ci    {'d',       8,              0,              lu_double,      lp_double},
12297db96d56Sopenharmony_ci    {0}
12307db96d56Sopenharmony_ci};
12317db96d56Sopenharmony_ci
12327db96d56Sopenharmony_ci
12337db96d56Sopenharmony_cistatic const formatdef *
12347db96d56Sopenharmony_ciwhichtable(const char **pfmt)
12357db96d56Sopenharmony_ci{
12367db96d56Sopenharmony_ci    const char *fmt = (*pfmt)++; /* May be backed out of later */
12377db96d56Sopenharmony_ci    switch (*fmt) {
12387db96d56Sopenharmony_ci    case '<':
12397db96d56Sopenharmony_ci        return lilendian_table;
12407db96d56Sopenharmony_ci    case '>':
12417db96d56Sopenharmony_ci    case '!': /* Network byte order is big-endian */
12427db96d56Sopenharmony_ci        return bigendian_table;
12437db96d56Sopenharmony_ci    case '=': { /* Host byte order -- different from native in alignment! */
12447db96d56Sopenharmony_ci#if PY_LITTLE_ENDIAN
12457db96d56Sopenharmony_ci        return lilendian_table;
12467db96d56Sopenharmony_ci#else
12477db96d56Sopenharmony_ci        return bigendian_table;
12487db96d56Sopenharmony_ci#endif
12497db96d56Sopenharmony_ci    }
12507db96d56Sopenharmony_ci    default:
12517db96d56Sopenharmony_ci        --*pfmt; /* Back out of pointer increment */
12527db96d56Sopenharmony_ci        /* Fall through */
12537db96d56Sopenharmony_ci    case '@':
12547db96d56Sopenharmony_ci        return native_table;
12557db96d56Sopenharmony_ci    }
12567db96d56Sopenharmony_ci}
12577db96d56Sopenharmony_ci
12587db96d56Sopenharmony_ci
12597db96d56Sopenharmony_ci/* Get the table entry for a format code */
12607db96d56Sopenharmony_ci
12617db96d56Sopenharmony_cistatic const formatdef *
12627db96d56Sopenharmony_cigetentry(_structmodulestate *state, int c, const formatdef *f)
12637db96d56Sopenharmony_ci{
12647db96d56Sopenharmony_ci    for (; f->format != '\0'; f++) {
12657db96d56Sopenharmony_ci        if (f->format == c) {
12667db96d56Sopenharmony_ci            return f;
12677db96d56Sopenharmony_ci        }
12687db96d56Sopenharmony_ci    }
12697db96d56Sopenharmony_ci    PyErr_SetString(state->StructError, "bad char in struct format");
12707db96d56Sopenharmony_ci    return NULL;
12717db96d56Sopenharmony_ci}
12727db96d56Sopenharmony_ci
12737db96d56Sopenharmony_ci
12747db96d56Sopenharmony_ci/* Align a size according to a format code.  Return -1 on overflow. */
12757db96d56Sopenharmony_ci
12767db96d56Sopenharmony_cistatic Py_ssize_t
12777db96d56Sopenharmony_cialign(Py_ssize_t size, char c, const formatdef *e)
12787db96d56Sopenharmony_ci{
12797db96d56Sopenharmony_ci    Py_ssize_t extra;
12807db96d56Sopenharmony_ci
12817db96d56Sopenharmony_ci    if (e->format == c) {
12827db96d56Sopenharmony_ci        if (e->alignment && size > 0) {
12837db96d56Sopenharmony_ci            extra = (e->alignment - 1) - (size - 1) % (e->alignment);
12847db96d56Sopenharmony_ci            if (extra > PY_SSIZE_T_MAX - size)
12857db96d56Sopenharmony_ci                return -1;
12867db96d56Sopenharmony_ci            size += extra;
12877db96d56Sopenharmony_ci        }
12887db96d56Sopenharmony_ci    }
12897db96d56Sopenharmony_ci    return size;
12907db96d56Sopenharmony_ci}
12917db96d56Sopenharmony_ci
12927db96d56Sopenharmony_ci/*
12937db96d56Sopenharmony_ci * Struct object implementation.
12947db96d56Sopenharmony_ci */
12957db96d56Sopenharmony_ci
12967db96d56Sopenharmony_ci/* calculate the size of a format string */
12977db96d56Sopenharmony_ci
12987db96d56Sopenharmony_cistatic int
12997db96d56Sopenharmony_ciprepare_s(PyStructObject *self)
13007db96d56Sopenharmony_ci{
13017db96d56Sopenharmony_ci    const formatdef *f;
13027db96d56Sopenharmony_ci    const formatdef *e;
13037db96d56Sopenharmony_ci    formatcode *codes;
13047db96d56Sopenharmony_ci
13057db96d56Sopenharmony_ci    const char *s;
13067db96d56Sopenharmony_ci    const char *fmt;
13077db96d56Sopenharmony_ci    char c;
13087db96d56Sopenharmony_ci    Py_ssize_t size, len, num, itemsize;
13097db96d56Sopenharmony_ci    size_t ncodes;
13107db96d56Sopenharmony_ci
13117db96d56Sopenharmony_ci    _structmodulestate *state = get_struct_state_structinst(self);
13127db96d56Sopenharmony_ci
13137db96d56Sopenharmony_ci    fmt = PyBytes_AS_STRING(self->s_format);
13147db96d56Sopenharmony_ci    if (strlen(fmt) != (size_t)PyBytes_GET_SIZE(self->s_format)) {
13157db96d56Sopenharmony_ci        PyErr_SetString(state->StructError,
13167db96d56Sopenharmony_ci                        "embedded null character");
13177db96d56Sopenharmony_ci        return -1;
13187db96d56Sopenharmony_ci    }
13197db96d56Sopenharmony_ci
13207db96d56Sopenharmony_ci    f = whichtable(&fmt);
13217db96d56Sopenharmony_ci
13227db96d56Sopenharmony_ci    s = fmt;
13237db96d56Sopenharmony_ci    size = 0;
13247db96d56Sopenharmony_ci    len = 0;
13257db96d56Sopenharmony_ci    ncodes = 0;
13267db96d56Sopenharmony_ci    while ((c = *s++) != '\0') {
13277db96d56Sopenharmony_ci        if (Py_ISSPACE(c))
13287db96d56Sopenharmony_ci            continue;
13297db96d56Sopenharmony_ci        if ('0' <= c && c <= '9') {
13307db96d56Sopenharmony_ci            num = c - '0';
13317db96d56Sopenharmony_ci            while ('0' <= (c = *s++) && c <= '9') {
13327db96d56Sopenharmony_ci                /* overflow-safe version of
13337db96d56Sopenharmony_ci                   if (num*10 + (c - '0') > PY_SSIZE_T_MAX) { ... } */
13347db96d56Sopenharmony_ci                if (num >= PY_SSIZE_T_MAX / 10 && (
13357db96d56Sopenharmony_ci                        num > PY_SSIZE_T_MAX / 10 ||
13367db96d56Sopenharmony_ci                        (c - '0') > PY_SSIZE_T_MAX % 10))
13377db96d56Sopenharmony_ci                    goto overflow;
13387db96d56Sopenharmony_ci                num = num*10 + (c - '0');
13397db96d56Sopenharmony_ci            }
13407db96d56Sopenharmony_ci            if (c == '\0') {
13417db96d56Sopenharmony_ci                PyErr_SetString(state->StructError,
13427db96d56Sopenharmony_ci                                "repeat count given without format specifier");
13437db96d56Sopenharmony_ci                return -1;
13447db96d56Sopenharmony_ci            }
13457db96d56Sopenharmony_ci        }
13467db96d56Sopenharmony_ci        else
13477db96d56Sopenharmony_ci            num = 1;
13487db96d56Sopenharmony_ci
13497db96d56Sopenharmony_ci        e = getentry(state, c, f);
13507db96d56Sopenharmony_ci        if (e == NULL)
13517db96d56Sopenharmony_ci            return -1;
13527db96d56Sopenharmony_ci
13537db96d56Sopenharmony_ci        switch (c) {
13547db96d56Sopenharmony_ci            case 's': /* fall through */
13557db96d56Sopenharmony_ci            case 'p': len++; ncodes++; break;
13567db96d56Sopenharmony_ci            case 'x': break;
13577db96d56Sopenharmony_ci            default: len += num; if (num) ncodes++; break;
13587db96d56Sopenharmony_ci        }
13597db96d56Sopenharmony_ci
13607db96d56Sopenharmony_ci        itemsize = e->size;
13617db96d56Sopenharmony_ci        size = align(size, c, e);
13627db96d56Sopenharmony_ci        if (size == -1)
13637db96d56Sopenharmony_ci            goto overflow;
13647db96d56Sopenharmony_ci
13657db96d56Sopenharmony_ci        /* if (size + num * itemsize > PY_SSIZE_T_MAX) { ... } */
13667db96d56Sopenharmony_ci        if (num > (PY_SSIZE_T_MAX - size) / itemsize)
13677db96d56Sopenharmony_ci            goto overflow;
13687db96d56Sopenharmony_ci        size += num * itemsize;
13697db96d56Sopenharmony_ci    }
13707db96d56Sopenharmony_ci
13717db96d56Sopenharmony_ci    /* check for overflow */
13727db96d56Sopenharmony_ci    if ((ncodes + 1) > ((size_t)PY_SSIZE_T_MAX / sizeof(formatcode))) {
13737db96d56Sopenharmony_ci        PyErr_NoMemory();
13747db96d56Sopenharmony_ci        return -1;
13757db96d56Sopenharmony_ci    }
13767db96d56Sopenharmony_ci
13777db96d56Sopenharmony_ci    self->s_size = size;
13787db96d56Sopenharmony_ci    self->s_len = len;
13797db96d56Sopenharmony_ci    codes = PyMem_Malloc((ncodes + 1) * sizeof(formatcode));
13807db96d56Sopenharmony_ci    if (codes == NULL) {
13817db96d56Sopenharmony_ci        PyErr_NoMemory();
13827db96d56Sopenharmony_ci        return -1;
13837db96d56Sopenharmony_ci    }
13847db96d56Sopenharmony_ci    /* Free any s_codes value left over from a previous initialization. */
13857db96d56Sopenharmony_ci    if (self->s_codes != NULL)
13867db96d56Sopenharmony_ci        PyMem_Free(self->s_codes);
13877db96d56Sopenharmony_ci    self->s_codes = codes;
13887db96d56Sopenharmony_ci
13897db96d56Sopenharmony_ci    s = fmt;
13907db96d56Sopenharmony_ci    size = 0;
13917db96d56Sopenharmony_ci    while ((c = *s++) != '\0') {
13927db96d56Sopenharmony_ci        if (Py_ISSPACE(c))
13937db96d56Sopenharmony_ci            continue;
13947db96d56Sopenharmony_ci        if ('0' <= c && c <= '9') {
13957db96d56Sopenharmony_ci            num = c - '0';
13967db96d56Sopenharmony_ci            while ('0' <= (c = *s++) && c <= '9')
13977db96d56Sopenharmony_ci                num = num*10 + (c - '0');
13987db96d56Sopenharmony_ci        }
13997db96d56Sopenharmony_ci        else
14007db96d56Sopenharmony_ci            num = 1;
14017db96d56Sopenharmony_ci
14027db96d56Sopenharmony_ci        e = getentry(state, c, f);
14037db96d56Sopenharmony_ci
14047db96d56Sopenharmony_ci        size = align(size, c, e);
14057db96d56Sopenharmony_ci        if (c == 's' || c == 'p') {
14067db96d56Sopenharmony_ci            codes->offset = size;
14077db96d56Sopenharmony_ci            codes->size = num;
14087db96d56Sopenharmony_ci            codes->fmtdef = e;
14097db96d56Sopenharmony_ci            codes->repeat = 1;
14107db96d56Sopenharmony_ci            codes++;
14117db96d56Sopenharmony_ci            size += num;
14127db96d56Sopenharmony_ci        } else if (c == 'x') {
14137db96d56Sopenharmony_ci            size += num;
14147db96d56Sopenharmony_ci        } else if (num) {
14157db96d56Sopenharmony_ci            codes->offset = size;
14167db96d56Sopenharmony_ci            codes->size = e->size;
14177db96d56Sopenharmony_ci            codes->fmtdef = e;
14187db96d56Sopenharmony_ci            codes->repeat = num;
14197db96d56Sopenharmony_ci            codes++;
14207db96d56Sopenharmony_ci            size += e->size * num;
14217db96d56Sopenharmony_ci        }
14227db96d56Sopenharmony_ci    }
14237db96d56Sopenharmony_ci    codes->fmtdef = NULL;
14247db96d56Sopenharmony_ci    codes->offset = size;
14257db96d56Sopenharmony_ci    codes->size = 0;
14267db96d56Sopenharmony_ci    codes->repeat = 0;
14277db96d56Sopenharmony_ci
14287db96d56Sopenharmony_ci    return 0;
14297db96d56Sopenharmony_ci
14307db96d56Sopenharmony_ci  overflow:
14317db96d56Sopenharmony_ci    PyErr_SetString(state->StructError,
14327db96d56Sopenharmony_ci                    "total struct size too long");
14337db96d56Sopenharmony_ci    return -1;
14347db96d56Sopenharmony_ci}
14357db96d56Sopenharmony_ci
14367db96d56Sopenharmony_cistatic PyObject *
14377db96d56Sopenharmony_cis_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
14387db96d56Sopenharmony_ci{
14397db96d56Sopenharmony_ci    PyObject *self;
14407db96d56Sopenharmony_ci
14417db96d56Sopenharmony_ci    assert(type != NULL);
14427db96d56Sopenharmony_ci    allocfunc alloc_func = PyType_GetSlot(type, Py_tp_alloc);
14437db96d56Sopenharmony_ci    assert(alloc_func != NULL);
14447db96d56Sopenharmony_ci
14457db96d56Sopenharmony_ci    self = alloc_func(type, 0);
14467db96d56Sopenharmony_ci    if (self != NULL) {
14477db96d56Sopenharmony_ci        PyStructObject *s = (PyStructObject*)self;
14487db96d56Sopenharmony_ci        s->s_format = Py_NewRef(Py_None);
14497db96d56Sopenharmony_ci        s->s_codes = NULL;
14507db96d56Sopenharmony_ci        s->s_size = -1;
14517db96d56Sopenharmony_ci        s->s_len = -1;
14527db96d56Sopenharmony_ci    }
14537db96d56Sopenharmony_ci    return self;
14547db96d56Sopenharmony_ci}
14557db96d56Sopenharmony_ci
14567db96d56Sopenharmony_ci/*[clinic input]
14577db96d56Sopenharmony_ciStruct.__init__
14587db96d56Sopenharmony_ci
14597db96d56Sopenharmony_ci    format: object
14607db96d56Sopenharmony_ci
14617db96d56Sopenharmony_ciCreate a compiled struct object.
14627db96d56Sopenharmony_ci
14637db96d56Sopenharmony_ciReturn a new Struct object which writes and reads binary data according to
14647db96d56Sopenharmony_cithe format string.
14657db96d56Sopenharmony_ci
14667db96d56Sopenharmony_ciSee help(struct) for more on format strings.
14677db96d56Sopenharmony_ci[clinic start generated code]*/
14687db96d56Sopenharmony_ci
14697db96d56Sopenharmony_cistatic int
14707db96d56Sopenharmony_ciStruct___init___impl(PyStructObject *self, PyObject *format)
14717db96d56Sopenharmony_ci/*[clinic end generated code: output=b8e80862444e92d0 input=192a4575a3dde802]*/
14727db96d56Sopenharmony_ci{
14737db96d56Sopenharmony_ci    int ret = 0;
14747db96d56Sopenharmony_ci
14757db96d56Sopenharmony_ci    if (PyUnicode_Check(format)) {
14767db96d56Sopenharmony_ci        format = PyUnicode_AsASCIIString(format);
14777db96d56Sopenharmony_ci        if (format == NULL)
14787db96d56Sopenharmony_ci            return -1;
14797db96d56Sopenharmony_ci    }
14807db96d56Sopenharmony_ci    else {
14817db96d56Sopenharmony_ci        Py_INCREF(format);
14827db96d56Sopenharmony_ci    }
14837db96d56Sopenharmony_ci
14847db96d56Sopenharmony_ci    if (!PyBytes_Check(format)) {
14857db96d56Sopenharmony_ci        Py_DECREF(format);
14867db96d56Sopenharmony_ci        PyErr_Format(PyExc_TypeError,
14877db96d56Sopenharmony_ci                     "Struct() argument 1 must be a str or bytes object, "
14887db96d56Sopenharmony_ci                     "not %.200s",
14897db96d56Sopenharmony_ci                     _PyType_Name(Py_TYPE(format)));
14907db96d56Sopenharmony_ci        return -1;
14917db96d56Sopenharmony_ci    }
14927db96d56Sopenharmony_ci
14937db96d56Sopenharmony_ci    Py_SETREF(self->s_format, format);
14947db96d56Sopenharmony_ci
14957db96d56Sopenharmony_ci    ret = prepare_s(self);
14967db96d56Sopenharmony_ci    return ret;
14977db96d56Sopenharmony_ci}
14987db96d56Sopenharmony_ci
14997db96d56Sopenharmony_cistatic int
15007db96d56Sopenharmony_cis_clear(PyStructObject *s)
15017db96d56Sopenharmony_ci{
15027db96d56Sopenharmony_ci    Py_CLEAR(s->s_format);
15037db96d56Sopenharmony_ci    return 0;
15047db96d56Sopenharmony_ci}
15057db96d56Sopenharmony_ci
15067db96d56Sopenharmony_cistatic int
15077db96d56Sopenharmony_cis_traverse(PyStructObject *s, visitproc visit, void *arg)
15087db96d56Sopenharmony_ci{
15097db96d56Sopenharmony_ci    Py_VISIT(Py_TYPE(s));
15107db96d56Sopenharmony_ci    Py_VISIT(s->s_format);
15117db96d56Sopenharmony_ci    return 0;
15127db96d56Sopenharmony_ci}
15137db96d56Sopenharmony_ci
15147db96d56Sopenharmony_cistatic void
15157db96d56Sopenharmony_cis_dealloc(PyStructObject *s)
15167db96d56Sopenharmony_ci{
15177db96d56Sopenharmony_ci    PyTypeObject *tp = Py_TYPE(s);
15187db96d56Sopenharmony_ci    PyObject_GC_UnTrack(s);
15197db96d56Sopenharmony_ci    if (s->weakreflist != NULL)
15207db96d56Sopenharmony_ci        PyObject_ClearWeakRefs((PyObject *)s);
15217db96d56Sopenharmony_ci    if (s->s_codes != NULL) {
15227db96d56Sopenharmony_ci        PyMem_Free(s->s_codes);
15237db96d56Sopenharmony_ci    }
15247db96d56Sopenharmony_ci    Py_XDECREF(s->s_format);
15257db96d56Sopenharmony_ci    freefunc free_func = PyType_GetSlot(Py_TYPE(s), Py_tp_free);
15267db96d56Sopenharmony_ci    free_func(s);
15277db96d56Sopenharmony_ci    Py_DECREF(tp);
15287db96d56Sopenharmony_ci}
15297db96d56Sopenharmony_ci
15307db96d56Sopenharmony_cistatic PyObject *
15317db96d56Sopenharmony_cis_unpack_internal(PyStructObject *soself, const char *startfrom,
15327db96d56Sopenharmony_ci                  _structmodulestate *state) {
15337db96d56Sopenharmony_ci    formatcode *code;
15347db96d56Sopenharmony_ci    Py_ssize_t i = 0;
15357db96d56Sopenharmony_ci    PyObject *result = PyTuple_New(soself->s_len);
15367db96d56Sopenharmony_ci    if (result == NULL)
15377db96d56Sopenharmony_ci        return NULL;
15387db96d56Sopenharmony_ci
15397db96d56Sopenharmony_ci    for (code = soself->s_codes; code->fmtdef != NULL; code++) {
15407db96d56Sopenharmony_ci        const formatdef *e = code->fmtdef;
15417db96d56Sopenharmony_ci        const char *res = startfrom + code->offset;
15427db96d56Sopenharmony_ci        Py_ssize_t j = code->repeat;
15437db96d56Sopenharmony_ci        while (j--) {
15447db96d56Sopenharmony_ci            PyObject *v;
15457db96d56Sopenharmony_ci            if (e->format == 's') {
15467db96d56Sopenharmony_ci                v = PyBytes_FromStringAndSize(res, code->size);
15477db96d56Sopenharmony_ci            } else if (e->format == 'p') {
15487db96d56Sopenharmony_ci                Py_ssize_t n = *(unsigned char*)res;
15497db96d56Sopenharmony_ci                if (n >= code->size)
15507db96d56Sopenharmony_ci                    n = code->size - 1;
15517db96d56Sopenharmony_ci                v = PyBytes_FromStringAndSize(res + 1, n);
15527db96d56Sopenharmony_ci            } else {
15537db96d56Sopenharmony_ci                v = e->unpack(state, res, e);
15547db96d56Sopenharmony_ci            }
15557db96d56Sopenharmony_ci            if (v == NULL)
15567db96d56Sopenharmony_ci                goto fail;
15577db96d56Sopenharmony_ci            PyTuple_SET_ITEM(result, i++, v);
15587db96d56Sopenharmony_ci            res += code->size;
15597db96d56Sopenharmony_ci        }
15607db96d56Sopenharmony_ci    }
15617db96d56Sopenharmony_ci
15627db96d56Sopenharmony_ci    return result;
15637db96d56Sopenharmony_cifail:
15647db96d56Sopenharmony_ci    Py_DECREF(result);
15657db96d56Sopenharmony_ci    return NULL;
15667db96d56Sopenharmony_ci}
15677db96d56Sopenharmony_ci
15687db96d56Sopenharmony_ci
15697db96d56Sopenharmony_ci/*[clinic input]
15707db96d56Sopenharmony_ciStruct.unpack
15717db96d56Sopenharmony_ci
15727db96d56Sopenharmony_ci    buffer: Py_buffer
15737db96d56Sopenharmony_ci    /
15747db96d56Sopenharmony_ci
15757db96d56Sopenharmony_ciReturn a tuple containing unpacked values.
15767db96d56Sopenharmony_ci
15777db96d56Sopenharmony_ciUnpack according to the format string Struct.format. The buffer's size
15787db96d56Sopenharmony_ciin bytes must be Struct.size.
15797db96d56Sopenharmony_ci
15807db96d56Sopenharmony_ciSee help(struct) for more on format strings.
15817db96d56Sopenharmony_ci[clinic start generated code]*/
15827db96d56Sopenharmony_ci
15837db96d56Sopenharmony_cistatic PyObject *
15847db96d56Sopenharmony_ciStruct_unpack_impl(PyStructObject *self, Py_buffer *buffer)
15857db96d56Sopenharmony_ci/*[clinic end generated code: output=873a24faf02e848a input=3113f8e7038b2f6c]*/
15867db96d56Sopenharmony_ci{
15877db96d56Sopenharmony_ci    _structmodulestate *state = get_struct_state_structinst(self);
15887db96d56Sopenharmony_ci    assert(self->s_codes != NULL);
15897db96d56Sopenharmony_ci    if (buffer->len != self->s_size) {
15907db96d56Sopenharmony_ci        PyErr_Format(state->StructError,
15917db96d56Sopenharmony_ci                     "unpack requires a buffer of %zd bytes",
15927db96d56Sopenharmony_ci                     self->s_size);
15937db96d56Sopenharmony_ci        return NULL;
15947db96d56Sopenharmony_ci    }
15957db96d56Sopenharmony_ci    return s_unpack_internal(self, buffer->buf, state);
15967db96d56Sopenharmony_ci}
15977db96d56Sopenharmony_ci
15987db96d56Sopenharmony_ci/*[clinic input]
15997db96d56Sopenharmony_ciStruct.unpack_from
16007db96d56Sopenharmony_ci
16017db96d56Sopenharmony_ci    buffer: Py_buffer
16027db96d56Sopenharmony_ci    offset: Py_ssize_t = 0
16037db96d56Sopenharmony_ci
16047db96d56Sopenharmony_ciReturn a tuple containing unpacked values.
16057db96d56Sopenharmony_ci
16067db96d56Sopenharmony_ciValues are unpacked according to the format string Struct.format.
16077db96d56Sopenharmony_ci
16087db96d56Sopenharmony_ciThe buffer's size in bytes, starting at position offset, must be
16097db96d56Sopenharmony_ciat least Struct.size.
16107db96d56Sopenharmony_ci
16117db96d56Sopenharmony_ciSee help(struct) for more on format strings.
16127db96d56Sopenharmony_ci[clinic start generated code]*/
16137db96d56Sopenharmony_ci
16147db96d56Sopenharmony_cistatic PyObject *
16157db96d56Sopenharmony_ciStruct_unpack_from_impl(PyStructObject *self, Py_buffer *buffer,
16167db96d56Sopenharmony_ci                        Py_ssize_t offset)
16177db96d56Sopenharmony_ci/*[clinic end generated code: output=57fac875e0977316 input=cafd4851d473c894]*/
16187db96d56Sopenharmony_ci{
16197db96d56Sopenharmony_ci    _structmodulestate *state = get_struct_state_structinst(self);
16207db96d56Sopenharmony_ci    assert(self->s_codes != NULL);
16217db96d56Sopenharmony_ci
16227db96d56Sopenharmony_ci    if (offset < 0) {
16237db96d56Sopenharmony_ci        if (offset + self->s_size > 0) {
16247db96d56Sopenharmony_ci            PyErr_Format(state->StructError,
16257db96d56Sopenharmony_ci                         "not enough data to unpack %zd bytes at offset %zd",
16267db96d56Sopenharmony_ci                         self->s_size,
16277db96d56Sopenharmony_ci                         offset);
16287db96d56Sopenharmony_ci            return NULL;
16297db96d56Sopenharmony_ci        }
16307db96d56Sopenharmony_ci
16317db96d56Sopenharmony_ci        if (offset + buffer->len < 0) {
16327db96d56Sopenharmony_ci            PyErr_Format(state->StructError,
16337db96d56Sopenharmony_ci                         "offset %zd out of range for %zd-byte buffer",
16347db96d56Sopenharmony_ci                         offset,
16357db96d56Sopenharmony_ci                         buffer->len);
16367db96d56Sopenharmony_ci            return NULL;
16377db96d56Sopenharmony_ci        }
16387db96d56Sopenharmony_ci        offset += buffer->len;
16397db96d56Sopenharmony_ci    }
16407db96d56Sopenharmony_ci
16417db96d56Sopenharmony_ci    if ((buffer->len - offset) < self->s_size) {
16427db96d56Sopenharmony_ci        PyErr_Format(state->StructError,
16437db96d56Sopenharmony_ci                     "unpack_from requires a buffer of at least %zu bytes for "
16447db96d56Sopenharmony_ci                     "unpacking %zd bytes at offset %zd "
16457db96d56Sopenharmony_ci                     "(actual buffer size is %zd)",
16467db96d56Sopenharmony_ci                     (size_t)self->s_size + (size_t)offset,
16477db96d56Sopenharmony_ci                     self->s_size,
16487db96d56Sopenharmony_ci                     offset,
16497db96d56Sopenharmony_ci                     buffer->len);
16507db96d56Sopenharmony_ci        return NULL;
16517db96d56Sopenharmony_ci    }
16527db96d56Sopenharmony_ci    return s_unpack_internal(self, (char*)buffer->buf + offset, state);
16537db96d56Sopenharmony_ci}
16547db96d56Sopenharmony_ci
16557db96d56Sopenharmony_ci
16567db96d56Sopenharmony_ci
16577db96d56Sopenharmony_ci/* Unpack iterator type */
16587db96d56Sopenharmony_ci
16597db96d56Sopenharmony_citypedef struct {
16607db96d56Sopenharmony_ci    PyObject_HEAD
16617db96d56Sopenharmony_ci    PyStructObject *so;
16627db96d56Sopenharmony_ci    Py_buffer buf;
16637db96d56Sopenharmony_ci    Py_ssize_t index;
16647db96d56Sopenharmony_ci} unpackiterobject;
16657db96d56Sopenharmony_ci
16667db96d56Sopenharmony_cistatic void
16677db96d56Sopenharmony_ciunpackiter_dealloc(unpackiterobject *self)
16687db96d56Sopenharmony_ci{
16697db96d56Sopenharmony_ci    /* bpo-31095: UnTrack is needed before calling any callbacks */
16707db96d56Sopenharmony_ci    PyTypeObject *tp = Py_TYPE(self);
16717db96d56Sopenharmony_ci    PyObject_GC_UnTrack(self);
16727db96d56Sopenharmony_ci    Py_XDECREF(self->so);
16737db96d56Sopenharmony_ci    PyBuffer_Release(&self->buf);
16747db96d56Sopenharmony_ci    PyObject_GC_Del(self);
16757db96d56Sopenharmony_ci    Py_DECREF(tp);
16767db96d56Sopenharmony_ci}
16777db96d56Sopenharmony_ci
16787db96d56Sopenharmony_cistatic int
16797db96d56Sopenharmony_ciunpackiter_traverse(unpackiterobject *self, visitproc visit, void *arg)
16807db96d56Sopenharmony_ci{
16817db96d56Sopenharmony_ci    Py_VISIT(Py_TYPE(self));
16827db96d56Sopenharmony_ci    Py_VISIT(self->so);
16837db96d56Sopenharmony_ci    Py_VISIT(self->buf.obj);
16847db96d56Sopenharmony_ci    return 0;
16857db96d56Sopenharmony_ci}
16867db96d56Sopenharmony_ci
16877db96d56Sopenharmony_cistatic PyObject *
16887db96d56Sopenharmony_ciunpackiter_len(unpackiterobject *self, PyObject *Py_UNUSED(ignored))
16897db96d56Sopenharmony_ci{
16907db96d56Sopenharmony_ci    Py_ssize_t len;
16917db96d56Sopenharmony_ci    if (self->so == NULL)
16927db96d56Sopenharmony_ci        len = 0;
16937db96d56Sopenharmony_ci    else
16947db96d56Sopenharmony_ci        len = (self->buf.len - self->index) / self->so->s_size;
16957db96d56Sopenharmony_ci    return PyLong_FromSsize_t(len);
16967db96d56Sopenharmony_ci}
16977db96d56Sopenharmony_ci
16987db96d56Sopenharmony_cistatic PyMethodDef unpackiter_methods[] = {
16997db96d56Sopenharmony_ci    {"__length_hint__", (PyCFunction) unpackiter_len, METH_NOARGS, NULL},
17007db96d56Sopenharmony_ci    {NULL,              NULL}           /* sentinel */
17017db96d56Sopenharmony_ci};
17027db96d56Sopenharmony_ci
17037db96d56Sopenharmony_cistatic PyObject *
17047db96d56Sopenharmony_ciunpackiter_iternext(unpackiterobject *self)
17057db96d56Sopenharmony_ci{
17067db96d56Sopenharmony_ci    _structmodulestate *state = get_struct_state_iterinst(self);
17077db96d56Sopenharmony_ci    PyObject *result;
17087db96d56Sopenharmony_ci    if (self->so == NULL)
17097db96d56Sopenharmony_ci        return NULL;
17107db96d56Sopenharmony_ci    if (self->index >= self->buf.len) {
17117db96d56Sopenharmony_ci        /* Iterator exhausted */
17127db96d56Sopenharmony_ci        Py_CLEAR(self->so);
17137db96d56Sopenharmony_ci        PyBuffer_Release(&self->buf);
17147db96d56Sopenharmony_ci        return NULL;
17157db96d56Sopenharmony_ci    }
17167db96d56Sopenharmony_ci    assert(self->index + self->so->s_size <= self->buf.len);
17177db96d56Sopenharmony_ci    result = s_unpack_internal(self->so,
17187db96d56Sopenharmony_ci                               (char*) self->buf.buf + self->index,
17197db96d56Sopenharmony_ci                               state);
17207db96d56Sopenharmony_ci    self->index += self->so->s_size;
17217db96d56Sopenharmony_ci    return result;
17227db96d56Sopenharmony_ci}
17237db96d56Sopenharmony_ci
17247db96d56Sopenharmony_ciPyObject *unpackiter_new(PyTypeObject *type, PyObject *args, PyObject *kwds) {
17257db96d56Sopenharmony_ci    PyErr_Format(PyExc_TypeError, "Cannot create '%.200s objects", _PyType_Name(type));
17267db96d56Sopenharmony_ci    return NULL;
17277db96d56Sopenharmony_ci}
17287db96d56Sopenharmony_ci
17297db96d56Sopenharmony_cistatic PyType_Slot unpackiter_type_slots[] = {
17307db96d56Sopenharmony_ci    {Py_tp_dealloc, unpackiter_dealloc},
17317db96d56Sopenharmony_ci    {Py_tp_getattro, PyObject_GenericGetAttr},
17327db96d56Sopenharmony_ci    {Py_tp_traverse, unpackiter_traverse},
17337db96d56Sopenharmony_ci    {Py_tp_iter, PyObject_SelfIter},
17347db96d56Sopenharmony_ci    {Py_tp_iternext, unpackiter_iternext},
17357db96d56Sopenharmony_ci    {Py_tp_methods, unpackiter_methods},
17367db96d56Sopenharmony_ci    {Py_tp_new, unpackiter_new},
17377db96d56Sopenharmony_ci    {0, 0},
17387db96d56Sopenharmony_ci};
17397db96d56Sopenharmony_ci
17407db96d56Sopenharmony_cistatic PyType_Spec unpackiter_type_spec = {
17417db96d56Sopenharmony_ci    "_struct.unpack_iterator",
17427db96d56Sopenharmony_ci    sizeof(unpackiterobject),
17437db96d56Sopenharmony_ci    0,
17447db96d56Sopenharmony_ci    (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |
17457db96d56Sopenharmony_ci     Py_TPFLAGS_IMMUTABLETYPE),
17467db96d56Sopenharmony_ci    unpackiter_type_slots
17477db96d56Sopenharmony_ci};
17487db96d56Sopenharmony_ci
17497db96d56Sopenharmony_ci/*[clinic input]
17507db96d56Sopenharmony_ciStruct.iter_unpack
17517db96d56Sopenharmony_ci
17527db96d56Sopenharmony_ci    buffer: object
17537db96d56Sopenharmony_ci    /
17547db96d56Sopenharmony_ci
17557db96d56Sopenharmony_ciReturn an iterator yielding tuples.
17567db96d56Sopenharmony_ci
17577db96d56Sopenharmony_ciTuples are unpacked from the given bytes source, like a repeated
17587db96d56Sopenharmony_ciinvocation of unpack_from().
17597db96d56Sopenharmony_ci
17607db96d56Sopenharmony_ciRequires that the bytes length be a multiple of the struct size.
17617db96d56Sopenharmony_ci[clinic start generated code]*/
17627db96d56Sopenharmony_ci
17637db96d56Sopenharmony_cistatic PyObject *
17647db96d56Sopenharmony_ciStruct_iter_unpack(PyStructObject *self, PyObject *buffer)
17657db96d56Sopenharmony_ci/*[clinic end generated code: output=172d83d0cd15dbab input=6d65b3f3107dbc99]*/
17667db96d56Sopenharmony_ci{
17677db96d56Sopenharmony_ci    _structmodulestate *state = get_struct_state_structinst(self);
17687db96d56Sopenharmony_ci    unpackiterobject *iter;
17697db96d56Sopenharmony_ci
17707db96d56Sopenharmony_ci    assert(self->s_codes != NULL);
17717db96d56Sopenharmony_ci
17727db96d56Sopenharmony_ci    if (self->s_size == 0) {
17737db96d56Sopenharmony_ci        PyErr_Format(state->StructError,
17747db96d56Sopenharmony_ci                     "cannot iteratively unpack with a struct of length 0");
17757db96d56Sopenharmony_ci        return NULL;
17767db96d56Sopenharmony_ci    }
17777db96d56Sopenharmony_ci
17787db96d56Sopenharmony_ci    iter = (unpackiterobject *) PyType_GenericAlloc((PyTypeObject *)state->unpackiter_type, 0);
17797db96d56Sopenharmony_ci    if (iter == NULL)
17807db96d56Sopenharmony_ci        return NULL;
17817db96d56Sopenharmony_ci
17827db96d56Sopenharmony_ci    if (PyObject_GetBuffer(buffer, &iter->buf, PyBUF_SIMPLE) < 0) {
17837db96d56Sopenharmony_ci        Py_DECREF(iter);
17847db96d56Sopenharmony_ci        return NULL;
17857db96d56Sopenharmony_ci    }
17867db96d56Sopenharmony_ci    if (iter->buf.len % self->s_size != 0) {
17877db96d56Sopenharmony_ci        PyErr_Format(state->StructError,
17887db96d56Sopenharmony_ci                     "iterative unpacking requires a buffer of "
17897db96d56Sopenharmony_ci                     "a multiple of %zd bytes",
17907db96d56Sopenharmony_ci                     self->s_size);
17917db96d56Sopenharmony_ci        Py_DECREF(iter);
17927db96d56Sopenharmony_ci        return NULL;
17937db96d56Sopenharmony_ci    }
17947db96d56Sopenharmony_ci    Py_INCREF(self);
17957db96d56Sopenharmony_ci    iter->so = self;
17967db96d56Sopenharmony_ci    iter->index = 0;
17977db96d56Sopenharmony_ci    return (PyObject *)iter;
17987db96d56Sopenharmony_ci}
17997db96d56Sopenharmony_ci
18007db96d56Sopenharmony_ci
18017db96d56Sopenharmony_ci/*
18027db96d56Sopenharmony_ci * Guts of the pack function.
18037db96d56Sopenharmony_ci *
18047db96d56Sopenharmony_ci * Takes a struct object, a tuple of arguments, and offset in that tuple of
18057db96d56Sopenharmony_ci * argument for where to start processing the arguments for packing, and a
18067db96d56Sopenharmony_ci * character buffer for writing the packed string.  The caller must insure
18077db96d56Sopenharmony_ci * that the buffer may contain the required length for packing the arguments.
18087db96d56Sopenharmony_ci * 0 is returned on success, 1 is returned if there is an error.
18097db96d56Sopenharmony_ci *
18107db96d56Sopenharmony_ci */
18117db96d56Sopenharmony_cistatic int
18127db96d56Sopenharmony_cis_pack_internal(PyStructObject *soself, PyObject *const *args, int offset,
18137db96d56Sopenharmony_ci                char* buf, _structmodulestate *state)
18147db96d56Sopenharmony_ci{
18157db96d56Sopenharmony_ci    formatcode *code;
18167db96d56Sopenharmony_ci    /* XXX(nnorwitz): why does i need to be a local?  can we use
18177db96d56Sopenharmony_ci       the offset parameter or do we need the wider width? */
18187db96d56Sopenharmony_ci    Py_ssize_t i;
18197db96d56Sopenharmony_ci
18207db96d56Sopenharmony_ci    memset(buf, '\0', soself->s_size);
18217db96d56Sopenharmony_ci    i = offset;
18227db96d56Sopenharmony_ci    for (code = soself->s_codes; code->fmtdef != NULL; code++) {
18237db96d56Sopenharmony_ci        const formatdef *e = code->fmtdef;
18247db96d56Sopenharmony_ci        char *res = buf + code->offset;
18257db96d56Sopenharmony_ci        Py_ssize_t j = code->repeat;
18267db96d56Sopenharmony_ci        while (j--) {
18277db96d56Sopenharmony_ci            PyObject *v = args[i++];
18287db96d56Sopenharmony_ci            if (e->format == 's') {
18297db96d56Sopenharmony_ci                Py_ssize_t n;
18307db96d56Sopenharmony_ci                int isstring;
18317db96d56Sopenharmony_ci                const void *p;
18327db96d56Sopenharmony_ci                isstring = PyBytes_Check(v);
18337db96d56Sopenharmony_ci                if (!isstring && !PyByteArray_Check(v)) {
18347db96d56Sopenharmony_ci                    PyErr_SetString(state->StructError,
18357db96d56Sopenharmony_ci                                    "argument for 's' must be a bytes object");
18367db96d56Sopenharmony_ci                    return -1;
18377db96d56Sopenharmony_ci                }
18387db96d56Sopenharmony_ci                if (isstring) {
18397db96d56Sopenharmony_ci                    n = PyBytes_GET_SIZE(v);
18407db96d56Sopenharmony_ci                    p = PyBytes_AS_STRING(v);
18417db96d56Sopenharmony_ci                }
18427db96d56Sopenharmony_ci                else {
18437db96d56Sopenharmony_ci                    n = PyByteArray_GET_SIZE(v);
18447db96d56Sopenharmony_ci                    p = PyByteArray_AS_STRING(v);
18457db96d56Sopenharmony_ci                }
18467db96d56Sopenharmony_ci                if (n > code->size)
18477db96d56Sopenharmony_ci                    n = code->size;
18487db96d56Sopenharmony_ci                if (n > 0)
18497db96d56Sopenharmony_ci                    memcpy(res, p, n);
18507db96d56Sopenharmony_ci            } else if (e->format == 'p') {
18517db96d56Sopenharmony_ci                Py_ssize_t n;
18527db96d56Sopenharmony_ci                int isstring;
18537db96d56Sopenharmony_ci                const void *p;
18547db96d56Sopenharmony_ci                isstring = PyBytes_Check(v);
18557db96d56Sopenharmony_ci                if (!isstring && !PyByteArray_Check(v)) {
18567db96d56Sopenharmony_ci                    PyErr_SetString(state->StructError,
18577db96d56Sopenharmony_ci                                    "argument for 'p' must be a bytes object");
18587db96d56Sopenharmony_ci                    return -1;
18597db96d56Sopenharmony_ci                }
18607db96d56Sopenharmony_ci                if (isstring) {
18617db96d56Sopenharmony_ci                    n = PyBytes_GET_SIZE(v);
18627db96d56Sopenharmony_ci                    p = PyBytes_AS_STRING(v);
18637db96d56Sopenharmony_ci                }
18647db96d56Sopenharmony_ci                else {
18657db96d56Sopenharmony_ci                    n = PyByteArray_GET_SIZE(v);
18667db96d56Sopenharmony_ci                    p = PyByteArray_AS_STRING(v);
18677db96d56Sopenharmony_ci                }
18687db96d56Sopenharmony_ci                if (n > (code->size - 1))
18697db96d56Sopenharmony_ci                    n = code->size - 1;
18707db96d56Sopenharmony_ci                if (n > 0)
18717db96d56Sopenharmony_ci                    memcpy(res + 1, p, n);
18727db96d56Sopenharmony_ci                if (n > 255)
18737db96d56Sopenharmony_ci                    n = 255;
18747db96d56Sopenharmony_ci                *res = Py_SAFE_DOWNCAST(n, Py_ssize_t, unsigned char);
18757db96d56Sopenharmony_ci            } else {
18767db96d56Sopenharmony_ci                if (e->pack(state, res, v, e) < 0) {
18777db96d56Sopenharmony_ci                    if (PyLong_Check(v) && PyErr_ExceptionMatches(PyExc_OverflowError))
18787db96d56Sopenharmony_ci                        PyErr_SetString(state->StructError,
18797db96d56Sopenharmony_ci                                        "int too large to convert");
18807db96d56Sopenharmony_ci                    return -1;
18817db96d56Sopenharmony_ci                }
18827db96d56Sopenharmony_ci            }
18837db96d56Sopenharmony_ci            res += code->size;
18847db96d56Sopenharmony_ci        }
18857db96d56Sopenharmony_ci    }
18867db96d56Sopenharmony_ci
18877db96d56Sopenharmony_ci    /* Success */
18887db96d56Sopenharmony_ci    return 0;
18897db96d56Sopenharmony_ci}
18907db96d56Sopenharmony_ci
18917db96d56Sopenharmony_ci
18927db96d56Sopenharmony_ciPyDoc_STRVAR(s_pack__doc__,
18937db96d56Sopenharmony_ci"S.pack(v1, v2, ...) -> bytes\n\
18947db96d56Sopenharmony_ci\n\
18957db96d56Sopenharmony_ciReturn a bytes object containing values v1, v2, ... packed according\n\
18967db96d56Sopenharmony_cito the format string S.format.  See help(struct) for more on format\n\
18977db96d56Sopenharmony_cistrings.");
18987db96d56Sopenharmony_ci
18997db96d56Sopenharmony_cistatic PyObject *
19007db96d56Sopenharmony_cis_pack(PyObject *self, PyObject *const *args, Py_ssize_t nargs)
19017db96d56Sopenharmony_ci{
19027db96d56Sopenharmony_ci    char *buf;
19037db96d56Sopenharmony_ci    PyStructObject *soself;
19047db96d56Sopenharmony_ci    _structmodulestate *state = get_struct_state_structinst(self);
19057db96d56Sopenharmony_ci
19067db96d56Sopenharmony_ci    /* Validate arguments. */
19077db96d56Sopenharmony_ci    soself = (PyStructObject *)self;
19087db96d56Sopenharmony_ci    assert(PyStruct_Check(self, state));
19097db96d56Sopenharmony_ci    assert(soself->s_codes != NULL);
19107db96d56Sopenharmony_ci    if (nargs != soself->s_len)
19117db96d56Sopenharmony_ci    {
19127db96d56Sopenharmony_ci        PyErr_Format(state->StructError,
19137db96d56Sopenharmony_ci            "pack expected %zd items for packing (got %zd)", soself->s_len, nargs);
19147db96d56Sopenharmony_ci        return NULL;
19157db96d56Sopenharmony_ci    }
19167db96d56Sopenharmony_ci
19177db96d56Sopenharmony_ci    /* Allocate a new string */
19187db96d56Sopenharmony_ci    _PyBytesWriter writer;
19197db96d56Sopenharmony_ci    _PyBytesWriter_Init(&writer);
19207db96d56Sopenharmony_ci    buf = _PyBytesWriter_Alloc(&writer, soself->s_size);
19217db96d56Sopenharmony_ci    if (buf == NULL) {
19227db96d56Sopenharmony_ci        _PyBytesWriter_Dealloc(&writer);
19237db96d56Sopenharmony_ci        return NULL;
19247db96d56Sopenharmony_ci    }
19257db96d56Sopenharmony_ci
19267db96d56Sopenharmony_ci    /* Call the guts */
19277db96d56Sopenharmony_ci    if ( s_pack_internal(soself, args, 0, buf, state) != 0 ) {
19287db96d56Sopenharmony_ci        _PyBytesWriter_Dealloc(&writer);
19297db96d56Sopenharmony_ci        return NULL;
19307db96d56Sopenharmony_ci    }
19317db96d56Sopenharmony_ci
19327db96d56Sopenharmony_ci    return _PyBytesWriter_Finish(&writer, buf + soself->s_size);
19337db96d56Sopenharmony_ci}
19347db96d56Sopenharmony_ci
19357db96d56Sopenharmony_ciPyDoc_STRVAR(s_pack_into__doc__,
19367db96d56Sopenharmony_ci"S.pack_into(buffer, offset, v1, v2, ...)\n\
19377db96d56Sopenharmony_ci\n\
19387db96d56Sopenharmony_ciPack the values v1, v2, ... according to the format string S.format\n\
19397db96d56Sopenharmony_ciand write the packed bytes into the writable buffer buf starting at\n\
19407db96d56Sopenharmony_cioffset.  Note that the offset is a required argument.  See\n\
19417db96d56Sopenharmony_cihelp(struct) for more on format strings.");
19427db96d56Sopenharmony_ci
19437db96d56Sopenharmony_cistatic PyObject *
19447db96d56Sopenharmony_cis_pack_into(PyObject *self, PyObject *const *args, Py_ssize_t nargs)
19457db96d56Sopenharmony_ci{
19467db96d56Sopenharmony_ci    PyStructObject *soself;
19477db96d56Sopenharmony_ci    Py_buffer buffer;
19487db96d56Sopenharmony_ci    Py_ssize_t offset;
19497db96d56Sopenharmony_ci    _structmodulestate *state = get_struct_state_structinst(self);
19507db96d56Sopenharmony_ci
19517db96d56Sopenharmony_ci    /* Validate arguments.  +1 is for the first arg as buffer. */
19527db96d56Sopenharmony_ci    soself = (PyStructObject *)self;
19537db96d56Sopenharmony_ci    assert(PyStruct_Check(self, state));
19547db96d56Sopenharmony_ci    assert(soself->s_codes != NULL);
19557db96d56Sopenharmony_ci    if (nargs != (soself->s_len + 2))
19567db96d56Sopenharmony_ci    {
19577db96d56Sopenharmony_ci        if (nargs == 0) {
19587db96d56Sopenharmony_ci            PyErr_Format(state->StructError,
19597db96d56Sopenharmony_ci                        "pack_into expected buffer argument");
19607db96d56Sopenharmony_ci        }
19617db96d56Sopenharmony_ci        else if (nargs == 1) {
19627db96d56Sopenharmony_ci            PyErr_Format(state->StructError,
19637db96d56Sopenharmony_ci                        "pack_into expected offset argument");
19647db96d56Sopenharmony_ci        }
19657db96d56Sopenharmony_ci        else {
19667db96d56Sopenharmony_ci            PyErr_Format(state->StructError,
19677db96d56Sopenharmony_ci                        "pack_into expected %zd items for packing (got %zd)",
19687db96d56Sopenharmony_ci                        soself->s_len, (nargs - 2));
19697db96d56Sopenharmony_ci        }
19707db96d56Sopenharmony_ci        return NULL;
19717db96d56Sopenharmony_ci    }
19727db96d56Sopenharmony_ci
19737db96d56Sopenharmony_ci    /* Extract a writable memory buffer from the first argument */
19747db96d56Sopenharmony_ci    if (!PyArg_Parse(args[0], "w*", &buffer))
19757db96d56Sopenharmony_ci        return NULL;
19767db96d56Sopenharmony_ci    assert(buffer.len >= 0);
19777db96d56Sopenharmony_ci
19787db96d56Sopenharmony_ci    /* Extract the offset from the first argument */
19797db96d56Sopenharmony_ci    offset = PyNumber_AsSsize_t(args[1], PyExc_IndexError);
19807db96d56Sopenharmony_ci    if (offset == -1 && PyErr_Occurred()) {
19817db96d56Sopenharmony_ci        PyBuffer_Release(&buffer);
19827db96d56Sopenharmony_ci        return NULL;
19837db96d56Sopenharmony_ci    }
19847db96d56Sopenharmony_ci
19857db96d56Sopenharmony_ci    /* Support negative offsets. */
19867db96d56Sopenharmony_ci    if (offset < 0) {
19877db96d56Sopenharmony_ci         /* Check that negative offset is low enough to fit data */
19887db96d56Sopenharmony_ci        if (offset + soself->s_size > 0) {
19897db96d56Sopenharmony_ci            PyErr_Format(state->StructError,
19907db96d56Sopenharmony_ci                         "no space to pack %zd bytes at offset %zd",
19917db96d56Sopenharmony_ci                         soself->s_size,
19927db96d56Sopenharmony_ci                         offset);
19937db96d56Sopenharmony_ci            PyBuffer_Release(&buffer);
19947db96d56Sopenharmony_ci            return NULL;
19957db96d56Sopenharmony_ci        }
19967db96d56Sopenharmony_ci
19977db96d56Sopenharmony_ci        /* Check that negative offset is not crossing buffer boundary */
19987db96d56Sopenharmony_ci        if (offset + buffer.len < 0) {
19997db96d56Sopenharmony_ci            PyErr_Format(state->StructError,
20007db96d56Sopenharmony_ci                         "offset %zd out of range for %zd-byte buffer",
20017db96d56Sopenharmony_ci                         offset,
20027db96d56Sopenharmony_ci                         buffer.len);
20037db96d56Sopenharmony_ci            PyBuffer_Release(&buffer);
20047db96d56Sopenharmony_ci            return NULL;
20057db96d56Sopenharmony_ci        }
20067db96d56Sopenharmony_ci
20077db96d56Sopenharmony_ci        offset += buffer.len;
20087db96d56Sopenharmony_ci    }
20097db96d56Sopenharmony_ci
20107db96d56Sopenharmony_ci    /* Check boundaries */
20117db96d56Sopenharmony_ci    if ((buffer.len - offset) < soself->s_size) {
20127db96d56Sopenharmony_ci        assert(offset >= 0);
20137db96d56Sopenharmony_ci        assert(soself->s_size >= 0);
20147db96d56Sopenharmony_ci
20157db96d56Sopenharmony_ci        PyErr_Format(state->StructError,
20167db96d56Sopenharmony_ci                     "pack_into requires a buffer of at least %zu bytes for "
20177db96d56Sopenharmony_ci                     "packing %zd bytes at offset %zd "
20187db96d56Sopenharmony_ci                     "(actual buffer size is %zd)",
20197db96d56Sopenharmony_ci                     (size_t)soself->s_size + (size_t)offset,
20207db96d56Sopenharmony_ci                     soself->s_size,
20217db96d56Sopenharmony_ci                     offset,
20227db96d56Sopenharmony_ci                     buffer.len);
20237db96d56Sopenharmony_ci        PyBuffer_Release(&buffer);
20247db96d56Sopenharmony_ci        return NULL;
20257db96d56Sopenharmony_ci    }
20267db96d56Sopenharmony_ci
20277db96d56Sopenharmony_ci    /* Call the guts */
20287db96d56Sopenharmony_ci    if (s_pack_internal(soself, args, 2, (char*)buffer.buf + offset, state) != 0) {
20297db96d56Sopenharmony_ci        PyBuffer_Release(&buffer);
20307db96d56Sopenharmony_ci        return NULL;
20317db96d56Sopenharmony_ci    }
20327db96d56Sopenharmony_ci
20337db96d56Sopenharmony_ci    PyBuffer_Release(&buffer);
20347db96d56Sopenharmony_ci    Py_RETURN_NONE;
20357db96d56Sopenharmony_ci}
20367db96d56Sopenharmony_ci
20377db96d56Sopenharmony_cistatic PyObject *
20387db96d56Sopenharmony_cis_get_format(PyStructObject *self, void *unused)
20397db96d56Sopenharmony_ci{
20407db96d56Sopenharmony_ci    return PyUnicode_FromStringAndSize(PyBytes_AS_STRING(self->s_format),
20417db96d56Sopenharmony_ci                                       PyBytes_GET_SIZE(self->s_format));
20427db96d56Sopenharmony_ci}
20437db96d56Sopenharmony_ci
20447db96d56Sopenharmony_cistatic PyObject *
20457db96d56Sopenharmony_cis_get_size(PyStructObject *self, void *unused)
20467db96d56Sopenharmony_ci{
20477db96d56Sopenharmony_ci    return PyLong_FromSsize_t(self->s_size);
20487db96d56Sopenharmony_ci}
20497db96d56Sopenharmony_ci
20507db96d56Sopenharmony_ciPyDoc_STRVAR(s_sizeof__doc__,
20517db96d56Sopenharmony_ci"S.__sizeof__() -> size of S in memory, in bytes");
20527db96d56Sopenharmony_ci
20537db96d56Sopenharmony_cistatic PyObject *
20547db96d56Sopenharmony_cis_sizeof(PyStructObject *self, void *unused)
20557db96d56Sopenharmony_ci{
20567db96d56Sopenharmony_ci    Py_ssize_t size;
20577db96d56Sopenharmony_ci    formatcode *code;
20587db96d56Sopenharmony_ci
20597db96d56Sopenharmony_ci    size = _PyObject_SIZE(Py_TYPE(self)) + sizeof(formatcode);
20607db96d56Sopenharmony_ci    for (code = self->s_codes; code->fmtdef != NULL; code++)
20617db96d56Sopenharmony_ci        size += sizeof(formatcode);
20627db96d56Sopenharmony_ci    return PyLong_FromSsize_t(size);
20637db96d56Sopenharmony_ci}
20647db96d56Sopenharmony_ci
20657db96d56Sopenharmony_ci/* List of functions */
20667db96d56Sopenharmony_ci
20677db96d56Sopenharmony_cistatic struct PyMethodDef s_methods[] = {
20687db96d56Sopenharmony_ci    STRUCT_ITER_UNPACK_METHODDEF
20697db96d56Sopenharmony_ci    {"pack",            _PyCFunction_CAST(s_pack), METH_FASTCALL, s_pack__doc__},
20707db96d56Sopenharmony_ci    {"pack_into",       _PyCFunction_CAST(s_pack_into), METH_FASTCALL, s_pack_into__doc__},
20717db96d56Sopenharmony_ci    STRUCT_UNPACK_METHODDEF
20727db96d56Sopenharmony_ci    STRUCT_UNPACK_FROM_METHODDEF
20737db96d56Sopenharmony_ci    {"__sizeof__",      (PyCFunction)s_sizeof, METH_NOARGS, s_sizeof__doc__},
20747db96d56Sopenharmony_ci    {NULL,       NULL}          /* sentinel */
20757db96d56Sopenharmony_ci};
20767db96d56Sopenharmony_ci
20777db96d56Sopenharmony_cistatic PyMemberDef s_members[] = {
20787db96d56Sopenharmony_ci    {"__weaklistoffset__", T_PYSSIZET, offsetof(PyStructObject, weakreflist), READONLY},
20797db96d56Sopenharmony_ci    {NULL}  /* sentinel */
20807db96d56Sopenharmony_ci};
20817db96d56Sopenharmony_ci
20827db96d56Sopenharmony_cistatic PyGetSetDef s_getsetlist[] = {
20837db96d56Sopenharmony_ci    {"format", (getter)s_get_format, (setter)NULL, "struct format string", NULL},
20847db96d56Sopenharmony_ci    {"size", (getter)s_get_size, (setter)NULL, "struct size in bytes", NULL},
20857db96d56Sopenharmony_ci    {NULL} /* sentinel */
20867db96d56Sopenharmony_ci};
20877db96d56Sopenharmony_ci
20887db96d56Sopenharmony_ciPyDoc_STRVAR(s__doc__,
20897db96d56Sopenharmony_ci"Struct(fmt) --> compiled struct object\n"
20907db96d56Sopenharmony_ci"\n"
20917db96d56Sopenharmony_ci);
20927db96d56Sopenharmony_ci
20937db96d56Sopenharmony_cistatic PyType_Slot PyStructType_slots[] = {
20947db96d56Sopenharmony_ci    {Py_tp_dealloc, s_dealloc},
20957db96d56Sopenharmony_ci    {Py_tp_getattro, PyObject_GenericGetAttr},
20967db96d56Sopenharmony_ci    {Py_tp_setattro, PyObject_GenericSetAttr},
20977db96d56Sopenharmony_ci    {Py_tp_doc, (void*)s__doc__},
20987db96d56Sopenharmony_ci    {Py_tp_traverse, s_traverse},
20997db96d56Sopenharmony_ci    {Py_tp_clear, s_clear},
21007db96d56Sopenharmony_ci    {Py_tp_methods, s_methods},
21017db96d56Sopenharmony_ci    {Py_tp_members, s_members},
21027db96d56Sopenharmony_ci    {Py_tp_getset, s_getsetlist},
21037db96d56Sopenharmony_ci    {Py_tp_init, Struct___init__},
21047db96d56Sopenharmony_ci    {Py_tp_alloc, PyType_GenericAlloc},
21057db96d56Sopenharmony_ci    {Py_tp_new, s_new},
21067db96d56Sopenharmony_ci    {Py_tp_free, PyObject_GC_Del},
21077db96d56Sopenharmony_ci    {0, 0},
21087db96d56Sopenharmony_ci};
21097db96d56Sopenharmony_ci
21107db96d56Sopenharmony_cistatic PyType_Spec PyStructType_spec = {
21117db96d56Sopenharmony_ci    "_struct.Struct",
21127db96d56Sopenharmony_ci    sizeof(PyStructObject),
21137db96d56Sopenharmony_ci    0,
21147db96d56Sopenharmony_ci    (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |
21157db96d56Sopenharmony_ci     Py_TPFLAGS_BASETYPE | Py_TPFLAGS_IMMUTABLETYPE),
21167db96d56Sopenharmony_ci    PyStructType_slots
21177db96d56Sopenharmony_ci};
21187db96d56Sopenharmony_ci
21197db96d56Sopenharmony_ci
21207db96d56Sopenharmony_ci/* ---- Standalone functions  ---- */
21217db96d56Sopenharmony_ci
21227db96d56Sopenharmony_ci#define MAXCACHE 100
21237db96d56Sopenharmony_ci
21247db96d56Sopenharmony_cistatic int
21257db96d56Sopenharmony_cicache_struct_converter(PyObject *module, PyObject *fmt, PyStructObject **ptr)
21267db96d56Sopenharmony_ci{
21277db96d56Sopenharmony_ci    PyObject * s_object;
21287db96d56Sopenharmony_ci    _structmodulestate *state = get_struct_state(module);
21297db96d56Sopenharmony_ci
21307db96d56Sopenharmony_ci    if (fmt == NULL) {
21317db96d56Sopenharmony_ci        Py_DECREF(*ptr);
21327db96d56Sopenharmony_ci        *ptr = NULL;
21337db96d56Sopenharmony_ci        return 1;
21347db96d56Sopenharmony_ci    }
21357db96d56Sopenharmony_ci
21367db96d56Sopenharmony_ci    if (state->cache == NULL) {
21377db96d56Sopenharmony_ci        state->cache = PyDict_New();
21387db96d56Sopenharmony_ci        if (state->cache == NULL)
21397db96d56Sopenharmony_ci            return 0;
21407db96d56Sopenharmony_ci    }
21417db96d56Sopenharmony_ci
21427db96d56Sopenharmony_ci    s_object = PyDict_GetItemWithError(state->cache, fmt);
21437db96d56Sopenharmony_ci    if (s_object != NULL) {
21447db96d56Sopenharmony_ci        Py_INCREF(s_object);
21457db96d56Sopenharmony_ci        *ptr = (PyStructObject *)s_object;
21467db96d56Sopenharmony_ci        return Py_CLEANUP_SUPPORTED;
21477db96d56Sopenharmony_ci    }
21487db96d56Sopenharmony_ci    else if (PyErr_Occurred()) {
21497db96d56Sopenharmony_ci        return 0;
21507db96d56Sopenharmony_ci    }
21517db96d56Sopenharmony_ci
21527db96d56Sopenharmony_ci    s_object = PyObject_CallOneArg(state->PyStructType, fmt);
21537db96d56Sopenharmony_ci    if (s_object != NULL) {
21547db96d56Sopenharmony_ci        if (PyDict_GET_SIZE(state->cache) >= MAXCACHE)
21557db96d56Sopenharmony_ci            PyDict_Clear(state->cache);
21567db96d56Sopenharmony_ci        /* Attempt to cache the result */
21577db96d56Sopenharmony_ci        if (PyDict_SetItem(state->cache, fmt, s_object) == -1)
21587db96d56Sopenharmony_ci            PyErr_Clear();
21597db96d56Sopenharmony_ci        *ptr = (PyStructObject *)s_object;
21607db96d56Sopenharmony_ci        return Py_CLEANUP_SUPPORTED;
21617db96d56Sopenharmony_ci    }
21627db96d56Sopenharmony_ci    return 0;
21637db96d56Sopenharmony_ci}
21647db96d56Sopenharmony_ci
21657db96d56Sopenharmony_ci/*[clinic input]
21667db96d56Sopenharmony_ci_clearcache
21677db96d56Sopenharmony_ci
21687db96d56Sopenharmony_ciClear the internal cache.
21697db96d56Sopenharmony_ci[clinic start generated code]*/
21707db96d56Sopenharmony_ci
21717db96d56Sopenharmony_cistatic PyObject *
21727db96d56Sopenharmony_ci_clearcache_impl(PyObject *module)
21737db96d56Sopenharmony_ci/*[clinic end generated code: output=ce4fb8a7bf7cb523 input=463eaae04bab3211]*/
21747db96d56Sopenharmony_ci{
21757db96d56Sopenharmony_ci    Py_CLEAR(get_struct_state(module)->cache);
21767db96d56Sopenharmony_ci    Py_RETURN_NONE;
21777db96d56Sopenharmony_ci}
21787db96d56Sopenharmony_ci
21797db96d56Sopenharmony_ci
21807db96d56Sopenharmony_ci/*[clinic input]
21817db96d56Sopenharmony_cicalcsize -> Py_ssize_t
21827db96d56Sopenharmony_ci
21837db96d56Sopenharmony_ci    format as s_object: cache_struct
21847db96d56Sopenharmony_ci    /
21857db96d56Sopenharmony_ci
21867db96d56Sopenharmony_ciReturn size in bytes of the struct described by the format string.
21877db96d56Sopenharmony_ci[clinic start generated code]*/
21887db96d56Sopenharmony_ci
21897db96d56Sopenharmony_cistatic Py_ssize_t
21907db96d56Sopenharmony_cicalcsize_impl(PyObject *module, PyStructObject *s_object)
21917db96d56Sopenharmony_ci/*[clinic end generated code: output=db7d23d09c6932c4 input=96a6a590c7717ecd]*/
21927db96d56Sopenharmony_ci{
21937db96d56Sopenharmony_ci    return s_object->s_size;
21947db96d56Sopenharmony_ci}
21957db96d56Sopenharmony_ci
21967db96d56Sopenharmony_ciPyDoc_STRVAR(pack_doc,
21977db96d56Sopenharmony_ci"pack(format, v1, v2, ...) -> bytes\n\
21987db96d56Sopenharmony_ci\n\
21997db96d56Sopenharmony_ciReturn a bytes object containing the values v1, v2, ... packed according\n\
22007db96d56Sopenharmony_cito the format string.  See help(struct) for more on format strings.");
22017db96d56Sopenharmony_ci
22027db96d56Sopenharmony_cistatic PyObject *
22037db96d56Sopenharmony_cipack(PyObject *module, PyObject *const *args, Py_ssize_t nargs)
22047db96d56Sopenharmony_ci{
22057db96d56Sopenharmony_ci    PyObject *s_object = NULL;
22067db96d56Sopenharmony_ci    PyObject *format, *result;
22077db96d56Sopenharmony_ci
22087db96d56Sopenharmony_ci    if (nargs == 0) {
22097db96d56Sopenharmony_ci        PyErr_SetString(PyExc_TypeError, "missing format argument");
22107db96d56Sopenharmony_ci        return NULL;
22117db96d56Sopenharmony_ci    }
22127db96d56Sopenharmony_ci    format = args[0];
22137db96d56Sopenharmony_ci
22147db96d56Sopenharmony_ci    if (!cache_struct_converter(module, format, (PyStructObject **)&s_object)) {
22157db96d56Sopenharmony_ci        return NULL;
22167db96d56Sopenharmony_ci    }
22177db96d56Sopenharmony_ci    result = s_pack(s_object, args + 1, nargs - 1);
22187db96d56Sopenharmony_ci    Py_DECREF(s_object);
22197db96d56Sopenharmony_ci    return result;
22207db96d56Sopenharmony_ci}
22217db96d56Sopenharmony_ci
22227db96d56Sopenharmony_ciPyDoc_STRVAR(pack_into_doc,
22237db96d56Sopenharmony_ci"pack_into(format, buffer, offset, v1, v2, ...)\n\
22247db96d56Sopenharmony_ci\n\
22257db96d56Sopenharmony_ciPack the values v1, v2, ... according to the format string and write\n\
22267db96d56Sopenharmony_cithe packed bytes into the writable buffer buf starting at offset.  Note\n\
22277db96d56Sopenharmony_cithat the offset is a required argument.  See help(struct) for more\n\
22287db96d56Sopenharmony_cion format strings.");
22297db96d56Sopenharmony_ci
22307db96d56Sopenharmony_cistatic PyObject *
22317db96d56Sopenharmony_cipack_into(PyObject *module, PyObject *const *args, Py_ssize_t nargs)
22327db96d56Sopenharmony_ci{
22337db96d56Sopenharmony_ci    PyObject *s_object = NULL;
22347db96d56Sopenharmony_ci    PyObject *format, *result;
22357db96d56Sopenharmony_ci
22367db96d56Sopenharmony_ci    if (nargs == 0) {
22377db96d56Sopenharmony_ci        PyErr_SetString(PyExc_TypeError, "missing format argument");
22387db96d56Sopenharmony_ci        return NULL;
22397db96d56Sopenharmony_ci    }
22407db96d56Sopenharmony_ci    format = args[0];
22417db96d56Sopenharmony_ci
22427db96d56Sopenharmony_ci    if (!cache_struct_converter(module, format, (PyStructObject **)&s_object)) {
22437db96d56Sopenharmony_ci        return NULL;
22447db96d56Sopenharmony_ci    }
22457db96d56Sopenharmony_ci    result = s_pack_into(s_object, args + 1, nargs - 1);
22467db96d56Sopenharmony_ci    Py_DECREF(s_object);
22477db96d56Sopenharmony_ci    return result;
22487db96d56Sopenharmony_ci}
22497db96d56Sopenharmony_ci
22507db96d56Sopenharmony_ci/*[clinic input]
22517db96d56Sopenharmony_ciunpack
22527db96d56Sopenharmony_ci
22537db96d56Sopenharmony_ci    format as s_object: cache_struct
22547db96d56Sopenharmony_ci    buffer: Py_buffer
22557db96d56Sopenharmony_ci    /
22567db96d56Sopenharmony_ci
22577db96d56Sopenharmony_ciReturn a tuple containing values unpacked according to the format string.
22587db96d56Sopenharmony_ci
22597db96d56Sopenharmony_ciThe buffer's size in bytes must be calcsize(format).
22607db96d56Sopenharmony_ci
22617db96d56Sopenharmony_ciSee help(struct) for more on format strings.
22627db96d56Sopenharmony_ci[clinic start generated code]*/
22637db96d56Sopenharmony_ci
22647db96d56Sopenharmony_cistatic PyObject *
22657db96d56Sopenharmony_ciunpack_impl(PyObject *module, PyStructObject *s_object, Py_buffer *buffer)
22667db96d56Sopenharmony_ci/*[clinic end generated code: output=48ddd4d88eca8551 input=05fa3b91678da727]*/
22677db96d56Sopenharmony_ci{
22687db96d56Sopenharmony_ci    return Struct_unpack_impl(s_object, buffer);
22697db96d56Sopenharmony_ci}
22707db96d56Sopenharmony_ci
22717db96d56Sopenharmony_ci/*[clinic input]
22727db96d56Sopenharmony_ciunpack_from
22737db96d56Sopenharmony_ci
22747db96d56Sopenharmony_ci    format as s_object: cache_struct
22757db96d56Sopenharmony_ci    /
22767db96d56Sopenharmony_ci    buffer: Py_buffer
22777db96d56Sopenharmony_ci    offset: Py_ssize_t = 0
22787db96d56Sopenharmony_ci
22797db96d56Sopenharmony_ciReturn a tuple containing values unpacked according to the format string.
22807db96d56Sopenharmony_ci
22817db96d56Sopenharmony_ciThe buffer's size, minus offset, must be at least calcsize(format).
22827db96d56Sopenharmony_ci
22837db96d56Sopenharmony_ciSee help(struct) for more on format strings.
22847db96d56Sopenharmony_ci[clinic start generated code]*/
22857db96d56Sopenharmony_ci
22867db96d56Sopenharmony_cistatic PyObject *
22877db96d56Sopenharmony_ciunpack_from_impl(PyObject *module, PyStructObject *s_object,
22887db96d56Sopenharmony_ci                 Py_buffer *buffer, Py_ssize_t offset)
22897db96d56Sopenharmony_ci/*[clinic end generated code: output=1042631674c6e0d3 input=6e80a5398e985025]*/
22907db96d56Sopenharmony_ci{
22917db96d56Sopenharmony_ci    return Struct_unpack_from_impl(s_object, buffer, offset);
22927db96d56Sopenharmony_ci}
22937db96d56Sopenharmony_ci
22947db96d56Sopenharmony_ci/*[clinic input]
22957db96d56Sopenharmony_ciiter_unpack
22967db96d56Sopenharmony_ci
22977db96d56Sopenharmony_ci    format as s_object: cache_struct
22987db96d56Sopenharmony_ci    buffer: object
22997db96d56Sopenharmony_ci    /
23007db96d56Sopenharmony_ci
23017db96d56Sopenharmony_ciReturn an iterator yielding tuples unpacked from the given bytes.
23027db96d56Sopenharmony_ci
23037db96d56Sopenharmony_ciThe bytes are unpacked according to the format string, like
23047db96d56Sopenharmony_cia repeated invocation of unpack_from().
23057db96d56Sopenharmony_ci
23067db96d56Sopenharmony_ciRequires that the bytes length be a multiple of the format struct size.
23077db96d56Sopenharmony_ci[clinic start generated code]*/
23087db96d56Sopenharmony_ci
23097db96d56Sopenharmony_cistatic PyObject *
23107db96d56Sopenharmony_ciiter_unpack_impl(PyObject *module, PyStructObject *s_object,
23117db96d56Sopenharmony_ci                 PyObject *buffer)
23127db96d56Sopenharmony_ci/*[clinic end generated code: output=0ae50e250d20e74d input=b214a58869a3c98d]*/
23137db96d56Sopenharmony_ci{
23147db96d56Sopenharmony_ci    return Struct_iter_unpack(s_object, buffer);
23157db96d56Sopenharmony_ci}
23167db96d56Sopenharmony_ci
23177db96d56Sopenharmony_cistatic struct PyMethodDef module_functions[] = {
23187db96d56Sopenharmony_ci    _CLEARCACHE_METHODDEF
23197db96d56Sopenharmony_ci    CALCSIZE_METHODDEF
23207db96d56Sopenharmony_ci    ITER_UNPACK_METHODDEF
23217db96d56Sopenharmony_ci    {"pack",            _PyCFunction_CAST(pack), METH_FASTCALL,   pack_doc},
23227db96d56Sopenharmony_ci    {"pack_into",       _PyCFunction_CAST(pack_into), METH_FASTCALL,   pack_into_doc},
23237db96d56Sopenharmony_ci    UNPACK_METHODDEF
23247db96d56Sopenharmony_ci    UNPACK_FROM_METHODDEF
23257db96d56Sopenharmony_ci    {NULL,       NULL}          /* sentinel */
23267db96d56Sopenharmony_ci};
23277db96d56Sopenharmony_ci
23287db96d56Sopenharmony_ci
23297db96d56Sopenharmony_ci/* Module initialization */
23307db96d56Sopenharmony_ci
23317db96d56Sopenharmony_ciPyDoc_STRVAR(module_doc,
23327db96d56Sopenharmony_ci"Functions to convert between Python values and C structs.\n\
23337db96d56Sopenharmony_ciPython bytes objects are used to hold the data representing the C struct\n\
23347db96d56Sopenharmony_ciand also as format strings (explained below) to describe the layout of data\n\
23357db96d56Sopenharmony_ciin the C struct.\n\
23367db96d56Sopenharmony_ci\n\
23377db96d56Sopenharmony_ciThe optional first format char indicates byte order, size and alignment:\n\
23387db96d56Sopenharmony_ci  @: native order, size & alignment (default)\n\
23397db96d56Sopenharmony_ci  =: native order, std. size & alignment\n\
23407db96d56Sopenharmony_ci  <: little-endian, std. size & alignment\n\
23417db96d56Sopenharmony_ci  >: big-endian, std. size & alignment\n\
23427db96d56Sopenharmony_ci  !: same as >\n\
23437db96d56Sopenharmony_ci\n\
23447db96d56Sopenharmony_ciThe remaining chars indicate types of args and must match exactly;\n\
23457db96d56Sopenharmony_cithese can be preceded by a decimal repeat count:\n\
23467db96d56Sopenharmony_ci  x: pad byte (no data); c:char; b:signed byte; B:unsigned byte;\n\
23477db96d56Sopenharmony_ci  ?: _Bool (requires C99; if not available, char is used instead)\n\
23487db96d56Sopenharmony_ci  h:short; H:unsigned short; i:int; I:unsigned int;\n\
23497db96d56Sopenharmony_ci  l:long; L:unsigned long; f:float; d:double; e:half-float.\n\
23507db96d56Sopenharmony_ciSpecial cases (preceding decimal count indicates length):\n\
23517db96d56Sopenharmony_ci  s:string (array of char); p: pascal string (with count byte).\n\
23527db96d56Sopenharmony_ciSpecial cases (only available in native format):\n\
23537db96d56Sopenharmony_ci  n:ssize_t; N:size_t;\n\
23547db96d56Sopenharmony_ci  P:an integer type that is wide enough to hold a pointer.\n\
23557db96d56Sopenharmony_ciSpecial case (not in native mode unless 'long long' in platform C):\n\
23567db96d56Sopenharmony_ci  q:long long; Q:unsigned long long\n\
23577db96d56Sopenharmony_ciWhitespace between formats is ignored.\n\
23587db96d56Sopenharmony_ci\n\
23597db96d56Sopenharmony_ciThe variable struct.error is an exception raised on errors.\n");
23607db96d56Sopenharmony_ci
23617db96d56Sopenharmony_ci
23627db96d56Sopenharmony_cistatic int
23637db96d56Sopenharmony_ci_structmodule_traverse(PyObject *module, visitproc visit, void *arg)
23647db96d56Sopenharmony_ci{
23657db96d56Sopenharmony_ci    _structmodulestate *state = get_struct_state(module);
23667db96d56Sopenharmony_ci    if (state) {
23677db96d56Sopenharmony_ci        Py_VISIT(state->cache);
23687db96d56Sopenharmony_ci        Py_VISIT(state->PyStructType);
23697db96d56Sopenharmony_ci        Py_VISIT(state->unpackiter_type);
23707db96d56Sopenharmony_ci        Py_VISIT(state->StructError);
23717db96d56Sopenharmony_ci    }
23727db96d56Sopenharmony_ci    return 0;
23737db96d56Sopenharmony_ci}
23747db96d56Sopenharmony_ci
23757db96d56Sopenharmony_cistatic int
23767db96d56Sopenharmony_ci_structmodule_clear(PyObject *module)
23777db96d56Sopenharmony_ci{
23787db96d56Sopenharmony_ci    _structmodulestate *state = get_struct_state(module);
23797db96d56Sopenharmony_ci    if (state) {
23807db96d56Sopenharmony_ci        Py_CLEAR(state->cache);
23817db96d56Sopenharmony_ci        Py_CLEAR(state->PyStructType);
23827db96d56Sopenharmony_ci        Py_CLEAR(state->unpackiter_type);
23837db96d56Sopenharmony_ci        Py_CLEAR(state->StructError);
23847db96d56Sopenharmony_ci    }
23857db96d56Sopenharmony_ci    return 0;
23867db96d56Sopenharmony_ci}
23877db96d56Sopenharmony_ci
23887db96d56Sopenharmony_cistatic void
23897db96d56Sopenharmony_ci_structmodule_free(void *module)
23907db96d56Sopenharmony_ci{
23917db96d56Sopenharmony_ci    _structmodule_clear((PyObject *)module);
23927db96d56Sopenharmony_ci}
23937db96d56Sopenharmony_ci
23947db96d56Sopenharmony_cistatic int
23957db96d56Sopenharmony_ci_structmodule_exec(PyObject *m)
23967db96d56Sopenharmony_ci{
23977db96d56Sopenharmony_ci    _structmodulestate *state = get_struct_state(m);
23987db96d56Sopenharmony_ci
23997db96d56Sopenharmony_ci    state->PyStructType = PyType_FromModuleAndSpec(
24007db96d56Sopenharmony_ci        m, &PyStructType_spec, NULL);
24017db96d56Sopenharmony_ci    if (state->PyStructType == NULL) {
24027db96d56Sopenharmony_ci        return -1;
24037db96d56Sopenharmony_ci    }
24047db96d56Sopenharmony_ci    if (PyModule_AddType(m, (PyTypeObject *)state->PyStructType) < 0) {
24057db96d56Sopenharmony_ci        return -1;
24067db96d56Sopenharmony_ci    }
24077db96d56Sopenharmony_ci
24087db96d56Sopenharmony_ci    state->unpackiter_type = PyType_FromModuleAndSpec(
24097db96d56Sopenharmony_ci        m, &unpackiter_type_spec, NULL);
24107db96d56Sopenharmony_ci    if (state->unpackiter_type == NULL) {
24117db96d56Sopenharmony_ci        return -1;
24127db96d56Sopenharmony_ci    }
24137db96d56Sopenharmony_ci
24147db96d56Sopenharmony_ci    /* Check endian and swap in faster functions */
24157db96d56Sopenharmony_ci    {
24167db96d56Sopenharmony_ci        const formatdef *native = native_table;
24177db96d56Sopenharmony_ci        formatdef *other, *ptr;
24187db96d56Sopenharmony_ci#if PY_LITTLE_ENDIAN
24197db96d56Sopenharmony_ci        other = lilendian_table;
24207db96d56Sopenharmony_ci#else
24217db96d56Sopenharmony_ci        other = bigendian_table;
24227db96d56Sopenharmony_ci#endif
24237db96d56Sopenharmony_ci        /* Scan through the native table, find a matching
24247db96d56Sopenharmony_ci           entry in the endian table and swap in the
24257db96d56Sopenharmony_ci           native implementations whenever possible
24267db96d56Sopenharmony_ci           (64-bit platforms may not have "standard" sizes) */
24277db96d56Sopenharmony_ci        while (native->format != '\0' && other->format != '\0') {
24287db96d56Sopenharmony_ci            ptr = other;
24297db96d56Sopenharmony_ci            while (ptr->format != '\0') {
24307db96d56Sopenharmony_ci                if (ptr->format == native->format) {
24317db96d56Sopenharmony_ci                    /* Match faster when formats are
24327db96d56Sopenharmony_ci                       listed in the same order */
24337db96d56Sopenharmony_ci                    if (ptr == other)
24347db96d56Sopenharmony_ci                        other++;
24357db96d56Sopenharmony_ci                    /* Only use the trick if the
24367db96d56Sopenharmony_ci                       size matches */
24377db96d56Sopenharmony_ci                    if (ptr->size != native->size)
24387db96d56Sopenharmony_ci                        break;
24397db96d56Sopenharmony_ci                    /* Skip float and double, could be
24407db96d56Sopenharmony_ci                       "unknown" float format */
24417db96d56Sopenharmony_ci                    if (ptr->format == 'd' || ptr->format == 'f')
24427db96d56Sopenharmony_ci                        break;
24437db96d56Sopenharmony_ci                    /* Skip _Bool, semantics are different for standard size */
24447db96d56Sopenharmony_ci                    if (ptr->format == '?')
24457db96d56Sopenharmony_ci                        break;
24467db96d56Sopenharmony_ci                    ptr->pack = native->pack;
24477db96d56Sopenharmony_ci                    ptr->unpack = native->unpack;
24487db96d56Sopenharmony_ci                    break;
24497db96d56Sopenharmony_ci                }
24507db96d56Sopenharmony_ci                ptr++;
24517db96d56Sopenharmony_ci            }
24527db96d56Sopenharmony_ci            native++;
24537db96d56Sopenharmony_ci        }
24547db96d56Sopenharmony_ci    }
24557db96d56Sopenharmony_ci
24567db96d56Sopenharmony_ci    /* Add some symbolic constants to the module */
24577db96d56Sopenharmony_ci    state->StructError = PyErr_NewException("struct.error", NULL, NULL);
24587db96d56Sopenharmony_ci    if (state->StructError == NULL) {
24597db96d56Sopenharmony_ci        return -1;
24607db96d56Sopenharmony_ci    }
24617db96d56Sopenharmony_ci    if (PyModule_AddObjectRef(m, "error", state->StructError) < 0) {
24627db96d56Sopenharmony_ci        return -1;
24637db96d56Sopenharmony_ci    }
24647db96d56Sopenharmony_ci
24657db96d56Sopenharmony_ci    return 0;
24667db96d56Sopenharmony_ci}
24677db96d56Sopenharmony_ci
24687db96d56Sopenharmony_cistatic PyModuleDef_Slot _structmodule_slots[] = {
24697db96d56Sopenharmony_ci    {Py_mod_exec, _structmodule_exec},
24707db96d56Sopenharmony_ci    {0, NULL}
24717db96d56Sopenharmony_ci};
24727db96d56Sopenharmony_ci
24737db96d56Sopenharmony_cistatic struct PyModuleDef _structmodule = {
24747db96d56Sopenharmony_ci    PyModuleDef_HEAD_INIT,
24757db96d56Sopenharmony_ci    .m_name = "_struct",
24767db96d56Sopenharmony_ci    .m_doc = module_doc,
24777db96d56Sopenharmony_ci    .m_size = sizeof(_structmodulestate),
24787db96d56Sopenharmony_ci    .m_methods = module_functions,
24797db96d56Sopenharmony_ci    .m_slots = _structmodule_slots,
24807db96d56Sopenharmony_ci    .m_traverse = _structmodule_traverse,
24817db96d56Sopenharmony_ci    .m_clear = _structmodule_clear,
24827db96d56Sopenharmony_ci    .m_free = _structmodule_free,
24837db96d56Sopenharmony_ci};
24847db96d56Sopenharmony_ci
24857db96d56Sopenharmony_ciPyMODINIT_FUNC
24867db96d56Sopenharmony_ciPyInit__struct(void)
24877db96d56Sopenharmony_ci{
24887db96d56Sopenharmony_ci    return PyModuleDef_Init(&_structmodule);
24897db96d56Sopenharmony_ci}
2490