From d40c109fb791dbea777546e9c94fba05e4c62ce3 Mon Sep 17 00:00:00 2001 From: Bruno BELANYI Date: Fri, 20 Aug 2021 19:00:53 +0200 Subject: [PATCH] abacus: bignum: add input operator --- src/bignum/bignum.cc | 35 +++++++++++++++++++++++++++++++++++ src/bignum/bignum.hh | 5 +++++ tests/unit/bignum.cc | 14 ++++++++++++++ 3 files changed, 54 insertions(+) diff --git a/src/bignum/bignum.cc b/src/bignum/bignum.cc index cf0d6b6..efe537e 100644 --- a/src/bignum/bignum.cc +++ b/src/bignum/bignum.cc @@ -105,6 +105,41 @@ std::ostream& BigNum::dump(std::ostream& out) const { return out; } +std::istream& BigNum::read(std::istream& in) { + bool parsed = false; + bool leading = true; + + if (in.peek() == '-') { + in.get(); + sign_ = -1; + } else { + sign_ = 1; + } + + digits_type digits; + while (std::isdigit(in.peek())) { + parsed = true; + int digit = in.get() - '0'; + if (digit != 0 || !leading) { + digits.push_back(digit); + leading = false; + } + } + + if (leading) { + sign_ = 0; + } + + if (!parsed) { + in.setstate(std::ios::failbit); + } else { + std::reverse(digits.begin(), digits.end()); + digits_ = std::move(digits); + } + + return in; +} + void BigNum::flip_sign() { assert(is_canonicalized()); diff --git a/src/bignum/bignum.hh b/src/bignum/bignum.hh index 149e962..9753840 100644 --- a/src/bignum/bignum.hh +++ b/src/bignum/bignum.hh @@ -15,6 +15,10 @@ public: return num.dump(out); } + friend std::istream& operator>>(std::istream& in, BigNum& num) { + return num.read(in); + } + friend BigNum operator+(BigNum const& rhs) { return rhs; } @@ -73,6 +77,7 @@ public: private: std::ostream& dump(std::ostream& out) const; + std::istream& read(std::istream& in); void flip_sign(); void add(BigNum const& rhs); diff --git a/tests/unit/bignum.cc b/tests/unit/bignum.cc index bf788b6..57b248b 100644 --- a/tests/unit/bignum.cc +++ b/tests/unit/bignum.cc @@ -24,6 +24,20 @@ TEST(BigNum, dump) { EXPECT_EQ(to_str(forty_two), "42"); } +TEST(BigNum, read) { + auto const from_str = [](auto num) -> BigNum { + std::stringstream str(num); + BigNum res; + EXPECT_TRUE(str >> res); + return res; + }; + + EXPECT_EQ(from_str("0"), BigNum(0)); + EXPECT_EQ(from_str("1"), BigNum(1)); + EXPECT_EQ(from_str("-1"), BigNum(-1)); + EXPECT_EQ(from_str("42"), BigNum(42)); +} + TEST(BigNum, equality) { auto const zero = BigNum(0); auto const one = BigNum(1);