mirror of
https://gitee.com/Lyon1998/pikapython.git
synced 2025-01-22 17:12:55 +08:00
132 lines
4.2 KiB
C
132 lines
4.2 KiB
C
#include "_json.h"
|
|
#include "jsmn.h"
|
|
|
|
#if !PIKASCRIPT_VERSION_REQUIRE_MINIMUN(1, 13, 0)
|
|
#error "pikapython version must be greater than 1.13.0"
|
|
#endif
|
|
|
|
int parse_json(const char* json_string,
|
|
jsmn_parser* parser,
|
|
jsmntok_t** tokens) {
|
|
jsmn_init(parser);
|
|
|
|
int token_count =
|
|
jsmn_parse(parser, json_string, strlen(json_string), NULL, 0);
|
|
|
|
if (token_count < 0) {
|
|
// JSMN_ERROR_INVAL or JSMN_ERROR_PART
|
|
pika_platform_printf("Failed to parse JSON: %d\n", token_count);
|
|
return -1;
|
|
}
|
|
|
|
*tokens = pika_platform_malloc(sizeof(jsmntok_t) * token_count);
|
|
if (*tokens == NULL) {
|
|
pika_platform_printf("Failed to allocate memory: %d\n", token_count);
|
|
return -1;
|
|
}
|
|
|
|
jsmn_init(parser);
|
|
int result = jsmn_parse(parser, json_string, strlen(json_string), *tokens,
|
|
token_count);
|
|
if (result < 0) {
|
|
pika_platform_printf("Failed to parse JSON: %d\n", result);
|
|
pika_platform_free(*tokens);
|
|
*tokens = NULL;
|
|
return -1;
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
void PikaStdData_List_append(PikaObj* self, Arg* arg);
|
|
void PikaStdData_Dict_set(PikaObj* self, char* key, Arg* arg);
|
|
|
|
Arg* json_to_arg_recursive(jsmntok_t* t, int* index, char* json_str) {
|
|
Arg* val;
|
|
jsmntype_t type = t[*index].type;
|
|
switch (type) {
|
|
case JSMN_PRIMITIVE: {
|
|
char buff[PIKA_NAME_BUFF_SIZE] = {0};
|
|
pika_platform_memcpy(buff, json_str + t[*index].start,
|
|
t[*index].end - t[*index].start);
|
|
if (strEqu(buff, "true")) {
|
|
val = arg_newBool(1);
|
|
} else if (strEqu(buff, "false")) {
|
|
val = arg_newBool(0);
|
|
} else if (strEqu(buff, "null")) {
|
|
val = arg_newNull();
|
|
} else {
|
|
/* float */
|
|
if (strIsContain(buff, '.') ||
|
|
(strIsContain(buff, 'e') || strIsContain(buff, 'E'))) {
|
|
val = arg_newFloat(strtod(buff, NULL));
|
|
} else {
|
|
/* int */
|
|
val = arg_newInt(fast_atoi(buff));
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
case JSMN_STRING:
|
|
val = arg_newStrN(json_str + t[*index].start,
|
|
t[*index].end - t[*index].start);
|
|
break;
|
|
case JSMN_OBJECT: {
|
|
PikaObj* ret = obj_newDict(NULL);
|
|
int num_keys = t[*index].size;
|
|
(*index)++;
|
|
for (int i = 0; i < num_keys; i++) {
|
|
char key[PIKA_NAME_BUFF_SIZE] = {0};
|
|
pika_platform_memcpy(key, json_str + t[*index].start,
|
|
t[*index].end - t[*index].start);
|
|
(*index)++;
|
|
Arg* val_nested = json_to_arg_recursive(t, index, json_str);
|
|
PikaStdData_Dict_set(ret, key, val_nested);
|
|
arg_deinit(val_nested);
|
|
if (i < num_keys - 1) {
|
|
(*index)++;
|
|
}
|
|
}
|
|
val = arg_newObj(ret);
|
|
break;
|
|
}
|
|
case JSMN_ARRAY: {
|
|
PikaObj* ret = obj_newList(NULL);
|
|
int num_elements = t[*index].size;
|
|
(*index)++;
|
|
for (int i = 0; i < num_elements; i++) {
|
|
Arg* val_nested = json_to_arg_recursive(t, index, json_str);
|
|
PikaStdData_List_append(ret, val_nested);
|
|
arg_deinit(val_nested);
|
|
if (i < num_elements - 1) {
|
|
(*index)++;
|
|
}
|
|
}
|
|
val = arg_newObj(ret);
|
|
break;
|
|
}
|
|
default: /* Should not reach here */
|
|
val = NULL;
|
|
}
|
|
return val;
|
|
}
|
|
|
|
Arg* _json_loads(PikaObj* self, char* json_str) {
|
|
jsmn_parser parser;
|
|
jsmntok_t* tokens = NULL;
|
|
Arg* ret = NULL;
|
|
int token_count = parse_json(json_str, &parser, &tokens);
|
|
if (token_count < 0) {
|
|
ret = NULL;
|
|
goto __exit;
|
|
}
|
|
jsmntok_t tokens_[50];
|
|
pika_platform_memcpy(tokens_, tokens, sizeof(jsmntok_t) * token_count);
|
|
ret = json_to_arg_recursive(tokens, &(int){0}, json_str);
|
|
__exit:
|
|
if (NULL != tokens) {
|
|
free(tokens);
|
|
}
|
|
return ret;
|
|
}
|