From a76c9cd40a3e6140d3f562de375d2299fd9865af Mon Sep 17 00:00:00 2001 From: Eduardo Chappa Date: Sat, 27 Aug 2022 22:08:12 -0600 Subject: * Addition of a first attempt to transform a json structure into a string. --- imap/src/c-client/http.c | 14 ----- imap/src/c-client/json.c | 141 +++++++++++++++++++++++++++++++++++++++++++++-- imap/src/c-client/json.h | 1 + imap/src/c-client/misc.c | 13 +++++ imap/src/c-client/misc.h | 1 + 5 files changed, 152 insertions(+), 18 deletions(-) (limited to 'imap') diff --git a/imap/src/c-client/http.c b/imap/src/c-client/http.c index d291c975..04ae0c09 100644 --- a/imap/src/c-client/http.c +++ b/imap/src/c-client/http.c @@ -88,7 +88,6 @@ typedef struct http_header_data_s { HTTP_STATUS_S *http_status_line_get(unsigned char *); void http_status_line_free(HTTP_STATUS_S **); void http_header_free(HTTP_HEADER_DATA_S **); -void buffer_add(unsigned char **, unsigned char *); unsigned char *hex_escape_url_part(unsigned char *, unsigned char *); unsigned char *encode_url_body_part(unsigned char *, unsigned char *); @@ -770,19 +769,6 @@ http_add_header(HTTP_REQUEST_S **reqp, unsigned char *name, unsigned char *value sprintf((*reqp)->header + hlen, "%s: %s\015\012", name, value); } -void -buffer_add(unsigned char **bufp, unsigned char *text) -{ - int len; - - if(!bufp || !text || !*text) return; - - len = *bufp ? strlen(*bufp) : 0; - fs_resize((void **) bufp, (len + strlen(text) + 1)*sizeof(char)); - (*bufp)[len] = '\0'; - strcat(*bufp, text); -} - void http_add_body(HTTP_REQUEST_S **reqp, unsigned char *text) { 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; +} diff --git a/imap/src/c-client/json.h b/imap/src/c-client/json.h index ed7800f5..2911044b 100644 --- a/imap/src/c-client/json.h +++ b/imap/src/c-client/json.h @@ -38,5 +38,6 @@ JSON_S *json_by_name_and_type(JSON_S *, char *, JObjType); JSON_S *json_parse(unsigned char *); JSON_S *json_body_value(JSON_S *, unsigned char *); void json_free(JSON_S **); +unsigned char *json2uchar(JSON_S *, unsigned char **); #endif /* JSON_H_INCLUDED */ diff --git a/imap/src/c-client/misc.c b/imap/src/c-client/misc.c index 0ddab9cc..621118b2 100644 --- a/imap/src/c-client/misc.c +++ b/imap/src/c-client/misc.c @@ -490,3 +490,16 @@ int compare_csizedtext (unsigned char *s1,SIZEDTEXT *s2) if (*s1) return 1; /* first string is longer */ return j ? -1 : 0; /* second string longer : strings identical */ } + +void +buffer_add(unsigned char **bufp, unsigned char *text) +{ + size_t len; + + if(!bufp || !text || !*text) return; + + len = *bufp ? strlen(*bufp) : 0; + fs_resize((void **) bufp, len + strlen(text) + 1); + (*bufp)[len] = '\0'; + strcat(*bufp, text); +} diff --git a/imap/src/c-client/misc.h b/imap/src/c-client/misc.h index 4e7afc23..b178124d 100644 --- a/imap/src/c-client/misc.h +++ b/imap/src/c-client/misc.h @@ -105,3 +105,4 @@ int compare_uchar (unsigned char c1,unsigned char c2); int compare_string (unsigned char *s1,unsigned char *s2); int compare_cstring (unsigned char *s1,unsigned char *s2); int compare_csizedtext (unsigned char *s1,SIZEDTEXT *s2); +void buffer_add(unsigned char **, unsigned char *); -- cgit v1.2.3-70-g09d2