2
0
mirror of https://github.com/openvswitch/ovs synced 2025-10-09 13:49:05 +00:00
Files
openvswitch/python/ovs/_json.c
Ilya Maximets 78dad3a0c8 python-c-ext: Use designated initializers for type and module.
Python documentation suggests to do so "to avoid listing all the
PyTypeObject fields that you don't care about and also to avoid
caring about the fields' declaration order".  And that does make
sense.

Acked-by: Dumitru Ceara <dceara@redhat.com>
Signed-off-by: Ilya Maximets <i.maximets@ovn.org>
2022-08-30 21:41:32 +02:00

212 lines
5.1 KiB
C

#include "Python.h"
#include <openvswitch/json.h>
#include "structmember.h"
typedef struct {
PyObject_HEAD
struct json_parser *_parser;
} json_ParserObject;
static void
Parser_dealloc(json_ParserObject * p)
{
json_parser_abort(p->_parser);
Py_TYPE(p)->tp_free(p);
}
static PyObject *
Parser_new(PyTypeObject * type, PyObject * args, PyObject * kwargs)
{
json_ParserObject *self;
static char *kwlist[] = { "check_trailer", NULL };
PyObject *check_trailer = NULL;
int ct_int = 0;
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|O", kwlist,
&check_trailer)) {
return NULL;
}
if (check_trailer != NULL) {
ct_int = PyObject_IsTrue(check_trailer);
if (ct_int < 0) {
return NULL;
} else if (ct_int) {
ct_int = JSPF_TRAILER;
}
}
self = (json_ParserObject *) type->tp_alloc(type, 0);
if (self != NULL) {
self->_parser = json_parser_create(ct_int);
}
return (PyObject *) self;
}
static PyObject *
Parser_feed(json_ParserObject * self, PyObject * args)
{
Py_ssize_t input_sz;
PyObject *input;
size_t rd;
const char *input_str;
if (self->_parser == NULL) {
return NULL;
}
if (!PyArg_UnpackTuple(args, "input", 1, 1, &input)) {
return NULL;
}
if ((input_str = PyUnicode_AsUTF8AndSize(input, &input_sz)) == NULL) {
return NULL;
}
rd = json_parser_feed(self->_parser, input_str, (size_t) input_sz);
return PyLong_FromSize_t(rd);
}
static PyObject *
Parser_is_done(json_ParserObject * self)
{
if (self->_parser == NULL) {
return NULL;
}
return PyBool_FromLong(json_parser_is_done(self->_parser));
}
static PyObject *
json_to_python(struct json *json)
{
switch (json->type) {
case JSON_NULL:
Py_RETURN_NONE;
case JSON_FALSE:
Py_RETURN_FALSE;
case JSON_TRUE:
Py_RETURN_TRUE;
case JSON_OBJECT:{
struct shash_node *node;
PyObject *dict = PyDict_New();
if (dict == NULL) {
return PyErr_NoMemory();
}
SHASH_FOR_EACH (node, json->object) {
PyObject *key = PyUnicode_FromString(node->name);
PyObject *val = json_to_python(node->data);
if (!(key && val) || PyDict_SetItem(dict, key, val)) {
Py_XDECREF(key);
Py_XDECREF(val);
Py_XDECREF(dict);
return NULL;
}
Py_XDECREF(key);
Py_XDECREF(val);
}
return dict;
}
case JSON_ARRAY:{
size_t i;
PyObject *arr = PyList_New(json->array.n);
if (arr == NULL) {
return PyErr_NoMemory();
}
for (i = 0; i < json->array.n; i++) {
PyObject *item = json_to_python(json->array.elems[i]);
if (!item || PyList_SetItem(arr, i, item)) {
Py_XDECREF(arr);
return NULL;
}
}
return arr;
}
case JSON_REAL:
if (json->real != 0) {
return PyFloat_FromDouble(json->real);
} /* fall through to treat 0 as int */
case JSON_INTEGER:
return PyLong_FromLong((long) json->integer);
case JSON_STRING:
return PyUnicode_FromString(json->string);
default:
return NULL;
}
}
static PyObject *
Parser_finish(json_ParserObject * self)
{
struct json *json;
PyObject *obj;
if (self->_parser == NULL) {
return NULL;
}
json = json_parser_finish(self->_parser);
self->_parser = NULL;
obj = json_to_python(json);
json_destroy(json);
return obj;
}
static PyMethodDef Parser_methods[] = {
{"feed", (PyCFunction) Parser_feed, METH_VARARGS,
"Feed data to the parser and return the index of the last object."},
{"is_done", (PyCFunction) Parser_is_done, METH_NOARGS,
"Whether the parser has finished decoding an object."},
{"finish", (PyCFunction) Parser_finish, METH_NOARGS,
"Finish parsing and return Python object parsed."},
{NULL},
};
static PyTypeObject json_ParserType = {
PyVarObject_HEAD_INIT(NULL, 0)
.tp_name = "ovs._json.Parser",
.tp_doc = "Parser objects",
.tp_basicsize = sizeof(json_ParserObject),
.tp_itemsize = 0,
.tp_dealloc = (destructor) Parser_dealloc,
.tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
.tp_methods = Parser_methods,
.tp_new = Parser_new,
};
static struct PyModuleDef moduledef = {
PyModuleDef_HEAD_INIT,
.m_name = "ovs._json",
.m_doc = "OVS JSON Parser module",
.m_size = 0,
};
PyMODINIT_FUNC
PyInit__json(void)
{
PyObject *m;
if (PyType_Ready(&json_ParserType) < 0) {
return NULL;
}
m = PyModule_Create(&moduledef);
if (!m) {
return NULL;
}
Py_INCREF(&json_ParserType);
if (PyModule_AddObject(m, "Parser", (PyObject *) &json_ParserType) < 0) {
Py_DECREF(&json_ParserType);
Py_DECREF(m);
return NULL;
}
return m;
}