diff options
Diffstat (limited to 'main/pbx.c')
-rw-r--r-- | main/pbx.c | 54 |
1 files changed, 36 insertions, 18 deletions
diff --git a/main/pbx.c b/main/pbx.c index 6fe2c3c73..529899793 100644 --- a/main/pbx.c +++ b/main/pbx.c @@ -647,9 +647,8 @@ static void pbx_destroy(struct ast_pbx *p) * 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; @@ -658,6 +657,7 @@ static int ext_cmp1(const char **p) */ while ( (c = *(*p)++) && (c == ' ' || c == '-') ) ; /* ignore some characters */ + memset(bitwise, 0xff, 32); /* always return unless we have a set of chars */ switch (c) { @@ -665,12 +665,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 */ @@ -694,22 +701,28 @@ static int ext_cmp1(const char **p) return 0x40000; /* XXX make this entry go last... */ } - bzero(chars, 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)++; @@ -723,8 +736,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] != '_') @@ -733,16 +747,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; + } } /*! |