From 44cf8ec67278bd1ab6c7f83a9993f7a5686a9541 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sat, 9 Mar 2024 01:06:44 +0100 Subject: Adding upstream version 0.23.93. Signed-off-by: Daniel Baumann --- python/enum.c | 259 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 259 insertions(+) create mode 100644 python/enum.c (limited to 'python/enum.c') diff --git a/python/enum.c b/python/enum.c new file mode 100644 index 0000000..b57a880 --- /dev/null +++ b/python/enum.c @@ -0,0 +1,259 @@ +/*------------------------------------------------------------------------ + * Copyright 2009-2010 (c) Jeff Brown + * + * This file is part of the ZBar Bar Code Reader. + * + * The ZBar Bar Code Reader is free software; you can redistribute it + * and/or modify it under the terms of the GNU Lesser Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * The ZBar Bar Code Reader is distributed in the hope that it will be + * useful, but WITHOUT ANY WARRANTY; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser Public License for more details. + * + * You should have received a copy of the GNU Lesser Public License + * along with the ZBar Bar Code Reader; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301 USA + * + * http://sourceforge.net/projects/zbar + *------------------------------------------------------------------------*/ + +#include "zbarmodule.h" + +static char enumitem_doc[] = + PyDoc_STR("simple enumeration item.\n" + "\n" + "associates an int value with a name for printing."); + +static zbarEnumItem *enumitem_new(PyTypeObject *type, PyObject *args, + PyObject *kwds) +{ + int val = 0; + PyObject *name = NULL; + static char *kwlist[] = { "value", "name", NULL }; + if (!PyArg_ParseTupleAndKeywords(args, kwds, "iS", kwlist, &val, &name)) + return (NULL); + + zbarEnumItem *self = (zbarEnumItem *)type->tp_alloc(type, 0); + if (!self) + return (NULL); + +#if PY_MAJOR_VERSION >= 3 + PyLongObject *longval = (PyLongObject *)PyLong_FromLong(val); + if (!longval) { + Py_DECREF(self); + return (NULL); + } + + /* we assume the "fast path" for a single-digit ints (see longobject.c) */ + /* this also holds if we get a small_int preallocated long */ +#if PY_VERSION_HEX >= 0x030900A4 + Py_SET_SIZE(&self->val, Py_SIZE(longval)); +#else + Py_SIZE(&self->val) = Py_SIZE(longval); +#endif +#if PY_VERSION_HEX >= 0x030c0000 + self->val.long_value.ob_digit[0] = longval->long_value.ob_digit[0]; +#else + self->val.ob_digit[0] = longval->ob_digit[0]; +#endif + Py_DECREF(longval); +#else + self->val.ob_ival = val; +#endif + self->name = name; + return (self); +} + +static void enumitem_dealloc(zbarEnumItem *self) +{ + Py_CLEAR(self->name); + ((PyObject *)self)->ob_type->tp_free((PyObject *)self); +} + +static PyObject *enumitem_str(zbarEnumItem *self) +{ + Py_INCREF(self->name); + return (self->name); +} + +#if PY_MAJOR_VERSION < 3 +/* tp_print was dropped on Python 3.9 */ +static int enumitem_print(zbarEnumItem *self, FILE *fp, int flags) +{ + return (self->name->ob_type->tp_print(self->name, fp, flags)); +} +#endif + +static PyObject *enumitem_repr(zbarEnumItem *self) +{ + PyObject *name = PyObject_Repr(self->name); + if (!name) + return (NULL); +#if PY_MAJOR_VERSION >= 3 + PyObject *repr = PyUnicode_FromFormat("%s(%ld, %U)", + ((PyObject *)self)->ob_type->tp_name, + PyLong_AsLong((PyObject *)self), + name); +#else + char *namestr = PyString_AsString(name); + PyObject *repr = PyString_FromFormat("%s(%ld, %s)", + ((PyObject *)self)->ob_type->tp_name, + self->val.ob_ival, namestr); +#endif + Py_DECREF(name); + return ((PyObject *)repr); +} + +PyTypeObject zbarEnumItem_Type = { + PyVarObject_HEAD_INIT(NULL, 0).tp_name = "zbar.EnumItem", + .tp_doc = enumitem_doc, + .tp_basicsize = sizeof(zbarEnumItem), + .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + .tp_new = (newfunc)enumitem_new, + .tp_dealloc = (destructor)enumitem_dealloc, + .tp_str = (reprfunc)enumitem_str, +#if PY_MAJOR_VERSION < 3 + .tp_print = (printfunc)enumitem_print, +#endif + .tp_repr = (reprfunc)enumitem_repr, +}; + +zbarEnumItem *zbarEnumItem_New(PyObject *byname, PyObject *byvalue, int val, + const char *name) +{ + zbarEnumItem *self = PyObject_New(zbarEnumItem, &zbarEnumItem_Type); + if (!self) + return (NULL); +#if PY_MAJOR_VERSION >= 3 + PyLongObject *longval = (PyLongObject *)PyLong_FromLong(val); + if (!longval) { + Py_DECREF(self); + return (NULL); + } + + /* we assume the "fast path" for a single-digit ints (see longobject.c) */ + /* this also holds if we get a small_int preallocated long */ +#if PY_VERSION_HEX >= 0x030900A4 + Py_SET_SIZE(&self->val, Py_SIZE(longval)); +#else + Py_SIZE(&self->val) = Py_SIZE(longval); +#endif +#if PY_VERSION_HEX >= 0x030c0000 + self->val.long_value.ob_digit[0] = longval->long_value.ob_digit[0]; +#else + self->val.ob_digit[0] = longval->ob_digit[0]; +#endif + Py_DECREF(longval); + + self->name = PyUnicode_FromString(name); +#else + self->val.ob_ival = val; + self->name = PyString_FromString(name); +#endif + if (!self->name || + (byname && PyDict_SetItem(byname, self->name, (PyObject *)self)) || + (byvalue && + PyDict_SetItem(byvalue, (PyObject *)self, (PyObject *)self))) { + Py_DECREF((PyObject *)self); + return (NULL); + } + return (self); +} + +static char enum_doc[] = PyDoc_STR("enumeration container for EnumItems.\n" + "\n" + "exposes items as read-only attributes"); + +/* FIXME add iteration */ + +static int enum_traverse(zbarEnum *self, visitproc visit, void *arg) +{ + Py_VISIT(self->byname); + Py_VISIT(self->byvalue); + return (0); +} + +static int enum_clear(zbarEnum *self) +{ + Py_CLEAR(self->byname); + Py_CLEAR(self->byvalue); + return (0); +} + +static void enum_dealloc(zbarEnum *self) +{ + enum_clear(self); + ((PyObject *)self)->ob_type->tp_free((PyObject *)self); +} + +PyTypeObject zbarEnum_Type = { + PyVarObject_HEAD_INIT(NULL, 0).tp_name = "zbar.Enum", + + .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, + + .tp_doc = enum_doc, + .tp_basicsize = sizeof(zbarEnum), + .tp_dictoffset = offsetof(zbarEnum, byname), + .tp_traverse = (traverseproc)enum_traverse, + .tp_clear = (inquiry)enum_clear, + .tp_dealloc = (destructor)enum_dealloc, +}; + +zbarEnum *zbarEnum_New() +{ + zbarEnum *self = PyObject_GC_New(zbarEnum, &zbarEnum_Type); + if (!self) + return (NULL); + self->byname = PyDict_New(); + self->byvalue = PyDict_New(); + if (!self->byname || !self->byvalue) { + Py_DECREF(self); + return (NULL); + } + return (self); +} + +int zbarEnum_Add(zbarEnum *self, int val, const char *name) +{ + zbarEnumItem *item; + item = zbarEnumItem_New(self->byname, self->byvalue, val, name); + if (!item) + return (-1); + return (0); +} + +zbarEnumItem *zbarEnum_LookupValue(zbarEnum *self, int val) +{ +#if PY_MAJOR_VERSION >= 3 + PyObject *key = PyLong_FromLong(val); +#else + PyObject *key = PyInt_FromLong(val); +#endif + zbarEnumItem *e = (zbarEnumItem *)PyDict_GetItem(self->byvalue, key); + if (!e) + return ((zbarEnumItem *)key); + Py_INCREF((PyObject *)e); + Py_DECREF(key); + return (e); +} + +PyObject *zbarEnum_SetFromMask(zbarEnum *self, unsigned int mask) +{ + PyObject *result = PySet_New(NULL); + PyObject *key, *item; + Py_ssize_t i = 0; + while (PyDict_Next(self->byvalue, &i, &key, &item)) { +#if PY_MAJOR_VERSION >= 3 + unsigned long val = (unsigned long)PyLong_AsLong(item); +#else + int val = PyInt_AsLong(item); +#endif + if (val < sizeof(mask) * 8 && ((mask >> val) & 1)) + PySet_Add(result, item); + } + return (result); +} -- cgit v1.2.3