summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--json.c12
-rw-r--r--json.h10
-rw-r--r--test_json.c24
3 files changed, 43 insertions, 3 deletions
diff --git a/json.c b/json.c
index adc4d744..cfbed639 100644
--- a/json.c
+++ b/json.c
@@ -63,6 +63,7 @@ static int json_internal_read_object(const char *cp, const struct json_attr_t *a
char valbuf[JSON_VAL_MAX+1], *pval = NULL;
const struct json_attr_t *cursor;
int substatus, maxlen;
+ const struct json_enum_t *mp;
/* stuff fields with defaults in case they're omitted in the JSON input */
for (cursor = attrs; cursor->attribute != NULL; cursor++)
@@ -228,6 +229,8 @@ static int json_internal_read_object(const char *cp, const struct json_attr_t *a
maxlen = cursor->len - 1;
else if (cursor->type == check)
maxlen = strlen(cursor->dflt.check);
+ else if (cursor->map != NULL)
+ maxlen = sizeof(valbuf)-1;
if (*cp == '"') {
*pval = '\0';
#ifdef JSONDEBUG
@@ -260,6 +263,15 @@ static int json_internal_read_object(const char *cp, const struct json_attr_t *a
*pval++ = *cp;
break;
case post_val:
+ if (cursor->map != 0) {
+ for (mp = cursor->map; mp->name != NULL; mp++)
+ if (strcmp(mp->name, valbuf) == 0) {
+ goto foundit;
+ }
+ return JSON_ERR_BADENUM;
+ foundit:
+ (void)snprintf(valbuf, sizeof(valbuf), "%d", mp->value);
+ }
if (parent == NULL || parent->element_type != structobject) {
/* ordinary case - use the address in the cursor structure */
switch(cursor->type)
diff --git a/json.h b/json.h
index 30ca4c1a..bcf7ab8b 100644
--- a/json.h
+++ b/json.h
@@ -9,6 +9,11 @@ typedef enum {integer, uinteger, real, string, boolean, character,
#define nullbool -1 /* not true, not false */
+struct json_enum_t {
+ char *name;
+ int value;
+};
+
struct json_array_t {
json_type element_type;
union {
@@ -48,6 +53,7 @@ struct json_attr_t {
char *check;
} dflt;
size_t len;
+ const struct json_enum_t *map;
};
#define JSON_ATTR_MAX 31 /* max chars in JSON attribute name */
@@ -74,8 +80,8 @@ const char *json_error_string(int);
#define JSON_ERR_BADSTRING 15 /* error while string parsing */
#define JSON_ERR_CHECKFAIL 16 /* check attribute not matched */
#define JSON_ERR_NOPARSTR 17 /* can't support strings in parallel arrays */
-#define JSON_ERR_MISC 18 /* other data conversion error */
-
+#define JSON_ERR_BADENUM 18 /* invalid enumerated value */
+#define JSON_ERR_MISC 19 /* other data conversion error */
/*
* Use the following macros to declare template initializers for structobject
diff --git a/test_json.c b/test_json.c
index 82b78175..c0aeac10 100644
--- a/test_json.c
+++ b/test_json.c
@@ -109,7 +109,7 @@ static const char *json_str4 = "{\"flag1\":true,\"flag2\":false}";
static bool flag1, flag2;
static double dftreal;
static int dftinteger;
-static int dftuinteger;
+static unsigned int dftuinteger;
static const struct json_attr_t json_attrs_4[] = {
{"dftint", integer, .addr.integer = &dftinteger, .dflt.integer = -5},
@@ -168,6 +168,21 @@ static const char *json_str7 = "{\"class\":\"VERSION\",\
\"release\":\"2.40dev\",\"rev\":\"dummy-revision\",\
\"api_major\":3,\"api_minor\":1}";
+/* Case 8: test parsing arrays of enumerated types */
+
+const char *json_str8 = "{\"fee\":\"FOO\",\"fie\":\"BAR\",\"foe\":\"BAZ\"}";
+const struct json_enum_t enum_table[] = {
+ {"BAR", 6}, {"FOO", 3}, {"BAZ", 14}, {NULL}
+};
+
+static int fee, fie, foe;
+static const struct json_attr_t json_attrs_8[] = {
+ {"fee", integer, .addr.integer = &fee, .map=enum_table},
+ {"fie", integer, .addr.integer = &fie, .map=enum_table},
+ {"foe", integer, .addr.integer = &foe, .map=enum_table},
+ {NULL},
+};
+
#endif /* GPSDNG_ENABLE */
int main(int argc UNUSED, char *argv[] UNUSED)
@@ -244,6 +259,13 @@ int main(int argc UNUSED, char *argv[] UNUSED)
assert_string("rev", gpsdata.version.rev, "dummy-revision");
assert_integer("api_major", gpsdata.version.api_major, 3);
assert_integer("api_minor", gpsdata.version.api_minor, 1);
+
+ status = json_read_object(json_str8, json_attrs_8, NULL);
+ assert_case(8, status);
+ assert_integer("fee", fee, 3);
+ assert_integer("fie", fie, 6);
+ assert_integer("foe", foe, 14);
+
#endif /* GPSDNG_ENABLE */
(void)fprintf(stderr, "succeeded.\n");