1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211
|
#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;
}
|