java-topology/defects/postfix/patch/postfix-0001.patch

86 lines
3.4 KiB
Diff

--- a/postfix/src/util/match_list.c
+++ b/postfix/src/util/match_list.c
@@ -50,6 +50,7 @@
#include <argv.h>
#include <dict.h>
#include <match_list.h>
+#include <htable.h>
/* Application-specific */
@@ -132,6 +132,7 @@ MATCH_LIST *match_list_init(const char *pname, int flags,
list->match_count = match_count;
list->match_func =
(MATCH_LIST_FN *) mymalloc(match_count * sizeof(MATCH_LIST_FN));
list->match_args =
(const char **) mymalloc(match_count * sizeof(const char *));
va_start(ap, match_count);
for (i = 0; i < match_count; i++)
list->match_func[i] = va_arg(ap, MATCH_LIST_FN);
va_end(ap);
list->error = 0;
list->fold_buf = vstring_alloc(20);
+ list->string_cache = htable_create(8);
#define DO_MATCH 1
@@ -140,6 +141,12 @@ MATCH_LIST *match_list_init(const char *pname, int flags,
list->patterns = match_list_parse(list, argv_alloc(1), saved_patterns,
DO_MATCH);
argv_terminate(list->patterns);
+ /* Pre-index all inline string patterns (no '!' negation, no ':' dict) */
+ {
+ char **cpp;
+ for (cpp = list->patterns->argv; *cpp != 0; cpp++) {
+ char *p = *cpp;
+ int neg = 0;
+ while (*p == '!') { neg = !neg; p++; }
+ if (strchr(p, ':') == 0 && *p != '/') /* plain string pattern */
+ htable_enter(list->string_cache, p, (char *)(neg ? (void*)1 : (void*)2));
+ }
+ }
myfree(saved_patterns);
return (list);
}
@@ -160,6 +167,21 @@ int match_list_match(MATCH_LIST *list,...)
list->error = 0;
/*
+ * Fast path: O(1) hash lookup for the common case where all patterns
+ * are plain strings (no wildcards, no file includes, no type:table).
+ * Fall through to the linear scan only when non-string patterns exist.
+ */
+ if (list->match_count == 1 && htable_used(list->string_cache) > 0) {
+ casefold(list->fold_buf, list->match_args[0]);
+ HTABLE_INFO *entry = htable_find(list->string_cache, STR(list->fold_buf));
+ if (entry) {
+ /* value 2 = positive match, value 1 = negated (no match) */
+ return (entry->value == (char*)2) ? 1 : 0;
+ }
+ /* Not found in hash — could still match a non-string pattern below */
+ if (list->patterns->argc == (int)htable_used(list->string_cache))
+ return 0; /* all patterns are plain strings and none matched */
+ }
+
+ /*
* Iterate over all patterns in the list, stop at the first match.
*/
for (cpp = list->patterns->argv; (pat = *cpp) != 0; cpp++) {
@@ -185,5 +207,6 @@ void match_list_free(MATCH_LIST *list)
argv_free(list->patterns);
myfree((void *) list->match_func);
myfree((void *) list->match_args);
+ htable_free(list->string_cache, (void (*)(char *)) 0);
vstring_free(list->fold_buf);
myfree((void *) list);
}
--- a/postfix/src/util/match_list.h
+++ b/postfix/src/util/match_list.h
@@ -38,6 +38,7 @@ typedef int (*MATCH_LIST_FN) (struct MATCH_LIST *, const char *, const char *);
typedef struct MATCH_LIST {
const char *pname; /* parameter name for error reports */
int flags; /* MATCH_FLAG_XXX */
+ struct HTABLE *string_cache; /* O(1) index for inline string patterns */
ARGV *patterns; /* one pattern per element */
int match_count; /* number of match functions */
MATCH_LIST_FN *match_func; /* match functions */