From 0ca886540279347830df9203df67ee64e36748a6 Mon Sep 17 00:00:00 2001 From: fyrchik Date: Fri, 4 May 2018 20:41:42 +0300 Subject: [PATCH] add ParseString constructor to util.Fixed8 (#79) --- pkg/util/fixed8.go | 29 ++++++++++++++++++++++++++++- pkg/util/fixed8_test.go | 22 ++++++++++++++++++++++ 2 files changed, 50 insertions(+), 1 deletion(-) diff --git a/pkg/util/fixed8.go b/pkg/util/fixed8.go index de03cc03d..b583aadf2 100644 --- a/pkg/util/fixed8.go +++ b/pkg/util/fixed8.go @@ -2,10 +2,17 @@ package util import ( "bytes" + "errors" "strconv" + "strings" ) -const decimals = 100000000 +const ( + precision = 8 + decimals = 100000000 +) + +var errInvalidString = errors.New("Fixed8 must satisfy following regex \\d+(\\.\\d{1,8})?") // Fixed8 represents a fixed-point number with precision 10^-8. type Fixed8 int64 @@ -41,3 +48,23 @@ func (f Fixed8) Value() int64 { func NewFixed8(val int) Fixed8 { return Fixed8(decimals * val) } + +// Fixed8DecodeString +func Fixed8DecodeString(s string) (Fixed8, error) { + parts := strings.SplitN(s, ".", 2) + ip, err := strconv.Atoi(parts[0]) + if err != nil { + return 0, errInvalidString + } else if len(parts) == 1 { + return NewFixed8(ip), nil + } + + fp, err := strconv.Atoi(parts[1]) + if err != nil || fp >= decimals { + return 0, errInvalidString + } + for i := len(parts[1]); i < precision; i++ { + fp *= 10 + } + return Fixed8(ip*decimals + fp), nil +} diff --git a/pkg/util/fixed8_test.go b/pkg/util/fixed8_test.go index 13fbeac49..6cf3a8392 100644 --- a/pkg/util/fixed8_test.go +++ b/pkg/util/fixed8_test.go @@ -14,3 +14,25 @@ func TestNewFixed8(t *testing.T) { assert.Equal(t, int64(val), NewFixed8(val).Value()) } } + +func TestFixed8DecodeString(t *testing.T) { + // Fixed8DecodeString works correctly with integers + ivalues := []string{"9000", "100000000", "5", "10945"} + for _, val:= range ivalues { + n, err := Fixed8DecodeString(val) + assert.Nil(t, err) + assert.Equal(t, val, n.String()) + } + + // Fixed8DecodeString parses number with maximal precision + val := "123456789.12345678" + n, err := Fixed8DecodeString(val) + assert.Nil(t, err) + assert.Equal(t, Fixed8(12345678912345678), n) + + // Fixed8DecodeString parses number with non-maximal precision + val = "901.2341" + n, err = Fixed8DecodeString(val) + assert.Nil(t, err) + assert.Equal(t, Fixed8(90123410000), n) +}