aboutsummaryrefslogtreecommitdiffstats
path: root/main/pbx.c
diff options
context:
space:
mode:
Diffstat (limited to 'main/pbx.c')
-rw-r--r--main/pbx.c54
1 files changed, 36 insertions, 18 deletions
diff --git a/main/pbx.c b/main/pbx.c
index ed852956a..30c988951 100644
--- a/main/pbx.c
+++ b/main/pbx.c
@@ -2133,9 +2133,8 @@ static void destroy_pattern_tree(struct match_char *pattern_tree) /* pattern tre
* we could encode the special cases as 0xffXX where XX
* is 1, 2, 3, 4 as used above.
*/
-static int ext_cmp1(const char **p)
+static int ext_cmp1(const char **p, unsigned char *bitwise)
{
- uint32_t chars[8];
int c, cmin = 0xff, count = 0;
const char *end;
@@ -2143,6 +2142,7 @@ static int ext_cmp1(const char **p)
* a valid character.
*/
c = *(*p)++;
+ memset(bitwise, 0xff, 32);
/* always return unless we have a set of chars */
switch (toupper(c)) {
@@ -2150,12 +2150,19 @@ static int ext_cmp1(const char **p)
return 0x0000 | (c & 0xff);
case 'N': /* 2..9 */
- return 0x0800 | '2' ;
+ bitwise[6] = 0x01;
+ bitwise[7] = 0xfe;
+ return 0x0800 | '2';
case 'X': /* 0..9 */
+ bitwise[5] = 0x7f;
+ bitwise[6] = 0x00;
+ bitwise[7] = 0xfe;
return 0x0A00 | '0';
case 'Z': /* 1..9 */
+ bitwise[6] = 0x00;
+ bitwise[7] = 0xfe;
return 0x0900 | '1';
case '.': /* wildcard */
@@ -2179,22 +2186,28 @@ static int ext_cmp1(const char **p)
return 0x40000; /* XXX make this entry go last... */
}
- memset(chars, '\0', sizeof(chars)); /* clear all chars in the set */
for (; *p < end ; (*p)++) {
unsigned char c1, c2; /* first-last char in range */
c1 = (unsigned char)((*p)[0]);
if (*p + 2 < end && (*p)[1] == '-') { /* this is a range */
c2 = (unsigned char)((*p)[2]);
- *p += 2; /* skip a total of 3 chars */
- } else /* individual character */
+ *p += 2; /* skip a total of 3 chars */
+ } else { /* individual character */
c2 = c1;
- if (c1 < cmin)
+ }
+ if (c1 < cmin) {
cmin = c1;
+ }
for (; c1 <= c2; c1++) {
- uint32_t mask = 1 << (c1 % 32);
- if ( (chars[ c1 / 32 ] & mask) == 0)
+ unsigned char mask = 1 << (c1 % 8);
+ /* Count the number of characters in the class, discarding duplicates. */
+ if ( (bitwise[ c1 / 8 ] & mask) == 1) {
count += 0x100;
- chars[ c1 / 32 ] |= mask;
+ }
+ /*!\note If two patterns score the same, but one includes '0' (as
+ * the lowest ASCII value in the given class) and the other does
+ * not, then the one including '0' will compare as coming first. */
+ bitwise[ c1 / 8 ] &= ~mask;
}
}
(*p)++;
@@ -2208,8 +2221,9 @@ static int ext_cmp(const char *a, const char *b)
{
/* make sure non-patterns come first.
* If a is not a pattern, it either comes first or
- * we use strcmp to compare the strings.
+ * we do a more complex pattern comparison.
*/
+ unsigned char bitwise[2][32];
int ret = 0;
if (a[0] != '_')
@@ -2218,16 +2232,20 @@ static int ext_cmp(const char *a, const char *b)
/* Now we know a is a pattern; if b is not, a comes first */
if (b[0] != '_')
return 1;
-#if 0 /* old mode for ext matching */
- return strcmp(a, b);
-#endif
+
/* ok we need full pattern sorting routine */
- while (!ret && a && b)
- ret = ext_cmp1(&a) - ext_cmp1(&b);
- if (ret == 0)
+ while (!ret && a && b) {
+ ret = ext_cmp1(&a, bitwise[0]) - ext_cmp1(&b, bitwise[1]);
+ if (ret == 0) {
+ /* Are the classes different, even though they score the same? */
+ ret = memcmp(bitwise[0], bitwise[1], 32);
+ }
+ }
+ if (ret == 0) {
return 0;
- else
+ } else {
return (ret > 0) ? 1 : -1;
+ }
}
int ast_extension_cmp(const char *a, const char *b)