summaryrefslogtreecommitdiff
path: root/imap/src/c-client/json.c
diff options
context:
space:
mode:
Diffstat (limited to 'imap/src/c-client/json.c')
-rw-r--r--imap/src/c-client/json.c141
1 files changed, 137 insertions, 4 deletions
diff --git a/imap/src/c-client/json.c b/imap/src/c-client/json.c
index 23446e87..c6df062d 100644
--- a/imap/src/c-client/json.c
+++ b/imap/src/c-client/json.c
@@ -47,6 +47,8 @@ JSON_S *json_array_parse_work(unsigned char **);
JSON_S *json_array_parse(unsigned char **);
void json_array_free(JSON_S **);
+unsigned char *json_add_array_value(JSON_S *, unsigned char **);
+
/* we are parsing from the text of the json object, so it is
* never possible to have a null character, unless something
* is corrupt, in whose case we return JNumberError.
@@ -210,8 +212,9 @@ void *
json_value_parse(unsigned char **s, JObjType *jtype)
{
void *rv = NIL;
- unsigned char *u, *w;
+ unsigned char *t, *u, *v, *w;
unsigned long *l;
+ double d;
w = *s;
json_skipws(w);
@@ -268,10 +271,16 @@ json_value_parse(unsigned char **s, JObjType *jtype)
json_skipws(w);
break;
+ /* in order to make sure we go back and forth we save the
+ * original value, not the converted value.
+ */
case JDecimal :
- case JExponential: l = fs_get(sizeof(double));
- *l = strtod((char *) w, (char **) &w);
- rv = (void *) l;
+ case JExponential: t = w;
+ d = strtod((char *) w, (char **) &w);
+ u = v = fs_get(w-t);
+ for(; t < w; t++) *v++ = *t++;
+ *v = '\0';
+ rv = (void *) u;
json_skipws(w);
break;
@@ -477,3 +486,127 @@ json_by_name_and_type(JSON_S *json, char *name, JObjType jtype)
return j && j->jtype == jtype ? j : NIL;
}
+
+#define JSON_ADD_NAME(X) { \
+ if((X)){ \
+ unsigned char *buf; \
+ size_t len; \
+ len = strlen((X)) + 4; \
+ buf = fs_get(len); \
+ sprintf(buf, "\"%s\":", (X)); \
+ buffer_add(rv, buf); \
+ fs_give((void **) &buf); \
+ } \
+}
+
+#define JSON_ADD_STRING_VALUE(X) { \
+ if((X)){ \
+ unsigned char *buf; \
+ size_t len; \
+ len = strlen((X)) + 3; \
+ buf = fs_get(len); \
+ sprintf(buf, "\"%s\"", (X)); \
+ buffer_add(rv, buf); \
+ fs_give((void **) &buf); \
+ } \
+}
+
+#define JSON_ADD_LONG_VALUE(X) { \
+ if((X)){ \
+ unsigned char *buf; \
+ buf = fs_get(128 + 1); \
+ sprintf(buf, "%lu", (X)); \
+ buffer_add(rv, buf); \
+ fs_give((void **) &buf); \
+ } \
+}
+
+unsigned char *json2uchar(JSON_S *j, unsigned char **rv)
+{
+ JSON_S *jp;
+ unsigned char *buf = NIL;
+ unsigned long buflen = 0L;
+ size_t len;
+
+ if(!j || j->jtype != JObject) return *rv;
+
+ if(*rv) JSON_ADD_NAME(j->name);
+ buffer_add(rv, "{");
+
+ for(jp = (JSON_S *) j->value; jp; jp = jp->next){
+ switch(jp->jtype){
+ case JObject: *rv = json2uchar(jp, rv);
+ break;
+
+ case JString: JSON_ADD_NAME(jp->name);
+ JSON_ADD_STRING_VALUE((unsigned char *) jp->value);
+ break;
+
+ case JExponential:
+ case JDecimal:
+ case JNull:
+ case JBoolean: JSON_ADD_NAME(jp->name);
+ buffer_add(rv, (unsigned char *) jp->value);
+ break;
+
+ case JLong: JSON_ADD_NAME(jp->name);
+ JSON_ADD_LONG_VALUE(*(long *) jp->value);
+ break;
+
+ case JArray: JSON_ADD_NAME(jp->name);
+ *rv = json_add_array_value(jp, rv);
+ break;
+
+ default: break;
+ }
+ if(jp->next) buffer_add(rv, ",");
+ }
+
+ buffer_add(rv, "}");
+ return *rv;
+}
+
+unsigned char *json_add_array_value(JSON_S *j, unsigned char **rv)
+{
+ JSON_S *jp;
+ unsigned char *buf = NIL;
+ unsigned long buflen = 0L;
+ size_t len;
+
+ if(!j || j->jtype != JArray) return *rv;
+
+ if(*rv) JSON_ADD_NAME(j->name);
+ buffer_add(rv, "[");
+
+ for(jp = (JSON_S *) j->value; jp; jp = jp->next){
+ switch(jp->jtype){
+ case JObject: *rv = json2uchar(jp, rv);
+ break;
+
+ case JString: JSON_ADD_NAME(jp->name);
+ JSON_ADD_STRING_VALUE((unsigned char *) jp->value);
+ break;
+
+ case JExponential:
+ case JDecimal:
+ case JNull:
+ case JBoolean: JSON_ADD_NAME(jp->name);
+ buffer_add(rv, (unsigned char *) jp->value);
+ break;
+
+ case JLong: JSON_ADD_NAME(jp->name);
+ JSON_ADD_LONG_VALUE(*(long *) jp->value);
+ break;
+
+ case JArray: JSON_ADD_NAME(jp->name);
+ *rv = json_add_array_value(jp, rv);
+ break;
+
+ default: break;
+ }
+ if(jp->next) buffer_add(rv, ",");
+ }
+
+ buffer_add(rv, "]");
+ return *rv;
+}