[sr-dev] git:master: pv: new transformation class 'line'

Daniel-Constantin Mierla miconda at gmail.com
Fri Dec 16 13:18:44 CET 2011


Module: sip-router
Branch: master
Commit: 0f598b1a5798ecd403ef588f7d4c6b38177883ce
URL:    http://git.sip-router.org/cgi-bin/gitweb.cgi/sip-router/?a=commit;h=0f598b1a5798ecd403ef588f7d4c6b38177883ce

Author: Daniel-Constantin Mierla <miconda at gmail.com>
Committer: Daniel-Constantin Mierla <miconda at gmail.com>
Date:   Fri Dec 16 13:10:57 2011 +0100

pv: new transformation class 'line'

- {line.count} - return number of lines in PV
- {line.at,pos} - return the line at position pos
- {line.sw,exp} - return the line starting with 'exp'

---

 modules_k/pv/pv.c       |    2 +
 modules_k/pv/pv_trans.c |  291 +++++++++++++++++++++++++++++++++++++++++++++++
 modules_k/pv/pv_trans.h |    6 +-
 3 files changed, 298 insertions(+), 1 deletions(-)

diff --git a/modules_k/pv/pv.c b/modules_k/pv/pv.c
index f5784d9..bc47e1a 100644
--- a/modules_k/pv/pv.c
+++ b/modules_k/pv/pv.c
@@ -53,6 +53,8 @@ static tr_export_t mod_trans[] = {
 		tr_parse_paramlist },
 	{ {"tobody", sizeof("tobody")-1}, /* param class */
 		tr_parse_tobody },
+	{ {"line", sizeof("line")-1}, /* line class */
+		tr_parse_line },
 
 	{ { 0, 0 }, 0 }
 };
diff --git a/modules_k/pv/pv_trans.c b/modules_k/pv/pv_trans.c
index f1dcce3..22d3a9e 100644
--- a/modules_k/pv/pv_trans.c
+++ b/modules_k/pv/pv_trans.c
@@ -1342,6 +1342,202 @@ int tr_eval_tobody(struct sip_msg *msg, tr_param_t *tp, int subtype,
 	return 0;
 }
 
+void *memfindrchr(const void *buf, int c, size_t n)
+{
+	int i;
+	unsigned char *p;
+
+	p = (unsigned char*)buf;
+
+	for (i=n-1; i>=0; i--) {
+		if (p[i] == (unsigned char)c) {
+			return (void*)(p+i);
+		}
+	}
+	return NULL;
+}
+
+/*!
+ * \brief Evaluate line transformations
+ * \param msg SIP message
+ * \param tp transformation
+ * \param subtype transformation type
+ * \param val pseudo-variable
+ * \return 0 on success, -1 on error
+ */
+int tr_eval_line(struct sip_msg *msg, tr_param_t *tp, int subtype,
+		pv_value_t *val)
+{
+	pv_value_t v;
+	str sv;
+	str mv;
+	char *p;
+	int n, i;
+
+	if(val==NULL || (!(val->flags&PV_VAL_STR)) || val->rs.len<=0)
+		return -1;
+
+	switch(subtype)
+	{
+		case TR_LINE_SW:
+			if(tp==NULL)
+			{
+				LM_ERR("value invalid parameters\n");
+				return -1;
+			}
+
+			if(tp->type==TR_PARAM_STRING)
+			{
+				sv = tp->v.s;
+			} else {
+				if(pv_get_spec_value(msg, (pv_spec_p)tp->v.data, &v)!=0
+						|| (!(v.flags&PV_VAL_STR)) || v.rs.len<=0)
+				{
+					LM_ERR("value cannot get p1\n");
+					return -1;
+				}
+				sv = v.rs;
+			}
+
+			if(val->rs.len < sv.len)
+			{
+				val->rs = _tr_empty;
+				goto done;
+			}
+			p = val->rs.s;
+			do {
+				if(strncmp(p, sv.s, sv.len)==0)
+				{
+					/* match */
+					mv.s = p;
+					p += sv.len;
+					p = memchr(p, '\n', (val->rs.s + val->rs.len) - p);
+					if(p==NULL)
+					{
+						/* last line */
+						mv.len = (val->rs.s + val->rs.len) - p;
+					} else {
+						mv.len = p - mv.s;
+					}
+					val->rs = mv;
+					goto done;
+				}
+				p = memchr(p, '\n', (val->rs.s + val->rs.len) - p);
+			} while(p && ((++p)<=val->rs.s+val->rs.len-sv.len));
+			val->rs = _tr_empty;
+			break;
+
+		case TR_LINE_AT:
+			if(tp==NULL)
+			{
+				LM_ERR("name invalid parameters\n");
+				return -1;
+			}
+
+			if(tp->type==TR_PARAM_NUMBER)
+			{
+				n = tp->v.n;
+			} else {
+				if(pv_get_spec_value(msg, (pv_spec_p)tp->v.data, &v)!=0
+						|| (!(v.flags&PV_VAL_INT)))
+				{
+					LM_ERR("name cannot get p1\n");
+					return -1;
+				}
+				n = v.ri;
+			}
+			if(n<0)
+			{
+				p = val->rs.s + val->rs.len - 1;
+				if(*p=='\n')
+					p--;
+				mv.s = p;
+				n = -n;
+				i=1;
+				p = memfindrchr(val->rs.s, '\n', p - val->rs.s);
+				if(p!=NULL)
+					p--;
+				while(i<n && p)
+				{
+					mv.s = p;
+					p = memfindrchr(val->rs.s, '\n', p - val->rs.s);
+					if(p!=NULL)
+						p--;
+					i++;
+				}
+				if(i==n)
+				{
+					if(p==NULL)
+					{
+						/* first line */
+						mv.len = mv.s - val->rs.s + 1;
+						mv.s = val->rs.s;
+					} else {
+						mv.len = mv.s - p - 1;
+						mv.s = p + 2;
+					}
+					val->rs = mv;
+					goto done;
+				}
+			} else {
+				p = val->rs.s;
+				i = 0;
+				while(i<n && p)
+				{
+					p = memchr(p, '\n', (val->rs.s + val->rs.len) - p);
+					if(p!=NULL)
+						p++;
+					i++;
+				}
+				if(i==n && p!=NULL)
+				{
+					/* line found */
+					mv.s = p;
+					p = memchr(p, '\n', (val->rs.s + val->rs.len) - p);
+					if(p==NULL)
+					{
+						/* last line */
+						mv.len = (val->rs.s + val->rs.len) - p;
+					} else {
+						mv.len = p - mv.s;
+					}
+					val->rs = mv;
+					goto done;
+				}
+			}
+			val->rs = _tr_empty;
+			break;
+
+		case TR_LINE_COUNT:
+			n=0;
+			for(i=0; i<val->rs.len; i++)
+				if(val->rs.s[i]=='\n')
+					n++;
+			if(n==0 && val->rs.len>0)
+				n = 1;
+			val->flags = PV_TYPE_INT|PV_VAL_INT|PV_VAL_STR;
+			val->ri = n;
+			val->rs.s = int2str(val->ri, &val->rs.len);
+			break;
+
+			break;
+
+		default:
+			LM_ERR("unknown subtype %d\n",
+					subtype);
+			return -1;
+	}
+done:
+	if(val->rs.len>0)
+	{
+		/* skip ending '\r' if present */
+		if(val->rs.s[val->rs.len-1]=='\r')
+			val->rs.len--;
+	}
+	val->flags = PV_VAL_STR;
+	return 0;
+}
+
 
 #define _tr_parse_nparam(_p, _p0, _tp, _spec, _n, _sign, _in, _s) \
 	while(is_in_str(_p, _in) && (*_p==' ' || *_p=='\t' || *_p=='\n')) _p++; \
@@ -2113,3 +2309,98 @@ done:
 	t->name = name;
 	return p;
 }
+
+/*!
+ * \brief Helper fuction to parse a line transformation
+ * \param in parsed string
+ * \param t transformation
+ * \return pointer to the end of the transformation in the string - '}', null on error
+ */
+char* tr_parse_line(str* in, trans_t *t)
+{
+	char *p;
+	char *p0;
+	char *ps;
+	str s;
+	str name;
+	int n;
+	int sign;
+	pv_spec_t *spec = NULL;
+	tr_param_t *tp = NULL;
+
+
+	if(in==NULL || t==NULL)
+		return NULL;
+
+	p = in->s;
+	name.s = in->s;
+	t->type = TR_LINE;
+	t->trf = tr_eval_line;
+
+	/* find next token */
+	while(is_in_str(p, in) && *p!=TR_PARAM_MARKER && *p!=TR_RBRACKET) p++;
+	if(*p=='\0')
+	{
+		LM_ERR("invalid transformation: %.*s\n",
+				in->len, in->s);
+		goto error;
+	}
+	name.len = p - name.s;
+	trim(&name);
+
+	if(name.len==2 && strncasecmp(name.s, "at", 2)==0)
+	{
+		t->subtype = TR_LINE_AT;
+		if(*p!=TR_PARAM_MARKER)
+		{
+			LM_ERR("invalid name transformation: %.*s\n",
+					in->len, in->s);
+			goto error;
+		}
+		p++;
+		_tr_parse_nparam(p, p0, tp, spec, n, sign, in, s)
+		t->params = tp;
+		tp = 0;
+		while(is_in_str(p, in) && (*p==' ' || *p=='\t' || *p=='\n')) p++;
+		if(*p!=TR_RBRACKET)
+		{
+			LM_ERR("invalid name transformation: %.*s!\n",
+					in->len, in->s);
+			goto error;
+		}
+
+		goto done;
+	} else if(name.len==2 && strncasecmp(name.s, "sw", 2)==0) {
+		t->subtype = TR_LINE_SW;
+		if(*p!=TR_PARAM_MARKER)
+		{
+			LM_ERR("invalid value transformation: %.*s\n",
+					in->len, in->s);
+			goto error;
+		}
+		p++;
+		_tr_parse_sparam(p, p0, tp, spec, ps, in, s);
+		t->params = tp;
+		tp = 0;
+		while(*p && (*p==' ' || *p=='\t' || *p=='\n')) p++;
+		if(*p!=TR_RBRACKET)
+		{
+			LM_ERR("invalid value transformation: %.*s!\n",
+					in->len, in->s);
+			goto error;
+		}
+		goto done;
+	} else if(name.len==5 && strncasecmp(name.s, "count", 5)==0) {
+		t->subtype = TR_LINE_COUNT;
+		goto done;
+	}
+
+
+	LM_ERR("unknown transformation: %.*s/%.*s/%d!\n", in->len, in->s,
+			name.len, name.s, name.len);
+error:
+	return NULL;
+done:
+	t->name = name;
+	return p;
+}
diff --git a/modules_k/pv/pv_trans.h b/modules_k/pv/pv_trans.h
index 4d77e1d..c660102 100644
--- a/modules_k/pv/pv_trans.h
+++ b/modules_k/pv/pv_trans.h
@@ -33,7 +33,7 @@
 
 
 enum _tr_type { TR_NONE=0, TR_STRING, TR_URI, TR_PARAMLIST, TR_NAMEADDR,
-				TR_TOBODY };
+				TR_TOBODY, TR_LINE };
 enum _tr_s_subtype { 
 	TR_S_NONE=0, TR_S_LEN, TR_S_INT, TR_S_MD5, TR_S_SUBSTR,
 	TR_S_SELECT, TR_S_ENCODEHEXA, TR_S_DECODEHEXA,
@@ -58,6 +58,9 @@ enum _tr_tobody_subtype {
 	TR_TOBODY_NONE=0, TR_TOBODY_DISPLAY, TR_TOBODY_URI, TR_TOBODY_TAG,
 	TR_TOBODY_URI_USER, TR_TOBODY_URI_HOST, TR_TOBODY_PARAMS
 };
+enum _tr_line_subtype {
+	TR_LINE_NONE=0, TR_LINE_COUNT, TR_LINE_AT, TR_LINE_SW
+};
 
 
 char* tr_parse_string(str *in, trans_t *tr);
@@ -65,6 +68,7 @@ char* tr_parse_uri(str *in, trans_t *tr);
 char* tr_parse_paramlist(str *in, trans_t *tr);
 char* tr_parse_nameaddr(str *in, trans_t *tr);
 char* tr_parse_tobody(str* in, trans_t *t);
+char* tr_parse_line(str* in, trans_t *t);
 
 int tr_init_buffers(void);
 




More information about the sr-dev mailing list