FazBrowse GitHub Viewer | Trending |
URL:
| Home
Tools: [Download Repo ZIP]   [Original HTTPS Page]

GitHub Viewer

/* struct module -- pack values into and (out of) bytes objects */ /* New version supporting byte order, alignment and size options, byte strings, and unsigned numbers */ #ifndef Py_BUILD_CORE_BUILTIN # define Py_BUILD_CORE_MODULE 1 #endif #include "Python.h" #include "pycore_bytesobject.h" // _PyBytesWriter #include "pycore_lock.h" // _PyOnceFlag_CallOnce() #include "pycore_long.h" // _PyLong_AsByteArray() #include "pycore_moduleobject.h" // _PyModule_GetState() #include "pycore_weakref.h" // FT_CLEAR_WEAKREFS() #include // offsetof() /*[clinic input] class Struct "PyStructObject *" "&PyStructType" [clinic start generated code]*/ /*[clinic end generated code: output=da39a3ee5e6b4b0d input=9b032058a83ed7c3]*/ typedef struct { PyObject *cache; PyObject *PyStructType; PyObject *unpackiter_type; PyObject *StructError; } _structmodulestate; static inline _structmodulestate* get_struct_state(PyObject *module) { void *state = _PyModule_GetState(module); assert(state != NULL); return (_structmodulestate *)state; } static struct PyModuleDef _structmodule; #define get_struct_state_structinst(self) \ (get_struct_state(PyType_GetModuleByDef(Py_TYPE(self), &_structmodule))) #define get_struct_state_iterinst(self) \ (get_struct_state(PyType_GetModule(Py_TYPE(self)))) /* The translation function for each format character is table driven */ typedef struct _formatdef { const char *format; Py_ssize_t size; Py_ssize_t alignment; PyObject* (*unpack)(_structmodulestate *, const char *, const struct _formatdef *); int (*pack)(_structmodulestate *, char *, PyObject *, const struct _formatdef *); } formatdef; typedef struct _formatcode { const struct _formatdef *fmtdef; Py_ssize_t offset; Py_ssize_t size; Py_ssize_t repeat; } formatcode; /* Struct object interface */ typedef struct { PyObject_HEAD Py_ssize_t s_size; Py_ssize_t s_len; formatcode *s_codes; PyObject *s_format; PyObject *weakreflist; /* List of weak references */ bool init_called; } PyStructObject; #define PyStructObject_CAST(op) ((PyStructObject *)(op)) #define PyStruct_Check(op, state) PyObject_TypeCheck(op, (PyTypeObject *)(state)->PyStructType) #ifdef __powerc #pragma options align=reset #endif /*[python input] class cache_struct_converter(CConverter): type = 'PyStructObject *' converter = 'cache_struct_converter' c_default = "NULL" broken_limited_capi = True def parse_arg(self, argname, displayname, *, limited_capi): assert not limited_capi return self.format_code(""" if (!{converter}(module, {argname}, &{paramname})) {{{{ goto exit; }}}} """, argname=argname, converter=self.converter) def cleanup(self): return "Py_XDECREF(%s);\n" % self.name [python start generated code]*/ /*[python end generated code: output=da39a3ee5e6b4b0d input=c33b27d6b06006c6]*/ static int cache_struct_converter(PyObject *, PyObject *, PyStructObject **); #include "clinic/_struct.c.h" /* Helper for integer format codes: converts an arbitrary Python object to a PyLongObject if possible, otherwise fails. Caller should decref. */ static PyObject * get_pylong(_structmodulestate *state, PyObject *v) { assert(v != NULL); if (!PyLong_Check(v)) { /* Not an integer; try to use __index__ to convert. */ if (PyIndex_Check(v)) { v = _PyNumber_Index(v); if (v == NULL) return NULL; } else { PyErr_SetString(state->StructError, "required argument is not an integer"); return NULL; } } else Py_INCREF(v); assert(PyLong_Check(v)); return v; } /* Helper routine to get a C long and raise the appropriate error if it isn't one */ static int get_long(_structmodulestate *state, PyObject *v, long *p) { long x; v = get_pylong(state, v); if (v == NULL) return -1; assert(PyLong_Check(v)); x = PyLong_AsLong(v); Py_DECREF(v); if (x == (long)-1 && PyErr_Occurred()) { return -1; } *p = x; return 0; } /* Same, but handling unsigned long */ static int get_ulong(_structmodulestate *state, PyObject *v, unsigned long *p) { unsigned long x; v = get_pylong(state, v); if (v == NULL) return -1; assert(PyLong_Check(v)); x = PyLong_AsUnsignedLong(v); Py_DECREF(v); if (x == (unsigned long)-1 && PyErr_Occurred()) { return -1; } *p = x; return 0; } /* Same, but handling native long long. */ static int get_longlong(_structmodulestate *state, PyObject *v, long long *p) { long long x; v = get_pylong(state, v); if (v == NULL) return -1; assert(PyLong_Check(v)); x = PyLong_AsLongLong(v); Py_DECREF(v); if (x == (long long)-1 && PyErr_Occurred()) { return -1; } *p = x; return 0; } /* Same, but handling native unsigned long long. */ static int get_ulonglong(_structmodulestate *state, PyObject *v, unsigned long long *p) { unsigned long long x; v = get_pylong(state, v); if (v == NULL) return -1; assert(PyLong_Check(v)); x = PyLong_AsUnsignedLongLong(v); Py_DECREF(v); if (x == (unsigned long long)-1 && PyErr_Occurred()) { return -1; } *p = x; return 0; } /* Same, but handling Py_ssize_t */ static int get_ssize_t(_structmodulestate *state, PyObject *v, Py_ssize_t *p) { Py_ssize_t x; v = get_pylong(state, v); if (v == NULL) return -1; assert(PyLong_Check(v)); x = PyLong_AsSsize_t(v); Py_DECREF(v); if (x == (Py_ssize_t)-1 && PyErr_Occurred()) { return -1; } *p = x; return 0; } /* Same, but handling size_t */ static int get_size_t(_structmodulestate *state, PyObject *v, size_t *p) { size_t x; v = get_pylong(state, v); if (v == NULL) return -1; assert(PyLong_Check(v)); x = PyLong_AsSize_t(v); Py_DECREF(v); if (x == (size_t)-1 && PyErr_Occurred()) { return -1; } *p = x; return 0; } #define RANGE_ERROR(state, f, flag) return _range_error(state, f, flag) /* Floating-point helpers */ static PyObject * unpack_halffloat(const char *p, /* start of 2-byte string */ int le) /* true for little-endian, false for big-endian */ { double x = PyFloat_Unpack2(p, le); if (x == -1.0 && PyErr_Occurred()) { return NULL; } return PyFloat_FromDouble(x); } static int pack_halffloat(_structmodulestate *state, char *p, /* start of 2-byte string */ PyObject *v, /* value to pack */ int le) /* true for little-endian, false for big-endian */ { double x = PyFloat_AsDouble(v); if (x == -1.0 && PyErr_Occurred()) { PyErr_SetString(state->StructError, "required argument is not a float"); return -1; } return PyFloat_Pack2(x, p, le); } static PyObject * unpack_float(const char *p, /* start of 4-byte string */ int le) /* true for little-endian, false for big-endian */ { double x; x = PyFloat_Unpack4(p, le); if (x == -1.0 && PyErr_Occurred()) return NULL; return PyFloat_FromDouble(x); } static PyObject * unpack_double(const char *p, /* start of 8-byte string */ int le) /* true for little-endian, false for big-endian */ { double x; x = PyFloat_Unpack8(p, le); if (x == -1.0 && PyErr_Occurred()) return NULL; return PyFloat_FromDouble(x); } /* Helper to format the range error exceptions */ static int _range_error(_structmodulestate *state, const formatdef *f, int is_unsigned) { /* ulargest is the largest unsigned value with f->size bytes. * Note that the simpler: * ((size_t)1 size * 8)) - 1 * doesn't work when f->size == sizeof(size_t) because C doesn't * define what happens when a left shift count is >= the number of * bits in the integer being shifted; e.g., on some boxes it doesn't * shift at all when they're equal. */ const size_t ulargest = (size_t)-1 >> ((SIZEOF_SIZE_T - f->size)*8); assert(f->size >= 1 && f->size StructError, "'%s' format requires 0 \n\ \n\ The remaining characters indicate types of args and must match exactly;\n\ these can be preceded by a decimal repeat count:\n\ x: pad byte (no data); c: char; b: signed byte; B: unsigned byte;\n\ ?: _Bool; h: short; H: unsigned short; i: int; I: unsigned int;\n\ l: long; L: unsigned long; q: long long; Q: unsigned long long;\n\ f: float; d: double; e: half-float;\n\ F: float complex; D: double complex.\n\ Special cases (preceding decimal count indicates length):\n\ s: byte string (array of char); p: Pascal string (with count byte).\n\ Special cases (only available in native format):\n\ n: ssize_t; N: size_t;\n\ P: an integer type that is wide enough to hold a pointer.\n\ Whitespace between formats is ignored.\n\ \n\ The variable struct.error is an exception raised on errors.\n"); static int _structmodule_traverse(PyObject *module, visitproc visit, void *arg) { _structmodulestate *state = get_struct_state(module); if (state) { Py_VISIT(state->cache); Py_VISIT(state->PyStructType); Py_VISIT(state->unpackiter_type); Py_VISIT(state->StructError); } return 0; } static int _structmodule_clear(PyObject *module) { _structmodulestate *state = get_struct_state(module); if (state) { Py_CLEAR(state->cache); Py_CLEAR(state->PyStructType); Py_CLEAR(state->unpackiter_type); Py_CLEAR(state->StructError); } return 0; } static void _structmodule_free(void *module) { (void)_structmodule_clear((PyObject *)module); } static int _structmodule_exec(PyObject *m) { _structmodulestate *state = get_struct_state(m); state->cache = PyDict_New(); if (state->cache == NULL) { return -1; } state->PyStructType = PyType_FromModuleAndSpec( m, &PyStructType_spec, NULL); if (state->PyStructType == NULL) { return -1; } if (PyModule_AddType(m, (PyTypeObject *)state->PyStructType) < 0) { return -1; } state->unpackiter_type = PyType_FromModuleAndSpec( m, &unpackiter_type_spec, NULL); if (state->unpackiter_type == NULL) { return -1; } /* init cannot fail */ (void)_PyOnceFlag_CallOnce(&endian_tables_init_once, init_endian_tables, NULL); /* Add some symbolic constants to the module */ state->StructError = PyErr_NewException("struct.error", NULL, NULL); if (state->StructError == NULL) { return -1; } if (PyModule_AddObjectRef(m, "error", state->StructError) < 0) { return -1; } return 0; } static PyModuleDef_Slot _structmodule_slots[] = { _Py_ABI_SLOT, {Py_mod_exec, _structmodule_exec}, {Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED}, {Py_mod_gil, Py_MOD_GIL_NOT_USED}, {0, NULL} }; static struct PyModuleDef _structmodule = { PyModuleDef_HEAD_INIT, .m_name = "_struct", .m_doc = module_doc, .m_size = sizeof(_structmodulestate), .m_methods = module_functions, .m_slots = _structmodule_slots, .m_traverse = _structmodule_traverse, .m_clear = _structmodule_clear, .m_free = _structmodule_free, }; PyMODINIT_FUNC PyInit__struct(void) { return PyModuleDef_Init(&_structmodule); }

Back | FazBrowse Home | New Git URL