diff options
author | Eric S. Raymond <esr@thyrsus.com> | 2009-08-19 02:25:32 +0000 |
---|---|---|
committer | Eric S. Raymond <esr@thyrsus.com> | 2009-08-19 02:25:32 +0000 |
commit | 747088bbe5dc34c0902c0bddc492bc4815f4a7c3 (patch) | |
tree | 4c2d4ef502290f6e7ce9136a30b6284f6d7e1bcc | |
parent | 276ffa0a53aae3fe555bdcbf98c4007120a2f0e3 (diff) | |
download | gpsd-747088bbe5dc34c0902c0bddc492bc4815f4a7c3.tar.gz |
Give the JSON parser the ability to map strings to enumerated types.
-rw-r--r-- | json.c | 39 | ||||
-rw-r--r-- | json.h | 14 | ||||
-rw-r--r-- | test_json.c | 24 |
3 files changed, 74 insertions, 3 deletions
@@ -27,6 +27,9 @@ objects or strings - not reals or integers or floats - as elements (this limitation could be easily removed if required). Third, all elements of an array must be of the same type. + There's a way to map arrays of strings to arrays of enumerated values +by supplying a lookup table. + There are separata entry points for beginning a parse of either JSON object or a JSON array. JSON "float" quantities are actually stored as doubles. @@ -66,7 +69,8 @@ int json_read_object(const char *cp, const struct json_attr_t *attrs, int offset if (cursor->dflt.boolean != nullbool) cursor->addr.boolean[offset] = cursor->dflt.boolean; break; - case object: /* silences a compiler warning */ + case enumerated: /* silences a compiler warning */ + case object: case array: case check: break; @@ -185,7 +189,8 @@ int json_read_object(const char *cp, const struct json_attr_t *attrs, int offset case check: if (strcmp(cursor->dflt.check, valbuf)!=0) return JSON_ERR_CHECKFAIL; - case object: /* silences a compiler warning */ + case enumerated: /* silences a compiler warning */ + case object: case array: break; } @@ -211,6 +216,8 @@ int json_read_array(const char *cp, const struct json_array_t *arr, const char * { int substatus, offset; char *tp; + char enumbuf[JSON_VAL_MAX+1]; + const struct json_enum_t *mp; #ifdef JSONDEBUG (void) printf("Entered json_read_array()\n"); @@ -253,6 +260,33 @@ int json_read_array(const char *cp, const struct json_array_t *arr, const char * return JSON_ERR_BADSTRING; stringend: break; + case enumerated: + if (isspace(*cp)) + cp++; + if (*cp != '"') + return JSON_ERR_BADSTRING; + else + ++cp; + for (tp = enumbuf; tp < enumbuf + sizeof(enumbuf) -1; tp++) + if (*cp == '"') { + ++cp; + *tp++ = '\0'; + goto enumend; + } else if (*cp == '\0') + return JSON_ERR_BADSTRING; + else { + *tp = *cp++; + } + return JSON_ERR_BADSTRING; + enumend: + for (mp = arr->arr.enumerated.map; mp->name != NULL; mp++) + if (strcmp(mp->name, enumbuf) == 0) { + arr->arr.enumerated.store[offset] = mp->value; + goto foundit; + } + return JSON_ERR_BADENUM; + foundit:; + break; case object: #ifdef JSONDEBUG (void) printf("Subarray parse begins.\n"); @@ -312,6 +346,7 @@ const char *json_error_string(int err) "unsupported array element type", "error while string parsing", "check attribute not matched", + "invalid enumerated value", }; if (err <= 0 || err >= (int)(sizeof(errors)/sizeof(errors[0]))) @@ -4,10 +4,16 @@ #include <stdbool.h> #include <ctype.h> -typedef enum {integer, real, string, boolean, object, array, check} json_type; +typedef enum {integer, real, string, boolean, + enumerated, object, array, check} json_type; #define nullbool -1 /* not true, not false */ +struct json_enum_t { + char *name; + int value; +}; + struct json_array_t { json_type element_type; union { @@ -17,6 +23,11 @@ struct json_array_t { char *store; int storelen; } strings; + struct { + const struct json_enum_t *map; + int *store; + int storelen; + } enumerated; } arr; int *count, maxlen; }; @@ -66,5 +77,6 @@ const char *json_error_string(int); #define JSON_ERR_SUBTYPE 14 /* unsupported array element type */ #define JSON_ERR_BADSTRING 15 /* error while string parsing */ #define JSON_ERR_CHECKFAIL 16 /* check attribute not matched */ +#define JSON_ERR_BADENUM 17 /* invalid enumerated value */ /* json.h ends here */ diff --git a/test_json.c b/test_json.c index c0a0263a..728c1afe 100644 --- a/test_json.c +++ b/test_json.c @@ -116,6 +116,22 @@ const struct json_attr_t json_attrs_4[] = { {NULL}, }; +/* Case 5: test parsing arrays of enumerated types */ + +const char *json_str5 = "[\"FOO\",\"BAR\",\"BAZ\"]"; +const struct json_enum_t enum_table[] = {{"BAR", 6}, {"FOO", 3}, {"BAZ", 14}, {NULL}}; + +static int enumstore[256]; +static int enumcount; + +const struct json_array_t json_array_5 = { + .element_type = enumerated, + .arr.enumerated.map = enum_table, + .arr.enumerated.store = enumstore, + .maxlen = sizeof(enumstore)/sizeof(enumstore[0]), + .count = &enumcount, +}; + int main(int argc UNUSED, char *argv[] UNUSED) { int status; @@ -160,6 +176,14 @@ int main(int argc UNUSED, char *argv[] UNUSED) ASSERT_BOOLEAN("flag1", flag1, true); ASSERT_BOOLEAN("flag2", flag2, false); + status = json_read_array(json_str5, &json_array_5, NULL); + ASSERT_CASE(5, status); + assert(enumcount == 3); + assert(enumstore[0] == 3); + assert(enumstore[1] == 6); + assert(enumstore[2] == 14); + (void)fprintf(stderr, "succeeded.\n"); + exit(0); } |