Skip to content

Commit cde0ca2

Browse files
committed
py: Simplify JSON str printing (while still conforming to JSON spec).
The JSON specs are relatively flexible and allow us to use one function to print strings, be they ascii, bytes or utf-8 encoded.
1 parent d19c256 commit cde0ca2

4 files changed

Lines changed: 12 additions & 41 deletions

File tree

py/objstr.c

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -93,24 +93,24 @@ void mp_str_print_quoted(void (*print)(void *env, const char *fmt, ...), void *e
9393
}
9494

9595
#if MICROPY_PY_UJSON
96-
STATIC void str_print_json(void (*print)(void *env, const char *fmt, ...), void *env, const byte *str_data, mp_uint_t str_len) {
96+
void mp_str_print_json(void (*print)(void *env, const char *fmt, ...), void *env, const byte *str_data, mp_uint_t str_len) {
97+
// for JSON spec, see http://www.ietf.org/rfc/rfc4627.txt
98+
// if we are given a valid utf8-encoded string, we will print it in a JSON-conforming way
9799
print(env, "\"");
98100
for (const byte *s = str_data, *top = str_data + str_len; s < top; s++) {
99-
if (*s == '"' || *s == '\\' || *s == '/') {
101+
if (*s == '"' || *s == '\\') {
100102
print(env, "\\%c", *s);
101-
} else if (32 <= *s && *s <= 126) {
103+
} else if (*s >= 32) {
104+
// this will handle normal and utf-8 encoded chars
102105
print(env, "%c", *s);
103-
} else if (*s == '\b') {
104-
print(env, "\\b");
105-
} else if (*s == '\f') {
106-
print(env, "\\f");
107106
} else if (*s == '\n') {
108107
print(env, "\\n");
109108
} else if (*s == '\r') {
110109
print(env, "\\r");
111110
} else if (*s == '\t') {
112111
print(env, "\\t");
113112
} else {
113+
// this will handle control chars
114114
print(env, "\\u%04x", *s);
115115
}
116116
}
@@ -120,13 +120,13 @@ STATIC void str_print_json(void (*print)(void *env, const char *fmt, ...), void
120120

121121
STATIC void str_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in, mp_print_kind_t kind) {
122122
GET_STR_DATA_LEN(self_in, str_data, str_len);
123-
bool is_bytes = MP_OBJ_IS_TYPE(self_in, &mp_type_bytes);
124123
#if MICROPY_PY_UJSON
125124
if (kind == PRINT_JSON) {
126-
str_print_json(print, env, str_data, str_len);
125+
mp_str_print_json(print, env, str_data, str_len);
127126
return;
128127
}
129128
#endif
129+
bool is_bytes = MP_OBJ_IS_TYPE(self_in, &mp_type_bytes);
130130
if (kind == PRINT_STR && !is_bytes) {
131131
print(env, "%.*s", str_len, str_data);
132132
} else {

py/objstr.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ typedef struct _mp_obj_str_t {
5050
{ str_data = qstr_data(MP_OBJ_QSTR_VALUE(str_obj_in), &str_len); } \
5151
else { str_len = ((mp_obj_str_t*)str_obj_in)->len; str_data = ((mp_obj_str_t*)str_obj_in)->data; }
5252

53+
void mp_str_print_json(void (*print)(void *env, const char *fmt, ...), void *env, const byte *str_data, mp_uint_t str_len);
5354
mp_obj_t mp_obj_str_format(mp_uint_t n_args, const mp_obj_t *args);
5455
mp_obj_t mp_obj_new_str_of_type(const mp_obj_type_t *type, const byte* data, mp_uint_t len);
5556

py/objstrunicode.c

Lines changed: 1 addition & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -91,41 +91,11 @@ STATIC void uni_print_quoted(void (*print)(void *env, const char *fmt, ...), voi
9191
print(env, "%c", quote_char);
9292
}
9393

94-
#if MICROPY_PY_UJSON
95-
STATIC void uni_print_json(void (*print)(void *env, const char *fmt, ...), void *env, const byte *str_data, uint str_len) {
96-
print(env, "\"");
97-
const byte *s = str_data, *top = str_data + str_len;
98-
while (s < top) {
99-
unichar ch;
100-
ch = utf8_get_char(s);
101-
s = utf8_next_char(s);
102-
if (ch == '"' || ch == '\\' || ch == '/') {
103-
print(env, "\\%c", ch);
104-
} else if (32 <= ch && ch <= 126) {
105-
print(env, "%c", ch);
106-
} else if (*s == '\b') {
107-
print(env, "\\b");
108-
} else if (*s == '\f') {
109-
print(env, "\\f");
110-
} else if (*s == '\n') {
111-
print(env, "\\n");
112-
} else if (*s == '\r') {
113-
print(env, "\\r");
114-
} else if (*s == '\t') {
115-
print(env, "\\t");
116-
} else {
117-
print(env, "\\u%04x", ch);
118-
}
119-
}
120-
print(env, "\"");
121-
}
122-
#endif
123-
12494
STATIC void uni_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in, mp_print_kind_t kind) {
12595
GET_STR_DATA_LEN(self_in, str_data, str_len);
12696
#if MICROPY_PY_UJSON
12797
if (kind == PRINT_JSON) {
128-
uni_print_json(print, env, str_data, str_len);
98+
mp_str_print_json(print, env, str_data, str_len);
12999
return;
130100
}
131101
#endif

tests/extmod/ujson_dumps.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
print(json.dumps(1))
1010
print(json.dumps(1.2))
1111
print(json.dumps('abc'))
12-
print(json.dumps('\x01\x7e\x7f\x80\u1234'))
12+
print(json.dumps('\x00\x01\x7e'))
1313
print(json.dumps([]))
1414
print(json.dumps([1]))
1515
print(json.dumps([1, 2]))

0 commit comments

Comments
 (0)