summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--json.c143
-rw-r--r--json.h13
2 files changed, 106 insertions, 50 deletions
diff --git a/json.c b/json.c
index aa84ba9a..086ad0e6 100644
--- a/json.c
+++ b/json.c
@@ -20,23 +20,42 @@ int json_read_object(const char *cp, char *baseptr, const struct json_attr_t *at
/* stuff fields with defaults in case they're omitted in the JSON input */
for (cursor = attrs; cursor->attribute != NULL; cursor++)
- switch(cursor->type)
- {
- case integer:
- *(cursor->addr.integer) = cursor->dflt.integer;
- break;
- case real:
- *(cursor->addr.real) = cursor->dflt.real;
- break;
- case string:
- cursor->addr.string.ptr[0] = '\0';
- break;
- case boolean:
- *(cursor->addr.boolean) = cursor->dflt.boolean;
- break;
- case array: /* silences a compiler warning */
- break;
- }
+ if (baseptr != NULL)
+ switch(cursor->type)
+ {
+ case integer:
+ *((int *)&baseptr[cursor->addr.offset]) = cursor->dflt.integer;
+ break;
+ case real:
+ *((double *)&baseptr[cursor->addr.offset]) = cursor->dflt.real;
+ break;
+ case string:
+ baseptr[cursor->addr.offset] = '\0';
+ break;
+ case boolean:
+ *((bool *)&baseptr[cursor->addr.offset]) = cursor->dflt.boolean;
+ break;
+ case array: /* silences a compiler warning */
+ break;
+ }
+ else
+ switch(cursor->type)
+ {
+ case integer:
+ *(cursor->addr.integer) = cursor->dflt.integer;
+ break;
+ case real:
+ *(cursor->addr.real) = cursor->dflt.real;
+ break;
+ case string:
+ cursor->addr.string.ptr[0] = '\0';
+ break;
+ case boolean:
+ *(cursor->addr.boolean) = cursor->dflt.boolean;
+ break;
+ case array: /* silences a compiler warning */
+ break;
+ }
/* parse input JSON */
for (; *cp; cp++) {
@@ -51,7 +70,7 @@ int json_read_object(const char *cp, char *baseptr, const struct json_attr_t *at
else if (*cp == '{')
state = await_attr;
else
- return -1; /* non-whitespace when expecting object start */
+ return JSON_ERR_OBSTART; /* non-WS when expecting object start */
break;
case await_attr:
if (isspace(*cp))
@@ -62,7 +81,7 @@ int json_read_object(const char *cp, char *baseptr, const struct json_attr_t *at
} else if (*cp == '}')
break;
else
- return -2; /* non-whitespace while expecting attribute */
+ return JSON_ERR_ATTRSTART; /* non-WS while expecting attribute */
break;
case in_attr:
if (*cp == '"') {
@@ -74,11 +93,11 @@ int json_read_object(const char *cp, char *baseptr, const struct json_attr_t *at
if (strcmp(cursor->attribute, attrbuf)==0)
break;
if (cursor->attribute == NULL)
- return -3; /* unknown attribute name */
+ return JSON_ERR_BADATTR; /* unknown attribute name */
state = await_value;
pval = valbuf;
} else if (pattr >= attrbuf + JSON_ATTR_MAX - 1)
- return -4; /* attribute name too long */
+ return JSON_ERR_ATTRLEN; /* attribute name too long */
else
*pattr++ = *cp;
break;
@@ -88,12 +107,12 @@ int json_read_object(const char *cp, char *baseptr, const struct json_attr_t *at
else if (*cp == '[') {
--cp;
if (cursor->type != array)
- return -5; /* saw [ when not expecting array */
+ return JSON_ERR_NOARRAY; /* saw [ when not expecting array */
substatus = json_read_array(cp, cursor->addr.array, &cp);
if (substatus < 0)
return substatus;
} else if (cursor->type == array)
- return -6; /* array element was specified, but no [ */
+ return JSON_ERR_NOBRAK; /* array element was specified, but no [ */
else if (*cp == '"') {
state = in_val_string;
pval = valbuf;
@@ -110,8 +129,8 @@ int json_read_object(const char *cp, char *baseptr, const struct json_attr_t *at
(void) printf("Collected string value %s\n", valbuf);
#endif /* JSONDEBUG */
state = post_val;
- } else if (pval > valbuf + JSON_VAL_MAX - 1)
- return -7; /* value too long */
+ } else if (pval > valbuf + JSON_VAL_MAX - 1 || pval > valbuf + cursor->addr.string.len - 1)
+ return JSON_ERR_STRLONG; /* value too long */
else
*pval++ = *cp;
break;
@@ -125,32 +144,49 @@ int json_read_object(const char *cp, char *baseptr, const struct json_attr_t *at
if (*cp == '}' || *cp == ',')
--cp;
} else if (pval > valbuf + JSON_VAL_MAX - 1)
- return -8; /* value too long */
+ return JSON_ERR_TOKLONG; /* value too long */
else
*pval++ = *cp;
break;
case post_val:
- switch(cursor->type)
- {
- case integer:
- *(cursor->addr.integer) = atoi(valbuf);
- break;
- case real:
- *(cursor->addr.real) = atof(valbuf);
- break;
- case string:
- (void)strncpy(cursor->addr.string.ptr, valbuf, cursor->addr.string.len);
- break;
- case boolean:
-#ifdef JSONDEBUG
- (void) printf("Boolean value '%s' processed to %d\n", valbuf, !strcmp(valbuf, "true"));
-#endif /* JSONDEBUG */
- *(cursor->addr.boolean) = (bool)!strcmp(valbuf, "true");
- break;
- case array:
- // FIXME: must actually handle this case
- break;
- }
+ if (baseptr != NULL)
+ switch(cursor->type)
+ {
+ case integer:
+ *((int *)&baseptr[cursor->addr.offset]) = atoi(valbuf);
+ break;
+ case real:
+ *((double *)&baseptr[cursor->addr.offset]) = atof(valbuf);
+ break;
+ case string:
+ return JSON_ERR_SUBSTRING; /* string in array subojects not supported */
+ case boolean:
+ *((bool *)&baseptr[cursor->addr.offset]) = (bool)!strcmp(valbuf, "true");
+ break;
+ case array: /* silences a compiler warning */
+ break;
+ }
+ else
+ switch(cursor->type)
+ {
+ case integer:
+ *(cursor->addr.integer) = atoi(valbuf);
+ break;
+ case real:
+ *(cursor->addr.real) = atof(valbuf);
+ break;
+ case string:
+ (void)strncpy(cursor->addr.string.ptr, valbuf, cursor->addr.string.len);
+ break;
+ case boolean:
+ #ifdef JSONDEBUG
+ (void) printf("Boolean value '%s' processed to %d\n", valbuf, !strcmp(valbuf, "true"));
+ #endif /* JSONDEBUG */
+ *(cursor->addr.boolean) = (bool)!strcmp(valbuf, "true");
+ break;
+ case array: /* silences a compiler warning */
+ break;
+ }
if (isspace(*cp))
continue;
else if (*cp == ',')
@@ -158,7 +194,7 @@ int json_read_object(const char *cp, char *baseptr, const struct json_attr_t *at
else if (*cp == '}')
return 0;
else
- return -9; /* garbage while expecting comma or } */
+ return JSON_ERR_BADTRAIL; /* garbage while expecting comma or } */
break;
}
}
@@ -170,12 +206,19 @@ int json_read_object(const char *cp, char *baseptr, const struct json_attr_t *at
int json_read_array(const char *cp, const struct json_array_t *attrs, const char **end)
{
+ int substatus;
+
while (isspace(*cp))
cp++;
if (*cp != '[')
- return -10; /* didn't find expected array start */
+ return JSON_ERR_ARRAYSTART; /* didn't find expected array start */
- // Array parsing logic goes here
+ for (;;) {
+ while (isspace(*cp))
+ cp++;
+ if (*cp == ']')
+ break;
+ }
if (end != NULL)
*end = cp;
diff --git a/json.h b/json.h
index 34b98c06..e98e04b7 100644
--- a/json.h
+++ b/json.h
@@ -21,6 +21,7 @@ struct json_attr_t {
} string;
bool *boolean;
struct json_array_t *array;
+ int offset;
} addr;
union {
int integer;
@@ -35,4 +36,16 @@ struct json_attr_t {
int json_read_object(const char *, char *, const struct json_attr_t *, const char **end);
+#define JSON_ERR_OBSTART -1 /* non-WZ when expecting object start */
+#define JSON_ERR_ATTRSTART -2 /* non-WZ when expecting attrib start */
+#define JSON_ERR_BADATTR -3 /* unknown attribute name */
+#define JSON_ERR_ATTRLEN -4 /* attribute name too long */
+#define JSON_ERR_NOARRAY -5 /* saw [ when not expecting array */
+#define JSON_ERR_NOBRAK -6 /* array element specified, but no [ */
+#define JSON_ERR_STRLONG -7 /* string value too long */
+#define JSON_ERR_TOKLONG -8 /* token value too long */
+#define JSON_ERR_SUBSTRING -9 /* no strings in array subobjects */
+#define JSON_ERR_BADTRAIL -10 /* garbage while expecting , or } */
+#define JSON_ERR_ARRAYSTART -11 /* didn't find expected array start */
+
/* json.h ends here */