[asterisk-commits] murf: branch murf/fast-ast r44761 - in
/team/murf/fast-ast: include/asterisk/...
asterisk-commits at lists.digium.com
asterisk-commits at lists.digium.com
Mon Oct 9 08:48:03 MST 2006
Author: murf
Date: Mon Oct 9 10:48:03 2006
New Revision: 44761
URL: http://svn.digium.com/view/asterisk?rev=44761&view=rev
Log:
Fleshed out the syntax tree for pattern names
Removed:
team/murf/fast-ast/include/asterisk/trb.h
Modified:
team/murf/fast-ast/main/pbx.c
Modified: team/murf/fast-ast/main/pbx.c
URL: http://svn.digium.com/view/asterisk/team/murf/fast-ast/main/pbx.c?rev=44761&r1=44760&r2=44761&view=diff
==============================================================================
--- team/murf/fast-ast/main/pbx.c (original)
+++ team/murf/fast-ast/main/pbx.c Mon Oct 9 10:48:03 2006
@@ -161,11 +161,30 @@
const char pattern[0];
};
+/*! \brief match_char: forms a syntax tree for quick matching of extension patterns */
+struct match_char
+{
+ int is_pattern; /* the pattern started with '_' */
+ char *x;
+ int specificity; /* simply the strlen of x, or 10 for X, 9 for Z, and 8 for N; and '.' and '!' will add 11 ? */
+ struct match_char *alt_char;
+ struct match_char *next_char;
+ struct ast_exten *exten; /* attached to last char of a pattern for exten */
+};
+
+struct scoreboard /* make sure all fields are 0 before calling new_find_extension */
+{
+ int total_specificity;
+ int total_length;
+ struct ast_exten *exten;
+};
+
/*! \brief ast_context: An extension context */
struct ast_context {
ast_mutex_t lock; /*!< A lock to prevent multiple threads from clobbering the context */
struct ast_exten *root; /*!< The root of the list of extensions */
struct trb_table *root_tree; /*!< The root of the list of extensions in threaded red-black tree form */
+ struct match_char *pattern_tree; /*!< A tree to speed up extension pattern matching */
struct ast_context *next; /*!< Link them together */
struct ast_include *includes; /*!< Include other contexts */
struct ast_ignorepat *ignorepats; /*!< Patterns for which to continue playing dialtone */
@@ -245,6 +264,10 @@
static int trb_compare_extens(const void *trb_a, const void *trb_b, void *trb_param);
static int trb_compare_exten_numbers(const void *trb_a, const void *trb_b, void *trb_param);
static int trb_compare_exten_labels(const void *trb_a, const void *trb_b, void *trb_param);
+void new_find_extension(char *str, struct scoreboard *score, struct match_char *tree, int length, int spec);
+struct match_char *already_in_tree(struct match_char *current, char *pat);
+struct match_char *add_pattern_node(struct ast_context *con, struct match_char *current, char *pattern, int is_pattern);
+struct match_char *create_match_char_tree(struct ast_context *con);
static int trb_compare_contexts(const void *trb_a, const void *trb_b, void *trb_param)
@@ -600,15 +623,6 @@
{
free(p);
}
-
-struct match_char
-{
- char *x;
- int specificity; /* simply the strlen of x, or 10 for X, 9 for Z, and 8 for N; and '.' and '!' will add 11 ? */
- struct match_char *alt_char;
- struct match_char *next_char;
- struct ast_exten *exten_match; /* attached to last char of a pattern for exten */
-};
/* form a tree that fully describes all the patterns in a context's extensions
* in this tree, a "node" consists of a series of match_char structs linked in a chain
@@ -660,19 +674,12 @@
*
* */
-struct scoreboard /* make sure all fields are 0 before calling new_find_extension */
-{
- int total_specificity;
- int total_length;
- struct ast_extension *exten;
-};
-
/* you only really update the scoreboard, if the new score is BETTER than the
* one stored there. ignore it otherwise.
*/
-static void update_scoreboard(struct scoreboard *board, int length, int spec, struct ast_extension *exten)
+static void update_scoreboard(struct scoreboard *board, int length, int spec, struct ast_exten *exten)
{
if (length > board->total_length) {
board->total_specificity = spec;
@@ -692,8 +699,8 @@
for (p=tree; p; p=p->alt_char)
{
if (p->x[0] == 'N' && p->x[1] == 0 && *str >= '2' && *str <= '9' ) {
- if (p->next && *(str+1))
- find_extension(str+1, score, p->next_char, length+1, spec+8);
+ if (p->next_char && *(str+1))
+ new_find_extension(str+1, score, p->next_char, length+1, spec+8);
else if (p->exten) {
update_scoreboard(score, length+1, spec+8, p->exten);
return;
@@ -701,8 +708,8 @@
return;
}
} else if (p->x[0] == 'Z' && p->x[1] == 0 && *str >= '1' && *str <= '9' ) {
- if (p->next && *(str+1))
- find_extension(str+1, score, p->next_char, length+1, spec+9);
+ if (p->next_char && *(str+1))
+ new_find_extension(str+1, score, p->next_char, length+1, spec+9);
else if (p->exten) {
update_scoreboard(score, length+1, spec+9, p->exten);
return;
@@ -710,8 +717,8 @@
return;
}
} else if (p->x[0] == 'X' && p->x[1] == 0 && *str >= '0' && *str <= '9' ) {
- if (p->next && *(str+1))
- find_extension(str+1, score, p->next_char, length+1, spec+10);
+ if (p->next_char && *(str+1))
+ new_find_extension(str+1, score, p->next_char, length+1, spec+10);
else if (p->exten) {
update_scoreboard(score, length+1, spec+10, p->exten);
return;
@@ -725,8 +732,8 @@
update_scoreboard(score, length+1, spec+11, p->exten);
return;
} else if (index(p->x, *str)) {
- if (p->next && *(str+1))
- find_extension(str+1, score, p->next_char, length+1, spec+p->specificity);
+ if (p->next_char && *(str+1))
+ new_find_extension(str+1, score, p->next_char, length+1, spec+p->specificity);
else if (p->exten) {
update_scoreboard(score, length+1, spec+p->specificity, p->exten);
return;
@@ -750,10 +757,112 @@
* filled. It could be done as a finishing step after extensions.conf or .ael is
* loaded, or it could be done when the first search is encountered. It should only
* have to be done once, until the next unload or reload.
+ *
+ * I guess forming this pattern tree would be analogous to compiling a regex.
*/
-void create_match_char_tree(struct ast_context *con)
-{
+
+struct match_char *already_in_tree(struct match_char *current, char *pat)
+{
+ struct match_char *t;
+ if (!current)
+ return 0;
+ for (t=current; t; t=t->alt_char) {
+ if (strcmp(pat,t->x) == 0) /* uh, we may want to sort exploded [] contents to make matching easy */
+ return t;
+ }
+ return 0;
+}
+
+struct match_char *add_pattern_node(struct ast_context *con, struct match_char *current, char *pattern, int is_pattern)
+{
+ struct match_char *m = (struct match_char *)malloc(sizeof(struct match_char));
+ m->x = strdup(pattern);
+ m->is_pattern = is_pattern;
+
+ if (!con->pattern_tree) {
+ con->pattern_tree = m;
+ } else {
+ if (current->next_char) {
+ m->alt_char = current->next_char->alt_char;
+ current->next_char = m;
+ } else {
+ current->next_char = m;
+ }
+ }
+ return m;
+}
+
+struct match_char *create_match_char_tree(struct ast_context *con)
+{
+ struct trb_traverser t1;
+ struct ast_exten *e1;
+ struct match_char *m1,*m2;
+ char buf[256];
+ int already;
+
+ trb_t_init(&t1, con->root_tree);
+ while( (e1 = trb_t_next(&t1)) ) {
+ int pattern = 0;
+ char *s1 = e1->exten;
+ m1 = con->pattern_tree; /* each pattern starts over at the root of the pattern tree */
+ already = 1;
+
+ if ( *s1 == '_') {
+ pattern = 1;
+ s1++;
+ }
+ while( *s1 )
+ {
+ if (pattern && *s1 == '[' && *(s1-1) != '\\') {
+ char *s2 = buf;
+ while (*s1 != ']' && *(s1-1) != '\\' ) {
+ if (*s1 == '\\') {
+ if (*(s1+1) == ']') {
+ *s2++ = ']';
+ s1++;s1++;
+ } else if (*(s1+1) == '\\') {
+ *s2++ = '\\';
+ s1++;s1++;
+ } else if (*(s1+1) == '-') {
+ *s2++ = '-';
+ s1++; s1++;
+ } else if (*(s1+1) == '[') {
+ *s2++ = '[';
+ s1++; s1++;
+ }
+ } else if (*s1 == '-') { /* remember to add some error checking to all this! */
+ char s3 = *(s1-1);
+ char s4 = *(s1+1);
+ for (s3++; s3 <= s4; s3++) {
+ *s2++ = s3;
+ }
+ s1++; s1++;
+ } else {
+ *s2++ = *s1++;
+ }
+ }
+ } else {
+ if (*s1 == '\\') {
+ s1++;
+ buf[0] = *s1;
+ } else {
+ buf[0] = *s1;
+ }
+ buf[1] = 0;
+ }
+
+ if (already && (m2=already_in_tree(m1,buf))) {
+ m1 = m2->next_char; /* m1 points to the node to compare against */
+ } else {
+ already = 0;
+ m1 = add_pattern_node(con, m1, buf, pattern); /* m1 is the node just added */
+ }
+ s1++; /* advance to next char */
+ }
+ m1->exten = e1; /* that last node should have an exten pointer */
+ }
+ return m1; /* return the last node inserted, so you can add the exten data */
}
/*
@@ -1057,11 +1166,26 @@
return extension_match_core(pattern, data, needmore);
}
+struct fake_context /* this struct is purely for matching in the RB tree */
+{
+ ast_mutex_t lock;
+ struct ast_exten *root;
+ struct trb_table *root_tree;
+ struct match_char *pattern_tree;
+ struct ast_context *next;
+ struct ast_include *includes;
+ struct ast_ignorepat *ignorepats;
+ const char *registrar;
+ AST_LIST_HEAD_NOLOCK(, ast_sw) alts;
+ ast_mutex_t macrolock;
+ char name[256];
+};
+
struct ast_context *ast_context_find(const char *name)
{
struct ast_context *tmp = NULL;
- struct ast_context item;
- item->name = name;
+ struct fake_context item;
+ strncpy(item.name,name,256);
ast_mutex_lock(&conlock);
tmp = trb_find(contexts_tree,&item);
#ifdef NOTNOW
@@ -1119,8 +1243,8 @@
struct ast_sw *sw;
struct ast_exten pattern;
- pattern->label = label;
- pattern->priority = priority;
+ pattern.label = label;
+ pattern.priority = priority;
/* Initialize status if appropriate */
if (q->stacklen == 0) {
@@ -1142,8 +1266,8 @@
if (bypass) /* bypass means we only look there */
tmp = bypass;
else { /* look in contexts */
- struct ast_context item;
- item->name = name;
+ struct fake_context item;
+ strncpy(item.name,context,256);
tmp = trb_find(contexts_tree,&item);
#ifdef NOTNOW
tmp = NULL;
@@ -2757,8 +2881,8 @@
static struct ast_context *find_context_locked(const char *context)
{
struct ast_context *c = NULL;
- struct ast_context item;
- item->name = context;
+ struct fake_context item;
+ strncpy(item.name, context, 256);
ast_lock_contexts();
c = trb_find(contexts_tree,&item);
#ifdef NOTNOW
@@ -2985,8 +3109,8 @@
{
struct ast_context *c = NULL;
int ret = -1;
- struct ast_context item;
- item->name = context;
+ struct fake_context item;
+ strncpy(item.name,context,256);
ast_lock_contexts();
c = trb_find(contexts_tree,&item);
if (c)
@@ -3020,8 +3144,8 @@
{
struct ast_context *c = NULL;
int ret = -1;
- struct ast_context item;
- item->name = context;
+ struct fake_context item;
+ strncpy(item.name, context, 256);
ast_lock_contexts();
@@ -4644,6 +4768,7 @@
trb_delete(con->root_tree, e->exten);
trb_insert(con->root_tree, tmp->exten);
con->root = tmp;
+ }
if (tmp->priority == PRIORITY_HINT)
ast_change_hint(e,tmp);
/* Destroy the old one */
More information about the asterisk-commits
mailing list