cJSONw.cpp 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125
  1. #include "cJSONw.hpp"
  2. namespace pkpy{
  3. static cJSON* convert_python_object_to_cjson(PyVar obj, VM* vm);
  4. static PyVar convert_cjson_to_python_object(const cJSON * const item, VM* vm);
  5. template<typename T>
  6. static cJSON* convert_list_to_cjson(const T& list, VM* vm){
  7. cJSON *cjson_list = cJSON_CreateArray();
  8. for(auto& element : list){
  9. cJSON_AddItemToArray(cjson_list, convert_python_object_to_cjson(element, vm));
  10. }
  11. return cjson_list;
  12. }
  13. static cJSON* covert_dict_to_cjson(const Dict& dict, VM* vm){
  14. cJSON *cjson_object = cJSON_CreateObject();
  15. dict.apply([&](PyVar key, PyVar val){
  16. cJSON_AddItemToObject(cjson_object, CAST(Str&, key).c_str(), convert_python_object_to_cjson(val, vm));
  17. });
  18. return cjson_object;
  19. }
  20. static cJSON* convert_python_object_to_cjson(PyVar obj, VM* vm){
  21. if(obj == vm->None) return cJSON_CreateNull();
  22. Type obj_t = vm->_tp(obj);
  23. switch(obj_t){
  24. case VM::tp_int.index: cJSON_CreateNumber(_CAST(i64, obj));
  25. case VM::tp_float.index: cJSON_CreateNumber(_CAST(f64, obj));
  26. case VM::tp_bool.index: cJSON_CreateBool(obj == vm->True);
  27. case VM::tp_str.index: cJSON_CreateString(_CAST(Str&, obj).c_str());
  28. case VM::tp_dict.index: return covert_dict_to_cjson(_CAST(Dict&, obj), vm);
  29. case VM::tp_list.index: return convert_list_to_cjson<List>(_CAST(List&, obj), vm);
  30. case VM::tp_tuple.index: return convert_list_to_cjson<Tuple>(_CAST(Tuple&, obj), vm);
  31. default: break;
  32. }
  33. vm->TypeError(_S("unrecognized type ", _type_name(vm, obj_t).escape()));
  34. PK_UNREACHABLE()
  35. }
  36. static PyVar convert_cjson_to_list(const cJSON * const item, VM* vm){
  37. List output;
  38. cJSON *element = item->child;
  39. while(element != NULL){
  40. output.push_back(convert_cjson_to_python_object(element, vm));
  41. element = element->next;
  42. }
  43. return VAR(std::move(output));
  44. }
  45. static PyVar convert_cjson_to_dict(const cJSON* const item, VM* vm){
  46. Dict output(vm);
  47. cJSON *child = item->child;
  48. while(child != NULL){
  49. const char* key = child->string;
  50. const cJSON *child_value = cJSON_GetObjectItemCaseSensitive(item, key);
  51. output.set(VAR(key), convert_cjson_to_python_object(child_value, vm));
  52. child = child->next;
  53. }
  54. return VAR(std::move(output));
  55. }
  56. static PyVar convert_cjson_to_python_object(const cJSON * const item, VM* vm)
  57. {
  58. if (cJSON_IsString(item))
  59. {
  60. return VAR(Str(item->valuestring));
  61. }
  62. else if (cJSON_IsNumber(item)){
  63. if(item->valuedouble != item->valueint){
  64. return VAR(item->valuedouble);
  65. }
  66. return VAR(item->valueint);
  67. }
  68. else if (cJSON_IsBool(item)){
  69. return item->valueint!=0 ? vm->True : vm->False;
  70. }
  71. else if (cJSON_IsNull(item)){
  72. return vm->None;
  73. }
  74. else if (cJSON_IsArray(item)){
  75. return convert_cjson_to_list(item, vm);
  76. }
  77. else if (cJSON_IsObject(item)){
  78. return convert_cjson_to_dict(item, vm);
  79. }
  80. return vm->None;
  81. }
  82. void add_module_cjson(VM* vm){
  83. PyVar mod = vm->new_module("cjson");
  84. PK_LOCAL_STATIC cJSON_Hooks hooks;
  85. hooks.malloc_fn = pool64_alloc;
  86. hooks.free_fn = pool64_dealloc;
  87. cJSON_InitHooks(&hooks);
  88. vm->bind_func(mod, "loads", 1, [](VM* vm, ArgsView args){
  89. std::string_view sv;
  90. if(is_type(args[0], vm->tp_bytes)){
  91. sv = PK_OBJ_GET(Bytes, args[0]).sv();
  92. }else{
  93. sv = CAST(Str&, args[0]).sv();
  94. }
  95. cJSON *json = cJSON_ParseWithLength(sv.data(), sv.size());
  96. if(json == NULL){
  97. const char* start = cJSON_GetErrorPtr();
  98. const char* end = start;
  99. while(*end != '\0' && *end != '\n') end++;
  100. vm->IOError(_S("cjson: ", std::string_view(start, end-start)));
  101. }
  102. PyVar output = convert_cjson_to_python_object(json, vm);
  103. cJSON_Delete(json);
  104. return output;
  105. });
  106. vm->bind_func(mod, "dumps", 1, [](VM* vm, ArgsView args) {
  107. return VAR(vm->py_json(args[0]));
  108. });
  109. }
  110. } // namespace pkpy