From 8d701f092d5dba49a79fada561e90cfdb84f2bd1 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Thu, 24 Sep 2015 16:36:08 -0700 Subject: [PATCH] math/big: implement Int.Text, Int.Append This makes the Int conversion routines match the respective strconv and big.Float conversion routines. Change-Id: I5cfcda1632ee52fe87c5bb75892bdda76cc3af15 Reviewed-on: https://go-review.googlesource.com/14994 Reviewed-by: Alan Donovan --- src/math/big/intconv.go | 39 +++++++++++++--- src/math/big/intconv_test.go | 89 ++++++++++++++++++++++++++++-------- 2 files changed, 102 insertions(+), 26 deletions(-) diff --git a/src/math/big/intconv.go b/src/math/big/intconv.go index 4693b171598a78..524f775a393611 100644 --- a/src/math/big/intconv.go +++ b/src/math/big/intconv.go @@ -12,14 +12,41 @@ import ( "io" ) -func (x *Int) String() string { - switch { - case x == nil: +// TODO(gri) Should rename itoa to utoa (there's no sign). That +// would permit the introduction of itoa which is like utoa but +// reserves a byte for a possible sign that's passed in. That +// would permit Int.Text to be implemented w/o the need for +// string copy if the number is negative. + +// Text returns the string representation of x in the given base. +// Base must be between 2 and 36, inclusive. The result uses the +// lower-case letters 'a' to 'z' for digit values >= 10. No base +// prefix (such as "0x") is added to the string. +func (x *Int) Text(base int) string { + if x == nil { return "" - case x.neg: - return "-" + string(x.abs.itoa(10)) } - return string(x.abs.itoa(10)) + s := string(x.abs.itoa(base)) + if x.neg { + s = "-" + s + } + return s +} + +// Append appends the string representation of x, as generated by +// x.Text(base), to buf and returns the extended buffer. +func (x *Int) Append(buf []byte, base int) []byte { + if x == nil { + return append(buf, ""...) + } + if x.neg { + buf = append(buf, '-') + } + return append(buf, x.abs.itoa(base)...) +} + +func (x *Int) String() string { + return x.Text(10) } // write count copies of text to s diff --git a/src/math/big/intconv_test.go b/src/math/big/intconv_test.go index 2deb84b48f68a4..514208145fdf11 100644 --- a/src/math/big/intconv_test.go +++ b/src/math/big/intconv_test.go @@ -17,19 +17,19 @@ var stringTests = []struct { val int64 ok bool }{ - {in: "", ok: false}, - {in: "a", ok: false}, - {in: "z", ok: false}, - {in: "+", ok: false}, - {in: "-", ok: false}, - {in: "0b", ok: false}, - {in: "0x", ok: false}, - {in: "2", base: 2, ok: false}, - {in: "0b2", base: 0, ok: false}, - {in: "08", ok: false}, - {in: "8", base: 8, ok: false}, - {in: "0xg", base: 0, ok: false}, - {in: "g", base: 16, ok: false}, + {in: ""}, + {in: "a"}, + {in: "z"}, + {in: "+"}, + {in: "-"}, + {in: "0b"}, + {in: "0x"}, + {in: "2", base: 2}, + {in: "0b2", base: 0}, + {in: "08"}, + {in: "8", base: 8}, + {in: "0xg", base: 0}, + {in: "g", base: 16}, {"0", "0", 0, 0, true}, {"0", "0", 10, 0, true}, {"0", "0", 16, 0, true}, @@ -41,7 +41,7 @@ var stringTests = []struct { {"-10", "-10", 16, -16, true}, {"+10", "10", 16, 16, true}, {"0x10", "16", 0, 16, true}, - {in: "0x10", base: 16, ok: false}, + {in: "0x10", base: 16}, {"-0x10", "-16", 0, -16, true}, {"+0x10", "16", 0, 16, true}, {"00", "0", 0, 0, true}, @@ -58,6 +58,57 @@ var stringTests = []struct { {"1001010111", "1001010111", 2, 0x257, true}, } +func TestIntText(t *testing.T) { + z := new(Int) + for _, test := range stringTests { + if !test.ok { + continue + } + + _, ok := z.SetString(test.in, test.base) + if !ok { + t.Errorf("%v: failed to parse", test) + continue + } + + base := test.base + if base == 0 { + base = 10 + } + + if got := z.Text(base); got != test.out { + t.Errorf("%v: got %s; want %s", test, got, test.out) + } + } +} + +func TestAppendText(t *testing.T) { + z := new(Int) + var buf []byte + for _, test := range stringTests { + if !test.ok { + continue + } + + _, ok := z.SetString(test.in, test.base) + if !ok { + t.Errorf("%v: failed to parse", test) + continue + } + + base := test.base + if base == 0 { + base = 10 + } + + i := len(buf) + buf = z.Append(buf, base) + if got := string(buf[i:]); got != test.out { + t.Errorf("%v: got %s; want %s", test, got, test.out) + } + } +} + func format(base int) string { switch base { case 2: @@ -79,15 +130,13 @@ func TestGetString(t *testing.T) { z.SetInt64(test.val) if test.base == 10 { - s := z.String() - if s != test.out { - t.Errorf("#%da got %s; want %s", i, s, test.out) + if got := z.String(); got != test.out { + t.Errorf("#%da got %s; want %s", i, got, test.out) } } - s := fmt.Sprintf(format(test.base), z) - if s != test.out { - t.Errorf("#%db got %s; want %s", i, s, test.out) + if got := fmt.Sprintf(format(test.base), z); got != test.out { + t.Errorf("#%db got %s; want %s", i, got, test.out) } } }