aboutsummaryrefslogtreecommitdiffstats
path: root/pbx.c
diff options
context:
space:
mode:
authorroot <root@f38db490-d61c-443f-a65b-d21fe96a405b>2006-01-22 03:00:19 +0000
committerroot <root@f38db490-d61c-443f-a65b-d21fe96a405b>2006-01-22 03:00:19 +0000
commitb0c9accd11a7baffb7b906c37bb1737e4659c28d (patch)
tree75b1a6c9147ddf78b2ec8db3d3fec45ad91eb091 /pbx.c
parent39f4ed089ef642ae432bc185c81aead32ba9258c (diff)
automerge commit
git-svn-id: http://svn.digium.com/svn/asterisk/branches/1.2-netsec@8425 f38db490-d61c-443f-a65b-d21fe96a405b
Diffstat (limited to 'pbx.c')
-rw-r--r--pbx.c48
1 files changed, 23 insertions, 25 deletions
diff --git a/pbx.c b/pbx.c
index 3446ab58e..a07a66a1b 100644
--- a/pbx.c
+++ b/pbx.c
@@ -927,40 +927,38 @@ pvn_endfor:
}
}
-static char *substring(char *value, int offset, int length, char *workspace, size_t workspace_len)
+/*! \brief takes a substring. It is ok to call with value == workspace.
+ *
+ * offset < 0 means start from the end of the string and set the beginning
+ * to be that many characters back.
+ * length is the length of the substring, -1 means unlimited
+ * (we take any negative value).
+ * Always return a copy in workspace.
+ */
+static char *substring(const char *value, int offset, int length, char *workspace, size_t workspace_len)
{
char *ret = workspace;
+ int lr; /* length of the input string after the copy */
- /* No need to do anything */
- if (offset == 0 && length==-1) {
- return value;
- }
+ ast_copy_string(workspace, value, workspace_len); /* always make a copy */
- ast_copy_string(workspace, value, workspace_len);
+ if (offset == 0 && length < 0) /* take the whole string */
+ return ret;
- if (abs(offset) > strlen(ret)) { /* Offset beyond string */
- if (offset >= 0)
- offset = strlen(ret);
- else
- offset =- strlen(ret);
- }
+ lr = strlen(ret); /* compute length after copy, so we never go out of the workspace */
- /* Detect too-long length */
- if ((offset < 0 && length > -offset) || (offset >= 0 && offset+length > strlen(ret))) {
- if (offset >= 0)
- length = strlen(ret)-offset;
- else
- length = strlen(ret)+offset;
+ if (offset < 0) { /* translate negative offset into positive ones */
+ offset = lr + offset;
+ if (offset < 0) /* If the negative offset was greater than the length of the string, just start at the beginning */
+ offset = 0;
}
- /* Bounce up to the right offset */
- if (offset >= 0)
- ret += offset;
- else
- ret += strlen(ret)+offset;
+ /* too large offset result in empty string so we know what to return */
+ if (offset >= lr)
+ return ret + lr; /* the final '\0' */
- /* Chop off at the requisite length */
- if (length >= 0)
+ ret += offset; /* move to the start position */
+ if (length >= 0 && length < lr - offset) /* truncate if necessary */
ret[length] = '\0';
return ret;