taler-go

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

commit 101e52d82c80bfbb21d6a5b8ebbf2991300b129e
parent c738fd713210648b515acd4fde8b187869f4ea7c
Author: Martin Schanzenbach <schanzen@gnunet.org>
Date:   Sun, 17 Jul 2022 12:26:54 +0200

rename module

Diffstat:
Mgo.mod | 2+-
Dpkg/taler/amount.go | 117-------------------------------------------------------------------------------
Dpkg/taler/amount_test.go | 50--------------------------------------------------
Apkg/util/amount.go | 117+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Apkg/util/amount_test.go | 50++++++++++++++++++++++++++++++++++++++++++++++++++
5 files changed, 168 insertions(+), 168 deletions(-)

diff --git a/go.mod b/go.mod @@ -1,3 +1,3 @@ -module taler.net/taler-util.git +module taler.net/taler-go.git go 1.18 diff --git a/pkg/taler/amount.go b/pkg/taler/amount.go @@ -1,117 +0,0 @@ -package taler - -import( - "errors" - "regexp" - "strconv" - "fmt" - "math" - "strings" -) - -// The GNU Taler Amount ob -type Amount struct { - - // The type of currency, e.g. EUR - Currency string - - // The value (before the ".") - Value uint64 - - // The fraction (after the ".", optional) - Fraction uint64 -} - -const FractionalLength = 8 - -const FractionalBase = 1e8 - -const MaxAmountValue = 2^52 - -func NewAmount(currency string, value uint64, fraction uint64) Amount { - return Amount{ - Currency: currency, - Value: value, - Fraction: fraction, - } -} - -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) 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("Amount Overflow!") - } - f := uint64((a.Fraction + b.Fraction) % FractionalBase) - r := Amount{ - Currency: a.Currency, - Value: v, - Fraction: f, - } - return &r, 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 -} - -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) -} diff --git a/pkg/taler/amount_test.go b/pkg/taler/amount_test.go @@ -1,50 +0,0 @@ -package taler - -import ( - "testing" -) - -var a = Amount{ - Currency: "EUR", - Value: 1, - Fraction: 50000000, -} -var b = Amount{ - Currency: "EUR", - Value: 23, - Fraction: 70007000, -} -var c = Amount{ - Currency: "EUR", - Value: 25, - Fraction: 20007000, -} - - - - -func TestAmountAdd(t *testing.T) { - d, err := a.Add(b) - if err != nil { - t.Errorf("Failed adding amount") - } - if c.String() != d.String() { - t.Errorf("Failed to add to correct amount") - } -} - -func TestAmountSub(t *testing.T) { - d, err := c.Sub(b) - if err != nil { - t.Errorf("Failed substracting amount") - } - if a.String() != d.String() { - t.Errorf("Failed to substract to correct amount") - } -} - -func TestAmountString(t *testing.T) { - if c.String() != "EUR:25.20007" { - t.Errorf("Failed to generate correct string") - } -} diff --git a/pkg/util/amount.go b/pkg/util/amount.go @@ -0,0 +1,117 @@ +package util + +import( + "errors" + "regexp" + "strconv" + "fmt" + "math" + "strings" +) + +// The GNU Taler Amount ob +type Amount struct { + + // The type of currency, e.g. EUR + Currency string + + // The value (before the ".") + Value uint64 + + // The fraction (after the ".", optional) + Fraction uint64 +} + +const FractionalLength = 8 + +const FractionalBase = 1e8 + +const MaxAmountValue = 2^52 + +func NewAmount(currency string, value uint64, fraction uint64) Amount { + return Amount{ + Currency: currency, + Value: value, + Fraction: fraction, + } +} + +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) 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("Amount Overflow!") + } + f := uint64((a.Fraction + b.Fraction) % FractionalBase) + r := Amount{ + Currency: a.Currency, + Value: v, + Fraction: f, + } + return &r, 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 +} + +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) +} diff --git a/pkg/util/amount_test.go b/pkg/util/amount_test.go @@ -0,0 +1,50 @@ +package util + +import ( + "testing" +) + +var a = Amount{ + Currency: "EUR", + Value: 1, + Fraction: 50000000, +} +var b = Amount{ + Currency: "EUR", + Value: 23, + Fraction: 70007000, +} +var c = Amount{ + Currency: "EUR", + Value: 25, + Fraction: 20007000, +} + + + + +func TestAmountAdd(t *testing.T) { + d, err := a.Add(b) + if err != nil { + t.Errorf("Failed adding amount") + } + if c.String() != d.String() { + t.Errorf("Failed to add to correct amount") + } +} + +func TestAmountSub(t *testing.T) { + d, err := c.Sub(b) + if err != nil { + t.Errorf("Failed substracting amount") + } + if a.String() != d.String() { + t.Errorf("Failed to substract to correct amount") + } +} + +func TestAmountString(t *testing.T) { + if c.String() != "EUR:25.20007" { + t.Errorf("Failed to generate correct string") + } +}