}
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);
}
}
}
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;
}
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);
#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 {
bool nocase;
};
-struct ue2_literal {
+struct ue2_literal : totally_ordered<ue2_literal> {
public:
/// Single element proxy, pointed to by our const_iterator.
struct elem {
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;
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 {
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(); }
}
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.