String head and tail operators
authorMyhailo Danylenko <isbear@ukrpost.net>
Fri, 15 Jan 2010 15:44:00 +0200
changeset 4 faaed3ae3fa8
parent 3 7b0b509e02e4
child 5 d745f94ecc08
String head and tail operators * : string head * ^ string tail * fix for negative integer detection
TODO
help/en/hlp_eval.txt
yaubil.c
--- a/TODO	Fri Jan 15 12:57:16 2010 +0200
+++ b/TODO	Fri Jan 15 15:44:00 2010 +0200
@@ -1,3 +1,3 @@
 
-String splitting (need to decide, which operator characters to use)
+Pattern matching/cutting over strings
 
--- a/help/en/hlp_eval.txt	Fri Jan 15 12:57:16 2010 +0200
+++ b/help/en/hlp_eval.txt	Fri Jan 15 15:44:00 2010 +0200
@@ -6,6 +6,8 @@
 * all operators have the same precedence;
 * supported operators:
   . string concatenation
+  : string head
+  ^ string tail
   + binary plus / string concatenation
   - binary minus
   * multiplication / string replication
@@ -25,3 +27,4 @@
 Example:
  /eval "echo 2 + 2 = " . (2+2)
  /eval "set ping_interval = " . (ping_interval + 1)    ) this example probably should use /let command.
+ /eval "echo " . (ssl_fingerprint : 5) . "..." . (ssl_fingerprint ^ 5)    ) negative offsets are also supported
--- a/yaubil.c	Fri Jan 15 12:57:16 2010 +0200
+++ b/yaubil.c	Fri Jan 15 15:44:00 2010 +0200
@@ -55,7 +55,7 @@
 {
 	if (value) {
 		const char *e;
-		gboolean    integer = (*value == '-') ? FALSE : (g_ascii_isdigit (*value) ? TRUE : FALSE);
+		gboolean    integer = (*value == '-') ? TRUE : (g_ascii_isdigit (*value) ? TRUE : FALSE);
 
 		if (integer) {
 			for (e = value + 1; *e; ++e) {
@@ -78,7 +78,7 @@
 
 static gboolean op_concat (value_t *l, value_t *r)
 {
-	GString *res = g_string_new (NULL);;
+	GString *res = g_string_new (NULL);
 
 	if (l->type == TYPE_INT)
 		g_string_append_printf (res, "%d", l->int_value);
@@ -97,6 +97,84 @@
 	return TRUE;
 }
 
+static gboolean op_head (value_t *l, value_t *r)
+{
+	if (l->type == TYPE_UNDEF) {
+		l->type      = TYPE_INT;
+		l->int_value = 0;
+	}
+	if (r->type == TYPE_UNDEF) {
+		r->type      = TYPE_INT;
+		r->int_value = 0;
+	}
+
+	if (l -> type == TYPE_INT) {
+		l -> type = TYPE_STR;
+		if (!l -> str_value)
+			l -> str_value = g_strdup_printf ("%d", l -> int_value);
+	}
+	if (r->type == TYPE_STR && check_value_type (r->str_value) == TYPE_INT) {
+		r->type      = TYPE_INT;
+		r->int_value = atoi (r->str_value);
+		g_free (r->str_value);
+		r->str_value = NULL;
+	}
+
+	if (l->type == TYPE_STR && r->type == TYPE_INT) {
+		gchar *res = NULL;
+		int    len = l -> str_value ? strlen (l -> str_value) : 0; // XXX can str_value be NULL?
+		int    off = r -> int_value;
+		if (off < 0 && len + off > 0)
+			res = g_strndup (l -> str_value, len + off);
+		else if (off > 0 && len > off)
+			res = g_strndup (l -> str_value, off);
+		else
+			res = g_strdup (""); // XXX leave NULL here?
+		g_free (l->str_value);
+		l->str_value = res;
+	} else
+		return FALSE;
+}
+
+static gboolean op_tail (value_t *l, value_t *r)
+{
+	if (l->type == TYPE_UNDEF) {
+		l->type      = TYPE_INT;
+		l->int_value = 0;
+	}
+	if (r->type == TYPE_UNDEF) {
+		r->type      = TYPE_INT;
+		r->int_value = 0;
+	}
+
+	if (l -> type == TYPE_INT) {
+		l -> type = TYPE_STR;
+		if (!l -> str_value)
+			l -> str_value = g_strdup_printf ("%d", l -> int_value);
+	}
+	if (r->type == TYPE_STR && check_value_type (r->str_value) == TYPE_INT) {
+		r->type      = TYPE_INT;
+		r->int_value = atoi (r->str_value);
+		g_free (r->str_value);
+		r->str_value = NULL;
+	}
+
+	if (l->type == TYPE_STR && r->type == TYPE_INT) {
+		gchar *res = NULL;
+		int    len = l -> str_value ? strlen (l -> str_value) : 0; // XXX can str_value be NULL?
+		int    off = r -> int_value;
+		if (off < 0 && len + off > 0)
+			res = g_strdup (l -> str_value + (-off));
+		else if (off > 0 && len > off)
+			res = g_strdup (l -> str_value + (len - off));
+		else
+			res = g_strdup (""); // XXX leave NULL here?
+		g_free (l->str_value);
+		l->str_value = res;
+	} else
+		return FALSE;
+}
+
 static gboolean op_plus (value_t *l, value_t *r)
 {
 	if (l->type == TYPE_UNDEF) {
@@ -454,6 +532,8 @@
 
 static op_t operators[] = {
 	{ '.', op_concat   },
+	{ ':', op_head     },
+	{ '^', op_tail     },
 	{ '+', op_plus     },
 	{ '-', op_minus    },
 	{ '*', op_multiply },