summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEric S. Raymond <esr@thyrsus.com>2009-08-19 02:25:32 +0000
committerEric S. Raymond <esr@thyrsus.com>2009-08-19 02:25:32 +0000
commit747088bbe5dc34c0902c0bddc492bc4815f4a7c3 (patch)
tree4c2d4ef502290f6e7ce9136a30b6284f6d7e1bcc
parent276ffa0a53aae3fe555bdcbf98c4007120a2f0e3 (diff)
downloadgpsd-747088bbe5dc34c0902c0bddc492bc4815f4a7c3.tar.gz
Give the JSON parser the ability to map strings to enumerated types.
-rw-r--r--json.c39
-rw-r--r--json.h14
-rw-r--r--test_json.c24
3 files changed, 74 insertions, 3 deletions
diff --git a/json.c b/json.c
index 1b8ad3bd..dea599ed 100644
--- a/json.c
+++ b/json.c
@@ -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])))
diff --git a/json.h b/json.h
index 9aa983aa..b39c9417 100644
--- a/json.h
+++ b/json.h
@@ -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);
}