forked from OctaForge/libostd
implement a basic CompressedPair for internal container usage (removes code dups)
parent
4d97aa7ac2
commit
e4738e0368
|
@ -207,43 +207,6 @@ struct DefaultDelete<T[]> {
|
||||||
/* box */
|
/* box */
|
||||||
|
|
||||||
namespace detail {
|
namespace detail {
|
||||||
template<typename T, typename U, bool = octa::IsEmpty<U>::value>
|
|
||||||
struct BoxPair;
|
|
||||||
|
|
||||||
template<typename T, typename U>
|
|
||||||
struct BoxPair<T, U, false> { /* non-empty deleter */
|
|
||||||
T *p_ptr;
|
|
||||||
private:
|
|
||||||
U p_del;
|
|
||||||
|
|
||||||
public:
|
|
||||||
template<typename D>
|
|
||||||
BoxPair(T *ptr, D &&dltr): p_ptr(ptr), p_del(octa::forward<D>(dltr)) {}
|
|
||||||
|
|
||||||
U &get_deleter() { return p_del; }
|
|
||||||
const U &get_deleter() const { return p_del; }
|
|
||||||
|
|
||||||
void swap(BoxPair &v) {
|
|
||||||
octa::swap(p_ptr, v.p_ptr);
|
|
||||||
octa::swap(p_del, v.p_del);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename T, typename U>
|
|
||||||
struct BoxPair<T, U, true>: U { /* empty deleter */
|
|
||||||
T *p_ptr;
|
|
||||||
|
|
||||||
template<typename D>
|
|
||||||
BoxPair(T *ptr, D &&dltr): U(octa::forward<D>(dltr)), p_ptr(ptr) {}
|
|
||||||
|
|
||||||
U &get_deleter() { return *this; }
|
|
||||||
const U &get_deleter() const { return *this; }
|
|
||||||
|
|
||||||
void swap(BoxPair &v) {
|
|
||||||
octa::swap(p_ptr, v.p_ptr);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
static int ptr_test(...);
|
static int ptr_test(...);
|
||||||
template<typename T>
|
template<typename T>
|
||||||
|
@ -315,7 +278,7 @@ public:
|
||||||
|
|
||||||
Box &operator=(Box &&u) {
|
Box &operator=(Box &&u) {
|
||||||
reset(u.release());
|
reset(u.release());
|
||||||
p_stor.get_deleter() = octa::forward<D>(u.get_deleter());
|
p_stor.second() = octa::forward<D>(u.get_deleter());
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -326,7 +289,7 @@ public:
|
||||||
Box &
|
Box &
|
||||||
> operator=(Box<TT, DD> &&u) {
|
> operator=(Box<TT, DD> &&u) {
|
||||||
reset(u.release());
|
reset(u.release());
|
||||||
p_stor.get_deleter() = octa::forward<DD>(u.get_deleter());
|
p_stor.second() = octa::forward<DD>(u.get_deleter());
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -337,28 +300,28 @@ public:
|
||||||
|
|
||||||
~Box() { reset(); }
|
~Box() { reset(); }
|
||||||
|
|
||||||
octa::AddLvalueReference<T> operator*() const { return *p_stor.p_ptr; }
|
octa::AddLvalueReference<T> operator*() const { return *p_stor.first(); }
|
||||||
Pointer operator->() const { return p_stor.p_ptr; }
|
Pointer operator->() const { return p_stor.first(); }
|
||||||
|
|
||||||
explicit operator bool() const {
|
explicit operator bool() const {
|
||||||
return p_stor.p_ptr != nullptr;
|
return p_stor.first() != nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
Pointer get() const { return p_stor.p_ptr; }
|
Pointer get() const { return p_stor.first(); }
|
||||||
|
|
||||||
Dref get_deleter() { return p_stor.get_deleter(); }
|
Dref get_deleter() { return p_stor.second(); }
|
||||||
Dcref get_deleter() const { return p_stor.get_deleter(); }
|
Dcref get_deleter() const { return p_stor.second(); }
|
||||||
|
|
||||||
Pointer release() {
|
Pointer release() {
|
||||||
Pointer p = p_stor.p_ptr;
|
Pointer p = p_stor.first();
|
||||||
p_stor.p_ptr = nullptr;
|
p_stor.first() = nullptr;
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
void reset(Pointer p = nullptr) {
|
void reset(Pointer p = nullptr) {
|
||||||
Pointer tmp = p_stor.p_ptr;
|
Pointer tmp = p_stor.first();
|
||||||
p_stor.p_ptr = p;
|
p_stor.first() = p;
|
||||||
if (tmp) p_stor.get_deleter()(tmp);
|
if (tmp) p_stor.second()(tmp);
|
||||||
}
|
}
|
||||||
|
|
||||||
void swap(Box &u) {
|
void swap(Box &u) {
|
||||||
|
@ -366,7 +329,7 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
octa::detail::BoxPair<T, D> p_stor;
|
octa::detail::CompressedPair<T *, D> p_stor;
|
||||||
};
|
};
|
||||||
|
|
||||||
namespace detail {
|
namespace detail {
|
||||||
|
@ -452,7 +415,7 @@ public:
|
||||||
|
|
||||||
Box &operator=(Box &&u) {
|
Box &operator=(Box &&u) {
|
||||||
reset(u.release());
|
reset(u.release());
|
||||||
p_stor.get_deleter() = octa::forward<D>(u.get_deleter());
|
p_stor.second() = octa::forward<D>(u.get_deleter());
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -464,7 +427,7 @@ public:
|
||||||
Box &
|
Box &
|
||||||
> operator=(Box<TT, DD> &&u) {
|
> operator=(Box<TT, DD> &&u) {
|
||||||
reset(u.release());
|
reset(u.release());
|
||||||
p_stor.get_deleter() = octa::forward<DD>(u.get_deleter());
|
p_stor.second() = octa::forward<DD>(u.get_deleter());
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -476,36 +439,36 @@ public:
|
||||||
~Box() { reset(); }
|
~Box() { reset(); }
|
||||||
|
|
||||||
octa::AddLvalueReference<T> operator[](octa::Size idx) const {
|
octa::AddLvalueReference<T> operator[](octa::Size idx) const {
|
||||||
return p_stor.p_ptr[idx];
|
return p_stor.first()[idx];
|
||||||
}
|
}
|
||||||
|
|
||||||
explicit operator bool() const {
|
explicit operator bool() const {
|
||||||
return p_stor.p_ptr != nullptr;
|
return p_stor.first() != nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
Pointer get() const { return p_stor.p_ptr; }
|
Pointer get() const { return p_stor.first(); }
|
||||||
|
|
||||||
Dref get_deleter() { return p_stor.get_deleter(); }
|
Dref get_deleter() { return p_stor.second(); }
|
||||||
Dcref get_deleter() const { return p_stor.get_deleter(); }
|
Dcref get_deleter() const { return p_stor.second(); }
|
||||||
|
|
||||||
Pointer release() {
|
Pointer release() {
|
||||||
Pointer p = p_stor.p_ptr;
|
Pointer p = p_stor.first();
|
||||||
p_stor.p_ptr = nullptr;
|
p_stor.first() = nullptr;
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename U> EnableIf<
|
template<typename U> EnableIf<
|
||||||
octa::detail::SameOrLessCvQualified<U, Pointer>::value, void
|
octa::detail::SameOrLessCvQualified<U, Pointer>::value, void
|
||||||
> reset(U p) {
|
> reset(U p) {
|
||||||
Pointer tmp = p_stor.p_ptr;
|
Pointer tmp = p_stor.first();
|
||||||
p_stor.p_ptr = p;
|
p_stor.first() = p;
|
||||||
if (tmp) p_stor.get_deleter()(tmp);
|
if (tmp) p_stor.second()(tmp);
|
||||||
}
|
}
|
||||||
|
|
||||||
void reset(octa::Nullptr) {
|
void reset(octa::Nullptr) {
|
||||||
Pointer tmp = p_stor.p_ptr;
|
Pointer tmp = p_stor.first();
|
||||||
p_stor.p_ptr = nullptr;
|
p_stor.first() = nullptr;
|
||||||
if (tmp) p_stor.get_deleter()(tmp);
|
if (tmp) p_stor.second()(tmp);
|
||||||
}
|
}
|
||||||
|
|
||||||
void reset() {
|
void reset() {
|
||||||
|
@ -517,7 +480,7 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
octa::detail::BoxPair<T, D> p_stor;
|
octa::detail::CompressedPair<T *, D> p_stor;
|
||||||
};
|
};
|
||||||
|
|
||||||
namespace detail {
|
namespace detail {
|
||||||
|
|
|
@ -133,7 +133,7 @@ private:
|
||||||
|
|
||||||
template<typename T, typename A>
|
template<typename T, typename A>
|
||||||
class StringBase {
|
class StringBase {
|
||||||
octa::Vector<T> p_buf;
|
octa::Vector<T, A> p_buf;
|
||||||
|
|
||||||
void terminate() {
|
void terminate() {
|
||||||
if (p_buf.empty() || (p_buf.back() != '\0')) p_buf.push('\0');
|
if (p_buf.empty() || (p_buf.back() != '\0')) p_buf.push('\0');
|
||||||
|
@ -417,7 +417,7 @@ namespace detail {
|
||||||
n = 0;
|
n = 0;
|
||||||
*(s->data()) = '\0';
|
*(s->data()) = '\0';
|
||||||
}
|
}
|
||||||
*(((octa::Size *)s) + 1) = n + 1;
|
*((octa::Size *)s) = n + 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
119
octa/utility.h
119
octa/utility.h
|
@ -166,6 +166,125 @@ Pair<typename octa::detail::MakePairRet<T>::Type,
|
||||||
>(forward<T>(a), forward<U>(b));;
|
>(forward<T>(a), forward<U>(b));;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace detail {
|
||||||
|
template<typename T, typename U,
|
||||||
|
bool = octa::IsSame<octa::RemoveCv<T>, octa::RemoveCv<U>>::value,
|
||||||
|
bool = octa::IsEmpty<T>::value,
|
||||||
|
bool = octa::IsEmpty<U>::value
|
||||||
|
> struct CompressedPairSwitch;
|
||||||
|
|
||||||
|
/* neither empty */
|
||||||
|
template<typename T, typename U, bool Same>
|
||||||
|
struct CompressedPairSwitch<T, U, Same, false, false> { enum { value = 0 }; };
|
||||||
|
|
||||||
|
/* first empty */
|
||||||
|
template<typename T, typename U, bool Same>
|
||||||
|
struct CompressedPairSwitch<T, U, Same, true, false> { enum { value = 1 }; };
|
||||||
|
|
||||||
|
/* second empty */
|
||||||
|
template<typename T, typename U, bool Same>
|
||||||
|
struct CompressedPairSwitch<T, U, Same, false, true> { enum { value = 2 }; };
|
||||||
|
|
||||||
|
/* both empty, not the same */
|
||||||
|
template<typename T, typename U>
|
||||||
|
struct CompressedPairSwitch<T, U, false, true, true> { enum { value = 3 }; };
|
||||||
|
|
||||||
|
/* both empty and same */
|
||||||
|
template<typename T, typename U>
|
||||||
|
struct CompressedPairSwitch<T, U, true, true, true> { enum { value = 1 }; };
|
||||||
|
|
||||||
|
template<typename T, typename U, octa::Size = CompressedPairSwitch<T, U>::value>
|
||||||
|
struct CompressedPairBase;
|
||||||
|
|
||||||
|
template<typename T, typename U>
|
||||||
|
struct CompressedPairBase<T, U, 0> {
|
||||||
|
T p_first;
|
||||||
|
U p_second;
|
||||||
|
|
||||||
|
CompressedPairBase(T a, U b): p_first(octa::forward<T>(a)),
|
||||||
|
p_second(octa::forward<U>(b)) {}
|
||||||
|
|
||||||
|
T &first() { return p_first; }
|
||||||
|
const T &first() const { return p_first; }
|
||||||
|
|
||||||
|
U &second() { return p_second; }
|
||||||
|
const U &second() const { return p_second; }
|
||||||
|
|
||||||
|
void swap(CompressedPairBase &v) {
|
||||||
|
octa::swap(p_first, v.p_first);
|
||||||
|
octa::swap(p_second, v.p_second);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename T, typename U>
|
||||||
|
struct CompressedPairBase<T, U, 1>: T {
|
||||||
|
U p_second;
|
||||||
|
|
||||||
|
CompressedPairBase(T a, U b): T(octa::forward<T>(a)),
|
||||||
|
p_second(octa::forward<U>(b)) {}
|
||||||
|
|
||||||
|
T &first() { return *this; }
|
||||||
|
const T &first() const { return *this; }
|
||||||
|
|
||||||
|
U &second() { return p_second; }
|
||||||
|
const U &second() const { return p_second; }
|
||||||
|
|
||||||
|
void swap(CompressedPairBase &v) {
|
||||||
|
octa::swap(p_second, v.p_second);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename T, typename U>
|
||||||
|
struct CompressedPairBase<T, U, 2>: U {
|
||||||
|
T p_first;
|
||||||
|
|
||||||
|
CompressedPairBase(T a, U b): U(octa::forward<U>(b)),
|
||||||
|
p_first(octa::forward<T>(a)) {}
|
||||||
|
|
||||||
|
T &first() { return p_first; }
|
||||||
|
const T &first() const { return p_first; }
|
||||||
|
|
||||||
|
U &second() { return *this; }
|
||||||
|
const U &second() const { return *this; }
|
||||||
|
|
||||||
|
void swap(CompressedPairBase &v) {
|
||||||
|
octa::swap(p_first, v.p_first);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename T, typename U>
|
||||||
|
struct CompressedPairBase<T, U, 3>: T, U {
|
||||||
|
CompressedPairBase(T a, U b): T(octa::forward<T>(a)),
|
||||||
|
U(octa::forward<U>(b)) {}
|
||||||
|
|
||||||
|
T &first() { return *this; }
|
||||||
|
const T &first() const { return *this; }
|
||||||
|
|
||||||
|
U &second() { return *this; }
|
||||||
|
const U &second() const { return *this; }
|
||||||
|
|
||||||
|
void swap(CompressedPairBase &) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename T, typename U>
|
||||||
|
struct CompressedPair: CompressedPairBase<T, U> {
|
||||||
|
typedef CompressedPairBase<T, U> Base;
|
||||||
|
|
||||||
|
CompressedPair(T a, U b): Base(octa::forward<T>(a),
|
||||||
|
octa::forward<U>(b)) {}
|
||||||
|
|
||||||
|
T &first() { return Base::first(); }
|
||||||
|
const T &first() const { return Base::first(); }
|
||||||
|
|
||||||
|
U &second() { return Base::second(); }
|
||||||
|
const U &second() const { return Base::second(); }
|
||||||
|
|
||||||
|
void swap(CompressedPair &v) {
|
||||||
|
Base::swap(v);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
} /* namespace detail */
|
||||||
|
|
||||||
} /* namespace octa */
|
} /* namespace octa */
|
||||||
|
|
||||||
#endif
|
#endif
|
210
octa/vector.h
210
octa/vector.h
|
@ -19,56 +19,20 @@
|
||||||
namespace octa {
|
namespace octa {
|
||||||
|
|
||||||
namespace detail {
|
namespace detail {
|
||||||
template<typename A, bool = octa::IsEmpty<A>::value>
|
|
||||||
struct VectorPair;
|
|
||||||
|
|
||||||
template<typename A>
|
|
||||||
struct VectorPair<A, false> { /* non-empty allocator */
|
|
||||||
octa::AllocatorPointer<A> p_ptr;
|
|
||||||
A p_a;
|
|
||||||
|
|
||||||
template<typename U>
|
|
||||||
VectorPair(octa::AllocatorPointer<A> ptr, U &&a): p_ptr(ptr),
|
|
||||||
p_a(octa::forward<U>(a)) {}
|
|
||||||
|
|
||||||
A &get_alloc() { return p_a; }
|
|
||||||
const A &get_alloc() const { return p_a; }
|
|
||||||
|
|
||||||
void swap(VectorPair &v) {
|
|
||||||
octa::swap(p_ptr, v.p_ptr);
|
|
||||||
octa::swap(p_a , v.p_a );
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename A>
|
|
||||||
struct VectorPair<A, true>: A { /* empty allocator */
|
|
||||||
octa::AllocatorPointer<A> p_ptr;
|
|
||||||
|
|
||||||
template<typename U>
|
|
||||||
VectorPair(octa::AllocatorPointer<A> ptr, U &&a):
|
|
||||||
A(octa::forward<U>(a)), p_ptr(ptr) {}
|
|
||||||
|
|
||||||
A &get_alloc() { return *this; }
|
|
||||||
const A &get_alloc() const { return *this; }
|
|
||||||
|
|
||||||
void swap(VectorPair &v) {
|
|
||||||
octa::swap(p_ptr, v.p_ptr);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
} /* namespace detail */
|
} /* namespace detail */
|
||||||
|
|
||||||
template<typename T, typename A = octa::Allocator<T>>
|
template<typename T, typename A = octa::Allocator<T>>
|
||||||
class Vector {
|
class Vector {
|
||||||
using VecPair = octa::detail::VectorPair<A>;
|
using VecPair = octa::detail::CompressedPair<octa::AllocatorPointer<A>, A>;
|
||||||
|
|
||||||
VecPair p_buf;
|
|
||||||
octa::Size p_len, p_cap;
|
octa::Size p_len, p_cap;
|
||||||
|
VecPair p_buf;
|
||||||
|
|
||||||
void insert_base(octa::Size idx, octa::Size n) {
|
void insert_base(octa::Size idx, octa::Size n) {
|
||||||
if (p_len + n > p_cap) reserve(p_len + n);
|
if (p_len + n > p_cap) reserve(p_len + n);
|
||||||
p_len += n;
|
p_len += n;
|
||||||
for (octa::Size i = p_len - 1; i > idx + n - 1; --i) {
|
for (octa::Size i = p_len - 1; i > idx + n - 1; --i) {
|
||||||
p_buf.p_ptr[i] = octa::move(p_buf.p_ptr[i - n]);
|
p_buf.first()[i] = octa::move(p_buf.first()[i - n]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -80,12 +44,12 @@ class Vector {
|
||||||
reserve(l);
|
reserve(l);
|
||||||
p_len = l;
|
p_len = l;
|
||||||
if (octa::IsPod<T>() && octa::IsSame<T, octa::RangeValue<R>>()) {
|
if (octa::IsPod<T>() && octa::IsSame<T, octa::RangeValue<R>>()) {
|
||||||
memcpy(p_buf.p_ptr, &range.front(), range.size());
|
memcpy(p_buf.first(), &range.front(), range.size());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
for (octa::Size i = 0; !range.empty(); range.pop_front()) {
|
for (octa::Size i = 0; !range.empty(); range.pop_front()) {
|
||||||
octa::allocator_construct(p_buf.get_alloc(),
|
octa::allocator_construct(p_buf.second(),
|
||||||
&p_buf.p_ptr[i], range.front());
|
&p_buf.first()[i], range.front());
|
||||||
++i;
|
++i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -97,8 +61,8 @@ class Vector {
|
||||||
octa::Size i = 0;
|
octa::Size i = 0;
|
||||||
for (; !range.empty(); range.pop_front()) {
|
for (; !range.empty(); range.pop_front()) {
|
||||||
reserve(i + 1);
|
reserve(i + 1);
|
||||||
octa::allocator_construct(p_buf.get_alloc(),
|
octa::allocator_construct(p_buf.second(),
|
||||||
&p_buf.p_ptr[i], range.front());
|
&p_buf.first()[i], range.front());
|
||||||
++i;
|
++i;
|
||||||
p_len = i;
|
p_len = i;
|
||||||
}
|
}
|
||||||
|
@ -106,12 +70,12 @@ class Vector {
|
||||||
|
|
||||||
void copy_contents(const Vector &v) {
|
void copy_contents(const Vector &v) {
|
||||||
if (octa::IsPod<T>()) {
|
if (octa::IsPod<T>()) {
|
||||||
memcpy(p_buf.p_ptr, v.p_buf.p_ptr, p_len * sizeof(T));
|
memcpy(p_buf.first(), v.p_buf.first(), p_len * sizeof(T));
|
||||||
} else {
|
} else {
|
||||||
Pointer cur = p_buf.p_ptr, last = p_buf.p_ptr + p_len;
|
Pointer cur = p_buf.first(), last = p_buf.first() + p_len;
|
||||||
Pointer vbuf = v.p_buf.p_ptr;
|
Pointer vbuf = v.p_buf.first();
|
||||||
while (cur != last) {
|
while (cur != last) {
|
||||||
octa::allocator_construct(p_buf.get_alloc(),
|
octa::allocator_construct(p_buf.second(),
|
||||||
cur++, *vbuf++);
|
cur++, *vbuf++);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -133,71 +97,69 @@ public:
|
||||||
>;
|
>;
|
||||||
using Allocator = A;
|
using Allocator = A;
|
||||||
|
|
||||||
Vector(const A &a = A()): p_buf(nullptr, a), p_len(0), p_cap(0) {}
|
Vector(const A &a = A()): p_len(0), p_cap(0), p_buf(nullptr, a) {}
|
||||||
|
|
||||||
explicit Vector(Size n, const T &val = T(),
|
explicit Vector(Size n, const T &val = T(),
|
||||||
const A &al = A()): Vector(al) {
|
const A &al = A()): Vector(al) {
|
||||||
p_buf.p_ptr = octa::allocator_allocate(p_buf.get_alloc(), n);
|
p_buf.first() = octa::allocator_allocate(p_buf.second(), n);
|
||||||
p_len = p_cap = n;
|
p_len = p_cap = n;
|
||||||
Pointer cur = p_buf.p_ptr, last = p_buf.p_ptr + n;
|
Pointer cur = p_buf.first(), last = p_buf.first() + n;
|
||||||
while (cur != last)
|
while (cur != last)
|
||||||
octa::allocator_construct(p_buf.get_alloc(), cur++, val);
|
octa::allocator_construct(p_buf.second(), cur++, val);
|
||||||
}
|
}
|
||||||
|
|
||||||
Vector(const Vector &v): p_buf(nullptr,
|
Vector(const Vector &v): p_len(0), p_cap(0), p_buf(nullptr,
|
||||||
octa::allocator_container_copy(v.p_buf.get_alloc())), p_len(0),
|
octa::allocator_container_copy(v.p_buf.second())) {
|
||||||
p_cap(0) {
|
|
||||||
reserve(v.p_cap);
|
reserve(v.p_cap);
|
||||||
p_len = v.p_len;
|
p_len = v.p_len;
|
||||||
copy_contents(v);
|
copy_contents(v);
|
||||||
}
|
}
|
||||||
|
|
||||||
Vector(const Vector &v, const A &a): p_buf(nullptr, a),
|
Vector(const Vector &v, const A &a): p_len(0), p_cap(0), p_buf(nullptr, a) {
|
||||||
p_len(0), p_cap(0) {
|
|
||||||
reserve(v.p_cap);
|
reserve(v.p_cap);
|
||||||
p_len = v.p_len;
|
p_len = v.p_len;
|
||||||
copy_contents(v);
|
copy_contents(v);
|
||||||
}
|
}
|
||||||
|
|
||||||
Vector(Vector &&v): p_buf(v.p_buf.p_ptr,
|
Vector(Vector &&v): p_len(v.p_len), p_cap(v.p_cap), p_buf(v.p_buf.first(),
|
||||||
octa::move(v.p_buf.get_alloc())), p_len(v.p_len), p_cap(v.p_cap) {
|
octa::move(v.p_buf.second())) {
|
||||||
v.p_buf.p_ptr = nullptr;
|
v.p_buf.first() = nullptr;
|
||||||
v.p_len = v.p_cap = 0;
|
v.p_len = v.p_cap = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
Vector(Vector &&v, const A &a) {
|
Vector(Vector &&v, const A &a) {
|
||||||
if (a != v.a) {
|
if (a != v.a) {
|
||||||
p_buf.get_alloc() = a;
|
p_buf.second() = a;
|
||||||
reserve(v.p_cap);
|
reserve(v.p_cap);
|
||||||
p_len = v.p_len;
|
p_len = v.p_len;
|
||||||
if (octa::IsPod<T>()) {
|
if (octa::IsPod<T>()) {
|
||||||
memcpy(p_buf.p_ptr, v.p_buf.p_ptr, p_len * sizeof(T));
|
memcpy(p_buf.first(), v.p_buf.first(), p_len * sizeof(T));
|
||||||
} else {
|
} else {
|
||||||
Pointer cur = p_buf.p_ptr, last = p_buf.p_ptr + p_len;
|
Pointer cur = p_buf.first(), last = p_buf.first() + p_len;
|
||||||
Pointer vbuf = v.p_buf.p_ptr;
|
Pointer vbuf = v.p_buf.first();
|
||||||
while (cur != last) {
|
while (cur != last) {
|
||||||
octa::allocator_construct(p_buf.get_alloc(), cur++,
|
octa::allocator_construct(p_buf.second(), cur++,
|
||||||
octa::move(*vbuf++));
|
octa::move(*vbuf++));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
new (&p_buf) VecPair(v.p_buf.p_ptr,
|
new (&p_buf) VecPair(v.p_buf.first(),
|
||||||
octa::move(v.p_buf.get_alloc()));
|
octa::move(v.p_buf.second()));
|
||||||
p_len = v.p_len;
|
p_len = v.p_len;
|
||||||
p_cap = v.p_cap;
|
p_cap = v.p_cap;
|
||||||
v.p_buf.p_ptr = nullptr;
|
v.p_buf.first() = nullptr;
|
||||||
v.p_len = v.p_cap = 0;
|
v.p_len = v.p_cap = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
Vector(ConstPointer buf, Size n, const A &a = A()): Vector(a) {
|
Vector(ConstPointer buf, Size n, const A &a = A()): Vector(a) {
|
||||||
reserve(n);
|
reserve(n);
|
||||||
if (octa::IsPod<T>()) {
|
if (octa::IsPod<T>()) {
|
||||||
memcpy(p_buf.p_ptr, buf, n * sizeof(T));
|
memcpy(p_buf.first(), buf, n * sizeof(T));
|
||||||
} else {
|
} else {
|
||||||
for (Size i = 0; i < n; ++i)
|
for (Size i = 0; i < n; ++i)
|
||||||
octa::allocator_construct(p_buf.get_alloc(),
|
octa::allocator_construct(p_buf.second(),
|
||||||
&p_buf.p_ptr[i], buf[i]);
|
&p_buf.first()[i], buf[i]);
|
||||||
}
|
}
|
||||||
p_len = n;
|
p_len = n;
|
||||||
}
|
}
|
||||||
|
@ -212,14 +174,14 @@ public:
|
||||||
|
|
||||||
~Vector() {
|
~Vector() {
|
||||||
clear();
|
clear();
|
||||||
octa::allocator_deallocate(p_buf.get_alloc(), p_buf.p_ptr, p_cap);
|
octa::allocator_deallocate(p_buf.second(), p_buf.first(), p_cap);
|
||||||
}
|
}
|
||||||
|
|
||||||
void clear() {
|
void clear() {
|
||||||
if (p_len > 0 && !octa::IsPod<T>()) {
|
if (p_len > 0 && !octa::IsPod<T>()) {
|
||||||
Pointer cur = p_buf.p_ptr, last = p_buf.p_ptr + p_len;
|
Pointer cur = p_buf.first(), last = p_buf.first() + p_len;
|
||||||
while (cur != last)
|
while (cur != last)
|
||||||
octa::allocator_destroy(p_buf.get_alloc(), cur++);
|
octa::allocator_destroy(p_buf.second(), cur++);
|
||||||
}
|
}
|
||||||
p_len = 0;
|
p_len = 0;
|
||||||
}
|
}
|
||||||
|
@ -235,11 +197,11 @@ public:
|
||||||
|
|
||||||
Vector &operator=(Vector &&v) {
|
Vector &operator=(Vector &&v) {
|
||||||
clear();
|
clear();
|
||||||
octa::allocator_deallocate(p_buf.get_alloc(), p_buf.p_ptr, p_cap);
|
octa::allocator_deallocate(p_buf.second(), p_buf.first(), p_cap);
|
||||||
p_len = v.p_len;
|
p_len = v.p_len;
|
||||||
p_cap = v.p_cap;
|
p_cap = v.p_cap;
|
||||||
p_buf.~VecPair();
|
p_buf.~VecPair();
|
||||||
new (&p_buf) VecPair(v.disown(), octa::move(v.p_buf.get_alloc()));
|
new (&p_buf) VecPair(v.disown(), octa::move(v.p_buf.second()));
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -248,12 +210,12 @@ public:
|
||||||
Size ilen = il.end() - il.begin();
|
Size ilen = il.end() - il.begin();
|
||||||
reserve(ilen);
|
reserve(ilen);
|
||||||
if (octa::IsPod<T>()) {
|
if (octa::IsPod<T>()) {
|
||||||
memcpy(p_buf.p_ptr, il.begin(), ilen);
|
memcpy(p_buf.first(), il.begin(), ilen);
|
||||||
} else {
|
} else {
|
||||||
Pointer tbuf = p_buf.p_ptr, ibuf = il.begin(),
|
Pointer tbuf = p_buf.first(), ibuf = il.begin(),
|
||||||
last = il.end();
|
last = il.end();
|
||||||
while (ibuf != last) {
|
while (ibuf != last) {
|
||||||
octa::allocator_construct(p_buf.get_alloc(),
|
octa::allocator_construct(p_buf.second(),
|
||||||
tbuf++, *ibuf++);
|
tbuf++, *ibuf++);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -274,13 +236,13 @@ public:
|
||||||
p_len = n;
|
p_len = n;
|
||||||
if (octa::IsPod<T>()) {
|
if (octa::IsPod<T>()) {
|
||||||
for (Size i = l; i < p_len; ++i) {
|
for (Size i = l; i < p_len; ++i) {
|
||||||
p_buf.p_ptr[i] = T(v);
|
p_buf.first()[i] = T(v);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Pointer first = p_buf.p_ptr + l;
|
Pointer first = p_buf.first() + l;
|
||||||
Pointer last = p_buf.p_ptr + p_len;
|
Pointer last = p_buf.first() + p_len;
|
||||||
while (first != last)
|
while (first != last)
|
||||||
octa::allocator_construct(p_buf.get_alloc(), first++, v);
|
octa::allocator_construct(p_buf.second(), first++, v);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -292,69 +254,69 @@ public:
|
||||||
} else {
|
} else {
|
||||||
while (p_cap < n) p_cap *= 2;
|
while (p_cap < n) p_cap *= 2;
|
||||||
}
|
}
|
||||||
Pointer tmp = octa::allocator_allocate(p_buf.get_alloc(), p_cap);
|
Pointer tmp = octa::allocator_allocate(p_buf.second(), p_cap);
|
||||||
if (oc > 0) {
|
if (oc > 0) {
|
||||||
if (octa::IsPod<T>()) {
|
if (octa::IsPod<T>()) {
|
||||||
memcpy(tmp, p_buf.p_ptr, p_len * sizeof(T));
|
memcpy(tmp, p_buf.first(), p_len * sizeof(T));
|
||||||
} else {
|
} else {
|
||||||
Pointer cur = p_buf.p_ptr, tcur = tmp,
|
Pointer cur = p_buf.first(), tcur = tmp,
|
||||||
last = tmp + p_len;
|
last = tmp + p_len;
|
||||||
while (tcur != last) {
|
while (tcur != last) {
|
||||||
octa::allocator_construct(p_buf.get_alloc(), tcur++,
|
octa::allocator_construct(p_buf.second(), tcur++,
|
||||||
octa::move(*cur));
|
octa::move(*cur));
|
||||||
octa::allocator_destroy(p_buf.get_alloc(), cur);
|
octa::allocator_destroy(p_buf.second(), cur);
|
||||||
++cur;
|
++cur;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
octa::allocator_deallocate(p_buf.get_alloc(), p_buf.p_ptr, oc);
|
octa::allocator_deallocate(p_buf.second(), p_buf.first(), oc);
|
||||||
}
|
}
|
||||||
p_buf.p_ptr = tmp;
|
p_buf.first() = tmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
T &operator[](Size i) { return p_buf.p_ptr[i]; }
|
T &operator[](Size i) { return p_buf.first()[i]; }
|
||||||
const T &operator[](Size i) const { return p_buf.p_ptr[i]; }
|
const T &operator[](Size i) const { return p_buf.first()[i]; }
|
||||||
|
|
||||||
T &at(Size i) { return p_buf.p_ptr[i]; }
|
T &at(Size i) { return p_buf.first()[i]; }
|
||||||
const T &at(Size i) const { return p_buf.p_ptr[i]; }
|
const T &at(Size i) const { return p_buf.first()[i]; }
|
||||||
|
|
||||||
T &push(const T &v) {
|
T &push(const T &v) {
|
||||||
if (p_len == p_cap) reserve(p_len + 1);
|
if (p_len == p_cap) reserve(p_len + 1);
|
||||||
octa::allocator_construct(p_buf.get_alloc(),
|
octa::allocator_construct(p_buf.second(),
|
||||||
&p_buf.p_ptr[p_len], v);
|
&p_buf.first()[p_len], v);
|
||||||
return p_buf.p_ptr[p_len++];
|
return p_buf.first()[p_len++];
|
||||||
}
|
}
|
||||||
|
|
||||||
T &push() {
|
T &push() {
|
||||||
if (p_len == p_cap) reserve(p_len + 1);
|
if (p_len == p_cap) reserve(p_len + 1);
|
||||||
octa::allocator_construct(p_buf.get_alloc(), &p_buf.p_ptr[p_len]);
|
octa::allocator_construct(p_buf.second(), &p_buf.first()[p_len]);
|
||||||
return p_buf.p_ptr[p_len++];
|
return p_buf.first()[p_len++];
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename ...U>
|
template<typename ...U>
|
||||||
T &emplace_back(U &&...args) {
|
T &emplace_back(U &&...args) {
|
||||||
if (p_len == p_cap) reserve(p_len + 1);
|
if (p_len == p_cap) reserve(p_len + 1);
|
||||||
octa::allocator_construct(p_buf.get_alloc(), &p_buf.p_ptr[p_len],
|
octa::allocator_construct(p_buf.second(), &p_buf.first()[p_len],
|
||||||
octa::forward<U>(args)...);
|
octa::forward<U>(args)...);
|
||||||
return p_buf.p_ptr[p_len++];
|
return p_buf.first()[p_len++];
|
||||||
}
|
}
|
||||||
|
|
||||||
void pop() {
|
void pop() {
|
||||||
if (!octa::IsPod<T>()) {
|
if (!octa::IsPod<T>()) {
|
||||||
octa::allocator_destroy(p_buf.get_alloc(),
|
octa::allocator_destroy(p_buf.second(),
|
||||||
&p_buf.p_ptr[--p_len]);
|
&p_buf.first()[--p_len]);
|
||||||
} else {
|
} else {
|
||||||
--p_len;
|
--p_len;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
T &front() { return p_buf.p_ptr[0]; }
|
T &front() { return p_buf.first()[0]; }
|
||||||
const T &front() const { return p_buf.p_ptr[0]; }
|
const T &front() const { return p_buf.first()[0]; }
|
||||||
|
|
||||||
T &back() { return p_buf.p_ptr[p_len - 1]; }
|
T &back() { return p_buf.first()[p_len - 1]; }
|
||||||
const T &back() const { return p_buf.p_ptr[p_len - 1]; }
|
const T &back() const { return p_buf.first()[p_len - 1]; }
|
||||||
|
|
||||||
Pointer data() { return p_buf.p_ptr; }
|
Pointer data() { return p_buf.first(); }
|
||||||
ConstPointer data() const { return p_buf.p_ptr; }
|
ConstPointer data() const { return p_buf.first(); }
|
||||||
|
|
||||||
Size size() const { return p_len; }
|
Size size() const { return p_len; }
|
||||||
Size capacity() const { return p_cap; }
|
Size capacity() const { return p_cap; }
|
||||||
|
@ -364,34 +326,34 @@ public:
|
||||||
bool in_range(Size idx) { return idx < p_len; }
|
bool in_range(Size idx) { return idx < p_len; }
|
||||||
bool in_range(int idx) { return idx >= 0 && Size(idx) < p_len; }
|
bool in_range(int idx) { return idx >= 0 && Size(idx) < p_len; }
|
||||||
bool in_range(ConstPointer ptr) {
|
bool in_range(ConstPointer ptr) {
|
||||||
return ptr >= p_buf.p_ptr && ptr < &p_buf.p_ptr[p_len];
|
return ptr >= p_buf.first() && ptr < &p_buf.first()[p_len];
|
||||||
}
|
}
|
||||||
|
|
||||||
Pointer disown() {
|
Pointer disown() {
|
||||||
Pointer r = p_buf.p_ptr;
|
Pointer r = p_buf.first();
|
||||||
p_buf.p_ptr = nullptr;
|
p_buf.first() = nullptr;
|
||||||
p_len = p_cap = 0;
|
p_len = p_cap = 0;
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
Range insert(Size idx, T &&v) {
|
Range insert(Size idx, T &&v) {
|
||||||
insert_base(idx, 1);
|
insert_base(idx, 1);
|
||||||
p_buf.p_ptr[idx] = octa::move(v);
|
p_buf.first()[idx] = octa::move(v);
|
||||||
return Range(&p_buf.p_ptr[idx], &p_buf.p_ptr[p_len]);
|
return Range(&p_buf.first()[idx], &p_buf.first()[p_len]);
|
||||||
}
|
}
|
||||||
|
|
||||||
Range insert(Size idx, const T &v) {
|
Range insert(Size idx, const T &v) {
|
||||||
insert_base(idx, 1);
|
insert_base(idx, 1);
|
||||||
p_buf.p_ptr[idx] = v;
|
p_buf.first()[idx] = v;
|
||||||
return Range(&p_buf.p_ptr[idx], &p_buf.p_ptr[p_len]);
|
return Range(&p_buf.first()[idx], &p_buf.first()[p_len]);
|
||||||
}
|
}
|
||||||
|
|
||||||
Range insert(Size idx, Size n, const T &v) {
|
Range insert(Size idx, Size n, const T &v) {
|
||||||
insert_base(idx, n);
|
insert_base(idx, n);
|
||||||
for (Size i = 0; i < n; ++i) {
|
for (Size i = 0; i < n; ++i) {
|
||||||
p_buf.p_ptr[idx + i] = v;
|
p_buf.first()[idx + i] = v;
|
||||||
}
|
}
|
||||||
return Range(&p_buf.p_ptr[idx], &p_buf.p_ptr[p_len]);
|
return Range(&p_buf.first()[idx], &p_buf.first()[p_len]);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename U>
|
template<typename U>
|
||||||
|
@ -399,10 +361,10 @@ public:
|
||||||
Size l = range.size();
|
Size l = range.size();
|
||||||
insert_base(idx, l);
|
insert_base(idx, l);
|
||||||
for (Size i = 0; i < l; ++i) {
|
for (Size i = 0; i < l; ++i) {
|
||||||
p_buf.p_ptr[idx + i] = range.front();
|
p_buf.first()[idx + i] = range.front();
|
||||||
range.pop_front();
|
range.pop_front();
|
||||||
}
|
}
|
||||||
return Range(&p_buf.p_ptr[idx], &p_buf.p_ptr[p_len]);
|
return Range(&p_buf.first()[idx], &p_buf.first()[p_len]);
|
||||||
}
|
}
|
||||||
|
|
||||||
Range insert(Size idx, InitializerList<T> il) {
|
Range insert(Size idx, InitializerList<T> il) {
|
||||||
|
@ -410,13 +372,13 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
Range each() {
|
Range each() {
|
||||||
return Range(p_buf.p_ptr, p_buf.p_ptr + p_len);
|
return Range(p_buf.first(), p_buf.first() + p_len);
|
||||||
}
|
}
|
||||||
ConstRange each() const {
|
ConstRange each() const {
|
||||||
return ConstRange(p_buf.p_ptr, p_buf.p_ptr + p_len);
|
return ConstRange(p_buf.first(), p_buf.first() + p_len);
|
||||||
}
|
}
|
||||||
ConstRange ceach() const {
|
ConstRange ceach() const {
|
||||||
return ConstRange(p_buf.p_ptr, p_buf.p_ptr + p_len);
|
return ConstRange(p_buf.first(), p_buf.first() + p_len);
|
||||||
}
|
}
|
||||||
|
|
||||||
void swap(Vector &v) {
|
void swap(Vector &v) {
|
||||||
|
@ -426,7 +388,7 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
A get_allocator() const {
|
A get_allocator() const {
|
||||||
return p_buf.get_alloc();
|
return p_buf.second();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue