/* Function objects for OctaSTD. * * This file is part of OctaSTD. See COPYING.md for futher information. */ #ifndef OSTD_FUNCTIONAL_HH #define OSTD_FUNCTIONAL_HH #include #include #include #include #include "ostd/platform.hh" #include "ostd/memory.hh" #include "ostd/utility.hh" #include "ostd/type_traits.hh" namespace ostd { /* basic function objects */ #define OSTD_DEFINE_BINARY_OP(name, op, RT) \ template \ struct name { \ RT operator()(T const &x, T const &y) const { \ return x op y; \ } \ using FirstArgument = T; \ using SecondARgument = T; \ using Result = RT; \ }; OSTD_DEFINE_BINARY_OP(Less, <, bool) OSTD_DEFINE_BINARY_OP(LessEqual, <=, bool) OSTD_DEFINE_BINARY_OP(Greater, >, bool) OSTD_DEFINE_BINARY_OP(GreaterEqual, >=, bool) OSTD_DEFINE_BINARY_OP(Equal, ==, bool) OSTD_DEFINE_BINARY_OP(NotEqual, !=, bool) OSTD_DEFINE_BINARY_OP(LogicalAnd, &&, bool) OSTD_DEFINE_BINARY_OP(LogicalOr, ||, bool) OSTD_DEFINE_BINARY_OP(Modulo, %, T) OSTD_DEFINE_BINARY_OP(Multiply, *, T) OSTD_DEFINE_BINARY_OP(Divide, /, T) OSTD_DEFINE_BINARY_OP(Add, +, T) OSTD_DEFINE_BINARY_OP(Subtract, -, T) OSTD_DEFINE_BINARY_OP(BitAnd, &, T) OSTD_DEFINE_BINARY_OP(BitOr, |, T) OSTD_DEFINE_BINARY_OP(BitXor, ^, T) #undef OSTD_DEFINE_BINARY_OP namespace detail { template, char>> struct CharEqual { using FirstArgument = T *; using SecondArgument = T *; using Result = bool; bool operator()(T *x, T *y) const { return !strcmp(x, y); } }; template struct CharEqual { using FirstArgument = T *; using SecondArgument = T *; using Result = bool; bool operator()(T *x, T *y) const { return x == y; } }; } template struct EqualWithCstr { using FirstArgument = T; using SecondArgument = T; bool operator()(T const &x, T const &y) const { return x == y; } }; template struct EqualWithCstr: detail::CharEqual {}; template struct LogicalNot { bool operator()(T const &x) const { return !x; } using Argument = T; using Result = bool; }; template struct Negate { bool operator()(T const &x) const { return -x; } using Argument = T; using Result = T; }; template struct BinaryNegate { using FirstArgument = typename T::FirstArgument; using SecondArgument = typename T::SecondArgument; using Result = bool; explicit BinaryNegate(T const &f): p_fn(f) {} bool operator()(FirstArgument const &x, SecondArgument const &y) { return !p_fn(x, y); } private: T p_fn; }; template struct UnaryNegate { using Argument = typename T::Argument; using Result = bool; explicit UnaryNegate(T const &f): p_fn(f) {} bool operator()(Argument const &x) { return !p_fn(x); } private: T p_fn; }; template UnaryNegate not1(T const &fn) { return UnaryNegate(fn); } template BinaryNegate not2(T const &fn) { return BinaryNegate(fn); } /* endian swap */ template> struct EndianSwap; template struct EndianSwap { using Argument = T; using Result = T; T operator()(T v) const { union { T iv; uint16_t sv; } u; u.iv = v; u.sv = endian_swap16(u.sv); return u.iv; } }; template struct EndianSwap { using Argument = T; using Result = T; T operator()(T v) const { union { T iv; uint32_t sv; } u; u.iv = v; u.sv = endian_swap32(u.sv); return u.iv; } }; template struct EndianSwap { using Argument = T; using Result = T; T operator()(T v) const { union { T iv; uint64_t sv; } u; u.iv = v; u.sv = endian_swap64(u.sv); return u.iv; } }; template T endian_swap(T x) { return EndianSwap()(x); } namespace detail { template> struct EndianSame; template struct EndianSame { using Argument = T; using Result = T; T operator()(T v) const { return v; } }; template struct EndianSame { using Argument = T; using Result = T; T operator()(T v) const { return v; } }; template struct EndianSame { using Argument = T; using Result = T; T operator()(T v) const { return v; } }; } #if OSTD_BYTE_ORDER == OSTD_ENDIAN_LIL template struct FromLilEndian: detail::EndianSame {}; template struct FromBigEndian: EndianSwap {}; #else template struct FromLilEndian: EndianSwap {}; template struct FromBigEndian: detail::EndianSame {}; #endif template T from_lil_endian(T x) { return FromLilEndian()(x); } template T from_big_endian(T x) { return FromBigEndian()(x); } } /* namespace ostd */ #endif