diff options
Diffstat (limited to 'contrib/libucl/python/src/uclmodule.c')
-rw-r--r-- | contrib/libucl/python/src/uclmodule.c | 223 |
1 files changed, 171 insertions, 52 deletions
diff --git a/contrib/libucl/python/src/uclmodule.c b/contrib/libucl/python/src/uclmodule.c index d63b73a..bc13c70 100644 --- a/contrib/libucl/python/src/uclmodule.c +++ b/contrib/libucl/python/src/uclmodule.c @@ -2,65 +2,63 @@ #include <ucl.h> #include <Python.h> -static PyObject* -_basic_ucl_type(ucl_object_t const * const obj) { - if (obj->type == UCL_INT) { - return Py_BuildValue("L", (long long)ucl_object_toint (obj)); - } - else if (obj->type == UCL_FLOAT) { - return Py_BuildValue("d", ucl_object_todouble (obj)); - } - else if (obj->type == UCL_STRING) { - return Py_BuildValue("s", ucl_object_tostring (obj)); - } - else if (obj->type == UCL_BOOLEAN) { - // maybe used 'p' here? - return Py_BuildValue("s", ucl_object_tostring_forced (obj)); - } - else if (obj->type == UCL_TIME) { - return Py_BuildValue("d", ucl_object_todouble (obj)); +static PyObject * +_basic_ucl_type (ucl_object_t const *obj) +{ + switch (obj->type) { + case UCL_INT: + return Py_BuildValue ("L", (long long)ucl_object_toint (obj)); + case UCL_FLOAT: + return Py_BuildValue ("d", ucl_object_todouble (obj)); + case UCL_STRING: + return Py_BuildValue ("s", ucl_object_tostring (obj)); + case UCL_BOOLEAN: + return ucl_object_toboolean (obj) ? Py_True : Py_False; + case UCL_TIME: + return Py_BuildValue ("d", ucl_object_todouble (obj)); } return NULL; } -static PyObject* -_iterate_valid_ucl(ucl_object_t const * obj) { +static PyObject * +_iterate_valid_ucl (ucl_object_t const *obj) +{ const ucl_object_t *tmp; ucl_object_iter_t it = NULL; tmp = obj; - while ((obj = ucl_iterate_object (tmp, &it, false))) { - - PyObject* val; + while ((obj = ucl_object_iterate (tmp, &it, false))) { + PyObject *val; val = _basic_ucl_type(obj); if (!val) { - PyObject* key = NULL; + PyObject *key = NULL; + if (obj->key != NULL) { key = Py_BuildValue("s", ucl_object_key(obj)); } - PyObject* ret; - ret = PyDict_New(); if (obj->type == UCL_OBJECT) { - val = PyDict_New(); const ucl_object_t *cur; ucl_object_iter_t it_obj = NULL; - while ((cur = ucl_iterate_object (obj, &it_obj, true))) { - PyObject* keyobj = Py_BuildValue("s",ucl_object_key(cur)); + + val = PyDict_New(); + + while ((cur = ucl_object_iterate (obj, &it_obj, true))) { + PyObject *keyobj = Py_BuildValue("s",ucl_object_key(cur)); PyDict_SetItem(val, keyobj, _iterate_valid_ucl(cur)); } - } - else if (obj->type == UCL_ARRAY) { - val = PyList_New(0); + } else if (obj->type == UCL_ARRAY) { const ucl_object_t *cur; ucl_object_iter_t it_obj = NULL; - while ((cur = ucl_iterate_object (obj, &it_obj, true))) { + + val = PyList_New(0); + + while ((cur = ucl_object_iterate (obj, &it_obj, true))) { PyList_Append(val, _iterate_valid_ucl(cur)); } - } - else if (obj->type == UCL_USERDATA) { + } else if (obj->type == UCL_USERDATA) { // XXX: this should be // PyBytes_FromStringAndSize; where is the // length from? @@ -74,13 +72,13 @@ _iterate_valid_ucl(ucl_object_t const * obj) { return NULL; } -static PyObject* -_internal_load_ucl(char* uclstr) { - PyObject* ret; - +static PyObject * +_internal_load_ucl (char *uclstr) +{ + PyObject *ret; struct ucl_parser *parser = ucl_parser_new (UCL_PARSER_NO_TIME); - bool r = ucl_parser_add_string(parser, uclstr, 0); + if (r) { if (ucl_parser_get_error (parser)) { PyErr_SetString(PyExc_ValueError, ucl_parser_get_error(parser)); @@ -88,13 +86,13 @@ _internal_load_ucl(char* uclstr) { ret = NULL; goto return_with_parser; } else { - ucl_object_t* uclobj = ucl_parser_get_object(parser); + ucl_object_t *uclobj = ucl_parser_get_object(parser); ret = _iterate_valid_ucl(uclobj); ucl_object_unref(uclobj); goto return_with_parser; } - - } else { + } + else { PyErr_SetString(PyExc_ValueError, ucl_parser_get_error (parser)); ret = NULL; goto return_with_parser; @@ -106,36 +104,151 @@ return_with_parser: } static PyObject* -ucl_load(PyObject *self, PyObject *args) { - char* uclstr; +ucl_load (PyObject *self, PyObject *args) +{ + char *uclstr; + if (PyArg_ParseTuple(args, "z", &uclstr)) { if (!uclstr) { Py_RETURN_NONE; } + return _internal_load_ucl(uclstr); } + return NULL; } -static PyObject* -ucl_validate(PyObject *self, PyObject *args) { - char *uclstr, *schema; +static ucl_object_t * +_iterate_python (PyObject *obj) +{ + if (obj == Py_None) { + return ucl_object_new(); + } else if (PyBool_Check (obj)) { + return ucl_object_frombool (obj == Py_True); + } else if (PyInt_Check (obj)) { + return ucl_object_fromint (PyInt_AsLong (obj)); + } else if (PyFloat_Check (obj)) { + return ucl_object_fromdouble (PyFloat_AsDouble (obj)); + } else if (PyString_Check (obj)) { + return ucl_object_fromstring (PyString_AsString (obj)); + // } else if (PyDateTime_Check (obj)) { + } + else if (PyDict_Check(obj)) { + PyObject *key, *value; + Py_ssize_t pos = 0; + ucl_object_t *top, *elm; + + top = ucl_object_typed_new (UCL_OBJECT); + + while (PyDict_Next(obj, &pos, &key, &value)) { + elm = _iterate_python(value); + ucl_object_insert_key (top, elm, PyString_AsString(key), 0, true); + } + + return top; + } + else if (PySequence_Check(obj)) { + PyObject *value; + Py_ssize_t len, pos; + ucl_object_t *top, *elm; + + len = PySequence_Length(obj); + top = ucl_object_typed_new (UCL_ARRAY); + + for (pos = 0; pos < len; pos++) { + value = PySequence_GetItem(obj, pos); + elm = _iterate_python(value); + ucl_array_append(top, elm); + } + + return top; + } + else { + PyErr_SetString(PyExc_TypeError, "Unhandled object type"); + return NULL; + } + + return NULL; +} + +static PyObject * +ucl_dump (PyObject *self, PyObject *args) +{ + PyObject *obj; + ucl_emitter_t emitter; + ucl_object_t *root = NULL; + + emitter = UCL_EMIT_CONFIG; + + if (!PyArg_ParseTuple(args, "O|i", &obj, &emitter)) { + PyErr_SetString(PyExc_TypeError, "Unhandled object type"); + return NULL; + } + + if (emitter >= UCL_EMIT_MAX) { + PyErr_SetString(PyExc_TypeError, "Invalid emitter type"); + return NULL; + } + + if (obj == Py_None) { + Py_RETURN_NONE; + } + + if (!PyDict_Check(obj)) { + PyErr_SetString(PyExc_TypeError, "Argument must be dict"); + return NULL; + } + + root = _iterate_python(obj); + if (root) { + PyObject *ret; + char *buf; + + buf = (char *) ucl_object_emit (root, emitter); + ucl_object_unref (root); + ret = PyString_FromString (buf); + free(buf); + + return ret; + } + + return NULL; +} + +static PyObject * +ucl_validate (PyObject *self, PyObject *args) +{ + char *uclstr, *schema; + if (PyArg_ParseTuple(args, "zz", &uclstr, &schema)) { if (!uclstr || !schema) { Py_RETURN_NONE; } + PyErr_SetString(PyExc_NotImplementedError, "schema validation is not yet supported"); - return NULL; } + return NULL; } static PyMethodDef uclMethods[] = { {"load", ucl_load, METH_VARARGS, "Load UCL from stream"}, + {"dump", ucl_dump, METH_VARARGS, "Dump UCL to stream"}, {"validate", ucl_validate, METH_VARARGS, "Validate ucl stream against schema"}, {NULL, NULL, 0, NULL} }; +static void +init_macros(PyObject *mod) +{ + PyModule_AddIntMacro(mod, UCL_EMIT_JSON); + PyModule_AddIntMacro(mod, UCL_EMIT_JSON_COMPACT); + PyModule_AddIntMacro(mod, UCL_EMIT_CONFIG); + PyModule_AddIntMacro(mod, UCL_EMIT_YAML); + PyModule_AddIntMacro(mod, UCL_EMIT_MSGPACK); +} + #if PY_MAJOR_VERSION >= 3 static struct PyModuleDef uclmodule = { PyModuleDef_HEAD_INIT, @@ -146,11 +259,17 @@ static struct PyModuleDef uclmodule = { }; PyMODINIT_FUNC -PyInit_ucl(void) { - return PyModule_Create(&uclmodule); +PyInit_ucl (void) +{ + PyObject *mod = PyModule_Create (&uclmodule); + init_macros (mod); + + return mod; } #else -void initucl(void) { - Py_InitModule("ucl", uclMethods); +void initucl (void) +{ + PyObject *mod = Py_InitModule ("ucl", uclMethods); + init_macros (mod); } #endif |