mirror of
https://github.com/mauiaaron/apple2.git
synced 2024-06-26 00:29:27 +00:00
json_parse module passes new tests
This commit is contained in:
parent
a03c074a52
commit
b59e1ca7ab
386
src/json_parse.c
386
src/json_parse.c
|
@ -33,6 +33,13 @@
|
|||
# define JSON_LOG(...)
|
||||
#endif
|
||||
|
||||
#define ASSERT_TOKEN_VALID(TOK) \
|
||||
do { \
|
||||
assert((TOK).start >= 0 && "bug"); \
|
||||
assert((TOK).end >= 0 && "bug"); \
|
||||
assert((TOK).end >= (TOK).start && "bug"); \
|
||||
} while (0)
|
||||
|
||||
static bool _json_write(const char *jsonString, size_t buflen, int fd) {
|
||||
ssize_t idx = 0;
|
||||
size_t chunk = buflen;
|
||||
|
@ -381,6 +388,8 @@ int json_createFromString(const char *jsonString, INOUT JSON_ref *jsonRef) {
|
|||
return _json_createFromString(jsonString, jsonRef, strlen(jsonString));
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
static bool _json_mapGetStringValue(const JSON_s *map, const char *key, INOUT int *index) {
|
||||
bool foundMatch = false;
|
||||
|
||||
|
@ -391,8 +400,16 @@ static bool _json_mapGetStringValue(const JSON_s *map, const char *key, INOUT in
|
|||
|
||||
*index = -1;
|
||||
|
||||
if (!map) {
|
||||
break;
|
||||
}
|
||||
|
||||
int tokCount = map->numTokens;
|
||||
if (tokCount < 0) {
|
||||
if (tokCount <= 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (!key) {
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -417,15 +434,13 @@ static bool _json_mapGetStringValue(const JSON_s *map, const char *key, INOUT in
|
|||
break;
|
||||
}
|
||||
|
||||
int start = keyTok.start;
|
||||
int end = keyTok.end;
|
||||
assert(end >= start && "bug");
|
||||
const int size = end - start;
|
||||
ASSERT_TOKEN_VALID(keyTok);
|
||||
const int size = keyTok.end - keyTok.start;
|
||||
|
||||
++idx;
|
||||
jsmntok_t valTok = map->jsonTokens[idx];
|
||||
if (size == keySize) {
|
||||
foundMatch = (strncmp(key, &map->jsonString[start], size) == 0);
|
||||
foundMatch = (strncmp(key, &map->jsonString[keyTok.start], size) == 0);
|
||||
if (foundMatch) {
|
||||
*index = idx;
|
||||
break;
|
||||
|
@ -439,19 +454,40 @@ static bool _json_mapGetStringValue(const JSON_s *map, const char *key, INOUT in
|
|||
return foundMatch;
|
||||
}
|
||||
|
||||
bool json_isMap(const JSON_ref jsonRef) {
|
||||
JSON_s *map = (JSON_s *)jsonRef;
|
||||
|
||||
bool ret = false;
|
||||
do {
|
||||
if (!map) {
|
||||
break;
|
||||
}
|
||||
if (map->numTokens <= 0) {
|
||||
break;
|
||||
}
|
||||
ret = map->jsonTokens[0].type == JSMN_OBJECT;
|
||||
} while (0);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int json_mapCopyJSON(const JSON_ref jsonRef, const char *key, INOUT JSON_ref *val) {
|
||||
JSON_s *map = (JSON_s *)jsonRef;
|
||||
|
||||
int idx = 0;
|
||||
int errCount = JSMN_ERROR_NOMEM;
|
||||
do {
|
||||
if (!val) {
|
||||
break;
|
||||
}
|
||||
|
||||
bool foundMatch = _json_mapGetStringValue(map, key, &idx);
|
||||
if (!foundMatch) {
|
||||
break;
|
||||
}
|
||||
|
||||
jsmntok_t tok = map->jsonTokens[idx];
|
||||
assert(tok.end >= tok.start && "bug");
|
||||
ASSERT_TOKEN_VALID(tok);
|
||||
int len = tok.end - tok.start;
|
||||
if (len<=0) {
|
||||
break;
|
||||
|
@ -473,15 +509,26 @@ int json_mapCopyJSON(const JSON_ref jsonRef, const char *key, INOUT JSON_ref *va
|
|||
|
||||
bool json_mapCopyStringValue(const JSON_ref jsonRef, const char *key, INOUT char **val) {
|
||||
JSON_s *map = (JSON_s *)jsonRef;
|
||||
bool foundMatch = false;
|
||||
|
||||
do {
|
||||
if (!val) {
|
||||
break;
|
||||
}
|
||||
|
||||
int idx = 0;
|
||||
if (!_json_mapGetStringValue(map, key, &idx)) {
|
||||
break;
|
||||
}
|
||||
|
||||
int idx = 0;
|
||||
bool foundMatch = _json_mapGetStringValue(map, key, &idx);
|
||||
if (foundMatch) {
|
||||
jsmntok_t tok = map->jsonTokens[idx];
|
||||
assert(tok.end >= tok.start && "bug");
|
||||
ASSERT_TOKEN_VALID(tok);
|
||||
int len = tok.end - tok.start;
|
||||
*val = len>0 ? STRNDUP(&map->jsonString[tok.start], len) : STRDUP("");
|
||||
}
|
||||
|
||||
foundMatch = true;
|
||||
|
||||
} while (0);
|
||||
|
||||
return foundMatch;
|
||||
}
|
||||
|
@ -496,17 +543,20 @@ bool json_mapParseLongValue(const JSON_ref jsonRef, const char *key, INOUT long
|
|||
}
|
||||
|
||||
int idx = 0;
|
||||
foundMatch = _json_mapGetStringValue(map, key, &idx);
|
||||
if (foundMatch) {
|
||||
jsmntok_t tok = map->jsonTokens[idx];
|
||||
assert(tok.end >= tok.start && "bug");
|
||||
int len = tok.end - tok.start;
|
||||
char *str = &map->jsonString[tok.start];
|
||||
char ch = str[len];
|
||||
str[len] = '\0';
|
||||
*val = strtol(str, NULL, base);
|
||||
str[len] = ch;
|
||||
if (!_json_mapGetStringValue(map, key, &idx)) {
|
||||
break;
|
||||
}
|
||||
|
||||
jsmntok_t tok = map->jsonTokens[idx];
|
||||
ASSERT_TOKEN_VALID(tok);
|
||||
int len = tok.end - tok.start;
|
||||
char *str = &map->jsonString[tok.start];
|
||||
char ch = str[len];
|
||||
str[len] = '\0';
|
||||
*val = strtol(str, NULL, base);
|
||||
str[len] = ch;
|
||||
|
||||
foundMatch = true;
|
||||
} while (0);
|
||||
|
||||
return foundMatch;
|
||||
|
@ -522,17 +572,20 @@ bool json_mapParseBoolValue(const JSON_ref jsonRef, const char *key, INOUT bool
|
|||
}
|
||||
|
||||
int idx = 0;
|
||||
foundMatch = _json_mapGetStringValue(map, key, &idx);
|
||||
if (foundMatch) {
|
||||
jsmntok_t tok = map->jsonTokens[idx];
|
||||
assert(tok.end >= tok.start && "bug");
|
||||
int len = tok.end - tok.start;
|
||||
char *str = &map->jsonString[tok.start];
|
||||
char ch = str[len];
|
||||
str[len] = '\0';
|
||||
*val = (strncasecmp("false", str, sizeof("false")) != 0);
|
||||
str[len] = ch;
|
||||
if (!_json_mapGetStringValue(map, key, &idx)) {
|
||||
break;
|
||||
}
|
||||
|
||||
jsmntok_t tok = map->jsonTokens[idx];
|
||||
ASSERT_TOKEN_VALID(tok);
|
||||
int len = tok.end - tok.start;
|
||||
char *str = &map->jsonString[tok.start];
|
||||
char ch = str[len];
|
||||
str[len] = '\0';
|
||||
*val = (strncasecmp("false", str, sizeof("false")) != 0);
|
||||
str[len] = ch;
|
||||
|
||||
foundMatch = true;
|
||||
} while (0);
|
||||
|
||||
return foundMatch;
|
||||
|
@ -548,17 +601,20 @@ bool json_mapParseFloatValue(const JSON_ref jsonRef, const char *key, INOUT floa
|
|||
}
|
||||
|
||||
int idx = 0;
|
||||
foundMatch = _json_mapGetStringValue(map, key, &idx);
|
||||
if (foundMatch) {
|
||||
jsmntok_t tok = map->jsonTokens[idx];
|
||||
assert(tok.end >= tok.start && "bug");
|
||||
int len = tok.end - tok.start;
|
||||
char *str = &map->jsonString[tok.start];
|
||||
char ch = str[len];
|
||||
str[len] = '\0';
|
||||
*val = strtof(str, NULL);
|
||||
str[len] = ch;
|
||||
if (!_json_mapGetStringValue(map, key, &idx)) {
|
||||
break;
|
||||
}
|
||||
|
||||
jsmntok_t tok = map->jsonTokens[idx];
|
||||
ASSERT_TOKEN_VALID(tok);
|
||||
int len = tok.end - tok.start;
|
||||
char *str = &map->jsonString[tok.start];
|
||||
char ch = str[len];
|
||||
str[len] = '\0';
|
||||
*val = strtof(str, NULL);
|
||||
str[len] = ch;
|
||||
|
||||
foundMatch = true;
|
||||
} while (0);
|
||||
|
||||
return foundMatch;
|
||||
|
@ -597,7 +653,7 @@ static bool _json_mapSetValue(const JSON_ref jsonRef, const char *key, const cha
|
|||
bool foundMatch = _json_mapGetStringValue(map, key, &idx);
|
||||
if (foundMatch) {
|
||||
jsmntok_t tok = map->jsonTokens[idx];
|
||||
assert(tok.end >= tok.start && "bug");
|
||||
ASSERT_TOKEN_VALID(tok);
|
||||
spliceBegin = tok.start;
|
||||
spliceEnd = tok.end;
|
||||
|
||||
|
@ -727,7 +783,7 @@ bool json_mapSetRawStringValue(const JSON_ref jsonRef, const char *key, const ch
|
|||
bool json_mapSetJSONValue(const JSON_ref jsonRef, const char *key, const JSON_ref jsonSubRef) {
|
||||
bool didSetValue = false;
|
||||
do {
|
||||
if (!jsonRef) {
|
||||
if (!jsonSubRef) {
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -758,6 +814,248 @@ bool json_mapSetFloatValue(const JSON_ref jsonRef, const char *key, float val) {
|
|||
return _json_mapSetValue(jsonRef, key, buf, JSMN_PRIMITIVE);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
static bool _json_arrayCalcIndex(const JSON_s *array, INOUT unsigned long *index) {
|
||||
bool valid = false;
|
||||
|
||||
do {
|
||||
if (!array) {
|
||||
break;
|
||||
}
|
||||
if (array->numTokens <= 0) {
|
||||
break;
|
||||
}
|
||||
jsmntok_t tok = array->jsonTokens[0];
|
||||
if (tok.type != JSMN_ARRAY) {
|
||||
break;
|
||||
}
|
||||
|
||||
int count = tok.size;
|
||||
if ((*index) >= count) {
|
||||
break;
|
||||
}
|
||||
|
||||
int idx = 1;
|
||||
for (int i=0; i<(*index); i++) {
|
||||
tok = array->jsonTokens[idx];
|
||||
idx += tok.skip;
|
||||
}
|
||||
|
||||
*index = idx;
|
||||
valid = true;
|
||||
|
||||
} while (0);
|
||||
|
||||
return valid;
|
||||
}
|
||||
|
||||
bool json_isArray(const JSON_ref jsonRef) {
|
||||
JSON_s *array = (JSON_s *)jsonRef;
|
||||
|
||||
bool ret = false;
|
||||
do {
|
||||
if (!array) {
|
||||
break;
|
||||
}
|
||||
if (array->numTokens <= 0) {
|
||||
break;
|
||||
}
|
||||
ret = array->jsonTokens[0].type == JSMN_ARRAY;
|
||||
} while (0);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool json_arrayCount(const JSON_ref jsonRef, INOUT long *count) {
|
||||
JSON_s *array = (JSON_s *)jsonRef;
|
||||
|
||||
bool ret = false;
|
||||
do {
|
||||
if (!array) {
|
||||
break;
|
||||
}
|
||||
if (!count) {
|
||||
break;
|
||||
}
|
||||
if (array->numTokens <= 0) {
|
||||
break;
|
||||
}
|
||||
jsmntok_t tok = array->jsonTokens[0];
|
||||
if (tok.type != JSMN_ARRAY) {
|
||||
break;
|
||||
}
|
||||
|
||||
*count = tok.size;
|
||||
ret = true;
|
||||
} while (0);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int json_arrayCopyJSONAtIndex(const JSON_ref jsonRef, unsigned long index, INOUT JSON_ref *val) {
|
||||
JSON_s *array = (JSON_s *)jsonRef;
|
||||
|
||||
int errCount = JSMN_ERROR_NOMEM;
|
||||
do {
|
||||
if (!val) {
|
||||
break;
|
||||
}
|
||||
bool valid = _json_arrayCalcIndex(array, &index);
|
||||
if (!valid) {
|
||||
break;
|
||||
}
|
||||
|
||||
jsmntok_t tok = array->jsonTokens[index];
|
||||
ASSERT_TOKEN_VALID(tok);
|
||||
int len = tok.end - tok.start;
|
||||
if (len <= 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
char *str = STRNDUP(&array->jsonString[tok.start], len);
|
||||
if (!str) {
|
||||
break;
|
||||
}
|
||||
|
||||
errCount = json_createFromString(str, val);
|
||||
assert(errCount >= 0);
|
||||
FREE(str);
|
||||
|
||||
} while (0);
|
||||
|
||||
return errCount;
|
||||
}
|
||||
|
||||
bool json_arrayCopyStringValueAtIndex(const JSON_ref jsonRef, unsigned long index, INOUT char **val) {
|
||||
JSON_s *array = (JSON_s *)jsonRef;
|
||||
|
||||
bool ret = false;
|
||||
do {
|
||||
if (!val) {
|
||||
break;
|
||||
}
|
||||
bool valid = _json_arrayCalcIndex(array, &index);
|
||||
if (!valid) {
|
||||
break;
|
||||
}
|
||||
|
||||
jsmntok_t tok = array->jsonTokens[index];
|
||||
ASSERT_TOKEN_VALID(tok);
|
||||
int len = tok.end - tok.start;
|
||||
if (len <= 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
*val = STRNDUP(&array->jsonString[tok.start], len);
|
||||
if (!*val) {
|
||||
break;
|
||||
}
|
||||
|
||||
ret = true;
|
||||
} while (0);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool json_arrayParseLongValueAtIndex(const JSON_ref jsonRef, unsigned long index, INOUT long *val, const long base) {
|
||||
JSON_s *array = (JSON_s *)jsonRef;
|
||||
|
||||
bool ret = false;
|
||||
do {
|
||||
if (!val) {
|
||||
break;
|
||||
}
|
||||
bool valid = _json_arrayCalcIndex(array, &index);
|
||||
if (!valid) {
|
||||
break;
|
||||
}
|
||||
|
||||
jsmntok_t tok = array->jsonTokens[index];
|
||||
ASSERT_TOKEN_VALID(tok);
|
||||
int len = tok.end - tok.start;
|
||||
if (len <= 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
char *str = &array->jsonString[tok.start];
|
||||
char ch = str[len];
|
||||
str[len] = '\0';
|
||||
*val = strtol(str, NULL, base);
|
||||
str[len] = ch;
|
||||
|
||||
ret = true;
|
||||
} while (0);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool json_arrayParseBoolValueAtIndex(const JSON_ref jsonRef, unsigned long index, INOUT bool *val) {
|
||||
JSON_s *array = (JSON_s *)jsonRef;
|
||||
|
||||
bool ret = false;
|
||||
do {
|
||||
if (!val) {
|
||||
break;
|
||||
}
|
||||
bool valid = _json_arrayCalcIndex(array, &index);
|
||||
if (!valid) {
|
||||
break;
|
||||
}
|
||||
|
||||
jsmntok_t tok = array->jsonTokens[index];
|
||||
ASSERT_TOKEN_VALID(tok);
|
||||
int len = tok.end - tok.start;
|
||||
if (len <= 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
char *str = &array->jsonString[tok.start];
|
||||
char ch = str[len];
|
||||
str[len] = '\0';
|
||||
*val = (strncasecmp("false", str, sizeof("false")) != 0);
|
||||
str[len] = ch;
|
||||
|
||||
ret = true;
|
||||
} while (0);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool json_arrayParseFloatValueAtIndex(const JSON_ref jsonRef, unsigned long index, INOUT float *val) {
|
||||
JSON_s *array = (JSON_s *)jsonRef;
|
||||
|
||||
bool ret = false;
|
||||
do {
|
||||
if (!val) {
|
||||
break;
|
||||
}
|
||||
bool valid = _json_arrayCalcIndex(array, &index);
|
||||
if (!valid) {
|
||||
break;
|
||||
}
|
||||
|
||||
jsmntok_t tok = array->jsonTokens[index];
|
||||
ASSERT_TOKEN_VALID(tok);
|
||||
int len = tok.end - tok.start;
|
||||
if (len <= 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
char *str = &array->jsonString[tok.start];
|
||||
char ch = str[len];
|
||||
str[len] = '\0';
|
||||
*val = strtof(str, NULL);
|
||||
str[len] = ch;
|
||||
|
||||
ret = true;
|
||||
} while (0);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
bool json_serialize(JSON_ref jsonRef, int fd, bool pretty) {
|
||||
JSON_s *parsedData = (JSON_s *)jsonRef;
|
||||
if (pretty) {
|
||||
|
|
|
@ -33,7 +33,10 @@ int json_createFromFD(int fd, INOUT JSON_ref *jsonRef);
|
|||
// ----------------------------------------------------------------------------
|
||||
// map functions
|
||||
|
||||
// get JSON_ref value for key in map JSON, returns true upon success and allocated JSON_ref
|
||||
// returns true if JSON_ref is map collection
|
||||
bool json_isMap(const JSON_ref array);
|
||||
|
||||
// get JSON_ref value for key in map JSON, returns error or tokenCount and allocated JSON_ref
|
||||
int json_mapCopyJSON(const JSON_ref map, const char *key, INOUT JSON_ref *val);
|
||||
|
||||
// get string value for key in map JSON, returns true upon success and strdup()'d value in *val
|
||||
|
@ -69,9 +72,33 @@ bool json_mapSetFloatValue(const JSON_ref map, const char *key, float val);
|
|||
// ----------------------------------------------------------------------------
|
||||
// array functions
|
||||
|
||||
//bool json_arrayCopyStringValueAtIndex(const JSON_ref array, unsigned long index, INOUT const char **val);
|
||||
//bool json_arrayParseLongValueAtIndex(const JSON_ref array, unsigned long index, INOUT const long *val, const long base);
|
||||
//bool json_arrayParseFloatValueAtIndex(const JSON_ref array, unsigned long index, INOUT const float *val);
|
||||
// returns true if JSON_ref is array collection
|
||||
bool json_isArray(const JSON_ref array);
|
||||
|
||||
// returns true if JSON_ref is array collection and returns count of array elements in
|
||||
bool json_arrayCount(const JSON_ref array, INOUT long *count);
|
||||
|
||||
// get JSON_ref value for index in array JSON, returns error or tokenCount and allocated JSON_ref
|
||||
int json_arrayCopyJSONAtIndex(const JSON_ref array, unsigned long index, INOUT JSON_ref *val);
|
||||
|
||||
// get string value for index in array JSON, returns true upon success and strdup()'d value in *val
|
||||
bool json_arrayCopyStringValueAtIndex(const JSON_ref array, unsigned long index, INOUT char **val);
|
||||
|
||||
// get long value for index in array JSON, returns true upon success
|
||||
bool json_arrayParseLongValueAtIndex(const JSON_ref array, unsigned long index, INOUT long *val, const long base);
|
||||
|
||||
// get bool value for index in array JSON, returns true upon success
|
||||
bool json_arrayParseBoolValueAtIndex(const JSON_ref array, unsigned long index, INOUT bool *val);
|
||||
|
||||
// get float value for index in array JSON, returns true upon success
|
||||
bool json_arrayParseFloatValueAtIndex(const JSON_ref array, unsigned long index, INOUT float *val);
|
||||
|
||||
//bool json_arraySetStringValueAtIndex(const JSON_ref array, unsigned long index, const char *val);
|
||||
//bool json_arraySetRawStringValue(const JSON_ref array, unsigned long index, const char *val);
|
||||
//bool json_arraySetJSONValue(const JSON_ref array, unsigned long index, const JSON_ref val);
|
||||
//bool json_arraySetLongValue(const JSON_ref array, unsigned long index, long val);
|
||||
//bool json_arraySetBoolValue(const JSON_ref array, unsigned long index, bool val);
|
||||
//bool json_arraySetFloatValue(const JSON_ref array, unsigned long index, float val);
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// serialization
|
||||
|
|
Loading…
Reference in New Issue
Block a user