cJSONw.cpp 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137
  1. #include "cJSONw.hpp"
  2. namespace pkpy{
  3. static cJSON* convert_python_object_to_cjson(PyObject* obj, VM* vm);
  4. static PyObject* 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([&](PyObject* key, PyObject* 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(PyObject* obj, VM* vm){
  21. Type obj_t = vm->_tp(obj);
  22. if (obj_t == vm->tp_int){
  23. return cJSON_CreateNumber(_CAST(i64, obj));
  24. }
  25. else if (obj_t == vm->tp_float){
  26. return cJSON_CreateNumber(_CAST(f64, obj));
  27. }
  28. else if (obj_t == vm->tp_bool){
  29. return cJSON_CreateBool(obj == vm->True);
  30. }
  31. else if (obj_t == vm->tp_str){
  32. return cJSON_CreateString(_CAST(Str&, obj).c_str());
  33. }
  34. else if (obj_t == vm->tp_dict){
  35. return covert_dict_to_cjson(_CAST(Dict&, obj), vm);
  36. }
  37. else if (obj_t == vm->tp_list){
  38. return convert_list_to_cjson<List>(_CAST(List&, obj), vm);
  39. }
  40. else if(obj_t == vm->tp_tuple){
  41. return convert_list_to_cjson<Tuple>(_CAST(Tuple&, obj), vm);
  42. }else if(obj == vm->None){
  43. return cJSON_CreateNull();
  44. }else{
  45. vm->TypeError(fmt("cjson: unrecognized type ", obj_type_name(vm, obj_t)));
  46. }
  47. UNREACHABLE();
  48. }
  49. static PyObject* convert_cjson_to_list(const cJSON * const item, VM* vm){
  50. List output;
  51. cJSON *element = item->child;
  52. while(element != NULL){
  53. output.push_back(convert_cjson_to_python_object(element, vm));
  54. element = element->next;
  55. }
  56. return VAR(std::move(output));
  57. }
  58. static PyObject* convert_cjson_to_dict(const cJSON* const item, VM* vm){
  59. Dict output(vm);
  60. cJSON *child = item->child;
  61. while(child != NULL){
  62. const char* key = child->string;
  63. const cJSON *child_value = cJSON_GetObjectItemCaseSensitive(item, key);
  64. output.set(VAR(key), convert_cjson_to_python_object(child_value, vm));
  65. child = child->next;
  66. }
  67. return VAR(std::move(output));
  68. }
  69. static PyObject* convert_cjson_to_python_object(const cJSON * const item, VM* vm)
  70. {
  71. if (cJSON_IsString(item))
  72. {
  73. return VAR(Str(item->valuestring));
  74. }
  75. else if (cJSON_IsNumber(item)){
  76. if(item->valuedouble != item->valueint){
  77. return VAR(item->valuedouble);
  78. }
  79. return VAR(item->valueint);
  80. }
  81. else if (cJSON_IsBool(item)){
  82. return item->valueint!=0 ? vm->True : vm->False;
  83. }
  84. else if (cJSON_IsNull(item)){
  85. return vm->None;
  86. }
  87. else if (cJSON_IsArray(item)){
  88. return convert_cjson_to_list(item, vm);
  89. }
  90. else if (cJSON_IsObject(item)){
  91. return convert_cjson_to_dict(item, vm);
  92. }
  93. return vm->None;
  94. }
  95. void add_module_cjson(VM* vm){
  96. PyObject* mod = vm->new_module("cjson");
  97. PK_LOCAL_STATIC cJSON_Hooks hooks;
  98. hooks.malloc_fn = pool64_alloc;
  99. hooks.free_fn = pool64_dealloc;
  100. cJSON_InitHooks(&hooks);
  101. vm->bind_func<1>(mod, "loads", [](VM* vm, ArgsView args){
  102. const Str& string = CAST(Str&, args[0]);
  103. cJSON *json = cJSON_ParseWithLength(string.data, string.size);
  104. if(json == NULL){
  105. const char* err = cJSON_GetErrorPtr();
  106. vm->TypeError(fmt("cjson: ", err));
  107. UNREACHABLE();
  108. }
  109. PyObject* output = convert_cjson_to_python_object(json, vm);
  110. cJSON_Delete(json);
  111. return output;
  112. });
  113. vm->bind_func<1>(mod, "dumps", [](VM* vm, ArgsView args) {
  114. cJSON* cjson = convert_python_object_to_cjson(args[0], vm);
  115. char* str = cJSON_Print(cjson);
  116. cJSON_Delete(cjson);
  117. PyObject* ret = VAR((const char*)str);
  118. hooks.free_fn(str);
  119. return ret;
  120. });
  121. }
  122. } // namespace pkpy