msm: consistency for equally ranked keys
[platform/upstream/rpm.git] / python / rpmtd-py.c
1 /** \ingroup py_c
2  * \file python/rpmtd-py.c
3  */
4
5 #include "rpmsystem-py.h"
6 #include <rpm/rpmtd.h>
7 #include <rpm/header.h>
8 #include "rpmtd-py.h"
9 #include "header-py.h"
10
11 /*
12  * Convert single tag data item to python object of suitable type
13  */
14 static PyObject * rpmtd_ItemAsPyobj(rpmtd td, rpmTagClass tclass)
15 {
16     PyObject *res = NULL;
17
18     switch (tclass) {
19     case RPM_STRING_CLASS:
20         res = PyBytes_FromString(rpmtdGetString(td));
21         break;
22     case RPM_NUMERIC_CLASS:
23         res = PyLong_FromLongLong(rpmtdGetNumber(td));
24         break;
25     case RPM_BINARY_CLASS:
26         res = PyBytes_FromStringAndSize(td->data, td->count);
27         break;
28     default:
29         PyErr_SetString(PyExc_KeyError, "unknown data type");
30         break;
31     }
32     return res;
33 }
34
35 PyObject *rpmtd_AsPyobj(rpmtd td)
36 {
37     PyObject *res = NULL;
38     int array = (rpmTagGetReturnType(td->tag) == RPM_ARRAY_RETURN_TYPE);
39     rpmTagClass tclass = rpmtdClass(td);
40
41     if (!array && rpmtdCount(td) < 1) {
42         Py_RETURN_NONE;
43     }
44     
45     if (array) {
46         int ix;
47         res = PyList_New(rpmtdCount(td));
48         if (!res) {
49             return NULL;
50         }
51         while ((ix = rpmtdNext(td)) >= 0) {
52             PyObject *item = rpmtd_ItemAsPyobj(td, tclass);
53             if (!item) {
54                 Py_DECREF(res);
55                 return NULL;
56             }
57             PyList_SET_ITEM(res, ix, item);
58         }
59     } else {
60         res = rpmtd_ItemAsPyobj(td, tclass);
61     }
62     return res;
63 }
64
65 #if 0
66 struct rpmtdObject_s {
67     PyObject_HEAD
68     PyObject *md_dict;
69     struct rpmtd_s td;
70 };
71
72 /* string format should never fail but do regular repr just in case it does */
73 static PyObject *rpmtd_str(rpmtdObject *s)
74 {
75     PyObject *res = NULL;
76     char *str = rpmtdFormat(&(s->td), RPMTD_FORMAT_STRING, NULL);
77     if (str) {
78         res = PyBytes_FromString(str);
79         free(str);
80     } else {
81         res = PyObject_Repr((PyObject *)s);
82     }
83     return res;
84 }
85
86 static PyObject *rpmtd_iternext(rpmtdObject *s)
87 {
88     PyObject *next = NULL;
89
90     if (rpmtdNext(&(s->td)) >= 0) {
91         Py_INCREF(s);
92         next = (PyObject*) s;
93     }
94     return next;
95 }
96
97 static PyObject *rpmtd_new(PyTypeObject * subtype, PyObject *args, PyObject *kwds)
98 {
99     rpmtdObject *s = NULL;
100     Header h = NULL;
101     rpmTagVal tag;
102     int raw = 0;
103     int noext = 0;
104     headerGetFlags flags = (HEADERGET_EXT | HEADERGET_ALLOC);
105     char *kwlist[] = { "header", "tag", "raw", "noext", NULL };
106
107     if (!PyArg_ParseTupleAndKeywords(args, kwds, "O&O&|ii", kwlist,
108                         hdrFromPyObject, &h, tagNumFromPyObject, &tag,
109                         &raw, &noext))
110         return NULL;
111
112     if (raw) {
113         flags |= HEADERGET_RAW;
114         noext = 1; /* extensions with raw dont make sense */
115     }
116     if (noext) flags &= ~HEADERGET_EXT;
117
118     if ((s = (rpmtdObject *)subtype->tp_alloc(subtype, 0)) == NULL)
119         return NULL;
120
121     headerGet(h, tag, &(s->td), flags);
122
123     return (PyObject *) s;
124 }
125
126 static void rpmtd_dealloc(rpmtdObject * s)
127 {
128     rpmtdFreeData(&(s->td));
129     Py_TYPE(s)->tp_free((PyObject *)s);
130 }
131
132 static int rpmtd_length(rpmtdObject *s)
133 {
134     return rpmtdCount(&(s->td));
135 }
136
137 static PyMappingMethods rpmtd_as_mapping = {
138     (lenfunc) rpmtd_length,             /* mp_length */
139 };
140
141 static PyMemberDef rpmtd_members[] = {
142     { "type", T_INT, offsetof(rpmtdObject, td.type), READONLY, NULL },
143     { NULL }
144 };
145
146 static PyObject *rpmtd_get_tag(rpmtdObject *s, void *closure)
147 {
148     return Py_BuildValue("i", rpmtdTag(&(s->td)));
149 }
150
151 static int rpmtd_set_tag(rpmtdObject *s, PyObject *value, void *closure)
152 {
153     rpmTagVal tag;
154     if (!tagNumFromPyObject(value, &tag)) return -1;
155
156     if (!rpmtdSetTag(&(s->td), tag)) {
157         PyErr_SetString(PyExc_ValueError, "incompatible tag for data");
158         return -1;
159     }
160     return 0;
161 }
162
163 static PyGetSetDef rpmtd_getseters[] = {
164     { "tag", (getter)rpmtd_get_tag, (setter)rpmtd_set_tag, NULL },
165     { NULL }
166 };
167
168 PyTypeObject rpmtd_Type = {
169         PyVarObject_HEAD_INIT(&PyType_Type, 0)
170         "rpm.td",                       /* tp_name */
171         sizeof(rpmtdObject),            /* tp_size */
172         0,                              /* tp_itemsize */
173         (destructor) rpmtd_dealloc,     /* tp_dealloc */
174         0,                              /* tp_print */
175         (getattrfunc)0,                 /* tp_getattr */
176         0,                              /* tp_setattr */
177         0,                              /* tp_compare */
178         0,                              /* tp_repr */
179         0,                              /* tp_as_number */
180         0,                              /* tp_as_sequence */
181         &rpmtd_as_mapping,              /* tp_as_mapping */
182         0,                              /* tp_hash */
183         0,                              /* tp_call */
184         (reprfunc)rpmtd_str,            /* tp_str */
185         PyObject_GenericGetAttr,        /* tp_getattro */
186         PyObject_GenericSetAttr,        /* tp_setattro */
187         0,                              /* tp_as_buffer */
188         Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, /* tp_flags */
189         0,                              /* tp_doc */
190         0,                              /* tp_traverse */
191         0,                              /* tp_clear */
192         0,                              /* tp_richcompare */
193         0,                              /* tp_weaklistoffset */
194         PyObject_SelfIter,              /* tp_iter */
195         (iternextfunc)rpmtd_iternext,   /* tp_iternext */
196         0,                              /* tp_methods */
197         rpmtd_members,                  /* tp_members */
198         rpmtd_getseters,                /* tp_getset */
199         0,                              /* tp_base */
200         0,                              /* tp_dict */
201         0,                              /* tp_descr_get */
202         0,                              /* tp_descr_set */
203         0,                              /* tp_dictoffset */
204         0,                              /* tp_init */
205         0,                              /* tp_alloc */
206         rpmtd_new,                      /* tp_new */
207         0,                              /* tp_free */
208         0,                              /* tp_is_gc */
209 };
210
211 int rpmtdFromPyObject(PyObject *obj, rpmtd *td)
212 {
213     if (rpmtdObject_Check(obj)) {
214         *td = &(((rpmtdObject *)obj)->td);
215         return 1;
216     } else {
217         PyErr_SetString(PyExc_TypeError, "rpm.td type expected");
218         return 0;
219     }
220 }
221 #endif