]> git.ipfire.org Git - thirdparty/vectorscan.git/commitdiff
ue2_literal: make nocase member a dynamic_bitset
authorJustin Viiret <justin.viiret@intel.com>
Thu, 10 Aug 2017 05:02:57 +0000 (15:02 +1000)
committerMatthew Barr <matthew.barr@intel.com>
Mon, 18 Sep 2017 03:26:18 +0000 (13:26 +1000)
We were previously using vector<bool>, but dynamic_bitset provides a
faster any() impl

src/util/ue2string.cpp
src/util/ue2string.h

index 02d7b713c4b8e3921750e900b2b4400558a498da..b9cb67f48c357ff53c53a128261fc15a4080ad7b 100644 (file)
@@ -237,12 +237,12 @@ ue2_literal::elem::operator CharReach () const {
 }
 
 ue2_literal::ue2_literal(const std::string &s_in, bool nc_in)
-    : s(nc_in ? toUpperString(s_in) : s_in), nocase(s_in.size(), nc_in) {
+    : s(nc_in ? toUpperString(s_in) : s_in), nocase(s_in.size()) {
     if (nc_in) {
-        // Quash nocase bit for non-alpha chars
+        // Switch on nocase bit for all alpha characters.
         for (size_t i = 0; i < s.length(); i++) {
-            if (!ourisalpha(s[i])) {
-                nocase[i] = false;
+            if (ourisalpha(s[i])) {
+                nocase.set(i);
             }
         }
     }
@@ -255,21 +255,27 @@ ue2_literal ue2_literal::substr(size_type pos, size_type n) const {
     ue2_literal rv;
     rv.s = s.substr(pos, n);
     size_type upper = nocase.size();
-    if (n != string::npos && n + pos < nocase.size()) {
+    if (n != npos && n + pos < nocase.size()) {
         upper = n + pos;
     }
-    rv.nocase.insert(rv.nocase.end(), nocase.begin() + pos,
-                     nocase.begin() + upper);
+
+    rv.nocase.resize(upper - pos, false);
+    for (size_t i = pos; i < upper; i++) {
+        rv.nocase.set(i - pos, nocase.test(i));
+    }
+    assert(s.size() == nocase.size());
     return rv;
 }
 
 ue2_literal &ue2_literal::erase(size_type pos, size_type n) {
     s.erase(pos, n);
-    size_type upper = nocase.size();
-    if (n != string::npos && n + pos < nocase.size()) {
-        upper = n + pos;
+
+    if (n != npos) {
+        for (size_type i = pos + n; i < nocase.size(); i++) {
+            nocase.set(i - n, nocase.test(i));
+        }
     }
-    nocase.erase(nocase.begin() + pos, nocase.begin() + upper);
+    nocase.resize(s.size());
     return *this;
 }
 
@@ -306,29 +312,24 @@ bool ue2_literal::operator<(const ue2_literal &b) const {
     return nocase < b.nocase;
 }
 
-ue2_literal operator+(const ue2_literal &a, const ue2_literal &b) {
-    ue2_literal rv;
-    rv.s = a.s + b.s;
-    rv.nocase = a.nocase;
-    rv.nocase.insert(rv.nocase.end(), b.nocase.begin(), b.nocase.end());
-    return rv;
-}
-
 void ue2_literal::operator+=(const ue2_literal &b) {
     s += b.s;
-    nocase.insert(nocase.end(), b.nocase.begin(), b.nocase.end());
+    size_t prefix = nocase.size();
+    nocase.resize(prefix + b.nocase.size());
+    for (size_t i = 0; i < b.nocase.size(); i++) {
+        nocase.set(prefix + i, b.nocase[i]);
+    }
 }
 
 bool ue2_literal::any_nocase() const {
-    return find(nocase.begin(), nocase.end(), true) != nocase.end();
+    return nocase.any();
 }
 
 void make_nocase(ue2_literal *lit) {
     ue2_literal rv;
 
-    for (ue2_literal::const_iterator it = lit->begin(); it != lit->end();
-         ++it) {
-        rv.push_back(it->c, ourisalpha(it->c));
+    for (const auto &elem: *lit) {
+        rv.push_back(elem.c, ourisalpha(elem.c));
     }
 
     lit->swap(rv);
index 9eef65da1111ed1b19694b3a20baa09a201b503a..703faa2fe4f1ce27c9a4f3a7d481f93cc6562fd9 100644 (file)
 #include "util/charreach.h"
 #include "util/compare.h"
 #include "util/hash.h"
+#include "util/operators.h"
 
 #include <iterator>
 #include <string>
 #include <vector>
 
+#include <boost/dynamic_bitset.hpp>
 #include <boost/iterator/iterator_facade.hpp>
 
 namespace ue2 {
@@ -80,7 +82,7 @@ struct ue2_case_string {
     bool nocase;
 };
 
-struct ue2_literal {
+struct ue2_literal : totally_ordered<ue2_literal> {
 public:
     /// Single element proxy, pointed to by our const_iterator.
     struct elem {
@@ -108,38 +110,37 @@ public:
     private:
         friend class boost::iterator_core_access;
         void increment() {
-            ++it; ++it_nc;
+            ++idx;
         }
         void decrement() {
-            --it; --it_nc;
+            --idx;
         }
         void advance(size_t n) {
-            it += n; it_nc += n;
+            idx += n;
         }
         difference_type distance_to(const const_iterator &other) const {
-            return other.it - it;
+            return other.idx - idx;
         }
         bool equal(const const_iterator &other) const {
-            return it == other.it;
+            return idx == other.idx && lit == other.lit;
         }
         const elem dereference() const {
-            return elem(*it, *it_nc);
+            return elem(lit->s[idx], lit->nocase[idx]);
         }
 
         friend struct ue2_literal;
-        const_iterator(const std::string::const_iterator &it_in,
-                       const std::vector<bool>::const_iterator &it_nc_in)
-            : it(it_in), it_nc(it_nc_in) {}
+        const_iterator(const ue2_literal &lit_in, size_t idx_in)
+            : lit(&lit_in), idx(idx_in) {}
 
-        std::string::const_iterator it;
-        std::vector<bool>::const_iterator it_nc;
+        const ue2_literal *lit = nullptr;
+        size_t idx;
     };
 
     using const_reverse_iterator = std::reverse_iterator<const_iterator>;
+    using size_type = std::string::size_type;
+    static const size_type npos = std::string::npos;
 
-    typedef std::string::size_type size_type;
-
-    ue2_literal() {}
+    ue2_literal() = default;
     ue2_literal(const std::string &s_in, bool nc_in);
     ue2_literal(char c, bool nc_in);
     ue2_literal(const ue2_literal &) = default;
@@ -156,16 +157,16 @@ public:
 
     size_type length() const { return s.length(); }
     bool empty() const { return s.empty(); }
-    ue2_literal substr(size_type pos, size_type n = std::string::npos) const;
+    ue2_literal substr(size_type pos, size_type n = npos) const;
     const char *c_str() const { return s.c_str(); }
     bool any_nocase() const;
 
     const_iterator begin() const {
-        return const_iterator(s.begin(), nocase.begin());
+        return const_iterator(*this, 0);
     }
 
     const_iterator end() const {
-        return const_iterator(s.end(), nocase.end());
+        return const_iterator(*this, s.size());
     }
 
     const_reverse_iterator rbegin() const {
@@ -176,22 +177,23 @@ public:
         return const_reverse_iterator(begin());
     }
 
-    ue2_literal &erase(size_type pos = 0, size_type n = std::string::npos);
+    ue2_literal &erase(size_type pos = 0, size_type n = npos);
     void push_back(const elem &e) {
         push_back(e.c, e.nocase);
     }
 
     void push_back(char c, bool nc);
-    const elem back() const { return elem(*s.rbegin(), nocase.back()); }
-    friend ue2_literal operator+(const ue2_literal &a, const ue2_literal &b);
+    const elem back() const { return *rbegin(); }
+
+    friend ue2_literal operator+(ue2_literal a, const ue2_literal &b) {
+        a += b;
+        return a;
+    }
 
     void operator+=(const ue2_literal &b);
     bool operator==(const ue2_literal &b) const {
         return s == b.s && nocase == b.nocase;
     }
-    bool operator!=(const ue2_literal &b) const {
-        return !(*this == b);
-    }
     bool operator<(const ue2_literal &b) const;
 
     void clear(void) { s.clear(); nocase.clear(); }
@@ -204,8 +206,9 @@ public:
     }
 
 private:
+    friend const_iterator;
     std::string s;
-    std::vector<bool> nocase; /* for trolling value */
+    boost::dynamic_bitset<> nocase;
 };
 
 /// Return a reversed copy of this literal.