LCOV - code coverage report
Current view: top level - libreoffice/workdir/unxlngi6.pro/UnpackedTarball/python3/Objects - structseq.c (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 44 168 26.2 %
Date: 2012-12-17 Functions: 3 9 33.3 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* Implementation helper: a struct that looks like a tuple.  See timemodule
       2             :    and posixmodule for example uses. */
       3             : 
       4             : #include "Python.h"
       5             : #include "structmember.h"
       6             : 
       7             : static char visible_length_key[] = "n_sequence_fields";
       8             : static char real_length_key[] = "n_fields";
       9             : static char unnamed_fields_key[] = "n_unnamed_fields";
      10             : 
      11             : /* Fields with this name have only a field index, not a field name.
      12             :    They are only allowed for indices < n_visible_fields. */
      13             : char *PyStructSequence_UnnamedField = "unnamed field";
      14             : 
      15             : #define VISIBLE_SIZE(op) Py_SIZE(op)
      16             : #define VISIBLE_SIZE_TP(tp) PyLong_AsLong( \
      17             :                       PyDict_GetItemString((tp)->tp_dict, visible_length_key))
      18             : 
      19             : #define REAL_SIZE_TP(tp) PyLong_AsLong( \
      20             :                       PyDict_GetItemString((tp)->tp_dict, real_length_key))
      21             : #define REAL_SIZE(op) REAL_SIZE_TP(Py_TYPE(op))
      22             : 
      23             : #define UNNAMED_FIELDS_TP(tp) PyLong_AsLong( \
      24             :                       PyDict_GetItemString((tp)->tp_dict, unnamed_fields_key))
      25             : #define UNNAMED_FIELDS(op) UNNAMED_FIELDS_TP(Py_TYPE(op))
      26             : 
      27             : 
      28             : PyObject *
      29         330 : PyStructSequence_New(PyTypeObject *type)
      30             : {
      31             :     PyStructSequence *obj;
      32         330 :     Py_ssize_t size = REAL_SIZE_TP(type), i;
      33             : 
      34         330 :     obj = PyObject_GC_NewVar(PyStructSequence, type, size);
      35         330 :     if (obj == NULL)
      36           0 :         return NULL;
      37             :     /* Hack the size of the variable object, so invisible fields don't appear
      38             :      to Python code. */
      39         330 :     Py_SIZE(obj) = VISIBLE_SIZE_TP(type);
      40        6524 :     for (i = 0; i < size; i++)
      41        6194 :         obj->ob_item[i] = NULL;
      42             : 
      43         330 :     return (PyObject*)obj;
      44             : }
      45             : 
      46             : void
      47           0 : PyStructSequence_SetItem(PyObject* op, Py_ssize_t i, PyObject* v)
      48             : {
      49           0 :     PyStructSequence_SET_ITEM(op, i, v);
      50           0 : }
      51             : 
      52             : PyObject*
      53           0 : PyStructSequence_GetItem(PyObject* op, Py_ssize_t i)
      54             : {
      55           0 :     return PyStructSequence_GET_ITEM(op, i);
      56             : }
      57             : 
      58             : static void
      59         324 : structseq_dealloc(PyStructSequence *obj)
      60             : {
      61             :     Py_ssize_t i, size;
      62             :     
      63         324 :     size = REAL_SIZE(obj);
      64        6480 :     for (i = 0; i < size; ++i) {
      65        6156 :         Py_XDECREF(obj->ob_item[i]);
      66             :     }
      67         324 :     PyObject_GC_Del(obj);
      68         324 : }
      69             : 
      70             : static PyObject *
      71           0 : structseq_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
      72             : {
      73           0 :     PyObject *arg = NULL;
      74           0 :     PyObject *dict = NULL;
      75             :     PyObject *ob;
      76           0 :     PyStructSequence *res = NULL;
      77             :     Py_ssize_t len, min_len, max_len, i, n_unnamed_fields;
      78             :     static char *kwlist[] = {"sequence", "dict", 0};
      79             : 
      80           0 :     if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|O:structseq",
      81             :                                      kwlist, &arg, &dict))
      82           0 :         return NULL;
      83             : 
      84           0 :     arg = PySequence_Fast(arg, "constructor requires a sequence");
      85             : 
      86           0 :     if (!arg) {
      87           0 :         return NULL;
      88             :     }
      89             : 
      90           0 :     if (dict && !PyDict_Check(dict)) {
      91           0 :         PyErr_Format(PyExc_TypeError,
      92             :                      "%.500s() takes a dict as second arg, if any",
      93             :                      type->tp_name);
      94           0 :         Py_DECREF(arg);
      95           0 :         return NULL;
      96             :     }
      97             : 
      98           0 :     len = PySequence_Fast_GET_SIZE(arg);
      99           0 :     min_len = VISIBLE_SIZE_TP(type);
     100           0 :     max_len = REAL_SIZE_TP(type);
     101           0 :     n_unnamed_fields = UNNAMED_FIELDS_TP(type);
     102             : 
     103           0 :     if (min_len != max_len) {
     104           0 :         if (len < min_len) {
     105           0 :             PyErr_Format(PyExc_TypeError,
     106             :                 "%.500s() takes an at least %zd-sequence (%zd-sequence given)",
     107             :                 type->tp_name, min_len, len);
     108           0 :             Py_DECREF(arg);
     109           0 :             return NULL;
     110             :         }
     111             : 
     112           0 :         if (len > max_len) {
     113           0 :             PyErr_Format(PyExc_TypeError,
     114             :                 "%.500s() takes an at most %zd-sequence (%zd-sequence given)",
     115             :                 type->tp_name, max_len, len);
     116           0 :             Py_DECREF(arg);
     117           0 :             return NULL;
     118             :         }
     119             :     }
     120             :     else {
     121           0 :         if (len != min_len) {
     122           0 :             PyErr_Format(PyExc_TypeError,
     123             :                          "%.500s() takes a %zd-sequence (%zd-sequence given)",
     124             :                          type->tp_name, min_len, len);
     125           0 :             Py_DECREF(arg);
     126           0 :             return NULL;
     127             :         }
     128             :     }
     129             : 
     130           0 :     res = (PyStructSequence*) PyStructSequence_New(type);
     131           0 :     if (res == NULL) {
     132           0 :         Py_DECREF(arg);
     133           0 :         return NULL;
     134             :     }
     135           0 :     for (i = 0; i < len; ++i) {
     136           0 :         PyObject *v = PySequence_Fast_GET_ITEM(arg, i);
     137           0 :         Py_INCREF(v);
     138           0 :         res->ob_item[i] = v;
     139             :     }
     140           0 :     for (; i < max_len; ++i) {
     141           0 :         if (dict && (ob = PyDict_GetItemString(
     142           0 :             dict, type->tp_members[i-n_unnamed_fields].name))) {
     143             :         }
     144             :         else {
     145           0 :             ob = Py_None;
     146             :         }
     147           0 :         Py_INCREF(ob);
     148           0 :         res->ob_item[i] = ob;
     149             :     }
     150             : 
     151           0 :     Py_DECREF(arg);
     152           0 :     return (PyObject*) res;
     153             : }
     154             : 
     155             : 
     156             : static PyObject *
     157           0 : structseq_repr(PyStructSequence *obj)
     158             : {
     159             :     /* buffer and type size were chosen well considered. */
     160             : #define REPR_BUFFER_SIZE 512
     161             : #define TYPE_MAXSIZE 100
     162             : 
     163           0 :     PyTypeObject *typ = Py_TYPE(obj);
     164           0 :     int i, removelast = 0;
     165             :     Py_ssize_t len;
     166             :     char buf[REPR_BUFFER_SIZE];
     167           0 :     char *endofbuf, *pbuf = buf;
     168             : 
     169             :     /* pointer to end of writeable buffer; safes space for "...)\0" */
     170           0 :     endofbuf= &buf[REPR_BUFFER_SIZE-5];
     171             : 
     172             :     /* "typename(", limited to  TYPE_MAXSIZE */
     173           0 :     len = strlen(typ->tp_name) > TYPE_MAXSIZE ? TYPE_MAXSIZE :
     174           0 :                             strlen(typ->tp_name);
     175           0 :     strncpy(pbuf, typ->tp_name, len);
     176           0 :     pbuf += len;
     177           0 :     *pbuf++ = '(';
     178             : 
     179           0 :     for (i=0; i < VISIBLE_SIZE(obj); i++) {
     180             :         PyObject *val, *repr;
     181             :         char *cname, *crepr;
     182             : 
     183           0 :         cname = typ->tp_members[i].name;
     184           0 :         if (cname == NULL) {
     185           0 :             PyErr_Format(PyExc_SystemError, "In structseq_repr(), member %d name is NULL"
     186             :                          " for type %.500s", i, typ->tp_name);
     187           0 :             return NULL;
     188             :         }
     189           0 :         val = PyStructSequence_GET_ITEM(obj, i);
     190           0 :         repr = PyObject_Repr(val);
     191           0 :         if (repr == NULL)
     192           0 :             return NULL;
     193           0 :         crepr = _PyUnicode_AsString(repr);
     194           0 :         if (crepr == NULL) {
     195           0 :             Py_DECREF(repr);
     196           0 :             return NULL;
     197             :         }
     198             : 
     199             :         /* + 3: keep space for "=" and ", " */
     200           0 :         len = strlen(cname) + strlen(crepr) + 3;
     201           0 :         if ((pbuf+len) <= endofbuf) {
     202           0 :             strcpy(pbuf, cname);
     203           0 :             pbuf += strlen(cname);
     204           0 :             *pbuf++ = '=';
     205           0 :             strcpy(pbuf, crepr);
     206           0 :             pbuf += strlen(crepr);
     207           0 :             *pbuf++ = ',';
     208           0 :             *pbuf++ = ' ';
     209           0 :             removelast = 1;
     210           0 :             Py_DECREF(repr);
     211             :         }
     212             :         else {
     213           0 :             strcpy(pbuf, "...");
     214           0 :             pbuf += 3;
     215           0 :             removelast = 0;
     216           0 :             Py_DECREF(repr);
     217           0 :             break;
     218             :         }
     219             :     }
     220           0 :     if (removelast) {
     221             :         /* overwrite last ", " */
     222           0 :         pbuf-=2;
     223             :     }
     224           0 :     *pbuf++ = ')';
     225           0 :     *pbuf = '\0';
     226             : 
     227           0 :     return PyUnicode_FromString(buf);
     228             : }
     229             : 
     230             : static PyObject *
     231           0 : structseq_reduce(PyStructSequence* self)
     232             : {
     233             :     PyObject* tup;
     234             :     PyObject* dict;
     235             :     PyObject* result;
     236             :     Py_ssize_t n_fields, n_visible_fields, n_unnamed_fields;
     237             :     int i;
     238             : 
     239           0 :     n_fields = REAL_SIZE(self);
     240           0 :     n_visible_fields = VISIBLE_SIZE(self);
     241           0 :     n_unnamed_fields = UNNAMED_FIELDS(self);
     242           0 :     tup = PyTuple_New(n_visible_fields);
     243           0 :     if (!tup) {
     244           0 :         return NULL;
     245             :     }
     246             : 
     247           0 :     dict = PyDict_New();
     248           0 :     if (!dict) {
     249           0 :         Py_DECREF(tup);
     250           0 :         return NULL;
     251             :     }
     252             : 
     253           0 :     for (i = 0; i < n_visible_fields; i++) {
     254           0 :         Py_INCREF(self->ob_item[i]);
     255           0 :         PyTuple_SET_ITEM(tup, i, self->ob_item[i]);
     256             :     }
     257             : 
     258           0 :     for (; i < n_fields; i++) {
     259           0 :         char *n = Py_TYPE(self)->tp_members[i-n_unnamed_fields].name;
     260           0 :         PyDict_SetItemString(dict, n,
     261             :                              self->ob_item[i]);
     262             :     }
     263             : 
     264           0 :     result = Py_BuildValue("(O(OO))", Py_TYPE(self), tup, dict);
     265             : 
     266           0 :     Py_DECREF(tup);
     267           0 :     Py_DECREF(dict);
     268             : 
     269           0 :     return result;
     270             : }
     271             : 
     272             : static PyMethodDef structseq_methods[] = {
     273             :     {"__reduce__", (PyCFunction)structseq_reduce, METH_NOARGS, NULL},
     274             :     {NULL, NULL}
     275             : };
     276             : 
     277             : static PyTypeObject _struct_sequence_template = {
     278             :     PyVarObject_HEAD_INIT(&PyType_Type, 0)
     279             :     NULL,                                       /* tp_name */
     280             :     sizeof(PyStructSequence) - sizeof(PyObject *), /* tp_basicsize */
     281             :     sizeof(PyObject *),                         /* tp_itemsize */
     282             :     (destructor)structseq_dealloc,              /* tp_dealloc */
     283             :     0,                                          /* tp_print */
     284             :     0,                                          /* tp_getattr */
     285             :     0,                                          /* tp_setattr */
     286             :     0,                                          /* tp_reserved */
     287             :     (reprfunc)structseq_repr,                   /* tp_repr */
     288             :     0,                                          /* tp_as_number */
     289             :     0,                                          /* tp_as_sequence */
     290             :     0,                                          /* tp_as_mapping */
     291             :     0,                                          /* tp_hash */
     292             :     0,                                          /* tp_call */
     293             :     0,                                          /* tp_str */
     294             :     0,                                          /* tp_getattro */
     295             :     0,                                          /* tp_setattro */
     296             :     0,                                          /* tp_as_buffer */
     297             :     Py_TPFLAGS_DEFAULT,                         /* tp_flags */
     298             :     NULL,                                       /* tp_doc */
     299             :     0,                                          /* tp_traverse */
     300             :     0,                                          /* tp_clear */
     301             :     0,                                          /* tp_richcompare */
     302             :     0,                                          /* tp_weaklistoffset */
     303             :     0,                                          /* tp_iter */
     304             :     0,                                          /* tp_iternext */
     305             :     structseq_methods,                          /* tp_methods */
     306             :     NULL,                                       /* tp_members */
     307             :     0,                                          /* tp_getset */
     308             :     0,                                          /* tp_base */
     309             :     0,                                          /* tp_dict */
     310             :     0,                                          /* tp_descr_get */
     311             :     0,                                          /* tp_descr_set */
     312             :     0,                                          /* tp_dictoffset */
     313             :     0,                                          /* tp_init */
     314             :     0,                                          /* tp_alloc */
     315             :     structseq_new,                              /* tp_new */
     316             : };
     317             : 
     318             : void
     319          14 : PyStructSequence_InitType(PyTypeObject *type, PyStructSequence_Desc *desc)
     320             : {
     321             :     PyObject *dict;
     322             :     PyMemberDef* members;
     323             :     int n_members, n_unnamed_members, i, k;
     324             : 
     325             : #ifdef Py_TRACE_REFS
     326             :     /* if the type object was chained, unchain it first
     327             :        before overwriting its storage */
     328             :     if (type->ob_base.ob_base._ob_next) {
     329             :         _Py_ForgetReference((PyObject*)type);
     330             :     }
     331             : #endif
     332             : 
     333          14 :     n_unnamed_members = 0;
     334         106 :     for (i = 0; desc->fields[i].name != NULL; ++i)
     335          92 :         if (desc->fields[i].name == PyStructSequence_UnnamedField)
     336           3 :             n_unnamed_members++;
     337          14 :     n_members = i;
     338             : 
     339          14 :     memcpy(type, &_struct_sequence_template, sizeof(PyTypeObject));
     340          14 :     type->tp_base = &PyTuple_Type;
     341          14 :     type->tp_name = desc->name;
     342          14 :     type->tp_doc = desc->doc;
     343             : 
     344          14 :     members = PyMem_NEW(PyMemberDef, n_members-n_unnamed_members+1);
     345          14 :     if (members == NULL)
     346           0 :         return;
     347             : 
     348         106 :     for (i = k = 0; i < n_members; ++i) {
     349          92 :         if (desc->fields[i].name == PyStructSequence_UnnamedField)
     350           3 :             continue;
     351          89 :         members[k].name = desc->fields[i].name;
     352          89 :         members[k].type = T_OBJECT;
     353         178 :         members[k].offset = offsetof(PyStructSequence, ob_item)
     354          89 :           + i * sizeof(PyObject*);
     355          89 :         members[k].flags = READONLY;
     356          89 :         members[k].doc = desc->fields[i].doc;
     357          89 :         k++;
     358             :     }
     359          14 :     members[k].name = NULL;
     360             : 
     361          14 :     type->tp_members = members;
     362             : 
     363          14 :     if (PyType_Ready(type) < 0)
     364           0 :         return;
     365          14 :     Py_INCREF(type);
     366             : 
     367          14 :     dict = type->tp_dict;
     368             : #define SET_DICT_FROM_INT(key, value)                           \
     369             :     do {                                                        \
     370             :         PyObject *v = PyLong_FromLong((long) value);            \
     371             :         if (v != NULL) {                                        \
     372             :             PyDict_SetItemString(dict, key, v);                 \
     373             :             Py_DECREF(v);                                       \
     374             :         }                                                       \
     375             :     } while (0)
     376             : 
     377          14 :     SET_DICT_FROM_INT(visible_length_key, desc->n_in_sequence);
     378          14 :     SET_DICT_FROM_INT(real_length_key, n_members);
     379          14 :     SET_DICT_FROM_INT(unnamed_fields_key, n_unnamed_members);
     380             : }
     381             : 
     382             : PyTypeObject*
     383           0 : PyStructSequence_NewType(PyStructSequence_Desc *desc)
     384             : {
     385           0 :     PyTypeObject *result = (PyTypeObject*)PyType_GenericAlloc(&PyType_Type, 0);
     386           0 :     if (result != NULL) {
     387           0 :         PyStructSequence_InitType(result, desc);
     388             :     }
     389           0 :     return result;
     390             : }

Generated by: LCOV version 1.10