Support non-dictionary json objects (list, tuple, string, number, bool, null)

This commit is contained in:
Mahbub Alam 2023-10-13 21:33:01 -04:00
parent 4def9dd091
commit 004f2bb3ad
4 changed files with 111 additions and 77 deletions

2
.gitignore vendored
View File

@ -38,3 +38,5 @@ libpocketpy.dylib
.xmake/
tests/res/WorldMap_Free_layout.ldtk
tests/res/WorldMap_GridVania_layout.ldtk
*.gcda

View File

@ -2,90 +2,122 @@
namespace pkpy{
static std::string convert_python_object_to_string(PyObject* obj, VM* vm);
static PyObject* convert_cjson_to_python_object(const cJSON * const item, VM* vm);
static std::string convert_list_to_string(const List& list, VM* vm){
bool extra_comma_flag = false;
std::string output = "[";
for(auto& element : list){
output = output + convert_python_object_to_string(element, vm) + ", ";
extra_comma_flag = true;
}
if(extra_comma_flag){
output.pop_back();
output.pop_back();
}
return output + "]";
}
static std::string convert_tuple_to_string(const Tuple& tuple, VM* vm){
bool extra_comma_flag = false;
std::string output = "[";
for(auto& element : tuple){
output = output + convert_python_object_to_string(element, vm) + ", ";
extra_comma_flag = true;
}
if (extra_comma_flag){
output.pop_back();
output.pop_back();
}
return output + "]";
}
static std::string covert_dict_to_string(const Dict& dict, VM* vm){
std::string output = "{";
dict.apply([&](PyObject* key, PyObject* val){
output = output + "\"" + CAST(Str&, key).c_str() + "\":";
try{
Dict child_dict = CAST(Dict&, val);
std::string chilld_str = covert_dict_to_string(child_dict, vm);
output = output + chilld_str + ",";
}
catch(...) {
if (is_float(val)){
output = output + std::to_string(CAST(f64, val)) + ",";
}
else if(is_int(val)){
output = output + std::to_string(CAST(i64, val)) + ",";
}
else{
output = output + "\"" + CAST(Str&, val).c_str() + "\",";
}
}
output = output + convert_python_object_to_string(val, vm) + ",";
});
output.pop_back();
return output + "}";
}
static Dict convert_cjson_to_dict(const cJSON * const item, VM* vm)
{
Dict output(vm);
List list;
if ((item == NULL))
{
return NULL;
static std::string convert_python_object_to_string(PyObject* obj, VM* vm){
if (is_type(obj, vm->tp_int)){
return std::to_string(CAST(i64, obj));
}
else if (is_type(obj, vm->tp_float)){
return std::to_string(CAST(f64, obj));
}
else if (is_type(obj, vm->tp_bool)){
if (obj == vm->True){
return "true";
}
else{
return "false";
}
}
else if (is_type(obj, vm->tp_str)){
return std::string("\"") + CAST(Str&, obj).c_str() + std::string("\"");
}
else if (is_type(obj, vm->tp_dict)){
return covert_dict_to_string(CAST(Dict&, obj), vm);
if (((item->type) & 0xFF) == cJSON_Object){
}
else if (is_type(obj, vm->tp_list)){
return convert_list_to_string(CAST(List&, obj), vm);
}
else if(is_type(obj, vm->tp_tuple)){
return convert_tuple_to_string(CAST(Tuple&, obj), vm);
}
return "null";
}
static PyObject* convert_cjson_to_list(const cJSON * const item, VM* vm){
List list;
cJSON *element = item->child;
while(element != NULL){
list.push_back(convert_cjson_to_python_object(element, vm));
element = element->next;
}
return VAR(list);
}
static PyObject* convert_cjson_to_dict(const cJSON* const item, VM* vm){
Dict output(vm);
cJSON *child = item->child;
while(child != NULL){
const cJSON *child_value = cJSON_GetObjectItemCaseSensitive(item, child->string);
if (cJSON_IsString(child_value))
{
output.set(VAR(Str(child->string)), VAR(Str(child_value->valuestring)));
}
else if (cJSON_IsNumber(child_value)){
output.set(VAR(Str(child->string)), VAR(child_value->valueint));
}
else if (cJSON_IsBool(child_value)){
output.set(VAR(Str(child->string)), child_value->valueint!=0 ? vm->True : vm->False);
}
else if (cJSON_IsNull(child_value)){
output.set(VAR(Str(child->string)), vm->None);
}
else if (cJSON_IsArray(child_value)){
cJSON *array_child = child_value->child;
while(array_child != NULL){
if (cJSON_IsString(array_child))
{
list.push_back(VAR(Str(array_child->valuestring)));
}
else if (cJSON_IsNumber(array_child)){
list.push_back(VAR(array_child->valueint));
}
else if (cJSON_IsBool(array_child)){
list.push_back(child_value->valueint!=0 ? vm->True : vm->False);
}
else if (cJSON_IsNull(array_child)){
list.push_back(vm->None);
}
array_child = array_child->next;
}
output.set(VAR(Str(child->string)), VAR(list));
}
else if (cJSON_IsObject(child_value)){
Dict child_object = convert_cjson_to_dict(child_value, vm);
output.set(VAR(Str(child->string)), VAR(child_object));
}
output.set(VAR(Str(child->string)), convert_cjson_to_python_object(child_value, vm));
child = child->next;
}
return VAR(output);
}
static PyObject* convert_cjson_to_python_object(const cJSON * const item, VM* vm)
{
if (cJSON_IsString(item))
{
return VAR(Str(item->valuestring));
}
return output;
else if (cJSON_IsNumber(item)){
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){
@ -93,17 +125,17 @@ void add_module_cjson(VM* vm){
vm->bind_func<1>(mod, "loads", [](VM* vm, ArgsView args) {
const Str& expr = CAST(Str&, args[0]);
cJSON *json = cJSON_Parse(expr.c_str());
Dict output = convert_cjson_to_dict(json, vm);
return VAR(output);
PyObject* output = convert_cjson_to_python_object(json, vm);
cJSON_Delete(json);
return output;
});
vm->bind_func<1>(mod, "dumps", [](VM* vm, ArgsView args) {
const Dict& dict = CAST(Dict&, args[0]);
std::string str = covert_dict_to_string(dict, vm);
std::string str = convert_python_object_to_string(args[0], vm);
return VAR(str);
});

View File

@ -14,7 +14,7 @@ a = {
'h': False
}
import json
import cjson as json
_j = json.dumps(a)
_a = json.loads(_j)

View File

@ -1,4 +1,4 @@
import json
import cjson as json
_2489KB = 'WorldMap_GridVania_layout.ldtk'
_1093KB = 'WorldMap_Free_layout.ldtk'