add StringRange (provides hashing and proper ToString), make it the range for String, add extra ptr-ctor for Vector and new ctors for String, optimizations

master
Daniel Kolesa 2015-06-09 18:59:25 +01:00
parent 13b8b06d33
commit 1553e2d30f
3 changed files with 159 additions and 16 deletions

View File

@ -636,6 +636,10 @@ struct PointerRange: InputRange<PointerRange<T>, FiniteRandomAccessRangeTag, T>
*(p_beg++) = octa::move(v);
}
/* non-range methods */
T *data() { return p_beg; }
const T *data() const { return p_beg; }
private:
T *p_beg, *p_end;
};

View File

@ -16,7 +16,122 @@
namespace octa {
static constexpr octa::Size npos = -1;
template<typename T, typename A = octa::Allocator<T>>
template<typename T, typename A = octa::Allocator<T>> class StringBase;
template<typename T>
struct StringRangeBase: InputRange<
StringRangeBase<T>, FiniteRandomAccessRangeTag, T
> {
StringRangeBase(): p_beg(nullptr), p_end(nullptr) {}
StringRangeBase(const StringRangeBase &v): p_beg(v.p_beg),
p_end(v.p_end) {}
StringRangeBase(T *beg, T *end): p_beg(beg), p_end(end) {}
StringRangeBase(T *beg, octa::Size n): p_beg(beg), p_end(beg + n) {}
/* TODO: traits for utf-16/utf-32 string lengths, for now assume char */
StringRangeBase(T *beg): p_beg(beg), p_end(beg + strlen(beg)) {}
StringRangeBase(const StringBase<T> &s): p_beg(s.data()),
p_end(s.data() + s.size()) {}
StringRangeBase &operator=(const StringRangeBase &v) {
p_beg = v.p_beg; p_end = v.p_end; return *this;
}
StringRangeBase &operator=(const StringBase<T> &s) {
p_beg = s.data(); p_end = s.data() + s.size(); return *this;
}
/* TODO: traits for utf-16/utf-32 string lengths, for now assume char */
StringRangeBase &operator=(T *s) {
p_beg = s; p_end = s + strlen(s); return *this;
}
bool empty() const { return p_beg == p_end; }
bool pop_front() {
if (p_beg == p_end) return false;
++p_beg;
return true;
}
bool push_front() { --p_beg; return true; }
octa::Size pop_front_n(octa::Size n) {
octa::Size olen = p_end - p_beg;
p_beg += n;
if (p_beg > p_end) {
p_beg = p_end;
return olen;
}
return n;
}
octa::Size push_front_n(octa::Size n) { p_beg -= n; return true; }
T &front() const { return *p_beg; }
bool equals_front(const StringRangeBase &range) const {
return p_beg == range.p_beg;
}
octa::Ptrdiff distance_front(const StringRangeBase &range) const {
return range.p_beg - p_beg;
}
bool pop_back() {
if (p_end == p_beg) return false;
--p_end;
return true;
}
bool push_back() { ++p_end; return true; }
octa::Size pop_back_n(octa::Size n) {
octa::Size olen = p_end - p_beg;
p_end -= n;
if (p_end < p_beg) {
p_end = p_beg;
return olen;
}
return n;
}
octa::Size push_back_n(octa::Size n) { p_end += n; return true; }
T &back() const { return *(p_end - 1); }
bool equals_back(const StringRangeBase &range) const {
return p_end == range.p_end;
}
octa::Ptrdiff distance_back(const StringRangeBase &range) const {
return range.p_end - p_end;
}
octa::Size size() const { return p_end - p_beg; }
StringRangeBase slice(octa::Size start, octa::Size end) const {
return StringRangeBase(p_beg + start, p_beg + end);
}
T &operator[](octa::Size i) const { return p_beg[i]; }
void put(T v) {
*(p_beg++) = v;
}
/* non-range methods */
T *data() { return p_beg; }
const T *data() const { return p_beg; }
octa::Size to_hash() const {
const T *d = data();
Size h = 5381, len = size();
for (Size i = 0; i < len; ++i)
h = ((h << 5) + h) ^ d[i];
return h;
}
private:
T *p_beg, *p_end;
};
template<typename T, typename A>
class StringBase {
octa::Vector<T> p_buf;
@ -32,8 +147,8 @@ public:
using ConstReference = const T &;
using Pointer = T *;
using ConstPointer = const T *;
using Range = octa::PointerRange<T>;
using ConstRange = octa::PointerRange<const T>;
using Range = octa::StringRangeBase<T>;
using ConstRange = octa::StringRangeBase<const T>;
using Allocator = A;
StringBase(const A &a = A()): p_buf(1, '\0', a) {}
@ -56,6 +171,9 @@ public:
StringBase(const T *v, const A &a = A()):
p_buf(ConstRange(v, strlen(v) + 1), a) {}
StringBase(const T *v, Size n, const A &a = A()):
p_buf(ConstRange(v, n), a) {}
template<typename R> StringBase(R range, const A &a = A()):
p_buf(range, a) {
terminate();
@ -75,6 +193,11 @@ public:
p_buf = ConstRange(v, strlen(v) + 1);
return *this;
}
StringBase<T> &operator=(const Range &r) {
p_buf = r;
terminate();
return *this;
}
void resize(octa::Size n, T v = T()) {
p_buf.pop();
@ -177,15 +300,13 @@ public:
}
Size to_hash() const {
const T *d = data();
Size h = 5381, len = size();
for (Size i = 0; i < len; ++i)
h = ((h << 5) + h) ^ d[i];
return h;
return each().to_hash();
}
};
using String = StringBase<char>;
using StringRange = StringRangeBase<char>;
using ConstStringRange = StringRangeBase<const char>;
template<typename T, typename F>
String concat(const T v, const String &sep, F func) {
@ -354,6 +475,14 @@ template<> struct ToString<String> {
}
};
template<> struct ToString<StringRange> {
using Argument = const StringRange &;
using Result = String;
String operator()(Argument s) {
return String(s);
}
};
template<typename T, typename U> struct ToString<octa::Pair<T, U>> {
using Argument = const octa::Pair<T, U> &;
using Result = String;

View File

@ -79,6 +79,10 @@ class Vector {
octa::RangeSize<R> l = range.size();
reserve(l);
p_len = l;
if (octa::IsPod<T>() && octa::IsSame<T, octa::RangeValue<R>>()) {
memcpy(p_buf.p_ptr, &range.front(), range.size());
return;
}
for (octa::Size i = 0; !range.empty(); range.pop_front()) {
octa::allocator_construct(p_buf.get_alloc(),
&p_buf.p_ptr[i], range.front());
@ -182,16 +186,21 @@ public:
v.p_len = v.p_cap = 0;
}
Vector(InitializerList<T> v, const A &a = A()): Vector(a) {
Size l = v.end() - v.begin();
const T *ptr = v.begin();
reserve(l);
for (Size i = 0; i < l; ++i)
octa::allocator_construct(p_buf.get_alloc(),
&p_buf.p_ptr[i], ptr[i]);
p_len = l;
Vector(const T *buf, Size n, const A &a = A()): Vector(a) {
reserve(n);
if (octa::IsPod<T>()) {
memcpy(p_buf.p_ptr, buf, n * sizeof(T));
} else {
for (Size i = 0; i < n; ++i)
octa::allocator_construct(p_buf.get_alloc(),
&p_buf.p_ptr[i], buf[i]);
}
p_len = n;
}
Vector(InitializerList<T> v, const A &a = A()):
Vector(v.begin(), v.size(), a) {}
template<typename R> Vector(R range, const A &a = A()):
Vector(a) {
ctor_from_range(range);
@ -252,6 +261,7 @@ public:
Vector &operator=(R range) {
clear();
ctor_from_range(range);
return *this;
}
void resize(Size n, const T &v = T()) {