json.c 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197
  1. #include "pocketpy/pocketpy.h"
  2. #include "pocketpy/common/utils.h"
  3. #include "pocketpy/objects/object.h"
  4. #include "pocketpy/common/sstream.h"
  5. #include "pocketpy/interpreter/vm.h"
  6. #include <math.h>
  7. static bool json_loads(int argc, py_Ref argv) {
  8. PY_CHECK_ARGC(1);
  9. PY_CHECK_ARG_TYPE(0, tp_str);
  10. const char* source = py_tostr(argv);
  11. return py_json_loads(source);
  12. }
  13. static bool json_dumps(int argc, py_Ref argv) {
  14. PY_CHECK_ARGC(2);
  15. PY_CHECK_ARG_TYPE(1, tp_int);
  16. int indent = py_toint(&argv[1]);
  17. return py_json_dumps(argv, indent);
  18. }
  19. void pk__add_module_json() {
  20. py_Ref mod = py_newmodule("json");
  21. py_setdict(mod, py_name("null"), py_None());
  22. py_setdict(mod, py_name("true"), py_True());
  23. py_setdict(mod, py_name("false"), py_False());
  24. py_TValue tmp;
  25. py_newfloat(&tmp, NAN);
  26. py_setdict(mod, py_name("NaN"), &tmp);
  27. py_newfloat(&tmp, INFINITY);
  28. py_setdict(mod, py_name("Infinity"), &tmp);
  29. py_bindfunc(mod, "loads", json_loads);
  30. py_bind(mod, "dumps(obj, indent=0)", json_dumps);
  31. }
  32. typedef struct {
  33. c11_sbuf* buf;
  34. bool first;
  35. int indent;
  36. int depth;
  37. } json__write_dict_kv_ctx;
  38. static bool json__write_object(c11_sbuf* buf, py_TValue* obj, int indent, int depth);
  39. static void json__write_indent(c11_sbuf* buf, int n_spaces) {
  40. for(int i = 0; i < n_spaces; i++) {
  41. c11_sbuf__write_char(buf, ' ');
  42. }
  43. }
  44. static bool json__write_array(c11_sbuf* buf, py_TValue* arr, int length, int indent, int depth) {
  45. c11_sbuf__write_char(buf, '[');
  46. if(length == 0) {
  47. c11_sbuf__write_char(buf, ']');
  48. return true;
  49. }
  50. if(indent > 0) c11_sbuf__write_char(buf, '\n');
  51. int n_spaces = indent * depth;
  52. const char* sep = indent > 0 ? ",\n" : ", ";
  53. for(int i = 0; i < length; i++) {
  54. if(i != 0) c11_sbuf__write_cstr(buf, sep);
  55. json__write_indent(buf, n_spaces);
  56. bool ok = json__write_object(buf, arr + i, indent, depth);
  57. if(!ok) return false;
  58. }
  59. if(indent > 0) {
  60. c11_sbuf__write_char(buf, '\n');
  61. json__write_indent(buf, n_spaces - indent);
  62. }
  63. c11_sbuf__write_char(buf, ']');
  64. return true;
  65. }
  66. static bool json__write_dict_kv(py_Ref k, py_Ref v, void* ctx_) {
  67. json__write_dict_kv_ctx* ctx = ctx_;
  68. int n_spaces = ctx->indent * ctx->depth;
  69. const char* sep = ctx->indent > 0 ? ",\n" : ", ";
  70. if(!ctx->first) c11_sbuf__write_cstr(ctx->buf, sep);
  71. ctx->first = false;
  72. if(!py_isstr(k)) return TypeError("keys must be strings");
  73. json__write_indent(ctx->buf, n_spaces);
  74. c11_sbuf__write_quoted(ctx->buf, py_tosv(k), '"');
  75. c11_sbuf__write_cstr(ctx->buf, ": ");
  76. return json__write_object(ctx->buf, v, ctx->indent, ctx->depth);
  77. }
  78. static bool json__write_namedict_kv(py_Name k, py_Ref v, void* ctx_) {
  79. json__write_dict_kv_ctx* ctx = ctx_;
  80. int n_spaces = ctx->indent * ctx->depth;
  81. const char* sep = ctx->indent > 0 ? ",\n" : ", ";
  82. if(!ctx->first) c11_sbuf__write_cstr(ctx->buf, sep);
  83. ctx->first = false;
  84. json__write_indent(ctx->buf, n_spaces);
  85. c11_sbuf__write_quoted(ctx->buf, py_name2sv(k), '"');
  86. c11_sbuf__write_cstr(ctx->buf, ": ");
  87. return json__write_object(ctx->buf, v, ctx->indent, ctx->depth);
  88. }
  89. static bool json__write_object(c11_sbuf* buf, py_TValue* obj, int indent, int depth) {
  90. switch(obj->type) {
  91. case tp_NoneType: c11_sbuf__write_cstr(buf, "null"); return true;
  92. case tp_int: c11_sbuf__write_int(buf, obj->_i64); return true;
  93. case tp_float: {
  94. if(isnan(obj->_f64)) {
  95. c11_sbuf__write_cstr(buf, "NaN");
  96. } else if(isinf(obj->_f64)) {
  97. c11_sbuf__write_cstr(buf, obj->_f64 < 0 ? "-Infinity" : "Infinity");
  98. } else {
  99. c11_sbuf__write_f64(buf, obj->_f64, -1);
  100. }
  101. return true;
  102. }
  103. case tp_bool: {
  104. c11_sbuf__write_cstr(buf, py_tobool(obj) ? "true" : "false");
  105. return true;
  106. }
  107. case tp_str: {
  108. c11_sbuf__write_quoted(buf, py_tosv(obj), '"');
  109. return true;
  110. }
  111. case tp_list: {
  112. return json__write_array(buf, py_list_data(obj), py_list_len(obj), indent, depth + 1);
  113. }
  114. case tp_tuple: {
  115. return json__write_array(buf, py_tuple_data(obj), py_tuple_len(obj), indent, depth + 1);
  116. }
  117. case tp_dict: {
  118. c11_sbuf__write_char(buf, '{');
  119. if(py_dict_len(obj) == 0) {
  120. c11_sbuf__write_char(buf, '}');
  121. return true;
  122. }
  123. if(indent > 0) c11_sbuf__write_char(buf, '\n');
  124. json__write_dict_kv_ctx ctx = {.buf = buf,
  125. .first = true,
  126. .indent = indent,
  127. .depth = depth + 1};
  128. bool ok = py_dict_apply(obj, json__write_dict_kv, &ctx);
  129. if(!ok) return false;
  130. if(indent > 0) {
  131. c11_sbuf__write_char(buf, '\n');
  132. json__write_indent(buf, indent * depth);
  133. }
  134. c11_sbuf__write_char(buf, '}');
  135. return true;
  136. }
  137. case tp_namedict: {
  138. py_Ref original = py_getslot(obj, 0);
  139. c11_sbuf__write_char(buf, '{');
  140. if(PyObject__dict(original->_obj)->length == 0) {
  141. c11_sbuf__write_char(buf, '}');
  142. return true;
  143. }
  144. if(indent > 0) c11_sbuf__write_char(buf, '\n');
  145. json__write_dict_kv_ctx ctx = {.buf = buf,
  146. .first = true,
  147. .indent = indent,
  148. .depth = depth + 1};
  149. bool ok = py_applydict(original, json__write_namedict_kv, &ctx);
  150. if(!ok) return false;
  151. if(indent > 0) {
  152. c11_sbuf__write_char(buf, '\n');
  153. json__write_indent(buf, indent * depth);
  154. }
  155. c11_sbuf__write_char(buf, '}');
  156. return true;
  157. }
  158. default: return TypeError("'%t' object is not JSON serializable", obj->type);
  159. }
  160. }
  161. bool py_json_dumps(py_Ref val, int indent) {
  162. c11_sbuf buf;
  163. c11_sbuf__ctor(&buf);
  164. bool ok = json__write_object(&buf, val, indent, 0);
  165. if(!ok) {
  166. c11_sbuf__dtor(&buf);
  167. return false;
  168. }
  169. c11_sbuf__py_submit(&buf, py_retval());
  170. return true;
  171. }
  172. bool py_json_loads(const char* source) {
  173. py_GlobalRef mod = py_getmodule("json");
  174. return py_exec(source, "<json>", EVAL_MODE, mod);
  175. }
  176. bool py_pusheval(const char* expr, py_GlobalRef module) {
  177. bool ok = py_exec(expr, "<string>", EVAL_MODE, module);
  178. if(!ok) return false;
  179. py_push(py_retval());
  180. return true;
  181. }