forked from OctaForge/libostd
get rid of full namespace where unambiguous resolution is guaranteed
This commit is contained in:
parent
d2aba4d5b6
commit
1654ee84db
|
@ -42,25 +42,25 @@ bool is_partitioned(R range, P pred) {
|
|||
namespace detail {
|
||||
template<typename R, typename C>
|
||||
void insort(R range, C compare) {
|
||||
octa::RangeSize<R> rlen = range.size();
|
||||
for (octa::RangeSize<R> i = 1; i < rlen; ++i) {
|
||||
octa::RangeSize<R> j = i;
|
||||
octa::RangeValue<R> v(octa::move(range[i]));
|
||||
RangeSize<R> rlen = range.size();
|
||||
for (RangeSize<R> i = 1; i < rlen; ++i) {
|
||||
RangeSize<R> j = i;
|
||||
RangeValue<R> v(move(range[i]));
|
||||
while (j > 0 && !compare(range[j - 1], v)) {
|
||||
range[j] = range[j - 1];
|
||||
--j;
|
||||
}
|
||||
range[j] = octa::move(v);
|
||||
range[j] = move(v);
|
||||
}
|
||||
}
|
||||
|
||||
template<typename R, typename C>
|
||||
void hs_sift_down(R range, octa::RangeSize<R> s,
|
||||
octa::RangeSize<R> e, C compare) {
|
||||
octa::RangeSize<R> r = s;
|
||||
void hs_sift_down(R range, RangeSize<R> s,
|
||||
RangeSize<R> e, C compare) {
|
||||
RangeSize<R> r = s;
|
||||
while ((r * 2 + 1) <= e) {
|
||||
octa::RangeSize<R> ch = r * 2 + 1;
|
||||
octa::RangeSize<R> sw = r;
|
||||
RangeSize<R> ch = r * 2 + 1;
|
||||
RangeSize<R> sw = r;
|
||||
if (compare(range[sw], range[ch]))
|
||||
sw = ch;
|
||||
if (((ch + 1) <= e) && compare(range[sw], range[ch + 1]))
|
||||
|
@ -74,32 +74,32 @@ namespace detail {
|
|||
|
||||
template<typename R, typename C>
|
||||
void heapsort(R range, C compare) {
|
||||
octa::RangeSize<R> len = range.size();
|
||||
octa::RangeSize<R> st = (len - 2) / 2;
|
||||
RangeSize<R> len = range.size();
|
||||
RangeSize<R> st = (len - 2) / 2;
|
||||
for (;;) {
|
||||
octa::detail::hs_sift_down(range, st, len - 1, compare);
|
||||
detail::hs_sift_down(range, st, len - 1, compare);
|
||||
if (st-- == 0) break;
|
||||
}
|
||||
octa::RangeSize<R> e = len - 1;
|
||||
RangeSize<R> e = len - 1;
|
||||
while (e > 0) {
|
||||
octa::swap(range[e], range[0]);
|
||||
--e;
|
||||
octa::detail::hs_sift_down(range, 0, e, compare);
|
||||
detail::hs_sift_down(range, 0, e, compare);
|
||||
}
|
||||
}
|
||||
|
||||
template<typename R, typename C>
|
||||
void introloop(R range, C compare, RangeSize<R> depth) {
|
||||
if (range.size() <= 10) {
|
||||
octa::detail::insort(range, compare);
|
||||
detail::insort(range, compare);
|
||||
return;
|
||||
}
|
||||
if (depth == 0) {
|
||||
octa::detail::heapsort(range, compare);
|
||||
detail::heapsort(range, compare);
|
||||
return;
|
||||
}
|
||||
octa::swap(range[range.size() / 2], range.back());
|
||||
octa::RangeSize<R> pi = 0;
|
||||
RangeSize<R> pi = 0;
|
||||
R pr = range;
|
||||
pr.pop_back();
|
||||
for (; !pr.empty(); pr.pop_front()) {
|
||||
|
@ -107,26 +107,26 @@ namespace detail {
|
|||
octa::swap(pr.front(), range[pi++]);
|
||||
}
|
||||
octa::swap(range[pi], range.back());
|
||||
octa::detail::introloop(range.slice(0, pi), compare, depth - 1);
|
||||
octa::detail::introloop(range.slice(pi + 1, range.size()), compare,
|
||||
detail::introloop(range.slice(0, pi), compare, depth - 1);
|
||||
detail::introloop(range.slice(pi + 1, range.size()), compare,
|
||||
depth - 1);
|
||||
}
|
||||
|
||||
template<typename R, typename C>
|
||||
void introsort(R range, C compare) {
|
||||
octa::detail::introloop(range, compare, octa::RangeSize<R>(2
|
||||
detail::introloop(range, compare, RangeSize<R>(2
|
||||
* (log(range.size()) / log(2))));
|
||||
}
|
||||
} /* namespace detail */
|
||||
|
||||
template<typename R, typename C>
|
||||
void sort(R range, C compare) {
|
||||
octa::detail::introsort(range, compare);
|
||||
detail::introsort(range, compare);
|
||||
}
|
||||
|
||||
template<typename R>
|
||||
void sort(R range) {
|
||||
sort(range, octa::Less<RangeValue<R>>());
|
||||
sort(range, Less<RangeValue<R>>());
|
||||
}
|
||||
|
||||
/* min/max(_element) */
|
||||
|
@ -220,7 +220,7 @@ template<typename R, typename F>
|
|||
F for_each(R range, F func) {
|
||||
for (; !range.empty(); range.pop_front())
|
||||
func(range.front());
|
||||
return octa::move(func);
|
||||
return move(func);
|
||||
}
|
||||
|
||||
template<typename R, typename P>
|
||||
|
@ -333,7 +333,7 @@ R2 copy_if_not(R1 irange, R2 orange, P pred) {
|
|||
template<typename R1, typename R2>
|
||||
R2 move(R1 irange, R2 orange) {
|
||||
for (; !irange.empty(); irange.pop_front())
|
||||
orange.put(octa::move(irange.front()));
|
||||
orange.put(move(irange.front()));
|
||||
return orange;
|
||||
}
|
||||
|
||||
|
@ -366,7 +366,7 @@ void generate(R range, F gen) {
|
|||
}
|
||||
|
||||
template<typename R1, typename R2>
|
||||
octa::Pair<R1, R2> swap_ranges(R1 range1, R2 range2) {
|
||||
Pair<R1, R2> swap_ranges(R1 range1, R2 range2) {
|
||||
while (!range1.empty() && !range2.empty()) {
|
||||
octa::swap(range1.front(), range2.front());
|
||||
range1.pop_front();
|
||||
|
@ -411,11 +411,11 @@ T foldr(R range, T init, F func) {
|
|||
|
||||
template<typename T, typename F, typename R>
|
||||
struct MapRange: InputRange<
|
||||
MapRange<T, F, R>, octa::RangeCategory<T>, R, R, octa::RangeSize<T>
|
||||
MapRange<T, F, R>, RangeCategory<T>, R, R, RangeSize<T>
|
||||
> {
|
||||
private:
|
||||
T p_range;
|
||||
octa::FunctionMakeDefaultConstructible<F> p_func;
|
||||
FunctionMakeDefaultConstructible<F> p_func;
|
||||
|
||||
public:
|
||||
MapRange() = delete;
|
||||
|
@ -438,7 +438,7 @@ public:
|
|||
}
|
||||
|
||||
bool empty() const { return p_range.empty(); }
|
||||
octa::RangeSize<T> size() const { return p_range.size(); }
|
||||
RangeSize<T> size() const { return p_range.size(); }
|
||||
|
||||
bool equals_front(const MapRange &r) const {
|
||||
return p_range.equals_front(r.p_range);
|
||||
|
@ -447,10 +447,10 @@ public:
|
|||
return p_range.equals_front(r.p_range);
|
||||
}
|
||||
|
||||
octa::RangeDifference<T> distance_front(const MapRange &r) const {
|
||||
RangeDifference<T> distance_front(const MapRange &r) const {
|
||||
return p_range.distance_front(r.p_range);
|
||||
}
|
||||
octa::RangeDifference<T> distance_back(const MapRange &r) const {
|
||||
RangeDifference<T> distance_back(const MapRange &r) const {
|
||||
return p_range.distance_back(r.p_range);
|
||||
}
|
||||
|
||||
|
@ -460,54 +460,51 @@ public:
|
|||
bool push_front() { return p_range.pop_front(); }
|
||||
bool push_back() { return p_range.push_back(); }
|
||||
|
||||
octa::RangeSize<T> pop_front_n(octa::RangeSize<T> n) {
|
||||
RangeSize<T> pop_front_n(RangeSize<T> n) {
|
||||
p_range.pop_front_n(n);
|
||||
}
|
||||
octa::RangeSize<T> pop_back_n(octa::RangeSize<T> n) {
|
||||
RangeSize<T> pop_back_n(RangeSize<T> n) {
|
||||
p_range.pop_back_n(n);
|
||||
}
|
||||
|
||||
octa::RangeSize<T> push_front_n(octa::RangeSize<T> n) {
|
||||
RangeSize<T> push_front_n(RangeSize<T> n) {
|
||||
return p_range.push_front_n(n);
|
||||
}
|
||||
octa::RangeSize<T> push_back_n(octa::RangeSize<T> n) {
|
||||
RangeSize<T> push_back_n(RangeSize<T> n) {
|
||||
return p_range.push_back_n(n);
|
||||
}
|
||||
|
||||
R front() const { return p_func(p_range.front()); }
|
||||
R back() const { return p_func(p_range.back()); }
|
||||
|
||||
R operator[](octa::RangeSize<T> idx) const {
|
||||
R operator[](RangeSize<T> idx) const {
|
||||
return p_func(p_range[idx]);
|
||||
}
|
||||
|
||||
MapRange slice(octa::RangeSize<T> start,
|
||||
octa::RangeSize<T> end) {
|
||||
MapRange slice(RangeSize<T> start, RangeSize<T> end) {
|
||||
return MapRange(p_range.slice(start, end), p_func);
|
||||
}
|
||||
};
|
||||
|
||||
namespace detail {
|
||||
template<typename R, typename F> using MapReturnType
|
||||
= decltype(declval<F>()(octa::declval<octa::RangeReference<R>>()));
|
||||
= decltype(declval<F>()(declval<RangeReference<R>>()));
|
||||
}
|
||||
|
||||
template<typename R, typename F>
|
||||
MapRange<R, F, octa::detail::MapReturnType<R, F>> map(R range,
|
||||
F func) {
|
||||
return octa::MapRange<R, F, octa::detail::MapReturnType<R, F>>(range,
|
||||
MapRange<R, F, detail::MapReturnType<R, F>> map(R range, F func) {
|
||||
return MapRange<R, F, detail::MapReturnType<R, F>>(range,
|
||||
func);
|
||||
}
|
||||
|
||||
template<typename T, typename F>
|
||||
struct FilterRange: InputRange<
|
||||
FilterRange<T, F>, octa::CommonType<octa::RangeCategory<T>,
|
||||
octa::ForwardRangeTag>,
|
||||
octa::RangeValue<T>, octa::RangeReference<T>, octa::RangeSize<T>
|
||||
FilterRange<T, F>, CommonType<RangeCategory<T>, ForwardRangeTag>,
|
||||
RangeValue<T>, RangeReference<T>, RangeSize<T>
|
||||
> {
|
||||
private:
|
||||
T p_range;
|
||||
octa::FunctionMakeDefaultConstructible<F> p_pred;
|
||||
FunctionMakeDefaultConstructible<F> p_pred;
|
||||
|
||||
void advance_valid() {
|
||||
while (!p_range.empty() && !p_pred(front())) p_range.pop_front();
|
||||
|
@ -554,22 +551,19 @@ public:
|
|||
return ret;
|
||||
}
|
||||
|
||||
octa::RangeReference<T> front() const { return p_range.front(); }
|
||||
RangeReference<T> front() const { return p_range.front(); }
|
||||
};
|
||||
|
||||
namespace detail {
|
||||
template<typename R, typename P> using FilterPred
|
||||
= octa::EnableIf<IsSame<
|
||||
decltype(octa::declval<P>()(octa::declval<
|
||||
octa::RangeReference<R>
|
||||
>())),
|
||||
bool
|
||||
= EnableIf<IsSame<
|
||||
decltype(declval<P>()(declval<RangeReference<R>>())), bool
|
||||
>::value, P>;
|
||||
}
|
||||
|
||||
template<typename R, typename P>
|
||||
FilterRange<R, octa::detail::FilterPred<R, P>> filter(R range, P pred) {
|
||||
return octa::FilterRange<R, P>(range, pred);
|
||||
FilterRange<R, detail::FilterPred<R, P>> filter(R range, P pred) {
|
||||
return FilterRange<R, P>(range, pred);
|
||||
}
|
||||
|
||||
} /* namespace octa */
|
||||
|
|
|
@ -14,17 +14,17 @@
|
|||
|
||||
namespace octa {
|
||||
|
||||
template<typename T, octa::Size N>
|
||||
template<typename T, Size N>
|
||||
struct Array {
|
||||
using Size = octa::Size;
|
||||
using Difference = octa::Ptrdiff;
|
||||
using Size = Size;
|
||||
using Difference = Ptrdiff;
|
||||
using Value = T;
|
||||
using Reference = T &;
|
||||
using ConstReference = const T &;
|
||||
using Pointer = T *;
|
||||
using ConstPointer = const T *;
|
||||
using Range = octa::PointerRange<T>;
|
||||
using ConstRange = octa::PointerRange<const T>;
|
||||
using Range = PointerRange<T>;
|
||||
using ConstRange = PointerRange<const T>;
|
||||
|
||||
T &operator[](Size i) { return p_buf[i]; }
|
||||
const T &operator[](Size i) const { return p_buf[i]; }
|
||||
|
|
217
octa/atomic.hh
217
octa/atomic.hh
|
@ -115,7 +115,7 @@ namespace detail {
|
|||
__atomic_signal_fence(to_gcc_order(ord));
|
||||
}
|
||||
|
||||
static inline bool atomic_is_lock_free(octa::Size size) {
|
||||
static inline bool atomic_is_lock_free(Size size) {
|
||||
/* return __atomic_is_lock_free(size, 0); cannot be used on some platforms */
|
||||
return size <= sizeof(void *);
|
||||
}
|
||||
|
@ -201,13 +201,13 @@ namespace detail {
|
|||
}
|
||||
|
||||
template<typename T>
|
||||
struct SkipAmt { static constexpr octa::Size value = 1; };
|
||||
struct SkipAmt { static constexpr Size value = 1; };
|
||||
|
||||
template<typename T>
|
||||
struct SkipAmt<T *> { static constexpr octa::Size value = sizeof(T); };
|
||||
struct SkipAmt<T *> { static constexpr Size value = sizeof(T); };
|
||||
|
||||
template<typename T> struct SkipAmt<T[]> {};
|
||||
template<typename T, octa::Size N> struct SkipAmt<T[N]> {};
|
||||
template<typename T, Size N> struct SkipAmt<T[N]> {};
|
||||
|
||||
template<typename T, typename U>
|
||||
static inline T atomic_fetch_add(volatile AtomicBase<T> *a,
|
||||
|
@ -288,8 +288,7 @@ template <typename T> inline T kill_dependency(T v) {
|
|||
}
|
||||
|
||||
namespace detail {
|
||||
template<typename T, bool = octa::IsIntegral<T>::value &&
|
||||
!octa::IsSame<T, bool>::value>
|
||||
template<typename T, bool = IsIntegral<T>::value && !IsSame<T, bool>::value>
|
||||
struct Atomic {
|
||||
mutable AtomicBase<T> p_a;
|
||||
|
||||
|
@ -451,8 +450,8 @@ namespace detail {
|
|||
}
|
||||
|
||||
template<typename T>
|
||||
struct Atomic: octa::detail::Atomic<T> {
|
||||
using Base = octa::detail::Atomic<T>;
|
||||
struct Atomic: detail::Atomic<T> {
|
||||
using Base = detail::Atomic<T>;
|
||||
|
||||
Atomic() = default;
|
||||
|
||||
|
@ -468,8 +467,8 @@ struct Atomic: octa::detail::Atomic<T> {
|
|||
};
|
||||
|
||||
template<typename T>
|
||||
struct Atomic<T *>: octa::detail::Atomic<T *> {
|
||||
using Base = octa::detail::Atomic<T *>;
|
||||
struct Atomic<T *>: detail::Atomic<T *> {
|
||||
using Base = detail::Atomic<T *>;
|
||||
|
||||
Atomic() = default;
|
||||
|
||||
|
@ -483,22 +482,22 @@ struct Atomic<T *>: octa::detail::Atomic<T *> {
|
|||
Base::store(v); return v;
|
||||
}
|
||||
|
||||
T *fetch_add(octa::Ptrdiff op, MemoryOrder ord = MemoryOrder::seq_cst)
|
||||
T *fetch_add(Ptrdiff op, MemoryOrder ord = MemoryOrder::seq_cst)
|
||||
volatile {
|
||||
return octa::detail::atomic_fetch_add(&this->p_a, op, ord);
|
||||
return detail::atomic_fetch_add(&this->p_a, op, ord);
|
||||
}
|
||||
|
||||
T *fetch_add(octa::Ptrdiff op, MemoryOrder ord = MemoryOrder::seq_cst) {
|
||||
return octa::detail::atomic_fetch_add(&this->p_a, op, ord);
|
||||
T *fetch_add(Ptrdiff op, MemoryOrder ord = MemoryOrder::seq_cst) {
|
||||
return detail::atomic_fetch_add(&this->p_a, op, ord);
|
||||
}
|
||||
|
||||
T *fetch_sub(octa::Ptrdiff op, MemoryOrder ord = MemoryOrder::seq_cst)
|
||||
T *fetch_sub(Ptrdiff op, MemoryOrder ord = MemoryOrder::seq_cst)
|
||||
volatile {
|
||||
return octa::detail::atomic_fetch_sub(&this->p_a, op, ord);
|
||||
return detail::atomic_fetch_sub(&this->p_a, op, ord);
|
||||
}
|
||||
|
||||
T *fetch_sub(octa::Ptrdiff op, MemoryOrder ord = MemoryOrder::seq_cst) {
|
||||
return octa::detail::atomic_fetch_sub(&this->p_a, op, ord);
|
||||
T *fetch_sub(Ptrdiff op, MemoryOrder ord = MemoryOrder::seq_cst) {
|
||||
return detail::atomic_fetch_sub(&this->p_a, op, ord);
|
||||
}
|
||||
|
||||
|
||||
|
@ -511,10 +510,10 @@ struct Atomic<T *>: octa::detail::Atomic<T *> {
|
|||
T *operator--( ) volatile { return fetch_sub(1) - 1; }
|
||||
T *operator--( ) { return fetch_sub(1) - 1; }
|
||||
|
||||
T *operator+=(octa::Ptrdiff op) volatile { return fetch_add(op) + op; }
|
||||
T *operator+=(octa::Ptrdiff op) { return fetch_add(op) + op; }
|
||||
T *operator-=(octa::Ptrdiff op) volatile { return fetch_sub(op) - op; }
|
||||
T *operator-=(octa::Ptrdiff op) { return fetch_sub(op) - op; }
|
||||
T *operator+=(Ptrdiff op) volatile { return fetch_add(op) + op; }
|
||||
T *operator+=(Ptrdiff op) { return fetch_add(op) + op; }
|
||||
T *operator-=(Ptrdiff op) volatile { return fetch_sub(op) - op; }
|
||||
T *operator-=(Ptrdiff op) { return fetch_sub(op) - op; }
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
|
@ -529,12 +528,12 @@ inline bool atomic_is_lock_free(const Atomic<T> *a) {
|
|||
|
||||
template<typename T>
|
||||
inline void atomic_init(volatile Atomic<T> *a, T v) {
|
||||
octa::detail::atomic_init(&a->p_a, v);
|
||||
detail::atomic_init(&a->p_a, v);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline void atomic_init(Atomic<T> *a, T v) {
|
||||
octa::detail::atomic_init(&a->p_a, v);
|
||||
detail::atomic_init(&a->p_a, v);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
|
@ -657,196 +656,176 @@ inline bool atomic_compare_exchange_strong_explicit(Atomic<T> *a, T *e,
|
|||
}
|
||||
|
||||
template <typename T>
|
||||
inline octa::EnableIf<octa::IsIntegral<T>::value &&
|
||||
!octa::IsSame<T, bool>::value, T>
|
||||
inline EnableIf<IsIntegral<T>::value && !IsSame<T, bool>::value, T>
|
||||
atomic_fetch_add(volatile Atomic<T> *a, T op) {
|
||||
return a->fetch_add(op);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline octa::EnableIf<octa::IsIntegral<T>::value &&
|
||||
!octa::IsSame<T, bool>::value, T>
|
||||
inline EnableIf<IsIntegral<T>::value && !IsSame<T, bool>::value, T>
|
||||
atomic_fetch_add(Atomic<T> *a, T op) {
|
||||
return a->fetch_add(op);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline T *atomic_fetch_add(volatile Atomic<T *> *a, octa::Ptrdiff op) {
|
||||
inline T *atomic_fetch_add(volatile Atomic<T *> *a, Ptrdiff op) {
|
||||
return a->fetch_add(op);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline T *atomic_fetch_add(Atomic<T *> *a, octa::Ptrdiff op) {
|
||||
inline T *atomic_fetch_add(Atomic<T *> *a, Ptrdiff op) {
|
||||
return a->fetch_add(op);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline octa::EnableIf<octa::IsIntegral<T>::value &&
|
||||
!octa::IsSame<T, bool>::value, T>
|
||||
inline EnableIf<IsIntegral<T>::value && !IsSame<T, bool>::value, T>
|
||||
atomic_fetch_add_explicit(volatile Atomic<T> *a, T op,
|
||||
MemoryOrder ord) {
|
||||
return a->fetch_add(op, ord);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline octa::EnableIf<octa::IsIntegral<T>::value &&
|
||||
!octa::IsSame<T, bool>::value, T>
|
||||
inline EnableIf<IsIntegral<T>::value && !IsSame<T, bool>::value, T>
|
||||
atomic_fetch_add_explicit(Atomic<T> *a, T op, MemoryOrder ord) {
|
||||
return a->fetch_add(op, ord);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline T *atomic_fetch_add_explicit(volatile Atomic<T *> *a,
|
||||
octa::Ptrdiff op, MemoryOrder ord) {
|
||||
Ptrdiff op, MemoryOrder ord) {
|
||||
return a->fetch_add(op, ord);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline T *atomic_fetch_add_explicit(Atomic<T *> *a, octa::Ptrdiff op,
|
||||
inline T *atomic_fetch_add_explicit(Atomic<T *> *a, Ptrdiff op,
|
||||
MemoryOrder ord) {
|
||||
return a->fetch_add(op, ord);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline octa::EnableIf<octa::IsIntegral<T>::value &&
|
||||
!octa::IsSame<T, bool>::value, T>
|
||||
inline EnableIf<IsIntegral<T>::value && !IsSame<T, bool>::value, T>
|
||||
atomic_fetch_sub(volatile Atomic<T> *a, T op) {
|
||||
return a->fetch_sub(op);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline octa::EnableIf<octa::IsIntegral<T>::value &&
|
||||
!octa::IsSame<T, bool>::value, T>
|
||||
inline EnableIf<IsIntegral<T>::value && !IsSame<T, bool>::value, T>
|
||||
atomic_fetch_sub(Atomic<T> *a, T op) {
|
||||
return a->fetch_sub(op);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline T *atomic_fetch_sub(volatile Atomic<T *> *a, octa::Ptrdiff op) {
|
||||
inline T *atomic_fetch_sub(volatile Atomic<T *> *a, Ptrdiff op) {
|
||||
return a->fetch_sub(op);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline T *atomic_fetch_sub(Atomic<T *> *a, octa::Ptrdiff op) {
|
||||
inline T *atomic_fetch_sub(Atomic<T *> *a, Ptrdiff op) {
|
||||
return a->fetch_sub(op);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline octa::EnableIf<octa::IsIntegral<T>::value &&
|
||||
!octa::IsSame<T, bool>::value, T>
|
||||
inline EnableIf<IsIntegral<T>::value && !IsSame<T, bool>::value, T>
|
||||
atomic_fetch_sub_explicit(volatile Atomic<T> *a, T op,
|
||||
MemoryOrder ord) {
|
||||
return a->fetch_sub(op, ord);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline octa::EnableIf<octa::IsIntegral<T>::value &&
|
||||
!octa::IsSame<T, bool>::value, T>
|
||||
inline EnableIf<IsIntegral<T>::value && !IsSame<T, bool>::value, T>
|
||||
atomic_fetch_sub_explicit(Atomic<T> *a, T op, MemoryOrder ord) {
|
||||
return a->fetch_sub(op, ord);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline T *atomic_fetch_sub_explicit(volatile Atomic<T *> *a,
|
||||
octa::Ptrdiff op, MemoryOrder ord) {
|
||||
Ptrdiff op, MemoryOrder ord) {
|
||||
return a->fetch_sub(op, ord);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline T *atomic_fetch_sub_explicit(Atomic<T *> *a, octa::Ptrdiff op,
|
||||
inline T *atomic_fetch_sub_explicit(Atomic<T *> *a, Ptrdiff op,
|
||||
MemoryOrder ord) {
|
||||
return a->fetch_sub(op, ord);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline octa::EnableIf<octa::IsIntegral<T>::value &&
|
||||
!octa::IsSame<T, bool>::value, T>
|
||||
inline EnableIf<IsIntegral<T>::value && !IsSame<T, bool>::value, T>
|
||||
atomic_fetch_and(volatile Atomic<T> *a, T op) {
|
||||
return a->fetch_and(op);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline octa::EnableIf<octa::IsIntegral<T>::value &&
|
||||
!octa::IsSame<T, bool>::value, T>
|
||||
inline EnableIf<IsIntegral<T>::value && !IsSame<T, bool>::value, T>
|
||||
atomic_fetch_and(Atomic<T> *a, T op) {
|
||||
return a->fetch_and(op);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline octa::EnableIf<octa::IsIntegral<T>::value &&
|
||||
!octa::IsSame<T, bool>::value, T>
|
||||
inline EnableIf<IsIntegral<T>::value && !IsSame<T, bool>::value, T>
|
||||
atomic_fetch_and_explicit(volatile Atomic<T> *a, T op,
|
||||
MemoryOrder ord) {
|
||||
return a->fetch_and(op, ord);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline octa::EnableIf<octa::IsIntegral<T>::value &&
|
||||
!octa::IsSame<T, bool>::value, T>
|
||||
inline EnableIf<IsIntegral<T>::value && !IsSame<T, bool>::value, T>
|
||||
atomic_fetch_and_explicit(Atomic<T> *a, T op, MemoryOrder ord) {
|
||||
return a->fetch_and(op, ord);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline octa::EnableIf<octa::IsIntegral<T>::value &&
|
||||
!octa::IsSame<T, bool>::value, T>
|
||||
inline EnableIf<IsIntegral<T>::value && !IsSame<T, bool>::value, T>
|
||||
atomic_fetch_or(volatile Atomic<T> *a, T op) {
|
||||
return a->fetch_or(op);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline octa::EnableIf<octa::IsIntegral<T>::value &&
|
||||
!octa::IsSame<T, bool>::value, T>
|
||||
inline EnableIf<IsIntegral<T>::value && !IsSame<T, bool>::value, T>
|
||||
atomic_fetch_or(Atomic<T> *a, T op) {
|
||||
return a->fetch_or(op);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline octa::EnableIf<octa::IsIntegral<T>::value &&
|
||||
!octa::IsSame<T, bool>::value, T>
|
||||
inline EnableIf<IsIntegral<T>::value && !IsSame<T, bool>::value, T>
|
||||
atomic_fetch_or_explicit(volatile Atomic<T> *a, T op,
|
||||
MemoryOrder ord) {
|
||||
return a->fetch_or(op, ord);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline octa::EnableIf<octa::IsIntegral<T>::value &&
|
||||
!octa::IsSame<T, bool>::value, T>
|
||||
inline EnableIf<IsIntegral<T>::value && !IsSame<T, bool>::value, T>
|
||||
atomic_fetch_or_explicit(Atomic<T> *a, T op, MemoryOrder ord) {
|
||||
return a->fetch_or(op, ord);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline octa::EnableIf<octa::IsIntegral<T>::value &&
|
||||
!octa::IsSame<T, bool>::value, T>
|
||||
inline EnableIf<IsIntegral<T>::value && !IsSame<T, bool>::value, T>
|
||||
atomic_fetch_xor(volatile Atomic<T> *a, T op) {
|
||||
return a->fetch_xor(op);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline octa::EnableIf<octa::IsIntegral<T>::value &&
|
||||
!octa::IsSame<T, bool>::value, T>
|
||||
inline EnableIf<IsIntegral<T>::value && !IsSame<T, bool>::value, T>
|
||||
atomic_fetch_xor(Atomic<T> *a, T op) {
|
||||
return a->fetch_xor(op);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline octa::EnableIf<octa::IsIntegral<T>::value &&
|
||||
!octa::IsSame<T, bool>::value, T>
|
||||
inline EnableIf<IsIntegral<T>::value && !IsSame<T, bool>::value, T>
|
||||
atomic_fetch_xor_explicit(volatile Atomic<T> *a, T op,
|
||||
MemoryOrder ord) {
|
||||
return a->fetch_xor(op, ord);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline octa::EnableIf<octa::IsIntegral<T>::value &&
|
||||
!octa::IsSame<T, bool>::value, T>
|
||||
inline EnableIf<IsIntegral<T>::value && !IsSame<T, bool>::value, T>
|
||||
atomic_fetch_xor_explicit(Atomic<T> *a, T op, MemoryOrder ord) {
|
||||
return a->fetch_xor(op, ord);
|
||||
}
|
||||
|
||||
struct AtomicFlag {
|
||||
octa::detail::AtomicBase<bool> p_a;
|
||||
detail::AtomicBase<bool> p_a;
|
||||
|
||||
AtomicFlag() = default;
|
||||
|
||||
|
@ -858,19 +837,19 @@ struct AtomicFlag {
|
|||
AtomicFlag &operator=(const AtomicFlag &) volatile = delete;
|
||||
|
||||
bool test_and_set(MemoryOrder ord = MemoryOrder::seq_cst) volatile {
|
||||
return octa::detail::atomic_exchange(&p_a, true, ord);
|
||||
return detail::atomic_exchange(&p_a, true, ord);
|
||||
}
|
||||
|
||||
bool test_and_set(MemoryOrder ord = MemoryOrder::seq_cst) {
|
||||
return octa::detail::atomic_exchange(&p_a, true, ord);
|
||||
return detail::atomic_exchange(&p_a, true, ord);
|
||||
}
|
||||
|
||||
void clear(MemoryOrder ord = MemoryOrder::seq_cst) volatile {
|
||||
octa::detail::atomic_store(&p_a, false, ord);
|
||||
detail::atomic_store(&p_a, false, ord);
|
||||
}
|
||||
|
||||
void clear(MemoryOrder ord = MemoryOrder::seq_cst) {
|
||||
octa::detail::atomic_store(&p_a, false, ord);
|
||||
detail::atomic_store(&p_a, false, ord);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -910,11 +889,11 @@ inline void atomic_flag_clear_explicit(AtomicFlag *a, MemoryOrder ord) {
|
|||
}
|
||||
|
||||
inline void atomic_thread_fence(MemoryOrder ord) {
|
||||
octa::detail::atomic_thread_fence(ord);
|
||||
detail::atomic_thread_fence(ord);
|
||||
}
|
||||
|
||||
inline void atomic_signal_fence(MemoryOrder ord) {
|
||||
octa::detail::atomic_signal_fence(ord);
|
||||
detail::atomic_signal_fence(ord);
|
||||
}
|
||||
|
||||
using AtomicBool = Atomic<bool>;
|
||||
|
@ -922,56 +901,56 @@ using AtomicChar = Atomic<char>;
|
|||
using AtomicShort = Atomic<short>;
|
||||
using AtomicInt = Atomic<int>;
|
||||
using AtomicLong = Atomic<long>;
|
||||
using AtomicSbyte = Atomic<octa::sbyte>;
|
||||
using AtomicByte = Atomic<octa::byte>;
|
||||
using AtomicUshort = Atomic<octa::ushort>;
|
||||
using AtomicUint = Atomic<octa::uint>;
|
||||
using AtomicUlong = Atomic<octa::ulong>;
|
||||
using AtomicLlong = Atomic<octa::llong>;
|
||||
using AtomicUllong = Atomic<octa::ullong>;
|
||||
using AtomicSbyte = Atomic<sbyte>;
|
||||
using AtomicByte = Atomic<byte>;
|
||||
using AtomicUshort = Atomic<ushort>;
|
||||
using AtomicUint = Atomic<uint>;
|
||||
using AtomicUlong = Atomic<ulong>;
|
||||
using AtomicLlong = Atomic<llong>;
|
||||
using AtomicUllong = Atomic<ullong>;
|
||||
|
||||
using AtomicChar16 = Atomic<octa::Char16>;
|
||||
using AtomicChar32 = Atomic<octa::Char32>;
|
||||
using AtomicWchar = Atomic<octa::Wchar>;
|
||||
using AtomicChar16 = Atomic<Char16>;
|
||||
using AtomicChar32 = Atomic<Char32>;
|
||||
using AtomicWchar = Atomic<Wchar>;
|
||||
|
||||
using AtomicPtrdiff = Atomic<octa::Ptrdiff>;
|
||||
using AtomicSize = Atomic<octa::Size>;
|
||||
using AtomicPtrdiff = Atomic<Ptrdiff>;
|
||||
using AtomicSize = Atomic<Size>;
|
||||
|
||||
using AtomicIntmax = Atomic<octa::Intmax>;
|
||||
using AtomicUintmax = Atomic<octa::Uintmax>;
|
||||
using AtomicIntmax = Atomic<Intmax>;
|
||||
using AtomicUintmax = Atomic<Uintmax>;
|
||||
|
||||
using AtomicIntptr = Atomic<octa::Intptr>;
|
||||
using AtomicUintptr = Atomic<octa::Uintptr>;
|
||||
using AtomicIntptr = Atomic<Intptr>;
|
||||
using AtomicUintptr = Atomic<Uintptr>;
|
||||
|
||||
using AtomicInt8 = Atomic<octa::Int8>;
|
||||
using AtomicInt16 = Atomic<octa::Int16>;
|
||||
using AtomicInt32 = Atomic<octa::Int32>;
|
||||
using AtomicInt64 = Atomic<octa::Int64>;
|
||||
using AtomicInt8 = Atomic<Int8>;
|
||||
using AtomicInt16 = Atomic<Int16>;
|
||||
using AtomicInt32 = Atomic<Int32>;
|
||||
using AtomicInt64 = Atomic<Int64>;
|
||||
|
||||
using AtomicUint8 = Atomic<octa::Uint8>;
|
||||
using AtomicUint16 = Atomic<octa::Uint16>;
|
||||
using AtomicUint32 = Atomic<octa::Uint32>;
|
||||
using AtomicUint64 = Atomic<octa::Uint64>;
|
||||
using AtomicUint8 = Atomic<Uint8>;
|
||||
using AtomicUint16 = Atomic<Uint16>;
|
||||
using AtomicUint32 = Atomic<Uint32>;
|
||||
using AtomicUint64 = Atomic<Uint64>;
|
||||
|
||||
using AtomicIntLeast8 = Atomic<octa::IntLeast8>;
|
||||
using AtomicIntLeast16 = Atomic<octa::IntLeast16>;
|
||||
using AtomicIntLeast32 = Atomic<octa::IntLeast32>;
|
||||
using AtomicIntLeast64 = Atomic<octa::IntLeast64>;
|
||||
using AtomicIntLeast8 = Atomic<IntLeast8>;
|
||||
using AtomicIntLeast16 = Atomic<IntLeast16>;
|
||||
using AtomicIntLeast32 = Atomic<IntLeast32>;
|
||||
using AtomicIntLeast64 = Atomic<IntLeast64>;
|
||||
|
||||
using AtomicUintLeast8 = Atomic<octa::UintLeast8>;
|
||||
using AtomicUintLeast16 = Atomic<octa::UintLeast16>;
|
||||
using AtomicUintLeast32 = Atomic<octa::UintLeast32>;
|
||||
using AtomicUintLeast64 = Atomic<octa::UintLeast64>;
|
||||
using AtomicUintLeast8 = Atomic<UintLeast8>;
|
||||
using AtomicUintLeast16 = Atomic<UintLeast16>;
|
||||
using AtomicUintLeast32 = Atomic<UintLeast32>;
|
||||
using AtomicUintLeast64 = Atomic<UintLeast64>;
|
||||
|
||||
using AtomicIntFast8 = Atomic<octa::IntFast8>;
|
||||
using AtomicIntFast16 = Atomic<octa::IntFast16>;
|
||||
using AtomicIntFast32 = Atomic<octa::IntFast32>;
|
||||
using AtomicIntFast64 = Atomic<octa::IntFast64>;
|
||||
using AtomicIntFast8 = Atomic<IntFast8>;
|
||||
using AtomicIntFast16 = Atomic<IntFast16>;
|
||||
using AtomicIntFast32 = Atomic<IntFast32>;
|
||||
using AtomicIntFast64 = Atomic<IntFast64>;
|
||||
|
||||
using AtomicUintFast8 = Atomic<octa::UintFast8>;
|
||||
using AtomicUintFast16 = Atomic<octa::UintFast16>;
|
||||
using AtomicUintFast32 = Atomic<octa::UintFast32>;
|
||||
using AtomicUintFast64 = Atomic<octa::UintFast64>;
|
||||
using AtomicUintFast8 = Atomic<UintFast8>;
|
||||
using AtomicUintFast16 = Atomic<UintFast16>;
|
||||
using AtomicUintFast32 = Atomic<UintFast32>;
|
||||
using AtomicUintFast64 = Atomic<UintFast64>;
|
||||
|
||||
#define ATOMIC_FLAG_INIT {false}
|
||||
#define ATOMIC_VAR_INIT(v) {v}
|
||||
|
|
304
octa/format.hh
304
octa/format.hh
|
@ -41,8 +41,8 @@ namespace detail {
|
|||
return ret;
|
||||
}
|
||||
|
||||
static inline octa::Size read_digits(const char *&fmt, char *buf) {
|
||||
octa::Size ret = 0;
|
||||
static inline Size read_digits(const char *&fmt, char *buf) {
|
||||
Size ret = 0;
|
||||
for (; isdigit(*fmt); ++ret)
|
||||
*buf++ = *fmt++;
|
||||
*buf = '\0';
|
||||
|
@ -59,7 +59,7 @@ namespace detail {
|
|||
* 7 .. string
|
||||
* 8 .. custom object
|
||||
*/
|
||||
static constexpr const octa::byte fmt_specs[] = {
|
||||
static constexpr const byte fmt_specs[] = {
|
||||
/* uppercase spec set */
|
||||
1, 3, 8, 8, /* A B C D */
|
||||
1, 1, 1, 8, /* E F G H */
|
||||
|
@ -107,23 +107,23 @@ namespace detail {
|
|||
|
||||
/* retrieve width/precision */
|
||||
template<typename T>
|
||||
bool convert_arg_param(const T &val, int ¶m, octa::EnableIf<
|
||||
octa::IsIntegral<T>::value, bool
|
||||
bool convert_arg_param(const T &val, int ¶m, EnableIf<
|
||||
IsIntegral<T>::value, bool
|
||||
> = true) {
|
||||
param = int(val);
|
||||
return true;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
bool convert_arg_param(const T &, int &, octa::EnableIf<
|
||||
!octa::IsIntegral<T>::value, bool
|
||||
bool convert_arg_param(const T &, int &, EnableIf<
|
||||
!IsIntegral<T>::value, bool
|
||||
> = true) {
|
||||
assert(false && "invalid argument for width/precision");
|
||||
return false;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
bool get_arg_param(octa::Size idx, int ¶m, const T &val) {
|
||||
bool get_arg_param(Size idx, int ¶m, const T &val) {
|
||||
if (idx) {
|
||||
assert(false && "not enough format args");
|
||||
return false;
|
||||
|
@ -131,7 +131,7 @@ namespace detail {
|
|||
return convert_arg_param(val, param);
|
||||
}
|
||||
template<typename T, typename ...A>
|
||||
bool get_arg_param(octa::Size idx, int ¶m, const T &val,
|
||||
bool get_arg_param(Size idx, int ¶m, const T &val,
|
||||
const A &...args) {
|
||||
if (idx) return get_arg_param(idx - 1, param, args...);
|
||||
return convert_arg_param(val, param);
|
||||
|
@ -144,8 +144,8 @@ struct FormatSpec {
|
|||
p_nested_escape(escape), p_fmt(fmt) {}
|
||||
|
||||
template<typename R>
|
||||
bool read_until_spec(R &writer, octa::Size *wret) {
|
||||
octa::Size written = 0;
|
||||
bool read_until_spec(R &writer, Size *wret) {
|
||||
Size written = 0;
|
||||
if (!p_fmt) return false;
|
||||
while (*p_fmt) {
|
||||
if (*p_fmt == '%') {
|
||||
|
@ -164,8 +164,7 @@ struct FormatSpec {
|
|||
}
|
||||
|
||||
template<typename R>
|
||||
octa::Size write_spaces(R &writer, octa::Size n,
|
||||
bool left, char c = ' ') const {
|
||||
Size write_spaces(R &writer, Size n, bool left, char c = ' ') const {
|
||||
if (left == bool(p_flags & FMT_FLAG_DASH)) return 0;
|
||||
int r = p_width - int(n);
|
||||
for (int w = p_width - int(n); --w >= 0; writer.put(c));
|
||||
|
@ -177,7 +176,7 @@ struct FormatSpec {
|
|||
return p_fmt;
|
||||
}
|
||||
|
||||
void build_spec(char *buf, const char *spec, octa::Size specn) {
|
||||
void build_spec(char *buf, const char *spec, Size specn) {
|
||||
*buf++ = '%';
|
||||
if (p_flags & FMT_FLAG_DASH ) *buf++ = '-';
|
||||
if (p_flags & FMT_FLAG_ZERO ) *buf++ = '0';
|
||||
|
@ -199,36 +198,36 @@ struct FormatSpec {
|
|||
bool arg_precision() const { return p_arg_precision; }
|
||||
|
||||
template<typename ...A>
|
||||
bool set_width(octa::Size idx, const A &...args) {
|
||||
return octa::detail::get_arg_param(idx, p_width, args...);
|
||||
bool set_width(Size idx, const A &...args) {
|
||||
return detail::get_arg_param(idx, p_width, args...);
|
||||
}
|
||||
|
||||
template<typename ...A>
|
||||
bool set_precision(octa::Size idx, const A &...args) {
|
||||
return octa::detail::get_arg_param(idx, p_precision, args...);
|
||||
bool set_precision(Size idx, const A &...args) {
|
||||
return detail::get_arg_param(idx, p_precision, args...);
|
||||
}
|
||||
|
||||
int flags() const { return p_flags; }
|
||||
|
||||
char spec() const { return p_spec; }
|
||||
|
||||
octa::byte index() const { return p_index; }
|
||||
byte index() const { return p_index; }
|
||||
|
||||
const char *nested() const { return p_nested; }
|
||||
octa::Size nested_len() const { return p_nested_len; }
|
||||
Size nested_len() const { return p_nested_len; }
|
||||
|
||||
const char *nested_sep() const { return p_nested_sep; }
|
||||
octa::Size nested_sep_len() const { return p_nested_sep_len; }
|
||||
Size nested_sep_len() const { return p_nested_sep_len; }
|
||||
|
||||
bool is_nested() const { return p_is_nested; }
|
||||
bool nested_escape() const { return p_nested_escape; }
|
||||
|
||||
protected:
|
||||
const char *p_nested = nullptr;
|
||||
octa::Size p_nested_len = 0;
|
||||
Size p_nested_len = 0;
|
||||
|
||||
const char *p_nested_sep = nullptr;
|
||||
octa::Size p_nested_sep_len = 0;
|
||||
Size p_nested_sep_len = 0;
|
||||
|
||||
int p_flags = 0;
|
||||
|
||||
|
@ -243,7 +242,7 @@ protected:
|
|||
|
||||
char p_spec = '\0';
|
||||
|
||||
octa::byte p_index = 0;
|
||||
byte p_index = 0;
|
||||
|
||||
bool p_is_nested = false;
|
||||
bool p_nested_escape = false;
|
||||
|
@ -323,7 +322,7 @@ protected:
|
|||
if ((*p_fmt == '(') || ((*p_fmt == '-') && (*(p_fmt + 1) == '('))) {
|
||||
return read_spec_range();
|
||||
}
|
||||
octa::Size ndig = octa::detail::read_digits(p_fmt, p_buf);
|
||||
Size ndig = detail::read_digits(p_fmt, p_buf);
|
||||
|
||||
bool havepos = false;
|
||||
p_index = 0;
|
||||
|
@ -332,7 +331,7 @@ protected:
|
|||
if (ndig <= 0) return false; /* no pos given */
|
||||
int idx = atoi(p_buf);
|
||||
if (idx <= 0 || idx > 255) return false; /* bad index */
|
||||
p_index = octa::byte(idx);
|
||||
p_index = byte(idx);
|
||||
++p_fmt;
|
||||
havepos = true;
|
||||
}
|
||||
|
@ -344,17 +343,17 @@ protected:
|
|||
|
||||
/* parse flags */
|
||||
p_flags = 0;
|
||||
octa::Size skipd = 0;
|
||||
Size skipd = 0;
|
||||
if (havepos || !ndig) {
|
||||
p_flags = octa::detail::parse_fmt_flags(p_fmt, 0);
|
||||
p_flags = detail::parse_fmt_flags(p_fmt, 0);
|
||||
} else {
|
||||
for (octa::Size i = 0; i < ndig; ++i) {
|
||||
for (Size i = 0; i < ndig; ++i) {
|
||||
if (p_buf[i] != '0') break;
|
||||
++skipd;
|
||||
}
|
||||
if (skipd) p_flags = FMT_FLAG_ZERO;
|
||||
if (skipd == ndig)
|
||||
p_flags = octa::detail::parse_fmt_flags(p_fmt, p_flags);
|
||||
p_flags = detail::parse_fmt_flags(p_fmt, p_flags);
|
||||
}
|
||||
|
||||
/* parse width */
|
||||
|
@ -364,7 +363,7 @@ protected:
|
|||
if (!havepos && ndig && (ndig - skipd)) {
|
||||
p_width = atoi(p_buf + skipd);
|
||||
p_has_width = true;
|
||||
} else if (octa::detail::read_digits(p_fmt, p_buf)) {
|
||||
} else if (detail::read_digits(p_fmt, p_buf)) {
|
||||
p_width = atoi(p_buf);
|
||||
p_has_width = true;
|
||||
} else if (*p_fmt == '*') {
|
||||
|
@ -379,7 +378,7 @@ protected:
|
|||
if (*p_fmt != '.') goto fmtchar;
|
||||
++p_fmt;
|
||||
|
||||
if (octa::detail::read_digits(p_fmt, p_buf)) {
|
||||
if (detail::read_digits(p_fmt, p_buf)) {
|
||||
p_precision = atoi(p_buf);
|
||||
p_has_precision = true;
|
||||
} else if (*p_fmt == '*') {
|
||||
|
@ -391,8 +390,8 @@ protected:
|
|||
p_spec = *p_fmt++;
|
||||
/* make sure we're testing on a signed byte - our mapping only
|
||||
* tests values up to 127 */
|
||||
octa::sbyte sp = p_spec;
|
||||
return (sp >= 65) && (octa::detail::fmt_specs[sp - 65] != 0);
|
||||
sbyte sp = p_spec;
|
||||
return (sp >= 65) && (detail::fmt_specs[sp - 65] != 0);
|
||||
}
|
||||
|
||||
const char *p_fmt;
|
||||
|
@ -401,24 +400,24 @@ protected:
|
|||
|
||||
namespace detail {
|
||||
template<typename R, typename T>
|
||||
static inline octa::Ptrdiff write_u(R &writer, const FormatSpec *fl,
|
||||
bool neg, T val) {
|
||||
static inline Ptrdiff write_u(R &writer, const FormatSpec *fl,
|
||||
bool neg, T val) {
|
||||
char buf[20];
|
||||
octa::Ptrdiff r = 0;
|
||||
octa::Size n = 0;
|
||||
Ptrdiff r = 0;
|
||||
Size n = 0;
|
||||
|
||||
char spec = fl->spec();
|
||||
if (spec == 's') spec = 'd';
|
||||
octa::byte specn = octa::detail::fmt_specs[spec - 65];
|
||||
byte specn = detail::fmt_specs[spec - 65];
|
||||
if (specn <= 2 || specn > 7) {
|
||||
assert(false && "cannot format integers with the given spec");
|
||||
return -1;
|
||||
}
|
||||
|
||||
int base = octa::detail::fmt_bases[specn];
|
||||
int base = detail::fmt_bases[specn];
|
||||
if (!val) buf[n++] = '0';
|
||||
for (; val; val /= base)
|
||||
buf[n++] = octa::detail::fmt_digits[spec >= 'a'][val % base];
|
||||
buf[n++] = detail::fmt_digits[spec >= 'a'][val % base];
|
||||
r = n;
|
||||
|
||||
int flags = fl->flags();
|
||||
|
@ -431,7 +430,7 @@ namespace detail {
|
|||
const char *pfx = nullptr;
|
||||
int pfxlen = 0;
|
||||
if (flags & FMT_FLAG_HASH && spec != 'd') {
|
||||
pfx = octa::detail::fmt_intpfx[spec >= 'a'][specn - 3];
|
||||
pfx = detail::fmt_intpfx[spec >= 'a'][specn - 3];
|
||||
pfxlen = !!pfx[1] + 1;
|
||||
r += pfxlen;
|
||||
}
|
||||
|
@ -451,52 +450,43 @@ namespace detail {
|
|||
}
|
||||
|
||||
template<typename R, typename ...A>
|
||||
static octa::Ptrdiff format_impl(R &writer, octa::Size &fmtn,
|
||||
bool escape, const char *fmt,
|
||||
const A &...args);
|
||||
static Ptrdiff format_impl(R &writer, Size &fmtn, bool escape,
|
||||
const char *fmt, const A &...args);
|
||||
|
||||
template<typename T, typename = octa::RangeOf<T>>
|
||||
static octa::True test_fmt_range(int);
|
||||
template<typename T, typename = RangeOf<T>>
|
||||
static True test_fmt_range(int);
|
||||
template<typename>
|
||||
static octa::False test_fmt_range(...);
|
||||
static False test_fmt_range(...);
|
||||
|
||||
template<typename T>
|
||||
using FmtRangeTest = decltype(test_fmt_range<T>(0));
|
||||
|
||||
template<typename R, typename T>
|
||||
static inline octa::Ptrdiff format_ritem(R &writer, octa::Size &fmtn,
|
||||
bool esc,
|
||||
const char *fmt,
|
||||
const T &item) {
|
||||
static inline Ptrdiff format_ritem(R &writer, Size &fmtn, bool esc,
|
||||
const char *fmt, const T &item) {
|
||||
return format_impl(writer, fmtn, esc, fmt, item);
|
||||
}
|
||||
|
||||
template<typename R, typename T, typename U>
|
||||
static inline octa::Ptrdiff format_ritem(R &writer, octa::Size &fmtn,
|
||||
bool esc,
|
||||
const char *fmt,
|
||||
const octa::Pair<T, U> &pair) {
|
||||
static inline Ptrdiff format_ritem(R &writer, Size &fmtn, bool esc,
|
||||
const char *fmt,
|
||||
const Pair<T, U> &pair) {
|
||||
return format_impl(writer, fmtn, esc, fmt, pair.first, pair.second);
|
||||
}
|
||||
|
||||
template<typename R, typename T>
|
||||
static inline octa::Ptrdiff write_range(R &writer,
|
||||
const FormatSpec *fl,
|
||||
bool escape,
|
||||
const char *sep,
|
||||
octa::Size seplen,
|
||||
const T &val,
|
||||
octa::EnableIf<
|
||||
FmtRangeTest<T>::value,
|
||||
bool
|
||||
> = true) {
|
||||
static inline Ptrdiff write_range(R &writer, const FormatSpec *fl,
|
||||
bool escape, const char *sep,
|
||||
Size seplen, const T &val,
|
||||
EnableIf<FmtRangeTest<T>::value,
|
||||
bool> = true) {
|
||||
auto range = octa::iter(val);
|
||||
if (range.empty()) return 0;
|
||||
octa::Ptrdiff ret = 0;
|
||||
octa::Size fmtn = 0;
|
||||
Ptrdiff ret = 0;
|
||||
Size fmtn = 0;
|
||||
/* test first item */
|
||||
octa::Ptrdiff fret = format_ritem(writer, fmtn, escape,
|
||||
fl->rest(), range.front());
|
||||
Ptrdiff fret = format_ritem(writer, fmtn, escape, fl->rest(),
|
||||
range.front());
|
||||
if (fret < 0) return fret;
|
||||
ret += fret;
|
||||
range.pop_front();
|
||||
|
@ -515,21 +505,18 @@ namespace detail {
|
|||
}
|
||||
|
||||
template<typename R, typename T>
|
||||
static inline octa::Ptrdiff write_range(R &, const FormatSpec *, bool,
|
||||
const char *, octa::Size,
|
||||
const T &,
|
||||
octa::EnableIf<
|
||||
!FmtRangeTest<T>::value,
|
||||
bool
|
||||
> = true) {
|
||||
static inline Ptrdiff write_range(R &, const FormatSpec *, bool,
|
||||
const char *, Size, const T &,
|
||||
EnableIf<!FmtRangeTest<T>::value,
|
||||
bool> = true) {
|
||||
assert(false && "invalid value for ranged format");
|
||||
return -1;
|
||||
}
|
||||
|
||||
template<typename T,
|
||||
typename = decltype(octa::to_string(octa::declval<T>()))
|
||||
> static octa::True test_fmt_tostr(int);
|
||||
template<typename> static octa::False test_fmt_tostr(...);
|
||||
typename = decltype(octa::to_string(declval<T>()))
|
||||
> static True test_fmt_tostr(int);
|
||||
template<typename> static False test_fmt_tostr(...);
|
||||
|
||||
template<typename T>
|
||||
using FmtTostrTest = decltype(test_fmt_tostr<T>(0));
|
||||
|
@ -549,15 +536,15 @@ namespace detail {
|
|||
|
||||
static inline const char *escape_fmt_char(char v, char quote) {
|
||||
if ((v >= 0 && v < 0x20) || (v == quote)) {
|
||||
return fmt_escapes[octa::Size(v)];
|
||||
return fmt_escapes[Size(v)];
|
||||
} else if (v == 0x7F) {
|
||||
return "\\x7F";
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
static inline octa::String escape_fmt_str(const char *val) {
|
||||
octa::String ret;
|
||||
static inline String escape_fmt_str(const char *val) {
|
||||
String ret;
|
||||
ret.push('"');
|
||||
while (*val) {
|
||||
const char *esc = escape_fmt_char(*val, '"');
|
||||
|
@ -572,7 +559,7 @@ namespace detail {
|
|||
}
|
||||
|
||||
template<typename R>
|
||||
struct FmtWriteRange: octa::OutputRange<FmtWriteRange<R>, char> {
|
||||
struct FmtWriteRange: OutputRange<FmtWriteRange<R>, char> {
|
||||
FmtWriteRange() = delete;
|
||||
FmtWriteRange(R &out): p_out(out), p_written(0) {}
|
||||
bool put(char v) {
|
||||
|
@ -580,15 +567,15 @@ namespace detail {
|
|||
p_written += ret;
|
||||
return ret;
|
||||
}
|
||||
octa::Size put_n(const char *v, octa::Size n) {
|
||||
octa::Size ret = p_out.put_n(v, n);
|
||||
Size put_n(const char *v, Size n) {
|
||||
Size ret = p_out.put_n(v, n);
|
||||
p_written += ret;
|
||||
return ret;
|
||||
}
|
||||
octa::Size get_written() const { return p_written; }
|
||||
Size get_written() const { return p_written; }
|
||||
private:
|
||||
R &p_out;
|
||||
octa::Size p_written;
|
||||
Size p_written;
|
||||
};
|
||||
|
||||
template<typename T, typename U>
|
||||
|
@ -602,21 +589,20 @@ namespace detail {
|
|||
static constexpr bool value = (sizeof(test<T, U>(0)) == sizeof(char));
|
||||
};
|
||||
|
||||
struct WriteSpec: octa::FormatSpec {
|
||||
WriteSpec(): octa::FormatSpec() {}
|
||||
WriteSpec(const char *fmt, bool esc): octa::FormatSpec(fmt, esc) {}
|
||||
struct WriteSpec: FormatSpec {
|
||||
WriteSpec(): FormatSpec() {}
|
||||
WriteSpec(const char *fmt, bool esc): FormatSpec(fmt, esc) {}
|
||||
|
||||
/* C string */
|
||||
template<typename R>
|
||||
octa::Ptrdiff write(R &writer, bool escape, const char *val,
|
||||
octa::Size n) {
|
||||
Ptrdiff write(R &writer, bool escape, const char *val, Size n) {
|
||||
if (escape) {
|
||||
octa::String esc = escape_fmt_str(val);
|
||||
String esc = escape_fmt_str(val);
|
||||
return write(writer, false, (const char *)esc.data(),
|
||||
esc.size());
|
||||
}
|
||||
if (this->precision()) n = this->precision();
|
||||
octa::Ptrdiff r = n;
|
||||
Ptrdiff r = n;
|
||||
r += this->write_spaces(writer, n, true);
|
||||
writer.put_n(val, n);
|
||||
r += this->write_spaces(writer, n, false);
|
||||
|
@ -624,7 +610,7 @@ namespace detail {
|
|||
}
|
||||
|
||||
template<typename R>
|
||||
octa::Ptrdiff write(R &writer, bool escape, const char *val) {
|
||||
Ptrdiff write(R &writer, bool escape, const char *val) {
|
||||
if (this->spec() != 's') {
|
||||
assert(false && "cannot print strings with the given spec");
|
||||
return -1;
|
||||
|
@ -634,8 +620,7 @@ namespace detail {
|
|||
|
||||
/* OctaSTD string */
|
||||
template<typename R, typename A>
|
||||
octa::Ptrdiff write(R &writer, bool escape,
|
||||
const octa::AnyString<A> &val) {
|
||||
Ptrdiff write(R &writer, bool escape, const AnyString<A> &val) {
|
||||
if (this->spec() != 's') {
|
||||
assert(false && "cannot print strings with the given spec");
|
||||
return -1;
|
||||
|
@ -645,7 +630,7 @@ namespace detail {
|
|||
|
||||
/* character */
|
||||
template<typename R>
|
||||
octa::Ptrdiff write(R &writer, bool escape, char val) {
|
||||
Ptrdiff write(R &writer, bool escape, char val) {
|
||||
if (this->spec() != 's' && this->spec() != 'c') {
|
||||
assert(false && "cannot print chars with the given spec");
|
||||
return -1;
|
||||
|
@ -655,13 +640,13 @@ namespace detail {
|
|||
if (esc) {
|
||||
char buf[6];
|
||||
buf[0] = '\'';
|
||||
octa::Size elen = strlen(esc);
|
||||
Size elen = strlen(esc);
|
||||
memcpy(buf + 1, esc, elen);
|
||||
buf[elen + 1] = '\'';
|
||||
return write(writer, false, (const char *)buf, elen + 2);
|
||||
}
|
||||
}
|
||||
octa::Ptrdiff r = 1 + escape * 2;
|
||||
Ptrdiff r = 1 + escape * 2;
|
||||
r += this->write_spaces(writer, 1 + escape * 2, true);
|
||||
if (escape) {
|
||||
writer.put('\'');
|
||||
|
@ -674,7 +659,7 @@ namespace detail {
|
|||
|
||||
/* bool */
|
||||
template<typename R>
|
||||
octa::Ptrdiff write(R &writer, bool, bool val) {
|
||||
Ptrdiff write(R &writer, bool, bool val) {
|
||||
if (this->spec() == 's')
|
||||
return write(writer, ("false\0true") + (6 * val));
|
||||
else
|
||||
|
@ -683,32 +668,32 @@ namespace detail {
|
|||
|
||||
/* signed integers */
|
||||
template<typename R, typename T>
|
||||
octa::Ptrdiff write(R &writer, bool, T val, octa::EnableIf<
|
||||
octa::IsIntegral<T>::value && octa::IsSigned<T>::value, bool
|
||||
Ptrdiff write(R &writer, bool, T val, EnableIf<
|
||||
IsIntegral<T>::value && IsSigned<T>::value, bool
|
||||
> = true) {
|
||||
using UT = octa::MakeUnsigned<T>;
|
||||
return octa::detail::write_u(writer, this, val < 0,
|
||||
(val < 0) ? UT(-val) : UT(val));
|
||||
using UT = MakeUnsigned<T>;
|
||||
return detail::write_u(writer, this, val < 0,
|
||||
(val < 0) ? (UT)(-val) : (UT)(val));
|
||||
}
|
||||
|
||||
/* unsigned integers */
|
||||
template<typename R, typename T>
|
||||
octa::Ptrdiff write(R &writer, bool, T val, octa::EnableIf<
|
||||
octa::IsIntegral<T>::value && octa::IsUnsigned<T>::value, bool
|
||||
Ptrdiff write(R &writer, bool, T val, EnableIf<
|
||||
IsIntegral<T>::value && IsUnsigned<T>::value, bool
|
||||
> = true) {
|
||||
return octa::detail::write_u(writer, this, false, val);
|
||||
return detail::write_u(writer, this, false, val);
|
||||
}
|
||||
|
||||
template<typename R, typename T,
|
||||
bool Long = octa::IsSame<T, octa::ldouble>::value
|
||||
> octa::Ptrdiff write(R &writer, bool, T val, octa::EnableIf<
|
||||
octa::IsFloatingPoint<T>::value, bool
|
||||
bool Long = IsSame<T, ldouble>::value
|
||||
> Ptrdiff write(R &writer, bool, T val, EnableIf<
|
||||
IsFloatingPoint<T>::value, bool
|
||||
> = true) {
|
||||
char buf[16], rbuf[128];
|
||||
char fmtspec[Long + 1];
|
||||
|
||||
fmtspec[Long] = this->spec();
|
||||
octa::byte specn = octa::detail::fmt_specs[this->spec() - 65];
|
||||
byte specn = detail::fmt_specs[this->spec() - 65];
|
||||
if (specn != 1 && specn != 7) {
|
||||
assert(false && "cannot format floats with the given spec");
|
||||
return -1;
|
||||
|
@ -717,12 +702,12 @@ namespace detail {
|
|||
if (Long) fmtspec[0] = 'L';
|
||||
|
||||
this->build_spec(buf, fmtspec, sizeof(fmtspec));
|
||||
octa::Ptrdiff ret = snprintf(rbuf, sizeof(rbuf), buf,
|
||||
Ptrdiff ret = snprintf(rbuf, sizeof(rbuf), buf,
|
||||
this->width(),
|
||||
this->has_precision() ? this->precision() : 6, val);
|
||||
|
||||
char *dbuf = nullptr;
|
||||
if (octa::Size(ret) >= sizeof(rbuf)) {
|
||||
if (Size(ret) >= sizeof(rbuf)) {
|
||||
/* this should typically never happen */
|
||||
dbuf = (char *)malloc(ret + 1);
|
||||
ret = snprintf(dbuf, ret + 1, buf, this->width(),
|
||||
|
@ -735,18 +720,18 @@ namespace detail {
|
|||
|
||||
/* pointer value */
|
||||
template<typename R, typename T>
|
||||
octa::Ptrdiff write(R &writer, bool, T *val) {
|
||||
Ptrdiff write(R &writer, bool, T *val) {
|
||||
if (this->p_spec == 's') {
|
||||
this->p_spec = 'x';
|
||||
this->p_flags |= FMT_FLAG_HASH;
|
||||
}
|
||||
return write(writer, false, octa::Size(val));
|
||||
return write(writer, false, Size(val));
|
||||
}
|
||||
|
||||
/* generic value */
|
||||
template<typename R, typename T>
|
||||
octa::Ptrdiff write(R &writer, bool, const T &val, octa::EnableIf<
|
||||
!octa::IsArithmetic<T>::value && FmtTostrTest<T>::value &&
|
||||
Ptrdiff write(R &writer, bool, const T &val, EnableIf<
|
||||
!IsArithmetic<T>::value && FmtTostrTest<T>::value &&
|
||||
!FmtTofmtTest<T, FmtWriteRange<R>>::value, bool
|
||||
> = true) {
|
||||
if (this->spec() != 's') {
|
||||
|
@ -758,8 +743,8 @@ namespace detail {
|
|||
|
||||
/* custom format case */
|
||||
template<typename R, typename T>
|
||||
octa::Ptrdiff write(R &writer, bool, const T &val,
|
||||
octa::EnableIf<FmtTofmtTest<T, FmtWriteRange<R>>::value, bool
|
||||
Ptrdiff write(R &writer, bool, const T &val,
|
||||
EnableIf<FmtTofmtTest<T, FmtWriteRange<R>>::value, bool
|
||||
> = true) {
|
||||
FmtWriteRange<R> sink(writer);
|
||||
if (!val.to_format(sink, *this)) return -1;
|
||||
|
@ -768,8 +753,8 @@ namespace detail {
|
|||
|
||||
/* generic failure case */
|
||||
template<typename R, typename T>
|
||||
octa::Ptrdiff write(R &, bool, const T &, octa::EnableIf<
|
||||
!octa::IsArithmetic<T>::value && !FmtTostrTest<T>::value, bool
|
||||
Ptrdiff write(R &, bool, const T &, EnableIf<
|
||||
!IsArithmetic<T>::value && !FmtTostrTest<T>::value, bool
|
||||
> = true) {
|
||||
assert(false && "value cannot be formatted");
|
||||
return -1;
|
||||
|
@ -777,7 +762,7 @@ namespace detail {
|
|||
|
||||
/* actual writer */
|
||||
template<typename R, typename T>
|
||||
octa::Ptrdiff write_arg(R &writer, octa::Size idx, const T &val) {
|
||||
Ptrdiff write_arg(R &writer, Size idx, const T &val) {
|
||||
if (idx) {
|
||||
assert(false && "not enough format args");
|
||||
return -1;
|
||||
|
@ -786,55 +771,50 @@ namespace detail {
|
|||
}
|
||||
|
||||
template<typename R, typename T, typename ...A>
|
||||
octa::Ptrdiff write_arg(R &writer, octa::Size idx, const T &val,
|
||||
const A &...args) {
|
||||
Ptrdiff write_arg(R &writer, Size idx, const T &val,
|
||||
const A &...args) {
|
||||
if (idx) return write_arg(writer, idx - 1, args...);
|
||||
return write(writer, this->p_nested_escape, val);
|
||||
}
|
||||
|
||||
/* range writer */
|
||||
template<typename R, typename T>
|
||||
octa::Ptrdiff write_range(R &writer, octa::Size idx,
|
||||
const char *sep, octa::Size seplen,
|
||||
const T &val) {
|
||||
Ptrdiff write_range(R &writer, Size idx, const char *sep,
|
||||
Size seplen, const T &val) {
|
||||
if (idx) {
|
||||
assert(false && "not enough format args");
|
||||
return -1;
|
||||
}
|
||||
return octa::detail::write_range(writer, this,
|
||||
this->p_nested_escape, sep, seplen, val);
|
||||
return detail::write_range(writer, this, this->p_nested_escape,
|
||||
sep, seplen, val);
|
||||
}
|
||||
|
||||
template<typename R, typename T, typename ...A>
|
||||
octa::Ptrdiff write_range(R &writer, octa::Size idx,
|
||||
const char *sep, octa::Size seplen,
|
||||
const T &val,
|
||||
const A &...args) {
|
||||
Ptrdiff write_range(R &writer, Size idx, const char *sep,
|
||||
Size seplen, const T &val, const A &...args) {
|
||||
if (idx) return write_range(writer, idx - 1, sep, seplen, args...);
|
||||
return octa::detail::write_range(writer, this,
|
||||
return detail::write_range(writer, this,
|
||||
this->p_nested_escape, sep, seplen, val);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename R, typename ...A>
|
||||
static inline octa::Ptrdiff format_impl(R &writer, octa::Size &fmtn,
|
||||
bool escape,
|
||||
const char *fmt,
|
||||
const A &...args) {
|
||||
octa::Size argidx = 1, retn = 0, twr = 0;
|
||||
octa::Ptrdiff written = 0;
|
||||
octa::detail::WriteSpec spec(fmt, escape);
|
||||
static inline Ptrdiff format_impl(R &writer, Size &fmtn, bool escape,
|
||||
const char *fmt, const A &...args) {
|
||||
Size argidx = 1, retn = 0, twr = 0;
|
||||
Ptrdiff written = 0;
|
||||
detail::WriteSpec spec(fmt, escape);
|
||||
while (spec.read_until_spec(writer, &twr)) {
|
||||
written += twr;
|
||||
octa::Size argpos = spec.index();
|
||||
Size argpos = spec.index();
|
||||
if (spec.is_nested()) {
|
||||
if (!argpos) argpos = argidx++;
|
||||
/* FIXME: figure out a better way */
|
||||
char new_fmt[256];
|
||||
memcpy(new_fmt, spec.nested(), spec.nested_len());
|
||||
new_fmt[spec.nested_len()] = '\0';
|
||||
octa::detail::WriteSpec nspec(new_fmt, spec.nested_escape());
|
||||
octa::Ptrdiff sw = nspec.write_range(writer, argpos - 1,
|
||||
detail::WriteSpec nspec(new_fmt, spec.nested_escape());
|
||||
Ptrdiff sw = nspec.write_range(writer, argpos - 1,
|
||||
spec.nested_sep(), spec.nested_sep_len(), args...);
|
||||
if (sw < 0) return sw;
|
||||
written += sw;
|
||||
|
@ -871,7 +851,7 @@ namespace detail {
|
|||
return -1;
|
||||
}
|
||||
}
|
||||
octa::Ptrdiff sw = spec.write_arg(writer, argpos - 1, args...);
|
||||
Ptrdiff sw = spec.write_arg(writer, argpos - 1, args...);
|
||||
if (sw < 0) return sw;
|
||||
written += sw;
|
||||
}
|
||||
|
@ -881,10 +861,10 @@ namespace detail {
|
|||
}
|
||||
|
||||
template<typename R, typename ...A>
|
||||
static inline octa::Ptrdiff format_impl(R &writer, octa::Size &fmtn,
|
||||
bool, const char *fmt) {
|
||||
octa::Size written = 0;
|
||||
octa::detail::WriteSpec spec(fmt, false);
|
||||
static inline Ptrdiff format_impl(R &writer, Size &fmtn, bool,
|
||||
const char *fmt) {
|
||||
Size written = 0;
|
||||
detail::WriteSpec spec(fmt, false);
|
||||
if (spec.read_until_spec(writer, &written)) return -1;
|
||||
fmtn = 0;
|
||||
return written;
|
||||
|
@ -892,28 +872,26 @@ namespace detail {
|
|||
} /* namespace detail */
|
||||
|
||||
template<typename R, typename ...A>
|
||||
static inline octa::Ptrdiff format(R &&writer, octa::Size &fmtn,
|
||||
const char *fmt, const A &...args) {
|
||||
return octa::detail::format_impl(writer, fmtn, false, fmt, args...);
|
||||
static inline Ptrdiff format(R &&writer, Size &fmtn, const char *fmt,
|
||||
const A &...args) {
|
||||
return detail::format_impl(writer, fmtn, false, fmt, args...);
|
||||
}
|
||||
|
||||
template<typename R, typename AL, typename ...A>
|
||||
octa::Ptrdiff format(R &&writer, octa::Size &fmtn,
|
||||
const octa::AnyString<AL> &fmt,
|
||||
const A &...args) {
|
||||
Ptrdiff format(R &&writer, Size &fmtn, const AnyString<AL> &fmt,
|
||||
const A &...args) {
|
||||
return format(writer, fmtn, fmt.data(), args...);
|
||||
}
|
||||
|
||||
template<typename R, typename ...A>
|
||||
octa::Ptrdiff format(R &&writer, const char *fmt, const A &...args) {
|
||||
octa::Size fmtn = 0;
|
||||
Ptrdiff format(R &&writer, const char *fmt, const A &...args) {
|
||||
Size fmtn = 0;
|
||||
return format(writer, fmtn, fmt, args...);
|
||||
}
|
||||
|
||||
template<typename R, typename AL, typename ...A>
|
||||
octa::Ptrdiff format(R &&writer, const octa::AnyString<AL> &fmt,
|
||||
const A &...args) {
|
||||
octa::Size fmtn = 0;
|
||||
Ptrdiff format(R &&writer, const AnyString<AL> &fmt, const A &...args) {
|
||||
Size fmtn = 0;
|
||||
return format(writer, fmtn, fmt.data(), args...);
|
||||
}
|
||||
|
||||
|
|
|
@ -96,8 +96,8 @@ template<typename T> BinaryNegate<T> not2(const T &fn) {
|
|||
|
||||
/* endian swap */
|
||||
|
||||
template<typename T, octa::Size N = sizeof(T),
|
||||
bool IsNum = octa::IsArithmetic<T>::value
|
||||
template<typename T, Size N = sizeof(T),
|
||||
bool IsNum = IsArithmetic<T>::value
|
||||
> struct EndianSwap;
|
||||
|
||||
template<typename T>
|
||||
|
@ -107,7 +107,7 @@ struct EndianSwap<T, 2, true> {
|
|||
T operator()(T v) const {
|
||||
union { T iv; uint16_t sv; } u;
|
||||
u.iv = v;
|
||||
u.sv = octa::endian_swap16(u.sv);
|
||||
u.sv = endian_swap16(u.sv);
|
||||
return u.iv;
|
||||
}
|
||||
};
|
||||
|
@ -119,7 +119,7 @@ struct EndianSwap<T, 4, true> {
|
|||
T operator()(T v) const {
|
||||
union { T iv; uint32_t sv; } u;
|
||||
u.iv = v;
|
||||
u.sv = octa::endian_swap32(u.sv);
|
||||
u.sv = endian_swap32(u.sv);
|
||||
return u.iv;
|
||||
}
|
||||
};
|
||||
|
@ -131,7 +131,7 @@ struct EndianSwap<T, 8, true> {
|
|||
T operator()(T v) const {
|
||||
union { T iv; uint64_t sv; } u;
|
||||
u.iv = v;
|
||||
u.sv = octa::endian_swap64(u.sv);
|
||||
u.sv = endian_swap64(u.sv);
|
||||
return u.iv;
|
||||
}
|
||||
};
|
||||
|
@ -140,8 +140,8 @@ template<typename T>
|
|||
T endian_swap(T x) { return EndianSwap<T>()(x); }
|
||||
|
||||
namespace detail {
|
||||
template<typename T, octa::Size N = sizeof(T),
|
||||
bool IsNum = octa::IsArithmetic<T>::value
|
||||
template<typename T, Size N = sizeof(T),
|
||||
bool IsNum = IsArithmetic<T>::value
|
||||
> struct EndianSame;
|
||||
|
||||
template<typename T>
|
||||
|
@ -165,11 +165,11 @@ namespace detail {
|
|||
}
|
||||
|
||||
#if OCTA_BYTE_ORDER == OCTA_ENDIAN_LIL
|
||||
template<typename T> struct FromLilEndian: octa::detail::EndianSame<T> {};
|
||||
template<typename T> struct FromLilEndian: detail::EndianSame<T> {};
|
||||
template<typename T> struct FromBigEndian: EndianSwap<T> {};
|
||||
#else
|
||||
template<typename T> struct FromLilEndian: EndianSwap<T> {};
|
||||
template<typename T> struct FromBigEndian: octa::detail::EndianSame<T> {};
|
||||
template<typename T> struct FromBigEndian: detail::EndianSame<T> {};
|
||||
#endif
|
||||
|
||||
template<typename T> T from_lil_endian(T x) { return FromLilEndian<T>()(x); }
|
||||
|
@ -179,9 +179,9 @@ template<typename T> T from_big_endian(T x) { return FromBigEndian<T>()(x); }
|
|||
|
||||
template<typename T> struct ToHash {
|
||||
using Argument = T;
|
||||
using Result = octa::Size;
|
||||
using Result = Size;
|
||||
|
||||
octa::Size operator()(const T &v) const {
|
||||
Size operator()(const T &v) const {
|
||||
return v.to_hash();
|
||||
}
|
||||
};
|
||||
|
@ -189,15 +189,15 @@ template<typename T> struct ToHash {
|
|||
namespace detail {
|
||||
template<typename T> struct ToHashBase {
|
||||
using Argument = T;
|
||||
using Result = octa::Size;
|
||||
using Result = Size;
|
||||
|
||||
octa::Size operator()(T v) const {
|
||||
return octa::Size(v);
|
||||
Size operator()(T v) const {
|
||||
return Size(v);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#define OCTA_HASH_BASIC(T) template<> struct ToHash<T>: octa::detail::ToHashBase<T> {};
|
||||
#define OCTA_HASH_BASIC(T) template<> struct ToHash<T>: detail::ToHashBase<T> {};
|
||||
|
||||
OCTA_HASH_BASIC(bool)
|
||||
OCTA_HASH_BASIC(char)
|
||||
|
@ -205,35 +205,35 @@ OCTA_HASH_BASIC(short)
|
|||
OCTA_HASH_BASIC(int)
|
||||
OCTA_HASH_BASIC(long)
|
||||
|
||||
OCTA_HASH_BASIC(octa::sbyte)
|
||||
OCTA_HASH_BASIC(octa::byte)
|
||||
OCTA_HASH_BASIC(octa::ushort)
|
||||
OCTA_HASH_BASIC(octa::uint)
|
||||
OCTA_HASH_BASIC(octa::ulong)
|
||||
OCTA_HASH_BASIC(sbyte)
|
||||
OCTA_HASH_BASIC(byte)
|
||||
OCTA_HASH_BASIC(ushort)
|
||||
OCTA_HASH_BASIC(uint)
|
||||
OCTA_HASH_BASIC(ulong)
|
||||
|
||||
OCTA_HASH_BASIC(octa::Char16)
|
||||
OCTA_HASH_BASIC(octa::Char32)
|
||||
OCTA_HASH_BASIC(octa::Wchar)
|
||||
OCTA_HASH_BASIC(Char16)
|
||||
OCTA_HASH_BASIC(Char32)
|
||||
OCTA_HASH_BASIC(Wchar)
|
||||
|
||||
#undef OCTA_HASH_BASIC
|
||||
|
||||
namespace detail {
|
||||
static inline Size mem_hash(const void *p, octa::Size l) {
|
||||
const octa::byte *d = (const octa::byte *)p;
|
||||
octa::Size h = 5381;
|
||||
static inline Size mem_hash(const void *p, Size l) {
|
||||
const byte *d = (const byte *)p;
|
||||
Size h = 5381;
|
||||
for (Size i = 0; i < l; ++i) h = ((h << 5) + h) ^ d[i];
|
||||
return h;
|
||||
}
|
||||
|
||||
template<typename T, octa::Size = sizeof(T) / sizeof(octa::Size)>
|
||||
template<typename T, Size = sizeof(T) / sizeof(Size)>
|
||||
struct ScalarHash;
|
||||
|
||||
template<typename T> struct ScalarHash<T, 0> {
|
||||
using Argument = T;
|
||||
using Result = octa::Size;
|
||||
using Result = Size;
|
||||
|
||||
octa::Size operator()(T v) const {
|
||||
union { T v; octa::Size h; } u;
|
||||
Size operator()(T v) const {
|
||||
union { T v; Size h; } u;
|
||||
u.h = 0;
|
||||
u.v = v;
|
||||
return u.h;
|
||||
|
@ -242,10 +242,10 @@ namespace detail {
|
|||
|
||||
template<typename T> struct ScalarHash<T, 1> {
|
||||
using Argument = T;
|
||||
using Result = octa::Size;
|
||||
using Result = Size;
|
||||
|
||||
octa::Size operator()(T v) const {
|
||||
union { T v; octa::Size h; } u;
|
||||
Size operator()(T v) const {
|
||||
union { T v; Size h; } u;
|
||||
u.v = v;
|
||||
return u.h;
|
||||
}
|
||||
|
@ -253,10 +253,10 @@ namespace detail {
|
|||
|
||||
template<typename T> struct ScalarHash<T, 2> {
|
||||
using Argument = T;
|
||||
using Result = octa::Size;
|
||||
using Result = Size;
|
||||
|
||||
octa::Size operator()(T v) const {
|
||||
union { T v; struct { octa::Size h1, h2; }; } u;
|
||||
Size operator()(T v) const {
|
||||
union { T v; struct { Size h1, h2; }; } u;
|
||||
u.v = v;
|
||||
return mem_hash((const void *)&u, sizeof(u));
|
||||
}
|
||||
|
@ -264,10 +264,10 @@ namespace detail {
|
|||
|
||||
template<typename T> struct ScalarHash<T, 3> {
|
||||
using Argument = T;
|
||||
using Result = octa::Size;
|
||||
using Result = Size;
|
||||
|
||||
octa::Size operator()(T v) const {
|
||||
union { T v; struct { octa::Size h1, h2, h3; }; } u;
|
||||
Size operator()(T v) const {
|
||||
union { T v; struct { Size h1, h2, h3; }; } u;
|
||||
u.v = v;
|
||||
return mem_hash((const void *)&u, sizeof(u));
|
||||
}
|
||||
|
@ -275,76 +275,76 @@ namespace detail {
|
|||
|
||||
template<typename T> struct ScalarHash<T, 4> {
|
||||
using Argument = T;
|
||||
using Result = octa::Size;
|
||||
using Result = Size;
|
||||
|
||||
octa::Size operator()(T v) const {
|
||||
union { T v; struct { octa::Size h1, h2, h3, h4; }; } u;
|
||||
Size operator()(T v) const {
|
||||
union { T v; struct { Size h1, h2, h3, h4; }; } u;
|
||||
u.v = v;
|
||||
return mem_hash((const void *)&u, sizeof(u));
|
||||
}
|
||||
};
|
||||
} /* namespace detail */
|
||||
|
||||
template<> struct ToHash<octa::llong>: octa::detail::ScalarHash<octa::llong> {};
|
||||
template<> struct ToHash<octa::ullong>: octa::detail::ScalarHash<octa::ullong> {};
|
||||
template<> struct ToHash<llong>: detail::ScalarHash<llong> {};
|
||||
template<> struct ToHash<ullong>: detail::ScalarHash<ullong> {};
|
||||
|
||||
template<> struct ToHash<float>: octa::detail::ScalarHash<float> {
|
||||
octa::Size operator()(float v) const {
|
||||
template<> struct ToHash<float>: detail::ScalarHash<float> {
|
||||
Size operator()(float v) const {
|
||||
if (v == 0) return 0;
|
||||
return octa::detail::ScalarHash<float>::operator()(v);
|
||||
return detail::ScalarHash<float>::operator()(v);
|
||||
}
|
||||
};
|
||||
|
||||
template<> struct ToHash<double>: octa::detail::ScalarHash<double> {
|
||||
octa::Size operator()(double v) const {
|
||||
template<> struct ToHash<double>: detail::ScalarHash<double> {
|
||||
Size operator()(double v) const {
|
||||
if (v == 0) return 0;
|
||||
return octa::detail::ScalarHash<double>::operator()(v);
|
||||
return detail::ScalarHash<double>::operator()(v);
|
||||
}
|
||||
};
|
||||
|
||||
template<> struct ToHash<octa::ldouble>: octa::detail::ScalarHash<octa::ldouble> {
|
||||
octa::Size operator()(octa::ldouble v) const {
|
||||
template<> struct ToHash<ldouble>: detail::ScalarHash<ldouble> {
|
||||
Size operator()(ldouble v) const {
|
||||
if (v == 0) return 0;
|
||||
#ifdef __i386__
|
||||
union { octa::ldouble v; struct { octa::Size h1, h2, h3, h4; }; } u;
|
||||
union { ldouble v; struct { Size h1, h2, h3, h4; }; } u;
|
||||
u.h1 = u.h2 = u.h3 = u.h4 = 0;
|
||||
u.v = v;
|
||||
return (u.h1 ^ u.h2 ^ u.h3 ^ u.h4);
|
||||
#else
|
||||
#ifdef __x86_64__
|
||||
union { octa::ldouble v; struct { octa::Size h1, h2; }; } u;
|
||||
union { ldouble v; struct { Size h1, h2; }; } u;
|
||||
u.h1 = u.h2 = 0;
|
||||
u.v = v;
|
||||
return (u.h1 ^ u.h2);
|
||||
#else
|
||||
return octa::detail::ScalarHash<octa::ldouble>::operator()(v);
|
||||
return detail::ScalarHash<ldouble>::operator()(v);
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
};
|
||||
|
||||
namespace detail {
|
||||
template<typename T, bool = octa::IsSame<octa::RemoveConst<T>, char>::value>
|
||||
template<typename T, bool = IsSame<RemoveConst<T>, char>::value>
|
||||
struct ToHashPtr {
|
||||
using Argument = T *;
|
||||
using Result = octa::Size;
|
||||
octa::Size operator()(T *v) const {
|
||||
union { T *v; octa::Size h; } u;
|
||||
using Result = Size;
|
||||
Size operator()(T *v) const {
|
||||
union { T *v; Size h; } u;
|
||||
u.v = v;
|
||||
return octa::detail::mem_hash((const void *)&u, sizeof(u));
|
||||
return detail::mem_hash((const void *)&u, sizeof(u));
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T> struct ToHashPtr<T, true> {
|
||||
using Argument = T *;
|
||||
using Result = octa::Size;
|
||||
octa::Size operator()(T *v) const {
|
||||
return octa::detail::mem_hash(v, strlen(v));
|
||||
using Result = Size;
|
||||
Size operator()(T *v) const {
|
||||
return detail::mem_hash(v, strlen(v));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
template<typename T> struct ToHash<T *>: octa::detail::ToHashPtr<T> {};
|
||||
template<typename T> struct ToHash<T *>: detail::ToHashPtr<T> {};
|
||||
|
||||
template<typename T>
|
||||
typename ToHash<T>::Result to_hash(const T &v) {
|
||||
|
@ -446,8 +446,8 @@ namespace detail {
|
|||
} /* namespace detail */
|
||||
|
||||
template<typename R, typename T>
|
||||
octa::detail::MemFn<R, T> mem_fn(R T:: *ptr) {
|
||||
return octa::detail::MemFn<R, T>(ptr);
|
||||
detail::MemFn<R, T> mem_fn(R T:: *ptr) {
|
||||
return detail::MemFn<R, T>(ptr);
|
||||
}
|
||||
|
||||
/* function impl
|
||||
|
@ -465,7 +465,7 @@ namespace detail {
|
|||
struct FunctorInPlace {
|
||||
static constexpr bool value = sizeof(T) <= sizeof(FunctorData)
|
||||
&& (alignof(FunctorData) % alignof(T)) == 0
|
||||
&& octa::IsMoveConstructible<T>::value;
|
||||
&& IsMoveConstructible<T>::value;
|
||||
};
|
||||
|
||||
struct FunctionManager;
|
||||
|
@ -498,15 +498,15 @@ namespace detail {
|
|||
struct FunctorDataManager {
|
||||
template<typename R, typename ...Args>
|
||||
static R call(const FunctorData &s, Args ...args) {
|
||||
return ((T &)s)(octa::forward<Args>(args)...);
|
||||
return ((T &)s)(forward<Args>(args)...);
|
||||
}
|
||||
|
||||
static void store_f(FmStorage &s, T v) {
|
||||
new (&get_ref(s)) T(octa::forward<T>(v));
|
||||
new (&get_ref(s)) T(forward<T>(v));
|
||||
}
|
||||
|
||||
static void move_f(FmStorage &lhs, FmStorage &&rhs) {
|
||||
new (&get_ref(lhs)) T(octa::move(get_ref(rhs)));
|
||||
new (&get_ref(lhs)) T(move(get_ref(rhs)));
|
||||
}
|
||||
|
||||
static void destroy_f(A &, FmStorage &s) {
|
||||
|
@ -529,20 +529,18 @@ namespace detail {
|
|||
> {
|
||||
template<typename R, typename ...Args>
|
||||
static R call(const FunctorData &s, Args ...args) {
|
||||
return (*(octa::AllocatorPointer<A> &)s)
|
||||
(octa::forward<Args>(args)...);
|
||||
return (*(AllocatorPointer<A> &)s)(forward<Args>(args)...);
|
||||
}
|
||||
|
||||
static void store_f(FmStorage &s, T v) {
|
||||
A &a = s.get_alloc<A>();
|
||||
AllocatorPointer<A> *ptr = new (&get_ptr_ref(s))
|
||||
AllocatorPointer<A>(allocator_allocate(a, 1));
|
||||
allocator_construct(a, *ptr, octa::forward<T>(v));
|
||||
allocator_construct(a, *ptr, forward<T>(v));
|
||||
}
|
||||
|
||||
static void move_f(FmStorage &lhs, FmStorage &&rhs) {
|
||||
new (&get_ptr_ref(lhs)) AllocatorPointer<A>(octa::move(
|
||||
get_ptr_ref(rhs)));
|
||||
new (&get_ptr_ref(lhs)) AllocatorPointer<A>(move(get_ptr_ref(rhs)));
|
||||
get_ptr_ref(rhs) = nullptr;
|
||||
}
|
||||
|
||||
|
@ -572,7 +570,7 @@ namespace detail {
|
|||
|
||||
template<typename T, typename A>
|
||||
static void create_fm(FmStorage &s, A &&a) {
|
||||
new (&s.get_alloc<A>()) A(octa::move(a));
|
||||
new (&s.get_alloc<A>()) A(move(a));
|
||||
s.manager = &get_default_fm<T, A>();
|
||||
}
|
||||
|
||||
|
@ -599,9 +597,9 @@ namespace detail {
|
|||
static void call_move_and_destroy(FmStorage &lhs,
|
||||
FmStorage &&rhs) {
|
||||
using Spec = FunctorDataManager<T, A>;
|
||||
Spec::move_f(lhs, octa::move(rhs));
|
||||
Spec::move_f(lhs, move(rhs));
|
||||
Spec::destroy_f(rhs.get_alloc<A>(), rhs);
|
||||
create_fm<T, A>(lhs, octa::move(rhs.get_alloc<A>()));
|
||||
create_fm<T, A>(lhs, move(rhs.get_alloc<A>()));
|
||||
rhs.get_alloc<A>().~A();
|
||||
}
|
||||
|
||||
|
@ -665,7 +663,7 @@ namespace detail {
|
|||
|
||||
template<typename T>
|
||||
T func_to_functor(T &&f) {
|
||||
return octa::forward<T>(f);
|
||||
return forward<T>(f);
|
||||
}
|
||||
|
||||
template<typename RR, typename T, typename ...AA>
|
||||
|
@ -685,24 +683,24 @@ namespace detail {
|
|||
struct Nat {};
|
||||
|
||||
template<typename U>
|
||||
static decltype(func_to_functor(octa::declval<U>())
|
||||
(octa::declval<A>()...)) test(U *);
|
||||
static decltype(func_to_functor(declval<U>()) (declval<A>()...))
|
||||
test(U *);
|
||||
template<typename>
|
||||
static Nat test(...);
|
||||
|
||||
static constexpr bool value = octa::IsConvertible<
|
||||
static constexpr bool value = IsConvertible<
|
||||
decltype(test<T>(nullptr)), R
|
||||
>::value;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
using FunctorType = decltype(func_to_functor(octa::declval<T>()));
|
||||
using FunctorType = decltype(func_to_functor(declval<T>()));
|
||||
} /* namespace detail */
|
||||
|
||||
template<typename R, typename ...Args>
|
||||
struct Function<R(Args...)>: octa::detail::FunctionBase<R, Args...> {
|
||||
Function( ) { init_empty(); }
|
||||
Function(octa::Nullptr) { init_empty(); }
|
||||
struct Function<R(Args...)>: detail::FunctionBase<R, Args...> {
|
||||
Function( ) { init_empty(); }
|
||||
Function(Nullptr) { init_empty(); }
|
||||
|
||||
Function(Function &&f) {
|
||||
init_empty();
|
||||
|
@ -713,45 +711,45 @@ struct Function<R(Args...)>: octa::detail::FunctionBase<R, Args...> {
|
|||
f.p_stor.manager->call_copyf(p_stor, f.p_stor);
|
||||
}
|
||||
|
||||
template<typename T, typename = octa::EnableIf<
|
||||
octa::detail::IsValidFunctor<T, R(Args...)>::value
|
||||
template<typename T, typename = EnableIf<
|
||||
detail::IsValidFunctor<T, R(Args...)>::value
|
||||
>> Function(T f) {
|
||||
if (func_is_null(f)) {
|
||||
init_empty();
|
||||
return;
|
||||
}
|
||||
initialize(octa::detail::func_to_functor(octa::forward<T>(f)),
|
||||
octa::Allocator<octa::detail::FunctorType<T>>());
|
||||
initialize(detail::func_to_functor(forward<T>(f)),
|
||||
Allocator<detail::FunctorType<T>>());
|
||||
}
|
||||
|
||||
template<typename A>
|
||||
Function(octa::AllocatorArg, const A &) { init_empty(); }
|
||||
Function(AllocatorArg, const A &) { init_empty(); }
|
||||
|
||||
template<typename A>
|
||||
Function(octa::AllocatorArg, const A &, octa::Nullptr) { init_empty(); }
|
||||
Function(AllocatorArg, const A &, Nullptr) { init_empty(); }
|
||||
|
||||
template<typename A>
|
||||
Function(octa::AllocatorArg, const A &, Function &&f) {
|
||||
Function(AllocatorArg, const A &, Function &&f) {
|
||||
init_empty();
|
||||
swap(f);
|
||||
}
|
||||
|
||||
template<typename A>
|
||||
Function(octa::AllocatorArg, const A &a, const Function &f):
|
||||
Function(AllocatorArg, const A &a, const Function &f):
|
||||
p_call(f.p_call) {
|
||||
const octa::detail::FunctionManager *mfa
|
||||
= &octa::detail::get_default_fm<octa::AllocatorValue<A>, A>();
|
||||
const detail::FunctionManager *mfa
|
||||
= &detail::get_default_fm<AllocatorValue<A>, A>();
|
||||
if (f.p_stor.manager == mfa) {
|
||||
octa::detail::create_fm<octa::AllocatorValue<A>, A>(p_stor, A(a));
|
||||
detail::create_fm<AllocatorValue<A>, A>(p_stor, A(a));
|
||||
mfa->call_copyf_fo(p_stor, f.p_stor);
|
||||
return;
|
||||
}
|
||||
|
||||
using AA = AllocatorRebind<A, Function>;
|
||||
const octa::detail::FunctionManager *mff
|
||||
= &octa::detail::get_default_fm<Function, AA>();
|
||||
const detail::FunctionManager *mff
|
||||
= &detail::get_default_fm<Function, AA>();
|
||||
if (f.p_stor.manager == mff) {
|
||||
octa::detail::create_fm<Function, AA>(p_stor, AA(a));
|
||||
detail::create_fm<Function, AA>(p_stor, AA(a));
|
||||
mff->call_copyf_fo(p_stor, f.P_stor);
|
||||
return;
|
||||
}
|
||||
|
@ -759,14 +757,14 @@ struct Function<R(Args...)>: octa::detail::FunctionBase<R, Args...> {
|
|||
initialize(f, AA(a));
|
||||
}
|
||||
|
||||
template<typename A, typename T, typename = octa::EnableIf<
|
||||
octa::detail::IsValidFunctor<T, R(Args...)>::value
|
||||
>> Function(octa::AllocatorArg, const A &a, T f) {
|
||||
template<typename A, typename T, typename = EnableIf<
|
||||
detail::IsValidFunctor<T, R(Args...)>::value
|
||||
>> Function(AllocatorArg, const A &a, T f) {
|
||||
if (func_is_null(f)) {
|
||||
init_empty();
|
||||
return;
|
||||
}
|
||||
initialize(octa::detail::func_to_functor(octa::forward<T>(f)), A(a));
|
||||
initialize(detail::func_to_functor(forward<T>(f)), A(a));
|
||||
}
|
||||
|
||||
~Function() {
|
||||
|
@ -786,45 +784,41 @@ struct Function<R(Args...)>: octa::detail::FunctionBase<R, Args...> {
|
|||
};
|
||||
|
||||
R operator()(Args ...args) const {
|
||||
return p_call(p_stor.data, octa::forward<Args>(args)...);
|
||||
return p_call(p_stor.data, forward<Args>(args)...);
|
||||
}
|
||||
|
||||
template<typename F, typename A>
|
||||
void assign(F &&f, const A &a) {
|
||||
Function(octa::allocator_arg, a, octa::forward<F>(f)).swap(*this);
|
||||
Function(allocator_arg, a, forward<F>(f)).swap(*this);
|
||||
}
|
||||
|
||||
void swap(Function &f) {
|
||||
octa::detail::FmStorage tmp;
|
||||
f.p_stor.manager->call_move_and_destroyf(tmp,
|
||||
octa::move(f.p_stor));
|
||||
p_stor.manager->call_move_and_destroyf(f.p_stor,
|
||||
octa::move(p_stor));
|
||||
tmp.manager->call_move_and_destroyf(p_stor,
|
||||
octa::move(tmp));
|
||||
detail::FmStorage tmp;
|
||||
f.p_stor.manager->call_move_and_destroyf(tmp, move(f.p_stor));
|
||||
p_stor.manager->call_move_and_destroyf(f.p_stor, move(p_stor));
|
||||
tmp.manager->call_move_and_destroyf(p_stor, move(tmp));
|
||||
octa::swap(p_call, f.p_call);
|
||||
}
|
||||
|
||||
operator bool() const { return p_call != nullptr; }
|
||||
|
||||
private:
|
||||
octa::detail::FmStorage p_stor;
|
||||
R (*p_call)(const octa::detail::FunctorData &, Args...);
|
||||
detail::FmStorage p_stor;
|
||||
R (*p_call)(const detail::FunctorData &, Args...);
|
||||
|
||||
template<typename T, typename A>
|
||||
void initialize(T &&f, A &&a) {
|
||||
p_call = &octa::detail::FunctorDataManager<T, A>::template call<R, Args...>;
|
||||
octa::detail::create_fm<T, A>(p_stor, octa::forward<A>(a));
|
||||
octa::detail::FunctorDataManager<T, A>::store_f(p_stor,
|
||||
octa::forward<T>(f));
|
||||
p_call = &detail::FunctorDataManager<T, A>::template call<R, Args...>;
|
||||
detail::create_fm<T, A>(p_stor, forward<A>(a));
|
||||
detail::FunctorDataManager<T, A>::store_f(p_stor, forward<T>(f));
|
||||
}
|
||||
|
||||
void init_empty() {
|
||||
using emptyf = R(*)(Args...);
|
||||
using emptya = octa::Allocator<emptyf>;
|
||||
using emptya = Allocator<emptyf>;
|
||||
p_call = nullptr;
|
||||
octa::detail::create_fm<emptyf, emptya>(p_stor, emptya());
|
||||
octa::detail::FunctorDataManager<emptyf, emptya>::store_f(p_stor,
|
||||
detail::create_fm<emptyf, emptya>(p_stor, emptya());
|
||||
detail::FunctorDataManager<emptyf, emptya>::store_f(p_stor,
|
||||
nullptr);
|
||||
}
|
||||
|
||||
|
@ -847,16 +841,16 @@ private:
|
|||
};
|
||||
|
||||
template<typename T>
|
||||
bool operator==(octa::Nullptr, const Function<T> &rhs) { return !rhs; }
|
||||
bool operator==(Nullptr, const Function<T> &rhs) { return !rhs; }
|
||||
|
||||
template<typename T>
|
||||
bool operator==(const Function<T> &lhs, octa::Nullptr) { return !lhs; }
|
||||
bool operator==(const Function<T> &lhs, Nullptr) { return !lhs; }
|
||||
|
||||
template<typename T>
|
||||
bool operator!=(octa::Nullptr, const Function<T> &rhs) { return rhs; }
|
||||
bool operator!=(Nullptr, const Function<T> &rhs) { return rhs; }
|
||||
|
||||
template<typename T>
|
||||
bool operator!=(const Function<T> &lhs, octa::Nullptr) { return lhs; }
|
||||
bool operator!=(const Function<T> &lhs, Nullptr) { return lhs; }
|
||||
|
||||
namespace detail {
|
||||
template<typename F>
|
||||
|
@ -865,7 +859,7 @@ namespace detail {
|
|||
template<typename C, typename R, typename ...A>
|
||||
struct DcLambdaTypes<R (C::*)(A...) const> {
|
||||
using Ptr = R (*)(A...);
|
||||
using Obj = octa::Function<R(A...)>;
|
||||
using Obj = Function<R(A...)>;
|
||||
};
|
||||
|
||||
template<typename F>
|
||||
|
@ -874,7 +868,7 @@ namespace detail {
|
|||
static char test(typename DcLambdaTypes<FF>::Ptr);
|
||||
template<typename FF>
|
||||
static int test(...);
|
||||
static constexpr bool value = (sizeof(test<F>(octa::declval<F>())) == 1);
|
||||
static constexpr bool value = (sizeof(test<F>(declval<F>())) == 1);
|
||||
};
|
||||
|
||||
template<typename F, bool = DcFuncTest<F>::value>
|
||||
|
@ -887,8 +881,8 @@ namespace detail {
|
|||
using Type = typename DcLambdaTypes<F>::Ptr;
|
||||
};
|
||||
|
||||
template<typename F, bool = octa::IsDefaultConstructible<F>::value &&
|
||||
octa::IsMoveConstructible<F>::value
|
||||
template<typename F, bool = IsDefaultConstructible<F>::value &&
|
||||
IsMoveConstructible<F>::value
|
||||
> struct DcFuncTypeObj {
|
||||
using Type = typename DcFuncTypeObjBase<F>::Type;
|
||||
};
|
||||
|
@ -898,7 +892,7 @@ namespace detail {
|
|||
using Type = F;
|
||||
};
|
||||
|
||||
template<typename F, bool = octa::IsClass<F>::value>
|
||||
template<typename F, bool = IsClass<F>::value>
|
||||
struct DcFuncType {
|
||||
using Type = F;
|
||||
};
|
||||
|
@ -910,7 +904,7 @@ namespace detail {
|
|||
}
|
||||
|
||||
template<typename F> using FunctionMakeDefaultConstructible
|
||||
= typename octa::detail::DcFuncType<F>::Type;
|
||||
= typename detail::DcFuncType<F>::Type;
|
||||
|
||||
} /* namespace octa */
|
||||
|
||||
|
|
|
@ -39,13 +39,13 @@ namespace octa {
|
|||
template<typename T> using InitializerList = std::initializer_list<T>;
|
||||
|
||||
template<typename T>
|
||||
octa::PointerRange<const T> iter(std::initializer_list<T> init) {
|
||||
return octa::PointerRange<const T>(init.begin(), init.end());
|
||||
PointerRange<const T> iter(std::initializer_list<T> init) {
|
||||
return PointerRange<const T>(init.begin(), init.end());
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
octa::PointerRange<const T> citer(std::initializer_list<T> init) {
|
||||
return octa::PointerRange<const T>(init.begin(), init.end());
|
||||
PointerRange<const T> citer(std::initializer_list<T> init) {
|
||||
return PointerRange<const T>(init.begin(), init.end());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -24,15 +24,15 @@ namespace detail {
|
|||
};
|
||||
|
||||
template<typename R>
|
||||
static inline octa::Size estimate_hrsize(const R &range,
|
||||
octa::EnableIf<octa::IsFiniteRandomAccessRange<R>::value, bool> = true
|
||||
static inline Size estimate_hrsize(const R &range,
|
||||
EnableIf<IsFiniteRandomAccessRange<R>::value, bool> = true
|
||||
) {
|
||||
return range.size();
|
||||
}
|
||||
|
||||
template<typename R>
|
||||
static inline octa::Size estimate_hrsize(const R &,
|
||||
octa::EnableIf<!octa::IsFiniteRandomAccessRange<R>::value, bool> = true
|
||||
static inline Size estimate_hrsize(const R &,
|
||||
EnableIf<!IsFiniteRandomAccessRange<R>::value, bool> = true
|
||||
) {
|
||||
/* we have no idea how big the range actually is */
|
||||
return 16;
|
||||
|
@ -40,12 +40,12 @@ namespace detail {
|
|||
}
|
||||
|
||||
template<typename T>
|
||||
struct HashRange: octa::InputRange<HashRange<T>, octa::ForwardRangeTag, T> {
|
||||
struct HashRange: InputRange<HashRange<T>, ForwardRangeTag, T> {
|
||||
private:
|
||||
template<typename U>
|
||||
friend struct HashRange;
|
||||
|
||||
using Chain = octa::detail::HashChain<T>;
|
||||
using Chain = detail::HashChain<T>;
|
||||
|
||||
Chain **p_beg;
|
||||
Chain **p_end;
|
||||
|
@ -57,7 +57,7 @@ private:
|
|||
if (p_beg != p_end) p_node = p_beg[0];
|
||||
}
|
||||
public:
|
||||
HashRange() = delete;
|
||||
HashRange(): p_beg(nullptr), p_end(nullptr), p_node(nullptr) {}
|
||||
HashRange(const HashRange &v): p_beg(v.p_beg), p_end(v.p_end),
|
||||
p_node(v.p_node) {}
|
||||
HashRange(Chain **beg, Chain **end): p_beg(beg), p_end(end), p_node() {
|
||||
|
@ -67,9 +67,9 @@ public:
|
|||
p_node(node) {}
|
||||
|
||||
template<typename U>
|
||||
HashRange(const HashRange<U> &v, octa::EnableIf<
|
||||
octa::IsSame<RemoveCv<T>, RemoveCv<U>>::value &&
|
||||
octa::IsConvertible<U *, T *>::value, bool
|
||||
HashRange(const HashRange<U> &v, EnableIf<
|
||||
IsSame<RemoveCv<T>, RemoveCv<U>>::value &&
|
||||
IsConvertible<U *, T *>::value, bool
|
||||
> = true): p_beg((Chain **)v.p_beg), p_end((Chain **)v.p_end),
|
||||
p_node((Chain *)v.p_node) {}
|
||||
|
||||
|
@ -99,22 +99,22 @@ public:
|
|||
};
|
||||
|
||||
template<typename T>
|
||||
struct BucketRange: octa::InputRange<BucketRange<T>, octa::ForwardRangeTag, T> {
|
||||
struct BucketRange: InputRange<BucketRange<T>, ForwardRangeTag, T> {
|
||||
private:
|
||||
template<typename U>
|
||||
friend struct BucketRange;
|
||||
|
||||
using Chain = octa::detail::HashChain<T>;
|
||||
using Chain = detail::HashChain<T>;
|
||||
Chain *p_node;
|
||||
public:
|
||||
BucketRange() = delete;
|
||||
BucketRange(): p_node(nullptr) {}
|
||||
BucketRange(Chain *node): p_node(node) {}
|
||||
BucketRange(const BucketRange &v): p_node(v.p_node) {}
|
||||
|
||||
template<typename U>
|
||||
BucketRange(const BucketRange<U> &v, octa::EnableIf<
|
||||
octa::IsSame<RemoveCv<T>, RemoveCv<U>>::value &&
|
||||
octa::IsConvertible<U *, T *>::value, bool
|
||||
BucketRange(const BucketRange<U> &v, EnableIf<
|
||||
IsSame<RemoveCv<T>, RemoveCv<U>>::value &&
|
||||
IsConvertible<U *, T *>::value, bool
|
||||
> = true): p_node((Chain *)v.p_node) {}
|
||||
|
||||
BucketRange &operator=(const BucketRange &v) {
|
||||
|
@ -149,51 +149,51 @@ namespace detail {
|
|||
bool Multihash
|
||||
> struct Hashtable {
|
||||
private:
|
||||
static constexpr octa::Size CHUNKSIZE = 64;
|
||||
static constexpr Size CHUNKSIZE = 64;
|
||||
|
||||
using Chain = octa::detail::HashChain<E>;
|
||||
using Chain = detail::HashChain<E>;
|
||||
|
||||
struct Chunk {
|
||||
Chain chains[CHUNKSIZE];
|
||||
Chunk *next;
|
||||
};
|
||||
|
||||
octa::Size p_size;
|
||||
octa::Size p_len;
|
||||
Size p_size;
|
||||
Size p_len;
|
||||
|
||||
Chunk *p_chunks;
|
||||
Chain *p_unused;
|
||||
|
||||
using CPA = octa::AllocatorRebind<A, Chain *>;
|
||||
using CHA = octa::AllocatorRebind<A, Chunk>;
|
||||
using CPA = AllocatorRebind<A, Chain *>;
|
||||
using CHA = AllocatorRebind<A, Chunk>;
|
||||
|
||||
using CoreAllocPair = octa::detail::CompressedPair<CPA, CHA>;
|
||||
using AllocPair = octa::detail::CompressedPair<A, CoreAllocPair>;
|
||||
using FuncPair = octa::detail::CompressedPair<H, C>;
|
||||
using FAPair = octa::detail::CompressedPair<AllocPair, FuncPair>;
|
||||
using DataPair = octa::detail::CompressedPair<Chain **, FAPair>;
|
||||
using CoreAllocPair = detail::CompressedPair<CPA, CHA>;
|
||||
using AllocPair = detail::CompressedPair<A, CoreAllocPair>;
|
||||
using FuncPair = detail::CompressedPair<H, C>;
|
||||
using FAPair = detail::CompressedPair<AllocPair, FuncPair>;
|
||||
using DataPair = detail::CompressedPair<Chain **, FAPair>;
|
||||
|
||||
using Range = octa::HashRange<E>;
|
||||
using ConstRange = octa::HashRange<const E>;
|
||||
using LocalRange = octa::BucketRange<E>;
|
||||
using ConstLocalRange = octa::BucketRange<const E>;
|
||||
using Range = HashRange<E>;
|
||||
using ConstRange = HashRange<const E>;
|
||||
using LocalRange = BucketRange<E>;
|
||||
using ConstLocalRange = BucketRange<const E>;
|
||||
|
||||
DataPair p_data;
|
||||
|
||||
float p_maxlf;
|
||||
|
||||
Range iter_from(Chain *c, octa::Size h) {
|
||||
Range iter_from(Chain *c, Size h) {
|
||||
return Range(p_data.first() + h + 1,
|
||||
p_data.first() + bucket_count(), c);
|
||||
}
|
||||
ConstRange iter_from(Chain *c, octa::Size h) const {
|
||||
using RChain = octa::detail::HashChain<const E>;
|
||||
ConstRange iter_from(Chain *c, Size h) const {
|
||||
using RChain = detail::HashChain<const E>;
|
||||
return ConstRange((RChain **)(p_data.first() + h + 1),
|
||||
(RChain **)(p_data.first() + bucket_count()),
|
||||
(RChain *)c);
|
||||
}
|
||||
|
||||
bool find(const K &key, octa::Size &h, Chain *&oc) const {
|
||||
bool find(const K &key, Size &h, Chain *&oc) const {
|
||||
if (!p_size) return false;
|
||||
h = get_hash()(key) & (p_size - 1);
|
||||
for (Chain *c = p_data.first()[h]; c; c = c->next) {
|
||||
|
@ -205,10 +205,10 @@ private:
|
|||
return false;
|
||||
}
|
||||
|
||||
Chain *insert(octa::Size h) {
|
||||
Chain *insert(Size h) {
|
||||
if (!p_unused) {
|
||||
Chunk *chunk = octa::allocator_allocate(get_challoc(), 1);
|
||||
octa::allocator_construct(get_challoc(), chunk);
|
||||
Chunk *chunk = allocator_allocate(get_challoc(), 1);
|
||||
allocator_construct(get_challoc(), chunk);
|
||||
chunk->next = p_chunks;
|
||||
p_chunks = chunk;
|
||||
for (Size i = 0; i < (CHUNKSIZE - 1); ++i)
|
||||
|
@ -227,12 +227,12 @@ private:
|
|||
void delete_chunks(Chunk *chunks) {
|
||||
for (Chunk *nc; chunks; chunks = nc) {
|
||||
nc = chunks->next;
|
||||
octa::allocator_destroy(get_challoc(), chunks);
|
||||
octa::allocator_deallocate(get_challoc(), chunks, 1);
|
||||
allocator_destroy(get_challoc(), chunks);
|
||||
allocator_deallocate(get_challoc(), chunks, 1);
|
||||
}
|
||||
}
|
||||
|
||||
T *access_base(const K &key, octa::Size &h) const {
|
||||
T *access_base(const K &key, Size &h) const {
|
||||
if (!p_size) return NULL;
|
||||
h = get_hash()(key) & (p_size - 1);
|
||||
for (Chain *c = p_data.first()[h]; c; c = c->next) {
|
||||
|
@ -242,23 +242,23 @@ private:
|
|||
return NULL;
|
||||
}
|
||||
|
||||
void rehash_ahead(octa::Size n) {
|
||||
void rehash_ahead(Size n) {
|
||||
if (!bucket_count())
|
||||
reserve(n);
|
||||
else if ((float(size() + n) / bucket_count()) > max_load_factor())
|
||||
rehash(octa::Size((size() + 1) / max_load_factor()) * 2);
|
||||
rehash(Size((size() + 1) / max_load_factor()) * 2);
|
||||
}
|
||||
|
||||
protected:
|
||||
template<typename U>
|
||||
T &insert(octa::Size h, U &&key) {
|
||||
T &insert(Size h, U &&key) {
|
||||
Chain *c = insert(h);
|
||||
B::set_key(c->value, octa::forward<U>(key), get_alloc());
|
||||
B::set_key(c->value, forward<U>(key), get_alloc());
|
||||
return B::get_data(c->value);
|
||||
}
|
||||
|
||||
T &access_or_insert(const K &key) {
|
||||
octa::Size h = 0;
|
||||
Size h = 0;
|
||||
T *v = access_base(key, h);
|
||||
if (v) return *v;
|
||||
rehash_ahead(1);
|
||||
|
@ -266,22 +266,22 @@ protected:
|
|||
}
|
||||
|
||||
T &access_or_insert(K &&key) {
|
||||
octa::Size h = 0;
|
||||
Size h = 0;
|
||||
T *v = access_base(key, h);
|
||||
if (v) return *v;
|
||||
rehash_ahead(1);
|
||||
return insert(h, octa::move(key));
|
||||
return insert(h, move(key));
|
||||
}
|
||||
|
||||
T &access(const K &key) const {
|
||||
octa::Size h;
|
||||
Size h;
|
||||
return *access_base(key, h);
|
||||
}
|
||||
|
||||
template<typename R>
|
||||
void assign_range(R range) {
|
||||
clear();
|
||||
reserve_at_least(octa::detail::estimate_hrsize(range));
|
||||
reserve_at_least(detail::estimate_hrsize(range));
|
||||
for (; !range.empty(); range.pop_front())
|
||||
emplace(range.front());
|
||||
rehash_up();
|
||||
|
@ -311,13 +311,13 @@ protected:
|
|||
return p_data.second().first().second().second();
|
||||
}
|
||||
|
||||
Hashtable(octa::Size size, const H &hf, const C &eqf, const A &alloc):
|
||||
Hashtable(Size size, const H &hf, const C &eqf, const A &alloc):
|
||||
p_size(size), p_len(0), p_chunks(nullptr), p_unused(nullptr),
|
||||
p_data(nullptr, FAPair(AllocPair(alloc, CoreAllocPair(alloc, alloc)),
|
||||
FuncPair(hf, eqf))),
|
||||
p_maxlf(1.0f) {
|
||||
if (!size) return;
|
||||
p_data.first() = octa::allocator_allocate(get_cpalloc(), size);
|
||||
p_data.first() = allocator_allocate(get_cpalloc(), size);
|
||||
memset(p_data.first(), 0, size * sizeof(Chain *));
|
||||
}
|
||||
|
||||
|
@ -327,22 +327,22 @@ protected:
|
|||
FuncPair(ht.get_hash(), ht.get_eq()))),
|
||||
p_maxlf(ht.p_maxlf) {
|
||||
if (!p_size) return;
|
||||
p_data.first() = octa::allocator_allocate(get_cpalloc(), p_size);
|
||||
p_data.first() = allocator_allocate(get_cpalloc(), p_size);
|
||||
memset(p_data.first(), 0, p_size * sizeof(Chain *));
|
||||
Chain **och = ht.p_data.first();
|
||||
for (octa::Size h = 0; h < p_size; ++h) {
|
||||
for (Size h = 0; h < p_size; ++h) {
|
||||
Chain *oc = och[h];
|
||||
for (; oc; oc = oc->next) {
|
||||
Chain *nc = insert(h);
|
||||
octa::allocator_destroy(get_alloc(), &nc->value);
|
||||
octa::allocator_construct(get_alloc(), &nc->value, oc->value);
|
||||
allocator_destroy(get_alloc(), &nc->value);
|
||||
allocator_construct(get_alloc(), &nc->value, oc->value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Hashtable(Hashtable &&ht): p_size(ht.p_size), p_len(ht.p_len),
|
||||
p_chunks(ht.p_chunks), p_unused(ht.p_unused),
|
||||
p_data(octa::move(ht.p_data)), p_maxlf(ht.p_maxlf) {
|
||||
p_data(move(ht.p_data)), p_maxlf(ht.p_maxlf) {
|
||||
ht.p_size = ht.p_len = 0;
|
||||
ht.p_chunks = nullptr;
|
||||
ht.p_unused = nullptr;
|
||||
|
@ -368,10 +368,10 @@ protected:
|
|||
p_len = 0;
|
||||
p_chunks = nullptr;
|
||||
p_unused = nullptr;
|
||||
p_data.first() = octa::allocator_allocate(get_cpalloc(), p_size);
|
||||
p_data.first() = allocator_allocate(get_cpalloc(), p_size);
|
||||
memset(p_data.first(), 0, p_size * sizeof(Chain *));
|
||||
Chain **och = ht.p_data.first();
|
||||
for (octa::Size h = 0; h < p_size; ++h) {
|
||||
for (Size h = 0; h < p_size; ++h) {
|
||||
Chain *oc = och[h];
|
||||
for (; oc; oc = oc->next) {
|
||||
Chain *nc = insert(h);
|
||||
|
@ -382,11 +382,11 @@ protected:
|
|||
|
||||
Hashtable &operator=(const Hashtable &ht) {
|
||||
clear();
|
||||
if (octa::AllocatorPropagateOnContainerCopyAssignment<A>::value) {
|
||||
if (AllocatorPropagateOnContainerCopyAssignment<A>::value) {
|
||||
if ((get_cpalloc() != ht.get_cpalloc()) && p_size) {
|
||||
octa::allocator_deallocate(get_cpalloc(),
|
||||
allocator_deallocate(get_cpalloc(),
|
||||
p_data.first(), p_size);
|
||||
p_data.first() = octa::allocator_allocate(get_cpalloc(),
|
||||
p_data.first() = allocator_allocate(get_cpalloc(),
|
||||
p_size);
|
||||
memset(p_data.first(), 0, p_size * sizeof(Chain *));
|
||||
}
|
||||
|
@ -407,18 +407,18 @@ protected:
|
|||
octa::swap(p_unused, ht.p_unused);
|
||||
octa::swap(p_data.first(), ht.p_data.first());
|
||||
octa::swap(p_data.second().second(), ht.p_data.second().second());
|
||||
if (octa::AllocatorPropagateOnContainerMoveAssignment<A>::value)
|
||||
if (AllocatorPropagateOnContainerMoveAssignment<A>::value)
|
||||
octa::swap(p_data.second().first(), ht.p_data.second().first());
|
||||
return *this;
|
||||
}
|
||||
|
||||
void rehash_up() {
|
||||
if (load_factor() <= max_load_factor()) return;
|
||||
rehash(octa::Size(size() / max_load_factor()) * 2);
|
||||
rehash(Size(size() / max_load_factor()) * 2);
|
||||
}
|
||||
|
||||
void reserve_at_least(octa::Size count) {
|
||||
octa::Size nc = octa::Size(ceil(count / max_load_factor()));
|
||||
void reserve_at_least(Size count) {
|
||||
Size nc = Size(ceil(count / max_load_factor()));
|
||||
if (p_size > nc) return;
|
||||
rehash(nc);
|
||||
}
|
||||
|
@ -430,13 +430,13 @@ protected:
|
|||
octa::swap(p_unused, ht.p_unused);
|
||||
octa::swap(p_data.first(), ht.p_data.first());
|
||||
octa::swap(p_data.second().second(), ht.p_data.second().second());
|
||||
if (octa::AllocatorPropagateOnContainerSwap<A>::value)
|
||||
if (AllocatorPropagateOnContainerSwap<A>::value)
|
||||
octa::swap(p_data.second().first(), ht.p_data.second().first());
|
||||
}
|
||||
|
||||
public:
|
||||
~Hashtable() {
|
||||
if (p_size) octa::allocator_deallocate(get_cpalloc(),
|
||||
if (p_size) allocator_deallocate(get_cpalloc(),
|
||||
p_data.first(), p_size);
|
||||
delete_chunks(p_chunks);
|
||||
}
|
||||
|
@ -454,18 +454,18 @@ public:
|
|||
}
|
||||
|
||||
bool empty() const { return p_len == 0; }
|
||||
octa::Size size() const { return p_len; }
|
||||
Size size() const { return p_len; }
|
||||
Size max_size() const { return Size(~0) / sizeof(E); }
|
||||
|
||||
octa::Size bucket_count() const { return p_size; }
|
||||
octa::Size max_bucket_count() const { return Size(~0) / sizeof(Chain); }
|
||||
Size bucket_count() const { return p_size; }
|
||||
Size max_bucket_count() const { return Size(~0) / sizeof(Chain); }
|
||||
|
||||
octa::Size bucket(const K &key) const {
|
||||
Size bucket(const K &key) const {
|
||||
return get_hash()(key) & (p_size - 1);
|
||||
}
|
||||
|
||||
octa::Size bucket_size(octa::Size n) const {
|
||||
octa::Size ret = 0;
|
||||
Size bucket_size(Size n) const {
|
||||
Size ret = 0;
|
||||
if (ret >= p_size) return ret;
|
||||
Chain *c = p_data.first()[n];
|
||||
if (!c) return ret;
|
||||
|
@ -475,16 +475,16 @@ public:
|
|||
}
|
||||
|
||||
template<typename ...Args>
|
||||
octa::Pair<Range, bool> emplace(Args &&...args) {
|
||||
Pair<Range, bool> emplace(Args &&...args) {
|
||||
rehash_ahead(1);
|
||||
E elem(octa::forward<Args>(args)...);
|
||||
octa::Size h = get_hash()(B::get_key(elem)) & (p_size - 1);
|
||||
E elem(forward<Args>(args)...);
|
||||
Size h = get_hash()(B::get_key(elem)) & (p_size - 1);
|
||||
if (Multihash) {
|
||||
/* multihash: always insert */
|
||||
Chain *ch = insert(h);
|
||||
B::swap_elem(ch->value, elem);
|
||||
Chain **hch = p_data.first();
|
||||
return octa::make_pair(Range(hch + h + 1, hch + bucket_count(),
|
||||
return make_pair(Range(hch + h + 1, hch + bucket_count(),
|
||||
ch), true);
|
||||
}
|
||||
Chain *found = nullptr;
|
||||
|
@ -501,14 +501,14 @@ public:
|
|||
B::swap_elem(found->value, elem);
|
||||
}
|
||||
Chain **hch = p_data.first();
|
||||
return octa::make_pair(Range(hch + h + 1, hch + bucket_count(),
|
||||
return make_pair(Range(hch + h + 1, hch + bucket_count(),
|
||||
found), ins);
|
||||
}
|
||||
|
||||
octa::Size erase(const K &key) {
|
||||
Size erase(const K &key) {
|
||||
if (!p_len) return 0;
|
||||
octa::Size olen = p_len;
|
||||
octa::Size h = get_hash()(key) & (p_size - 1);
|
||||
Size olen = p_len;
|
||||
Size h = get_hash()(key) & (p_size - 1);
|
||||
Chain **p = &p_data.first()[h], *c = *p;
|
||||
while (c) {
|
||||
if (get_eq()(key, B::get_key(c->value))) {
|
||||
|
@ -516,8 +516,8 @@ public:
|
|||
*p = c->next;
|
||||
c->next = p_unused;
|
||||
p_unused = c;
|
||||
octa::allocator_destroy(get_alloc(), &c->value);
|
||||
octa::allocator_construct(get_alloc(), &c->value);
|
||||
allocator_destroy(get_alloc(), &c->value);
|
||||
allocator_construct(get_alloc(), &c->value);
|
||||
if (!Multihash) return 1;
|
||||
} else {
|
||||
p = &c->next;
|
||||
|
@ -527,10 +527,10 @@ public:
|
|||
return olen - p_len;
|
||||
}
|
||||
|
||||
octa::Size count(const K &key) {
|
||||
Size count(const K &key) {
|
||||
if (!p_len) return 0;
|
||||
octa::Size h = get_hash()(key) & (p_size - 1);
|
||||
octa::Size ret = 0;
|
||||
Size h = get_hash()(key) & (p_size - 1);
|
||||
Size ret = 0;
|
||||
for (Chain *c = p_data.first()[h]; c; c = c->next)
|
||||
if (get_eq()(key, B::get_key(c->value))) {
|
||||
++ret;
|
||||
|
@ -540,14 +540,14 @@ public:
|
|||
}
|
||||
|
||||
Range find(const K &key) {
|
||||
octa::Size h = 0;
|
||||
Size h = 0;
|
||||
Chain *c;
|
||||
if (find(key, h, c)) return iter_from(c, h);
|
||||
return Range();
|
||||
}
|
||||
|
||||
ConstRange find(const K &key) const {
|
||||
octa::Size h = 0;
|
||||
Size h = 0;
|
||||
Chain *c;
|
||||
if (find(key, h, c)) return iter_from(c, h);
|
||||
return ConstRange();
|
||||
|
@ -557,21 +557,21 @@ public:
|
|||
float max_load_factor() const { return p_maxlf; }
|
||||
void max_load_factor(float lf) { p_maxlf = lf; }
|
||||
|
||||
void rehash(octa::Size count) {
|
||||
octa::Size fbcount = octa::Size(p_len / max_load_factor());
|
||||
void rehash(Size count) {
|
||||
Size fbcount = Size(p_len / max_load_factor());
|
||||
if (fbcount > count) count = fbcount;
|
||||
|
||||
Chain **och = p_data.first();
|
||||
Chain **nch = octa::allocator_allocate(get_cpalloc(), count);
|
||||
Chain **nch = allocator_allocate(get_cpalloc(), count);
|
||||
memset(nch, 0, count * sizeof(Chain *));
|
||||
p_data.first() = nch;
|
||||
|
||||
octa::Size osize = p_size;
|
||||
Size osize = p_size;
|
||||
p_size = count;
|
||||
|
||||
for (octa::Size i = 0; i < osize; ++i) {
|
||||
for (Size i = 0; i < osize; ++i) {
|
||||
for (Chain *oc = och[i]; oc;) {
|
||||
octa::Size h = get_hash()(B::get_key(oc->value)) & (p_size - 1);
|
||||
Size h = get_hash()(B::get_key(oc->value)) & (p_size - 1);
|
||||
Chain *nxc = oc->next;
|
||||
oc->next = nch[h];
|
||||
nch[h] = oc;
|
||||
|
@ -579,39 +579,39 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
if (och && osize) octa::allocator_deallocate(get_cpalloc(),
|
||||
if (och && osize) allocator_deallocate(get_cpalloc(),
|
||||
och, osize);
|
||||
}
|
||||
|
||||
void reserve(octa::Size count) {
|
||||
rehash(octa::Size(ceil(count / max_load_factor())));
|
||||
void reserve(Size count) {
|
||||
rehash(Size(ceil(count / max_load_factor())));
|
||||
}
|
||||
|
||||
Range iter() {
|
||||
return Range(p_data.first(), p_data.first() + bucket_count());
|
||||
}
|
||||
ConstRange iter() const {
|
||||
using Chain = octa::detail::HashChain<const E>;
|
||||
using Chain = detail::HashChain<const E>;
|
||||
return ConstRange((Chain **)p_data.first(),
|
||||
(Chain **)(p_data.first() + bucket_count()));
|
||||
}
|
||||
ConstRange citer() const {
|
||||
using Chain = octa::detail::HashChain<const E>;
|
||||
using Chain = detail::HashChain<const E>;
|
||||
return ConstRange((Chain **)p_data.first(),
|
||||
(Chain **)(p_data.first() + bucket_count()));
|
||||
}
|
||||
|
||||
LocalRange iter(octa::Size n) {
|
||||
LocalRange iter(Size n) {
|
||||
if (n >= p_size) return LocalRange();
|
||||
return LocalRange(p_data.first()[n]);
|
||||
}
|
||||
ConstLocalRange iter(octa::Size n) const {
|
||||
using Chain = octa::detail::HashChain<const E>;
|
||||
ConstLocalRange iter(Size n) const {
|
||||
using Chain = detail::HashChain<const E>;
|
||||
if (n >= p_size) return ConstLocalRange();
|
||||
return ConstLocalRange((Chain *)p_data.first()[n]);
|
||||
}
|
||||
ConstLocalRange citer(octa::Size n) const {
|
||||
using Chain = octa::detail::HashChain<const E>;
|
||||
ConstLocalRange citer(Size n) const {
|
||||
using Chain = detail::HashChain<const E>;
|
||||
if (n >= p_size) return ConstLocalRange();
|
||||
return ConstLocalRange((Chain *)p_data.first()[n]);
|
||||
}
|
||||
|
|
42
octa/io.hh
42
octa/io.hh
|
@ -39,7 +39,7 @@ struct FileStream: Stream {
|
|||
}
|
||||
|
||||
template<typename A>
|
||||
FileStream(const octa::AnyString<A> &path, StreamMode mode): p_f() {
|
||||
FileStream(const AnyString<A> &path, StreamMode mode): p_f() {
|
||||
open(path, mode);
|
||||
}
|
||||
|
||||
|
@ -56,13 +56,13 @@ struct FileStream: Stream {
|
|||
|
||||
bool open(const char *path, StreamMode mode) {
|
||||
if (p_f) return false;
|
||||
p_f = fopen(path, octa::detail::filemodes[octa::Size(mode)]);
|
||||
p_f = fopen(path, detail::filemodes[Size(mode)]);
|
||||
p_owned = true;
|
||||
return is_open();
|
||||
}
|
||||
|
||||
template<typename A>
|
||||
bool open(const octa::AnyString<A> &path, StreamMode mode) {
|
||||
bool open(const AnyString<A> &path, StreamMode mode) {
|
||||
return open(path.data(), mode);
|
||||
}
|
||||
|
||||
|
@ -104,11 +104,11 @@ struct FileStream: Stream {
|
|||
|
||||
bool flush() { return !fflush(p_f); }
|
||||
|
||||
octa::Size read_bytes(void *buf, octa::Size count) {
|
||||
Size read_bytes(void *buf, Size count) {
|
||||
return fread(buf, 1, count, p_f);
|
||||
}
|
||||
|
||||
octa::Size write_bytes(const void *buf, octa::Size count) {
|
||||
Size write_bytes(const void *buf, Size count) {
|
||||
return fwrite(buf, 1, count, p_f);
|
||||
}
|
||||
|
||||
|
@ -147,46 +147,46 @@ static inline void write(const char *s) {
|
|||
}
|
||||
|
||||
template<typename A>
|
||||
static inline void write(const octa::AnyString<A> &s) {
|
||||
static inline void write(const AnyString<A> &s) {
|
||||
fwrite(s.data(), 1, s.size(), ::stdout);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
static inline void write(const T &v) {
|
||||
octa::write(octa::to_string(v));
|
||||
write(octa::to_string(v));
|
||||
}
|
||||
|
||||
template<typename T, typename ...A>
|
||||
static inline void write(const T &v, const A &...args) {
|
||||
octa::write(v);
|
||||
write(v);
|
||||
write(args...);
|
||||
}
|
||||
|
||||
static inline void writeln(const char *s) {
|
||||
octa::write(s);
|
||||
write(s);
|
||||
putc('\n', ::stdout);
|
||||
}
|
||||
|
||||
template<typename A>
|
||||
static inline void writeln(const octa::AnyString<A> &s) {
|
||||
octa::write(s);
|
||||
static inline void writeln(const AnyString<A> &s) {
|
||||
write(s);
|
||||
putc('\n', ::stdout);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
static inline void writeln(const T &v) {
|
||||
octa::writeln(octa::to_string(v));
|
||||
writeln(octa::to_string(v));
|
||||
}
|
||||
|
||||
template<typename T, typename ...A>
|
||||
static inline void writeln(const T &v, const A &...args) {
|
||||
octa::write(v);
|
||||
write(v);
|
||||
write(args...);
|
||||
putc('\n', ::stdout);
|
||||
}
|
||||
|
||||
namespace detail {
|
||||
struct UnsafeWritefRange: octa::OutputRange<UnsafeWritefRange, char> {
|
||||
struct UnsafeWritefRange: OutputRange<UnsafeWritefRange, char> {
|
||||
UnsafeWritefRange(char *p): p_ptr(p) {}
|
||||
bool put(char c) {
|
||||
*p_ptr++ = c;
|
||||
|
@ -199,21 +199,21 @@ namespace detail {
|
|||
template<typename ...A>
|
||||
static inline void writef(const char *fmt, const A &...args) {
|
||||
char buf[512];
|
||||
octa::Ptrdiff need = octa::format(octa::detail::FormatOutRange<
|
||||
sizeof(buf)>(buf), fmt, args...);
|
||||
Ptrdiff need = format(detail::FormatOutRange<sizeof(buf)>(buf),
|
||||
fmt, args...);
|
||||
if (need < 0) return;
|
||||
else if (octa::Size(need) < sizeof(buf)) {
|
||||
else if (Size(need) < sizeof(buf)) {
|
||||
fwrite(buf, 1, need, ::stdout);
|
||||
return;
|
||||
}
|
||||
octa::Vector<char> s;
|
||||
Vector<char> s;
|
||||
s.reserve(need);
|
||||
octa::format(octa::detail::UnsafeWritefRange(s.data()), fmt, args...);
|
||||
format(detail::UnsafeWritefRange(s.data()), fmt, args...);
|
||||
fwrite(s.data(), 1, need, ::stdout);
|
||||
}
|
||||
|
||||
template<typename AL, typename ...A>
|
||||
static inline void writef(const octa::AnyString<AL> &fmt,
|
||||
static inline void writef(const AnyString<AL> &fmt,
|
||||
const A &...args) {
|
||||
writef(fmt.data(), args...);
|
||||
}
|
||||
|
@ -225,7 +225,7 @@ static inline void writefln(const char *fmt, const A &...args) {
|
|||
}
|
||||
|
||||
template<typename AL, typename ...A>
|
||||
static inline void writefln(const octa::AnyString<AL> &fmt,
|
||||
static inline void writefln(const AnyString<AL> &fmt,
|
||||
const A &...args) {
|
||||
writef(fmt, args...);
|
||||
putc('\n', ::stdout);
|
||||
|
|
99
octa/map.hh
99
octa/map.hh
|
@ -18,7 +18,7 @@ namespace octa {
|
|||
|
||||
namespace detail {
|
||||
template<typename K, typename T, typename A> struct MapBase {
|
||||
using Element = octa::Pair<const K, T>;
|
||||
using Element = Pair<const K, T>;
|
||||
|
||||
static inline const K &get_key(Element &e) {
|
||||
return e.first;
|
||||
|
@ -28,9 +28,8 @@ namespace detail {
|
|||
}
|
||||
template<typename U>
|
||||
static inline void set_key(Element &e, U &&key, A &alloc) {
|
||||
octa::allocator_destroy(alloc, &e);
|
||||
octa::allocator_construct(alloc, &e, octa::forward<U>(key),
|
||||
octa::move(T()));
|
||||
allocator_destroy(alloc, &e);
|
||||
allocator_construct(alloc, &e, forward<U>(key), move(T()));
|
||||
}
|
||||
static inline void swap_elem(Element &a, Element &b) {
|
||||
octa::swap(*((K *)&a.first), *((K *)&b.first));
|
||||
|
@ -41,59 +40,57 @@ namespace detail {
|
|||
template<
|
||||
typename K, typename T, typename H,
|
||||
typename C, typename A, bool IsMultihash
|
||||
> struct MapImpl: octa::detail::Hashtable<
|
||||
octa::detail::MapBase<K, T, A>, octa::Pair<const K, T>,
|
||||
K, T, H, C, A, IsMultihash
|
||||
> struct MapImpl: detail::Hashtable<detail::MapBase<K, T, A>,
|
||||
Pair<const K, T>, K, T, H, C, A, IsMultihash
|
||||
> {
|
||||
private:
|
||||
using Base = octa::detail::Hashtable<
|
||||
octa::detail::MapBase<K, T, A>, octa::Pair<const K, T>,
|
||||
K, T, H, C, A, IsMultihash
|
||||
using Base = detail::Hashtable<detail::MapBase<K, T, A>,
|
||||
Pair<const K, T>, K, T, H, C, A, IsMultihash
|
||||
>;
|
||||
|
||||
public:
|
||||
using Key = K;
|
||||
using Mapped = T;
|
||||
using Size = octa::Size;
|
||||
using Difference = octa::Ptrdiff;
|
||||
using Size = Size;
|
||||
using Difference = Ptrdiff;
|
||||
using Hasher = H;
|
||||
using KeyEqual = C;
|
||||
using Value = octa::Pair<const K, T>;
|
||||
using Value = Pair<const K, T>;
|
||||
using Reference = Value &;
|
||||
using Pointer = octa::AllocatorPointer<A>;
|
||||
using ConstPointer = octa::AllocatorConstPointer<A>;
|
||||
using Range = octa::HashRange<octa::Pair<const K, T>>;
|
||||
using ConstRange = octa::HashRange<const octa::Pair<const K, T>>;
|
||||
using LocalRange = octa::BucketRange<octa::Pair<const K, T>>;
|
||||
using ConstLocalRange = octa::BucketRange<const octa::Pair<const K, T>>;
|
||||
using Pointer = AllocatorPointer<A>;
|
||||
using ConstPointer = AllocatorConstPointer<A>;
|
||||
using Range = HashRange<Pair<const K, T>>;
|
||||
using ConstRange = HashRange<const Pair<const K, T>>;
|
||||
using LocalRange = BucketRange<Pair<const K, T>>;
|
||||
using ConstLocalRange = BucketRange<const Pair<const K, T>>;
|
||||
using Allocator = A;
|
||||
|
||||
explicit MapImpl(octa::Size size, const H &hf = H(),
|
||||
explicit MapImpl(Size size, const H &hf = H(),
|
||||
const C &eqf = C(), const A &alloc = A()
|
||||
): Base(size, hf, eqf, alloc) {}
|
||||
|
||||
MapImpl(): MapImpl(0) {}
|
||||
explicit MapImpl(const A &alloc): MapImpl(0, H(), C(), alloc) {}
|
||||
|
||||
MapImpl(octa::Size size, const A &alloc):
|
||||
MapImpl(Size size, const A &alloc):
|
||||
MapImpl(size, H(), C(), alloc) {}
|
||||
MapImpl(octa::Size size, const H &hf, const A &alloc):
|
||||
MapImpl(Size size, const H &hf, const A &alloc):
|
||||
MapImpl(size, hf, C(), alloc) {}
|
||||
|
||||
MapImpl(const MapImpl &m): Base(m,
|
||||
octa::allocator_container_copy(m.get_alloc())) {}
|
||||
allocator_container_copy(m.get_alloc())) {}
|
||||
|
||||
MapImpl(const MapImpl &m, const A &alloc): Base(m, alloc) {}
|
||||
|
||||
MapImpl(MapImpl &&m): Base(octa::move(m)) {}
|
||||
MapImpl(MapImpl &&m, const A &alloc): Base(octa::move(m), alloc) {}
|
||||
MapImpl(MapImpl &&m): Base(move(m)) {}
|
||||
MapImpl(MapImpl &&m, const A &alloc): Base(move(m), alloc) {}
|
||||
|
||||
template<typename R, typename = octa::EnableIf<
|
||||
octa::IsInputRange<R>::value &&
|
||||
octa::IsConvertible<RangeReference<R>, Value>::value
|
||||
>> MapImpl(R range, octa::Size size = 0, const H &hf = H(),
|
||||
template<typename R, typename = EnableIf<
|
||||
IsInputRange<R>::value && IsConvertible<RangeReference<R>,
|
||||
Value>::value
|
||||
>> MapImpl(R range, Size size = 0, const H &hf = H(),
|
||||
const C &eqf = C(), const A &alloc = A()
|
||||
): Base(size ? size : octa::detail::estimate_hrsize(range),
|
||||
): Base(size ? size : detail::estimate_hrsize(range),
|
||||
hf, eqf, alloc) {
|
||||
for (; !range.empty(); range.pop_front())
|
||||
Base::emplace(range.front());
|
||||
|
@ -101,23 +98,23 @@ namespace detail {
|
|||
}
|
||||
|
||||
template<typename R>
|
||||
MapImpl(R range, octa::Size size, const A &alloc)
|
||||
MapImpl(R range, Size size, const A &alloc)
|
||||
: MapImpl(range, size, H(), C(), alloc) {}
|
||||
|
||||
template<typename R>
|
||||
MapImpl(R range, octa::Size size, const H &hf, const A &alloc)
|
||||
MapImpl(R range, Size size, const H &hf, const A &alloc)
|
||||
: MapImpl(range, size, hf, C(), alloc) {}
|
||||
|
||||
MapImpl(octa::InitializerList<Value> init, octa::Size size = 0,
|
||||
MapImpl(InitializerList<Value> init, Size size = 0,
|
||||
const H &hf = H(), const C &eqf = C(), const A &alloc = A()
|
||||
): MapImpl(octa::iter(init), size, hf, eqf, alloc) {}
|
||||
): MapImpl(iter(init), size, hf, eqf, alloc) {}
|
||||
|
||||
MapImpl(octa::InitializerList<Value> init, octa::Size size, const A &alloc)
|
||||
: MapImpl(octa::iter(init), size, H(), C(), alloc) {}
|
||||
MapImpl(InitializerList<Value> init, Size size, const A &alloc)
|
||||
: MapImpl(iter(init), size, H(), C(), alloc) {}
|
||||
|
||||
MapImpl(octa::InitializerList<Value> init, octa::Size size, const H &hf,
|
||||
MapImpl(InitializerList<Value> init, Size size, const H &hf,
|
||||
const A &alloc
|
||||
): MapImpl(octa::iter(init), size, hf, C(), alloc) {}
|
||||
): MapImpl(iter(init), size, hf, C(), alloc) {}
|
||||
|
||||
MapImpl &operator=(const MapImpl &m) {
|
||||
Base::operator=(m);
|
||||
|
@ -125,13 +122,13 @@ namespace detail {
|
|||
}
|
||||
|
||||
MapImpl &operator=(MapImpl &&m) {
|
||||
Base::operator=(octa::move(m));
|
||||
Base::operator=(move(m));
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename R, typename = octa::EnableIf<
|
||||
octa::IsInputRange<R>::value &&
|
||||
octa::IsConvertible<RangeReference<R>, Value>::value
|
||||
template<typename R, typename = EnableIf<
|
||||
IsInputRange<R>::value &&
|
||||
IsConvertible<RangeReference<R>, Value>::value
|
||||
>> MapImpl &operator=(R range) {
|
||||
Base::assign_range(range);
|
||||
return *this;
|
||||
|
@ -157,7 +154,7 @@ namespace detail {
|
|||
}
|
||||
T &operator[](K &&key) {
|
||||
static_assert(!IsMultihash, "operator[] only allowed on regular maps");
|
||||
return Base::access_or_insert(octa::move(key));
|
||||
return Base::access_or_insert(move(key));
|
||||
}
|
||||
|
||||
void swap(MapImpl &v) {
|
||||
|
@ -168,17 +165,17 @@ namespace detail {
|
|||
|
||||
template<
|
||||
typename K, typename T,
|
||||
typename H = octa::ToHash<K>,
|
||||
typename C = octa::Equal<K>,
|
||||
typename A = octa::Allocator<octa::Pair<const K, T>>
|
||||
> using Map = octa::detail::MapImpl<K, T, H, C, A, false>;
|
||||
typename H = ToHash<K>,
|
||||
typename C = Equal<K>,
|
||||
typename A = Allocator<Pair<const K, T>>
|
||||
> using Map = detail::MapImpl<K, T, H, C, A, false>;
|
||||
|
||||
template<
|
||||
typename K, typename T,
|
||||
typename H = octa::ToHash<K>,
|
||||
typename C = octa::Equal<K>,
|
||||
typename A = octa::Allocator<octa::Pair<const K, T>>
|
||||
> using Multimap = octa::detail::MapImpl<K, T, H, C, A, true>;
|
||||
typename H = ToHash<K>,
|
||||
typename C = Equal<K>,
|
||||
typename A = Allocator<Pair<const K, T>>
|
||||
> using Multimap = detail::MapImpl<K, T, H, C, A, true>;
|
||||
|
||||
} /* namespace octa */
|
||||
|
||||
|
|
128
octa/maybe.hh
128
octa/maybe.hh
|
@ -24,7 +24,7 @@ struct Nothing {
|
|||
constexpr Nothing nothing = Nothing(0);
|
||||
|
||||
namespace detail {
|
||||
template<typename T, bool = octa::IsTriviallyDestructible<T>::value>
|
||||
template<typename T, bool = IsTriviallyDestructible<T>::value>
|
||||
class MaybeStorage {
|
||||
protected:
|
||||
using Value = T;
|
||||
|
@ -37,19 +37,19 @@ namespace detail {
|
|||
constexpr MaybeStorage(): p_null_state('\0') {}
|
||||
|
||||
MaybeStorage(const MaybeStorage &v): p_engaged(v.p_engaged) {
|
||||
if (p_engaged) ::new(octa::address_of(p_value)) Value(v.p_value);
|
||||
if (p_engaged) ::new(address_of(p_value)) Value(v.p_value);
|
||||
}
|
||||
|
||||
MaybeStorage(MaybeStorage &&v): p_engaged(v.p_engaged) {
|
||||
if (p_engaged)
|
||||
::new(octa::address_of(p_value)) Value(octa::move(v.p_value));
|
||||
::new(address_of(p_value)) Value(move(v.p_value));
|
||||
}
|
||||
|
||||
constexpr MaybeStorage(const Value &v): p_value(v), p_engaged(true) {}
|
||||
constexpr MaybeStorage(Value &&v): p_value(octa::move(v)), p_engaged(true) {}
|
||||
constexpr MaybeStorage(Value &&v): p_value(move(v)), p_engaged(true) {}
|
||||
|
||||
template<typename ...A> constexpr MaybeStorage(octa::InPlace, A &&...args):
|
||||
p_value(octa::forward<A>(args)...), p_engaged(true) {}
|
||||
template<typename ...A> constexpr MaybeStorage(InPlace, A &&...args):
|
||||
p_value(forward<A>(args)...), p_engaged(true) {}
|
||||
|
||||
~MaybeStorage() {
|
||||
if (p_engaged) p_value.~Value();
|
||||
|
@ -69,58 +69,58 @@ namespace detail {
|
|||
constexpr MaybeStorage(): p_null_state('\0') {}
|
||||
|
||||
MaybeStorage(const MaybeStorage &v): p_engaged(v.p_engaged) {
|
||||
if (p_engaged) ::new(octa::address_of(p_value)) Value(v.p_value);
|
||||
if (p_engaged) ::new(address_of(p_value)) Value(v.p_value);
|
||||
}
|
||||
|
||||
MaybeStorage(MaybeStorage &&v): p_engaged(v.p_engaged) {
|
||||
if (p_engaged)
|
||||
::new(octa::address_of(p_value)) Value(octa::move(v.p_value));
|
||||
::new(address_of(p_value)) Value(move(v.p_value));
|
||||
}
|
||||
|
||||
constexpr MaybeStorage(const Value &v): p_value(v), p_engaged(true) {}
|
||||
constexpr MaybeStorage(Value &&v):
|
||||
p_value(octa::move(v)), p_engaged(true) {}
|
||||
p_value(move(v)), p_engaged(true) {}
|
||||
|
||||
template<typename ...A>
|
||||
constexpr MaybeStorage(octa::InPlace, A &&...args):
|
||||
p_value(octa::forward<A>(args)...), p_engaged(true) {}
|
||||
constexpr MaybeStorage(InPlace, A &&...args):
|
||||
p_value(forward<A>(args)...), p_engaged(true) {}
|
||||
};
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
class Maybe: private octa::detail::MaybeStorage<T> {
|
||||
using Base = octa::detail::MaybeStorage<T>;
|
||||
class Maybe: private detail::MaybeStorage<T> {
|
||||
using Base = detail::MaybeStorage<T>;
|
||||
public:
|
||||
using Value = T;
|
||||
|
||||
static_assert(!octa::IsReference<T>::value,
|
||||
static_assert(!IsReference<T>::value,
|
||||
"Initialization of Maybe with a reference type is not allowed.");
|
||||
static_assert(!octa::IsSame<octa::RemoveCv<T>, octa::InPlace>::value,
|
||||
static_assert(!IsSame<RemoveCv<T>, InPlace>::value,
|
||||
"Initialization of Maybe with InPlace is not allowed.");
|
||||
static_assert(!octa::IsSame<octa::RemoveCv<T>, octa::Nothing>::value,
|
||||
static_assert(!IsSame<RemoveCv<T>, Nothing>::value,
|
||||
"Initialization of Maybe with Nothing is not allowed.");
|
||||
static_assert(octa::IsObject<T>::value,
|
||||
static_assert(IsObject<T>::value,
|
||||
"Initialization of Maybe with non-object type is not allowed.");
|
||||
static_assert(octa::IsDestructible<T>::value,
|
||||
static_assert(IsDestructible<T>::value,
|
||||
"Initialization of Maybe with a non-destructible object is not allowed.");
|
||||
|
||||
constexpr Maybe() {}
|
||||
Maybe(const Maybe &) = default;
|
||||
Maybe(Maybe &&) = default;
|
||||
constexpr Maybe(octa::Nothing) {}
|
||||
constexpr Maybe(Nothing) {}
|
||||
constexpr Maybe(const Value &v): Base(v) {}
|
||||
constexpr Maybe(Value &&v): Base(octa::move(v)) {}
|
||||
constexpr Maybe(Value &&v): Base(move(v)) {}
|
||||
|
||||
template<typename ...A, typename = octa::EnableIf<
|
||||
octa::IsConstructible<T, A...>::value>>
|
||||
constexpr explicit Maybe(octa::InPlace, A &&...args): Base(octa::in_place,
|
||||
octa::forward<A>(args)...) {}
|
||||
template<typename ...A, typename = EnableIf<
|
||||
IsConstructible<T, A...>::value>>
|
||||
constexpr explicit Maybe(InPlace, A &&...args): Base(in_place,
|
||||
forward<A>(args)...) {}
|
||||
|
||||
template<typename U, typename ...A, typename = typename octa::EnableIf<
|
||||
octa::IsConstructible<T, std::initializer_list<U> &, A...>::value>>
|
||||
template<typename U, typename ...A, typename = typename EnableIf<
|
||||
IsConstructible<T, std::initializer_list<U> &, A...>::value>>
|
||||
constexpr explicit
|
||||
Maybe(octa::InPlace, std::initializer_list<U> il, A &&...args):
|
||||
Base(octa::in_place, il, octa::forward<A>(args)...) {}
|
||||
Maybe(InPlace, std::initializer_list<U> il, A &&...args):
|
||||
Base(in_place, il, forward<A>(args)...) {}
|
||||
|
||||
~Maybe() = default;
|
||||
|
||||
|
@ -139,7 +139,7 @@ public:
|
|||
if (this->p_engaged)
|
||||
this->p_value.~Value();
|
||||
else
|
||||
::new(octa::address_of(this->p_value)) Value(v.p_value);
|
||||
::new(address_of(this->p_value)) Value(v.p_value);
|
||||
this->p_engaged = v.p_engaged;
|
||||
}
|
||||
return *this;
|
||||
|
@ -147,60 +147,58 @@ public:
|
|||
|
||||
Maybe &operator=(Maybe &&v) {
|
||||
if (this->p_engaged == v.p_engaged) {
|
||||
if (this->p_engaged) this->p_value = octa::move(v.p_value);
|
||||
if (this->p_engaged) this->p_value = move(v.p_value);
|
||||
} else {
|
||||
if (this->p_engaged)
|
||||
this->p_value.~Value();
|
||||
else {
|
||||
::new(octa::address_of(this->p_value))
|
||||
Value(octa::move(v.p_value));
|
||||
::new(address_of(this->p_value)) Value(move(v.p_value));
|
||||
}
|
||||
this->p_engaged = v.p_engaged;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename U, typename = octa::EnableIf<
|
||||
octa::IsSame<octa::RemoveReference<U>, Value>::value &&
|
||||
octa::IsConstructible<Value, U>::value &&
|
||||
octa::IsAssignable<Value &, U>::value
|
||||
template<typename U, typename = EnableIf<
|
||||
IsSame<RemoveReference<U>, Value>::value &&
|
||||
IsConstructible<Value, U>::value &&
|
||||
IsAssignable<Value &, U>::value
|
||||
>>
|
||||
Maybe &operator=(U &&v) {
|
||||
if (this->p_engaged) {
|
||||
this->p_value = octa::forward<U>(v);
|
||||
this->p_value = forward<U>(v);
|
||||
} else {
|
||||
::new(octa::address_of(this->p_value)) Value(octa::forward<U>(v));
|
||||
::new(address_of(this->p_value)) Value(forward<U>(v));
|
||||
this->p_engaged = true;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename ...A, typename = octa::EnableIf<
|
||||
octa::IsConstructible<Value, A...>::value
|
||||
template<typename ...A, typename = EnableIf<
|
||||
IsConstructible<Value, A...>::value
|
||||
>>
|
||||
void emplace(A &&...args) {
|
||||
*this = octa::nothing;
|
||||
::new(octa::address_of(this->p_value))
|
||||
Value(octa::forward<A>(args)...);
|
||||
*this = nothing;
|
||||
::new(address_of(this->p_value)) Value(forward<A>(args)...);
|
||||
this->p_engaged = true;
|
||||
}
|
||||
|
||||
template<typename U, typename ...A, typename = octa::EnableIf<
|
||||
octa::IsConstructible<Value, std::initializer_list<U> &, A...>::value
|
||||
template<typename U, typename ...A, typename = EnableIf<
|
||||
IsConstructible<Value, std::initializer_list<U> &, A...>::value
|
||||
>>
|
||||
void emplace(std::initializer_list<U> il, A &&...args) {
|
||||
*this = octa::nothing;
|
||||
::new(octa::address_of(this->p_value))
|
||||
Value(il, octa::forward<A>(args)...);
|
||||
*this = nothing;
|
||||
::new(address_of(this->p_value))
|
||||
Value(il, forward<A>(args)...);
|
||||
this->p_engaged = true;
|
||||
}
|
||||
|
||||
constexpr const Value *operator->() const {
|
||||
return octa::address_of(this->p_value);
|
||||
return address_of(this->p_value);
|
||||
}
|
||||
|
||||
Value *operator->() {
|
||||
return octa::address_of(this->p_value);
|
||||
return address_of(this->p_value);
|
||||
}
|
||||
|
||||
constexpr const Value &operator*() const {
|
||||
|
@ -223,21 +221,21 @@ public:
|
|||
|
||||
template<typename U>
|
||||
constexpr Value value_or(U &&v) const & {
|
||||
static_assert(octa::IsCopyConstructible<Value>::value,
|
||||
static_assert(IsCopyConstructible<Value>::value,
|
||||
"Maybe<T>::value_or: T must be copy constructible");
|
||||
static_assert(octa::IsConvertible<U, Value>::value,
|
||||
static_assert(IsConvertible<U, Value>::value,
|
||||
"Maybe<T>::value_or: U must be convertible to T");
|
||||
return this->p_engaged ? this->p_value : Value(octa::forward<U>(v));
|
||||
return this->p_engaged ? this->p_value : Value(forward<U>(v));
|
||||
}
|
||||
|
||||
template<typename U>
|
||||
Value value_or(U &&v) && {
|
||||
static_assert(octa::IsMoveConstructible<Value>::value,
|
||||
static_assert(IsMoveConstructible<Value>::value,
|
||||
"Maybe<T>::value_or: T must be copy constructible");
|
||||
static_assert(octa::IsConvertible<U, Value>::value,
|
||||
static_assert(IsConvertible<U, Value>::value,
|
||||
"Maybe<T>::value_or: U must be convertible to T");
|
||||
return this->p_engaged ? octa::move(this->p_value)
|
||||
: Value(octa::forward<U>(v));
|
||||
return this->p_engaged ? move(this->p_value)
|
||||
: Value(forward<U>(v));
|
||||
}
|
||||
|
||||
void swap(Maybe &v) {
|
||||
|
@ -245,19 +243,17 @@ public:
|
|||
if (this->p_engaged) octa::swap(this->p_value, v.p_value);
|
||||
} else {
|
||||
if (this->p_engaged) {
|
||||
::new(octa::address_of(v.p_value))
|
||||
Value(octa::move(this->p_value));
|
||||
::new(address_of(v.p_value)) Value(move(this->p_value));
|
||||
this->p_value.~Value();
|
||||
} else {
|
||||
::new(octa::address_of(this->p_value))
|
||||
Value(octa::move(v.p_value));
|
||||
::new(address_of(this->p_value)) Value(move(v.p_value));
|
||||
v.p_value.~Value();
|
||||
}
|
||||
octa::swap(this->p_engaged, v.p_engaged);
|
||||
}
|
||||
}
|
||||
|
||||
octa::Size to_hash() const {
|
||||
Size to_hash() const {
|
||||
return this->p_engaged ? octa::ToHash<T>()(this->p_value) : 0;
|
||||
}
|
||||
};
|
||||
|
@ -380,12 +376,12 @@ static inline constexpr bool operator!=(const T &b, const Maybe<T> &a) {
|
|||
|
||||
template<typename T>
|
||||
static inline constexpr bool operator<(const Maybe<T> &a, const T &b) {
|
||||
return bool(a) ? octa::Less<T>()(*a, b) : true;
|
||||
return bool(a) ? Less<T>()(*a, b) : true;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
static inline constexpr bool operator<(const T &b, const Maybe<T> &a) {
|
||||
return bool(a) ? octa::Less<T>()(b, *a) : false;
|
||||
return bool(a) ? Less<T>()(b, *a) : false;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
|
@ -421,8 +417,8 @@ static inline constexpr bool operator>=(const T &b, const Maybe<T> &a) {
|
|||
/* make maybe */
|
||||
|
||||
template<typename T>
|
||||
constexpr Maybe<octa::Decay<T>> make_maybe(T &&v) {
|
||||
return Maybe<octa::Decay<T>>(octa::forward<T>(v));
|
||||
constexpr Maybe<Decay<T>> make_maybe(T &&v) {
|
||||
return Maybe<Decay<T>>(forward<T>(v));
|
||||
}
|
||||
|
||||
} /* namespace octa */
|
||||
|
|
338
octa/memory.hh
338
octa/memory.hh
|
@ -68,7 +68,7 @@ namespace detail {
|
|||
|
||||
template<typename T, bool = HasDifference<T>::value>
|
||||
struct PointerDifferenceBase {
|
||||
using Type = octa::Ptrdiff;
|
||||
using Type = Ptrdiff;
|
||||
};
|
||||
|
||||
template<typename T> struct PointerDifferenceBase<T, true> {
|
||||
|
@ -82,7 +82,7 @@ namespace detail {
|
|||
|
||||
template<typename T>
|
||||
struct PointerDifferenceType<T *> {
|
||||
using Type = octa::Ptrdiff;
|
||||
using Type = Ptrdiff;
|
||||
};
|
||||
|
||||
template<typename T, typename U>
|
||||
|
@ -135,16 +135,16 @@ namespace detail {
|
|||
} /*namespace detail */
|
||||
|
||||
template<typename T>
|
||||
using Pointer = typename octa::detail::PointerPointer<T>::Type;
|
||||
using Pointer = typename detail::PointerPointer<T>::Type;
|
||||
|
||||
template<typename T>
|
||||
using PointerElement = typename octa::detail::PointerElementType<T>::Type;
|
||||
using PointerElement = typename detail::PointerElementType<T>::Type;
|
||||
|
||||
template<typename T>
|
||||
using PointerDifference = typename octa::detail::PointerDifferenceType<T>::Type;
|
||||
using PointerDifference = typename detail::PointerDifferenceType<T>::Type;
|
||||
|
||||
template<typename T, typename U>
|
||||
using PointerRebind = typename octa::detail::PointerRebindType<T, U>::Type;
|
||||
using PointerRebind = typename detail::PointerRebindType<T, U>::Type;
|
||||
|
||||
/* pointer to */
|
||||
|
||||
|
@ -153,8 +153,7 @@ namespace detail {
|
|||
|
||||
template<typename T>
|
||||
struct PointerTo {
|
||||
static T pointer_to(octa::Conditional<
|
||||
octa::IsVoid<PointerElement<T>>::value,
|
||||
static T pointer_to(Conditional<IsVoid<PointerElement<T>>::value,
|
||||
PointerToNat, PointerElement<T>
|
||||
> &r) {
|
||||
return T::pointer_to(r);
|
||||
|
@ -163,20 +162,19 @@ namespace detail {
|
|||
|
||||
template<typename T>
|
||||
struct PointerTo<T *> {
|
||||
static T pointer_to(octa::Conditional<
|
||||
octa::IsVoid<T>::value, PointerToNat, T
|
||||
static T pointer_to(Conditional<IsVoid<T>::value,
|
||||
PointerToNat, T
|
||||
> &r) {
|
||||
return octa::address_of(r);
|
||||
return address_of(r);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
static T pointer_to(octa::Conditional<
|
||||
octa::IsVoid<PointerElement<T>>::value,
|
||||
octa::detail::PointerToNat, PointerElement<T>
|
||||
static T pointer_to(Conditional<IsVoid<PointerElement<T>>::value,
|
||||
detail::PointerToNat, PointerElement<T>
|
||||
> &r) {
|
||||
return octa::detail::PointerTo<T>::pointer_to(r);
|
||||
return detail::PointerTo<T>::pointer_to(r);
|
||||
}
|
||||
|
||||
/* default deleter */
|
||||
|
@ -212,7 +210,7 @@ namespace detail {
|
|||
template<typename T>
|
||||
static char ptr_test(typename T::Pointer * = 0);
|
||||
|
||||
template<typename T> struct HasPtr: octa::IntegralConstant<bool,
|
||||
template<typename T> struct HasPtr: IntegralConstant<bool,
|
||||
(sizeof(ptr_test<T>(0)) == 1)
|
||||
> {};
|
||||
|
||||
|
@ -226,7 +224,7 @@ namespace detail {
|
|||
};
|
||||
|
||||
template<typename T, typename D> struct PointerType {
|
||||
using Type = typename PointerBase<T, octa::RemoveReference<D>>::Type;
|
||||
using Type = typename PointerBase<T, RemoveReference<D>>::Type;
|
||||
};
|
||||
} /* namespace detail */
|
||||
|
||||
|
@ -234,7 +232,7 @@ template<typename T, typename D = DefaultDelete<T>>
|
|||
struct Box {
|
||||
using Element = T;
|
||||
using Deleter = D;
|
||||
using Pointer = typename octa::detail::PointerType<T, D>::Type;
|
||||
using Pointer = typename detail::PointerType<T, D>::Type;
|
||||
|
||||
private:
|
||||
struct Nat { int x; };
|
||||
|
@ -244,63 +242,63 @@ private:
|
|||
|
||||
public:
|
||||
constexpr Box(): p_stor(nullptr, D()) {
|
||||
static_assert(!octa::IsPointer<D>::value,
|
||||
static_assert(!IsPointer<D>::value,
|
||||
"Box constructed with null fptr deleter");
|
||||
}
|
||||
constexpr Box(octa::Nullptr): p_stor(nullptr, D()) {
|
||||
static_assert(!octa::IsPointer<D>::value,
|
||||
constexpr Box(Nullptr): p_stor(nullptr, D()) {
|
||||
static_assert(!IsPointer<D>::value,
|
||||
"Box constructed with null fptr deleter");
|
||||
}
|
||||
|
||||
explicit Box(Pointer p): p_stor(p, D()) {
|
||||
static_assert(!octa::IsPointer<D>::value,
|
||||
static_assert(!IsPointer<D>::value,
|
||||
"Box constructed with null fptr deleter");
|
||||
}
|
||||
|
||||
Box(Pointer p, octa::Conditional<octa::IsReference<D>::value,
|
||||
D, octa::AddLvalueReference<const D>
|
||||
Box(Pointer p, Conditional<IsReference<D>::value,
|
||||
D, AddLvalueReference<const D>
|
||||
> d): p_stor(p, d) {}
|
||||
|
||||
Box(Pointer p, octa::RemoveReference<D> &&d):
|
||||
p_stor(p, octa::move(d)) {
|
||||
static_assert(!octa::IsReference<D>::value,
|
||||
Box(Pointer p, RemoveReference<D> &&d):
|
||||
p_stor(p, move(d)) {
|
||||
static_assert(!IsReference<D>::value,
|
||||
"rvalue deleter cannot be a ref");
|
||||
}
|
||||
|
||||
Box(Box &&u): p_stor(u.release(), octa::forward<D>(u.get_deleter())) {}
|
||||
Box(Box &&u): p_stor(u.release(), forward<D>(u.get_deleter())) {}
|
||||
|
||||
template<typename TT, typename DD>
|
||||
Box(Box<TT, DD> &&u, octa::EnableIf<!octa::IsArray<TT>::value
|
||||
&& octa::IsConvertible<typename Box<TT, DD>::Pointer, Pointer>::value
|
||||
&& octa::IsConvertible<DD, D>::value
|
||||
&& (!octa::IsReference<D>::value || octa::IsSame<D, DD>::value)
|
||||
> = Nat()): p_stor(u.release(), octa::forward<DD>(u.get_deleter())) {}
|
||||
Box(Box<TT, DD> &&u, EnableIf<!IsArray<TT>::value
|
||||
&& IsConvertible<typename Box<TT, DD>::Pointer, Pointer>::value
|
||||
&& IsConvertible<DD, D>::value
|
||||
&& (!IsReference<D>::value || IsSame<D, DD>::value)
|
||||
> = Nat()): p_stor(u.release(), forward<DD>(u.get_deleter())) {}
|
||||
|
||||
Box &operator=(Box &&u) {
|
||||
reset(u.release());
|
||||
p_stor.second() = octa::forward<D>(u.get_deleter());
|
||||
p_stor.second() = forward<D>(u.get_deleter());
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename TT, typename DD>
|
||||
EnableIf<!octa::IsArray<TT>::value
|
||||
&& octa::IsConvertible<typename Box<TT, DD>::Pointer, Pointer>::value
|
||||
&& octa::IsAssignable<D &, DD &&>::value,
|
||||
EnableIf<!IsArray<TT>::value
|
||||
&& IsConvertible<typename Box<TT, DD>::Pointer, Pointer>::value
|
||||
&& IsAssignable<D &, DD &&>::value,
|
||||
Box &
|
||||
> operator=(Box<TT, DD> &&u) {
|
||||
reset(u.release());
|
||||
p_stor.second() = octa::forward<DD>(u.get_deleter());
|
||||
p_stor.second() = forward<DD>(u.get_deleter());
|
||||
return *this;
|
||||
}
|
||||
|
||||
Box &operator=(octa::Nullptr) {
|
||||
Box &operator=(Nullptr) {
|
||||
reset();
|
||||
return *this;
|
||||
}
|
||||
|
||||
~Box() { reset(); }
|
||||
|
||||
octa::AddLvalueReference<T> operator*() const { return *p_stor.first(); }
|
||||
AddLvalueReference<T> operator*() const { return *p_stor.first(); }
|
||||
Pointer operator->() const { return p_stor.first(); }
|
||||
|
||||
explicit operator bool() const {
|
||||
|
@ -329,31 +327,31 @@ public:
|
|||
}
|
||||
|
||||
private:
|
||||
octa::detail::CompressedPair<T *, D> p_stor;
|
||||
detail::CompressedPair<T *, D> p_stor;
|
||||
};
|
||||
|
||||
namespace detail {
|
||||
template<typename T, typename U, bool = octa::IsSame<
|
||||
octa::RemoveCv<PointerElement<T>>,
|
||||
octa::RemoveCv<PointerElement<U>>
|
||||
>::value> struct SameOrLessCvQualifiedBase: octa::IsConvertible<T, U> {};
|
||||
template<typename T, typename U, bool = IsSame<
|
||||
RemoveCv<PointerElement<T>>,
|
||||
RemoveCv<PointerElement<U>>
|
||||
>::value> struct SameOrLessCvQualifiedBase: IsConvertible<T, U> {};
|
||||
|
||||
template<typename T, typename U>
|
||||
struct SameOrLessCvQualifiedBase<T, U, false>: octa::False {};
|
||||
struct SameOrLessCvQualifiedBase<T, U, false>: False {};
|
||||
|
||||
template<typename T, typename U, bool = octa::IsPointer<T>::value
|
||||
|| octa::IsSame<T, U>::value || octa::detail::HasElement<T>::value
|
||||
template<typename T, typename U, bool = IsPointer<T>::value
|
||||
|| IsSame<T, U>::value || detail::HasElement<T>::value
|
||||
> struct SameOrLessCvQualified: SameOrLessCvQualifiedBase<T, U> {};
|
||||
|
||||
template<typename T, typename U>
|
||||
struct SameOrLessCvQualified<T, U, false>: octa::False {};
|
||||
struct SameOrLessCvQualified<T, U, false>: False {};
|
||||
} /* namespace detail */
|
||||
|
||||
template<typename T, typename D>
|
||||
struct Box<T[], D> {
|
||||
using Element = T;
|
||||
using Deleter = D;
|
||||
using Pointer = typename octa::detail::PointerType<T, D>::Type;
|
||||
using Pointer = typename detail::PointerType<T, D>::Type;
|
||||
|
||||
private:
|
||||
struct Nat { int x; };
|
||||
|
@ -363,82 +361,82 @@ private:
|
|||
|
||||
public:
|
||||
constexpr Box(): p_stor(nullptr, D()) {
|
||||
static_assert(!octa::IsPointer<D>::value,
|
||||
static_assert(!IsPointer<D>::value,
|
||||
"Box constructed with null fptr deleter");
|
||||
}
|
||||
constexpr Box(octa::Nullptr): p_stor(nullptr, D()) {
|
||||
static_assert(!octa::IsPointer<D>::value,
|
||||
constexpr Box(Nullptr): p_stor(nullptr, D()) {
|
||||
static_assert(!IsPointer<D>::value,
|
||||
"Box constructed with null fptr deleter");
|
||||
}
|
||||
|
||||
template<typename U> explicit Box(U p, octa::EnableIf<
|
||||
octa::detail::SameOrLessCvQualified<U, Pointer>::value, Nat
|
||||
template<typename U> explicit Box(U p, EnableIf<
|
||||
detail::SameOrLessCvQualified<U, Pointer>::value, Nat
|
||||
> = Nat()): p_stor(p, D()) {
|
||||
static_assert(!octa::IsPointer<D>::value,
|
||||
static_assert(!IsPointer<D>::value,
|
||||
"Box constructed with null fptr deleter");
|
||||
}
|
||||
|
||||
template<typename U> Box(U p, octa::Conditional<
|
||||
octa::IsReference<D>::value,
|
||||
template<typename U> Box(U p, Conditional<
|
||||
IsReference<D>::value,
|
||||
D, AddLvalueReference<const D>
|
||||
> d, octa::EnableIf<octa::detail::SameOrLessCvQualified<U, Pointer>::value,
|
||||
> d, EnableIf<detail::SameOrLessCvQualified<U, Pointer>::value,
|
||||
Nat> = Nat()): p_stor(p, d) {}
|
||||
|
||||
Box(octa::Nullptr, octa::Conditional<octa::IsReference<D>::value,
|
||||
Box(Nullptr, Conditional<IsReference<D>::value,
|
||||
D, AddLvalueReference<const D>
|
||||
> d): p_stor(nullptr, d) {}
|
||||
|
||||
template<typename U> Box(U p, octa::RemoveReference<D> &&d,
|
||||
octa::EnableIf<
|
||||
octa::detail::SameOrLessCvQualified<U, Pointer>::value, Nat
|
||||
> = Nat()): p_stor(p, octa::move(d)) {
|
||||
static_assert(!octa::IsReference<D>::value,
|
||||
template<typename U> Box(U p, RemoveReference<D> &&d,
|
||||
EnableIf<
|
||||
detail::SameOrLessCvQualified<U, Pointer>::value, Nat
|
||||
> = Nat()): p_stor(p, move(d)) {
|
||||
static_assert(!IsReference<D>::value,
|
||||
"rvalue deleter cannot be a ref");
|
||||
}
|
||||
|
||||
Box(octa::Nullptr, octa::RemoveReference<D> &&d):
|
||||
p_stor(nullptr, octa::move(d)) {
|
||||
static_assert(!octa::IsReference<D>::value,
|
||||
Box(Nullptr, RemoveReference<D> &&d):
|
||||
p_stor(nullptr, move(d)) {
|
||||
static_assert(!IsReference<D>::value,
|
||||
"rvalue deleter cannot be a ref");
|
||||
}
|
||||
|
||||
Box(Box &&u): p_stor(u.release(), octa::forward<D>(u.get_deleter())) {}
|
||||
Box(Box &&u): p_stor(u.release(), forward<D>(u.get_deleter())) {}
|
||||
|
||||
template<typename TT, typename DD>
|
||||
Box(Box<TT, DD> &&u, EnableIf<IsArray<TT>::value
|
||||
&& octa::detail::SameOrLessCvQualified<typename Box<TT, DD>::Pointer,
|
||||
Pointer>::value
|
||||
&& octa::IsConvertible<DD, D>::value
|
||||
&& (!octa::IsReference<D>::value ||
|
||||
octa::IsSame<D, DD>::value)> = Nat()
|
||||
): p_stor(u.release(), octa::forward<DD>(u.get_deleter())) {}
|
||||
&& detail::SameOrLessCvQualified<typename Box<TT, DD>::Pointer,
|
||||
Pointer>::value
|
||||
&& IsConvertible<DD, D>::value
|
||||
&& (!IsReference<D>::value ||
|
||||
IsSame<D, DD>::value)> = Nat()
|
||||
): p_stor(u.release(), forward<DD>(u.get_deleter())) {}
|
||||
|
||||
Box &operator=(Box &&u) {
|
||||
reset(u.release());
|
||||
p_stor.second() = octa::forward<D>(u.get_deleter());
|
||||
p_stor.second() = forward<D>(u.get_deleter());
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename TT, typename DD>
|
||||
EnableIf<octa::IsArray<TT>::value
|
||||
&& octa::detail::SameOrLessCvQualified<typename Box<TT, DD>::Pointer,
|
||||
Pointer>::value
|
||||
EnableIf<IsArray<TT>::value
|
||||
&& detail::SameOrLessCvQualified<typename Box<TT, DD>::Pointer,
|
||||
Pointer>::value
|
||||
&& IsAssignable<D &, DD &&>::value,
|
||||
Box &
|
||||
> operator=(Box<TT, DD> &&u) {
|
||||
reset(u.release());
|
||||
p_stor.second() = octa::forward<DD>(u.get_deleter());
|
||||
p_stor.second() = forward<DD>(u.get_deleter());
|
||||
return *this;
|
||||
}
|
||||
|
||||
Box &operator=(octa::Nullptr) {
|
||||
Box &operator=(Nullptr) {
|
||||
reset();
|
||||
return *this;
|
||||
}
|
||||
|
||||
~Box() { reset(); }
|
||||
|
||||
octa::AddLvalueReference<T> operator[](octa::Size idx) const {
|
||||
AddLvalueReference<T> operator[](Size idx) const {
|
||||
return p_stor.first()[idx];
|
||||
}
|
||||
|
||||
|
@ -458,14 +456,14 @@ public:
|
|||
}
|
||||
|
||||
template<typename U> EnableIf<
|
||||
octa::detail::SameOrLessCvQualified<U, Pointer>::value, void
|
||||
detail::SameOrLessCvQualified<U, Pointer>::value, void
|
||||
> reset(U p) {
|
||||
Pointer tmp = p_stor.first();
|
||||
p_stor.first() = p;
|
||||
if (tmp) p_stor.second()(tmp);
|
||||
}
|
||||
|
||||
void reset(octa::Nullptr) {
|
||||
void reset(Nullptr) {
|
||||
Pointer tmp = p_stor.first();
|
||||
p_stor.first() = nullptr;
|
||||
if (tmp) p_stor.second()(tmp);
|
||||
|
@ -480,35 +478,35 @@ public:
|
|||
}
|
||||
|
||||
private:
|
||||
octa::detail::CompressedPair<T *, D> p_stor;
|
||||
detail::CompressedPair<T *, D> p_stor;
|
||||
};
|
||||
|
||||
namespace detail {
|
||||
template<typename T> struct BoxIf {
|
||||
using Box = octa::Box<T>;
|
||||
using Box = Box<T>;
|
||||
};
|
||||
|
||||
template<typename T> struct BoxIf<T[]> {
|
||||
using BoxUnknownSize = octa::Box<T[]>;
|
||||
using BoxUnknownSize = Box<T[]>;
|
||||
};
|
||||
|
||||
template<typename T, octa::Size N> struct BoxIf<T[N]> {
|
||||
template<typename T, Size N> struct BoxIf<T[N]> {
|
||||
using BoxKnownSize = void;
|
||||
};
|
||||
}
|
||||
|
||||
template<typename T, typename ...A>
|
||||
typename octa::detail::BoxIf<T>::Box make_box(A &&...args) {
|
||||
return Box<T>(new T(octa::forward<A>(args)...));
|
||||
typename detail::BoxIf<T>::Box make_box(A &&...args) {
|
||||
return Box<T>(new T(forward<A>(args)...));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
typename octa::detail::BoxIf<T>::BoxUnknownSize make_box(octa::Size n) {
|
||||
return Box<T>(new octa::RemoveExtent<T>[n]());
|
||||
typename detail::BoxIf<T>::BoxUnknownSize make_box(Size n) {
|
||||
return Box<T>(new RemoveExtent<T>[n]());
|
||||
}
|
||||
|
||||
template<typename T, typename ...A>
|
||||
typename octa::detail::BoxIf<T>::BoxKnownSize make_box(A &&...args) = delete;
|
||||
typename detail::BoxIf<T>::BoxKnownSize make_box(A &&...args) = delete;
|
||||
|
||||
/* allocator */
|
||||
|
||||
|
@ -531,8 +529,8 @@ template<> struct Allocator<const void> {
|
|||
};
|
||||
|
||||
template<typename T> struct Allocator {
|
||||
using Size = octa::Size;
|
||||
using Difference = octa::Ptrdiff;
|
||||
using Size = Size;
|
||||
using Difference = Ptrdiff;
|
||||
using Value = T;
|
||||
using Reference = T &;
|
||||
using ConstReference = const T &;
|
||||
|
@ -554,22 +552,22 @@ template<typename T> struct Allocator {
|
|||
Size max_size() const { return Size(~0) / sizeof(T); }
|
||||
|
||||
Pointer allocate(Size n, Allocator<void>::ConstPointer = nullptr) {
|
||||
return (Pointer) ::new octa::byte[n * sizeof(T)];
|
||||
return (Pointer) ::new byte[n * sizeof(T)];
|
||||
}
|
||||
|
||||
void deallocate(Pointer p, Size) { ::delete[] (octa::byte *) p; }
|
||||
void deallocate(Pointer p, Size) { ::delete[] (byte *) p; }
|
||||
|
||||
template<typename U, typename ...A>
|
||||
void construct(U *p, A &&...args) {
|
||||
::new((void *)p) U(octa::forward<A>(args)...);
|
||||
::new((void *)p) U(forward<A>(args)...);
|
||||
}
|
||||
|
||||
void destroy(Pointer p) { p->~T(); }
|
||||
};
|
||||
|
||||
template<typename T> struct Allocator<const T> {
|
||||
using Size = octa::Size;
|
||||
using Difference = octa::Ptrdiff;
|
||||
using Size = Size;
|
||||
using Difference = Ptrdiff;
|
||||
using Value = const T;
|
||||
using Reference = const T &;
|
||||
using ConstReference = const T &;
|
||||
|
@ -588,14 +586,14 @@ template<typename T> struct Allocator<const T> {
|
|||
Size max_size() const { return Size(~0) / sizeof(T); }
|
||||
|
||||
Pointer allocate(Size n, Allocator<void>::ConstPointer = nullptr) {
|
||||
return (Pointer) ::new octa::byte[n * sizeof(T)];
|
||||
return (Pointer) ::new byte[n * sizeof(T)];
|
||||
}
|
||||
|
||||
void deallocate(Pointer p, Size) { ::delete[] (octa::byte *) p; }
|
||||
void deallocate(Pointer p, Size) { ::delete[] (byte *) p; }
|
||||
|
||||
template<typename U, typename ...A>
|
||||
void construct(U *p, A &&...args) {
|
||||
::new((void *)p) U(octa::forward<A>(args)...);
|
||||
::new((void *)p) U(forward<A>(args)...);
|
||||
}
|
||||
|
||||
void destroy(Pointer p) { p->~T(); }
|
||||
|
@ -678,7 +676,7 @@ namespace detail {
|
|||
|
||||
template<typename A, typename D, bool = SizeTest<A>::value>
|
||||
struct SizeBase {
|
||||
using Type = octa::MakeUnsigned<D>;
|
||||
using Type = MakeUnsigned<D>;
|
||||
};
|
||||
|
||||
template<typename A, typename D>
|
||||
|
@ -696,22 +694,22 @@ template<typename A>
|
|||
using AllocatorValue = typename AllocatorType<A>::Value;
|
||||
|
||||
template<typename A>
|
||||
using AllocatorPointer = typename octa::detail::PointerType<
|
||||
using AllocatorPointer = typename detail::PointerType<
|
||||
AllocatorValue<A>, AllocatorType<A>
|
||||
>::Type;
|
||||
|
||||
template<typename A>
|
||||
using AllocatorConstPointer = typename octa::detail::ConstPointer<
|
||||
using AllocatorConstPointer = typename detail::ConstPointer<
|
||||
AllocatorValue<A>, AllocatorPointer<A>, AllocatorType<A>
|
||||
>::Type;
|
||||
|
||||
template<typename A>
|
||||
using AllocatorVoidPointer = typename octa::detail::VoidPointer<
|
||||
using AllocatorVoidPointer = typename detail::VoidPointer<
|
||||
AllocatorPointer<A>, AllocatorType<A>
|
||||
>::Type;
|
||||
|
||||
template<typename A>
|
||||
using AllocatorConstVoidPointer = typename octa::detail::ConstVoidPointer<
|
||||
using AllocatorConstVoidPointer = typename detail::ConstVoidPointer<
|
||||
AllocatorPointer<A>, AllocatorType<A>
|
||||
>::Type;
|
||||
|
||||
|
@ -737,21 +735,21 @@ namespace detail {
|
|||
}
|
||||
|
||||
template<typename A>
|
||||
using AllocatorDifference = typename octa::detail::AllocDifference<
|
||||
using AllocatorDifference = typename detail::AllocDifference<
|
||||
A, AllocatorPointer<A>
|
||||
>::Type;
|
||||
|
||||
/* allocator size */
|
||||
|
||||
template<typename A>
|
||||
using AllocatorSize = typename octa::detail::SizeBase<
|
||||
using AllocatorSize = typename detail::SizeBase<
|
||||
A, AllocatorDifference<A>
|
||||
>::Type;
|
||||
|
||||
/* allocator rebind */
|
||||
|
||||
namespace detail {
|
||||
template<typename T, typename U, bool = octa::detail::HasRebind<T, U>::value>
|
||||
template<typename T, typename U, bool = detail::HasRebind<T, U>::value>
|
||||
struct AllocTraitsRebindType {
|
||||
using Type = typename T::template Rebind<U>;
|
||||
};
|
||||
|
@ -772,7 +770,7 @@ namespace detail {
|
|||
} /* namespace detail */
|
||||
|
||||
template<typename A, typename T>
|
||||
using AllocatorRebind = typename octa::detail::AllocTraitsRebindType<
|
||||
using AllocatorRebind = typename detail::AllocTraitsRebindType<
|
||||
AllocatorType<A>, T
|
||||
>::Type;
|
||||
|
||||
|
@ -790,7 +788,7 @@ namespace detail {
|
|||
template<typename A, bool = PropagateOnContainerCopyAssignmentTest<
|
||||
A
|
||||
>::value> struct PropagateOnContainerCopyAssignmentBase {
|
||||
using Type = octa::False;
|
||||
using Type = False;
|
||||
};
|
||||
|
||||
template<typename A>
|
||||
|
@ -801,7 +799,7 @@ namespace detail {
|
|||
|
||||
template<typename A>
|
||||
using AllocatorPropagateOnContainerCopyAssignment
|
||||
= typename octa::detail::PropagateOnContainerCopyAssignmentBase<A>::Type;
|
||||
= typename detail::PropagateOnContainerCopyAssignmentBase<A>::Type;
|
||||
|
||||
/* allocator propagate on container move assignment */
|
||||
|
||||
|
@ -817,7 +815,7 @@ namespace detail {
|
|||
template<typename A, bool = PropagateOnContainerMoveAssignmentTest<
|
||||
A
|
||||
>::value> struct PropagateOnContainerMoveAssignmentBase {
|
||||
using Type = octa::False;
|
||||
using Type = False;
|
||||
};
|
||||
|
||||
template<typename A>
|
||||
|
@ -828,7 +826,7 @@ namespace detail {
|
|||
|
||||
template<typename A>
|
||||
using AllocatorPropagateOnContainerMoveAssignment
|
||||
= typename octa::detail::PropagateOnContainerMoveAssignmentBase<A>::Type;
|
||||
= typename detail::PropagateOnContainerMoveAssignmentBase<A>::Type;
|
||||
|
||||
/* allocator propagate on container swap */
|
||||
|
||||
|
@ -843,7 +841,7 @@ namespace detail {
|
|||
|
||||
template<typename A, bool = PropagateOnContainerSwapTest<A>::value>
|
||||
struct PropagateOnContainerSwapBase {
|
||||
using Type = octa::False;
|
||||
using Type = False;
|
||||
};
|
||||
|
||||
template<typename A>
|
||||
|
@ -854,7 +852,7 @@ namespace detail {
|
|||
|
||||
template<typename A>
|
||||
using AllocatorPropagateOnContainerSwap
|
||||
= typename octa::detail::PropagateOnContainerSwapBase<A>::Type;
|
||||
= typename detail::PropagateOnContainerSwapBase<A>::Type;
|
||||
|
||||
/* allocator is always equal */
|
||||
|
||||
|
@ -868,7 +866,7 @@ namespace detail {
|
|||
|
||||
template<typename A, bool = IsAlwaysEqualTest<A>::value>
|
||||
struct IsAlwaysEqualBase {
|
||||
using Type = typename octa::IsEmpty<A>::Type;
|
||||
using Type = typename IsEmpty<A>::Type;
|
||||
};
|
||||
|
||||
template<typename A>
|
||||
|
@ -878,7 +876,7 @@ namespace detail {
|
|||
} /* namespace detail */
|
||||
|
||||
template<typename A>
|
||||
using AllocatorIsAlwaysEqual = typename octa::detail::IsAlwaysEqualBase<A>::Type;
|
||||
using AllocatorIsAlwaysEqual = typename detail::IsAlwaysEqualBase<A>::Type;
|
||||
|
||||
/* allocator allocate */
|
||||
|
||||
|
@ -891,33 +889,31 @@ allocator_allocate(A &a, AllocatorSize<A> n) {
|
|||
namespace detail {
|
||||
template<typename A, typename S, typename CVP>
|
||||
auto allocate_hint_test(A &&a, S &&sz, CVP &&p)
|
||||
-> decltype(a.allocate(sz, p), octa::True());
|
||||
-> decltype(a.allocate(sz, p), True());
|
||||
|
||||
template<typename A, typename S, typename CVP>
|
||||
auto allocate_hint_test(const A &, S &&, CVP &&)
|
||||
-> octa::False;
|
||||
-> False;
|
||||
|
||||
template<typename A, typename S, typename CVP>
|
||||
struct AllocateHintTest: octa::IntegralConstant<bool,
|
||||
octa::IsSame<
|
||||
decltype(allocate_hint_test(octa::declval<A>(),
|
||||
octa::declval<S>(),
|
||||
octa::declval<CVP>())),
|
||||
octa::True
|
||||
struct AllocateHintTest: IntegralConstant<bool,
|
||||
IsSame<decltype(allocate_hint_test(declval<A>(),
|
||||
declval<S>(),
|
||||
declval<CVP>())), True
|
||||
>::value
|
||||
> {};
|
||||
|
||||
template<typename A>
|
||||
inline AllocatorPointer<A> allocate(A &a, AllocatorSize<A> n,
|
||||
AllocatorConstVoidPointer<A> h,
|
||||
octa::True) {
|
||||
True) {
|
||||
return a.allocate(n, h);
|
||||
}
|
||||
|
||||
template<typename A>
|
||||
inline AllocatorPointer<A> allocate(A &a, AllocatorSize<A> n,
|
||||
AllocatorConstVoidPointer<A>,
|
||||
octa::False) {
|
||||
False) {
|
||||
return a.allocate(n);
|
||||
}
|
||||
} /* namespace detail */
|
||||
|
@ -926,8 +922,8 @@ template<typename A>
|
|||
inline AllocatorPointer<A>
|
||||
allocator_allocate(A &a, AllocatorSize<A> n,
|
||||
AllocatorConstVoidPointer<A> h) {
|
||||
return octa::detail::allocate(a, n, h,
|
||||
octa::detail::AllocateHintTest<
|
||||
return detail::allocate(a, n, h,
|
||||
detail::AllocateHintTest<
|
||||
A, AllocatorSize<A>, AllocatorConstVoidPointer<A>
|
||||
>());
|
||||
}
|
||||
|
@ -945,139 +941,129 @@ inline void allocator_deallocate(A &a, AllocatorPointer<A> p,
|
|||
namespace detail {
|
||||
template<typename A, typename T, typename ...Args>
|
||||
auto construct_test(A &&a, T *p, Args &&...args)
|
||||
-> decltype(a.construct(p, octa::forward<Args>(args)...),
|
||||
octa::True());
|
||||
-> decltype(a.construct(p, forward<Args>(args)...),
|
||||
True());
|
||||
|
||||
template<typename A, typename T, typename ...Args>
|
||||
auto construct_test(const A &, T *, Args &&...)
|
||||
-> octa::False;
|
||||
-> False;
|
||||
|
||||
template<typename A, typename T, typename ...Args>
|
||||
struct ConstructTest: octa::IntegralConstant<bool,
|
||||
octa::IsSame<
|
||||
decltype(construct_test(octa::declval<A>(),
|
||||
octa::declval<T>(),
|
||||
octa::declval<Args>()...)),
|
||||
octa::True
|
||||
struct ConstructTest: IntegralConstant<bool,
|
||||
IsSame< decltype(construct_test(declval<A>(),
|
||||
declval<T>(),
|
||||
declval<Args>()...)), True
|
||||
>::value
|
||||
> {};
|
||||
|
||||
template<typename A, typename T, typename ...Args>
|
||||
inline void construct(octa::True, A &a, T *p, Args &&...args) {
|
||||
a.construct(p, octa::forward<Args>(args)...);
|
||||
inline void construct(True, A &a, T *p, Args &&...args) {
|
||||
a.construct(p, forward<Args>(args)...);
|
||||
}
|
||||
|
||||
template<typename A, typename T, typename ...Args>
|
||||
inline void construct(octa::False, A &, T *p, Args &&...args) {
|
||||
::new ((void *)p) T(octa::forward<Args>(args)...);
|
||||
inline void construct(False, A &, T *p, Args &&...args) {
|
||||
::new ((void *)p) T(forward<Args>(args)...);
|
||||
}
|
||||
} /* namespace detail */
|
||||
|
||||
template<typename A, typename T, typename ...Args>
|
||||
inline void allocator_construct(A &a, T *p, Args &&...args) {
|
||||
octa::detail::construct(octa::detail::ConstructTest<
|
||||
A, T *, Args...
|
||||
>(), a, p, octa::forward<Args>(args)...);
|
||||
detail::construct(detail::ConstructTest<A, T *, Args...>(), a, p,
|
||||
forward<Args>(args)...);
|
||||
}
|
||||
|
||||
/* allocator destroy */
|
||||
|
||||
namespace detail {
|
||||
template<typename A, typename P>
|
||||
auto destroy_test(A &&a, P &&p) -> decltype(a.destroy(p), octa::True());
|
||||
auto destroy_test(A &&a, P &&p) -> decltype(a.destroy(p), True());
|
||||
|
||||
template<typename A, typename P>
|
||||
auto destroy_test(const A &, P &&) -> octa::False;
|
||||
auto destroy_test(const A &, P &&) -> False;
|
||||
|
||||
template<typename A, typename P>
|
||||
struct DestroyTest: octa::IntegralConstant<bool,
|
||||
octa::IsSame<
|
||||
decltype(destroy_test(octa::declval<A>(), octa::declval<P>())),
|
||||
octa::True
|
||||
struct DestroyTest: IntegralConstant<bool,
|
||||
IsSame<decltype(destroy_test(declval<A>(), declval<P>())), True
|
||||
>::value
|
||||
> {};
|
||||
|
||||
template<typename A, typename T>
|
||||
inline void destroy(octa::True, A &a, T *p) {
|
||||
inline void destroy(True, A &a, T *p) {
|
||||
a.destroy(p);
|
||||
}
|
||||
|
||||
template<typename A, typename T>
|
||||
inline void destroy(octa::False, A &, T *p) {
|
||||
inline void destroy(False, A &, T *p) {
|
||||
p->~T();
|
||||
}
|
||||
} /* namespace detail */
|
||||
|
||||
template<typename A, typename T>
|
||||
inline void allocator_destroy(A &a, T *p) {
|
||||
octa::detail::destroy(octa::detail::DestroyTest<A, T *>(), a, p);
|
||||
detail::destroy(detail::DestroyTest<A, T *>(), a, p);
|
||||
}
|
||||
|
||||
/* allocator max size */
|
||||
|
||||
namespace detail {
|
||||
template<typename A>
|
||||
auto alloc_max_size_test(A &&a) -> decltype(a.max_size(), octa::True());
|
||||
auto alloc_max_size_test(A &&a) -> decltype(a.max_size(), True());
|
||||
|
||||
template<typename A>
|
||||
auto alloc_max_size_test(const A &) -> octa::False;
|
||||
auto alloc_max_size_test(const A &) -> False;
|
||||
|
||||
template<typename A>
|
||||
struct AllocMaxSizeTest: octa::IntegralConstant<bool,
|
||||
octa::IsSame<
|
||||
decltype(alloc_max_size_test(octa::declval<A &>())),
|
||||
octa::True
|
||||
struct AllocMaxSizeTest: IntegralConstant<bool,
|
||||
IsSame<decltype(alloc_max_size_test(declval<A &>())), True
|
||||
>::value
|
||||
> {};
|
||||
|
||||
template<typename A>
|
||||
inline AllocatorSize<A> alloc_max_size(octa::True, const A &a) {
|
||||
inline AllocatorSize<A> alloc_max_size(True, const A &a) {
|
||||
return a.max_size();
|
||||
}
|
||||
|
||||
template<typename A>
|
||||
inline AllocatorSize<A> alloc_max_size(octa::False, const A &) {
|
||||
inline AllocatorSize<A> alloc_max_size(False, const A &) {
|
||||
return AllocatorSize<A>(~0);
|
||||
}
|
||||
} /* namespace detail */
|
||||
|
||||
template<typename A>
|
||||
inline AllocatorSize<A> allocator_max_size(const A &a) {
|
||||
return octa::detail::alloc_max_size(octa::detail::AllocMaxSizeTest<
|
||||
const A
|
||||
>(), a);
|
||||
return detail::alloc_max_size(detail::AllocMaxSizeTest<const A>(), a);
|
||||
}
|
||||
|
||||
/* allocator container copy */
|
||||
|
||||
namespace detail {
|
||||
template<typename A>
|
||||
auto alloc_copy_test(A &&a) -> decltype(a.container_copy(), octa::True());
|
||||
auto alloc_copy_test(A &&a) -> decltype(a.container_copy(), True());
|
||||
|
||||
template<typename A>
|
||||
auto alloc_copy_test(const A &) -> octa::False;
|
||||
auto alloc_copy_test(const A &) -> False;
|
||||
|
||||
template<typename A>
|
||||
struct AllocCopyTest: octa::IntegralConstant<bool,
|
||||
octa::IsSame<
|
||||
decltype(alloc_copy_test(octa::declval<A &>())), octa::True
|
||||
struct AllocCopyTest: IntegralConstant<bool,
|
||||
IsSame<decltype(alloc_copy_test(declval<A &>())), True
|
||||
>::value
|
||||
> {};
|
||||
|
||||
template<typename A>
|
||||
inline AllocatorType<A> alloc_container_copy(octa::True, const A &a) {
|
||||
inline AllocatorType<A> alloc_container_copy(True, const A &a) {
|
||||
return a.container_copy();
|
||||
}
|
||||
|
||||
template<typename A>
|
||||
inline AllocatorType<A> alloc_container_copy(octa::False, const A &a) {
|
||||
inline AllocatorType<A> alloc_container_copy(False, const A &a) {
|
||||
return a;
|
||||
}
|
||||
} /* namespace detail */
|
||||
|
||||
template<typename A>
|
||||
inline AllocatorType<A> allocator_container_copy(const A &a) {
|
||||
return octa::detail::alloc_container_copy(octa::detail::AllocCopyTest<
|
||||
return detail::alloc_container_copy(detail::AllocCopyTest<
|
||||
const A
|
||||
>(), a);
|
||||
}
|
||||
|
|
196
octa/range.hh
196
octa/range.hh
|
@ -41,7 +41,7 @@ namespace detail { \
|
|||
}; \
|
||||
} \
|
||||
template<typename T> \
|
||||
using Range##Name = typename octa::detail::Range##Name##Base<T>::Type;
|
||||
using Range##Name = typename detail::Range##Name##Base<T>::Type;
|
||||
|
||||
OCTA_RANGE_TRAIT(Category)
|
||||
OCTA_RANGE_TRAIT(Size)
|
||||
|
@ -70,7 +70,7 @@ namespace detail {
|
|||
// is input range
|
||||
|
||||
namespace detail {
|
||||
template<typename T, bool = octa::IsConvertible<
|
||||
template<typename T, bool = IsConvertible<
|
||||
RangeCategory<T>, InputRangeTag
|
||||
>::value> struct IsInputRangeBase: False {};
|
||||
|
||||
|
@ -78,16 +78,16 @@ namespace detail {
|
|||
struct IsInputRangeBase<T, true>: True {};
|
||||
}
|
||||
|
||||
template<typename T, bool = octa::detail::IsRangeTest<T>::value>
|
||||
template<typename T, bool = detail::IsRangeTest<T>::value>
|
||||
struct IsInputRange: False {};
|
||||
|
||||
template<typename T>
|
||||
struct IsInputRange<T, true>: octa::detail::IsInputRangeBase<T>::Type {};
|
||||
struct IsInputRange<T, true>: detail::IsInputRangeBase<T>::Type {};
|
||||
|
||||
// is forward range
|
||||
|
||||
namespace detail {
|
||||
template<typename T, bool = octa::IsConvertible<
|
||||
template<typename T, bool = IsConvertible<
|
||||
RangeCategory<T>, ForwardRangeTag
|
||||
>::value> struct IsForwardRangeBase: False {};
|
||||
|
||||
|
@ -95,16 +95,16 @@ namespace detail {
|
|||
struct IsForwardRangeBase<T, true>: True {};
|
||||
}
|
||||
|
||||
template<typename T, bool = octa::detail::IsRangeTest<T>::value>
|
||||
template<typename T, bool = detail::IsRangeTest<T>::value>
|
||||
struct IsForwardRange: False {};
|
||||
|
||||
template<typename T>
|
||||
struct IsForwardRange<T, true>: octa::detail::IsForwardRangeBase<T>::Type {};
|
||||
struct IsForwardRange<T, true>: detail::IsForwardRangeBase<T>::Type {};
|
||||
|
||||
// is bidirectional range
|
||||
|
||||
namespace detail {
|
||||
template<typename T, bool = octa::IsConvertible<
|
||||
template<typename T, bool = IsConvertible<
|
||||
RangeCategory<T>, BidirectionalRangeTag
|
||||
>::value> struct IsBidirectionalRangeBase: False {};
|
||||
|
||||
|
@ -112,17 +112,17 @@ namespace detail {
|
|||
struct IsBidirectionalRangeBase<T, true>: True {};
|
||||
}
|
||||
|
||||
template<typename T, bool = octa::detail::IsRangeTest<T>::value>
|
||||
template<typename T, bool = detail::IsRangeTest<T>::value>
|
||||
struct IsBidirectionalRange: False {};
|
||||
|
||||
template<typename T>
|
||||
struct IsBidirectionalRange<T, true>:
|
||||
octa::detail::IsBidirectionalRangeBase<T>::Type {};
|
||||
detail::IsBidirectionalRangeBase<T>::Type {};
|
||||
|
||||
// is random access range
|
||||
|
||||
namespace detail {
|
||||
template<typename T, bool = octa::IsConvertible<
|
||||
template<typename T, bool = IsConvertible<
|
||||
RangeCategory<T>, RandomAccessRangeTag
|
||||
>::value> struct IsRandomAccessRangeBase: False {};
|
||||
|
||||
|
@ -130,17 +130,17 @@ namespace detail {
|
|||
struct IsRandomAccessRangeBase<T, true>: True {};
|
||||
}
|
||||
|
||||
template<typename T, bool = octa::detail::IsRangeTest<T>::value>
|
||||
template<typename T, bool = detail::IsRangeTest<T>::value>
|
||||
struct IsRandomAccessRange: False {};
|
||||
|
||||
template<typename T>
|
||||
struct IsRandomAccessRange<T, true>:
|
||||
octa::detail::IsRandomAccessRangeBase<T>::Type {};
|
||||
detail::IsRandomAccessRangeBase<T>::Type {};
|
||||
|
||||
// is finite random access range
|
||||
|
||||
namespace detail {
|
||||
template<typename T, bool = octa::IsConvertible<
|
||||
template<typename T, bool = IsConvertible<
|
||||
RangeCategory<T>, FiniteRandomAccessRangeTag
|
||||
>::value> struct IsFiniteRandomAccessRangeBase: False {};
|
||||
|
||||
|
@ -148,12 +148,12 @@ namespace detail {
|
|||
struct IsFiniteRandomAccessRangeBase<T, true>: True {};
|
||||
}
|
||||
|
||||
template<typename T, bool = octa::detail::IsRangeTest<T>::value>
|
||||
template<typename T, bool = detail::IsRangeTest<T>::value>
|
||||
struct IsFiniteRandomAccessRange: False {};
|
||||
|
||||
template<typename T>
|
||||
struct IsFiniteRandomAccessRange<T, true>:
|
||||
octa::detail::IsFiniteRandomAccessRangeBase<T>::Type {};
|
||||
detail::IsFiniteRandomAccessRangeBase<T>::Type {};
|
||||
|
||||
// is infinite random access range
|
||||
|
||||
|
@ -174,12 +174,12 @@ namespace detail {
|
|||
};
|
||||
}
|
||||
|
||||
template<typename T, bool = (octa::IsConvertible<
|
||||
template<typename T, bool = (IsConvertible<
|
||||
RangeCategory<T>, OutputRangeTag
|
||||
>::value || (IsInputRange<T>::value &&
|
||||
(octa::detail::OutputRangeTest<T, const RangeValue<T> &>::value ||
|
||||
octa::detail::OutputRangeTest<T, RangeValue<T> &&>::value ||
|
||||
octa::detail::OutputRangeTest<T, RangeValue<T> >::value)
|
||||
(detail::OutputRangeTest<T, const RangeValue<T> &>::value ||
|
||||
detail::OutputRangeTest<T, RangeValue<T> &&>::value ||
|
||||
detail::OutputRangeTest<T, RangeValue<T> >::value)
|
||||
))> struct IsOutputRange: False {};
|
||||
|
||||
template<typename T>
|
||||
|
@ -195,7 +195,7 @@ namespace detail {
|
|||
::new(&get_ref()) T(range);
|
||||
}
|
||||
explicit RangeIterator(T &&range) {
|
||||
::new(&get_ref()) T(octa::move(range));
|
||||
::new(&get_ref()) T(move(range));
|
||||
}
|
||||
RangeIterator &operator++() {
|
||||
get_ref().pop_front();
|
||||
|
@ -208,7 +208,7 @@ namespace detail {
|
|||
private:
|
||||
T &get_ref() { return *((T *)&p_range); }
|
||||
const T &get_ref() const { return *((T *)&p_range); }
|
||||
octa::AlignedStorage<sizeof(T), alignof(T)> p_range;
|
||||
AlignedStorage<sizeof(T), alignof(T)> p_range;
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -259,12 +259,12 @@ public:
|
|||
RangeHalf() = delete;
|
||||
RangeHalf(const T &range): p_range(range) {}
|
||||
|
||||
template<typename U, typename = octa::EnableIf<
|
||||
octa::IsConvertible<U, T>::value
|
||||
template<typename U, typename = EnableIf<
|
||||
IsConvertible<U, T>::value
|
||||
>> RangeHalf(const RangeHalf<U> &half): p_range(half.p_range) {}
|
||||
|
||||
RangeHalf(const RangeHalf &half): p_range(half.p_range) {}
|
||||
RangeHalf(RangeHalf &&half): p_range(octa::move(half.p_range)) {}
|
||||
RangeHalf(RangeHalf &&half): p_range(move(half.p_range)) {}
|
||||
|
||||
RangeHalf &operator=(const RangeHalf &half) {
|
||||
p_range = half.p_range;
|
||||
|
@ -272,7 +272,7 @@ public:
|
|||
}
|
||||
|
||||
RangeHalf &operator=(RangeHalf &&half) {
|
||||
p_range = octa::move(half.p_range);
|
||||
p_range = move(half.p_range);
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
@ -287,10 +287,10 @@ public:
|
|||
}
|
||||
|
||||
RangeDifference<T> add_n(RangeDifference<T> n) {
|
||||
return octa::detail::RangeAdd<RangeHalf<T>>::add_n(*this, n);
|
||||
return detail::RangeAdd<RangeHalf<T>>::add_n(*this, n);
|
||||
}
|
||||
RangeDifference<T> sub_n(RangeDifference<T> n) {
|
||||
return octa::detail::RangeAdd<RangeHalf<T>>::sub_n(*this, n);
|
||||
return detail::RangeAdd<RangeHalf<T>>::sub_n(*this, n);
|
||||
}
|
||||
|
||||
RangeReference<T> get() const {
|
||||
|
@ -408,7 +408,7 @@ template<typename> struct ReverseRange;
|
|||
template<typename> struct MoveRange;
|
||||
|
||||
template<typename B, typename C, typename V, typename R = V &,
|
||||
typename S = octa::Size, typename D = octa::Ptrdiff
|
||||
typename S = Size, typename D = Ptrdiff
|
||||
> struct InputRange {
|
||||
using Category = C;
|
||||
using Size = S;
|
||||
|
@ -416,27 +416,27 @@ template<typename B, typename C, typename V, typename R = V &,
|
|||
using Value = V;
|
||||
using Reference = R;
|
||||
|
||||
octa::detail::RangeIterator<B> begin() const {
|
||||
return octa::detail::RangeIterator<B>((const B &)*this);
|
||||
detail::RangeIterator<B> begin() const {
|
||||
return detail::RangeIterator<B>((const B &)*this);
|
||||
}
|
||||
octa::detail::RangeIterator<B> end() const {
|
||||
return octa::detail::RangeIterator<B>();
|
||||
detail::RangeIterator<B> end() const {
|
||||
return detail::RangeIterator<B>();
|
||||
}
|
||||
|
||||
Size pop_front_n(Size n) {
|
||||
return octa::detail::pop_front_n<B>(*((B *)this), n);
|
||||
return detail::pop_front_n<B>(*((B *)this), n);
|
||||
}
|
||||
|
||||
Size pop_back_n(Size n) {
|
||||
return octa::detail::pop_back_n<B>(*((B *)this), n);
|
||||
return detail::pop_back_n<B>(*((B *)this), n);
|
||||
}
|
||||
|
||||
Size push_front_n(Size n) {
|
||||
return octa::detail::push_front_n<B>(*((B *)this), n);
|
||||
return detail::push_front_n<B>(*((B *)this), n);
|
||||
}
|
||||
|
||||
Size push_back_n(Size n) {
|
||||
return octa::detail::push_back_n<B>(*((B *)this), n);
|
||||
return detail::push_back_n<B>(*((B *)this), n);
|
||||
}
|
||||
|
||||
B iter() const {
|
||||
|
@ -463,8 +463,8 @@ template<typename B, typename C, typename V, typename R = V &,
|
|||
}
|
||||
|
||||
template<typename OR,
|
||||
typename = octa::EnableIf<octa::IsOutputRange<OR>::value
|
||||
>> Size copy(OR &&orange, Size n = -1) {
|
||||
typename = EnableIf<IsOutputRange<OR>::value>
|
||||
> Size copy(OR &&orange, Size n = -1) {
|
||||
B r(*((B *)this));
|
||||
Size on = n;
|
||||
for (; n && !r.empty(); --n) {
|
||||
|
@ -474,7 +474,7 @@ template<typename B, typename C, typename V, typename R = V &,
|
|||
return (on - n);
|
||||
}
|
||||
|
||||
Size copy(octa::RemoveCv<Value> *p, Size n = -1) {
|
||||
Size copy(RemoveCv<Value> *p, Size n = -1) {
|
||||
B r(*((B *)this));
|
||||
Size on = n;
|
||||
for (; n && !r.empty(); --n) {
|
||||
|
@ -501,7 +501,7 @@ auto citer(const T &r) -> decltype(r.iter()) {
|
|||
}
|
||||
|
||||
template<typename B, typename V, typename R = V &,
|
||||
typename S = octa::Size, typename D = octa::Ptrdiff
|
||||
typename S = Size, typename D = Ptrdiff
|
||||
> struct OutputRange {
|
||||
using Category = OutputRangeTag;
|
||||
using Size = S;
|
||||
|
@ -533,12 +533,12 @@ public:
|
|||
HalfRange() = delete;
|
||||
HalfRange(const HalfRange &range): p_beg(range.p_beg),
|
||||
p_end(range.p_end) {}
|
||||
HalfRange(HalfRange &&range): p_beg(octa::move(range.p_beg)),
|
||||
p_end(octa::move(range.p_end)) {}
|
||||
HalfRange(HalfRange &&range): p_beg(move(range.p_beg)),
|
||||
p_end(move(range.p_end)) {}
|
||||
HalfRange(const T &beg, const T &end): p_beg(beg),
|
||||
p_end(end) {}
|
||||
HalfRange(T &&beg, T &&end): p_beg(octa::move(beg)),
|
||||
p_end(octa::move(end)) {}
|
||||
HalfRange(T &&beg, T &&end): p_beg(move(beg)),
|
||||
p_end(move(end)) {}
|
||||
|
||||
HalfRange &operator=(const HalfRange &range) {
|
||||
p_beg = range.p_beg;
|
||||
|
@ -547,8 +547,8 @@ public:
|
|||
}
|
||||
|
||||
HalfRange &operator=(HalfRange &&range) {
|
||||
p_beg = octa::move(range.p_beg);
|
||||
p_end = octa::move(range.p_end);
|
||||
p_beg = move(range.p_beg);
|
||||
p_end = move(range.p_end);
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
@ -601,7 +601,7 @@ public:
|
|||
return p_beg.range().put(v);
|
||||
}
|
||||
bool put(RangeValue<Rtype> &&v) {
|
||||
return p_beg.range().put(octa::move(v));
|
||||
return p_beg.range().put(move(v));
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -620,14 +620,14 @@ public:
|
|||
ReverseRange() = delete;
|
||||
ReverseRange(const T &range): p_range(range) {}
|
||||
ReverseRange(const ReverseRange &it): p_range(it.p_range) {}
|
||||
ReverseRange(ReverseRange &&it): p_range(octa::move(it.p_range)) {}
|
||||
ReverseRange(ReverseRange &&it): p_range(move(it.p_range)) {}
|
||||
|
||||
ReverseRange &operator=(const ReverseRange &v) {
|
||||
p_range = v.p_range;
|
||||
return *this;
|
||||
}
|
||||
ReverseRange &operator=(ReverseRange &&v) {
|
||||
p_range = octa::move(v.p_range);
|
||||
p_range = move(v.p_range);
|
||||
return *this;
|
||||
}
|
||||
ReverseRange &operator=(const T &v) {
|
||||
|
@ -635,7 +635,7 @@ public:
|
|||
return *this;
|
||||
}
|
||||
ReverseRange &operator=(T &&v) {
|
||||
p_range = octa::move(v);
|
||||
p_range = move(v);
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
@ -695,14 +695,14 @@ public:
|
|||
MoveRange() = delete;
|
||||
MoveRange(const T &range): p_range(range) {}
|
||||
MoveRange(const MoveRange &it): p_range(it.p_range) {}
|
||||
MoveRange(MoveRange &&it): p_range(octa::move(it.p_range)) {}
|
||||
MoveRange(MoveRange &&it): p_range(move(it.p_range)) {}
|
||||
|
||||
MoveRange &operator=(const MoveRange &v) {
|
||||
p_range = v.p_range;
|
||||
return *this;
|
||||
}
|
||||
MoveRange &operator=(MoveRange &&v) {
|
||||
p_range = octa::move(v.p_range);
|
||||
p_range = move(v.p_range);
|
||||
return *this;
|
||||
}
|
||||
MoveRange &operator=(const T &v) {
|
||||
|
@ -710,7 +710,7 @@ public:
|
|||
return *this;
|
||||
}
|
||||
MoveRange &operator=(T &&v) {
|
||||
p_range = octa::move(v);
|
||||
p_range = move(v);
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
@ -743,17 +743,17 @@ public:
|
|||
Rsize push_front_n(Rsize n) { return p_range.push_front_n(n); }
|
||||
Rsize push_back_n(Rsize n) { return p_range.push_back_n(n); }
|
||||
|
||||
Rref front() const { return octa::move(p_range.front()); }
|
||||
Rref back() const { return octa::move(p_range.back()); }
|
||||
Rref front() const { return move(p_range.front()); }
|
||||
Rref back() const { return move(p_range.back()); }
|
||||
|
||||
Rref operator[](Rsize i) const { return octa::move(p_range[i]); }
|
||||
Rref operator[](Rsize i) const { return move(p_range[i]); }
|
||||
|
||||
MoveRange<T> slice(Rsize start, Rsize end) const {
|
||||
return MoveRange<T>(p_range.slice(start, end));
|
||||
}
|
||||
|
||||
bool put(const Rval &v) { return p_range.put(v); }
|
||||
bool put(Rval &&v) { return p_range.put(octa::move(v)); }
|
||||
bool put(Rval &&v) { return p_range.put(move(v)); }
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
|
@ -792,10 +792,10 @@ template<typename T>
|
|||
struct PointerRange: InputRange<PointerRange<T>, FiniteRandomAccessRangeTag, T> {
|
||||
PointerRange() = delete;
|
||||
PointerRange(T *beg, T *end): p_beg(beg), p_end(end) {}
|
||||
PointerRange(T *beg, octa::Size n): p_beg(beg), p_end(beg + n) {}
|
||||
PointerRange(T *beg, Size n): p_beg(beg), p_end(beg + n) {}
|
||||
|
||||
template<typename U, typename = octa::EnableIf<
|
||||
octa::IsConvertible<U *, T *>::value
|
||||
template<typename U, typename = EnableIf<
|
||||
IsConvertible<U *, T *>::value
|
||||
>> PointerRange(const PointerRange<U> &v):
|
||||
p_beg(&v[0]), p_end(&v[v.size()]) {}
|
||||
|
||||
|
@ -817,8 +817,8 @@ struct PointerRange: InputRange<PointerRange<T>, FiniteRandomAccessRangeTag, T>
|
|||
--p_beg; return true;
|
||||
}
|
||||
|
||||
octa::Size pop_front_n(octa::Size n) {
|
||||
octa::Size olen = p_end - p_beg;
|
||||
Size pop_front_n(Size n) {
|
||||
Size olen = p_end - p_beg;
|
||||
p_beg += n;
|
||||
if (p_beg > p_end) {
|
||||
p_beg = p_end;
|
||||
|
@ -827,7 +827,7 @@ struct PointerRange: InputRange<PointerRange<T>, FiniteRandomAccessRangeTag, T>
|
|||
return n;
|
||||
}
|
||||
|
||||
octa::Size push_front_n(octa::Size n) {
|
||||
Size push_front_n(Size n) {
|
||||
p_beg -= n; return true;
|
||||
}
|
||||
|
||||
|
@ -837,7 +837,7 @@ struct PointerRange: InputRange<PointerRange<T>, FiniteRandomAccessRangeTag, T>
|
|||
return p_beg == range.p_beg;
|
||||
}
|
||||
|
||||
octa::Ptrdiff distance_front(const PointerRange &range) const {
|
||||
Ptrdiff distance_front(const PointerRange &range) const {
|
||||
return range.p_beg - p_beg;
|
||||
}
|
||||
|
||||
|
@ -851,8 +851,8 @@ struct PointerRange: InputRange<PointerRange<T>, FiniteRandomAccessRangeTag, T>
|
|||
++p_end; return true;
|
||||
}
|
||||
|
||||
octa::Size pop_back_n(octa::Size n) {
|
||||
octa::Size olen = p_end - p_beg;
|
||||
Size pop_back_n(Size n) {
|
||||
Size olen = p_end - p_beg;
|
||||
p_end -= n;
|
||||
if (p_end < p_beg) {
|
||||
p_end = p_beg;
|
||||
|
@ -861,7 +861,7 @@ struct PointerRange: InputRange<PointerRange<T>, FiniteRandomAccessRangeTag, T>
|
|||
return n;
|
||||
}
|
||||
|
||||
octa::Size push_back_n(octa::Size n) {
|
||||
Size push_back_n(Size n) {
|
||||
p_end += n; return true;
|
||||
}
|
||||
|
||||
|
@ -871,18 +871,18 @@ struct PointerRange: InputRange<PointerRange<T>, FiniteRandomAccessRangeTag, T>
|
|||
return p_end == range.p_end;
|
||||
}
|
||||
|
||||
octa::Ptrdiff distance_back(const PointerRange &range) const {
|
||||
Ptrdiff distance_back(const PointerRange &range) const {
|
||||
return range.p_end - p_end;
|
||||
}
|
||||
|
||||
/* satisfy FiniteRandomAccessRange */
|
||||
octa::Size size() const { return p_end - p_beg; }
|
||||
Size size() const { return p_end - p_beg; }
|
||||
|
||||
PointerRange slice(octa::Size start, octa::Size end) const {
|
||||
PointerRange slice(Size start, Size end) const {
|
||||
return PointerRange(p_beg + start, p_beg + end);
|
||||
}
|
||||
|
||||
T &operator[](octa::Size i) const { return p_beg[i]; }
|
||||
T &operator[](Size i) const { return p_beg[i]; }
|
||||
|
||||
/* satisfy OutputRange */
|
||||
bool put(const T &v) {
|
||||
|
@ -892,33 +892,33 @@ struct PointerRange: InputRange<PointerRange<T>, FiniteRandomAccessRangeTag, T>
|
|||
}
|
||||
bool put(T &&v) {
|
||||
if (empty()) return false;
|
||||
*(p_beg++) = octa::move(v);
|
||||
*(p_beg++) = move(v);
|
||||
return true;
|
||||
}
|
||||
|
||||
octa::Size put_n(const T *p, octa::Size n) {
|
||||
octa::Size ret = size();
|
||||
Size put_n(const T *p, Size n) {
|
||||
Size ret = size();
|
||||
if (n < ret) ret = n;
|
||||
if (octa::IsPod<T>()) {
|
||||
if (IsPod<T>()) {
|
||||
memcpy(p_beg, p, ret * sizeof(T));
|
||||
p_beg += ret;
|
||||
return ret;
|
||||
}
|
||||
for (octa::Size i = ret; i; --i)
|
||||
for (Size i = ret; i; --i)
|
||||
*p_beg++ = *p++;
|
||||
return ret;
|
||||
}
|
||||
|
||||
template<typename R,
|
||||
typename = octa::EnableIf<octa::IsOutputRange<R>::value
|
||||
>> octa::Size copy(R &&orange, octa::Size n = -1) {
|
||||
octa::Size c = size();
|
||||
typename = EnableIf<IsOutputRange<R>::value
|
||||
>> Size copy(R &&orange, Size n = -1) {
|
||||
Size c = size();
|
||||
if (n < c) c = n;
|
||||
return orange.put_n(p_beg, c);
|
||||
}
|
||||
|
||||
octa::Size copy(octa::RemoveCv<T> *p, octa::Size n = -1) {
|
||||
octa::Size c = size();
|
||||
Size copy(RemoveCv<T> *p, Size n = -1) {
|
||||
Size c = size();
|
||||
if (n < c) c = n;
|
||||
return copy(PointerRange(p, c), c);
|
||||
}
|
||||
|
@ -927,12 +927,12 @@ private:
|
|||
T *p_beg, *p_end;
|
||||
};
|
||||
|
||||
template<typename T, octa::Size N>
|
||||
template<typename T, Size N>
|
||||
PointerRange<T> iter(T (&array)[N]) {
|
||||
return PointerRange<T>(array, N);
|
||||
}
|
||||
|
||||
template<typename T, octa::Size N>
|
||||
template<typename T, Size N>
|
||||
PointerRange<const T> iter(const T (&array)[N]) {
|
||||
return PointerRange<const T>(array, N);
|
||||
}
|
||||
|
@ -965,7 +965,7 @@ public:
|
|||
p_range(it.p_range), p_index(it.p_index) {}
|
||||
|
||||
EnumeratedRange(EnumeratedRange &&it):
|
||||
p_range(octa::move(it.p_range)), p_index(it.p_index) {}
|
||||
p_range(move(it.p_range)), p_index(it.p_index) {}
|
||||
|
||||
EnumeratedRange &operator=(const EnumeratedRange &v) {
|
||||
p_range = v.p_range;
|
||||
|
@ -973,7 +973,7 @@ public:
|
|||
return *this;
|
||||
}
|
||||
EnumeratedRange &operator=(EnumeratedRange &&v) {
|
||||
p_range = octa::move(v.p_range);
|
||||
p_range = move(v.p_range);
|
||||
p_index = v.p_index;
|
||||
return *this;
|
||||
}
|
||||
|
@ -983,7 +983,7 @@ public:
|
|||
return *this;
|
||||
}
|
||||
EnumeratedRange &operator=(T &&v) {
|
||||
p_range = octa::move(v);
|
||||
p_range = move(v);
|
||||
p_index = 0;
|
||||
return *this;
|
||||
}
|
||||
|
@ -1032,14 +1032,14 @@ public:
|
|||
p_remaining(rem) {}
|
||||
TakeRange(const TakeRange &it): p_range(it.p_range),
|
||||
p_remaining(it.p_remaining) {}
|
||||
TakeRange(TakeRange &&it): p_range(octa::move(it.p_range)),
|
||||
TakeRange(TakeRange &&it): p_range(move(it.p_range)),
|
||||
p_remaining(it.p_remaining) {}
|
||||
|
||||
TakeRange &operator=(const TakeRange &v) {
|
||||
p_range = v.p_range; p_remaining = v.p_remaining; return *this;
|
||||
}
|
||||
TakeRange &operator=(TakeRange &&v) {
|
||||
p_range = octa::move(v.p_range);
|
||||
p_range = move(v.p_range);
|
||||
p_remaining = v.p_remaining;
|
||||
return *this;
|
||||
}
|
||||
|
@ -1086,14 +1086,14 @@ public:
|
|||
p_chunksize(chs) {}
|
||||
ChunksRange(const ChunksRange &it): p_range(it.p_range),
|
||||
p_chunksize(it.p_chunksize) {}
|
||||
ChunksRange(ChunksRange &&it): p_range(octa::move(it.p_range)),
|
||||
ChunksRange(ChunksRange &&it): p_range(move(it.p_range)),
|
||||
p_chunksize(it.p_chunksize) {}
|
||||
|
||||
ChunksRange &operator=(const ChunksRange &v) {
|
||||
p_range = v.p_range; p_chunksize = v.p_chunksize; return *this;
|
||||
}
|
||||
ChunksRange &operator=(ChunksRange &&v) {
|
||||
p_range = octa::move(v.p_range);
|
||||
p_range = move(v.p_range);
|
||||
p_chunksize = v.p_chunksize;
|
||||
return *this;
|
||||
}
|
||||
|
@ -1122,9 +1122,9 @@ struct AppenderRange: OutputRange<AppenderRange<T>, typename T::Value,
|
|||
typename T::Reference, typename T::Size, typename T::Difference> {
|
||||
AppenderRange(): p_data() {}
|
||||
AppenderRange(const T &v): p_data(v) {}
|
||||
AppenderRange(T &&v): p_data(octa::move(v)) {}
|
||||
AppenderRange(T &&v): p_data(move(v)) {}
|
||||
AppenderRange(const AppenderRange &v): p_data(v.p_data) {}
|
||||
AppenderRange(AppenderRange &&v): p_data(octa::move(v.p_data)) {}
|
||||
AppenderRange(AppenderRange &&v): p_data(move(v.p_data)) {}
|
||||
|
||||
AppenderRange &operator=(const AppenderRange &v) {
|
||||
p_data = v.p_data;
|
||||
|
@ -1132,7 +1132,7 @@ struct AppenderRange: OutputRange<AppenderRange<T>, typename T::Value,
|
|||
}
|
||||
|
||||
AppenderRange &operator=(AppenderRange &&v) {
|
||||
p_data = octa::move(v.p_data);
|
||||
p_data = move(v.p_data);
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
@ -1142,7 +1142,7 @@ struct AppenderRange: OutputRange<AppenderRange<T>, typename T::Value,
|
|||
}
|
||||
|
||||
AppenderRange &operator=(T &&v) {
|
||||
p_data = octa::move(v);
|
||||
p_data = move(v);
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
@ -1160,7 +1160,7 @@ struct AppenderRange: OutputRange<AppenderRange<T>, typename T::Value,
|
|||
}
|
||||
|
||||
bool put(typename T::Value &&v) {
|
||||
p_data.push(octa::move(v));
|
||||
p_data.push(move(v));
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -1176,11 +1176,11 @@ AppenderRange<T> appender() {
|
|||
|
||||
template<typename T>
|
||||
AppenderRange<T> appender(T &&v) {
|
||||
return AppenderRange<T>(octa::forward<T>(v));
|
||||
return AppenderRange<T>(forward<T>(v));
|
||||
}
|
||||
|
||||
// range of
|
||||
template<typename T> using RangeOf = decltype(octa::iter(octa::declval<T>()));
|
||||
template<typename T> using RangeOf = decltype(iter(declval<T>()));
|
||||
|
||||
} /* namespace octa */
|
||||
|
||||
|
|
86
octa/set.hh
86
octa/set.hh
|
@ -30,56 +30,56 @@ namespace detail {
|
|||
};
|
||||
|
||||
template<typename T, typename H, typename C, typename A, bool IsMultihash>
|
||||
struct SetImpl: octa::detail::Hashtable<
|
||||
octa::detail::SetBase<T, A>, T, T, T, H, C, A, IsMultihash
|
||||
struct SetImpl: detail::Hashtable<
|
||||
detail::SetBase<T, A>, T, T, T, H, C, A, IsMultihash
|
||||
> {
|
||||
private:
|
||||
using Base = octa::detail::Hashtable<
|
||||
octa::detail::SetBase<T, A>, T, T, T, H, C, A, IsMultihash
|
||||
using Base = detail::Hashtable<
|
||||
detail::SetBase<T, A>, T, T, T, H, C, A, IsMultihash
|
||||
>;
|
||||
|
||||
public:
|
||||
using Key = T;
|
||||
using Size = octa::Size;
|
||||
using Difference = octa::Ptrdiff;
|
||||
using Size = Size;
|
||||
using Difference = Ptrdiff;
|
||||
using Hasher = H;
|
||||
using KeyEqual = C;
|
||||
using Value = T;
|
||||
using Reference = Value &;
|
||||
using Pointer = octa::AllocatorPointer<A>;
|
||||
using ConstPointer = octa::AllocatorConstPointer<A>;
|
||||
using Range = octa::HashRange<T>;
|
||||
using ConstRange = octa::HashRange<const T>;
|
||||
using LocalRange = octa::BucketRange<T>;
|
||||
using ConstLocalRange = octa::BucketRange<const T>;
|
||||
using Pointer = AllocatorPointer<A>;
|
||||
using ConstPointer = AllocatorConstPointer<A>;
|
||||
using Range = HashRange<T>;
|
||||
using ConstRange = HashRange<const T>;
|
||||
using LocalRange = BucketRange<T>;
|
||||
using ConstLocalRange = BucketRange<const T>;
|
||||
using Allocator = A;
|
||||
|
||||
explicit SetImpl(octa::Size size, const H &hf = H(),
|
||||
explicit SetImpl(Size size, const H &hf = H(),
|
||||
const C &eqf = C(), const A &alloc = A()
|
||||
): Base(size, hf, eqf, alloc) {}
|
||||
|
||||
SetImpl(): SetImpl(0) {}
|
||||
explicit SetImpl(const A &alloc): SetImpl(0, H(), C(), alloc) {}
|
||||
|
||||
SetImpl(octa::Size size, const A &alloc):
|
||||
SetImpl(Size size, const A &alloc):
|
||||
SetImpl(size, H(), C(), alloc) {}
|
||||
SetImpl(octa::Size size, const H &hf, const A &alloc):
|
||||
SetImpl(Size size, const H &hf, const A &alloc):
|
||||
SetImpl(size, hf, C(), alloc) {}
|
||||
|
||||
SetImpl(const SetImpl &m): Base(m,
|
||||
octa::allocator_container_copy(m.get_alloc())) {}
|
||||
allocator_container_copy(m.get_alloc())) {}
|
||||
|
||||
SetImpl(const SetImpl &m, const A &alloc): Base(m, alloc) {}
|
||||
|
||||
SetImpl(SetImpl &&m): Base(octa::move(m)) {}
|
||||
SetImpl(SetImpl &&m, const A &alloc): Base(octa::move(m), alloc) {}
|
||||
SetImpl(SetImpl &&m): Base(move(m)) {}
|
||||
SetImpl(SetImpl &&m, const A &alloc): Base(move(m), alloc) {}
|
||||
|
||||
template<typename R, typename = octa::EnableIf<
|
||||
octa::IsInputRange<R>::value &&
|
||||
octa::IsConvertible<RangeReference<R>, Value>::value
|
||||
>> SetImpl(R range, octa::Size size = 0, const H &hf = H(),
|
||||
template<typename R, typename = EnableIf<
|
||||
IsInputRange<R>::value &&
|
||||
IsConvertible<RangeReference<R>, Value>::value
|
||||
>> SetImpl(R range, Size size = 0, const H &hf = H(),
|
||||
const C &eqf = C(), const A &alloc = A()
|
||||
): Base(size ? size : octa::detail::estimate_hrsize(range),
|
||||
): Base(size ? size : detail::estimate_hrsize(range),
|
||||
hf, eqf, alloc) {
|
||||
for (; !range.empty(); range.pop_front())
|
||||
Base::emplace(range.front());
|
||||
|
@ -87,23 +87,23 @@ namespace detail {
|
|||
}
|
||||
|
||||
template<typename R>
|
||||
SetImpl(R range, octa::Size size, const A &alloc)
|
||||
SetImpl(R range, Size size, const A &alloc)
|
||||
: SetImpl(range, size, H(), C(), alloc) {}
|
||||
|
||||
template<typename R>
|
||||
SetImpl(R range, octa::Size size, const H &hf, const A &alloc)
|
||||
SetImpl(R range, Size size, const H &hf, const A &alloc)
|
||||
: SetImpl(range, size, hf, C(), alloc) {}
|
||||
|
||||
SetImpl(octa::InitializerList<Value> init, octa::Size size = 0,
|
||||
SetImpl(InitializerList<Value> init, Size size = 0,
|
||||
const H &hf = H(), const C &eqf = C(), const A &alloc = A()
|
||||
): SetImpl(octa::iter(init), size, hf, eqf, alloc) {}
|
||||
): SetImpl(iter(init), size, hf, eqf, alloc) {}
|
||||
|
||||
SetImpl(octa::InitializerList<Value> init, octa::Size size, const A &alloc)
|
||||
: SetImpl(octa::iter(init), size, H(), C(), alloc) {}
|
||||
SetImpl(InitializerList<Value> init, Size size, const A &alloc)
|
||||
: SetImpl(iter(init), size, H(), C(), alloc) {}
|
||||
|
||||
SetImpl(octa::InitializerList<Value> init, octa::Size size, const H &hf,
|
||||
SetImpl(InitializerList<Value> init, Size size, const H &hf,
|
||||
const A &alloc
|
||||
): SetImpl(octa::iter(init), size, hf, C(), alloc) {}
|
||||
): SetImpl(iter(init), size, hf, C(), alloc) {}
|
||||
|
||||
SetImpl &operator=(const SetImpl &m) {
|
||||
Base::operator=(m);
|
||||
|
@ -111,13 +111,13 @@ namespace detail {
|
|||
}
|
||||
|
||||
SetImpl &operator=(SetImpl &&m) {
|
||||
Base::operator=(octa::move(m));
|
||||
Base::operator=(move(m));
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename R, typename = octa::EnableIf<
|
||||
octa::IsInputRange<R>::value &&
|
||||
octa::IsConvertible<RangeReference<R>, Value>::value
|
||||
template<typename R, typename = EnableIf<
|
||||
IsInputRange<R>::value &&
|
||||
IsConvertible<RangeReference<R>, Value>::value
|
||||
>> SetImpl &operator=(R range) {
|
||||
Base::assign_range(range);
|
||||
return *this;
|
||||
|
@ -136,17 +136,17 @@ namespace detail {
|
|||
|
||||
template<
|
||||
typename T,
|
||||
typename H = octa::ToHash<T>,
|
||||
typename C = octa::Equal<T>,
|
||||
typename A = octa::Allocator<T>
|
||||
> using Set = octa::detail::SetImpl<T, H, C, A, false>;
|
||||
typename H = ToHash<T>,
|
||||
typename C = Equal<T>,
|
||||
typename A = Allocator<T>
|
||||
> using Set = detail::SetImpl<T, H, C, A, false>;
|
||||
|
||||
template<
|
||||
typename T,
|
||||
typename H = octa::ToHash<T>,
|
||||
typename C = octa::Equal<T>,
|
||||
typename A = octa::Allocator<T>
|
||||
> using Multiset = octa::detail::SetImpl<T, H, C, A, true>;
|
||||
typename H = ToHash<T>,
|
||||
typename C = Equal<T>,
|
||||
typename A = Allocator<T>
|
||||
> using Multiset = detail::SetImpl<T, H, C, A, true>;
|
||||
|
||||
} /* namespace octa */
|
||||
|
||||
|
|
|
@ -30,16 +30,16 @@ enum class StreamSeek {
|
|||
set = SEEK_SET
|
||||
};
|
||||
|
||||
template<typename T = char, bool = octa::IsPod<T>::value>
|
||||
template<typename T = char, bool = IsPod<T>::value>
|
||||
struct StreamRange;
|
||||
|
||||
namespace detail {
|
||||
template<octa::Size N>
|
||||
struct FormatOutRange: octa::OutputRange<FormatOutRange<N>, char> {
|
||||
template<Size N>
|
||||
struct FormatOutRange: OutputRange<FormatOutRange<N>, char> {
|
||||
FormatOutRange(char *buf): buf(buf), idx(0) {}
|
||||
FormatOutRange(const FormatOutRange &r): buf(r.buf), idx(r.idx) {}
|
||||
char *buf;
|
||||
octa::Size idx;
|
||||
Size idx;
|
||||
bool put(char v) {
|
||||
if (idx < N) {
|
||||
buf[idx++] = v;
|
||||
|
@ -74,30 +74,30 @@ struct Stream {
|
|||
|
||||
virtual bool flush() { return true; }
|
||||
|
||||
virtual octa::Size read_bytes(void *, octa::Size) { return 0; }
|
||||
virtual octa::Size write_bytes(const void *, octa::Size) { return 0; }
|
||||
virtual Size read_bytes(void *, Size) { return 0; }
|
||||
virtual Size write_bytes(const void *, Size) { return 0; }
|
||||
|
||||
virtual int getchar() {
|
||||
octa::byte c;
|
||||
byte c;
|
||||
return (read_bytes(&c, 1) == 1) ? c : -1;
|
||||
}
|
||||
|
||||
virtual bool putchar(int c) {
|
||||
octa::byte wc = octa::byte(c);
|
||||
byte wc = byte(c);
|
||||
return write_bytes(&wc, 1) == 1;
|
||||
}
|
||||
|
||||
virtual bool write(const char *s) {
|
||||
octa::Size len = strlen(s);
|
||||
Size len = strlen(s);
|
||||
return write_bytes(s, len) == len;
|
||||
}
|
||||
|
||||
virtual bool write(const octa::String &s) {
|
||||
virtual bool write(const String &s) {
|
||||
return write_bytes(s.data(), s.size()) == s.size();
|
||||
}
|
||||
|
||||
template<typename T> bool write(const T &v) {
|
||||
return write(octa::to_string(v));
|
||||
return write(to_string(v));
|
||||
}
|
||||
|
||||
template<typename T, typename ...A>
|
||||
|
@ -105,7 +105,7 @@ struct Stream {
|
|||
return write(v) && write(args...);
|
||||
}
|
||||
|
||||
virtual bool writeln(const octa::String &s) {
|
||||
virtual bool writeln(const String &s) {
|
||||
return write(s) && putchar('\n');
|
||||
}
|
||||
|
||||
|
@ -125,19 +125,19 @@ struct Stream {
|
|||
template<typename ...A>
|
||||
bool writef(const char *fmt, const A &...args) {
|
||||
char buf[512];
|
||||
octa::Size need = octa::format(octa::detail::FormatOutRange<
|
||||
sizeof(buf)>(buf), fmt, args...);
|
||||
Size need = format(detail::FormatOutRange<sizeof(buf)>(buf),
|
||||
fmt, args...);
|
||||
if (need < sizeof(buf))
|
||||
return write_bytes(buf, need) == need;
|
||||
octa::String s;
|
||||
String s;
|
||||
s.reserve(need);
|
||||
s[need] = '\0';
|
||||
octa::format(s.iter(), fmt, args...);
|
||||
format(s.iter(), fmt, args...);
|
||||
return write_bytes(s.data(), need) == need;
|
||||
}
|
||||
|
||||
template<typename ...A>
|
||||
bool writef(const octa::String &fmt, const A &...args) {
|
||||
bool writef(const String &fmt, const A &...args) {
|
||||
return writef(fmt.data(), args...);
|
||||
}
|
||||
|
||||
|
@ -147,14 +147,14 @@ struct Stream {
|
|||
}
|
||||
|
||||
template<typename ...A>
|
||||
bool writefln(const octa::String &fmt, const A &...args) {
|
||||
bool writefln(const String &fmt, const A &...args) {
|
||||
return writefln(fmt.data(), args...);
|
||||
}
|
||||
|
||||
template<typename T = char>
|
||||
StreamRange<T> iter();
|
||||
|
||||
template<typename T> octa::Size put(const T *v, octa::Size count) {
|
||||
template<typename T> Size put(const T *v, Size count) {
|
||||
return write_bytes(v, count * sizeof(T)) / sizeof(T);
|
||||
}
|
||||
|
||||
|
@ -162,7 +162,7 @@ struct Stream {
|
|||
return write_bytes(&v, sizeof(T)) == sizeof(T);
|
||||
}
|
||||
|
||||
template<typename T> octa::Size get(T *v, octa::Size count) {
|
||||
template<typename T> Size get(T *v, Size count) {
|
||||
return read_bytes(v, count * sizeof(T)) / sizeof(T);
|
||||
}
|
||||
|
||||
|
@ -178,7 +178,7 @@ struct Stream {
|
|||
|
||||
template<typename T>
|
||||
struct StreamRange<T, true>: InputRange<
|
||||
StreamRange<T>, octa::InputRangeTag, T, T, octa::Size, StreamOffset
|
||||
StreamRange<T>, InputRangeTag, T, T, Size, StreamOffset
|
||||
> {
|
||||
StreamRange() = delete;
|
||||
StreamRange(Stream &s): p_stream(&s), p_size(s.size()) {}
|
||||
|
@ -205,17 +205,17 @@ struct StreamRange<T, true>: InputRange<
|
|||
}
|
||||
|
||||
bool put(T val) {
|
||||
octa::Size v = p_stream->write_bytes(&val, sizeof(T));
|
||||
Size v = p_stream->write_bytes(&val, sizeof(T));
|
||||
p_size += v;
|
||||
return (v == sizeof(T));
|
||||
}
|
||||
|
||||
octa::Size put_n(const T *p, octa::Size n) {
|
||||
Size put_n(const T *p, Size n) {
|
||||
return p_stream->put(p, n);
|
||||
}
|
||||
|
||||
octa::Size copy(octa::RemoveCv<T> *p, octa::Size n = -1) {
|
||||
if (n == octa::Size(-1)) {
|
||||
Size copy(RemoveCv<T> *p, Size n = -1) {
|
||||
if (n == Size(-1)) {
|
||||
n = p_stream->size() / sizeof(T);
|
||||
}
|
||||
return p_stream->get(p, n);
|
||||
|
|
138
octa/string.hh
138
octa/string.hh
|
@ -14,9 +14,9 @@
|
|||
#include "octa/vector.hh"
|
||||
|
||||
namespace octa {
|
||||
static constexpr octa::Size npos = -1;
|
||||
static constexpr Size npos = -1;
|
||||
|
||||
template<typename T, typename A = octa::Allocator<T>> class StringBase;
|
||||
template<typename T, typename A = Allocator<T>> class StringBase;
|
||||
|
||||
template<typename T>
|
||||
struct StringRangeBase: InputRange<
|
||||
|
@ -24,7 +24,7 @@ struct StringRangeBase: InputRange<
|
|||
> {
|
||||
StringRangeBase() = delete;
|
||||
StringRangeBase(T *beg, T *end): p_beg(beg), p_end(end) {}
|
||||
StringRangeBase(T *beg, octa::Size n): p_beg(beg), p_end(beg + n) {}
|
||||
StringRangeBase(T *beg, 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)) {}
|
||||
|
||||
|
@ -32,8 +32,8 @@ struct StringRangeBase: InputRange<
|
|||
StringRangeBase(const StringBase<T, A> &s): p_beg(s.data()),
|
||||
p_end(s.data() + s.size()) {}
|
||||
|
||||
template<typename U, typename = octa::EnableIf<
|
||||
octa::IsConvertible<U *, T *>::value
|
||||
template<typename U, typename = EnableIf<
|
||||
IsConvertible<U *, T *>::value
|
||||
>> StringRangeBase(const StringRangeBase<U> &v):
|
||||
p_beg(&v[0]), p_end(&v[v.size()]) {}
|
||||
|
||||
|
@ -59,8 +59,8 @@ struct StringRangeBase: InputRange<
|
|||
}
|
||||
bool push_front() { --p_beg; return true; }
|
||||
|
||||
octa::Size pop_front_n(octa::Size n) {
|
||||
octa::Size olen = p_end - p_beg;
|
||||
Size pop_front_n(Size n) {
|
||||
Size olen = p_end - p_beg;
|
||||
p_beg += n;
|
||||
if (p_beg > p_end) {
|
||||
p_beg = p_end;
|
||||
|
@ -69,7 +69,7 @@ struct StringRangeBase: InputRange<
|
|||
return n;
|
||||
}
|
||||
|
||||
octa::Size push_front_n(octa::Size n) { p_beg -= n; return true; }
|
||||
Size push_front_n(Size n) { p_beg -= n; return true; }
|
||||
|
||||
T &front() const { return *p_beg; }
|
||||
|
||||
|
@ -77,7 +77,7 @@ struct StringRangeBase: InputRange<
|
|||
return p_beg == range.p_beg;
|
||||
}
|
||||
|
||||
octa::Ptrdiff distance_front(const StringRangeBase &range) const {
|
||||
Ptrdiff distance_front(const StringRangeBase &range) const {
|
||||
return range.p_beg - p_beg;
|
||||
}
|
||||
|
||||
|
@ -88,8 +88,8 @@ struct StringRangeBase: InputRange<
|
|||
}
|
||||
bool push_back() { ++p_end; return true; }
|
||||
|
||||
octa::Size pop_back_n(octa::Size n) {
|
||||
octa::Size olen = p_end - p_beg;
|
||||
Size pop_back_n(Size n) {
|
||||
Size olen = p_end - p_beg;
|
||||
p_end -= n;
|
||||
if (p_end < p_beg) {
|
||||
p_end = p_beg;
|
||||
|
@ -98,7 +98,7 @@ struct StringRangeBase: InputRange<
|
|||
return n;
|
||||
}
|
||||
|
||||
octa::Size push_back_n(octa::Size n) { p_end += n; return true; }
|
||||
Size push_back_n(Size n) { p_end += n; return true; }
|
||||
|
||||
T &back() const { return *(p_end - 1); }
|
||||
|
||||
|
@ -106,17 +106,17 @@ struct StringRangeBase: InputRange<
|
|||
return p_end == range.p_end;
|
||||
}
|
||||
|
||||
octa::Ptrdiff distance_back(const StringRangeBase &range) const {
|
||||
Ptrdiff distance_back(const StringRangeBase &range) const {
|
||||
return range.p_end - p_end;
|
||||
}
|
||||
|
||||
octa::Size size() const { return p_end - p_beg; }
|
||||
Size size() const { return p_end - p_beg; }
|
||||
|
||||
StringRangeBase slice(octa::Size start, octa::Size end) const {
|
||||
StringRangeBase slice(Size start, Size end) const {
|
||||
return StringRangeBase(p_beg + start, p_beg + end);
|
||||
}
|
||||
|
||||
T &operator[](octa::Size i) const { return p_beg[i]; }
|
||||
T &operator[](Size i) const { return p_beg[i]; }
|
||||
|
||||
bool put(T v) {
|
||||
if (empty()) return false;
|
||||
|
@ -128,7 +128,7 @@ struct StringRangeBase: InputRange<
|
|||
T *data() { return p_beg; }
|
||||
const T *data() const { return p_beg; }
|
||||
|
||||
octa::Size to_hash() const {
|
||||
Size to_hash() const {
|
||||
const T *d = data();
|
||||
Size h = 5381, len = size();
|
||||
for (Size i = 0; i < len; ++i)
|
||||
|
@ -142,22 +142,22 @@ private:
|
|||
|
||||
template<typename T, typename A>
|
||||
class StringBase {
|
||||
octa::Vector<T, A> p_buf;
|
||||
Vector<T, A> p_buf;
|
||||
|
||||
void terminate() {
|
||||
if (p_buf.empty() || (p_buf.back() != '\0')) p_buf.push('\0');
|
||||
}
|
||||
|
||||
public:
|
||||
using Size = octa::Size;
|
||||
using Difference = octa::Ptrdiff;
|
||||
using Size = Size;
|
||||
using Difference = Ptrdiff;
|
||||
using Value = T;
|
||||
using Reference = T &;
|
||||
using ConstReference = const T &;
|
||||
using Pointer = octa::AllocatorPointer<A>;
|
||||
using ConstPointer = octa::AllocatorConstPointer<A>;
|
||||
using Range = octa::StringRangeBase<T>;
|
||||
using ConstRange = octa::StringRangeBase<const T>;
|
||||
using Pointer = AllocatorPointer<A>;
|
||||
using ConstPointer = AllocatorConstPointer<A>;
|
||||
using Range = StringRangeBase<T>;
|
||||
using ConstRange = StringRangeBase<const T>;
|
||||
using Allocator = A;
|
||||
|
||||
StringBase(const A &a = A()): p_buf(1, '\0', a) {}
|
||||
|
@ -168,11 +168,11 @@ public:
|
|||
StringBase(const StringBase &s): p_buf(s.p_buf) {}
|
||||
StringBase(const StringBase &s, const A &a):
|
||||
p_buf(s.p_buf, a) {}
|
||||
StringBase(StringBase &&s): p_buf(octa::move(s.p_buf)) {}
|
||||
StringBase(StringBase &&s): p_buf(move(s.p_buf)) {}
|
||||
StringBase(StringBase &&s, const A &a):
|
||||
p_buf(octa::move(s.p_buf), a) {}
|
||||
p_buf(move(s.p_buf), a) {}
|
||||
|
||||
StringBase(const StringBase &s, octa::Size pos, octa::Size len = npos,
|
||||
StringBase(const StringBase &s, Size pos, Size len = npos,
|
||||
const A &a = A()):
|
||||
p_buf(s.p_buf.iter().slice(pos,
|
||||
(len == npos) ? s.p_buf.size() : (pos + len)), a) {
|
||||
|
@ -186,9 +186,9 @@ public:
|
|||
StringBase(const Value *v, Size n, const A &a = A()):
|
||||
p_buf(ConstRange(v, n), a) {}
|
||||
|
||||
template<typename R, typename = octa::EnableIf<
|
||||
octa::IsInputRange<R>::value &&
|
||||
octa::IsConvertible<RangeReference<R>, Value>::value
|
||||
template<typename R, typename = EnableIf<
|
||||
IsInputRange<R>::value &&
|
||||
IsConvertible<RangeReference<R>, Value>::value
|
||||
>> StringBase(R range, const A &a = A()): p_buf(range, a) {
|
||||
terminate();
|
||||
}
|
||||
|
@ -200,37 +200,37 @@ public:
|
|||
return *this;
|
||||
}
|
||||
StringBase &operator=(StringBase &&v) {
|
||||
p_buf.operator=(octa::move(v));
|
||||
p_buf.operator=(move(v));
|
||||
return *this;
|
||||
}
|
||||
StringBase &operator=(const Value *v) {
|
||||
p_buf = ConstRange(v, strlen(v) + 1);
|
||||
return *this;
|
||||
}
|
||||
template<typename R, typename = octa::EnableIf<
|
||||
octa::IsInputRange<R>::value &&
|
||||
octa::IsConvertible<RangeReference<R>, Value>::value
|
||||
template<typename R, typename = EnableIf<
|
||||
IsInputRange<R>::value &&
|
||||
IsConvertible<RangeReference<R>, Value>::value
|
||||
>> StringBase &operator=(const R &r) {
|
||||
p_buf = r;
|
||||
terminate();
|
||||
return *this;
|
||||
}
|
||||
|
||||
void resize(octa::Size n, T v = T()) {
|
||||
void resize(Size n, T v = T()) {
|
||||
p_buf.pop();
|
||||
p_buf.resize(n, v);
|
||||
terminate();
|
||||
}
|
||||
|
||||
void reserve(octa::Size n) {
|
||||
void reserve(Size n) {
|
||||
p_buf.reserve(n + 1);
|
||||
}
|
||||
|
||||
T &operator[](octa::Size i) { return p_buf[i]; }
|
||||
const T &operator[](octa::Size i) const { return p_buf[i]; }
|
||||
T &operator[](Size i) { return p_buf[i]; }
|
||||
const T &operator[](Size i) const { return p_buf[i]; }
|
||||
|
||||
T &at(octa::Size i) { return p_buf[i]; }
|
||||
const T &at(octa::Size i) const { return p_buf[i]; }
|
||||
T &at(Size i) { return p_buf[i]; }
|
||||
const T &at(Size i) const { return p_buf[i]; }
|
||||
|
||||
T &front() { return p_buf[0]; }
|
||||
const T &front() const { return p_buf[0]; };
|
||||
|
@ -241,15 +241,15 @@ public:
|
|||
Value *data() { return p_buf.data(); }
|
||||
const Value *data() const { return p_buf.data(); }
|
||||
|
||||
octa::Size size() const {
|
||||
Size size() const {
|
||||
return p_buf.size() - 1;
|
||||
}
|
||||
|
||||
octa::Size capacity() const {
|
||||
Size capacity() const {
|
||||
return p_buf.capacity() - 1;
|
||||
}
|
||||
|
||||
octa::Size length() const {
|
||||
Size length() const {
|
||||
/* TODO: unicode */
|
||||
return size();
|
||||
}
|
||||
|
@ -267,7 +267,7 @@ public:
|
|||
return *this;
|
||||
}
|
||||
|
||||
StringBase &append(const StringBase &s, octa::Size idx, octa::Size len) {
|
||||
StringBase &append(const StringBase &s, Size idx, Size len) {
|
||||
p_buf.pop();
|
||||
p_buf.insert_range(p_buf.size(), Range(&s[idx],
|
||||
(len == npos) ? (s.size() - idx) : len));
|
||||
|
@ -282,9 +282,9 @@ public:
|
|||
return *this;
|
||||
}
|
||||
|
||||
StringBase &append(octa::Size n, T c) {
|
||||
StringBase &append(Size n, T c) {
|
||||
p_buf.pop();
|
||||
for (octa::Size i = 0; i < n; ++i) p_buf.push(c);
|
||||
for (Size i = 0; i < n; ++i) p_buf.push(c);
|
||||
p_buf.push('\0');
|
||||
return *this;
|
||||
}
|
||||
|
@ -441,23 +441,21 @@ template<typename T> struct ToString {
|
|||
|
||||
template<typename U>
|
||||
static String to_str(const U &v,
|
||||
octa::EnableIf<octa::detail::ToStringTest<U>::value, bool> = true
|
||||
EnableIf<detail::ToStringTest<U>::value, bool> = true
|
||||
) {
|
||||
return v.to_string();
|
||||
}
|
||||
|
||||
template<typename U>
|
||||
static String to_str(const U &v,
|
||||
octa::EnableIf<!octa::detail::ToStringTest<U>::value &&
|
||||
!octa::IsScalar<U>::value, bool> = true
|
||||
EnableIf<!detail::ToStringTest<U>::value &&
|
||||
!IsScalar<U>::value, bool> = true
|
||||
) {
|
||||
String ret("{");
|
||||
ret += concat(octa::iter(v), ", ", ToString<
|
||||
octa::RemoveCv<
|
||||
octa::RemoveReference<
|
||||
octa::RangeReference<decltype(octa::iter(v))>
|
||||
>
|
||||
>
|
||||
RemoveCv<RemoveReference<
|
||||
RangeReference<decltype(octa::iter(v))>
|
||||
>>
|
||||
>());
|
||||
ret += "}";
|
||||
return ret;
|
||||
|
@ -465,8 +463,8 @@ template<typename T> struct ToString {
|
|||
|
||||
template<typename U>
|
||||
static String to_str(const U &v,
|
||||
octa::EnableIf<!octa::detail::ToStringTest<U>::value &&
|
||||
octa::IsScalar<U>::value, bool> = true
|
||||
EnableIf<!detail::ToStringTest<U>::value &&
|
||||
IsScalar<U>::value, bool> = true
|
||||
) {
|
||||
return ToString<U>()(v);
|
||||
}
|
||||
|
@ -478,7 +476,7 @@ template<typename T> struct ToString {
|
|||
|
||||
namespace detail {
|
||||
template<typename T>
|
||||
void str_printf(octa::Vector<char> *s, const char *fmt, T v) {
|
||||
void str_printf(Vector<char> *s, const char *fmt, T v) {
|
||||
char buf[256];
|
||||
int n = snprintf(buf, sizeof(buf), fmt, v);
|
||||
s->clear();
|
||||
|
@ -491,7 +489,7 @@ namespace detail {
|
|||
n = 0;
|
||||
*(s->data()) = '\0';
|
||||
}
|
||||
*((octa::Size *)s) = n + 1;
|
||||
*((Size *)s) = n + 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -519,24 +517,24 @@ template<> struct ToString<T> { \
|
|||
using Result = String; \
|
||||
String operator()(T v) { \
|
||||
String ret; \
|
||||
octa::detail::str_printf((octa::Vector<char> *)&ret, fmt, v); \
|
||||
detail::str_printf((Vector<char> *)&ret, fmt, v); \
|
||||
return ret; \
|
||||
} \
|
||||
};
|
||||
|
||||
OCTA_TOSTR_NUM(octa::sbyte, "%d")
|
||||
OCTA_TOSTR_NUM(sbyte, "%d")
|
||||
OCTA_TOSTR_NUM(int, "%d")
|
||||
OCTA_TOSTR_NUM(int &, "%d")
|
||||
OCTA_TOSTR_NUM(long, "%ld")
|
||||
OCTA_TOSTR_NUM(float, "%f")
|
||||
OCTA_TOSTR_NUM(double, "%f")
|
||||
|
||||
OCTA_TOSTR_NUM(octa::byte, "%u")
|
||||
OCTA_TOSTR_NUM(octa::uint, "%u")
|
||||
OCTA_TOSTR_NUM(octa::ulong, "%lu")
|
||||
OCTA_TOSTR_NUM(octa::llong, "%lld")
|
||||
OCTA_TOSTR_NUM(octa::ullong, "%llu")
|
||||
OCTA_TOSTR_NUM(octa::ldouble, "%Lf")
|
||||
OCTA_TOSTR_NUM(byte, "%u")
|
||||
OCTA_TOSTR_NUM(uint, "%u")
|
||||
OCTA_TOSTR_NUM(ulong, "%lu")
|
||||
OCTA_TOSTR_NUM(llong, "%lld")
|
||||
OCTA_TOSTR_NUM(ullong, "%llu")
|
||||
OCTA_TOSTR_NUM(ldouble, "%Lf")
|
||||
|
||||
#undef OCTA_TOSTR_NUM
|
||||
|
||||
|
@ -545,7 +543,7 @@ template<typename T> struct ToString<T *> {
|
|||
using Result = String;
|
||||
String operator()(Argument v) {
|
||||
String ret;
|
||||
octa::detail::str_printf((octa::Vector<char> *)&ret, "%p", v);
|
||||
detail::str_printf((Vector<char> *)&ret, "%p", v);
|
||||
return ret;
|
||||
}
|
||||
};
|
||||
|
@ -566,8 +564,8 @@ template<> struct ToString<StringRange> {
|
|||
}
|
||||
};
|
||||
|
||||
template<typename T, typename U> struct ToString<octa::Pair<T, U>> {
|
||||
using Argument = octa::Pair<T, U>;
|
||||
template<typename T, typename U> struct ToString<Pair<T, U>> {
|
||||
using Argument = Pair<T, U>;
|
||||
using Result = String;
|
||||
String operator()(const Argument &v) {
|
||||
String ret("{");
|
||||
|
@ -579,7 +577,7 @@ template<typename T, typename U> struct ToString<octa::Pair<T, U>> {
|
|||
}
|
||||
};
|
||||
|
||||
template<typename T, typename = decltype(ToString<T>()(octa::declval<T>()))>
|
||||
template<typename T, typename = decltype(ToString<T>()(declval<T>()))>
|
||||
String to_string(const T &v) {
|
||||
return ToString<T>()(v);
|
||||
}
|
||||
|
|
|
@ -28,25 +28,25 @@ template<typename> struct IsReference;
|
|||
template<typename> struct IsTriviallyDefaultConstructible;
|
||||
|
||||
template<typename T>
|
||||
using RemoveCv = typename octa::detail::RemoveCvBase<T>::Type;
|
||||
using RemoveCv = typename detail::RemoveCvBase<T>::Type;
|
||||
|
||||
template<typename T>
|
||||
using AddLvalueReference = typename octa::detail::AddLr<T>::Type;
|
||||
using AddLvalueReference = typename detail::AddLr<T>::Type;
|
||||
|
||||
template<typename T>
|
||||
using AddRvalueReference = typename octa::detail::AddRr<T>::Type;
|
||||
using AddRvalueReference = typename detail::AddRr<T>::Type;
|
||||
|
||||
template<typename T>
|
||||
using AddConst = typename octa::detail::AddConstBase<T>::Type;
|
||||
using AddConst = typename detail::AddConstBase<T>::Type;
|
||||
|
||||
template<typename T>
|
||||
using RemoveReference = typename octa::detail::RemoveReferenceBase<T>::Type;
|
||||
using RemoveReference = typename detail::RemoveReferenceBase<T>::Type;
|
||||
|
||||
template<typename T>
|
||||
using RemoveAllExtents = typename octa::detail::RemoveAllExtentsBase<T>::Type;
|
||||
using RemoveAllExtents = typename detail::RemoveAllExtentsBase<T>::Type;
|
||||
|
||||
namespace detail {
|
||||
template<typename T> octa::AddRvalueReference<T> declval_in();
|
||||
template<typename T> AddRvalueReference<T> declval_in();
|
||||
}
|
||||
|
||||
/* integral constant */
|
||||
|
@ -75,17 +75,17 @@ namespace detail {
|
|||
}
|
||||
|
||||
template<typename T>
|
||||
struct IsVoid: octa::detail::IsVoidBase<RemoveCv<T>> {};
|
||||
struct IsVoid: detail::IsVoidBase<RemoveCv<T>> {};
|
||||
|
||||
/* is null pointer */
|
||||
|
||||
namespace detail {
|
||||
template<typename> struct IsNullPointerBase : False {};
|
||||
template< > struct IsNullPointerBase<octa::Nullptr>: True {};
|
||||
template<typename> struct IsNullPointerBase : False {};
|
||||
template< > struct IsNullPointerBase<Nullptr>: True {};
|
||||
}
|
||||
|
||||
template<typename T> struct IsNullPointer:
|
||||
octa::detail::IsNullPointerBase<RemoveCv<T>> {};
|
||||
detail::IsNullPointerBase<RemoveCv<T>> {};
|
||||
|
||||
/* is integer */
|
||||
|
||||
|
@ -98,21 +98,21 @@ namespace detail {
|
|||
template<> struct IsIntegralBase<int >: True {};
|
||||
template<> struct IsIntegralBase<long >: True {};
|
||||
|
||||
template<> struct IsIntegralBase<octa::sbyte >: True {};
|
||||
template<> struct IsIntegralBase<octa::byte >: True {};
|
||||
template<> struct IsIntegralBase<octa::ushort>: True {};
|
||||
template<> struct IsIntegralBase<octa::uint >: True {};
|
||||
template<> struct IsIntegralBase<octa::ulong >: True {};
|
||||
template<> struct IsIntegralBase<octa::llong >: True {};
|
||||
template<> struct IsIntegralBase<octa::ullong>: True {};
|
||||
template<> struct IsIntegralBase<sbyte >: True {};
|
||||
template<> struct IsIntegralBase<byte >: True {};
|
||||
template<> struct IsIntegralBase<ushort>: True {};
|
||||
template<> struct IsIntegralBase<uint >: True {};
|
||||
template<> struct IsIntegralBase<ulong >: True {};
|
||||
template<> struct IsIntegralBase<llong >: True {};
|
||||
template<> struct IsIntegralBase<ullong>: True {};
|
||||
|
||||
template<> struct IsIntegralBase<octa::Char16>: True {};
|
||||
template<> struct IsIntegralBase<octa::Char32>: True {};
|
||||
template<> struct IsIntegralBase<octa::Wchar >: True {};
|
||||
template<> struct IsIntegralBase<Char16>: True {};
|
||||
template<> struct IsIntegralBase<Char32>: True {};
|
||||
template<> struct IsIntegralBase<Wchar >: True {};
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
struct IsIntegral: octa::detail::IsIntegralBase<RemoveCv<T>> {};
|
||||
struct IsIntegral: detail::IsIntegralBase<RemoveCv<T>> {};
|
||||
|
||||
/* is floating point */
|
||||
|
||||
|
@ -122,17 +122,17 @@ namespace detail {
|
|||
template<> struct IsFloatingPointBase<float >: True {};
|
||||
template<> struct IsFloatingPointBase<double>: True {};
|
||||
|
||||
template<> struct IsFloatingPointBase<octa::ldouble>: True {};
|
||||
template<> struct IsFloatingPointBase<ldouble>: True {};
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
struct IsFloatingPoint: octa::detail::IsFloatingPointBase<RemoveCv<T>> {};
|
||||
struct IsFloatingPoint: detail::IsFloatingPointBase<RemoveCv<T>> {};
|
||||
|
||||
/* is array */
|
||||
|
||||
template<typename > struct IsArray : False {};
|
||||
template<typename T > struct IsArray<T[] >: True {};
|
||||
template<typename T, octa::Size N> struct IsArray<T[N]>: True {};
|
||||
template<typename > struct IsArray : False {};
|
||||
template<typename T > struct IsArray<T[] >: True {};
|
||||
template<typename T, Size N> struct IsArray<T[N]>: True {};
|
||||
|
||||
/* is pointer */
|
||||
|
||||
|
@ -142,7 +142,7 @@ namespace detail {
|
|||
}
|
||||
|
||||
template<typename T>
|
||||
struct IsPointer: octa::detail::IsPointerBase<RemoveCv<T>> {};
|
||||
struct IsPointer: detail::IsPointerBase<RemoveCv<T>> {};
|
||||
|
||||
/* is lvalue reference */
|
||||
|
||||
|
@ -178,11 +178,11 @@ namespace detail {
|
|||
template<typename T> T &function_source(int);
|
||||
template<typename T> FunctionTestDummy function_source(...);
|
||||
|
||||
template<typename T, bool = octa::IsClass<T>::value ||
|
||||
octa::IsUnion<T>::value ||
|
||||
octa::IsVoid<T>::value ||
|
||||
octa::IsReference<T>::value ||
|
||||
octa::IsNullPointer<T>::value
|
||||
template<typename T, bool = IsClass<T>::value ||
|
||||
IsUnion<T>::value ||
|
||||
IsVoid<T>::value ||
|
||||
IsReference<T>::value ||
|
||||
IsNullPointer<T>::value
|
||||
> struct IsFunctionBase: IntegralConstant<bool,
|
||||
sizeof(function_test<T>(function_source<T>(0))) == 1
|
||||
> {};
|
||||
|
@ -190,7 +190,7 @@ namespace detail {
|
|||
template<typename T> struct IsFunctionBase<T, true>: False {};
|
||||
} /* namespace detail */
|
||||
|
||||
template<typename T> struct IsFunction: octa::detail::IsFunctionBase<T> {};
|
||||
template<typename T> struct IsFunction: detail::IsFunctionBase<T> {};
|
||||
|
||||
/* is arithmetic */
|
||||
|
||||
|
@ -221,7 +221,7 @@ namespace detail {
|
|||
}
|
||||
|
||||
template<typename T>
|
||||
struct IsMemberPointer: octa::detail::IsMemberPointerBase<RemoveCv<T>> {};
|
||||
struct IsMemberPointer: detail::IsMemberPointerBase<RemoveCv<T>> {};
|
||||
|
||||
/* is pointer to member object */
|
||||
|
||||
|
@ -231,12 +231,12 @@ namespace detail {
|
|||
|
||||
template<typename T, typename U>
|
||||
struct IsMemberObjectPointerBase<T U::*>: IntegralConstant<bool,
|
||||
!octa::IsFunction<T>::value
|
||||
!IsFunction<T>::value
|
||||
> {};
|
||||
}
|
||||
|
||||
template<typename T> struct IsMemberObjectPointer:
|
||||
octa::detail::IsMemberObjectPointerBase<RemoveCv<T>> {};
|
||||
detail::IsMemberObjectPointerBase<RemoveCv<T>> {};
|
||||
|
||||
/* is pointer to member function */
|
||||
|
||||
|
@ -246,12 +246,12 @@ namespace detail {
|
|||
|
||||
template<typename T, typename U>
|
||||
struct IsMemberFunctionPointerBase<T U::*>: IntegralConstant<bool,
|
||||
octa::IsFunction<T>::value
|
||||
IsFunction<T>::value
|
||||
> {};
|
||||
}
|
||||
|
||||
template<typename T> struct IsMemberFunctionPointer:
|
||||
octa::detail::IsMemberFunctionPointerBase<RemoveCv<T>> {};
|
||||
detail::IsMemberFunctionPointerBase<RemoveCv<T>> {};
|
||||
|
||||
/* is reference */
|
||||
|
||||
|
@ -308,11 +308,11 @@ namespace detail {
|
|||
struct IsSignedBase: IntegralConstant<bool, T(-1) < T(0)> {};
|
||||
}
|
||||
|
||||
template<typename T, bool = octa::IsArithmetic<T>::value>
|
||||
template<typename T, bool = IsArithmetic<T>::value>
|
||||
struct IsSigned: False {};
|
||||
|
||||
template<typename T>
|
||||
struct IsSigned<T, true>: octa::detail::IsSignedBase<T> {};
|
||||
struct IsSigned<T, true>: detail::IsSignedBase<T> {};
|
||||
|
||||
/* is unsigned */
|
||||
|
||||
|
@ -321,11 +321,11 @@ namespace detail {
|
|||
struct IsUnsignedBase: IntegralConstant<bool, T(0) < T(-1)> {};
|
||||
}
|
||||
|
||||
template<typename T, bool = octa::IsArithmetic<T>::value>
|
||||
template<typename T, bool = IsArithmetic<T>::value>
|
||||
struct IsUnsigned: False {};
|
||||
|
||||
template<typename T>
|
||||
struct IsUnsigned<T, true>: octa::detail::IsUnsignedBase<T> {};
|
||||
struct IsUnsigned<T, true>: detail::IsUnsignedBase<T> {};
|
||||
|
||||
/* is standard layout */
|
||||
|
||||
|
@ -359,7 +359,7 @@ struct HasVirtualDestructor: IntegralConstant<bool,
|
|||
/* is constructible */
|
||||
|
||||
namespace detail {
|
||||
#define OCTA_MOVE(v) static_cast<octa::RemoveReference<decltype(v)> &&>(v)
|
||||
#define OCTA_MOVE(v) static_cast<RemoveReference<decltype(v)> &&>(v)
|
||||
|
||||
template<typename, typename T> struct Select2nd { using Type = T; };
|
||||
struct Any { Any(...); };
|
||||
|
@ -383,7 +383,7 @@ namespace detail {
|
|||
|
||||
/* scalars are default constructible, refs are not */
|
||||
template<typename T>
|
||||
struct CtibleCore<true, T>: octa::IsScalar<T> {};
|
||||
struct CtibleCore<true, T>: IsScalar<T> {};
|
||||
|
||||
/* scalars and references are constructible from one arg if
|
||||
* implicitly convertible to scalar or reference */
|
||||
|
@ -405,7 +405,7 @@ namespace detail {
|
|||
/* treat scalars and refs separately */
|
||||
template<bool, typename T, typename ...A>
|
||||
struct CtibleVoidCheck: CtibleCore<
|
||||
(octa::IsScalar<T>::value || octa::IsReference<T>::value), T, A...
|
||||
(IsScalar<T>::value || IsReference<T>::value), T, A...
|
||||
> {};
|
||||
|
||||
/* if any of T or A is void, IsConstructible should be false */
|
||||
|
@ -418,23 +418,23 @@ namespace detail {
|
|||
|
||||
template<typename T, typename ...A>
|
||||
struct CtibleContainsVoid<T, A...> {
|
||||
static constexpr bool value = octa::IsVoid<T>::value
|
||||
static constexpr bool value = IsVoid<T>::value
|
||||
|| CtibleContainsVoid<A...>::value;
|
||||
};
|
||||
|
||||
/* entry point */
|
||||
template<typename T, typename ...A>
|
||||
struct Ctible: CtibleVoidCheck<
|
||||
CtibleContainsVoid<T, A...>::value || octa::IsAbstract<T>::value,
|
||||
CtibleContainsVoid<T, A...>::value || IsAbstract<T>::value,
|
||||
T, A...
|
||||
> {};
|
||||
|
||||
/* array types are default constructible if their element type is */
|
||||
template<typename T, octa::Size N>
|
||||
struct CtibleCore<false, T[N]>: Ctible<octa::RemoveAllExtents<T>> {};
|
||||
template<typename T, Size N>
|
||||
struct CtibleCore<false, T[N]>: Ctible<RemoveAllExtents<T>> {};
|
||||
|
||||
/* otherwise array types are not constructible by this syntax */
|
||||
template<typename T, octa::Size N, typename ...A>
|
||||
template<typename T, Size N, typename ...A>
|
||||
struct CtibleCore<false, T[N], A...>: False {};
|
||||
|
||||
/* incomplete array types are not constructible */
|
||||
|
@ -443,7 +443,7 @@ namespace detail {
|
|||
} /* namespace detail */
|
||||
|
||||
template<typename T, typename ...A>
|
||||
struct IsConstructible: octa::detail::Ctible<T, A...> {};
|
||||
struct IsConstructible: detail::Ctible<T, A...> {};
|
||||
|
||||
/* is default constructible */
|
||||
|
||||
|
@ -464,14 +464,14 @@ template<typename T> struct IsMoveConstructible: IsConstructible<T,
|
|||
/* is assignable */
|
||||
|
||||
namespace detail {
|
||||
template<typename T, typename U> typename octa::detail::Select2nd<
|
||||
template<typename T, typename U> typename detail::Select2nd<
|
||||
decltype((declval_in<T>() = declval_in<U>())), True
|
||||
>::Type assign_test(T &&, U &&);
|
||||
|
||||
template<typename T> False assign_test(Any, T &&);
|
||||
|
||||
template<typename T, typename U, bool = octa::IsVoid<T>::value ||
|
||||
octa::IsVoid<U>::value
|
||||
template<typename T, typename U, bool = IsVoid<T>::value ||
|
||||
IsVoid<U>::value
|
||||
> struct IsAssignableBase: CommonTypeBase<
|
||||
decltype(assign_test(declval_in<T>(), declval_in<U>()))
|
||||
>::Type {};
|
||||
|
@ -481,7 +481,7 @@ namespace detail {
|
|||
} /* namespace detail */
|
||||
|
||||
template<typename T, typename U>
|
||||
struct IsAssignable: octa::detail::IsAssignableBase<T, U> {};
|
||||
struct IsAssignable: detail::IsAssignableBase<T, U> {};
|
||||
|
||||
/* is copy assignable */
|
||||
|
||||
|
@ -504,7 +504,7 @@ namespace detail {
|
|||
|
||||
template<typename T> struct IsDestructorWellformed {
|
||||
template<typename TT> static char test(typename IsDtibleApply<
|
||||
decltype(octa::detail::declval_in<TT &>().~TT())
|
||||
decltype(detail::declval_in<TT &>().~TT())
|
||||
>::Type);
|
||||
|
||||
template<typename TT> static int test(...);
|
||||
|
@ -515,8 +515,8 @@ namespace detail {
|
|||
template<typename, bool> struct DtibleImpl;
|
||||
|
||||
template<typename T>
|
||||
struct DtibleImpl<T, false>: octa::IntegralConstant<bool,
|
||||
IsDestructorWellformed<octa::RemoveAllExtents<T>>::value
|
||||
struct DtibleImpl<T, false>: IntegralConstant<bool,
|
||||
IsDestructorWellformed<RemoveAllExtents<T>>::value
|
||||
> {};
|
||||
|
||||
template<typename T>
|
||||
|
@ -525,13 +525,13 @@ namespace detail {
|
|||
template<typename T, bool> struct DtibleFalse;
|
||||
|
||||
template<typename T> struct DtibleFalse<T, false>
|
||||
: DtibleImpl<T, octa::IsReference<T>::value> {};
|
||||
: DtibleImpl<T, IsReference<T>::value> {};
|
||||
|
||||
template<typename T> struct DtibleFalse<T, true>: False {};
|
||||
} /* namespace detail */
|
||||
|
||||
template<typename T>
|
||||
struct IsDestructible: octa::detail::DtibleFalse<T, IsFunction<T>::value> {};
|
||||
struct IsDestructible: detail::DtibleFalse<T, IsFunction<T>::value> {};
|
||||
|
||||
template<typename T> struct IsDestructible<T[]>: False {};
|
||||
template< > struct IsDestructible<void>: False {};
|
||||
|
@ -634,10 +634,10 @@ struct IsBaseOf: IntegralConstant<bool, __is_base_of(B, D)> {};
|
|||
/* is convertible */
|
||||
|
||||
namespace detail {
|
||||
template<typename F, typename T, bool = octa::IsVoid<F>::value
|
||||
|| octa::IsFunction<T>::value || octa::IsArray<T>::value
|
||||
template<typename F, typename T, bool = IsVoid<F>::value
|
||||
|| IsFunction<T>::value || IsArray<T>::value
|
||||
> struct IsConvertibleBase {
|
||||
using Type = typename octa::IsVoid<T>::Type;
|
||||
using Type = typename IsVoid<T>::Type;
|
||||
};
|
||||
|
||||
template<typename F, typename T>
|
||||
|
@ -646,16 +646,16 @@ namespace detail {
|
|||
|
||||
template<typename FF, typename TT,
|
||||
typename = decltype(test_f<TT>(declval_in<FF>()))
|
||||
> static octa::True test(int);
|
||||
> static True test(int);
|
||||
|
||||
template<typename, typename> static octa::False test(...);
|
||||
template<typename, typename> static False test(...);
|
||||
|
||||
using Type = decltype(test<F, T>(0));
|
||||
};
|
||||
}
|
||||
|
||||
template<typename F, typename T>
|
||||
struct IsConvertible: octa::detail::IsConvertibleBase<F, T>::Type {};
|
||||
struct IsConvertible: detail::IsConvertibleBase<F, T>::Type {};
|
||||
|
||||
/* type equality */
|
||||
|
||||
|
@ -664,30 +664,30 @@ template<typename T > struct IsSame<T, T>: True {};
|
|||
|
||||
/* extent */
|
||||
|
||||
template<typename T, octa::uint I = 0>
|
||||
struct Extent: IntegralConstant<octa::Size, 0> {};
|
||||
template<typename T, uint I = 0>
|
||||
struct Extent: IntegralConstant<Size, 0> {};
|
||||
|
||||
template<typename T>
|
||||
struct Extent<T[], 0>: IntegralConstant<octa::Size, 0> {};
|
||||
struct Extent<T[], 0>: IntegralConstant<Size, 0> {};
|
||||
|
||||
template<typename T, octa::uint I>
|
||||
struct Extent<T[], I>: IntegralConstant<octa::Size, Extent<T, I - 1>::value> {};
|
||||
template<typename T, uint I>
|
||||
struct Extent<T[], I>: IntegralConstant<Size, Extent<T, I - 1>::value> {};
|
||||
|
||||
template<typename T, octa::Size N>
|
||||
struct Extent<T[N], 0>: IntegralConstant<octa::Size, N> {};
|
||||
template<typename T, Size N>
|
||||
struct Extent<T[N], 0>: IntegralConstant<Size, N> {};
|
||||
|
||||
template<typename T, octa::Size N, octa::uint I>
|
||||
struct Extent<T[N], I>: IntegralConstant<octa::Size, Extent<T, I - 1>::value> {};
|
||||
template<typename T, Size N, uint I>
|
||||
struct Extent<T[N], I>: IntegralConstant<Size, Extent<T, I - 1>::value> {};
|
||||
|
||||
/* rank */
|
||||
|
||||
template<typename T> struct Rank: IntegralConstant<octa::Size, 0> {};
|
||||
template<typename T> struct Rank: IntegralConstant<Size, 0> {};
|
||||
|
||||
template<typename T>
|
||||
struct Rank<T[]>: IntegralConstant<octa::Size, Rank<T>::value + 1> {};
|
||||
struct Rank<T[]>: IntegralConstant<Size, Rank<T>::value + 1> {};
|
||||
|
||||
template<typename T, octa::Size N>
|
||||
struct Rank<T[N]>: IntegralConstant<octa::Size, Rank<T>::value + 1> {};
|
||||
template<typename T, Size N>
|
||||
struct Rank<T[N]>: IntegralConstant<Size, Rank<T>::value + 1> {};
|
||||
|
||||
/* remove const, volatile, cv */
|
||||
|
||||
|
@ -704,22 +704,22 @@ namespace detail {
|
|||
}
|
||||
|
||||
template<typename T>
|
||||
using RemoveConst = typename octa::detail::RemoveConstBase<T>::Type;
|
||||
using RemoveConst = typename detail::RemoveConstBase<T>::Type;
|
||||
template<typename T>
|
||||
using RemoveVolatile = typename octa::detail::RemoveVolatileBase<T>::Type;
|
||||
using RemoveVolatile = typename detail::RemoveVolatileBase<T>::Type;
|
||||
|
||||
namespace detail {
|
||||
template<typename T>
|
||||
struct RemoveCvBase {
|
||||
using Type = octa::RemoveVolatile<octa::RemoveConst<T>>;
|
||||
using Type = RemoveVolatile<RemoveConst<T>>;
|
||||
};
|
||||
}
|
||||
|
||||
/* add const, volatile, cv */
|
||||
|
||||
namespace detail {
|
||||
template<typename T, bool = octa::IsReference<T>::value
|
||||
|| octa::IsFunction<T>::value || octa::IsConst<T>::value>
|
||||
template<typename T, bool = IsReference<T>::value
|
||||
|| IsFunction<T>::value || IsConst<T>::value>
|
||||
struct AddConstCore { using Type = T; };
|
||||
|
||||
template<typename T> struct AddConstCore<T, false> {
|
||||
|
@ -730,8 +730,8 @@ namespace detail {
|
|||
using Type = typename AddConstCore<T>::Type;
|
||||
};
|
||||
|
||||
template<typename T, bool = octa::IsReference<T>::value
|
||||
|| octa::IsFunction<T>::value || octa::IsVolatile<T>::value>
|
||||
template<typename T, bool = IsReference<T>::value
|
||||
|| IsFunction<T>::value || IsVolatile<T>::value>
|
||||
struct AddVolatileCore { using Type = T; };
|
||||
|
||||
template<typename T> struct AddVolatileCore<T, false> {
|
||||
|
@ -744,17 +744,17 @@ namespace detail {
|
|||
}
|
||||
|
||||
template<typename T>
|
||||
using AddVolatile = typename octa::detail::AddVolatileBase<T>::Type;
|
||||
using AddVolatile = typename detail::AddVolatileBase<T>::Type;
|
||||
|
||||
namespace detail {
|
||||
template<typename T>
|
||||
struct AddCvBase {
|
||||
using Type = octa::AddConst<octa::AddVolatile<T>>;
|
||||
using Type = AddConst<AddVolatile<T>>;
|
||||
};
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
using AddCv = typename octa::detail::AddCvBase<T>::Type;
|
||||
using AddCv = typename detail::AddCvBase<T>::Type;
|
||||
|
||||
/* remove reference */
|
||||
|
||||
|
@ -783,18 +783,18 @@ namespace detail {
|
|||
}
|
||||
|
||||
template<typename T>
|
||||
using RemovePointer = typename octa::detail::RemovePointerBase<T>::Type;
|
||||
using RemovePointer = typename detail::RemovePointerBase<T>::Type;
|
||||
|
||||
/* add pointer */
|
||||
|
||||
namespace detail {
|
||||
template<typename T> struct AddPointerBase {
|
||||
using Type = octa::RemoveReference<T> *;
|
||||
using Type = RemoveReference<T> *;
|
||||
};
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
using AddPointer = typename octa::detail::AddPointerBase<T>::Type;
|
||||
using AddPointer = typename detail::AddPointerBase<T>::Type;
|
||||
|
||||
/* add lvalue reference */
|
||||
|
||||
|
@ -843,12 +843,12 @@ namespace detail {
|
|||
struct RemoveExtentBase { using Type = T; };
|
||||
template<typename T>
|
||||
struct RemoveExtentBase<T[ ]> { using Type = T; };
|
||||
template<typename T, octa::Size N>
|
||||
template<typename T, Size N>
|
||||
struct RemoveExtentBase<T[N]> { using Type = T; };
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
using RemoveExtent = typename octa::detail::RemoveExtentBase<T>::Type;
|
||||
using RemoveExtent = typename detail::RemoveExtentBase<T>::Type;
|
||||
|
||||
/* remove all extents */
|
||||
|
||||
|
@ -859,7 +859,7 @@ namespace detail {
|
|||
using Type = RemoveAllExtentsBase<T>;
|
||||
};
|
||||
|
||||
template<typename T, octa::Size N> struct RemoveAllExtentsBase<T[N]> {
|
||||
template<typename T, Size N> struct RemoveAllExtentsBase<T[N]> {
|
||||
using Type = RemoveAllExtentsBase<T>;
|
||||
};
|
||||
}
|
||||
|
@ -884,34 +884,34 @@ namespace detail {
|
|||
~TlNat() = delete;
|
||||
};
|
||||
|
||||
using Stypes = TypeList<octa::sbyte,
|
||||
using Stypes = TypeList<sbyte,
|
||||
TypeList<short,
|
||||
TypeList<int,
|
||||
TypeList<long,
|
||||
TypeList<octa::llong, TlNat>>>>>;
|
||||
TypeList<llong, TlNat>>>>>;
|
||||
|
||||
using Utypes = TypeList<octa::byte,
|
||||
TypeList<octa::ushort,
|
||||
TypeList<octa::uint,
|
||||
TypeList<octa::ulong,
|
||||
TypeList<octa::ullong, TlNat>>>>>;
|
||||
using Utypes = TypeList<byte,
|
||||
TypeList<ushort,
|
||||
TypeList<uint,
|
||||
TypeList<ulong,
|
||||
TypeList<ullong, TlNat>>>>>;
|
||||
|
||||
template<typename T, octa::Size N, bool = (N <= sizeof(typename T::First))>
|
||||
template<typename T, Size N, bool = (N <= sizeof(typename T::First))>
|
||||
struct TypeFindFirst;
|
||||
|
||||
template<typename T, typename U, octa::Size N>
|
||||
template<typename T, typename U, Size N>
|
||||
struct TypeFindFirst<TypeList<T, U>, N, true> {
|
||||
using Type = T;
|
||||
};
|
||||
|
||||
template<typename T, typename U, octa::Size N>
|
||||
template<typename T, typename U, Size N>
|
||||
struct TypeFindFirst<TypeList<T, U>, N, false> {
|
||||
using Type = typename TypeFindFirst<U, N>::Type;
|
||||
};
|
||||
|
||||
template<typename T, typename U,
|
||||
bool = octa::IsConst<octa::RemoveReference<T>>::value,
|
||||
bool = octa::IsVolatile<octa::RemoveReference<T>>::value
|
||||
bool = IsConst<RemoveReference<T>>::value,
|
||||
bool = IsVolatile<RemoveReference<T>>::value
|
||||
> struct ApplyCv {
|
||||
using Type = U;
|
||||
};
|
||||
|
@ -946,67 +946,67 @@ namespace detail {
|
|||
using Type = const volatile U &;
|
||||
};
|
||||
|
||||
template<typename T, bool = octa::IsIntegral<T>::value ||
|
||||
octa::IsEnum<T>::value>
|
||||
struct MakeSigned {};
|
||||
template<typename T, bool = IsIntegral<T>::value ||
|
||||
IsEnum<T>::value>
|
||||
struct MakeSignedCore {};
|
||||
|
||||
template<typename T, bool = octa::IsIntegral<T>::value ||
|
||||
octa::IsEnum<T>::value>
|
||||
struct MakeUnsigned {};
|
||||
template<typename T, bool = IsIntegral<T>::value ||
|
||||
IsEnum<T>::value>
|
||||
struct MakeUnsignedCore {};
|
||||
|
||||
template<typename T>
|
||||
struct MakeSigned<T, true> {
|
||||
struct MakeSignedCore<T, true> {
|
||||
using Type = typename TypeFindFirst<Stypes, sizeof(T)>::Type;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct MakeUnsigned<T, true> {
|
||||
struct MakeUnsignedCore<T, true> {
|
||||
using Type = typename TypeFindFirst<Utypes, sizeof(T)>::Type;
|
||||
};
|
||||
|
||||
template<> struct MakeSigned<bool , true> {};
|
||||
template<> struct MakeSigned<short , true> { using Type = short; };
|
||||
template<> struct MakeSigned<int , true> { using Type = int; };
|
||||
template<> struct MakeSigned<long , true> { using Type = long; };
|
||||
template<> struct MakeSignedCore<bool , true> {};
|
||||
template<> struct MakeSignedCore<short , true> { using Type = short; };
|
||||
template<> struct MakeSignedCore<int , true> { using Type = int; };
|
||||
template<> struct MakeSignedCore<long , true> { using Type = long; };
|
||||
|
||||
template<> struct MakeSigned<octa::sbyte , true> { using Type = octa::sbyte; };
|
||||
template<> struct MakeSigned<octa::byte , true> { using Type = octa::sbyte; };
|
||||
template<> struct MakeSigned<octa::ushort, true> { using Type = short; };
|
||||
template<> struct MakeSigned<octa::uint , true> { using Type = int; };
|
||||
template<> struct MakeSigned<octa::ulong , true> { using Type = long; };
|
||||
template<> struct MakeSigned<octa::llong , true> { using Type = octa::llong; };
|
||||
template<> struct MakeSigned<octa::ullong, true> { using Type = octa::llong; };
|
||||
template<> struct MakeSignedCore<sbyte , true> { using Type = sbyte; };
|
||||
template<> struct MakeSignedCore<byte , true> { using Type = sbyte; };
|
||||
template<> struct MakeSignedCore<ushort, true> { using Type = short; };
|
||||
template<> struct MakeSignedCore<uint , true> { using Type = int; };
|
||||
template<> struct MakeSignedCore<ulong , true> { using Type = long; };
|
||||
template<> struct MakeSignedCore<llong , true> { using Type = llong; };
|
||||
template<> struct MakeSignedCore<ullong, true> { using Type = llong; };
|
||||
|
||||
template<> struct MakeUnsigned<bool , true> {};
|
||||
template<> struct MakeUnsigned<short , true> { using Type = octa::ushort; };
|
||||
template<> struct MakeUnsigned<int , true> { using Type = octa::uint; };
|
||||
template<> struct MakeUnsigned<long , true> { using Type = octa::ulong; };
|
||||
template<> struct MakeUnsignedCore<bool , true> {};
|
||||
template<> struct MakeUnsignedCore<short , true> { using Type = ushort; };
|
||||
template<> struct MakeUnsignedCore<int , true> { using Type = uint; };
|
||||
template<> struct MakeUnsignedCore<long , true> { using Type = ulong; };
|
||||
|
||||
template<> struct MakeUnsigned<octa::sbyte , true> { using Type = octa::byte; };
|
||||
template<> struct MakeUnsigned<octa::byte , true> { using Type = octa::byte; };
|
||||
template<> struct MakeUnsigned<octa::ushort, true> { using Type = octa::ushort; };
|
||||
template<> struct MakeUnsigned<octa::uint , true> { using Type = octa::uint; };
|
||||
template<> struct MakeUnsigned<octa::ulong , true> { using Type = octa::ulong; };
|
||||
template<> struct MakeUnsigned<octa::llong , true> { using Type = octa::ullong; };
|
||||
template<> struct MakeUnsigned<octa::ullong, true> { using Type = octa::ullong; };
|
||||
template<> struct MakeUnsignedCore<sbyte , true> { using Type = byte; };
|
||||
template<> struct MakeUnsignedCore<byte , true> { using Type = byte; };
|
||||
template<> struct MakeUnsignedCore<ushort, true> { using Type = ushort; };
|
||||
template<> struct MakeUnsignedCore<uint , true> { using Type = uint; };
|
||||
template<> struct MakeUnsignedCore<ulong , true> { using Type = ulong; };
|
||||
template<> struct MakeUnsignedCore<llong , true> { using Type = ullong; };
|
||||
template<> struct MakeUnsignedCore<ullong, true> { using Type = ullong; };
|
||||
|
||||
template<typename T> struct MakeSignedBase {
|
||||
using Type = typename ApplyCv<T,
|
||||
typename MakeSigned<octa::RemoveCv<T>>::Type
|
||||
typename MakeSignedCore<RemoveCv<T>>::Type
|
||||
>::Type;
|
||||
};
|
||||
|
||||
template<typename T> struct MakeUnsignedBase {
|
||||
using Type = typename ApplyCv<T,
|
||||
typename MakeUnsigned<octa::RemoveCv<T>>::Type
|
||||
typename MakeUnsignedCore<RemoveCv<T>>::Type
|
||||
>::Type;
|
||||
};
|
||||
} /* namespace detail */
|
||||
|
||||
template<typename T>
|
||||
using MakeSigned = typename octa::detail::MakeSignedBase<T>::Type;
|
||||
using MakeSigned = typename detail::MakeSignedBase<T>::Type;
|
||||
template<typename T>
|
||||
using MakeUnsigned = typename octa::detail::MakeUnsignedBase<T>::Type;
|
||||
using MakeUnsigned = typename detail::MakeUnsignedBase<T>::Type;
|
||||
|
||||
/* conditional */
|
||||
|
||||
|
@ -1023,7 +1023,7 @@ namespace detail {
|
|||
}
|
||||
|
||||
template<bool _cond, typename T, typename U>
|
||||
using Conditional = typename octa::detail::ConditionalBase<_cond, T, U>::Type;
|
||||
using Conditional = typename detail::ConditionalBase<_cond, T, U>::Type;
|
||||
|
||||
/* result of call at compile time */
|
||||
|
||||
|
@ -1062,16 +1062,16 @@ namespace detail {
|
|||
struct ResultOfCore {};
|
||||
template<typename F, typename ...A>
|
||||
struct ResultOfCore<F(A...), decltype(void(rof_invoke(
|
||||
octa::detail::declval_in<F>(), octa::detail::declval_in<A>()...)))> {
|
||||
using type = decltype(rof_invoke(octa::detail::declval_in<F>(),
|
||||
octa::detail::declval_in<A>()...));
|
||||
detail::declval_in<F>(), detail::declval_in<A>()...)))> {
|
||||
using type = decltype(rof_invoke(detail::declval_in<F>(),
|
||||
detail::declval_in<A>()...));
|
||||
};
|
||||
|
||||
template<typename T> struct ResultOfBase: ResultOfCore<T> {};
|
||||
} /* namespace detail */
|
||||
|
||||
template<typename T>
|
||||
using ResultOf = typename octa::detail::ResultOfBase<T>::Type;
|
||||
using ResultOf = typename detail::ResultOfBase<T>::Type;
|
||||
|
||||
/* enable if */
|
||||
|
||||
|
@ -1082,7 +1082,7 @@ namespace detail {
|
|||
}
|
||||
|
||||
template<bool B, typename T = void>
|
||||
using EnableIf = typename octa::detail::EnableIfBase<B, T>::Type;
|
||||
using EnableIf = typename detail::EnableIfBase<B, T>::Type;
|
||||
|
||||
/* decay */
|
||||
|
||||
|
@ -1090,18 +1090,18 @@ namespace detail {
|
|||
template<typename T>
|
||||
struct DecayBase {
|
||||
private:
|
||||
using U = octa::RemoveReference<T>;
|
||||
using U = RemoveReference<T>;
|
||||
public:
|
||||
using Type = octa::Conditional<octa::IsArray<U>::value,
|
||||
octa::RemoveExtent<U> *,
|
||||
octa::Conditional<octa::IsFunction<U>::value,
|
||||
octa::AddPointer<U>, octa::RemoveCv<U>>
|
||||
using Type = Conditional<IsArray<U>::value,
|
||||
RemoveExtent<U> *,
|
||||
Conditional<IsFunction<U>::value,
|
||||
AddPointer<U>, RemoveCv<U>>
|
||||
>;
|
||||
};
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
using Decay = typename octa::detail::DecayBase<T>::Type;
|
||||
using Decay = typename detail::DecayBase<T>::Type;
|
||||
|
||||
/* common type */
|
||||
|
||||
|
@ -1113,8 +1113,8 @@ namespace detail {
|
|||
};
|
||||
|
||||
template<typename T, typename U> struct CommonTypeBase<T, U> {
|
||||
using Type = Decay<decltype(true ? octa::detail::declval_in<T>()
|
||||
: octa::detail::declval_in<U>())>;
|
||||
using Type = Decay<decltype(true ? detail::declval_in<T>()
|
||||
: detail::declval_in<U>())>;
|
||||
};
|
||||
|
||||
template<typename T, typename U, typename ...V>
|
||||
|
@ -1126,61 +1126,61 @@ namespace detail {
|
|||
}
|
||||
|
||||
template<typename T, typename U, typename ...V>
|
||||
using CommonType = typename octa::detail::CommonTypeBase<T, U, V...>::Type;
|
||||
using CommonType = typename detail::CommonTypeBase<T, U, V...>::Type;
|
||||
|
||||
/* aligned storage */
|
||||
|
||||
namespace detail {
|
||||
template<octa::Size N> struct AlignedTest {
|
||||
template<Size N> struct AlignedTest {
|
||||
union Type {
|
||||
octa::byte data[N];
|
||||
octa::MaxAlign align;
|
||||
byte data[N];
|
||||
MaxAlign align;
|
||||
};
|
||||
};
|
||||
|
||||
template<octa::Size N, octa::Size A> struct AlignedStorageBase {
|
||||
template<Size N, Size A> struct AlignedStorageBase {
|
||||
struct Type {
|
||||
alignas(A) octa::byte data[N];
|
||||
alignas(A) byte data[N];
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
template<octa::Size N, octa::Size A
|
||||
= alignof(typename octa::detail::AlignedTest<N>::Type)
|
||||
> using AlignedStorage = typename octa::detail::AlignedStorageBase<N, A>::Type;
|
||||
template<Size N, Size A
|
||||
= alignof(typename detail::AlignedTest<N>::Type)
|
||||
> using AlignedStorage = typename detail::AlignedStorageBase<N, A>::Type;
|
||||
|
||||
/* aligned union */
|
||||
|
||||
namespace detail {
|
||||
template<octa::Size ...N> struct AlignMax;
|
||||
template<Size ...N> struct AlignMax;
|
||||
|
||||
template<octa::Size N> struct AlignMax<N> {
|
||||
static constexpr octa::Size value = N;
|
||||
template<Size N> struct AlignMax<N> {
|
||||
static constexpr Size value = N;
|
||||
};
|
||||
|
||||
template<octa::Size N1, octa::Size N2> struct AlignMax<N1, N2> {
|
||||
static constexpr octa::Size value = (N1 > N2) ? N1 : N2;
|
||||
template<Size N1, Size N2> struct AlignMax<N1, N2> {
|
||||
static constexpr Size value = (N1 > N2) ? N1 : N2;
|
||||
};
|
||||
|
||||
template<octa::Size N1, octa::Size N2, octa::Size ...N>
|
||||
template<Size N1, Size N2, Size ...N>
|
||||
struct AlignMax<N1, N2, N...> {
|
||||
static constexpr octa::Size value
|
||||
static constexpr Size value
|
||||
= AlignMax<AlignMax<N1, N2>::value, N...>::value;
|
||||
};
|
||||
|
||||
template<octa::Size N, typename ...T> struct AlignedUnionBase {
|
||||
static constexpr octa::Size alignment_value
|
||||
template<Size N, typename ...T> struct AlignedUnionBase {
|
||||
static constexpr Size alignment_value
|
||||
= AlignMax<alignof(T)...>::value;
|
||||
|
||||
struct type {
|
||||
alignas(alignment_value) octa::byte data[AlignMax<N,
|
||||
alignas(alignment_value) byte data[AlignMax<N,
|
||||
sizeof(T)...>::value];
|
||||
};
|
||||
};
|
||||
} /* namespace detail */
|
||||
|
||||
template<octa::Size N, typename ...T>
|
||||
using AlignedUnion = typename octa::detail::AlignedUnionBase<N, T...>::Type;
|
||||
template<Size N, typename ...T>
|
||||
using AlignedUnion = typename detail::AlignedUnionBase<N, T...>::Type;
|
||||
|
||||
/* underlying type */
|
||||
|
||||
|
@ -1192,7 +1192,7 @@ namespace detail {
|
|||
}
|
||||
|
||||
template<typename T>
|
||||
using UnderlyingType = typename octa::detail::UnderlyingTypeBase<T>::Type;
|
||||
using UnderlyingType = typename detail::UnderlyingTypeBase<T>::Type;
|
||||
} /* namespace octa */
|
||||
|
||||
#endif
|
|
@ -56,26 +56,26 @@ namespace detail {
|
|||
};
|
||||
|
||||
template<typename T> inline void swap(T &a, T &b, EnableIf<
|
||||
octa::detail::SwapTest<T>::value, bool
|
||||
detail::SwapTest<T>::value, bool
|
||||
> = true) {
|
||||
a.swap(b);
|
||||
}
|
||||
|
||||
template<typename T> inline void swap(T &a, T &b, EnableIf<
|
||||
!octa::detail::SwapTest<T>::value, bool
|
||||
!detail::SwapTest<T>::value, bool
|
||||
> = true) {
|
||||
T c(octa::move(a));
|
||||
a = octa::move(b);
|
||||
b = octa::move(c);
|
||||
T c(move(a));
|
||||
a = move(b);
|
||||
b = move(c);
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T> void swap(T &a, T &b) {
|
||||
octa::detail::swap(a, b);
|
||||
detail::swap(a, b);
|
||||
}
|
||||
|
||||
template<typename T, octa::Size N> void swap(T (&a)[N], T (&b)[N]) {
|
||||
for (octa::Size i = 0; i < N; ++i) {
|
||||
template<typename T, Size N> void swap(T (&a)[N], T (&b)[N]) {
|
||||
for (Size i = 0; i < N; ++i) {
|
||||
octa::swap(a[i], b[i]);
|
||||
}
|
||||
}
|
||||
|
@ -97,14 +97,14 @@ struct Pair {
|
|||
|
||||
template<typename TT, typename UU>
|
||||
Pair(TT &&x, UU &&y):
|
||||
first(octa::forward<TT>(x)), second(octa::forward<UU>(y)) {}
|
||||
first(forward<TT>(x)), second(forward<UU>(y)) {}
|
||||
|
||||
template<typename TT, typename UU>
|
||||
Pair(const Pair<TT, UU> &v): first(v.first), second(v.second) {}
|
||||
|
||||
template<typename TT, typename UU>
|
||||
Pair(Pair<TT, UU> &&v):
|
||||
first(octa::move(v.first)), second(octa::move(v.second)) {}
|
||||
first(move(v.first)), second(move(v.second)) {}
|
||||
|
||||
Pair &operator=(const Pair &v) {
|
||||
first = v.first;
|
||||
|
@ -120,21 +120,21 @@ struct Pair {
|
|||
}
|
||||
|
||||
Pair &operator=(Pair &&v) {
|
||||
first = octa::move(v.first);
|
||||
second = octa::move(v.second);
|
||||
first = move(v.first);
|
||||
second = move(v.second);
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename TT, typename UU>
|
||||
Pair &operator=(Pair<TT, UU> &&v) {
|
||||
first = octa::forward<TT>(v.first);
|
||||
second = octa::forward<UU>(v.second);
|
||||
first = forward<TT>(v.first);
|
||||
second = forward<UU>(v.second);
|
||||
return *this;
|
||||
}
|
||||
|
||||
void swap(Pair &v) {
|
||||
octa::swap(first, v.first);
|
||||
octa::swap(second, v.second);
|
||||
swap(first, v.first);
|
||||
swap(second, v.second);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -153,24 +153,24 @@ namespace detail {
|
|||
|
||||
template<typename T>
|
||||
struct MakePairRet {
|
||||
using Type = typename octa::detail::MakePairRetBase<octa::Decay<T>>::Type;
|
||||
using Type = typename detail::MakePairRetBase<Decay<T>>::Type;
|
||||
};
|
||||
} /* namespace detail */
|
||||
|
||||
template<typename T, typename U>
|
||||
Pair<typename octa::detail::MakePairRet<T>::Type,
|
||||
typename octa::detail::MakePairRet<U>::Type
|
||||
Pair<typename detail::MakePairRet<T>::Type,
|
||||
typename detail::MakePairRet<U>::Type
|
||||
> make_pair(T &&a, U &&b) {
|
||||
return Pair<typename octa::detail::MakePairRet<T>::Type,
|
||||
typename octa::detail::MakePairRet<U>::Type
|
||||
return Pair<typename detail::MakePairRet<T>::Type,
|
||||
typename detail::MakePairRet<U>::Type
|
||||
>(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
|
||||
bool = IsSame<RemoveCv<T>, RemoveCv<U>>::value,
|
||||
bool = IsEmpty<T>::value,
|
||||
bool = IsEmpty<U>::value
|
||||
> struct CompressedPairSwitch;
|
||||
|
||||
/* neither empty */
|
||||
|
@ -193,7 +193,7 @@ namespace detail {
|
|||
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>
|
||||
template<typename T, typename U, Size = CompressedPairSwitch<T, U>::value>
|
||||
struct CompressedPairBase;
|
||||
|
||||
template<typename T, typename U>
|
||||
|
@ -202,8 +202,8 @@ namespace detail {
|
|||
U p_second;
|
||||
|
||||
template<typename TT, typename UU>
|
||||
CompressedPairBase(TT &&a, UU &&b): p_first(octa::forward<TT>(a)),
|
||||
p_second(octa::forward<UU>(b)) {}
|
||||
CompressedPairBase(TT &&a, UU &&b): p_first(forward<TT>(a)),
|
||||
p_second(forward<UU>(b)) {}
|
||||
|
||||
T &first() { return p_first; }
|
||||
const T &first() const { return p_first; }
|
||||
|
@ -222,8 +222,8 @@ namespace detail {
|
|||
U p_second;
|
||||
|
||||
template<typename TT, typename UU>
|
||||
CompressedPairBase(TT &&a, UU &&b): T(octa::forward<TT>(a)),
|
||||
p_second(octa::forward<UU>(b)) {}
|
||||
CompressedPairBase(TT &&a, UU &&b): T(forward<TT>(a)),
|
||||
p_second(forward<UU>(b)) {}
|
||||
|
||||
T &first() { return *this; }
|
||||
const T &first() const { return *this; }
|
||||
|
@ -241,8 +241,8 @@ namespace detail {
|
|||
T p_first;
|
||||
|
||||
template<typename TT, typename UU>
|
||||
CompressedPairBase(TT &&a, UU &&b): U(octa::forward<UU>(b)),
|
||||
p_first(octa::forward<TT>(a)) {}
|
||||
CompressedPairBase(TT &&a, UU &&b): U(forward<UU>(b)),
|
||||
p_first(forward<TT>(a)) {}
|
||||
|
||||
T &first() { return p_first; }
|
||||
const T &first() const { return p_first; }
|
||||
|
@ -258,8 +258,8 @@ namespace detail {
|
|||
template<typename T, typename U>
|
||||
struct CompressedPairBase<T, U, 3>: T, U {
|
||||
template<typename TT, typename UU>
|
||||
CompressedPairBase(TT &&a, UU &&b): T(octa::forward<TT>(a)),
|
||||
U(octa::forward<UU>(b)) {}
|
||||
CompressedPairBase(TT &&a, UU &&b): T(forward<TT>(a)),
|
||||
U(forward<UU>(b)) {}
|
||||
|
||||
T &first() { return *this; }
|
||||
const T &first() const { return *this; }
|
||||
|
@ -275,8 +275,8 @@ namespace detail {
|
|||
using Base = CompressedPairBase<T, U>;
|
||||
|
||||
template<typename TT, typename UU>
|
||||
CompressedPair(TT &&a, UU &&b): Base(octa::forward<TT>(a),
|
||||
octa::forward<UU>(b)) {}
|
||||
CompressedPair(TT &&a, UU &&b): Base(forward<TT>(a),
|
||||
forward<UU>(b)) {}
|
||||
|
||||
T &first() { return Base::first(); }
|
||||
const T &first() const { return Base::first(); }
|
||||
|
|
139
octa/vector.hh
139
octa/vector.hh
|
@ -21,28 +21,28 @@ namespace octa {
|
|||
namespace detail {
|
||||
} /* namespace detail */
|
||||
|
||||
template<typename T, typename A = octa::Allocator<T>>
|
||||
template<typename T, typename A = Allocator<T>>
|
||||
class Vector {
|
||||
using VecPair = octa::detail::CompressedPair<octa::AllocatorPointer<A>, A>;
|
||||
using VecPair = detail::CompressedPair<AllocatorPointer<A>, A>;
|
||||
|
||||
octa::Size p_len, p_cap;
|
||||
Size p_len, p_cap;
|
||||
VecPair p_buf;
|
||||
|
||||
void insert_base(octa::Size idx, octa::Size n) {
|
||||
void insert_base(Size idx, Size n) {
|
||||
if (p_len + n > p_cap) reserve(p_len + n);
|
||||
p_len += n;
|
||||
for (octa::Size i = p_len - 1; i > idx + n - 1; --i) {
|
||||
p_buf.first()[i] = octa::move(p_buf.first()[i - n]);
|
||||
for (Size i = p_len - 1; i > idx + n - 1; --i) {
|
||||
p_buf.first()[i] = move(p_buf.first()[i - n]);
|
||||
}
|
||||
}
|
||||
|
||||
template<typename R>
|
||||
void ctor_from_range(R &range, octa::EnableIf<
|
||||
octa::IsFiniteRandomAccessRange<R>::value &&
|
||||
octa::IsPod<T>::value &&
|
||||
octa::IsSame<T, octa::RemoveCv<octa::RangeValue<R>>>::value, bool
|
||||
void ctor_from_range(R &range, EnableIf<
|
||||
IsFiniteRandomAccessRange<R>::value &&
|
||||
IsPod<T>::value &&
|
||||
IsSame<T, RemoveCv<RangeValue<R>>>::value, bool
|
||||
> = true) {
|
||||
octa::RangeSize<R> l = range.size();
|
||||
RangeSize<R> l = range.size();
|
||||
reserve(l);
|
||||
p_len = l;
|
||||
range.copy(p_buf.first(), l);
|
||||
|
@ -50,58 +50,57 @@ class Vector {
|
|||
|
||||
template<typename R>
|
||||
void ctor_from_range(R &range, EnableIf<
|
||||
!octa::IsFiniteRandomAccessRange<R>::value ||
|
||||
!octa::IsPod<T>::value ||
|
||||
!octa::IsSame<T, octa::RemoveCv<octa::RangeValue<R>>>::value, bool
|
||||
!IsFiniteRandomAccessRange<R>::value ||
|
||||
!IsPod<T>::value ||
|
||||
!IsSame<T, RemoveCv<RangeValue<R>>>::value, bool
|
||||
> = true) {
|
||||
octa::Size i = 0;
|
||||
Size i = 0;
|
||||
for (; !range.empty(); range.pop_front()) {
|
||||
reserve(i + 1);
|
||||
octa::allocator_construct(p_buf.second(),
|
||||
&p_buf.first()[i], range.front());
|
||||
allocator_construct(p_buf.second(), &p_buf.first()[i],
|
||||
range.front());
|
||||
++i;
|
||||
p_len = i;
|
||||
}
|
||||
}
|
||||
|
||||
void copy_contents(const Vector &v) {
|
||||
if (octa::IsPod<T>()) {
|
||||
if (IsPod<T>()) {
|
||||
memcpy(p_buf.first(), v.p_buf.first(), p_len * sizeof(T));
|
||||
} else {
|
||||
Pointer cur = p_buf.first(), last = p_buf.first() + p_len;
|
||||
Pointer vbuf = v.p_buf.first();
|
||||
while (cur != last) {
|
||||
octa::allocator_construct(p_buf.second(),
|
||||
cur++, *vbuf++);
|
||||
allocator_construct(p_buf.second(), cur++, *vbuf++);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
using Size = octa::Size;
|
||||
using Difference = octa::Ptrdiff;
|
||||
using Size = Size;
|
||||
using Difference = Ptrdiff;
|
||||
using Value = T;
|
||||
using Reference = T &;
|
||||
using ConstReference = const T &;
|
||||
using Pointer = octa::AllocatorPointer<A>;
|
||||
using ConstPointer = octa::AllocatorConstPointer<A>;
|
||||
using Range = octa::PointerRange<T>;
|
||||
using ConstRange = octa::PointerRange<const T>;
|
||||
using Pointer = AllocatorPointer<A>;
|
||||
using ConstPointer = AllocatorConstPointer<A>;
|
||||
using Range = PointerRange<T>;
|
||||
using ConstRange = PointerRange<const T>;
|
||||
using Allocator = A;
|
||||
|
||||
Vector(const A &a = A()): p_len(0), p_cap(0), p_buf(nullptr, a) {}
|
||||
|
||||
explicit Vector(Size n, const T &val = T(),
|
||||
const A &al = A()): Vector(al) {
|
||||
p_buf.first() = octa::allocator_allocate(p_buf.second(), n);
|
||||
p_buf.first() = allocator_allocate(p_buf.second(), n);
|
||||
p_len = p_cap = n;
|
||||
Pointer cur = p_buf.first(), last = p_buf.first() + n;
|
||||
while (cur != last)
|
||||
octa::allocator_construct(p_buf.second(), cur++, val);
|
||||
allocator_construct(p_buf.second(), cur++, val);
|
||||
}
|
||||
|
||||
Vector(const Vector &v): p_len(0), p_cap(0), p_buf(nullptr,
|
||||
octa::allocator_container_copy(v.p_buf.second())) {
|
||||
allocator_container_copy(v.p_buf.second())) {
|
||||
reserve(v.p_cap);
|
||||
p_len = v.p_len;
|
||||
copy_contents(v);
|
||||
|
@ -114,7 +113,7 @@ public:
|
|||
}
|
||||
|
||||
Vector(Vector &&v): p_len(v.p_len), p_cap(v.p_cap), p_buf(v.p_buf.first(),
|
||||
octa::move(v.p_buf.second())) {
|
||||
move(v.p_buf.second())) {
|
||||
v.p_buf.first() = nullptr;
|
||||
v.p_len = v.p_cap = 0;
|
||||
}
|
||||
|
@ -123,14 +122,13 @@ public:
|
|||
if (a != v.p_buf.second()) {
|
||||
reserve(v.p_cap);
|
||||
p_len = v.p_len;
|
||||
if (octa::IsPod<T>()) {
|
||||
if (IsPod<T>()) {
|
||||
memcpy(p_buf.first(), v.p_buf.first(), p_len * sizeof(T));
|
||||
} else {
|
||||
Pointer cur = p_buf.first(), last = p_buf.first() + p_len;
|
||||
Pointer vbuf = v.p_buf.first();
|
||||
while (cur != last) {
|
||||
octa::allocator_construct(p_buf.second(), cur++,
|
||||
octa::move(*vbuf++));
|
||||
allocator_construct(p_buf.second(), cur++, move(*vbuf++));
|
||||
}
|
||||
}
|
||||
return;
|
||||
|
@ -144,12 +142,11 @@ public:
|
|||
|
||||
Vector(const Value *buf, Size n, const A &a = A()): Vector(a) {
|
||||
reserve(n);
|
||||
if (octa::IsPod<T>()) {
|
||||
if (IsPod<T>()) {
|
||||
memcpy(p_buf.first(), buf, n * sizeof(T));
|
||||
} else {
|
||||
for (Size i = 0; i < n; ++i)
|
||||
octa::allocator_construct(p_buf.second(),
|
||||
&p_buf.first()[i], buf[i]);
|
||||
allocator_construct(p_buf.second(), &p_buf.first()[i], buf[i]);
|
||||
}
|
||||
p_len = n;
|
||||
}
|
||||
|
@ -157,23 +154,23 @@ public:
|
|||
Vector(InitializerList<T> v, const A &a = A()):
|
||||
Vector(v.begin(), v.size(), a) {}
|
||||
|
||||
template<typename R, typename = octa::EnableIf<
|
||||
octa::IsInputRange<R>::value &&
|
||||
octa::IsConvertible<RangeReference<R>, Value>::value
|
||||
template<typename R, typename = EnableIf<
|
||||
IsInputRange<R>::value &&
|
||||
IsConvertible<RangeReference<R>, Value>::value
|
||||
>> Vector(R range, const A &a = A()): Vector(a) {
|
||||
ctor_from_range(range);
|
||||
}
|
||||
|
||||
~Vector() {
|
||||
clear();
|
||||
octa::allocator_deallocate(p_buf.second(), p_buf.first(), p_cap);
|
||||
allocator_deallocate(p_buf.second(), p_buf.first(), p_cap);
|
||||
}
|
||||
|
||||
void clear() {
|
||||
if (p_len > 0 && !octa::IsPod<T>()) {
|
||||
if (p_len > 0 && !IsPod<T>()) {
|
||||
Pointer cur = p_buf.first(), last = p_buf.first() + p_len;
|
||||
while (cur != last)
|
||||
octa::allocator_destroy(p_buf.second(), cur++);
|
||||
allocator_destroy(p_buf.second(), cur++);
|
||||
}
|
||||
p_len = 0;
|
||||
}
|
||||
|
@ -181,9 +178,9 @@ public:
|
|||
Vector &operator=(const Vector &v) {
|
||||
if (this == &v) return *this;
|
||||
clear();
|
||||
if (octa::AllocatorPropagateOnContainerCopyAssignment<A>::value) {
|
||||
if (AllocatorPropagateOnContainerCopyAssignment<A>::value) {
|
||||
if (p_buf.second() != v.p_buf.second()) {
|
||||
octa::allocator_deallocate(p_buf.second(), p_buf.first(), p_cap);
|
||||
allocator_deallocate(p_buf.second(), p_buf.first(), p_cap);
|
||||
p_cap = 0;
|
||||
}
|
||||
p_buf.second() = v.p_buf.second();
|
||||
|
@ -196,13 +193,13 @@ public:
|
|||
|
||||
Vector &operator=(Vector &&v) {
|
||||
clear();
|
||||
octa::allocator_deallocate(p_buf.second(), p_buf.first(), p_cap);
|
||||
if (octa::AllocatorPropagateOnContainerMoveAssignment<A>::value)
|
||||
allocator_deallocate(p_buf.second(), p_buf.first(), p_cap);
|
||||
if (AllocatorPropagateOnContainerMoveAssignment<A>::value)
|
||||
p_buf.second() = v.p_buf.second();
|
||||
p_len = v.p_len;
|
||||
p_cap = v.p_cap;
|
||||
p_buf.~VecPair();
|
||||
new (&p_buf) VecPair(v.disown(), octa::move(v.p_buf.second()));
|
||||
new (&p_buf) VecPair(v.disown(), move(v.p_buf.second()));
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
@ -210,13 +207,13 @@ public:
|
|||
clear();
|
||||
Size ilen = il.end() - il.begin();
|
||||
reserve(ilen);
|
||||
if (octa::IsPod<T>()) {
|
||||
if (IsPod<T>()) {
|
||||
memcpy(p_buf.first(), il.begin(), ilen);
|
||||
} else {
|
||||
Pointer tbuf = p_buf.first(), ibuf = il.begin(),
|
||||
last = il.end();
|
||||
while (ibuf != last) {
|
||||
octa::allocator_construct(p_buf.second(),
|
||||
allocator_construct(p_buf.second(),
|
||||
tbuf++, *ibuf++);
|
||||
}
|
||||
}
|
||||
|
@ -224,9 +221,9 @@ public:
|
|||
return *this;
|
||||
}
|
||||
|
||||
template<typename R, typename = octa::EnableIf<
|
||||
octa::IsInputRange<R>::value &&
|
||||
octa::IsConvertible<RangeReference<R>, Value>::value
|
||||
template<typename R, typename = EnableIf<
|
||||
IsInputRange<R>::value &&
|
||||
IsConvertible<RangeReference<R>, Value>::value
|
||||
>> Vector &operator=(R range) {
|
||||
clear();
|
||||
ctor_from_range(range);
|
||||
|
@ -237,7 +234,7 @@ public:
|
|||
Size l = p_len;
|
||||
reserve(n);
|
||||
p_len = n;
|
||||
if (octa::IsPod<T>()) {
|
||||
if (IsPod<T>()) {
|
||||
for (Size i = l; i < p_len; ++i) {
|
||||
p_buf.first()[i] = T(v);
|
||||
}
|
||||
|
@ -245,7 +242,7 @@ public:
|
|||
Pointer first = p_buf.first() + l;
|
||||
Pointer last = p_buf.first() + p_len;
|
||||
while (first != last)
|
||||
octa::allocator_construct(p_buf.second(), first++, v);
|
||||
allocator_construct(p_buf.second(), first++, v);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -253,25 +250,24 @@ public:
|
|||
if (n <= p_cap) return;
|
||||
Size oc = p_cap;
|
||||
if (!oc) {
|
||||
p_cap = octa::max(n, Size(8));
|
||||
p_cap = max(n, Size(8));
|
||||
} else {
|
||||
while (p_cap < n) p_cap *= 2;
|
||||
}
|
||||
Pointer tmp = octa::allocator_allocate(p_buf.second(), p_cap);
|
||||
Pointer tmp = allocator_allocate(p_buf.second(), p_cap);
|
||||
if (oc > 0) {
|
||||
if (octa::IsPod<T>()) {
|
||||
if (IsPod<T>()) {
|
||||
memcpy(tmp, p_buf.first(), p_len * sizeof(T));
|
||||
} else {
|
||||
Pointer cur = p_buf.first(), tcur = tmp,
|
||||
last = tmp + p_len;
|
||||
while (tcur != last) {
|
||||
octa::allocator_construct(p_buf.second(), tcur++,
|
||||
octa::move(*cur));
|
||||
octa::allocator_destroy(p_buf.second(), cur);
|
||||
allocator_construct(p_buf.second(), tcur++, move(*cur));
|
||||
allocator_destroy(p_buf.second(), cur);
|
||||
++cur;
|
||||
}
|
||||
}
|
||||
octa::allocator_deallocate(p_buf.second(), p_buf.first(), oc);
|
||||
allocator_deallocate(p_buf.second(), p_buf.first(), oc);
|
||||
}
|
||||
p_buf.first() = tmp;
|
||||
}
|
||||
|
@ -290,36 +286,33 @@ public:
|
|||
|
||||
T &push(const T &v) {
|
||||
if (p_len == p_cap) reserve(p_len + 1);
|
||||
octa::allocator_construct(p_buf.second(),
|
||||
&p_buf.first()[p_len], v);
|
||||
allocator_construct(p_buf.second(), &p_buf.first()[p_len], v);
|
||||
return p_buf.first()[p_len++];
|
||||
}
|
||||
|
||||
T &push(T &&v) {
|
||||
if (p_len == p_cap) reserve(p_len + 1);
|
||||
octa::allocator_construct(p_buf.second(),
|
||||
&p_buf.first()[p_len], octa::move(v));
|
||||
allocator_construct(p_buf.second(), &p_buf.first()[p_len], move(v));
|
||||
return p_buf.first()[p_len++];
|
||||
}
|
||||
|
||||
T &push() {
|
||||
if (p_len == p_cap) reserve(p_len + 1);
|
||||
octa::allocator_construct(p_buf.second(), &p_buf.first()[p_len]);
|
||||
allocator_construct(p_buf.second(), &p_buf.first()[p_len]);
|
||||
return p_buf.first()[p_len++];
|
||||
}
|
||||
|
||||
template<typename ...U>
|
||||
T &emplace_back(U &&...args) {
|
||||
if (p_len == p_cap) reserve(p_len + 1);
|
||||
octa::allocator_construct(p_buf.second(), &p_buf.first()[p_len],
|
||||
octa::forward<U>(args)...);
|
||||
allocator_construct(p_buf.second(), &p_buf.first()[p_len],
|
||||
forward<U>(args)...);
|
||||
return p_buf.first()[p_len++];
|
||||
}
|
||||
|
||||
void pop() {
|
||||
if (!octa::IsPod<T>()) {
|
||||
octa::allocator_destroy(p_buf.second(),
|
||||
&p_buf.first()[--p_len]);
|
||||
if (!IsPod<T>()) {
|
||||
allocator_destroy(p_buf.second(), &p_buf.first()[--p_len]);
|
||||
} else {
|
||||
--p_len;
|
||||
}
|
||||
|
@ -356,7 +349,7 @@ public:
|
|||
|
||||
Range insert(Size idx, T &&v) {
|
||||
insert_base(idx, 1);
|
||||
p_buf.first()[idx] = octa::move(v);
|
||||
p_buf.first()[idx] = move(v);
|
||||
return Range(&p_buf.first()[idx], &p_buf.first()[p_len]);
|
||||
}
|
||||
|
||||
|
@ -407,7 +400,7 @@ public:
|
|||
octa::swap(p_len, v.p_len);
|
||||
octa::swap(p_cap, v.p_cap);
|
||||
octa::swap(p_buf.first(), v.p_buf.first());
|
||||
if (octa::AllocatorPropagateOnContainerSwap<A>::value)
|
||||
if (AllocatorPropagateOnContainerSwap<A>::value)
|
||||
octa::swap(p_buf.second(), v.p_buf.second());
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue