Exemple #1
0
SDB_API void sdb_array_sort(Sdb *s, const char *key, ut32 cas) {
	char *nstr, *str, **strs;
	int lstr, j, i;
	str = sdb_get_len (s, key, &lstr, 0);
	if (!str) {
		return;
	}
	if (!*str) {
		free (str);
		return;
	}
	strs = sdb_fmt_array (str);
	for (i = 0; strs[i]; i++) {
		//nothing to see here
	}
	qsort (strs, i, sizeof (char*), cstring_cmp);
	nstr = str;
	for (i = 0; strs[i]; i++) {
		j = strlen (strs[i]);
		memcpy (nstr, strs[i], j);
		nstr += j;
		*(nstr++) = SDB_RS;
	}
	if (nstr > str) {
		*(--nstr) = '\0';
	} else {
		*nstr = '\0';
	}
	sdb_set_owned (s, key, str, cas);
	free (strs);
}
Exemple #2
0
SDB_API int sdb_array_delete(Sdb *s, const char *key, int idx, ut32 cas) {
	int i;
	char *p, *n, *str = sdb_get (s, key, 0);
	p = str;
	if (!str || !*str) {
		free (str);
		return 0;
	}
	if (idx < 0) {
		idx = sdb_alen (str);
		if (idx) idx--;
	}
	for (i = 0; i < idx; i++) {
		if ( (n = strchr (p, SDB_RS)) ) {
			p = n + 1;
		} else {
			free (str);
			return 0;
		}
	}
	n = strchr (p, SDB_RS);
	if (n) {
		memmove (p, n + 1, strlen (n));
	} else {
		if (p != str)
			p--; // remove tailing SDB_RS
		*p = 0;
		p[1] = 0;
	}
	sdb_set_owned (s, key, str, cas);
	return 1;
}
Exemple #3
0
SDB_API int sdb_array_prepend (Sdb *s, const char *key, const char *val,
			       ut32 cas) {
	int str_len = 0;
	ut32 kas = cas;
	const char *str = sdb_const_get_len (s, key, &str_len, &kas);
	if (!val || (cas && cas != kas)) {
		return 0;
	}
	cas = kas;
	if (str && *str) {
		int val_len = strlen (val);
		char *newval = malloc (str_len + val_len + 2);
		if (!newval) {
			return 0;
		}
		memcpy (newval, val, val_len);
		newval[val_len] = SDB_RS;
		memcpy (newval + val_len + 1, str, str_len);
		newval[str_len + val_len + 1] = 0;
		// TODO: optimize this because we already have allocated and strlened everything
		sdb_set_owned (s, key, newval, cas);
	} else {
		sdb_set (s, key, val, cas);
	}
	return 1;
}
Exemple #4
0
SDB_API bool sdb_array_append(Sdb *s, const char *key, const char *val,
			       ut32 cas) {
#if SLOW
	return sdb_array_set (s, key, -1, val, cas);
#else
	int str_len = 0;
	ut32 kas = cas;
	const char *str = sdb_const_get_len (s, key, &str_len, &kas);
	if (!val || (cas && cas != kas)) {
		return false;
	}
	cas = kas;
	if (str && *str && str_len > 0) {
		int val_len = strlen (val);
		char *newval = malloc (str_len + val_len + 2);
		if (!newval) {
			return false;
		}
		memcpy (newval, str, str_len);
		newval[str_len] = SDB_RS;
		memcpy (newval+str_len+1, val, val_len);
		newval[str_len+val_len+1] = 0;
		sdb_set_owned (s, key, newval, cas);
	} else {
		sdb_set (s, key, val, cas);
	}
	return true;
#endif
}
Exemple #5
0
SDB_API char *sdb_array_pop(Sdb *s, const char *key, ut32 *cas) {
	ut32 kas;
	char *end, *str = sdb_get (s, key, &kas);
	if (!str || !*str) {
		free (str);
		return NULL;
	}
	if (cas && *cas != kas)
		*cas = kas;
#if PUSH_PREPENDS
	end = strchr (str, SDB_RS);
	if (end) {
		*end = 0;
		sdb_set (s, key, end+1, 0);
	} else {
		sdb_unset (s, key, 0);
	}
	return str;
#else
	for (end = str+strlen (str)-1;
		end>str && *end!=SDB_RS; end--);
	if (*end==SDB_RS) *end++ = 0;
	sdb_set_owned (s, key, str, 0);
	// XXX: probably wrong
	return strdup (end);
#endif
}
Exemple #6
0
SDB_API int sdb_array_add_sorted(Sdb *s, const char *key, const char *val, ut32 cas) {
	int lstr, lval, i, j;
	const char *str_e, *str_lp, *str_p, *str = sdb_const_get_len (s, key, &lstr, 0);
	char *nstr, *nstr_p, **vals;
	const char null = '\0';
	if (!str || !*str) {
		str = &null;
		lstr = 0;
	}
	str_e = str + lstr;
	str_lp = str_p = str;
	if (!val || !*val) {
		return 1;
	}
	lval = strlen (val);
	vals = sdb_fmt_array (val);
	for (i = 0; vals[i]; i++) {
		/* empty */
	}
	if (i > 1) {
		qsort (vals, i, sizeof (ut64*), cstring_cmp);
	}
	nstr_p = nstr = malloc (lstr + lval + 3);
	if (!nstr) {
		return 1;
	}
	for (i = 0; vals[i]; i++) {
		while (str_p < str_e) {
			if (astrcmp (vals[i], str_p) < 0) {
				break;
			}
			sdb_const_anext (str_p, &str_p);
			if (!str_p) {
				str_p = str_e;
			}
		}
		memcpy (nstr_p, str_lp, str_p - str_lp);
		nstr_p += str_p - str_lp;
		if (str_p == str_e && str_lp != str_e) {
			*(nstr_p++) = SDB_RS;
		}
		str_lp = str_p;
		j = strlen (vals[i]);
		memcpy (nstr_p, vals[i], j);
		nstr_p += j;
		*(nstr_p++) = SDB_RS;
	}
	if (str_lp < str_e) {
		memcpy (nstr_p, str_lp, str_e - str_lp);
		nstr_p += str_e - str_lp;
		*(nstr_p) = '\0';
	} else {
		*(--nstr_p) = '\0';
	}
	sdb_set_owned (s, key, nstr, cas);
	free (vals);
	return 0;
}
Exemple #7
0
SDB_API int sdb_array_set(Sdb *s, const char *key, int idx, const char *val,
			   ut32 cas) {
	int lstr, lval, len;
	const char *usr, *str = sdb_const_get_len (s, key, &lstr, 0);
	char *ptr;

	if (!str || !*str) {
		return sdb_set (s, key, val, cas);
	}
	// XXX: should we cache sdb_alen value inside kv?
	len = sdb_alen (str);
	lstr--;
	if (idx < 0 || idx == len) { // append
		return sdb_array_insert (s, key, -1, val, cas);
	}
	lval = strlen (val);
	if (idx > len) {
		int ret, i, ilen = idx-len;
		char *newkey = malloc (ilen + lval + 1);
		if (!newkey) {
			return 0;
		}
		for (i = 0; i < ilen; i++) {
			newkey [i] = SDB_RS;
		}
		memcpy (newkey + i, val, lval + 1);
		ret = sdb_array_insert (s, key, -1, newkey, cas);
		free (newkey);
		return ret;
	}
	//lstr = strlen (str);
	ptr = (char*)Aindexof (str, idx);
	if (ptr) {
		int diff = ptr - str;
		char *nstr = malloc (lstr + lval + 2);
		if (!nstr) {
			return false;
		}
		ptr = nstr + diff;
		//memcpy (nstr, str, lstr+1);
		memcpy (nstr, str, diff);
		memcpy (ptr, val, lval + 1);
		usr = Aindexof (str, idx + 1);
		if (usr) {
			ptr[lval] = SDB_RS;
			strcpy (ptr + lval + 1, usr);
		}
		return sdb_set_owned (s, key, nstr, 0);
	}
	return 0;
}
Exemple #8
0
// TODO: done, but there's room for improvement
SDB_API int sdb_array_insert(Sdb *s, const char *key, int idx, const char *val, ut32 cas) {
	int lnstr, lstr, lval;
	char *x, *ptr;
	const char *str = sdb_const_get_len (s, key, &lstr, 0);
	if (!str || !*str) {
		return sdb_set (s, key, val, cas);
	}
	lval = strlen (val);
	lstr--;
	//lstr = strlen (str); // we can optimize this by caching value len in memory . add sdb_const_get_size()
	x = malloc (lval + lstr + 2);
	if (idx == -1) {
		memcpy (x, str, lstr);
		x[lstr] = SDB_RS;
		memcpy (x+lstr+1, val, lval + 1);
	} else if (idx == 0) {
		memcpy (x, val, lval);
		x[lval] = SDB_RS;
		memcpy (x + lval + 1, str, lstr + 1);
	} else {
		char *nstr = malloc (lstr + 1);
		if (!nstr) {
			free (x);
			return false;
		}
		memcpy (nstr, str, lstr + 1);
		ptr = (char *)Aindexof (nstr, idx);
		if (ptr) {
			int lptr = (nstr+lstr+1)-ptr;
			*(ptr-1) = 0;
			lnstr = ptr-nstr-1;
			memcpy (x, nstr, lnstr);
			x[lnstr] = SDB_RS;
			memcpy (x + lnstr + 1, val, lval);
			x[lnstr + lval + 1] = SDB_RS;
			// TODO: this strlen hurts performance
			memcpy (x + lval + 2 + lnstr, ptr, lptr); //strlen (ptr)+1);
			free (nstr);
		} else {
			// this is not efficient
			free (nstr);
			free (x);
			// fallback for empty buckets
			return sdb_array_set (s, key, idx, val, cas);
		}
	}
	return sdb_set_owned (s, key, x, cas);
}
Exemple #9
0
SDB_API char *sdb_array_pop_tail(Sdb *s, const char *key, ut32 *cas) {
	ut32 kas;
	char *end, *str = sdb_get (s, key, &kas);
	if (!str || !*str) {
		free (str);
		return NULL;
	}
	if (cas && *cas != kas)
		*cas = kas;
	for (end = str + strlen (str) - 1;
		end > str && *end != SDB_RS; end--);
	if (*end == SDB_RS) *end++ = 0;
	sdb_set_owned (s, key, str, 0);
	// XXX: probably wrong
	return strdup (end);
}
Exemple #10
0
SDB_API void sdb_array_sort_num(Sdb *s, const char *key, ut32 cas) {
	char *ret, *nstr, *str;
	int lstr;
	ut64 *nums;
	str = sdb_get_len (s, key, &lstr, 0);
	if (!str) return;
	if (!*str) {
		free (str);
		return;
	}
	nums = sdb_fmt_array_num (str);
	qsort (nums + 1, (int)*nums, sizeof (ut64), int_cmp);
	nstr = str;
	memset (nstr, 'q', *nums);
	nstr += *nums;
	*nstr = '\0';
	ret = sdb_fmt_tostr (nums + 1, str);
	sdb_set_owned (s, key, ret, cas);
	free (str);
	free (nums);
	return;
}
Exemple #11
0
// TODO: done, but there's room for improvement
SDB_API int sdb_array_insert(Sdb *s, const char *key, int idx, const char *val,
			      ut32 cas) {
	int lnstr, lstr;
	size_t lval;
	char *x, *ptr;
	const char *str = sdb_const_get_len (s, key, &lstr, 0);
	if (!str || !*str) {
		return sdb_set (s, key, val, cas);
	}
	lval = strlen (val);
	lstr--;
	// XXX: lstr is wrongly computed in sdb_const_get_with an off-by-one
	// we can optimize this by caching value len in memory . add
	// sdb_const_get_size()
	lstr = strlen (str); 

	// When removing strlen this conversion should be checked
	size_t lstr_tmp = lstr;
	if (SZT_ADD_OVFCHK (lval, lstr_tmp) || SZT_ADD_OVFCHK (lval + lstr_tmp, 2)) {
		return false;
	}
	x = malloc (lval + lstr_tmp + 2);
	if (!x) {
		return false;
	}

	if (idx == -1) {
		memcpy (x, str, lstr);
		x[lstr] = SDB_RS;
		memcpy (x + lstr + 1, val, lval + 1);
	} else if (!idx) {
		memcpy (x, val, lval);
		x[lval] = SDB_RS;
		memcpy (x + lval + 1, str, lstr + 1);
	} else {
		char *nstr = malloc (lstr + 1);
		if (!nstr) {
			free (x);
			return false;
		}
		memcpy (nstr, str, lstr + 1);
		ptr = (char *)Aindexof (nstr, idx);
		if (ptr) {
			int lptr = (nstr + lstr + 1) - ptr;
			char *p_1 = ptr > nstr? ptr - 1: ptr;
			*p_1 = 0;
			lnstr = ptr - nstr - 1;
			memcpy (x, nstr, lnstr);
			x[lnstr] = SDB_RS;
			memcpy (x + lnstr + 1, val, lval);
			x[lnstr + lval + 1] = SDB_RS;
			// TODO: this strlen hurts performance
			memcpy (x + lval + 2 + lnstr, ptr, lptr); //strlen (ptr)+1);
			free (nstr);
		} else {
			// this is not efficient
			free (nstr);
			free (x);
			// fallback for empty buckets
			return sdb_array_set (s, key, idx, val, cas);
		}
	}
	return sdb_set_owned (s, key, x, cas);
}
Exemple #12
0
SDB_API int sdb_json_set (Sdb *s, const char *k, const char *p, const char *v, ut32 cas) {
    const char *beg[3];
    const char *end[3];
    int jslen, l, idx, len[3];
    char *b, *str = NULL;
    const char *js;
    Rangstr rs;
    ut32 c;

    if (!s || !k)
        return 0;
    js = sdb_const_get_len (s, k, &jslen, &c);
    if (!js) {
        b = malloc (strlen (p)+strlen (v)+8);
        if (b) {
            int is_str = isstring (v);
            const char *q = is_str?"\"":"";
            sprintf (b, "{\"%s\":%s%s%s}", p, q, v, q);
#if 0
            /* disabled because it memleaks */
            sdb_set_owned (s, k, b, cas);
#else
            sdb_set (s, k, b, cas);
            free (b);
#endif
            return 1;
        }
        return 0;
    }
    if (cas && c != cas) {
        return 0;
    }
    rs = json_get (js, p);
    if (!rs.p) {
        char *b = malloc (jslen+strlen(k)+strlen (v)+32);
        if (b) {
            int curlen, is_str = isstring (v);
            const char *q = is_str?"\"":"";
            const char *e = ""; // XX: or comma
            if (js[0] && js[1] != '}')
                e = ",";
            curlen = sprintf (b, "{\"%s\":%s%s%s%s",
                              p, q, v, q, e);
            strcpy (b+curlen, js+1);
            // transfer ownership
            sdb_set_owned (s, k, b, cas);
            return 1;
        }
        // invalid json?
        return 0;
    }
#define WLEN(x) (int)(size_t)(end[x]-beg[x])

    beg[0] = js;
    end[0] = rs.p + rs.f;
    len[0] = WLEN (0);

    if (*v) {
        beg[1] = v;
        end[1] = v + strlen (v);
        len[1] = WLEN (1);
    }

    beg[2] = rs.p + rs.t;
    end[2] = js + jslen;
    len[2] = WLEN (2);

    // TODO: accelerate with small buffer in stack for small jsons
    if (*v) {
        int is_str = isstring (v);
        int msz = len[0]+len[1]+len[2]+strlen (v);
        if (msz<1)
            return 0;
        str = malloc (msz);
        if (!str)
            return 0;
        idx = len[0];
        memcpy (str, beg[0], idx);
        if (is_str) {
            if (beg[2][0]!='"') {
                str[idx]='"';
                idx++;
            }
        } else {
            if (beg[2][0]=='"') {
                idx--;
            }
        }
        l = len[1];
        memcpy (str+idx, beg[1], l);
        idx += len[1];
        if (is_str) {
            // TODO: add quotes
            if (beg[2][0]!='"') {
                str[idx]='"';
                idx++;
            }
        } else {
            if (beg[2][0]=='"') {
                beg[2]++;
            }
        }
        l = len[2];
        memcpy (str+idx, beg[2], l);
        str[idx+l] = 0;
    } else {
        int kidx;
        // DELETE KEY
        rs.f -= 2;
        kidx = findkey (&rs);
        len[0] = R_MAX (1, kidx-1);
        if (kidx==1) {
            if (beg[2][0]=='"')
                beg[2]++;
            beg[2]++;
        }
        str = malloc (len[0]+len[2]+1);
        if (!str)
            return 0;
        memcpy (str, beg[0], len[0]);
        if (!*beg[2])
            beg[2]--;
        memcpy (str+len[0], beg[2], len[2]);
        str[len[0]+len[2]] = 0;
    }
    sdb_set_owned (s, k, str, cas);
    return 1;
}