diff options
Diffstat (limited to 'pbx.c')
-rw-r--r-- | pbx.c | 46 |
1 files changed, 26 insertions, 20 deletions
@@ -927,34 +927,40 @@ pvn_endfor: } } -/*! \brief takes a substring. It is ok to call with value == workspace. - * - * offset < 0 means start from the end of the string. - * 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) +static char *substring(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 */ - ast_copy_string(workspace, value, workspace_len); /* always make a copy */ + /* No need to do anything */ + if (offset == 0 && length==-1) { + return value; + } - if (offset == 0 && length < 0) /* take the whole string */ - return ret; + ast_copy_string(workspace, value, workspace_len); - lr = strlen(ret); /* compute length after copy, so we never go out of the workspace */ + if (abs(offset) > strlen(ret)) { /* Offset beyond string */ + if (offset >= 0) + offset = strlen(ret); + else + offset =- strlen(ret); + } - if (offset < 0) /* translate negative offset into positive ones */ - offset = lr - offset; + /* 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; + } - /* too large offset result in empty string so we know what to return */ - if (offset >= lr) - return ret + lr; /* the final '\0' */ + /* Bounce up to the right offset */ + if (offset >= 0) + ret += offset; + else + ret += strlen(ret)+offset; - ret += offset; /* move to the start position */ - if (length >= 0 && length < lr - offset) /* truncate if necessary */ + /* Chop off at the requisite length */ + if (length >= 0) ret[length] = '\0'; return ret; |