diff --git a/shlr/sdb/src/query.c b/shlr/sdb/src/query.c index c0b7d35eef..1048a9e0f5 100644 --- a/shlr/sdb/src/query.c +++ b/shlr/sdb/src/query.c @@ -8,6 +8,39 @@ #include #include "sdb.h" +typedef struct { + char *buf; + int len; + int size; +} StrBuf; + +static StrBuf* strbuf_new() { + return calloc (sizeof(StrBuf),1); +} + +static StrBuf* strbuf_append(StrBuf *sb, const char *str) { + int len = strlen (str); + if ((sb->len + len+1)>=sb->size) { + int newsize = sb->size+len+256; + char *b = realloc (sb->buf, newsize); + /// TODO perform free and force all callers to update the ref? + if (!b) return NULL; + sb->buf = b; + } + memcpy (sb->buf+sb->len, str, len); + memcpy (sb->buf+sb->len+len, "\n", 2); + sb->len += len+1; + return sb; +} + +static StrBuf *strbuf_free(StrBuf *sb) { + free (sb->buf); + free (sb); + return NULL; +} + +/*******/ + SDB_API int sdb_queryf (Sdb *s, const char *fmt, ...) { char string[4096]; int ret; @@ -32,24 +65,20 @@ SDB_API char *sdb_querysf (Sdb *s, char *buf, size_t buflen, const char *fmt, .. // TODO: Reimplement as a function with optimized concat #define out_concat(x) if (x&&*x) { \ - int size = 2+strlen(x)+(out?strlen(out)+4:0); \ - if (out) { char *o = realloc (out, size); \ - if (o) { strcat (o, "\n"); strcat (o, x); out = o; } \ - } else out = strdup (x); \ + strbuf_append (out, x); \ } typedef struct { - char **out; + StrBuf *out; int encode; } ForeachListUser; static int foreach_list_cb(void *user, const char *k, const char *v) { ForeachListUser *rlu = user; - char *line, *out; + char *line; int klen, vlen; ut8 *v2 = NULL; if (!rlu) return 0; - out = *rlu->out; klen = strlen (k); if (rlu->encode) { v2 = sdb_decode (v, NULL); @@ -60,43 +89,44 @@ static int foreach_list_cb(void *user, const char *k, const char *v) { memcpy (line, k, klen); line[klen] = '='; memcpy (line+klen+1, v, vlen+1); - out_concat (line); - *(rlu->out) = out; + strbuf_append (rlu->out, line); free (v2); free (line); return 1; } -static void walk_namespace (char **_out, char *root, int left, char *p, SdbNs *ns) { +static void walk_namespace (StrBuf *sb, char *root, int left, char *p, SdbNs *ns) { int len; SdbListIter *it; - char *out = *_out; + char *_out, *out = sb->buf; SdbNs *n; char *roote = root + strlen (root); - if (ns->sdb) { - ls_foreach (ns->sdb->ns, it, n) { - len = strlen (n->name); - p[0] = '/'; - if (len+2name, len+1); - left -= len+2; - } - out_concat (root); - *_out = out; - walk_namespace (_out, root, left, - roote+len+1, n); - out = *_out; + if (!ns->sdb) + return; + ls_foreach (ns->sdb->ns, it, n) { + len = strlen (n->name); + p[0] = '/'; + if (len+2name, len+1); + left -= len+2; } + strbuf_append (sb, root); + _out = out; + walk_namespace (sb, root, left, + roote+len+1, n); + out = _out; } } SDB_API char *sdb_querys (Sdb *r, char *buf, size_t len, const char *cmd) { int i, d, ok, w, alength, bufset = 0, is_ref = 0, encode = 0; - char *eq, *tmp, *json, *next, *quot, *arroba, *out = NULL; + char *eq, *tmp, *json, *next, *quot, *arroba; const char *p, *q, *val = NULL; + StrBuf *out; Sdb *s = r; ut64 n; if (!s || (!cmd && !buf)) return NULL; + out = strbuf_new (); if (cmd) { if (len<1 || !buf) { bufset = 1; @@ -158,7 +188,7 @@ next_quote: *eq++ = 0; if (bufset) free (buf); - free (out); + strbuf_free (out); return NULL; } next = strchr (quot, ';'); @@ -173,7 +203,7 @@ next_quote: s = sdb_ns (s, cmd, eq?1:0); if (!s) { eprintf ("Cant find namespace %s\n", cmd); - free (out); + strbuf_free (out); if (bufset) free (buf); return NULL; @@ -184,6 +214,7 @@ next_quote: goto next_arroba; } if (*cmd=='*') { + char *res; if (!strcmp (cmd, "***")) { char root[1024]; // limit namespace length? SdbListIter *it; @@ -193,14 +224,16 @@ next_quote: if (lenname, len+1); out_concat (root); - walk_namespace (&out, root, + walk_namespace (out, root, sizeof (root)-len, root+len, ns); } else eprintf ("TODO: Namespace too long\n"); } if (bufset) free (buf); - return out; + res = out->buf; + free (out); + return res; } if (!strcmp (cmd, "**")) { SdbListIter *it; @@ -210,14 +243,18 @@ next_quote: } if (bufset) free (buf); - return out; + res = out->buf; + free (out); + return res; } if (!strcmp (cmd, "*")) { - ForeachListUser user = { &out, encode }; + ForeachListUser user = { out, encode }; sdb_foreach (s, foreach_list_cb, &user); if (bufset) free (buf); - return out; + res = out->buf; + free (out); + return res; } } json = strchr (cmd, ':'); @@ -552,7 +589,8 @@ next_quote: fail: if (bufset) free (buf); - return out; + free (out); + return out->buf; } SDB_API int sdb_query (Sdb *s, const char *cmd) { diff --git a/shlr/sdb/src/util.c b/shlr/sdb/src/util.c index b39e3bfc60..5ed7a8aada 100644 --- a/shlr/sdb/src/util.c +++ b/shlr/sdb/src/util.c @@ -44,21 +44,22 @@ SDB_API char *sdb_itoa(ut64 n, char *s, int base) { static const char* lookup = "0123456789abcdef"; const int imax = 62; int i = imax; + if (base > 16) + return NULL; if (!s) { - s = malloc (64); + s = calloc (64, sizeof(char)); if (!s) return NULL; - memset (s, 0, 64); } s[imax+1] = '\0'; - if (base==16) { - for (; n && i>0; n/=16) - s[i--] = lookup[(n % 16)]; + if (base <= 10) { + for (; n && i>0; n/=base) + s[i--] = (n % base) + '0'; + } else { + for (; n && i>0; n/=base) + s[i--] = lookup[(n % base)]; if (i!=imax) s[i--] = 'x'; s[i--] = '0'; - } else { - for (; n && i>0; n/=10) - s[i--] = (n % 10) + '0'; } return s+i+1; }