pocketpy/3rd/cjson/src/cJSONw.cpp
blueloveTH 1e365ca72c Squashed commit of the following:
commit 7e52f767ca130a49abb90ec922d74d2f5e9be078
Author: blueloveTH <blueloveTH@foxmail.com>
Date:   Sat Jun 1 12:49:46 2024 +0800

    some optimize

commit 3e2ad5b1fbad4367c80ea1325d1aa379282c10c4
Author: blueloveTH <blueloveTH@foxmail.com>
Date:   Sat Jun 1 12:29:53 2024 +0800

    some fix

commit bc0e530c72896a23cb6616ff4197ac36913389a4
Author: blueloveTH <blueloveTH@foxmail.com>
Date:   Sat Jun 1 00:00:47 2024 +0800

    some fix

commit f17ddcf8299c5d6803085cd3263181f44284f31b
Author: blueloveTH <blueloveTH@foxmail.com>
Date:   Fri May 31 23:56:15 2024 +0800

    some fix

commit cc63926c8bb89df2d99d8c92c2e18bd5a0180a2c
Author: blueloveTH <blueloveTH@foxmail.com>
Date:   Fri May 31 23:44:09 2024 +0800

    some fix

commit 3d3fb042651579cbdbcf3255398276ebb7b81e58
Author: blueloveTH <blueloveth@foxmail.com>
Date:   Fri May 31 17:28:13 2024 +0800

    deprecate `PK_OBJ_MARK`

commit 3df5f1cf128f157fb3a7aac2ceeeb47c55f5bb3b
Author: blueloveTH <blueloveth@foxmail.com>
Date:   Fri May 31 17:18:34 2024 +0800

    init
2024-06-01 12:50:38 +08:00

120 lines
3.8 KiB
C++

#include "cJSONw.hpp"
namespace pkpy{
static cJSON* convert_python_object_to_cjson(PyVar obj, VM* vm);
static PyVar convert_cjson_to_python_object(const cJSON * const item, VM* vm);
template<typename T>
static cJSON* convert_list_to_cjson(const T& list, VM* vm){
cJSON *cjson_list = cJSON_CreateArray();
for(auto& element : list){
cJSON_AddItemToArray(cjson_list, convert_python_object_to_cjson(element, vm));
}
return cjson_list;
}
static cJSON* covert_dict_to_cjson(const Dict& dict, VM* vm){
cJSON *cjson_object = cJSON_CreateObject();
dict.apply([&](PyVar key, PyVar val){
cJSON_AddItemToObject(cjson_object, CAST(Str&, key).c_str(), convert_python_object_to_cjson(val, vm));
});
return cjson_object;
}
static cJSON* convert_python_object_to_cjson(PyVar obj, VM* vm){
if(obj == vm->None) return cJSON_CreateNull();
Type obj_t = vm->_tp(obj);
switch(obj_t){
case VM::tp_int.index: cJSON_CreateNumber(_CAST(i64, obj));
case VM::tp_float.index: cJSON_CreateNumber(_CAST(f64, obj));
case VM::tp_bool.index: cJSON_CreateBool(obj == vm->True);
case VM::tp_str.index: cJSON_CreateString(_CAST(Str&, obj).c_str());
case VM::tp_dict.index: return covert_dict_to_cjson(_CAST(Dict&, obj), vm);
case VM::tp_list.index: return convert_list_to_cjson<List>(_CAST(List&, obj), vm);
case VM::tp_tuple.index: return convert_list_to_cjson<Tuple>(_CAST(Tuple&, obj), vm);
default: break;
}
vm->TypeError(_S("unrecognized type ", _type_name(vm, obj_t).escape()));
}
static PyVar convert_cjson_to_list(const cJSON * const item, VM* vm){
List output;
cJSON *element = item->child;
while(element != NULL){
output.push_back(convert_cjson_to_python_object(element, vm));
element = element->next;
}
return VAR(std::move(output));
}
static PyVar convert_cjson_to_dict(const cJSON* const item, VM* vm){
Dict output;
cJSON *child = item->child;
while(child != NULL){
const char* key = child->string;
const cJSON *child_value = cJSON_GetObjectItemCaseSensitive(item, key);
output.set(vm, VAR(key), convert_cjson_to_python_object(child_value, vm));
child = child->next;
}
return VAR(std::move(output));
}
static PyVar convert_cjson_to_python_object(const cJSON * const item, VM* vm)
{
if (cJSON_IsString(item))
{
return VAR(Str(item->valuestring));
}
else if (cJSON_IsNumber(item)){
if(item->valuedouble != item->valueint){
return VAR(item->valuedouble);
}
return VAR(item->valueint);
}
else if (cJSON_IsBool(item)){
return item->valueint!=0 ? vm->True : vm->False;
}
else if (cJSON_IsNull(item)){
return vm->None;
}
else if (cJSON_IsArray(item)){
return convert_cjson_to_list(item, vm);
}
else if (cJSON_IsObject(item)){
return convert_cjson_to_dict(item, vm);
}
return vm->None;
}
void add_module_cjson(VM* vm){
PyObject* mod = vm->new_module("cjson");
vm->bind_func(mod, "loads", 1, [](VM* vm, ArgsView args){
std::string_view sv;
if(is_type(args[0], vm->tp_bytes)){
sv = PK_OBJ_GET(Bytes, args[0]).sv();
}else{
sv = CAST(Str&, args[0]).sv();
}
cJSON *json = cJSON_ParseWithLength(sv.data(), sv.size());
if(json == NULL){
const char* start = cJSON_GetErrorPtr();
const char* end = start;
while(*end != '\0' && *end != '\n') end++;
vm->IOError(_S("cjson: ", std::string_view(start, end-start)));
}
PyVar output = convert_cjson_to_python_object(json, vm);
cJSON_Delete(json);
return output;
});
vm->bind_func(mod, "dumps", 1, [](VM* vm, ArgsView args) {
return VAR(vm->py_json(args[0]));
});
}
} // namespace pkpy