1 // Attempts to load a UCL structure from a string
5 static PyObject *SchemaError;
8 _basic_ucl_type (ucl_object_t const *obj)
12 return Py_BuildValue ("L", (long long)ucl_object_toint (obj));
14 return Py_BuildValue ("d", ucl_object_todouble (obj));
16 return Py_BuildValue ("s", ucl_object_tostring (obj));
18 return PyBool_FromLong (ucl_object_toboolean (obj));
20 return Py_BuildValue ("d", ucl_object_todouble (obj));
28 _iterate_valid_ucl (ucl_object_t const *obj)
30 const ucl_object_t *tmp;
31 ucl_object_iter_t it = NULL;
35 while ((obj = ucl_object_iterate (tmp, &it, false))) {
38 val = _basic_ucl_type(obj);
42 if (obj->key != NULL) {
43 key = Py_BuildValue("s", ucl_object_key(obj));
46 if (obj->type == UCL_OBJECT) {
47 const ucl_object_t *cur;
48 ucl_object_iter_t it_obj = NULL;
52 while ((cur = ucl_object_iterate (obj, &it_obj, true))) {
53 PyObject *keyobj = Py_BuildValue("s",ucl_object_key(cur));
54 PyDict_SetItem(val, keyobj, _iterate_valid_ucl(cur));
56 } else if (obj->type == UCL_ARRAY) {
57 const ucl_object_t *cur;
58 ucl_object_iter_t it_obj = NULL;
62 while ((cur = ucl_object_iterate (obj, &it_obj, true))) {
63 PyList_Append(val, _iterate_valid_ucl(cur));
65 } else if (obj->type == UCL_USERDATA) {
66 // XXX: this should be
67 // PyBytes_FromStringAndSize; where is the
69 val = PyBytes_FromString(obj->value.ud);
75 PyErr_SetString(PyExc_SystemError, "unhandled type");
80 _internal_load_ucl (char *uclstr)
83 struct ucl_parser *parser =
84 ucl_parser_new (UCL_PARSER_NO_TIME|UCL_PARSER_NO_IMPLICIT_ARRAYS);
85 bool r = ucl_parser_add_string(parser, uclstr, 0);
88 if (ucl_parser_get_error (parser)) {
89 PyErr_SetString(PyExc_ValueError, ucl_parser_get_error(parser));
90 ucl_parser_free(parser);
92 goto return_with_parser;
94 ucl_object_t *uclobj = ucl_parser_get_object(parser);
95 ret = _iterate_valid_ucl(uclobj);
96 ucl_object_unref(uclobj);
97 goto return_with_parser;
101 PyErr_SetString(PyExc_ValueError, ucl_parser_get_error (parser));
103 goto return_with_parser;
107 ucl_parser_free(parser);
112 ucl_load (PyObject *self, PyObject *args)
116 if (PyArg_ParseTuple(args, "z", &uclstr)) {
121 return _internal_load_ucl(uclstr);
127 static ucl_object_t *
128 _iterate_python (PyObject *obj)
130 if (obj == Py_None) {
131 return ucl_object_new();
133 else if (PyBool_Check (obj)) {
134 return ucl_object_frombool (obj == Py_True);
136 #if PY_MAJOR_VERSION < 3
137 else if (PyInt_Check (obj)) {
138 return ucl_object_fromint (PyInt_AsLong (obj));
141 else if (PyLong_Check (obj)) {
142 return ucl_object_fromint (PyLong_AsLong (obj));
144 else if (PyFloat_Check (obj)) {
145 return ucl_object_fromdouble (PyFloat_AsDouble (obj));
147 else if (PyUnicode_Check (obj)) {
148 ucl_object_t *ucl_str;
149 PyObject *str = PyUnicode_AsASCIIString(obj);
150 ucl_str = ucl_object_fromstring (PyBytes_AsString (str));
154 #if PY_MAJOR_VERSION < 3
155 else if (PyString_Check (obj)) {
156 return ucl_object_fromstring (PyString_AsString (obj));
159 else if (PyDict_Check(obj)) {
160 PyObject *key, *value;
162 ucl_object_t *top, *elm;
165 top = ucl_object_typed_new (UCL_OBJECT);
167 while (PyDict_Next(obj, &pos, &key, &value)) {
168 elm = _iterate_python(value);
170 if (PyUnicode_Check(key)) {
171 PyObject *keyascii = PyUnicode_AsASCIIString(key);
172 keystr = PyBytes_AsString(keyascii);
175 #if PY_MAJOR_VERSION < 3
176 else if (PyString_Check(key)) {
177 keystr = PyString_AsString(key);
181 PyErr_SetString(PyExc_TypeError, "Unknown key type");
185 ucl_object_insert_key (top, elm, keystr, 0, true);
190 else if (PySequence_Check(obj)) {
193 ucl_object_t *top, *elm;
195 len = PySequence_Length(obj);
196 top = ucl_object_typed_new (UCL_ARRAY);
198 for (pos = 0; pos < len; pos++) {
199 value = PySequence_GetItem(obj, pos);
200 elm = _iterate_python(value);
201 ucl_array_append(top, elm);
207 PyErr_SetString(PyExc_TypeError, "Unhandled object type");
215 ucl_dump (PyObject *self, PyObject *args)
218 ucl_emitter_t emitter;
219 ucl_object_t *root = NULL;
221 emitter = UCL_EMIT_CONFIG;
223 if (!PyArg_ParseTuple(args, "O|i", &obj, &emitter)) {
224 PyErr_SetString(PyExc_TypeError, "Unhandled object type");
228 if (emitter >= UCL_EMIT_MAX) {
229 PyErr_SetString(PyExc_TypeError, "Invalid emitter type");
233 if (obj == Py_None) {
237 root = _iterate_python(obj);
242 buf = (char *) ucl_object_emit (root, emitter);
243 ucl_object_unref (root);
244 #if PY_MAJOR_VERSION < 3
245 ret = PyString_FromString (buf);
247 ret = PyUnicode_FromString (buf);
258 ucl_validate (PyObject *self, PyObject *args)
260 PyObject *dataobj, *schemaobj;
261 ucl_object_t *data, *schema;
263 struct ucl_schema_error err;
265 if (!PyArg_ParseTuple (args, "OO", &schemaobj, &dataobj)) {
266 PyErr_SetString (PyExc_TypeError, "Unhandled object type");
270 schema = _iterate_python(schemaobj);
274 data = _iterate_python(dataobj);
279 r = ucl_object_validate (schema, data, &err);
280 ucl_object_unref (schema);
281 ucl_object_unref (data);
284 PyErr_SetString (SchemaError, err.msg);
291 static PyMethodDef uclMethods[] = {
292 {"load", ucl_load, METH_VARARGS, "Load UCL from stream"},
293 {"dump", ucl_dump, METH_VARARGS, "Dump UCL to stream"},
294 {"validate", ucl_validate, METH_VARARGS, "Validate ucl stream against schema"},
295 {NULL, NULL, 0, NULL}
299 init_macros(PyObject *mod)
301 PyModule_AddIntMacro(mod, UCL_EMIT_JSON);
302 PyModule_AddIntMacro(mod, UCL_EMIT_JSON_COMPACT);
303 PyModule_AddIntMacro(mod, UCL_EMIT_CONFIG);
304 PyModule_AddIntMacro(mod, UCL_EMIT_YAML);
305 PyModule_AddIntMacro(mod, UCL_EMIT_MSGPACK);
307 SchemaError = PyErr_NewException("ucl.SchemaError", NULL, NULL);
308 Py_INCREF(SchemaError);
309 PyModule_AddObject(mod, "SchemaError", SchemaError);
312 #if PY_MAJOR_VERSION >= 3
313 static struct PyModuleDef uclmodule = {
314 PyModuleDef_HEAD_INIT,
324 PyObject *mod = PyModule_Create (&uclmodule);
332 PyObject *mod = Py_InitModule ("ucl", uclMethods);