1 // Attempts to load a UCL structure from a string
2 #include <ucl.h>
3 #include <Python.h>
4
5 static PyObject*
_basic_ucl_type(ucl_object_t const * const obj)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*
_iterate_valid_ucl(ucl_object_t const * obj)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*
_internal_load_ucl(char * uclstr)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*
ucl_load(PyObject * self,PyObject * args)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*
ucl_validate(PyObject * self,PyObject * args)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
PyInit_ucl(void)149 PyInit_ucl(void) {
150 return PyModule_Create(&uclmodule);
151 }
152 #else
initucl(void)153 void initucl(void) {
154 Py_InitModule("ucl", uclMethods);
155 }
156 #endif
157