Skip to content

Commit

Permalink
Merge pull request #24 from yobeonline/literal
Browse files Browse the repository at this point in the history
literal moved to io1
  • Loading branch information
yobeonline authored Feb 6, 2024
2 parents 8babbd0 + 78bae95 commit 38f7f9b
Show file tree
Hide file tree
Showing 3 changed files with 51 additions and 54 deletions.
101 changes: 47 additions & 54 deletions include/io1/money.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,6 @@
#include <string>
#include <type_traits>

namespace io1
{
class money;
}

template <char... STR>
constexpr io1::money operator""_money(void) noexcept;

namespace io1
{
class money
Expand All @@ -49,9 +41,6 @@ namespace io1
template <std::floating_point T>
explicit constexpr money(T amount) noexcept = delete;

template <char... STR>
friend constexpr money(::operator""_money)(void) noexcept;

[[nodiscard]] constexpr value_type const & data(void) const noexcept { return amount_; }

[[nodiscard]] constexpr money operator++(int) noexcept { return money{amount_++}; }
Expand Down Expand Up @@ -120,7 +109,6 @@ namespace io1
};

private:
struct StringLitteralDecoder;
struct PutMoney;
struct GetMoney;

Expand Down Expand Up @@ -203,52 +191,55 @@ namespace io1
}

// Helper structure to build a io1::Money object from a user-defined string litteral
struct money::StringLitteralDecoder
namespace detail
{
public:
template <char... STR>
[[nodiscard]] constexpr static money apply(void) noexcept
struct StringLitteralDecoder
{
return money{parse_mantissa<0, STR...>()};
}
public:
template <char... STR>
[[nodiscard]] constexpr static money apply(void) noexcept
{
return money{parse_mantissa<0, STR...>()};
}

private:
template <value_type CURRENT_MANTISSA, char DIGIT>
[[nodiscard]] constexpr static value_type parse_digit(void) noexcept
{
static_assert('0' <= DIGIT && '9' >= DIGIT, "Unexpected digit!");
private:
template <money::value_type CURRENT_MANTISSA, char DIGIT>
[[nodiscard]] constexpr static money::value_type parse_digit(void) noexcept
{
static_assert('0' <= DIGIT && '9' >= DIGIT, "Unexpected digit!");

constexpr auto d = static_cast<value_type>(DIGIT - '0');
constexpr auto ten = static_cast<value_type>(10);
constexpr auto d = static_cast<money::value_type>(DIGIT - '0');
constexpr auto ten = static_cast<money::value_type>(10);

static_assert(CURRENT_MANTISSA >= 0, "Parsing a raw user-defined litteral.");
static_assert((std::numeric_limits<value_type>::max() - d) / ten >= CURRENT_MANTISSA,
"Number not representable by io1::Money");
static_assert(CURRENT_MANTISSA >= 0, "Parsing a raw user-defined litteral.");
static_assert((std::numeric_limits<money::value_type>::max() - d) / ten >= CURRENT_MANTISSA,
"Number not representable by io1::Money");

return ten * CURRENT_MANTISSA + d;
}
return ten * CURRENT_MANTISSA + d;
}

template <char DIGIT>
[[nodiscard]] constexpr static bool not_a_digit(void) noexcept
{
return (DIGIT == '.' || DIGIT == '\'');
}
template <char DIGIT>
[[nodiscard]] constexpr static bool not_a_digit(void) noexcept
{
return (DIGIT == '.' || DIGIT == '\'');
}

template <value_type CURRENT_MANTISSA, char DIGIT, char... STR>
constexpr static value_type parse_mantissa(void) noexcept
{
constexpr auto new_mantissa = []()
template <money::value_type CURRENT_MANTISSA, char DIGIT, char... STR>
constexpr static money::value_type parse_mantissa(void) noexcept
{
if constexpr (not_a_digit<DIGIT>()) return CURRENT_MANTISSA;
constexpr auto new_mantissa = []()
{
if constexpr (not_a_digit<DIGIT>()) return CURRENT_MANTISSA;
else
return parse_digit<CURRENT_MANTISSA, DIGIT>();
}();

if constexpr (0 < sizeof...(STR)) return parse_mantissa<new_mantissa, STR...>();
else
return parse_digit<CURRENT_MANTISSA, DIGIT>();
}();

if constexpr (0 < sizeof...(STR)) return parse_mantissa<new_mantissa, STR...>();
else
return new_mantissa;
}
};
return new_mantissa;
}
};
} // namespace detail

inline std::ostream & operator<<(std::ostream & stream, io1::money m) noexcept
{
Expand Down Expand Up @@ -344,14 +335,16 @@ namespace io1
return {.quot = money(result.quot), .rem = money(result.rem)};
}

inline namespace literals
{
template <char... STR>
constexpr io1::money operator""_money(void) noexcept
{
return io1::detail::StringLitteralDecoder::apply<STR...>();
}
} // namespace literals
} // namespace io1

template <char... STR>
constexpr io1::money operator""_money(void) noexcept
{
return io1::money::StringLitteralDecoder::apply<STR...>();
}

template <class CharT>
struct std::formatter<io1::money, CharT>
{
Expand Down
2 changes: 2 additions & 0 deletions test/test_money.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
#define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN
#include <doctest/doctest.h>

using namespace io1::literals;

TEST_CASE("Value bounds")
{
[[maybe_unused]] constexpr auto max = 9'223'372'036'854'775'807_money;
Expand Down
2 changes: 2 additions & 0 deletions test/tutorial.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
#include <sstream>
#include <vector>

using namespace io1::literals;

class american_moneypunct_facet : public std::moneypunct<char, false>
{
private:
Expand Down

0 comments on commit 38f7f9b

Please sign in to comment.