Beispiel #1
0
SDB_VISIBLE char *sdb_querys (Sdb *s, char *buf, size_t len, const char *cmd) {
	const char *q;
	char *p, *eq, *ask;
	int i, ok, w, alength;
	ut64 n;
	if (!s) return NULL;
	if (cmd == NULL) {
		cmd = buf;
		buf = NULL;
	}
	if (!len || !buf) buf = malloc ((len=32));

	ask = strchr (cmd, '?');
	if (*cmd == '+' || *cmd == '-') {
		*buf = 0;
		if (ask) {
			*ask = 0;
			if (*cmd=='+') n = sdb_json_inc (s, cmd+1, ask+1, 1, 0);
			else n = sdb_json_dec (s, cmd+1, ask+1, 1, 0);
			*ask = '?';
		} else {
			if (*cmd=='+') n = sdb_inc (s, cmd+1, 1, 0);
			else n = sdb_dec (s, cmd+1, 1, 0);
		}
		w = snprintf (buf, len-1, "%"ULLFMT"d", n);
		if (w<0 || (size_t)w>len) {
			buf = malloc (0xff);
			snprintf (buf, 0xff, "%"ULLFMT"d", n);
		}
		return buf;
	} else if (*cmd == '(') {
		p = strchr (cmd, ')');
		if (!p) {
			fprintf (stderr, "Missing ')'.\n");
			return NULL;
		}
		*p = 0;
		eq = strchr (p+1, '=');
		if (cmd[1]=='?') {
			// if (!eq) { ...
			alength = sdb_alength (s, p+1);
			w = snprintf (buf, len, "%d", alength);
			if (w<0 || (size_t)w>len) {
				buf = malloc (32);
				snprintf (buf, 32, "%d", alength);
			}
			return buf;
		}
		if (cmd[1]) {
			/* (+)foo=bla (-)foo=bla */
			if ((cmd[1]=='+'||cmd[1]=='-') && !cmd[2]) {
				if (eq) {
					*eq = 0;
					if (cmd[1]=='+') {
						if (sdb_agetv (s, p+1, eq+1, 0)== -1)
							sdb_aset (s, p+1, -1, eq+1, 0);
					} else {
						sdb_adels (s, p+1, eq+1, 0);
					}
					return NULL;
				} else {
					if (cmd[1]=='+') {
						// (+)foo :: remove first element
						sdb_adel (s, p+1, 0, 0);
					} else {
						// (-)foo :: remove last element
						sdb_adel (s, p+1, -1, 0);
					}
					return NULL;
				}
			} else {
				i = atoi (cmd+1);
				if (eq) {
					*eq = 0;
					ok = eq[1]? (
							(cmd[1]=='+')?
							sdb_ains (s, p+1, i, eq+1, 0):
							sdb_aset (s, p+1, i, eq+1, 0)
						    ): sdb_adel (s, p+1, i, 0);
					if (ok) *buf = 0; else buf = NULL;
					return buf;
				}
				return sdb_aget (s, p+1, i, NULL);
			}
		} else {
			if (eq) {
				char *q, *out = strdup (eq+1);
				*eq = 0;
				// TODO: define new printable separator character
				for (q=out; *q; q++) if (*q==',') *q = SDB_RS;
				ok = sdb_set (s, p+1, out, 0);
				free (out);
				if (ok) {
					*buf = 0;
					return buf;
				}
			} else {
				const char *out = sdb_getc (s, p+1, 0);
				size_t wl;
				if (!out) return NULL;
				wl = strlen (out);
				if (wl>len) buf = malloc (wl+2);
				for (i=0; out[i]; i++) {
					if (out[i+1])
					buf[i] = out[i]==SDB_RS? '\n': out[i];
					else buf[i] = out[i];
				}
				buf[i] = 0;
				return buf;
			}
		}
	} else {
		eq = strchr (cmd, '=');
		if (eq) {
			// 1 0 kvpath=value
			// 1 1 kvpath?jspath=value
			if (ask>eq) ask = NULL;
			*eq++ = 0;
			if (ask) {
				*ask++ = 0;
				ok = sdb_json_set (s, cmd, ask, eq, 0);
			} else ok = sdb_set (s, cmd, eq, 0);
			if (!ok) return NULL;
			*buf = 0;
			return buf;
		} else {
			// 0 1 kvpath?jspath
			// 0 0 kvpath
			if (ask) {
				*ask++ = 0;
				// TODO: not optimized to reuse 'buf'
				if ((p = sdb_json_get (s, cmd, ask, 0)))
					return p;
			} else {
				// sdbget
				if (!(q = sdb_getc (s, cmd, 0)))
					return NULL;
				if (strlen (q)> len) return strdup (q);
				strcpy (buf, q);
				return buf;
			}
		}
	}
	return NULL;
}
Beispiel #2
0
// XXX: cmd is reused
SDB_API char *sdb_querys (Sdb *s, char *buf, size_t len, const char *cmd) {
	int i, d, ok, w, alength, bufset = 0;
	const char *p, *q, *val = NULL;
	char *eq, *ask;
	ut64 n;
	if (!s) return NULL;
	if (cmd == NULL) {
		cmd = buf;
		buf = NULL;
	}
	if (!len || !buf) {
		bufset = 1;
		buf = malloc ((len=64));
	}
	ask = strchr (cmd, '?');
	if (*cmd == '[') {
		char *tp = strchr (cmd, ']');
		if (!tp) {
			fprintf (stderr, "Missing ']'.\n");
			if (bufset)
				free (buf);
			return NULL;
		}
		*tp++ = 0;
		p = (const char *)tp;
	} else p = cmd;
	eq = strchr (p, '=');
	if (eq) {
		*eq++ = 0;
		if (*eq=='$')
			val = sdb_getc (s, eq+1, 0);
	}
	if (!val) val = eq;
	if (*cmd=='$')
		cmd = sdb_getc (s, cmd+1, 0);
	// cmd = val
	// cmd is key and val is value

	if (*cmd == '.') {
		sdb_query_file (s, cmd+1);
		if (bufset)
			free (buf);
		return NULL;
	} else
	if (*cmd == '+' || *cmd == '-') {
		d = 1;
		*buf = 0;
		if (val) {
			d = sdb_atoi (val);
			if (d) {
				if (*cmd=='+')
					sdb_inc (s, cmd+1, d, 0);
				else
					sdb_dec (s, cmd+1, d, 0);
			} else {
				sdb_concat (s, cmd+1, val, 0);
			}
		} else {
			if (ask) {
				*ask = 0;
				if (*cmd=='+') n = sdb_json_inc (s, cmd+1, ask+1, d, 0);
				else n = sdb_json_dec (s, cmd+1, ask+1, d, 0);
				*ask = '?';
			} else {
				if (*cmd=='+') n = sdb_inc (s, cmd+1, d, 0);
				else n = sdb_dec (s, cmd+1, d, 0);
			}
			w = snprintf (buf, len-1, "%"ULLFMT"d", n);
			if (w<0 || (size_t)w>len) {
				buf = malloc (0xff);
				snprintf (buf, 0xff, "%"ULLFMT"d", n);
			}
		}
		return buf;
	} else if (*cmd == '[') {
		// [?] - count elements of array
		if (cmd[1]=='?') {
			// if (!eq) { ...
			alength = sdb_alength (s, p);
			w = snprintf (buf, len, "%d", alength);
			if (w<0 || (size_t)w>len) {
				buf = malloc (32);
				snprintf (buf, 31, "%d", alength);
			}
			return buf;
		}
		if (cmd[1]=='+'||cmd[1]=='-') {
			// [+]foo        remove first element */
			// [+]foo=bar    PUSH */
			// [-]foo        POP */
			// [-]foo=xx     POP  (=xx ignored) */
			if (!cmd[2] || cmd[2] ==']') {
				// insert
				if (eq) {
					if (cmd[1]=='+') {
						if (sdb_agetv (s, p, val, 0)== -1)
							sdb_aset (s, p, -1, val, 0);
					} else {
						sdb_adels (s, p, val, 0);
					}
					return NULL;
				} else {
					char *ret;
					if (cmd[1]=='+') {
// XXX: this is a little strange syntax to remove an item
						ret = sdb_aget (s, p, 0, 0);
						// (+)foo :: remove first element
						sdb_adel (s, p, 0, 0);
					} else { // POP
						ret = sdb_aget (s, p, -1, 0);
						// (-)foo :: remove last element
						sdb_adel (s, p, -1, 0);
					}
					return ret;
				}
			} else {
				// get/set specific element in array
				/* (+3)foo=bla */
				i = atoi (cmd+1);
				if (eq) {
					ok = cmd[1]? (
							(cmd[1]=='+')?
							sdb_ains (s, p, i, val, 0):
							sdb_aset (s, p, i, val, 0)
						    ): sdb_adel (s, p, i, 0);
					if (ok) *buf = 0; else buf = NULL;
					return buf;
				}
				return sdb_aget (s, p, i, NULL);
			}
		} else {
			if (eq) {
				/* (3)foo=bla */
				char *q, *out = strdup (val);
				// TODO: define new printable separator character
				for (q=out; *q; q++) if (*q==',') *q = SDB_RS;
				if (cmd[1]) {
					int idx = atoi (cmd+1);
					ok = sdb_aset (s, p, idx, val, 0);
// TODO: handle when idx > sdb_alen
				} else {
					ok = sdb_set (s, p, out, 0);
				}
				free (out);
				if (ok) {
					*buf = 0;
					return buf;
				}
				return NULL;
			} else {
				/* (3)foo */
				const char *out = sdb_getc (s, p, 0);
				size_t wl;
				if (cmd[1]) {
					i = atoi (cmd+1);
					return sdb_aget (s, p, i, NULL);
				}
				if (!out) return NULL;
				wl = strlen (out);
				if (wl>len) buf = malloc (wl+2);
				for (i=0; out[i]; i++) {
					if (out[i+1])
					buf[i] = out[i]==SDB_RS? '\n': out[i];
					else buf[i] = out[i];
				}
				buf[i] = 0;
				return buf;
			}
		}
	} else {
		if (eq) {
			// 1 0 kvpath=value
			// 1 1 kvpath?jspath=value
			if (ask>eq) ask = NULL;
			if (ask) {
				*ask++ = 0;
				ok = sdb_json_set (s, cmd, ask, val, 0);
			} else ok = sdb_set (s, cmd, val, 0);
			if (!ok) {
				if (bufset)
					free (buf);
				return NULL;
			}
			*buf = 0;
			return buf;
		} else {
			// 0 1 kvpath?jspath
			// 0 0 kvpath
			if (ask) {
				*ask++ = 0;
				// TODO: not optimized to reuse 'buf'
				if ((p = sdb_json_get (s, cmd, ask, 0)))
					return strdup (p);
			} else {
				// sdbget
				if (!(q = sdb_getc (s, cmd, 0)))
					return NULL;
				if (strlen (q)> len) return strdup (q);
				strcpy (buf, q);
				return buf;
			}
		}
	}
	if (bufset)
		free (buf);
	return NULL;
}