/** * @short Creates a dict from a json * * Onion dicts do not support full json semantics, soit will do the translations as possible; * sometimes information may be lost. * * Anyway dicts created by onion are ensured to be readable by onion. * * If the data is invalid NULL is returned. */ onion_dict *onion_dict_from_json(const char *data){ if (!data) return NULL; const char *_data[1]={ data }; onion_dict *ret=onion_dict_from_json_(_data); while (is_json_space(*_data[0])) ++_data[0]; if (*_data[0]){ ONION_DEBUG("Invalid JSON, not ends at end"); onion_dict_free(ret); return NULL; } return ret; }
static WCHAR skip_spaces(json_parse_ctx_t *ctx) { while(is_json_space(*ctx->ptr)) ctx->ptr++; return *ctx->ptr; }
onion_dict *onion_dict_from_json_(const char **_data){ const char *data=*_data; ONION_DEBUG("Parse %s", *_data); while (is_json_space(*data)) ++data; if (*data!='{') return NULL; ++data; while (is_json_space(*data)) ++data; ; onion_dict *ret=onion_dict_new(); onion_block *key=onion_block_new(); onion_block *value=onion_block_new(); while (*data!='}'){ // Get Key ssize_t read_bytes=onion_json_unquote_add(key, data); if (read_bytes<0) goto error; data+=read_bytes; while (is_json_space(*data)) ++data; /// Get : if (*data!=':'){ // Includes \0 ONION_DEBUG("Expected : got %c", *data); goto error; } ++data; while (is_json_space(*data)) ++data; /// Get Value if (*data=='{'){ // Includes \0 *_data=data; onion_dict *sub=onion_dict_from_json_(_data); if (!sub){ goto error; } onion_dict_add(ret, onion_block_data(key), sub, OD_DUP_KEY|OD_DICT|OD_FREE_VALUE); data=*_data; } else if (is_json_digit(*data)){ while(is_json_digit(*data)){ onion_block_add_char(value, *data); ++data; } onion_dict_add(ret, onion_block_data(key), onion_block_data(value), OD_DUP_ALL); } else if (*data=='"'){ // parse string ssize_t read_bytes=onion_json_unquote_add(value, data); if (read_bytes<0) goto error; data+=read_bytes; onion_dict_add(ret, onion_block_data(key), onion_block_data(value), OD_DUP_ALL); onion_block_clear(value); } else { // Includes \0 ONION_DEBUG("Expected \" got %c", *data); goto error; } onion_block_clear(key); while (is_json_space(*data)) ++data; if (*data=='}'){ ++data; *_data=data; onion_block_free(key); onion_block_free(value); return ret; } if (*data!=','){ ONION_DEBUG("Expected , got %c", *data); goto error; } ++data; while (is_json_space(*data)) ++data; } ++data; *_data=data; onion_block_free(key); onion_block_free(value); return ret; error: onion_block_free(key); onion_block_free(value); onion_dict_free(ret); return NULL; }