[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