json.c 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111
  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. py_GlobalRef mod = py_getmodule("json");
  12. return py_exec(source, "<json>", EVAL_MODE, mod);
  13. }
  14. static bool json_dumps(int argc, py_Ref argv) {
  15. PY_CHECK_ARGC(1);
  16. return py_json(argv);
  17. }
  18. void pk__add_module_json() {
  19. py_Ref mod = py_newmodule("json");
  20. py_setdict(mod, py_name("null"), py_None);
  21. py_setdict(mod, py_name("true"), py_True);
  22. py_setdict(mod, py_name("false"), py_False);
  23. py_bindfunc(mod, "loads", json_loads);
  24. py_bindfunc(mod, "dumps", json_dumps);
  25. }
  26. static bool json__write_object(c11_sbuf* buf, py_TValue* obj);
  27. static bool json__write_array(c11_sbuf* buf, py_TValue* arr, int length) {
  28. c11_sbuf__write_char(buf, '[');
  29. for(int i = 0; i < length; i++) {
  30. if(i != 0) c11_sbuf__write_cstr(buf, ", ");
  31. bool ok = json__write_object(buf, arr + i);
  32. if(!ok) return false;
  33. }
  34. c11_sbuf__write_char(buf, ']');
  35. return true;
  36. }
  37. typedef struct {
  38. c11_sbuf* buf;
  39. bool first;
  40. } json__write_dict_kv_ctx;
  41. static bool json__write_dict_kv(py_Ref k, py_Ref v, void* ctx_) {
  42. json__write_dict_kv_ctx* ctx = ctx_;
  43. if(!ctx->first) c11_sbuf__write_cstr(ctx->buf, ", ");
  44. ctx->first = false;
  45. if(!py_isstr(k)) return TypeError("keys must be strings");
  46. c11_sbuf__write_quoted(ctx->buf, py_tosv(k), '"');
  47. c11_sbuf__write_char(ctx->buf, ':');
  48. return json__write_object(ctx->buf, v);
  49. }
  50. static bool json__write_object(c11_sbuf* buf, py_TValue* obj) {
  51. switch(obj->type) {
  52. case tp_NoneType: c11_sbuf__write_cstr(buf, "null"); return true;
  53. case tp_int: c11_sbuf__write_int(buf, obj->_i64); return true;
  54. case tp_float: {
  55. if(isnan(obj->_f64)) {
  56. c11_sbuf__write_cstr(buf, "NaN");
  57. } else if(isinf(obj->_f64)) {
  58. c11_sbuf__write_cstr(buf, obj->_f64 < 0 ? "-Infinity" : "Infinity");
  59. } else {
  60. c11_sbuf__write_f64(buf, obj->_f64, -1);
  61. }
  62. return true;
  63. }
  64. case tp_bool: {
  65. c11_sbuf__write_cstr(buf, py_tobool(obj) ? "true" : "false");
  66. return true;
  67. }
  68. case tp_str: {
  69. c11_sbuf__write_quoted(buf, py_tosv(obj), '"');
  70. return true;
  71. }
  72. case tp_list: {
  73. return json__write_array(buf, py_list_data(obj), py_list_len(obj));
  74. }
  75. case tp_tuple: {
  76. return json__write_array(buf, py_tuple_data(obj), py_tuple_len(obj));
  77. }
  78. case tp_dict: {
  79. c11_sbuf__write_char(buf, '{');
  80. json__write_dict_kv_ctx ctx = {.buf = buf, .first = true};
  81. bool ok = py_dict_apply(obj, json__write_dict_kv, &ctx);
  82. if(!ok) return false;
  83. c11_sbuf__write_char(buf, '}');
  84. return true;
  85. }
  86. default: return TypeError("'%t' object is not JSON serializable", obj->type);
  87. }
  88. }
  89. bool py_json(py_Ref val) {
  90. c11_sbuf buf;
  91. c11_sbuf__ctor(&buf);
  92. bool ok = json__write_object(&buf, val);
  93. if(!ok){
  94. c11_sbuf__dtor(&buf);
  95. return false;
  96. }
  97. c11_sbuf__py_submit(&buf, py_retval());
  98. return true;
  99. }