String head and tail operators
* : string head
* ^ string tail
* fix for negative integer detection
--- 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 },