From a77f983015ad46fb970101779809eca6850f584c Mon Sep 17 00:00:00 2001 From: q66 Date: Sat, 11 Jul 2015 16:07:52 +0100 Subject: [PATCH] more complete relational operator sets + add lexicographical comparison --- octa/algorithm.hh | 24 ++++++++++++++ octa/array.hh | 30 +++++++++++++++++ octa/format.hh | 54 ++++++++++++++---------------- octa/functional.hh | 2 +- octa/io.hh | 24 +++++++------- octa/maybe.hh | 62 +++++++++++++++++------------------ octa/platform.hh | 18 +++++----- octa/string.hh | 82 +++++++++++++++++++++++++++++++++++++--------- octa/utility.hh | 52 ++++++++++++++++++++++++----- 9 files changed, 243 insertions(+), 105 deletions(-) diff --git a/octa/algorithm.hh b/octa/algorithm.hh index b436f1f..57c018f 100644 --- a/octa/algorithm.hh +++ b/octa/algorithm.hh @@ -214,6 +214,30 @@ inline T clamp(const T &v, const U &lo, const U &hi, C compare) { return octa::max(T(lo), octa::min(v, T(hi), compare), compare); } +/* lexicographical compare */ + +template +bool lexicographical_compare(R1 range1, R2 range2) { + while (!range1.empty() && !range2.empty()) { + if (range1.front() < range2.front()) return true; + if (range2.front() < range1.front()) return false; + range1.pop_front(); + range2.pop_front(); + } + return (range1.empty() && !range2.empty()); +} + +template +bool lexicographical_compare(R1 range1, R2 range2, C compare) { + while (!range1.empty() && !range2.empty()) { + if (compare(range1.front(), range2.front())) return true; + if (compare(range2.front(), range1.front())) return false; + range1.pop_front(); + range2.pop_front(); + } + return (range1.empty() && !range2.empty()); +} + /* algos that don't change the range */ template diff --git a/octa/array.hh b/octa/array.hh index 7555679..28b6864 100644 --- a/octa/array.hh +++ b/octa/array.hh @@ -99,6 +99,36 @@ TupleElement> &&get(Array &&a) { return a[I]; } +template +inline bool operator==(const Array &x, const Array &y) { + return equal(x.iter(), y.iter()); +} + +template +inline bool operator!=(const Array &x, const Array &y) { + return !(x == y); +} + +template +inline bool operator<(const Array &x, const Array &y) { + return lexicographical_compare(x.iter(), y.iter()); +} + +template +inline bool operator>(const Array &x, const Array &y) { + return (y < x); +} + +template +inline bool operator<=(const Array &x, const Array &y) { + return !(y < x); +} + +template +inline bool operator>=(const Array &x, const Array &y) { + return !(x < y); +} + } /* namespace octa */ #endif \ No newline at end of file diff --git a/octa/format.hh b/octa/format.hh index 4a8d989..f92d4ef 100644 --- a/octa/format.hh +++ b/octa/format.hh @@ -26,7 +26,7 @@ enum FormatFlags { }; namespace detail { - static inline int parse_fmt_flags(const char *&fmt, int ret) { + inline int parse_fmt_flags(const char *&fmt, int ret) { while (*fmt) { switch (*fmt) { case '-': ret |= FMT_FLAG_DASH; ++fmt; break; @@ -41,7 +41,7 @@ namespace detail { return ret; } - static inline Size read_digits(const char *&fmt, char *buf) { + inline Size read_digits(const char *&fmt, char *buf) { Size ret = 0; for (; isdigit(*fmt); ++ret) *buf++ = *fmt++; @@ -398,8 +398,7 @@ protected: namespace detail { template - static inline Ptrdiff write_u(R &writer, const FormatSpec *fl, - bool neg, T val) { + inline Ptrdiff write_u(R &writer, const FormatSpec *fl, bool neg, T val) { char buf[20]; Ptrdiff r = 0; Size n = 0; @@ -460,17 +459,15 @@ namespace detail { using FmtRangeTest = decltype(test_fmt_range(0)); template - static inline Ptrdiff format_ritem(R &writer, Size &fmtn, bool esc, - bool, const char *fmt, - const T &item) { + inline Ptrdiff format_ritem(R &writer, Size &fmtn, bool esc, bool, + const char *fmt, const T &item) { return format_impl(writer, fmtn, esc, fmt, item); } template - static inline Ptrdiff format_ritem(R &writer, Size &fmtn, bool esc, - bool expandval, - const char *fmt, - const Pair &pair) { + inline Ptrdiff format_ritem(R &writer, Size &fmtn, bool esc, + bool expandval, const char *fmt, + const Pair &pair) { if (expandval) { return format_impl(writer, fmtn, esc, fmt, pair.first, pair.second); @@ -479,12 +476,12 @@ namespace detail { } template - static inline Ptrdiff write_range(R &writer, const FormatSpec *fl, - bool escape, bool expandval, - const char *sep, Size seplen, - const T &val, - EnableIf::value, - bool> = true) { + inline Ptrdiff write_range(R &writer, const FormatSpec *fl, + bool escape, bool expandval, + const char *sep, Size seplen, + const T &val, + EnableIf::value, bool> + = true) { auto range = octa::iter(val); if (range.empty()) return 0; Ptrdiff ret = 0; @@ -510,10 +507,10 @@ namespace detail { } template - static inline Ptrdiff write_range(R &, const FormatSpec *, bool, bool, - const char *, Size, const T &, - EnableIf::value, - bool> = true) { + inline Ptrdiff write_range(R &, const FormatSpec *, bool, bool, + const char *, Size, const T &, + EnableIf::value, bool> + = true) { assert(false && "invalid value for ranged format"); return -1; } @@ -539,7 +536,7 @@ namespace detail { nullptr, "\\\'" }; - static inline const char *escape_fmt_char(char v, char quote) { + inline const char *escape_fmt_char(char v, char quote) { if ((v >= 0 && v < 0x20) || (v == quote)) { return fmt_escapes[Size(v)]; } else if (v == 0x7F) { @@ -548,7 +545,7 @@ namespace detail { return nullptr; } - static inline String escape_fmt_str(const char *val) { + inline String escape_fmt_str(const char *val) { String ret; ret.push('"'); while (*val) { @@ -808,8 +805,8 @@ namespace detail { }; template - static inline Ptrdiff format_impl(R &writer, Size &fmtn, bool escape, - const char *fmt, const A &...args) { + 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); @@ -871,8 +868,7 @@ namespace detail { } template - static inline Ptrdiff format_impl(R &writer, Size &fmtn, bool, - const char *fmt) { + 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; @@ -882,8 +878,8 @@ namespace detail { } /* namespace detail */ template -static inline Ptrdiff format(R &&writer, Size &fmtn, const char *fmt, - const A &...args) { +inline Ptrdiff format(R &&writer, Size &fmtn, const char *fmt, + const A &...args) { return detail::format_impl(writer, fmtn, false, fmt, args...); } diff --git a/octa/functional.hh b/octa/functional.hh index 8118d25..8aad5f6 100644 --- a/octa/functional.hh +++ b/octa/functional.hh @@ -218,7 +218,7 @@ OCTA_HASH_BASIC(Wchar) #undef OCTA_HASH_BASIC namespace detail { - static inline Size mem_hash(const void *p, Size l) { + 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]; diff --git a/octa/io.hh b/octa/io.hh index 4395e2d..334b62e 100644 --- a/octa/io.hh +++ b/octa/io.hh @@ -142,44 +142,44 @@ static FileStream err(::stderr); /* no need to call anything from FileStream, prefer simple calls... */ -static inline void write(const char *s) { +inline void write(const char *s) { fputs(s, ::stdout); } template -static inline void write(const AnyString &s) { +inline void write(const AnyString &s) { fwrite(s.data(), 1, s.size(), ::stdout); } template -static inline void write(const T &v) { +inline void write(const T &v) { write(octa::to_string(v)); } template -static inline void write(const T &v, const A &...args) { +inline void write(const T &v, const A &...args) { write(v); write(args...); } -static inline void writeln(const char *s) { +inline void writeln(const char *s) { write(s); putc('\n', ::stdout); } template -static inline void writeln(const AnyString &s) { +inline void writeln(const AnyString &s) { write(s); putc('\n', ::stdout); } template -static inline void writeln(const T &v) { +inline void writeln(const T &v) { writeln(octa::to_string(v)); } template -static inline void writeln(const T &v, const A &...args) { +inline void writeln(const T &v, const A &...args) { write(v); write(args...); putc('\n', ::stdout); @@ -197,7 +197,7 @@ namespace detail { } template -static inline void writef(const char *fmt, const A &...args) { +inline void writef(const char *fmt, const A &...args) { char buf[512]; Ptrdiff need = format(detail::FormatOutRange(buf), fmt, args...); @@ -213,19 +213,19 @@ static inline void writef(const char *fmt, const A &...args) { } template -static inline void writef(const AnyString &fmt, +inline void writef(const AnyString &fmt, const A &...args) { writef(fmt.data(), args...); } template -static inline void writefln(const char *fmt, const A &...args) { +inline void writefln(const char *fmt, const A &...args) { writef(fmt, args...); putc('\n', ::stdout); } template -static inline void writefln(const AnyString &fmt, +inline void writefln(const AnyString &fmt, const A &...args) { writef(fmt, args...); putc('\n', ::stdout); diff --git a/octa/maybe.hh b/octa/maybe.hh index ec37f36..f7625ac 100644 --- a/octa/maybe.hh +++ b/octa/maybe.hh @@ -261,163 +261,163 @@ public: /* maybe vs maybe */ template -static inline constexpr bool operator==(const Maybe &a, const Maybe &b) { +inline constexpr bool operator==(const Maybe &a, const Maybe &b) { return (bool(a) != bool(b)) ? false : (!bool(a) ? true : (*a == *b)); } template -static inline constexpr bool operator!=(const Maybe &a, const Maybe &b) { +inline constexpr bool operator!=(const Maybe &a, const Maybe &b) { return !(a == b); } template -static inline constexpr bool operator<(const Maybe &a, const Maybe &b) { +inline constexpr bool operator<(const Maybe &a, const Maybe &b) { return !bool(b) ? false : (!bool(a) ? true : (*a < *b)); } template -static inline constexpr bool operator>(const Maybe &a, const Maybe &b) { +inline constexpr bool operator>(const Maybe &a, const Maybe &b) { return b < a; } template -static inline constexpr bool operator<=(const Maybe &a, const Maybe &b) { +inline constexpr bool operator<=(const Maybe &a, const Maybe &b) { return !(b < a); } template -static inline constexpr bool operator>=(const Maybe &a, const Maybe &b) { +inline constexpr bool operator>=(const Maybe &a, const Maybe &b) { return !(a < b); } /* maybe vs nothing */ template -static inline constexpr bool operator==(const Maybe &v, Nothing) { +inline constexpr bool operator==(const Maybe &v, Nothing) { return !bool(v); } template -static inline constexpr bool operator==(Nothing, const Maybe &v) { +inline constexpr bool operator==(Nothing, const Maybe &v) { return !bool(v); } template -static inline constexpr bool operator!=(const Maybe &v, Nothing) { +inline constexpr bool operator!=(const Maybe &v, Nothing) { return bool(v); } template -static inline constexpr bool operator!=(Nothing, const Maybe &v) { +inline constexpr bool operator!=(Nothing, const Maybe &v) { return bool(v); } template -static inline constexpr bool operator<(const Maybe &, Nothing) { +inline constexpr bool operator<(const Maybe &, Nothing) { return false; } template -static inline constexpr bool operator<(Nothing, const Maybe &v) { +inline constexpr bool operator<(Nothing, const Maybe &v) { return bool(v); } template -static inline constexpr bool operator<=(const Maybe &v, Nothing) { +inline constexpr bool operator<=(const Maybe &v, Nothing) { return !bool(v); } template -static inline constexpr bool operator<=(Nothing, const Maybe &) { +inline constexpr bool operator<=(Nothing, const Maybe &) { return true; } template -static inline constexpr bool operator>(const Maybe &v, Nothing) { +inline constexpr bool operator>(const Maybe &v, Nothing) { return bool(v); } template -static inline constexpr bool operator>(Nothing, const Maybe &) { +inline constexpr bool operator>(Nothing, const Maybe &) { return false; } template -static inline constexpr bool operator>=(const Maybe &, Nothing) { +inline constexpr bool operator>=(const Maybe &, Nothing) { return true; } template -static inline constexpr bool operator>=(Nothing, const Maybe &v) { +inline constexpr bool operator>=(Nothing, const Maybe &v) { return !bool(v); } /* maybe vs T */ template -static inline constexpr bool operator==(const Maybe &a, const T &b) { +inline constexpr bool operator==(const Maybe &a, const T &b) { return bool(a) ? (*a == b) : false; } template -static inline constexpr bool operator==(const T &b, const Maybe &a) { +inline constexpr bool operator==(const T &b, const Maybe &a) { return bool(a) ? (*a == b) : false; } template -static inline constexpr bool operator!=(const Maybe &a, const T &b) { +inline constexpr bool operator!=(const Maybe &a, const T &b) { return bool(a) ? !(*a == b) : true; } template -static inline constexpr bool operator!=(const T &b, const Maybe &a) { +inline constexpr bool operator!=(const T &b, const Maybe &a) { return bool(a) ? !(*a == b) : true; } template -static inline constexpr bool operator<(const Maybe &a, const T &b) { +inline constexpr bool operator<(const Maybe &a, const T &b) { return bool(a) ? Less()(*a, b) : true; } template -static inline constexpr bool operator<(const T &b, const Maybe &a) { +inline constexpr bool operator<(const T &b, const Maybe &a) { return bool(a) ? Less()(b, *a) : false; } template -static inline constexpr bool operator<=(const Maybe &a, const T &b) { +inline constexpr bool operator<=(const Maybe &a, const T &b) { return !(a > b); } template -static inline constexpr bool operator<=(const T &b, const Maybe &a) { +inline constexpr bool operator<=(const T &b, const Maybe &a) { return !(b > a); } template -static inline constexpr bool operator>(const Maybe &a, const T &b) { +inline constexpr bool operator>(const Maybe &a, const T &b) { return bool(a) ? (b < a) : true; } template -static inline constexpr bool operator>(const T &b, const Maybe &a) { +inline constexpr bool operator>(const T &b, const Maybe &a) { return bool(a) ? (a < b) : true; } template -static inline constexpr bool operator>=(const Maybe &a, const T &b) { +inline constexpr bool operator>=(const Maybe &a, const T &b) { return !(a < b); } template -static inline constexpr bool operator>=(const T &b, const Maybe &a) { +inline constexpr bool operator>=(const T &b, const Maybe &a) { return !(b < a); } /* make maybe */ template -constexpr Maybe> make_maybe(T &&v) { +inline constexpr Maybe> make_maybe(T &&v) { return Maybe>(forward(v)); } diff --git a/octa/platform.hh b/octa/platform.hh index 87043c2..dec5355 100644 --- a/octa/platform.hh +++ b/octa/platform.hh @@ -76,40 +76,40 @@ namespace octa { #if defined(OCTA_TOOLCHAIN_GNU) /* using gcc/clang builtins */ -static inline uint16_t endian_swap16(uint16_t x) { +inline uint16_t endian_swap16(uint16_t x) { return __builtin_bswap16(x); } -static inline uint32_t endian_swap32(uint32_t x) { +inline uint32_t endian_swap32(uint32_t x) { return __builtin_bswap32(x); } -static inline uint64_t endian_swap64(uint64_t x) { +inline uint64_t endian_swap64(uint64_t x) { return __builtin_bswap64(x); } #elif defined(OCTA_TOOLCHAIN_MSVC) /* using msvc builtins */ -static inline uint16_t endian_swap16(uint16_t x) { +inline uint16_t endian_swap16(uint16_t x) { return _byteswap_ushort(x); } -static inline uint32_t endian_swap32(uint32_t x) { +inline uint32_t endian_swap32(uint32_t x) { /* win64 is llp64 */ return _byteswap_ulong(x); } -static inline uint64_t endian_swap64(uint64_t x) { +inline uint64_t endian_swap64(uint64_t x) { return _byteswap_uint64(x); } #else /* fallback */ -static inline uint16_t endian_swap16(uint16_t x) { +inline uint16_t endian_swap16(uint16_t x) { return (x << 8) | (x >> 8); } -static inline uint32_t endian_swap32(uint32_t x) { +inline uint32_t endian_swap32(uint32_t x) { return (x << 24) | (x >> 24) | ((x >> 8) & 0xFF00) | ((x << 8) & 0xFF0000); } -static inline uint64_t endian_swap64(uint64_t x) { +inline uint64_t endian_swap64(uint64_t x) { return endian_swap32(uint32_t(x >> 32)) | (uint64_t(endian_swap32(uint32_t(x))) << 32); } diff --git a/octa/string.hh b/octa/string.hh index f54dfb8..25cd68b 100644 --- a/octa/string.hh +++ b/octa/string.hh @@ -352,35 +352,87 @@ using ConstStringRange = StringRangeBase; template using AnyString = StringBase; template -static inline bool operator==(const StringBase &lhs, - const StringBase &rhs) { +inline bool operator==(const StringBase &lhs, + const StringBase &rhs) { return !lhs.compare(rhs); } template -static inline bool operator==(const StringBase &lhs, - const char *rhs) { +inline bool operator==(const StringBase &lhs, const char *rhs) { return !lhs.compare(rhs); } template -static inline bool operator==(const char *lhs, - const StringBase &rhs) { +inline bool operator==(const char *lhs, const StringBase &rhs) { return !rhs.compare(lhs); } template -static inline bool operator!=(const StringBase &lhs, - const StringBase &rhs) { - return !!lhs.compare(rhs); +inline bool operator!=(const StringBase &lhs, + const StringBase &rhs) { + return !(lhs == rhs); } template -static inline bool operator!=(const StringBase &lhs, - const char *rhs) { - return !!lhs.compare(rhs); +inline bool operator!=(const StringBase &lhs, const char *rhs) { + return !(lhs == rhs); } template -static inline bool operator!=(const char *lhs, - const StringBase &rhs) { - return !!rhs.compare(lhs); +inline bool operator!=(const char *lhs, const StringBase &rhs) { + return !(rhs == lhs); +} + +template +inline bool operator<(const StringBase &lhs, + const StringBase &rhs) { + return lhs.compare(rhs) < 0; +} +template +inline bool operator<(const StringBase &lhs, const char *rhs) { + return lhs.compare(rhs) < 0; +} +template +inline bool operator<(const char *lhs, const StringBase &rhs) { + return rhs.compare(lhs) > 0; +} + +template +inline bool operator>(const StringBase &lhs, + const StringBase &rhs) { + return rhs < lhs; +} +template +inline bool operator>(const StringBase &lhs, const char *rhs) { + return rhs < lhs; +} +template +inline bool operator>(const char *lhs, const StringBase &rhs) { + return rhs < lhs; +} + +template +inline bool operator<=(const StringBase &lhs, + const StringBase &rhs) { + return !(rhs < lhs); +} +template +inline bool operator<=(const StringBase &lhs, const char *rhs) { + return !(rhs < lhs); +} +template +inline bool operator<=(const char *lhs, const StringBase &rhs) { + return !(rhs < lhs); +} + +template +inline bool operator>=(const StringBase &lhs, + const StringBase &rhs) { + return !(lhs < rhs); +} +template +inline bool operator>=(const StringBase &lhs, const char *rhs) { + return !(lhs < rhs); +} +template +inline bool operator>=(const char *lhs, const StringBase &rhs) { + return !(lhs < rhs); } template -static inline constexpr RemoveReference &&move(T &&v) { +inline constexpr RemoveReference &&move(T &&v) { return static_cast &&>(v); } /* forward */ template -static inline constexpr T &&forward(RemoveReference &v) { +inline constexpr T &&forward(RemoveReference &v) { return static_cast(v); } template -static inline constexpr T &&forward(RemoveReference &&v) { +inline constexpr T &&forward(RemoveReference &&v) { return static_cast(v); } /* exchange */ template -T exchange(T &v, U &&nv) { +inline T exchange(T &v, U &&nv) { T old = move(v); v = forward(nv); return old; @@ -71,11 +71,11 @@ namespace detail { } } -template void swap(T &a, T &b) { +template inline void swap(T &a, T &b) { detail::swap(a, b); } -template void swap(T (&a)[N], T (&b)[N]) { +template inline void swap(T (&a)[N], T (&b)[N]) { for (Size i = 0; i < N; ++i) { octa::swap(a[i], b[i]); } @@ -159,14 +159,50 @@ namespace detail { } /* namespace detail */ template -Pair::Type, - typename detail::MakePairRet::Type +inline Pair::Type, + typename detail::MakePairRet::Type > make_pair(T &&a, U &&b) { return Pair::Type, typename detail::MakePairRet::Type >(forward(a), forward(b));; } +template +inline constexpr bool operator==(const Pair &x, const Pair &y) { + return (x.first == y.first) && (x.second == y.second); +} + +template +inline constexpr bool operator!=(const Pair &x, const Pair &y) { + return (x.first != y.first) || (x.second != y.second); +} + +template +inline constexpr bool operator<(const Pair &x, const Pair &y) { + return (x.first < y.first) + ? true + : ((y.first < x.first) + ? false + : ((x.second < y.second) + ? true + : false)); +} + +template +inline constexpr bool operator>(const Pair &x, const Pair &y) { + return (y < x); +} + +template +inline constexpr bool operator<=(const Pair &x, const Pair &y) { + return !(y < x); +} + +template +inline constexpr bool operator>=(const Pair &x, const Pair &y) { + return !(x < y); +} + template struct TupleSize>: IntegralConstant {};