summaryrefslogtreecommitdiff
path: root/src/ints/udl.hpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/ints/udl.hpp')
-rw-r--r--src/ints/udl.hpp222
1 files changed, 222 insertions, 0 deletions
diff --git a/src/ints/udl.hpp b/src/ints/udl.hpp
new file mode 100644
index 0000000..e3e5fcc
--- /dev/null
+++ b/src/ints/udl.hpp
@@ -0,0 +1,222 @@
+#ifndef TMWA_INTS_UDL_HPP
+#define TMWA_INTS_UDL_HPP
+// udl.hpp - user-defined literals for integers.
+//
+// Copyright © 2014 Ben Longbons <b.r.longbons@gmail.com>
+//
+// This file is part of The Mana World (Athena server)
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+# include "../sanity.hpp"
+
+# include <cstdint>
+
+# include <type_traits>
+
+namespace ints
+{
+ namespace
+ {
+ typedef unsigned long long ullong;
+ template<char C>
+ struct CharParser
+ {
+ constexpr static
+ bool is_dec = '0' <= C && C <= '9';
+ constexpr static
+ bool is_upper = 'A' <= C && C <= 'F';
+ constexpr static
+ bool is_lower = 'a' <= C && C <= 'f';
+
+ static_assert(is_dec || is_upper || is_lower, "char base");
+
+ constexpr static
+ ullong value = is_upper ? (C - 'A' + 10) : is_lower ? (C - 'a' + 10) : C - '0';
+ };
+
+ template<ullong base, ullong accum, char... C>
+ struct BaseParser;
+ template<ullong base, ullong accum, char F, char... R>
+ struct BaseParser<base, accum, F, R...>
+ {
+ constexpr static
+ ullong mulled = accum * base;
+ constexpr static
+ ullong add = CharParser<F>::value;
+ static_assert(add < base, "parse base");
+ constexpr static
+ ullong added = mulled + add;
+ static_assert(added > accum || accum == 0, "parse overflow");
+
+ constexpr static
+ ullong value = BaseParser<base, added, R...>::value;
+ };
+ template<ullong base, ullong accum>
+ struct BaseParser<base, accum>
+ {
+ constexpr static
+ ullong value = accum;
+ };
+
+ template<char... C>
+ struct IntParser
+ {
+ constexpr static
+ ullong value = BaseParser<10, 0, C...>::value;
+ };
+
+ template<char... C>
+ struct IntParser<'0', C...>
+ {
+ constexpr static
+ ullong value = BaseParser<8, 0, C...>::value;
+ };
+
+ template<char... C>
+ struct IntParser<'0', 'x', C...>
+ {
+ constexpr static
+ ullong value = BaseParser<16, 0, C...>::value;
+ };
+
+ template<char... C>
+ struct IntParser<'0', 'X', C...>
+ {
+ constexpr static
+ ullong value = BaseParser<16, 0, C...>::value;
+ };
+
+ template<char... C>
+ struct IntParser<'0', 'b', C...>
+ {
+ constexpr static
+ ullong value = BaseParser<2, 0, C...>::value;
+ };
+
+ template<char... C>
+ struct IntParser<'0', 'B', C...>
+ {
+ constexpr static
+ ullong value = BaseParser<2, 0, C...>::value;
+ };
+
+ template<bool S, ullong V>
+ struct SignedMagnitudeConstant
+ {
+ static constexpr
+ bool sign = S;
+ static constexpr
+ ullong magnitude = V;
+
+ template<class T>
+ operator T()
+ {
+ typedef typename std::make_unsigned<T>::type U;
+
+ constexpr bool is_signed = T(-1) < T(0);
+ static_assert(is_signed >= (sign && magnitude), "signed");
+ constexpr ullong max = ullong(U(-1) >> is_signed);
+ static_assert(magnitude <= max || (sign && magnitude == max + 1), "magna");
+ return sign ? T(ullong(-magnitude)) : T(magnitude);
+ }
+ };
+
+ template<bool S1, ullong V1, bool S2, ullong V2>
+ constexpr
+ bool operator == (SignedMagnitudeConstant<S1, V1>, SignedMagnitudeConstant<S2, V2>)
+ {
+ return V1 == V2 && (S1 == S2 || !V1);
+ }
+ template<bool S1, ullong V1, bool S2, ullong V2>
+ constexpr
+ bool operator != (SignedMagnitudeConstant<S1, V1> lhs, SignedMagnitudeConstant<S2, V2> rhs)
+ {
+ return !(lhs == rhs);
+ }
+ template<bool S, ullong V>
+ constexpr
+ SignedMagnitudeConstant<!S, V> operator -(SignedMagnitudeConstant<S, V>)
+ {
+ return {};
+ }
+
+ struct pint8 { int8_t value; int8_t operator +() { return value; } };
+ struct pint16 { int16_t value; int16_t operator +() { return value; } };
+ struct pint32 { int32_t value; int32_t operator +() { return value; } };
+ struct pint64 { int64_t value; int64_t operator +() { return value; } };
+ struct nint8 { int8_t value; int8_t operator -() { return value; } };
+ struct nint16 { int16_t value; int16_t operator -() { return value; } };
+ struct nint32 { int32_t value; int32_t operator -() { return value; } };
+ struct nint64 { int64_t value; int64_t operator -() { return value; } };
+
+ template<char... C>
+ SignedMagnitudeConstant<false, IntParser<C...>::value> operator "" _const()
+ { return {}; }
+
+ template<char... C>
+ constexpr
+ uint8_t operator "" _u8 () { return operator "" _const<C...>(); }
+ template<char... C>
+ constexpr
+ uint16_t operator "" _u16 () { return operator "" _const<C...>(); }
+ template<char... C>
+ constexpr
+ uint32_t operator "" _u32 () { return operator "" _const<C...>(); }
+ template<char... C>
+ constexpr
+ uint64_t operator "" _u64 () { return operator "" _const<C...>(); }
+ template<char... C>
+ constexpr
+ pint8 operator "" _p8 () { return pint8{operator "" _const<C...>()}; }
+ template<char... C>
+ constexpr
+ pint16 operator "" _p16 () { return pint16{operator "" _const<C...>()}; }
+ template<char... C>
+ constexpr
+ pint32 operator "" _p32 () { return pint32{operator "" _const<C...>()}; }
+ template<char... C>
+ constexpr
+ pint64 operator "" _p64 () { return pint64{operator "" _const<C...>()}; }
+ template<char... C>
+ constexpr
+ nint8 operator "" _n8 () { return nint8{-operator "" _const<C...>()}; }
+ template<char... C>
+ constexpr
+ nint16 operator "" _n16 () { return nint16{-operator "" _const<C...>()}; }
+ template<char... C>
+ constexpr
+ nint32 operator "" _n32 () { return nint32{-operator "" _const<C...>()}; }
+ template<char... C>
+ constexpr
+ nint64 operator "" _n64 () { return nint64{-operator "" _const<C...>()}; }
+ } // anonymous namespace
+} // namespace ints
+
+using ints::operator "" _const;
+
+using ints::operator "" _u8;
+using ints::operator "" _u16;
+using ints::operator "" _u32;
+using ints::operator "" _u64;
+using ints::operator "" _p8;
+using ints::operator "" _p16;
+using ints::operator "" _p32;
+using ints::operator "" _p64;
+using ints::operator "" _n8;
+using ints::operator "" _n16;
+using ints::operator "" _n32;
+using ints::operator "" _n64;
+
+#endif // TMWA_INTS_UDL_HPP