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;
}