diff options
author | Joshua Colp <jcolp@digium.com> | 2016-03-29 13:16:17 -0500 |
---|---|---|
committer | Gerrit Code Review <gerrit2@gerrit.digium.api> | 2016-03-29 13:16:17 -0500 |
commit | 7b7e3909e492df29d5d51e885f9328a23e61cb6a (patch) | |
tree | 5d7ed5625f8641282414b0b28cd77b54cfc334a0 /main | |
parent | e0a916d6f588287a5bb04dbb34b3c779f0fe31b9 (diff) | |
parent | 5aa5c49413a9b86f9e0d4456e580e3d536d33ef6 (diff) |
Merge "sorcery/res_pjsip: Refactor for realtime performance" into 13
Diffstat (limited to 'main')
-rw-r--r-- | main/config.c | 90 | ||||
-rw-r--r-- | main/strings.c | 127 |
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; +} + + |