taler-go

Utility functions in Go language
Log | Files | Refs | LICENSE

commit 95f0f59f1e462cf543cd3acf335f08630dd84a1d
parent 8ae9aa1ed13e122e2f9ddf13120add39c246a424
Author: Martin Schanzenbach <schanzen@gnunet.org>
Date:   Mon, 18 Jul 2022 22:24:12 +0200

go fmt

Diffstat:
Mpkg/util/amount.go | 183+++++++++++++++++++++++++++++++++++++++----------------------------------------
1 file changed, 91 insertions(+), 92 deletions(-)

diff --git a/pkg/util/amount.go b/pkg/util/amount.go @@ -16,29 +16,28 @@ // // SPDX-License-Identifier: AGPL3.0-or-later - package util -import( - "errors" - "regexp" - "strconv" - "fmt" - "math" - "strings" +import ( + "errors" + "fmt" + "math" + "regexp" + "strconv" + "strings" ) // The GNU Taler Amount object type Amount struct { - // The type of currency, e.g. EUR - Currency string + // The type of currency, e.g. EUR + Currency string - // The value (before the ".") - Value uint64 + // The value (before the ".") + Value uint64 - // The fraction (after the ".", optional) - Fraction uint64 + // The fraction (after the ".", optional) + Fraction uint64 } // The maximim length of a fraction (in digits) @@ -52,103 +51,103 @@ var MaxAmountValue = uint64(math.Pow(2, 52)) // Create a new amount from value and fraction in a currency func NewAmount(currency string, value uint64, fraction uint64) Amount { - return Amount{ - Currency: currency, - Value: value, - Fraction: fraction, - } + return Amount{ + Currency: currency, + Value: value, + Fraction: fraction, + } } // Subtract the amount b from a and return the result. // a and b must be of the same currency and a >= b -func (a *Amount) Sub(b Amount) (*Amount,error) { - if a.Currency != b.Currency { - return nil, errors.New("Currency mismatch!") - } - v := a.Value - f := a.Fraction - if a.Fraction < b.Fraction { - v -= 1 - f += FractionalBase - } - f -= b.Fraction - if v < b.Value { - return nil, errors.New("Amount Overflow!") - } - v -= b.Value - r := Amount{ - Currency: a.Currency, - Value: v, - Fraction: f, - } - return &r, nil +func (a *Amount) Sub(b Amount) (*Amount, error) { + if a.Currency != b.Currency { + return nil, errors.New("Currency mismatch!") + } + v := a.Value + f := a.Fraction + if a.Fraction < b.Fraction { + v -= 1 + f += FractionalBase + } + f -= b.Fraction + if v < b.Value { + return nil, errors.New("Amount Overflow!") + } + v -= b.Value + r := Amount{ + Currency: a.Currency, + Value: v, + Fraction: f, + } + return &r, nil } // Add b to a and return the result. // Returns an error if the currencies do not match or the addition would // cause an overflow of the value -func (a *Amount) Add(b Amount) (*Amount,error) { - if a.Currency != b.Currency { - return nil, errors.New("Currency mismatch!") - } - v := a.Value + - b.Value + - uint64(math.Floor((float64(a.Fraction) + float64(b.Fraction)) / FractionalBase)) - - if v >= MaxAmountValue { - return nil, errors.New(fmt.Sprintf("Amount Overflow (%d > %d)!", v, MaxAmountValue)) - } - f := uint64((a.Fraction + b.Fraction) % FractionalBase) - r := Amount{ - Currency: a.Currency, - Value: v, - Fraction: f, - } - return &r, nil +func (a *Amount) Add(b Amount) (*Amount, error) { + if a.Currency != b.Currency { + return nil, errors.New("Currency mismatch!") + } + v := a.Value + + b.Value + + uint64(math.Floor((float64(a.Fraction)+float64(b.Fraction))/FractionalBase)) + + if v >= MaxAmountValue { + return nil, errors.New(fmt.Sprintf("Amount Overflow (%d > %d)!", v, MaxAmountValue)) + } + f := uint64((a.Fraction + b.Fraction) % FractionalBase) + r := Amount{ + Currency: a.Currency, + Value: v, + Fraction: f, + } + return &r, nil } // Parses an amount string in the format <currency>:<value>[.<fraction>] -func ParseAmount(s string) (*Amount,error) { - re, err := regexp.Compile(`^\s*([-_*A-Za-z0-9]+):([0-9]+)\.?([0-9]+)?\s*$`) - parsed := re.FindStringSubmatch(s) - - if nil != err { - return nil, errors.New(fmt.Sprintf("invalid amount: %s", s)) - } - tail := "0.0" - if len(parsed) >= 4 { - tail = "0." + parsed[3] - } - if len(tail) > FractionalLength + 1 { - return nil, errors.New("fraction too long") - } - value, err := strconv.ParseUint(parsed[2], 10, 64) - if nil != err { - return nil, errors.New(fmt.Sprintf("Unable to parse value %s", parsed[2])) - } - fractionF, err := strconv.ParseFloat(tail, 64) - if nil != err { - return nil, errors.New(fmt.Sprintf("Unable to parse fraction %s", tail)) - } - fraction := uint64(math.Round(fractionF * FractionalBase)) - currency := parsed[1] - a := NewAmount(currency, value, fraction) - return &a, nil +func ParseAmount(s string) (*Amount, error) { + re, err := regexp.Compile(`^\s*([-_*A-Za-z0-9]+):([0-9]+)\.?([0-9]+)?\s*$`) + parsed := re.FindStringSubmatch(s) + + if nil != err { + return nil, errors.New(fmt.Sprintf("invalid amount: %s", s)) + } + tail := "0.0" + if len(parsed) >= 4 { + tail = "0." + parsed[3] + } + if len(tail) > FractionalLength+1 { + return nil, errors.New("fraction too long") + } + value, err := strconv.ParseUint(parsed[2], 10, 64) + if nil != err { + return nil, errors.New(fmt.Sprintf("Unable to parse value %s", parsed[2])) + } + fractionF, err := strconv.ParseFloat(tail, 64) + if nil != err { + return nil, errors.New(fmt.Sprintf("Unable to parse fraction %s", tail)) + } + fraction := uint64(math.Round(fractionF * FractionalBase)) + currency := parsed[1] + a := NewAmount(currency, value, fraction) + return &a, nil } // Check if this amount is zero func (a *Amount) IsZero() bool { - return (a.Value == 0) && (a.Fraction == 0) + return (a.Value == 0) && (a.Fraction == 0) } // Returns the string representation of the amount: <currency>:<value>[.<fraction>] // Omits trailing zeroes. func (a *Amount) String() string { - v := strconv.FormatUint(a.Value, 10) - if a.Fraction != 0 { - f := strconv.FormatUint(a.Fraction, 10) - f = strings.TrimRight(f, "0") - v = fmt.Sprintf("%s.%s", v, f) - } - return fmt.Sprintf("%s:%s", a.Currency, v) + v := strconv.FormatUint(a.Value, 10) + if a.Fraction != 0 { + f := strconv.FormatUint(a.Fraction, 10) + f = strings.TrimRight(f, "0") + v = fmt.Sprintf("%s.%s", v, f) + } + return fmt.Sprintf("%s:%s", a.Currency, v) }