summaryrefslogtreecommitdiff
path: root/main
diff options
context:
space:
mode:
authorJoshua Colp <jcolp@digium.com>2016-03-29 13:16:17 -0500
committerGerrit Code Review <gerrit2@gerrit.digium.api>2016-03-29 13:16:17 -0500
commit7b7e3909e492df29d5d51e885f9328a23e61cb6a (patch)
tree5d7ed5625f8641282414b0b28cd77b54cfc334a0 /main
parente0a916d6f588287a5bb04dbb34b3c779f0fe31b9 (diff)
parent5aa5c49413a9b86f9e0d4456e580e3d536d33ef6 (diff)
Merge "sorcery/res_pjsip: Refactor for realtime performance" into 13
Diffstat (limited to 'main')
-rw-r--r--main/config.c90
-rw-r--r--main/strings.c127
2 files changed, 217 insertions, 0 deletions
diff --git a/main/config.c b/main/config.c
index 74f42cf72..69621868c 100644
--- a/main/config.c
+++ b/main/config.c
@@ -723,6 +723,96 @@ const char *ast_variable_find(const struct ast_category *category, const char *v
return ast_variable_find_in_list(category->root, variable);
}
+const struct ast_variable *ast_variable_find_variable_in_list(const struct ast_variable *list, const char *variable_name)
+{
+ const struct ast_variable *v;
+
+ for (v = list; v; v = v->next) {
+ if (!strcasecmp(variable_name, v->name)) {
+ return v;
+ }
+ }
+ return NULL;
+}
+
+int ast_variables_match(const struct ast_variable *left, const struct ast_variable *right)
+{
+ char *op;
+
+ if (left == right) {
+ return 1;
+ }
+
+ if (!(left && right)) {
+ return 0;
+ }
+
+ op = strrchr(right->name, ' ');
+ if (op) {
+ op++;
+ }
+
+ return ast_strings_match(left->value, op ? ast_strdupa(op) : NULL, right->value);
+}
+
+int ast_variable_lists_match(const struct ast_variable *left, const struct ast_variable *right, int exact_match)
+{
+ const struct ast_variable *field;
+ int right_count = 0;
+ int left_count = 0;
+
+ if (left == right) {
+ return 1;
+ }
+
+ if (!(left && right)) {
+ return 0;
+ }
+
+ for (field = right; field; field = field->next) {
+ char *space = strrchr(field->name, ' ');
+ const struct ast_variable *old;
+ char * name = (char *)field->name;
+
+ if (space) {
+ name = ast_strdup(field->name);
+ if (!name) {
+ return 0;
+ }
+ name[space - field->name] = '\0';
+ }
+
+ old = ast_variable_find_variable_in_list(left, name);
+ if (name != field->name) {
+ ast_free(name);
+ }
+
+ if (exact_match) {
+ if (!old || strcmp(old->value, field->value)) {
+ return 0;
+ }
+ } else {
+ if (!ast_variables_match(old, field)) {
+ return 0;
+ }
+ }
+
+ right_count++;
+ }
+
+ if (exact_match) {
+ for (field = left; field; field = field->next) {
+ left_count++;
+ }
+
+ if (right_count != left_count) {
+ return 0;
+ }
+ }
+
+ return 1;
+}
+
const char *ast_variable_find_in_list(const struct ast_variable *list, const char *variable)
{
const struct ast_variable *v;
diff --git a/main/strings.c b/main/strings.c
index 53d50954f..9e885ebc3 100644
--- a/main/strings.c
+++ b/main/strings.c
@@ -39,6 +39,7 @@
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
+#include <regex.h>
#include "asterisk/strings.h"
#include "asterisk/pbx.h"
@@ -228,3 +229,129 @@ char *ast_generate_random_string(char *buf, size_t size)
return buf;
}
+
+int ast_strings_match(const char *left, const char *op, const char *right)
+{
+ char *internal_op = (char *)op;
+ char *internal_right = (char *)right;
+ float left_num;
+ float right_num;
+ int scan_numeric = 0;
+
+ if (!(left && right)) {
+ return 0;
+ }
+
+ if (ast_strlen_zero(op)) {
+ if (ast_strlen_zero(left) && ast_strlen_zero(right)) {
+ return 1;
+ }
+
+ if (strlen(right) >= 2 && right[0] == '/' && right[strlen(right) - 1] == '/') {
+ internal_op = "regex";
+ internal_right = ast_strdupa(right);
+ /* strip the leading and trailing '/' */
+ internal_right++;
+ internal_right[strlen(internal_right) - 1] = '\0';
+ goto regex;
+ } else {
+ internal_op = "=";
+ goto equals;
+ }
+ }
+
+ if (!strcasecmp(op, "like")) {
+ char *tok;
+ struct ast_str *buffer = ast_str_alloca(128);
+
+ if (!strchr(right, '%')) {
+ return !strcmp(left, right);
+ } else {
+ internal_op = "regex";
+ internal_right = ast_strdupa(right);
+ tok = strsep(&internal_right, "%");
+ ast_str_set(&buffer, 0, "^%s", tok);
+
+ while ((tok = strsep(&internal_right, "%"))) {
+ ast_str_append(&buffer, 0, ".*%s", tok);
+ }
+ ast_str_append(&buffer, 0, "%s", "$");
+
+ internal_right = ast_str_buffer(buffer);
+ /* fall through to regex */
+ }
+ }
+
+regex:
+ if (!strcasecmp(internal_op, "regex")) {
+ regex_t expression;
+ int rc;
+
+ if (regcomp(&expression, internal_right, REG_EXTENDED | REG_NOSUB)) {
+ return 0;
+ }
+
+ rc = regexec(&expression, left, 0, NULL, 0);
+ regfree(&expression);
+ return !rc;
+ }
+
+equals:
+ scan_numeric = (sscanf(left, "%f", &left_num) && sscanf(internal_right, "%f", &right_num));
+
+ if (internal_op[0] == '=') {
+ if (ast_strlen_zero(left) && ast_strlen_zero(internal_right)) {
+ return 1;
+ }
+
+ if (scan_numeric) {
+ return (left_num == right_num);
+ } else {
+ return (!strcmp(left, internal_right));
+ }
+ }
+
+ if (internal_op[0] == '!' && internal_op[1] == '=') {
+ if (scan_numeric) {
+ return (left_num != right_num);
+ } else {
+ return !!strcmp(left, internal_right);
+ }
+ }
+
+ if (internal_op[0] == '<') {
+ if (scan_numeric) {
+ if (internal_op[1] == '=') {
+ return (left_num <= right_num);
+ } else {
+ return (left_num < right_num);
+ }
+ } else {
+ if (internal_op[1] == '=') {
+ return strcmp(left, internal_right) <= 0;
+ } else {
+ return strcmp(left, internal_right) < 0;
+ }
+ }
+ }
+
+ if (internal_op[0] == '>') {
+ if (scan_numeric) {
+ if (internal_op[1] == '=') {
+ return (left_num >= right_num);
+ } else {
+ return (left_num > right_num);
+ }
+ } else {
+ if (internal_op[1] == '=') {
+ return strcmp(left, internal_right) >= 0;
+ } else {
+ return strcmp(left, internal_right) > 0;
+ }
+ }
+ }
+
+ return 0;
+}
+
+