c00279
diff --git a/src/acl/RegexData.cc b/src/acl/RegexData.cc
c00279
index 01a4c12..b5c1679 100644
c00279
--- a/src/acl/RegexData.cc
c00279
+++ b/src/acl/RegexData.cc
c00279
@@ -22,6 +22,7 @@
c00279
 #include "ConfigParser.h"
c00279
 #include "Debug.h"
c00279
 #include "sbuf/List.h"
c00279
+#include "sbuf/Algorithms.h"
c00279
 
c00279
 ACLRegexData::~ACLRegexData()
c00279
 {
c00279
@@ -129,6 +130,18 @@ compileRE(std::list<RegexPattern> &curlist, const char * RE, int flags)
c00279
     return true;
c00279
 }
c00279
 
c00279
+static bool
c00279
+compileRE(std::list<RegexPattern> &curlist, const SBufList &RE, int flags)
c00279
+{
c00279
+	if (RE.empty())
c00279
+		return curlist.empty(); // XXX: old code did this. It looks wrong.
c00279
+	SBuf regexp;
c00279
+	static const SBuf openparen("("), closeparen(")"), separator(")|(");
c00279
+	JoinContainerIntoSBuf(regexp, RE.begin(), RE.end(), separator, openparen,
c00279
+			closeparen);
c00279
+	return compileRE(curlist, regexp.c_str(), flags);
c00279
+}
c00279
+
c00279
 /** Compose and compile one large RE from a set of (small) REs.
c00279
  * The ultimate goal is to have only one RE per ACL so that match() is
c00279
  * called only once per ACL.
c00279
@@ -137,16 +150,11 @@ static int
c00279
 compileOptimisedREs(std::list<RegexPattern> &curlist, const SBufList &sl)
c00279
 {
c00279
     std::list<RegexPattern> newlist;
c00279
-    int numREs = 0;
c00279
+    SBufList accumulatedRE;
c00279
+    int numREs = 0, reSize = 0;
c00279
     int flags = REG_EXTENDED | REG_NOSUB;
c00279
-    int largeREindex = 0;
c00279
-    char largeRE[BUFSIZ];
c00279
-    *largeRE = 0;
c00279
 
c00279
     for (const SBuf & configurationLineWord : sl) {
c00279
-        int RElen;
c00279
-        RElen = configurationLineWord.length();
c00279
-
c00279
         static const SBuf minus_i("-i");
c00279
         static const SBuf plus_i("+i");
c00279
         if (configurationLineWord == minus_i) {
c00279
@@ -155,10 +163,11 @@ compileOptimisedREs(std::list<RegexPattern> &curlist, const SBufList &sl)
c00279
                 debugs(28, 2, "optimisation of -i ... -i" );
c00279
             } else {
c00279
                 debugs(28, 2, "-i" );
c00279
-                if (!compileRE(newlist, largeRE, flags))
c00279
+                if (!compileRE(newlist, accumulatedRE, flags))
c00279
                     return 0;
c00279
                 flags |= REG_ICASE;
c00279
-                largeRE[largeREindex=0] = '\0';
c00279
+                accumulatedRE.clear();
c00279
+                reSize = 0;
c00279
             }
c00279
         } else if (configurationLineWord == plus_i) {
c00279
             if ((flags & REG_ICASE) == 0) {
c00279
@@ -166,37 +175,34 @@ compileOptimisedREs(std::list<RegexPattern> &curlist, const SBufList &sl)
c00279
                 debugs(28, 2, "optimisation of +i ... +i");
c00279
             } else {
c00279
                 debugs(28, 2, "+i");
c00279
-                if (!compileRE(newlist, largeRE, flags))
c00279
+                if (!compileRE(newlist, accumulatedRE, flags))
c00279
                     return 0;
c00279
                 flags &= ~REG_ICASE;
c00279
-                largeRE[largeREindex=0] = '\0';
c00279
+                accumulatedRE.clear();
c00279
+                reSize = 0;
c00279
             }
c00279
-        } else if (RElen + largeREindex + 3 < BUFSIZ-1) {
c00279
+        } else if (reSize < 1024) {
c00279
             debugs(28, 2, "adding RE '" << configurationLineWord << "'");
c00279
-            if (largeREindex > 0) {
c00279
-                largeRE[largeREindex] = '|';
c00279
-                ++largeREindex;
c00279
-            }
c00279
-            largeRE[largeREindex] = '(';
c00279
-            ++largeREindex;
c00279
-            configurationLineWord.copy(largeRE+largeREindex, BUFSIZ-largeREindex);
c00279
-            largeREindex += configurationLineWord.length();
c00279
-            largeRE[largeREindex] = ')';
c00279
-            ++largeREindex;
c00279
-            largeRE[largeREindex] = '\0';
c00279
+            accumulatedRE.push_back(configurationLineWord);
c00279
             ++numREs;
c00279
+            reSize += configurationLineWord.length();
c00279
         } else {
c00279
             debugs(28, 2, "buffer full, generating new optimised RE..." );
c00279
-            if (!compileRE(newlist, largeRE, flags))
c00279
+            accumulatedRE.push_back(configurationLineWord);
c00279
+            if (!compileRE(newlist, accumulatedRE, flags))
c00279
                 return 0;
c00279
-            largeRE[largeREindex=0] = '\0';
c00279
+            accumulatedRE.clear();
c00279
+            reSize = 0;
c00279
             continue;    /* do the loop again to add the RE to largeRE */
c00279
         }
c00279
     }
c00279
 
c00279
-    if (!compileRE(newlist, largeRE, flags))
c00279
+    if (!compileRE(newlist, accumulatedRE, flags))
c00279
         return 0;
c00279
 
c00279
+    accumulatedRE.clear();
c00279
+    reSize = 0;
c00279
+
c00279
     /* all was successful, so put the new list at the tail */
c00279
     curlist.splice(curlist.end(), newlist);
c00279
 
c00279
diff --git a/src/sbuf/Algorithms.h b/src/sbuf/Algorithms.h
c00279
index 21ee889..338e9c0 100644
c00279
--- a/src/sbuf/Algorithms.h
c00279
+++ b/src/sbuf/Algorithms.h
c00279
@@ -81,6 +81,57 @@ SBufContainerJoin(const Container &items, const SBuf& separator)
c00279
     return rv;
c00279
 }
c00279
 
c00279
+/** Join container of SBufs and append to supplied target
c00279
+ *
c00279
+ * append to the target SBuf all elements in the [begin,end) range from
c00279
+ * an iterable container, prefixed by prefix, separated by separator and
c00279
+ * followed by suffix. Prefix and suffix are added also in case of empty
c00279
+ * iterable
c00279
+ *
c00279
+ * \return the modified dest
c00279
+ */
c00279
+template <class ContainerIterator>
c00279
+SBuf&
c00279
+JoinContainerIntoSBuf(SBuf &dest, const ContainerIterator &begin,
c00279
+                      const ContainerIterator &end, const SBuf& separator,
c00279
+                      const SBuf& prefix = SBuf(), const SBuf& suffix = SBuf())
c00279
+{
c00279
+    if (begin == end) {
c00279
+        dest.append(prefix).append(suffix);
c00279
+        return dest;
c00279
+    }
c00279
+
c00279
+    // optimization: pre-calculate needed storage
c00279
+    const SBuf::size_type totalContainerSize =
c00279
+        std::accumulate(begin, end, 0, SBufAddLength(separator)) +
c00279
+        dest.length() + prefix.length() + suffix.length();
c00279
+    SBufReservationRequirements req;
c00279
+    req.minSpace = totalContainerSize;
c00279
+    dest.reserve(req);
c00279
+
c00279
+    auto i = begin;
c00279
+    dest.append(prefix);
c00279
+    dest.append(*i);
c00279
+    ++i;
c00279
+    for (; i != end; ++i)
c00279
+        dest.append(separator).append(*i);
c00279
+    dest.append(suffix);
c00279
+    return dest;
c00279
+}
c00279
+
c00279
+
c00279
+/// convenience wrapper of JoinContainerIntoSBuf with no caller-supplied SBuf
c00279
+template <class ContainerIterator>
c00279
+SBuf
c00279
+JoinContainerToSBuf(const ContainerIterator &begin,
c00279
+                    const ContainerIterator &end, const SBuf& separator,
c00279
+                    const SBuf& prefix = SBuf(), const SBuf& suffix = SBuf())
c00279
+{
c00279
+    SBuf rv;
c00279
+    return JoinContainerIntoSBuf(rv, begin, end, separator, prefix, suffix);
c00279
+}
c00279
+
c00279
+
c00279
 namespace std {
c00279
 /// default hash functor to support std::unordered_map<SBuf,*>
c00279
 template <>