1 // Attempts to load a UCL structure from a string 2 #include <ucl.h> 3 #include <Python.h> 4 5 static PyObject* 6 _basic_ucl_type(ucl_object_t const * const obj) { 7 if (obj->type == UCL_INT) { 8 return Py_BuildValue("L", (long long)ucl_object_toint (obj)); 9 } 10 else if (obj->type == UCL_FLOAT) { 11 return Py_BuildValue("d", ucl_object_todouble (obj)); 12 } 13 else if (obj->type == UCL_STRING) { 14 return Py_BuildValue("s", ucl_object_tostring (obj)); 15 } 16 else if (obj->type == UCL_BOOLEAN) { 17 // maybe used 'p' here? 18 return Py_BuildValue("s", ucl_object_tostring_forced (obj)); 19 } 20 else if (obj->type == UCL_TIME) { 21 return Py_BuildValue("d", ucl_object_todouble (obj)); 22 } 23 return NULL; 24 } 25 26 static PyObject* 27 _iterate_valid_ucl(ucl_object_t const * obj) { 28 const ucl_object_t *tmp; 29 ucl_object_iter_t it = NULL; 30 31 tmp = obj; 32 33 while ((obj = ucl_iterate_object (tmp, &it, false))) { 34 35 PyObject* val; 36 37 val = _basic_ucl_type(obj); 38 if (!val) { 39 PyObject* key = NULL; 40 if (obj->key != NULL) { 41 key = Py_BuildValue("s", ucl_object_key(obj)); 42 } 43 44 PyObject* ret; 45 ret = PyDict_New(); 46 if (obj->type == UCL_OBJECT) { 47 val = PyDict_New(); 48 const ucl_object_t *cur; 49 ucl_object_iter_t it_obj = NULL; 50 while ((cur = ucl_iterate_object (obj, &it_obj, true))) { 51 PyObject* keyobj = Py_BuildValue("s",ucl_object_key(cur)); 52 PyDict_SetItem(val, keyobj, _iterate_valid_ucl(cur)); 53 } 54 } 55 else if (obj->type == UCL_ARRAY) { 56 val = PyList_New(0); 57 const ucl_object_t *cur; 58 ucl_object_iter_t it_obj = NULL; 59 while ((cur = ucl_iterate_object (obj, &it_obj, true))) { 60 PyList_Append(val, _iterate_valid_ucl(cur)); 61 } 62 } 63 else if (obj->type == UCL_USERDATA) { 64 // XXX: this should be 65 // PyBytes_FromStringAndSize; where is the 66 // length from? 67 val = PyBytes_FromString(obj->value.ud); 68 } 69 } 70 return val; 71 } 72 73 PyErr_SetString(PyExc_SystemError, "unhandled type"); 74 return NULL; 75 } 76 77 static PyObject* 78 _internal_load_ucl(char* uclstr) { 79 PyObject* ret; 80 81 struct ucl_parser *parser = ucl_parser_new (UCL_PARSER_NO_TIME); 82 83 bool r = ucl_parser_add_string(parser, uclstr, 0); 84 if (r) { 85 if (ucl_parser_get_error (parser)) { 86 PyErr_SetString(PyExc_ValueError, ucl_parser_get_error(parser)); 87 ucl_parser_free(parser); 88 ret = NULL; 89 goto return_with_parser; 90 } else { 91 ucl_object_t* uclobj = ucl_parser_get_object(parser); 92 ret = _iterate_valid_ucl(uclobj); 93 ucl_object_unref(uclobj); 94 goto return_with_parser; 95 } 96 97 } else { 98 PyErr_SetString(PyExc_ValueError, ucl_parser_get_error (parser)); 99 ret = NULL; 100 goto return_with_parser; 101 } 102 103 return_with_parser: 104 ucl_parser_free(parser); 105 return ret; 106 } 107 108 static PyObject* 109 ucl_load(PyObject *self, PyObject *args) { 110 char* uclstr; 111 if (PyArg_ParseTuple(args, "z", &uclstr)) { 112 if (!uclstr) { 113 Py_RETURN_NONE; 114 } 115 return _internal_load_ucl(uclstr); 116 } 117 return NULL; 118 } 119 120 static PyObject* 121 ucl_validate(PyObject *self, PyObject *args) { 122 char *uclstr, *schema; 123 if (PyArg_ParseTuple(args, "zz", &uclstr, &schema)) { 124 if (!uclstr || !schema) { 125 Py_RETURN_NONE; 126 } 127 PyErr_SetString(PyExc_NotImplementedError, "schema validation is not yet supported"); 128 return NULL; 129 } 130 return NULL; 131 } 132 133 static PyMethodDef uclMethods[] = { 134 {"load", ucl_load, METH_VARARGS, "Load UCL from stream"}, 135 {"validate", ucl_validate, METH_VARARGS, "Validate ucl stream against schema"}, 136 {NULL, NULL, 0, NULL} 137 }; 138 139 #if PY_MAJOR_VERSION >= 3 140 static struct PyModuleDef uclmodule = { 141 PyModuleDef_HEAD_INIT, 142 "ucl", 143 NULL, 144 -1, 145 uclMethods 146 }; 147 148 PyMODINIT_FUNC 149 PyInit_ucl(void) { 150 return PyModule_Create(&uclmodule); 151 } 152 #else 153 void initucl(void) { 154 Py_InitModule("ucl", uclMethods); 155 } 156 #endif 157