cJSONw.cpp 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120
  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(is_none(obj)) return cJSON_CreateNull();
  22. Type obj_t = vm->_tp(obj);
  23. switch(obj_t){
  24. case VM::tp_int: cJSON_CreateNumber(_CAST(i64, obj));
  25. case VM::tp_float: cJSON_CreateNumber(_CAST(f64, obj));
  26. case VM::tp_bool: cJSON_CreateBool(obj.extra);
  27. case VM::tp_str: cJSON_CreateString(_CAST(Str&, obj).c_str());
  28. case VM::tp_dict: return covert_dict_to_cjson(_CAST(Dict&, obj), vm);
  29. case VM::tp_list: return convert_list_to_cjson<List>(_CAST(List&, obj), vm);
  30. case VM::tp_tuple: 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. }
  35. static PyVar convert_cjson_to_list(const cJSON * const item, VM* vm){
  36. List output;
  37. cJSON *element = item->child;
  38. while(element != NULL){
  39. output.push_back(convert_cjson_to_python_object(element, vm));
  40. element = element->next;
  41. }
  42. return VAR(std::move(output));
  43. }
  44. static PyVar convert_cjson_to_dict(const cJSON* const item, VM* vm){
  45. Dict output;
  46. cJSON *child = item->child;
  47. while(child != NULL){
  48. const char* key = child->string;
  49. const cJSON *child_value = cJSON_GetObjectItemCaseSensitive(item, key);
  50. output.set(vm, VAR(key), convert_cjson_to_python_object(child_value, vm));
  51. child = child->next;
  52. }
  53. return VAR(std::move(output));
  54. }
  55. static PyVar convert_cjson_to_python_object(const cJSON * const item, VM* vm)
  56. {
  57. if (cJSON_IsString(item))
  58. {
  59. return VAR(Str(item->valuestring));
  60. }
  61. else if (cJSON_IsNumber(item)){
  62. if(item->valuedouble != item->valueint){
  63. return VAR(item->valuedouble);
  64. }
  65. return VAR(item->valueint);
  66. }
  67. else if (cJSON_IsBool(item)){
  68. return item->valueint!=0 ? vm->True : vm->False;
  69. }
  70. else if (cJSON_IsNull(item)){
  71. return vm->None;
  72. }
  73. else if (cJSON_IsArray(item)){
  74. return convert_cjson_to_list(item, vm);
  75. }
  76. else if (cJSON_IsObject(item)){
  77. return convert_cjson_to_dict(item, vm);
  78. }
  79. return vm->None;
  80. }
  81. void add_module_cjson(VM* vm){
  82. PyObject* mod = vm->new_module("cjson");
  83. vm->bind_func(mod, "loads", 1, [](VM* vm, ArgsView args){
  84. std::string_view sv;
  85. if(is_type(args[0], vm->tp_bytes)){
  86. const Bytes& b = PK_OBJ_GET(Bytes, args[0]);
  87. sv = std::string_view((char*)b.data(), b.size());
  88. }else{
  89. sv = CAST(Str&, args[0]).sv();
  90. }
  91. cJSON *json = cJSON_ParseWithLength(sv.data(), sv.size());
  92. if(json == NULL){
  93. const char* start = cJSON_GetErrorPtr();
  94. const char* end = start;
  95. while(*end != '\0' && *end != '\n') end++;
  96. vm->IOError(_S("cjson: ", std::string_view(start, end-start)));
  97. }
  98. PyVar output = convert_cjson_to_python_object(json, vm);
  99. cJSON_Delete(json);
  100. return output;
  101. });
  102. vm->bind_func(mod, "dumps", 1, [](VM* vm, ArgsView args) {
  103. return VAR(vm->py_json(args[0]));
  104. });
  105. }
  106. } // namespace pkpy