2
0
mirror of https://github.com/openvswitch/ovs synced 2025-10-23 14:57:06 +00:00
Files
openvswitch/python/ovs/_json.c

212 lines
5.1 KiB
C
Raw Normal View History

#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;
}