aboutsummaryrefslogtreecommitdiff
path: root/src/json-gram.y
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org>2015-12-25 09:45:32 +0200
committerSergey Poznyakoff <gray@gnu.org>2015-12-25 09:45:32 +0200
commit8312f45f48ed9d995a15ee6707257f4c8946528d (patch)
tree1a32dcce9886c46654e7f8f3c3a7cc99413a5d9e /src/json-gram.y
parentffd39f82123a582b97fdbaf61ebcb932ecc6682e (diff)
downloadgrecs-8312f45f48ed9d995a15ee6707257f4c8946528d.tar.gz
grecs-8312f45f48ed9d995a15ee6707257f4c8946528d.tar.bz2
Cleanup json code.
* src/json-gram.y (json_new_string) (json_new_number,json_new_bool,json_new_null) (json_new_object),json_new_null) (json_new_object,json_new_array) (json_object_set,json_object_get) (json_array_size,json_array_flatten) (json_array_insert,json_array_append) (json_array_get): New functions. * src/json.h (json_array): New member ol. (json_unescape): Change signature. Add new prototypes. * src/json-lex.l: Return allocated string as T_STRING. (json_unescape): Change signature. * src/jsonfmt.c: Use new accessors. Don't escape / in strings.
Diffstat (limited to 'src/json-gram.y')
-rw-r--r--src/json-gram.y219
1 files changed, 181 insertions, 38 deletions
diff --git a/src/json-gram.y b/src/json-gram.y
index e92ad35..ecfb561 100644
--- a/src/json-gram.y
+++ b/src/json-gram.y
@@ -21,6 +21,7 @@
#include "grecs.h"
#include <grecs-locus.h>
#include <string.h>
+#include <errno.h>
#include "json-gram.h"
#include "json.h"
@@ -33,7 +34,7 @@ static void
pairfree(void *ptr)
{
struct json_pair *p = ptr;
- free(p->k);
+ grecs_free(p->k);
json_value_free(p->v);
free(p);
}
@@ -55,17 +56,15 @@ objfree(void *ptr)
%token <b> T_BOOL
%token T_NULL T_ERR
-%type <a> array
%type <list> objects objlist pairs pairlist
%type <p> pair
-%type <obj> object
+%type <obj> object array
%type <o> assoc
%union {
int b;
double n;
char *s;
- struct json_array *a;
struct grecs_symtab *o;
struct json_value *obj;
struct grecs_list *list;
@@ -75,7 +74,7 @@ objfree(void *ptr)
input : object
{
- json_return_obj = $1;
+ json_return_obj = $1;
}
;
@@ -99,10 +98,6 @@ object : T_NUMBER
$$ = json_value_create(json_null);
}
| array
- {
- $$ = json_value_create(json_arr);
- $$->v.a = $1;
- }
| assoc
{
$$ = json_value_create(json_object);
@@ -112,21 +107,8 @@ object : T_NUMBER
array : '[' objects ']'
{
- struct json_array *a = grecs_malloc(sizeof(*a));
- if (!$2) {
- a->oc = 0;
- a->ov = NULL;
- } else {
- size_t i;
- struct grecs_list_entry *ep;
- a->oc = $2->count;
- a->ov = grecs_calloc(a->oc, sizeof(a->ov));
- for (i = 0, ep = $2->head; ep; i++, ep = ep->next) {
- struct json_value *p = ep->data;
- a->ov[i] = p;
- }
- }
- $$ = a;
+ $$ = json_new_array();
+ $$->v.a->ol = $2;
}
;
@@ -140,7 +122,6 @@ objects : /* empty */
objlist : object
{
$$ = grecs_list_create();
- $$->free_entry = objfree;
grecs_list_append($$, $1);
}
| objlist ',' object
@@ -229,12 +210,16 @@ json_value_free(struct json_value *obj)
case json_number:
break;
case json_string:
- free(obj->v.s);
+ grecs_free(obj->v.s);
break;
case json_arr:
for (i = 0; i < obj->v.a->oc; i++)
json_value_free(obj->v.a->ov[i]);
- free(obj->v.a);
+ if (obj->v.a->ol) {
+ obj->v.a->ol->free_entry = objfree;
+ grecs_list_free(obj->v.a->ol);
+ }
+ grecs_free(obj->v.a);
break;
case json_object:
grecs_symtab_free(obj->v.o);
@@ -322,7 +307,7 @@ json_value_lookup(struct json_value *obj, const char *ident)
q = qbuf;
while (*ident) {
if (*ident == '\\') {
- int c;
+ char c;
++ident;
if (json_unescape(*ident, &c))
*q++ = *ident++;
@@ -345,18 +330,12 @@ json_value_lookup(struct json_value *obj, const char *ident)
break;
case json_arr:
l = strtoul(qbuf, &q, 10);
- if (*q == 0 && l < obj->v.a->oc)
- obj = obj->v.a->ov[l];
- else
+ if (*q != 0 || json_array_get(obj, l, &obj))
obj = NULL;
break;
- case json_object: {
- struct json_pair key, *match;
- key.k = qbuf;
- match = grecs_symtab_lookup_or_install(obj->v.o,
- &key, NULL);
- obj = match ? match->v : NULL;
- }
+ case json_object:
+ if (json_object_get(obj, qbuf, &obj))
+ obj = NULL;
}
}
if (*ident)
@@ -364,8 +343,172 @@ json_value_lookup(struct json_value *obj, const char *ident)
free(qbuf);
return obj;
}
+
+struct json_value *
+json_new_string(char const *str)
+{
+ struct json_value *j = json_value_create(json_string);
+ j->v.s = grecs_strdup(str);
+ return j;
+}
+struct json_value *
+json_new_number(double n)
+{
+ struct json_value *j = json_value_create(json_number);
+ j->v.n = n;
+ return j;
+}
+struct json_value *
+json_new_bool(int b)
+{
+ struct json_value *j = json_value_create(json_bool);
+ j->v.b = b;
+ return j;
+}
+struct json_value *
+json_new_null(void)
+{
+ return json_value_create(json_null);
+}
+
+struct json_value *
+json_new_object(void)
+{
+ struct json_value *j = json_value_create(json_object);
+ j->v.o = json_assoc_create();
+ return j;
+}
+
+int
+json_object_set(struct json_value *obj, char const *name,
+ struct json_value *val)
+{
+ struct json_pair pair, *ret;
+ int install;
+ if (obj->type != json_object) {
+ errno = EINVAL;
+ return -1;
+ }
+ pair.k = (char*) name;
+ pair.v = NULL;
+ ret = grecs_symtab_lookup_or_install(obj->v.o, &pair, &install);
+ if (install)
+ ret->k = grecs_strdup(ret->k);
+ ret->v = val;
+ return 0;
+}
+
+int
+json_object_get(struct json_value *obj, char const *name,
+ struct json_value **retval)
+{
+ struct json_pair pair, *ret;
+ if (obj->type != json_object) {
+ errno = EINVAL;
+ return -1;
+ }
+ pair.k = (char*) name;
+ pair.v = NULL;
+ ret = grecs_symtab_lookup_or_install(obj->v.o, &pair, NULL);
+ if (ret) {
+ *retval = ret->v;
+ return 0;
+ }
+ return 1;
+}
+struct json_value *
+json_new_array(void)
+{
+ struct json_value *j = json_value_create(json_arr);
+ j->v.a = grecs_malloc(sizeof(*j->v.a));
+ j->v.a->oc = 0;
+ j->v.a->ov = NULL;
+ j->v.a->ol = NULL;
+ return j;
+}
+
+size_t
+json_array_size(struct json_value *j)
+{
+ if (j->type != json_arr) {
+ errno = EINVAL;
+ return 0;
+ }
+ return j->v.a->oc + grecs_list_size(j->v.a->ol);
+}
+
+void
+json_array_flatten(struct json_value *j)
+{
+ size_t size, i;
+ struct grecs_list_entry *ep;
+
+ size = grecs_list_size(j->v.a->ol);
+
+ if (size == 0)
+ return;
+
+ j->v.a->ov = grecs_realloc(j->v.a->ov,
+ (j->v.a->oc + size) * sizeof(j->v.a->ov[0]));
+
+ for (ep = j->v.a->ol->head, i = j->v.a->oc; ep; ep = ep->next, i++)
+ j->v.a->ov[i] = ep->data;
+ j->v.a->oc = i;
+ grecs_list_clear(j->v.a->ol);
+}
+
+int
+json_array_insert(struct json_value *j, size_t idx, struct json_value *v)
+{
+ size_t size;
+ if (j->type != json_arr) {
+ errno = EINVAL;
+ return -1;
+ }
+ size = json_array_size(j);
+ if (idx < size) {
+ json_array_flatten(j);
+ j->v.a->ov[idx] = v;
+ } else {
+ size_t i;
+ for (i = size; i < idx; i++)
+ json_array_append(j, NULL);
+ json_array_append(j, v);
+ }
+ return 0;
+}
+
+int
+json_array_append(struct json_value *j, struct json_value *v)
+{
+ if (j->type != json_arr) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ if (!j->v.a->ol)
+ j->v.a->ol = grecs_list_create();
+ grecs_list_append(j->v.a->ol, v);
+ return 0;
+}
+int
+json_array_get(struct json_value *j, size_t idx, struct json_value **retval)
+{
+ if (j->type != json_arr) {
+ errno = EINVAL;
+ return -1;
+ }
+ if (idx >= json_array_size(j)) {
+ errno = ENOENT;
+ return -1;
+ }
+
+ json_array_flatten(j);
+ *retval = j->v.a->ov[idx];
+ return 0;
+}

Return to:

Send suggestions and report system problems to the System administrator.