summaryrefslogtreecommitdiff
path: root/py
diff options
context:
space:
mode:
authorDamien George <damien.p.george@gmail.com>2014-09-17 22:56:34 +0100
committerDamien George <damien.p.george@gmail.com>2014-09-17 22:56:34 +0100
commit612045f53f7e5edf9faa359ee9ee52d490d58000 (patch)
treea021612e31ff6275246514405c4a8421c6eff5d7 /py
parent8a9b999f1c9a0edf84b2507940efb8deaaa380b8 (diff)
py: Add native json printing using existing print framework.
Also add start of ujson module with dumps implemented. Enabled in unix and stmhal ports. Test passes on both.
Diffstat (limited to 'py')
-rw-r--r--py/builtin.h1
-rw-r--r--py/builtintables.c3
-rw-r--r--py/mpconfig.h4
-rw-r--r--py/obj.h3
-rw-r--r--py/objbool.c14
-rw-r--r--py/objdict.c7
-rw-r--r--py/objlist.c5
-rw-r--r--py/objnone.c6
-rw-r--r--py/objstr.c32
-rw-r--r--py/objstrunicode.c36
-rw-r--r--py/objtuple.c19
-rw-r--r--py/py.mk1
-rw-r--r--py/qstrdefs.h5
13 files changed, 123 insertions, 13 deletions
diff --git a/py/builtin.h b/py/builtin.h
index 1bb61f6eb..9c8b2b9be 100644
--- a/py/builtin.h
+++ b/py/builtin.h
@@ -89,3 +89,4 @@ extern struct _dummy_t mp_sys_stderr_obj;
// extmod modules
extern const mp_obj_module_t mp_module_uctypes;
extern const mp_obj_module_t mp_module_zlibd;
+extern const mp_obj_module_t mp_module_ujson;
diff --git a/py/builtintables.c b/py/builtintables.c
index 08b6b1649..391077d43 100644
--- a/py/builtintables.c
+++ b/py/builtintables.c
@@ -200,6 +200,9 @@ STATIC const mp_map_elem_t mp_builtin_module_table[] = {
#if MICROPY_PY_ZLIBD
{ MP_OBJ_NEW_QSTR(MP_QSTR_zlibd), (mp_obj_t)&mp_module_zlibd },
#endif
+#if MICROPY_PY_UJSON
+ { MP_OBJ_NEW_QSTR(MP_QSTR_ujson), (mp_obj_t)&mp_module_ujson },
+#endif
// extra builtin modules as defined by a port
MICROPY_PORT_BUILTIN_MODULES
diff --git a/py/mpconfig.h b/py/mpconfig.h
index adbcb0eb7..cf8553339 100644
--- a/py/mpconfig.h
+++ b/py/mpconfig.h
@@ -390,6 +390,10 @@ typedef double mp_float_t;
#define MICROPY_PY_ZLIBD (0)
#endif
+#ifndef MICROPY_PY_UJSON
+#define MICROPY_PY_UJSON (0)
+#endif
+
/*****************************************************************************/
/* Hooks for a port to add builtins */
diff --git a/py/obj.h b/py/obj.h
index c7745dc9e..9fee0413a 100644
--- a/py/obj.h
+++ b/py/obj.h
@@ -187,7 +187,8 @@ typedef enum {
PRINT_STR = 0,
PRINT_REPR = 1,
PRINT_EXC = 2, // Special format for printing exception in unhandled exception message
- PRINT_EXC_SUBCLASS = 4, // Internal flag for printing exception subclasses
+ PRINT_JSON = 3,
+ PRINT_EXC_SUBCLASS = 0x80, // Internal flag for printing exception subclasses
} mp_print_kind_t;
typedef void (*mp_print_fun_t)(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t o, mp_print_kind_t kind);
diff --git a/py/objbool.c b/py/objbool.c
index dbe84d92e..e6b5230f7 100644
--- a/py/objbool.c
+++ b/py/objbool.c
@@ -41,10 +41,18 @@ typedef struct _mp_obj_bool_t {
STATIC void bool_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in, mp_print_kind_t kind) {
mp_obj_bool_t *self = self_in;
- if (self->value) {
- print(env, "True");
+ if (MICROPY_PY_UJSON && kind == PRINT_JSON) {
+ if (self->value) {
+ print(env, "true");
+ } else {
+ print(env, "false");
+ }
} else {
- print(env, "False");
+ if (self->value) {
+ print(env, "True");
+ } else {
+ print(env, "False");
+ }
}
}
diff --git a/py/objdict.c b/py/objdict.c
index a378bf6db..a62432042 100644
--- a/py/objdict.c
+++ b/py/objdict.c
@@ -60,6 +60,9 @@ STATIC mp_map_elem_t *dict_iter_next(mp_obj_dict_t *dict, mp_uint_t *cur) {
STATIC void dict_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in, mp_print_kind_t kind) {
mp_obj_dict_t *self = self_in;
bool first = true;
+ if (!(MICROPY_PY_UJSON && kind == PRINT_JSON)) {
+ kind = PRINT_REPR;
+ }
print(env, "{");
mp_uint_t cur = 0;
mp_map_elem_t *next = NULL;
@@ -68,9 +71,9 @@ STATIC void dict_print(void (*print)(void *env, const char *fmt, ...), void *env
print(env, ", ");
}
first = false;
- mp_obj_print_helper(print, env, next->key, PRINT_REPR);
+ mp_obj_print_helper(print, env, next->key, kind);
print(env, ": ");
- mp_obj_print_helper(print, env, next->value, PRINT_REPR);
+ mp_obj_print_helper(print, env, next->value, kind);
}
print(env, "}");
}
diff --git a/py/objlist.c b/py/objlist.c
index 59390f371..789a1600d 100644
--- a/py/objlist.c
+++ b/py/objlist.c
@@ -49,12 +49,15 @@ STATIC mp_obj_t list_pop(mp_uint_t n_args, const mp_obj_t *args);
STATIC void list_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t o_in, mp_print_kind_t kind) {
mp_obj_list_t *o = o_in;
+ if (!(MICROPY_PY_UJSON && kind == PRINT_JSON)) {
+ kind = PRINT_REPR;
+ }
print(env, "[");
for (mp_uint_t i = 0; i < o->len; i++) {
if (i > 0) {
print(env, ", ");
}
- mp_obj_print_helper(print, env, o->items[i], PRINT_REPR);
+ mp_obj_print_helper(print, env, o->items[i], kind);
}
print(env, "]");
}
diff --git a/py/objnone.c b/py/objnone.c
index a8d607143..01536dcb3 100644
--- a/py/objnone.c
+++ b/py/objnone.c
@@ -38,7 +38,11 @@ typedef struct _mp_obj_none_t {
} mp_obj_none_t;
STATIC void none_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in, mp_print_kind_t kind) {
- print(env, "None");
+ if (MICROPY_PY_UJSON && kind == PRINT_JSON) {
+ print(env, "null");
+ } else {
+ print(env, "None");
+ }
}
STATIC mp_obj_t none_unary_op(mp_uint_t op, mp_obj_t o_in) {
diff --git a/py/objstr.c b/py/objstr.c
index b2afcdc98..130af8a6a 100644
--- a/py/objstr.c
+++ b/py/objstr.c
@@ -92,9 +92,41 @@ void mp_str_print_quoted(void (*print)(void *env, const char *fmt, ...), void *e
print(env, "%c", quote_char);
}
+#if MICROPY_PY_UJSON
+STATIC void str_print_json(void (*print)(void *env, const char *fmt, ...), void *env, const byte *str_data, mp_uint_t str_len) {
+ print(env, "\"");
+ for (const byte *s = str_data, *top = str_data + str_len; s < top; s++) {
+ if (*s == '"' || *s == '\\' || *s == '/') {
+ print(env, "\\%c", *s);
+ } else if (32 <= *s && *s <= 126) {
+ print(env, "%c", *s);
+ } else if (*s == '\b') {
+ print(env, "\\b");
+ } else if (*s == '\f') {
+ print(env, "\\f");
+ } else if (*s == '\n') {
+ print(env, "\\n");
+ } else if (*s == '\r') {
+ print(env, "\\r");
+ } else if (*s == '\t') {
+ print(env, "\\t");
+ } else {
+ print(env, "\\u%04x", *s);
+ }
+ }
+ print(env, "\"");
+}
+#endif
+
STATIC void str_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in, mp_print_kind_t kind) {
GET_STR_DATA_LEN(self_in, str_data, str_len);
bool is_bytes = MP_OBJ_IS_TYPE(self_in, &mp_type_bytes);
+ #if MICROPY_PY_UJSON
+ if (kind == PRINT_JSON) {
+ str_print_json(print, env, str_data, str_len);
+ return;
+ }
+ #endif
if (kind == PRINT_STR && !is_bytes) {
print(env, "%.*s", str_len, str_data);
} else {
diff --git a/py/objstrunicode.c b/py/objstrunicode.c
index 8231eb9b1..0ee7f1dc9 100644
--- a/py/objstrunicode.c
+++ b/py/objstrunicode.c
@@ -91,8 +91,44 @@ STATIC void uni_print_quoted(void (*print)(void *env, const char *fmt, ...), voi
print(env, "%c", quote_char);
}
+#if MICROPY_PY_UJSON
+STATIC void uni_print_json(void (*print)(void *env, const char *fmt, ...), void *env, const byte *str_data, uint str_len) {
+ print(env, "\"");
+ const byte *s = str_data, *top = str_data + str_len;
+ while (s < top) {
+ unichar ch;
+ ch = utf8_get_char(s);
+ s = utf8_next_char(s);
+ if (ch == '"' || ch == '\\' || ch == '/') {
+ print(env, "\\%c", ch);
+ } else if (32 <= ch && ch <= 126) {
+ print(env, "%c", ch);
+ } else if (*s == '\b') {
+ print(env, "\\b");
+ } else if (*s == '\f') {
+ print(env, "\\f");
+ } else if (*s == '\n') {
+ print(env, "\\n");
+ } else if (*s == '\r') {
+ print(env, "\\r");
+ } else if (*s == '\t') {
+ print(env, "\\t");
+ } else {
+ print(env, "\\u%04x", ch);
+ }
+ }
+ print(env, "\"");
+}
+#endif
+
STATIC void uni_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in, mp_print_kind_t kind) {
GET_STR_DATA_LEN(self_in, str_data, str_len);
+ #if MICROPY_PY_UJSON
+ if (kind == PRINT_JSON) {
+ uni_print_json(print, env, str_data, str_len);
+ return;
+ }
+ #endif
if (kind == PRINT_STR) {
print(env, "%.*s", str_len, str_data);
} else {
diff --git a/py/objtuple.c b/py/objtuple.c
index 6abe7d2c6..2793e4838 100644
--- a/py/objtuple.c
+++ b/py/objtuple.c
@@ -43,17 +43,26 @@ STATIC mp_obj_t mp_obj_new_tuple_iterator(mp_obj_tuple_t *tuple, mp_uint_t cur);
void mp_obj_tuple_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t o_in, mp_print_kind_t kind) {
mp_obj_tuple_t *o = o_in;
- print(env, "(");
+ if (MICROPY_PY_UJSON && kind == PRINT_JSON) {
+ print(env, "[");
+ } else {
+ print(env, "(");
+ kind = PRINT_REPR;
+ }
for (mp_uint_t i = 0; i < o->len; i++) {
if (i > 0) {
print(env, ", ");
}
- mp_obj_print_helper(print, env, o->items[i], PRINT_REPR);
+ mp_obj_print_helper(print, env, o->items[i], kind);
}
- if (o->len == 1) {
- print(env, ",");
+ if (MICROPY_PY_UJSON && kind == PRINT_JSON) {
+ print(env, "]");
+ } else {
+ if (o->len == 1) {
+ print(env, ",");
+ }
+ print(env, ")");
}
- print(env, ")");
}
STATIC mp_obj_t mp_obj_tuple_make_new(mp_obj_t type_in, mp_uint_t n_args, mp_uint_t n_kw, const mp_obj_t *args) {
diff --git a/py/py.mk b/py/py.mk
index e2288d382..fb59b8972 100644
--- a/py/py.mk
+++ b/py/py.mk
@@ -112,6 +112,7 @@ PY_O_BASENAME = \
pfenv_printf.o \
../extmod/moductypes.o \
../extmod/modzlibd.o \
+ ../extmod/modujson.o \
# prepend the build destination prefix to the py object files
PY_O = $(addprefix $(PY_BUILD)/, $(PY_O_BASENAME))
diff --git a/py/qstrdefs.h b/py/qstrdefs.h
index d41029a1f..41ffa1d20 100644
--- a/py/qstrdefs.h
+++ b/py/qstrdefs.h
@@ -463,3 +463,8 @@ Q(deleter)
Q(zlibd)
Q(decompress)
#endif
+
+#if MICROPY_PY_UJSON
+Q(ujson)
+Q(dumps)
+#endif