Changeset: 76211429a963 for MonetDB URL: https://dev.monetdb.org/hg/MonetDB?cmd=changeset;node=76211429a963 Modified Files: monetdb5/modules/atoms/json.c monetdb5/modules/atoms/json.h Branch: Jun2020 Log Message:
Allow for whole strings as separators in JSOnplaintext The idea is to check if there is enough space in the output string and realloc it if there isn't, before copying the value and the separator. diffs (161 lines): diff --git a/monetdb5/modules/atoms/json.c b/monetdb5/modules/atoms/json.c --- a/monetdb5/modules/atoms/json.c +++ b/monetdb5/modules/atoms/json.c @@ -1142,73 +1142,92 @@ JSONfilter(json *ret, json *js, str *exp // The json string should be valid static char * -JSONplaintext(char *r, size_t *l, JSON *jt, int idx, char sep) +JSONplaintext(char **r, size_t *l, size_t *ilen, JSON *jt, int idx, str sep, size_t sep_len) { int i; - size_t j; + unsigned int j, k; switch (jt->elm[idx].kind) { case JSON_OBJECT: for (i = jt->elm[idx].next; i; i = jt->elm[i].next) if (jt->elm[i].child) - r = JSONplaintext(r, l, jt, jt->elm[i].child, sep); + *r = JSONplaintext(r, l, ilen, jt, jt->elm[i].child, sep, sep_len); break; case JSON_ARRAY: for (i = jt->elm[idx].next; i; i = jt->elm[i].next) - r = JSONplaintext(r, l, jt, i, sep); + *r = JSONplaintext(r, l, ilen, jt, i, sep, sep_len); break; case JSON_ELEMENT: case JSON_VALUE: if (jt->elm[idx].child) - r = JSONplaintext(r, l, jt, jt->elm[idx].child, sep); + *r = JSONplaintext(r, l, ilen, jt, jt->elm[idx].child, sep, sep_len); break; - case JSON_STRING: - for (j = 1; *l > 1 && j < jt->elm[idx].valuelen - 1; j++) { + case JSON_STRING: + // Make sure there is enough space for the value plus the separator plus the NULL byte + if (*l < jt->elm[idx].valuelen - 2 + sep_len + 1) { + char *p = *r - *ilen + *l; + *ilen *= 2; + *r = GDKrealloc(p, *ilen); + *r += *l; + *l = *ilen - *l; + } + for (j = 1; j < jt->elm[idx].valuelen - 1; j++) { if (jt->elm[idx].value[j] == '\\') - *r = jt->elm[idx].value[++j]; + **r = jt->elm[idx].value[++j]; else - *r = jt->elm[idx].value[j]; - r++; - (*l)--; - } - if (*l > 1 && sep) { - *r++ = sep; + **r = jt->elm[idx].value[j]; + (*r)++; (*l)--; } + for(k = 0; k < sep_len; k++) { + **r = *(sep + k); + (*r)++; + } + (*l) -= k; break; default: - for (j = 0; *l > 1 && j < jt->elm[idx].valuelen; j++) { - *r = jt->elm[idx].value[j]; - r++; + if (*l < jt->elm[idx].valuelen + sep_len + 1) { + unsigned int offset = *ilen - *l; + char *p = *r - offset; + *ilen *= 2; + *r = GDKrealloc(p, *ilen); + *r += offset; + *l = *ilen - offset; + } + for (j = 0; j < jt->elm[idx].valuelen; j++) { + **r = jt->elm[idx].value[j]; + (*r)++; (*l)--; } - if (*l > 1 && sep) { - *r++ = sep; - (*l)--; + for(k = 0; k < sep_len; k++) { + **r = *(sep + k); + (*r)++; } + (*l) -= k; } assert(*l > 0); - *r = 0; - return r; + **r = 0; + return *r; } str JSONjson2text(str *ret, json *js) { JSON *jt; - size_t l; + size_t l, ilen; str s; jt = JSONparse(*js); CHECK_JSON(jt); - l = strlen(*js) + 1; + ilen = l = strlen(*js) + 1; s = GDKmalloc(l); if(s == NULL) { JSONfree(jt); throw(MAL,"json2txt", SQLSTATE(HY013) MAL_MALLOC_FAIL); } - JSONplaintext(s, &l, jt, 0, ' '); + s = JSONplaintext(&s, &l, &ilen, jt, 0, " ", 1); + s -= ilen - l; l = strlen(s); if (l) s[l - 1] = 0; @@ -1221,22 +1240,23 @@ str JSONjson2textSeparator(str *ret, json *js, str *sep) { JSON *jt; - size_t l; + size_t l, ilen, sep_len = strlen(*sep); str s; jt = JSONparse(*js); CHECK_JSON(jt); - l = strlen(*js) + 1; + ilen = l = strlen(*js) + 1; s = GDKmalloc(l); if(s == NULL) { JSONfree(jt); throw(MAL,"json2txt", SQLSTATE(HY013) MAL_MALLOC_FAIL); } - JSONplaintext(s, &l, jt, 0, **sep); + s = JSONplaintext(&s, &l, &ilen, jt, 0, *sep, sep_len); + s -= ilen - l; l = strlen(s); - if (l && **sep) - s[l - 1] = 0; + if (l && sep_len) + s[l - sep_len] = 0; *ret = s; JSONfree(jt); return MAL_SUCCEED; diff --git a/monetdb5/modules/atoms/json.h b/monetdb5/modules/atoms/json.h --- a/monetdb5/modules/atoms/json.h +++ b/monetdb5/modules/atoms/json.h @@ -10,6 +10,7 @@ #define JSON_H #include "gdk.h" +#include "gdk_utils.h" #include "mal.h" #include "mal_client.h" #include "mal_instruction.h" _______________________________________________ checkin-list mailing list checkin-list@monetdb.org https://www.monetdb.org/mailman/listinfo/checkin-list