diff options
author | Michael Schroeder <mls@suse.de> | 2012-11-28 17:57:10 +0100 |
---|---|---|
committer | Michael Schroeder <mls@suse.de> | 2012-11-28 17:57:10 +0100 |
commit | 67b4f920c26ba0f307b426b19426f411d11b765e (patch) | |
tree | 257450da36714d9d84e90cdfc4a94f58f770b8f5 | |
parent | f84307ce170e95d22a15c8199957b8f892a024f8 (diff) | |
download | libsolv-67b4f920c26ba0f307b426b19426f411d11b765e.tar.gz libsolv-67b4f920c26ba0f307b426b19426f411d11b765e.tar.bz2 libsolv-67b4f920c26ba0f307b426b19426f411d11b765e.zip |
speed up filelist matching by pre-matching the basename first
-rw-r--r-- | src/repodata.c | 77 |
1 files changed, 70 insertions, 7 deletions
diff --git a/src/repodata.c b/src/repodata.c index 50ff1dd..6cdf17b 100644 --- a/src/repodata.c +++ b/src/repodata.c @@ -1061,6 +1061,28 @@ datamatcher_init(Datamatcher *ma, const char *match, int flags) ma->flags = (flags & ~SEARCH_STRINGMASK) | SEARCH_ERROR; } } + if ((flags & SEARCH_FILES) != 0 && match) + { + /* prepare basename check */ + if ((flags & SEARCH_STRINGMASK) == SEARCH_STRING) + { + const char *p = strrchr(match, '/'); + ma->matchdata = (void *)(p ? p + 1 : match); + } + else if ((flags & SEARCH_STRINGMASK) == SEARCH_STRINGEND) + { + const char *p = strrchr(match, '/'); + ma->matchdata = (void *)(p ? p + 1 : 0); + } + else if ((flags & SEARCH_STRINGMASK) == SEARCH_GLOB) + { + const char *p; + for (p = match + strlen(match) - 1; p >= match; p--) + if (*p == '[' || *p == ']' || *p == '*' || *p == '?' || *p == '/') + break; + ma->matchdata = (void *)(p + 1); + } + } return ma->error; } @@ -1070,8 +1092,9 @@ datamatcher_free(Datamatcher *ma) if ((ma->flags & SEARCH_STRINGMASK) == SEARCH_REGEX && ma->matchdata) { regfree(ma->matchdata); - ma->matchdata = solv_free(ma->matchdata); + solv_free(ma->matchdata); } + ma->matchdata = 0; } int @@ -1145,6 +1168,49 @@ datamatcher_match(Datamatcher *ma, const char *str) return 1; } +/* check if the matcher can match the provides basename */ + +static int +datamatcher_checkbasename(Datamatcher *ma, const char *basename) +{ + int l; + const char *match = ma->match; + switch (ma->flags & SEARCH_STRINGMASK) + { + case SEARCH_STRING: + match = ma->matchdata; + break; + case SEARCH_STRINGEND: + if (ma->matchdata) + { + match = ma->matchdata; /* have slash */ + break; + } + l = strlen(basename) - strlen(match); + if (l < 0) + return 0; + basename += l; + break; + case SEARCH_GLOB: + match = ma->matchdata; + if (!match) + return 1; + l = strlen(basename) - strlen(match); + if (l < 0) + return 0; + basename += l; + break; + default: + return 1; /* maybe matches */ + } + if (!match) + return 1; + if ((ma->flags & SEARCH_NOCASE) != 0) + return !strcasecmp(match, basename); + else + return !strcmp(match, basename); +} + int repodata_filelistfilter_matches(Repodata *data, const char *str) { @@ -1578,12 +1644,9 @@ dataiterator_step(Dataiterator *di) if (di->matcher.match) { /* simple pre-check so that we don't need to stringify */ - if (di->keyname == SOLVABLE_FILELIST && di->key->type == REPOKEY_TYPE_DIRSTRARRAY && di->matcher.match && (di->matcher.flags & (SEARCH_FILES|SEARCH_NOCASE|SEARCH_STRINGMASK)) == (SEARCH_FILES|SEARCH_STRING)) - { - int l = strlen(di->matcher.match) - strlen(di->kv.str); - if (l < 0 || strcmp(di->matcher.match + l, di->kv.str)) - continue; - } + if (di->keyname == SOLVABLE_FILELIST && di->key->type == REPOKEY_TYPE_DIRSTRARRAY && (di->matcher.flags & SEARCH_FILES) != 0) + if (!datamatcher_checkbasename(&di->matcher, di->kv.str)) + continue; if (!repodata_stringify(di->pool, di->data, di->key, &di->kv, di->flags)) { if (di->keyname && (di->key->type == REPOKEY_TYPE_FIXARRAY || di->key->type == REPOKEY_TYPE_FLEXARRAY)) |