|
31 | 31 | #include "py/parsenum.h"
|
32 | 32 | #include "py/runtime.h"
|
33 | 33 | #include "py/stream.h"
|
| 34 | +#include "py/nlr.h" |
34 | 35 |
|
35 | 36 | #if MICROPY_PY_UJSON
|
36 | 37 |
|
37 |
| -STATIC mp_obj_t mod_ujson_dump(mp_obj_t obj, mp_obj_t stream) { |
38 |
| - mp_get_stream_raise(stream, MP_STREAM_OP_WRITE); |
39 |
| - mp_print_t print = {MP_OBJ_TO_PTR(stream), mp_stream_write_adaptor}; |
40 |
| - mp_obj_print_helper(&print, obj, PRINT_JSON); |
| 38 | +static void mod_ujson_separators(mp_obj_t separators_in, const char **item_separator, const char **key_separator) { |
| 39 | + if (separators_in == mp_const_none) { |
| 40 | + *item_separator = ", "; |
| 41 | + *key_separator = ": "; |
| 42 | + } else { |
| 43 | + mp_obj_t *items; |
| 44 | + size_t len; |
| 45 | + mp_obj_tuple_get(separators_in, &len, &items); |
| 46 | + |
| 47 | + if (len != 2) { |
| 48 | + mp_raise_ValueError(MP_ERROR_TEXT("too many values to unpack (expected 2)")); |
| 49 | + } |
| 50 | + |
| 51 | + *item_separator = mp_obj_str_get_str(items[0]); |
| 52 | + *key_separator = mp_obj_str_get_str(items[1]); |
| 53 | + } |
| 54 | +} |
| 55 | + |
| 56 | +const char *ujson_item_separator = ", "; |
| 57 | +const char *ujson_key_separator = ": "; |
| 58 | + |
| 59 | +STATIC mp_obj_t mod_ujson_dump(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { |
| 60 | + enum {ARG_indent, ARG_separators}; |
| 61 | + const mp_arg_t allowed_args[] = { |
| 62 | + { MP_QSTR_indent, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = mp_const_none} }, |
| 63 | + { MP_QSTR_separators, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = mp_const_none} }, |
| 64 | + }; |
| 65 | + |
| 66 | + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; |
| 67 | + mp_arg_parse_all(n_args - 2, pos_args + 2, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); |
| 68 | + |
| 69 | + if (args[ARG_indent].u_obj != mp_const_none) { |
| 70 | + mp_raise_NotImplementedError(MP_ERROR_TEXT("indent is not None")); |
| 71 | + } |
| 72 | + |
| 73 | + mp_get_stream_raise(pos_args[1], MP_STREAM_OP_WRITE); |
| 74 | + |
| 75 | + const char *old_item_separator = ujson_item_separator; |
| 76 | + const char *old_key_separator = ujson_key_separator; |
| 77 | + bool raise = false; |
| 78 | + mod_ujson_separators(args[ARG_separators].u_obj, &ujson_item_separator, &ujson_key_separator); |
| 79 | + |
| 80 | + nlr_buf_t nlr; |
| 81 | + if (nlr_push(&nlr) == 0) { |
| 82 | + mp_print_t print = {MP_OBJ_TO_PTR(pos_args[1]), mp_stream_write_adaptor}; |
| 83 | + mp_obj_print_helper(&print, pos_args[0], PRINT_JSON); |
| 84 | + nlr_pop(); |
| 85 | + } else { |
| 86 | + raise = true; |
| 87 | + } |
| 88 | + |
| 89 | + // revert old values in case of nested dump |
| 90 | + ujson_item_separator = old_item_separator; |
| 91 | + ujson_key_separator = old_key_separator; |
| 92 | + |
| 93 | + // Re-raise the exception |
| 94 | + if (raise) { |
| 95 | + nlr_raise(MP_OBJ_FROM_PTR(nlr.ret_val)); |
| 96 | + } |
| 97 | + |
41 | 98 | return mp_const_none;
|
42 | 99 | }
|
43 |
| -STATIC MP_DEFINE_CONST_FUN_OBJ_2(mod_ujson_dump_obj, mod_ujson_dump); |
| 100 | +STATIC MP_DEFINE_CONST_FUN_OBJ_KW(mod_ujson_dump_obj, 2, mod_ujson_dump); |
| 101 | + |
| 102 | +STATIC mp_obj_t mod_ujson_dumps(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { |
| 103 | + enum {ARG_indent, ARG_separators}; |
| 104 | + const mp_arg_t allowed_args[] = { |
| 105 | + { MP_QSTR_indent, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = mp_const_none} }, |
| 106 | + { MP_QSTR_separators, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = mp_const_none} }, |
| 107 | + }; |
| 108 | + |
| 109 | + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; |
| 110 | + mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); |
| 111 | + |
| 112 | + if (args[ARG_indent].u_obj != mp_const_none) { |
| 113 | + mp_raise_NotImplementedError(MP_ERROR_TEXT("indent is not None")); |
| 114 | + } |
44 | 115 |
|
45 |
| -STATIC mp_obj_t mod_ujson_dumps(mp_obj_t obj) { |
46 | 116 | vstr_t vstr;
|
47 | 117 | mp_print_t print;
|
48 | 118 | vstr_init_print(&vstr, 8, &print);
|
49 |
| - mp_obj_print_helper(&print, obj, PRINT_JSON); |
| 119 | + |
| 120 | + const char *old_item_separator = ujson_item_separator; |
| 121 | + const char *old_key_separator = ujson_key_separator; |
| 122 | + bool raise = false; |
| 123 | + mod_ujson_separators(args[ARG_separators].u_obj, &ujson_item_separator, &ujson_key_separator); |
| 124 | + |
| 125 | + nlr_buf_t nlr; |
| 126 | + if (nlr_push(&nlr) == 0) { |
| 127 | + mp_obj_print_helper(&print, pos_args[0], PRINT_JSON); |
| 128 | + nlr_pop(); |
| 129 | + } else { |
| 130 | + raise = true; |
| 131 | + } |
| 132 | + |
| 133 | + // revert old values in case of nested dump |
| 134 | + ujson_item_separator = old_item_separator; |
| 135 | + ujson_key_separator = old_key_separator; |
| 136 | + |
| 137 | + // Re-raise the exception |
| 138 | + if (raise) { |
| 139 | + nlr_raise(MP_OBJ_FROM_PTR(nlr.ret_val)); |
| 140 | + } |
| 141 | + |
50 | 142 | return mp_obj_new_str_from_vstr(&mp_type_str, &vstr);
|
51 | 143 | }
|
52 |
| -STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_ujson_dumps_obj, mod_ujson_dumps); |
| 144 | +STATIC MP_DEFINE_CONST_FUN_OBJ_KW(mod_ujson_dumps_obj, 1, mod_ujson_dumps); |
53 | 145 |
|
54 | 146 | // The function below implements a simple non-recursive JSON parser.
|
55 | 147 | //
|
|
0 commit comments