]> git.ipfire.org Git - thirdparty/squid.git/commitdiff
Replace RegexList wth std::list<RegexPattern>
authorAmos Jeffries <squid3@treenet.co.nz>
Mon, 27 Jul 2015 12:51:43 +0000 (05:51 -0700)
committerAmos Jeffries <squid3@treenet.co.nz>
Mon, 27 Jul 2015 12:51:43 +0000 (05:51 -0700)
src/AclRegs.cc
src/acl/HttpHeaderData.cc
src/acl/RegexData.cc
src/acl/RegexData.h
src/base/RegexPattern.cc
src/base/RegexPattern.h

index 9be5e3e052a34ec7b8f0328d85c799957f838a3f..068ac6d27e954c8afa68b9a3463b5b2fc173d9e8 100644 (file)
@@ -96,6 +96,7 @@
 #include "auth/AclMaxUserIp.h"
 #include "auth/AclProxyAuth.h"
 #endif
+#include "base/RegexPattern.h"
 #if USE_IDENT
 #include "ident/AclIdent.h"
 #endif
index 68cae3ec94d08202a915e89f91d17902905f640a..7b27e3f6fa2517a2bd0f86c0bbc06aa3392f116f 100644 (file)
@@ -13,6 +13,7 @@
 #include "acl/Checklist.h"
 #include "acl/HttpHeaderData.h"
 #include "acl/RegexData.h"
+#include "base/RegexPattern.h"
 #include "ConfigParser.h"
 #include "Debug.h"
 #include "HttpHeaderTools.h"
index 52c83811d1467544d0d7272716380fa662211793..951da42b017b9fef3b124d9c835261d185265023 100644 (file)
 
 ACLRegexData::~ACLRegexData()
 {
-    delete data;
 }
 
 bool
 ACLRegexData::match(char const *word)
 {
-    if (word == NULL)
+    if (!word)
         return 0;
 
-    debugs(28, 3, "aclRegexData::match: checking '" << word << "'");
+    debugs(28, 3, "checking '" << word << "'");
 
-    RegexList *first, *prev;
-
-    first = data;
-
-    prev = NULL;
-
-    RegexList *current = first;
-
-    while (current) {
-        debugs(28, 3, "aclRegexData::match: looking for '" << current->pattern << "'");
-
-        if (regexec(&current->regex, word, 0, 0, 0) == 0) {
-            if (prev != NULL) {
-                /* shift the element just found to the second position
-                 * in the list */
-                prev->next = current->next;
-                current->next = first->next;
-                first->next = current;
-            }
-
-            debugs(28, 2, "aclRegexData::match: match '" << current->pattern << "' found in '" << word << "'");
+    // walk the list of patterns to see if one matches
+    for (auto &i : data) {
+        if (regexec(&i.regex, word, 0, 0, 0) == 0) {
+            debugs(28, 2, "'" << i.pattern << "' found in '" << word << "'");
+            // TODO: old code also popped the pattern to second place of the list
+            // in order to reduce patterns search times.
             return 1;
         }
-
-        prev = current;
-        current = current->next;
     }
 
     return 0;
@@ -71,21 +52,21 @@ SBufList
 ACLRegexData::dump() const
 {
     SBufList sl;
-    RegexList *temp = data;
     int flags = REG_EXTENDED | REG_NOSUB;
 
-    while (temp != NULL) {
-        if (temp->flags != flags) {
-            if ((temp->flags&REG_ICASE) != 0) {
+    // walk and dump the list
+    // keeping the flags values consistent
+    for (auto &i : data) {
+        if (i.flags != flags) {
+            if ((i.flags&REG_ICASE) != 0) {
                 sl.push_back(SBuf("-i"));
             } else {
                 sl.push_back(SBuf("+i"));
             }
-            flags = temp->flags;
+            flags = i.flags;
         }
 
-        sl.push_back(SBuf(temp->pattern));
-        temp = temp->next;
+        sl.push_back(SBuf(i.pattern));
     }
 
     return sl;
@@ -119,31 +100,26 @@ removeUnnecessaryWildcards(char * t)
     return t;
 }
 
-static RegexList **
-compileRE(RegexList **Tail, char * RE, int flags)
+static bool
+compileRE(std::list<RegexPattern> &curlist, char * RE, int flags)
 {
-    int errcode;
-    RegexList *q;
-    regex_t comp;
+    if (RE == NULL || *RE == '\0')
+        return curlist.empty(); // XXX: old code did this. It looks wrong.
 
-    if (RE == NULL  ||  *RE == '\0')
-        return Tail;
-
-    if ((errcode = regcomp(&comp, RE, flags)) != 0) {
+    regex_t comp;
+    if (int errcode = regcomp(&comp, RE, flags)) {
         char errbuf[256];
         regerror(errcode, &comp, errbuf, sizeof errbuf);
         debugs(28, DBG_CRITICAL, "" << cfg_filename << " line " << config_lineno << ": " << config_input_line);
         debugs(28, DBG_CRITICAL, "ERROR: invalid regular expression: '" << RE << "': " << errbuf);
-        return NULL;
+        return false;
     }
-    debugs(28, 2, "compileRE: compiled '" << RE << "' with flags " << flags );
+    debugs(28, 2, "compiled '" << RE << "' with flags " << flags);
 
-    q = new RegexList(flags, RE);
-    q->regex = comp;
-    *(Tail) = q;
-    Tail = &q->next;
+    curlist.emplace_back(flags, RE);
+    curlist.back().regex = comp;
 
-    return Tail;
+    return true;
 }
 
 /** Compose and compile one large RE from a set of (small) REs.
@@ -151,20 +127,14 @@ compileRE(RegexList **Tail, char * RE, int flags)
  * called only once per ACL.
  */
 static int
-compileOptimisedREs(RegexList **curlist, wordlist * wl)
+compileOptimisedREs(std::list<RegexPattern> &curlist, wordlist * wl)
 {
-    RegexList **Tail;
-    RegexList *newlist;
-    RegexList **newlistp;
+    std::list<RegexPattern> newlist;
     int numREs = 0;
     int flags = REG_EXTENDED | REG_NOSUB;
     int largeREindex = 0;
     char largeRE[BUFSIZ];
-
-    newlist = NULL;
-    newlistp = &newlist;
-
-    largeRE[0] = '\0';
+    *largeRE = 0;
 
     while (wl != NULL) {
         int RElen;
@@ -176,11 +146,8 @@ compileOptimisedREs(RegexList **curlist, wordlist * wl)
                 debugs(28, 2, "compileOptimisedREs: optimisation of -i ... -i" );
             } else {
                 debugs(28, 2, "compileOptimisedREs: -i" );
-                newlistp = compileRE( newlistp, largeRE, flags );
-                if (newlistp == NULL) {
-                    delete newlist;
+                if (!compileRE(newlist, largeRE, flags))
                     return 0;
-                }
                 flags |= REG_ICASE;
                 largeRE[largeREindex=0] = '\0';
             }
@@ -190,11 +157,8 @@ compileOptimisedREs(RegexList **curlist, wordlist * wl)
                 debugs(28, 2, "compileOptimisedREs: optimisation of +i ... +i");
             } else {
                 debugs(28, 2, "compileOptimisedREs: +i");
-                newlistp = compileRE( newlistp, largeRE, flags );
-                if (newlistp == NULL) {
-                    delete newlist;
+                if (!compileRE(newlist, largeRE, flags))
                     return 0;
-                }
                 flags &= ~REG_ICASE;
                 largeRE[largeREindex=0] = '\0';
             }
@@ -216,31 +180,19 @@ compileOptimisedREs(RegexList **curlist, wordlist * wl)
             ++numREs;
         } else {
             debugs(28, 2, "compileOptimisedREs: buffer full, generating new optimised RE..." );
-            newlistp = compileRE( newlistp, largeRE, flags );
-            if (newlistp == NULL) {
-                delete newlist;
+            if (!compileRE(newlist, largeRE, flags))
                 return 0;
-            }
             largeRE[largeREindex=0] = '\0';
             continue;    /* do the loop again to add the RE to largeRE */
         }
         wl = wl->next;
     }
 
-    newlistp = compileRE( newlistp, largeRE, flags );
-    if (newlistp == NULL) {
-        delete newlist;
+    if (!compileRE(newlist, largeRE, flags))
         return 0;
-    }
 
     /* all was successful, so put the new list at the tail */
-    if (*curlist == NULL) {
-        *curlist = newlist;
-    } else {
-        for (Tail = curlist; *Tail != NULL; Tail = &((*Tail)->next))
-            ;
-        (*Tail) = newlist;
-    }
+    curlist.splice(curlist.end(), newlist);
 
     debugs(28, 2, "compileOptimisedREs: " << numREs << " REs are optimised into one RE.");
     if (numREs > 100) {
@@ -253,75 +205,59 @@ compileOptimisedREs(RegexList **curlist, wordlist * wl)
 }
 
 static void
-compileUnoptimisedREs(RegexList **curlist, wordlist * wl)
+compileUnoptimisedREs(std::list<RegexPattern> &curlist, wordlist * wl)
 {
-    RegexList **Tail;
-    RegexList **newTail;
     int flags = REG_EXTENDED | REG_NOSUB;
 
-    for (Tail = curlist; *Tail != NULL; Tail = &((*Tail)->next))
-        ;
-
     while (wl != NULL) {
         if (strcmp(wl->key, "-i") == 0) {
             flags |= REG_ICASE;
         } else if (strcmp(wl->key, "+i") == 0) {
             flags &= ~REG_ICASE;
         } else {
-            newTail = compileRE( Tail, wl->key , flags );
-            if (newTail == NULL)
+            if (!compileRE(curlist, wl->key , flags))
                 debugs(28, DBG_CRITICAL, "ERROR: Skipping regular expression. Compile failed: '" << wl->key << "'");
-            else
-                Tail = newTail;
         }
         wl = wl->next;
     }
 }
 
-static void
-aclParseRegexList(RegexList **curlist)
+void
+ACLRegexData::parse()
 {
-    char *t;
-    wordlist *wl = NULL;
+    debugs(28, 2, "new Regex line or file");
 
-    debugs(28, 2, HERE << "aclParseRegexList: new Regex line or file");
-
-    while ((t = ConfigParser::RegexStrtokFile()) != NULL) {
+    wordlist *wl = NULL;
+    while (char *t = ConfigParser::RegexStrtokFile()) {
         const char *clean = removeUnnecessaryWildcards(t);
         if (strlen(clean) > BUFSIZ-1) {
             debugs(28, DBG_CRITICAL, "" << cfg_filename << " line " << config_lineno << ": " << config_input_line);
             debugs(28, DBG_CRITICAL, "ERROR: Skipping regular expression. Larger than " << BUFSIZ-1 << " characters: '" << clean << "'");
         } else {
-            debugs(28, 3, "aclParseRegexList: buffering RE '" << clean << "'");
+            debugs(28, 3, "buffering RE '" << clean << "'");
             wordlistAdd(&wl, clean);
         }
     }
 
-    if (!compileOptimisedREs(curlist, wl)) {
+    if (!compileOptimisedREs(data, wl)) {
         debugs(28, DBG_IMPORTANT, "WARNING: optimisation of regular expressions failed; using fallback method without optimisation");
-        compileUnoptimisedREs(curlist, wl);
+        compileUnoptimisedREs(data, wl);
     }
 
     wordlistDestroy(&wl);
 }
 
-void
-ACLRegexData::parse()
-{
-    aclParseRegexList(&data);
-}
-
 bool
 ACLRegexData::empty() const
 {
-    return data == NULL;
+    return data.empty();
 }
 
 ACLData<char const *> *
 ACLRegexData::clone() const
 {
     /* Regex's don't clone yet. */
-    assert (!data);
+    assert(data.empty());
     return new ACLRegexData;
 }
 
index 19c5a1ae85dbd7314f2f170d65c559ce54e304c8..7b4b15ba2d965482915c9bb6186aa411f6b1bc5e 100644 (file)
@@ -11,7 +11,9 @@
 
 #include "acl/Data.h"
 
-class RegexList;
+#include <list>
+
+class RegexPattern;
 
 class ACLRegexData : public ACLData<char const *>
 {
@@ -26,7 +28,7 @@ public:
     virtual ACLData<char const *> *clone() const;
 
 private:
-    RegexList *data;
+    std::list<RegexPattern> data;
 };
 
 #endif /* SQUID_ACLREGEXDATA_H */
index 37018d48048cb573743bc786c3b01d42b32db621..e70879ac4d306ea2314077d766ffe3c239e52398 100644 (file)
@@ -14,15 +14,3 @@ RegexPattern::~RegexPattern()
     xfree(pattern);
     regfree(&regex);
 }
-
-RegexList::~RegexList()
-{
-    // lists could be very long
-    // iterate instead of recursing
-    for (auto p = next; p; p = next) {
-        next = p->next;
-        p->next = nullptr;
-        delete p;
-    }
-}
-
index eb2fdd5d456fcbcde7c762bcf79b5b8a6f3e4c3b..180488b1477db8dd713721826badda93d93c8223 100644 (file)
@@ -23,7 +23,7 @@ public:
     RegexPattern() = delete;
     RegexPattern(int aFlags, const char *aPattern) : flags(aFlags), pattern(xstrdup(aPattern)) {}
     RegexPattern(const RegexPattern &) = delete;
-    RegexPattern(const RegexPattern && o) = delete;
+    RegexPattern(RegexPattern &&) = default;
     ~RegexPattern();
 
     int flags;
@@ -31,21 +31,5 @@ public:
     regex_t regex;
 };
 
-/// list of regular expressions.
-/// \deprecated use a std::list<RegexPattern> instead
-class RegexList : public RegexPattern
-{
-    MEMPROXY_CLASS(RegexList);
-
-public:
-    RegexList() = delete;
-    RegexList(int aFlags, const char *aPattern) : RegexPattern(aFlags, aPattern), next(nullptr) {}
-    RegexList(const RegexList &) = delete;
-    RegexList(const RegexList && o) = delete;
-    ~RegexList();
-
-    RegexList *next;
-};
-
 #endif /* SQUID_SRC_BASE_REGEXPATTERN_H */