[asterisk-commits] murf: branch murf/fast-ast r44829 -
/team/murf/fast-ast/main/pbx.c
asterisk-commits at lists.digium.com
asterisk-commits at lists.digium.com
Tue Oct 10 11:44:43 MST 2006
Author: murf
Date: Tue Oct 10 13:44:43 2006
New Revision: 44829
URL: http://svn.digium.com/view/asterisk?rev=44829&view=rev
Log:
code working enough to do some benchmarks
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=44829&r1=44828&r2=44829&view=diff
==============================================================================
--- team/murf/fast-ast/main/pbx.c (original)
+++ team/murf/fast-ast/main/pbx.c Tue Oct 10 13:44:43 2006
@@ -1,4 +1,5 @@
/*
+ *
* Asterisk -- An open source telephony toolkit.
*
* Copyright (C) 1999 - 2006, Digium, Inc.
@@ -176,6 +177,9 @@
{
int total_specificity;
int total_length;
+ char last_char; /* set to ! or . if they are the end of the pattern */
+ int canmatch; /* if the string to match was just too short */
+ struct ast_exten *canmatch_exten;
struct ast_exten *exten;
};
@@ -264,10 +268,11 @@
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);
+void new_find_extension(const 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 *add_pattern_node(struct ast_context *con, struct match_char *current, char *pattern, int is_pattern, int already, int specificity);
struct match_char *create_match_char_tree(struct ast_context *con);
+struct ast_exten *get_canmatch_exten(struct match_char *node);
static int trb_compare_contexts(const void *trb_a, const void *trb_b, void *trb_param)
@@ -679,20 +684,32 @@
*/
-static void update_scoreboard(struct scoreboard *board, int length, int spec, struct ast_exten *exten)
+static void update_scoreboard(struct scoreboard *board, int length, int spec, struct ast_exten *exten, char last)
{
if (length > board->total_length) {
board->total_specificity = spec;
board->total_length = length;
board->exten = exten;
+ board->last_char = last;
} else if (length == board->total_length && spec < board->total_specificity) {
board->total_specificity = spec;
board->total_length = length;
board->exten = exten;
- }
-}
-
-void new_find_extension(char *str, struct scoreboard *score, struct match_char *tree, int length, int spec)
+ board->last_char = last;
+ }
+}
+
+struct ast_exten *get_canmatch_exten(struct match_char *node)
+{
+ /* find the exten at the end of the rope */
+ struct match_char *node2 = node;
+ for (node2 = node; node2; node2 = node2->next_char)
+ if (node2->exten)
+ return node2->exten;
+ return 0;
+}
+
+void new_find_extension(const char *str, struct scoreboard *score, struct match_char *tree, int length, int spec)
{
struct match_char *p; /* note minimal stack storage requirements */
@@ -702,8 +719,11 @@
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);
+ update_scoreboard(score, length+1, spec+8, p->exten,0);
return;
+ } else if (p->next_char && !*(str+1)) {
+ score->canmatch = 1;
+ score->canmatch_exten = get_canmatch_exten(p);
} else {
return;
}
@@ -711,8 +731,11 @@
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);
+ update_scoreboard(score, length+1, spec+9, p->exten,0);
return;
+ } else if (p->next_char && !*(str+1)) {
+ score->canmatch = 1;
+ score->canmatch_exten = get_canmatch_exten(p);
} else {
return;
}
@@ -720,29 +743,33 @@
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);
+ update_scoreboard(score, length+1, spec+10, p->exten,0);
return;
+ } else if (p->next_char && !*(str+1)) {
+ score->canmatch = 1;
+ score->canmatch_exten = get_canmatch_exten(p);
} else {
return;
}
} else if (p->x[0] == '.' && p->x[1] == 0 ) {
- update_scoreboard(score, length+1, spec+11, p->exten);
+ update_scoreboard(score, length+1, spec+11, p->exten, '.');
return;
} else if (p->x[0] == '!' && p->x[1] == 0 ) {
- update_scoreboard(score, length+1, spec+11, p->exten);
+ update_scoreboard(score, length+1, spec+11, p->exten, '!');
return;
} else if (index(p->x, *str)) {
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);
+ update_scoreboard(score, length+1, spec+p->specificity, p->exten,0);
return;
+ } else if (p->next_char && !*(str+1)) {
+ score->canmatch = 1;
+ score->canmatch_exten = get_canmatch_exten(p);
} else {
return;
}
- } else {
- return;
}
}
}
@@ -774,20 +801,37 @@
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));
+struct match_char *add_pattern_node(struct ast_context *con, struct match_char *current, char *pattern, int is_pattern, int already, int specificity)
+{
+ struct match_char *m = (struct match_char *)calloc(1,sizeof(struct match_char));
m->x = strdup(pattern);
m->is_pattern = is_pattern;
+ if (specificity == 1 && is_pattern && pattern[0] == 'N')
+ m->specificity = 8;
+ else if (specificity == 1 && is_pattern && pattern[0] == 'Z')
+ m->specificity = 9;
+ else if (specificity == 1 && is_pattern && pattern[0] == 'X')
+ m->specificity = 10;
+ else if (specificity == 1 && is_pattern && pattern[0] == '.')
+ m->specificity = 11;
+ else if (specificity == 1 && is_pattern && pattern[0] == '!')
+ m->specificity = 11;
+ else
+ m->specificity = specificity;
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;
+ if (already) { /* switch to the new regime (traversing vs appending)*/
+ m->alt_char = current->alt_char;
+ current->alt_char = m;
} else {
- current->next_char = m;
+ if (current->next_char) {
+ m->alt_char = current->next_char->alt_char;
+ current->next_char = m;
+ } else {
+ current->next_char = m;
+ }
}
}
return m;
@@ -800,6 +844,7 @@
struct match_char *m1,*m2;
char buf[256];
int already;
+ int specif;
trb_t_init(&t1, con->root_tree);
while( (e1 = trb_t_next(&t1)) ) {
@@ -842,6 +887,7 @@
*s2++ = *s1++;
}
}
+ specif = strlen(buf);
} else {
if (*s1 == '\\') {
s1++;
@@ -850,19 +896,20 @@
buf[0] = *s1;
}
buf[1] = 0;
+ specif = 1;
}
if (already && (m2=already_in_tree(m1,buf))) {
m1 = m2->next_char; /* m1 points to the node to compare against */
} else {
+ m1 = add_pattern_node(con, m1, buf, pattern, already,specif); /* m1 is the node just added */
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 */
+ return m1; /* just in case you want to see how the pattern ended */
}
/*
@@ -1187,7 +1234,8 @@
struct fake_context item;
strncpy(item.name,name,256);
ast_mutex_lock(&conlock);
- tmp = trb_find(contexts_tree,&item);
+ if( contexts_tree )
+ tmp = trb_find(contexts_tree,&item);
#ifdef NOTNOW
while ( (tmp = ast_walk_contexts(tmp)) ) {
if (!name || !strcasecmp(name, tmp->name))
@@ -1242,6 +1290,7 @@
struct ast_include *i;
struct ast_sw *sw;
struct ast_exten pattern;
+ struct scoreboard score;
pattern.label = label;
pattern.priority = priority;
@@ -1281,7 +1330,49 @@
}
if (q->status < STATUS_NO_EXTENSION)
q->status = STATUS_NO_EXTENSION;
-
+
+ /* Do a search for matching extension */
+ eroot = NULL;
+ score.total_specificity = 0;
+ score.exten = 0;
+ score.total_length = 0;
+ if (!tmp->pattern_tree)
+ create_match_char_tree(tmp);
+ new_find_extension(exten, &score, tmp->pattern_tree, 0, 0);
+ eroot = score.exten;
+
+ if (score.last_char == '!' && action == E_MATCHMORE) {
+ /* We match an extension ending in '!'.
+ * The decision in this case is final and is NULL (no match).
+ */
+ return NULL;
+ }
+
+ if (!eroot && action == E_CANMATCH && score.canmatch_exten) {
+ q->status = STATUS_SUCCESS;
+ return score.canmatch_exten;
+ }
+
+ if (eroot) {
+ /* found entry, now look for the right priority */
+ if (q->status < STATUS_NO_PRIORITY)
+ q->status = STATUS_NO_PRIORITY;
+ e = NULL;
+ if (action == E_FINDLABEL && label ) {
+ if (q->status < STATUS_NO_LABEL)
+ q->status = STATUS_NO_LABEL;
+ e = trb_find(eroot->peer_label_tree, &pattern);
+ } else {
+ e = trb_find(eroot->peer_tree, &pattern);
+ }
+ if (e) { /* found a valid match */
+ q->status = STATUS_SUCCESS;
+ q->foundcontext = context;
+ return e;
+ }
+ }
+
+#ifdef NOTNOW2
/* scan the list trying to match extension and CID */
eroot = NULL;
while ( (eroot = ast_walk_context_extensions(tmp, eroot)) ) {
@@ -1326,6 +1417,7 @@
return e;
}
}
+#endif
/* Check alternative switches */
AST_LIST_TRAVERSE(&tmp->alts, sw, list) {
struct ast_switch *asw = pbx_findswitch(sw->name);
@@ -4931,6 +5023,12 @@
tmp->next = e;
if (el) {
el->next = tmp;
+ tmp->peer_tree = trb_create(trb_compare_exten_numbers,0,0);
+ tmp->peer_label_tree = trb_create(trb_compare_exten_labels,0,0);
+ if (label)
+ trb_insert(tmp->peer_label_tree,tmp);
+ trb_insert(tmp->peer_tree, tmp);
+
} else {
con->root_tree = trb_create(trb_compare_extens,0,0);
con->root = tmp;
@@ -4938,7 +5036,7 @@
con->root->peer_label_tree = trb_create(trb_compare_exten_labels,0,0);
if (label)
trb_insert(con->root->peer_label_tree,tmp);
- trb_insert(con->root_tree, tmp);
+ trb_insert(con->root->peer_tree, tmp);
}
trb_insert(con->root_tree, tmp);
ast_mutex_unlock(&con->lock);
More information about the asterisk-commits
mailing list