aboutsummaryrefslogtreecommitdiff
path: root/libgo/go/strconv
diff options
context:
space:
mode:
authorIan Lance Taylor <ian@gcc.gnu.org>2011-12-14 15:41:54 +0000
committerIan Lance Taylor <ian@gcc.gnu.org>2011-12-14 15:41:54 +0000
commitd5363590597572228d4e0d0ae13f3469176ceb14 (patch)
treee3de46cbc89d82ca1f49843fe2e1e670db67795e /libgo/go/strconv
parentef0d4c4d9937276c8ff818ecb0b92925d322d3bd (diff)
downloadgcc-d5363590597572228d4e0d0ae13f3469176ceb14.zip
gcc-d5363590597572228d4e0d0ae13f3469176ceb14.tar.gz
gcc-d5363590597572228d4e0d0ae13f3469176ceb14.tar.bz2
libgo: Update to weekly.2011-12-06.
From-SVN: r182338
Diffstat (limited to 'libgo/go/strconv')
-rw-r--r--libgo/go/strconv/atob.go17
-rw-r--r--libgo/go/strconv/atob_test.go4
-rw-r--r--libgo/go/strconv/atof.go49
-rw-r--r--libgo/go/strconv/atof_test.go38
-rw-r--r--libgo/go/strconv/atoi.go102
-rw-r--r--libgo/go/strconv/atoi_test.go40
-rw-r--r--libgo/go/strconv/fp_test.go7
-rw-r--r--libgo/go/strconv/ftoa.go29
-rw-r--r--libgo/go/strconv/ftoa_test.go28
-rw-r--r--libgo/go/strconv/itoa.go132
-rw-r--r--libgo/go/strconv/itoa_test.go124
-rw-r--r--libgo/go/strconv/quote.go24
-rw-r--r--libgo/go/strconv/quote_test.go12
13 files changed, 324 insertions, 282 deletions
diff --git a/libgo/go/strconv/atob.go b/libgo/go/strconv/atob.go
index e2d87bc..1508118 100644
--- a/libgo/go/strconv/atob.go
+++ b/libgo/go/strconv/atob.go
@@ -4,10 +4,10 @@
package strconv
-// Atob returns the boolean value represented by the string.
+// ParseBool returns the boolean value represented by the string.
// It accepts 1, t, T, TRUE, true, True, 0, f, F, FALSE, false, False.
// Any other value returns an error.
-func Atob(str string) (value bool, err error) {
+func ParseBool(str string) (value bool, err error) {
switch str {
case "1", "t", "T", "true", "TRUE", "True":
return true, nil
@@ -17,10 +17,19 @@ func Atob(str string) (value bool, err error) {
return false, &NumError{str, ErrSyntax}
}
-// Btoa returns "true" or "false" according to the value of the boolean argument
-func Btoa(b bool) string {
+// FormatBool returns "true" or "false" according to the value of b
+func FormatBool(b bool) string {
if b {
return "true"
}
return "false"
}
+
+// AppendBool appends "true" or "false", according to the value of b,
+// to dst and returns the extended buffer.
+func AppendBool(dst []byte, b bool) []byte {
+ if b {
+ return append(dst, "true"...)
+ }
+ return append(dst, "false"...)
+}
diff --git a/libgo/go/strconv/atob_test.go b/libgo/go/strconv/atob_test.go
index 2f31eb5..a7c1454 100644
--- a/libgo/go/strconv/atob_test.go
+++ b/libgo/go/strconv/atob_test.go
@@ -32,9 +32,9 @@ var atobtests = []atobTest{
{"True", true, nil},
}
-func TestAtob(t *testing.T) {
+func TestParseBool(t *testing.T) {
for _, test := range atobtests {
- b, e := Atob(test.in)
+ b, e := ParseBool(test.in)
if test.err != nil {
// expect an error
if e == nil {
diff --git a/libgo/go/strconv/atof.go b/libgo/go/strconv/atof.go
index 06dae85..1642c18 100644
--- a/libgo/go/strconv/atof.go
+++ b/libgo/go/strconv/atof.go
@@ -338,21 +338,7 @@ func (d *decimal) atof32() (f float32, ok bool) {
return
}
-// Atof32 converts the string s to a 32-bit floating-point number.
-//
-// If s is well-formed and near a valid floating point number,
-// Atof32 returns the nearest floating point number rounded
-// using IEEE754 unbiased rounding.
-//
-// The errors that Atof32 returns have concrete type *NumError
-// and include err.Num = s.
-//
-// If s is not syntactically well-formed, Atof32 returns err.Error = ErrSyntax.
-//
-// If s is syntactically well-formed but is more than 1/2 ULP
-// away from the largest floating point number of the given size,
-// Atof32 returns f = ±Inf, err.Error = ErrRange.
-func Atof32(s string) (f float32, err error) {
+func atof32(s string) (f float32, err error) {
if val, ok := special(s); ok {
return float32(val), nil
}
@@ -374,10 +360,7 @@ func Atof32(s string) (f float32, err error) {
return f, err
}
-// Atof64 converts the string s to a 64-bit floating-point number.
-// Except for the type of its result, its definition is the same as that
-// of Atof32.
-func Atof64(s string) (f float64, err error) {
+func atof64(s string) (f float64, err error) {
if val, ok := special(s); ok {
return val, nil
}
@@ -399,14 +382,28 @@ func Atof64(s string) (f float64, err error) {
return f, err
}
-// AtofN converts the string s to a 64-bit floating-point number,
-// but it rounds the result assuming that it will be stored in a value
-// of n bits (32 or 64).
-func AtofN(s string, n int) (f float64, err error) {
- if n == 32 {
- f1, err1 := Atof32(s)
+// ParseFloat converts the string s to a floating-point number
+// with the precision specified by bitSize: 32 for float32, or 64 for float64.
+// When bitSize=32, the result still has type float64, but it will be
+// convertible to float32 without changing its value.
+//
+// If s is well-formed and near a valid floating point number,
+// ParseFloat returns the nearest floating point number rounded
+// using IEEE754 unbiased rounding.
+//
+// The errors that ParseFloat returns have concrete type *NumError
+// and include err.Num = s.
+//
+// If s is not syntactically well-formed, ParseFloat returns err.Error = ErrSyntax.
+//
+// If s is syntactically well-formed but is more than 1/2 ULP
+// away from the largest floating point number of the given size,
+// ParseFloat returns f = ±Inf, err.Error = ErrRange.
+func ParseFloat(s string, bitSize int) (f float64, err error) {
+ if bitSize == 32 {
+ f1, err1 := atof32(s)
return float64(f1), err1
}
- f1, err1 := Atof64(s)
+ f1, err1 := atof64(s)
return f1, err1
}
diff --git a/libgo/go/strconv/atof_test.go b/libgo/go/strconv/atof_test.go
index 871bf0c..a9820d1 100644
--- a/libgo/go/strconv/atof_test.go
+++ b/libgo/go/strconv/atof_test.go
@@ -128,33 +128,23 @@ func testAtof(t *testing.T, opt bool) {
oldopt := SetOptimize(opt)
for i := 0; i < len(atoftests); i++ {
test := &atoftests[i]
- out, err := Atof64(test.in)
- outs := Ftoa64(out, 'g', -1)
+ out, err := ParseFloat(test.in, 64)
+ outs := FormatFloat(out, 'g', -1, 64)
if outs != test.out || !reflect.DeepEqual(err, test.err) {
- t.Errorf("Atof64(%v) = %v, %v want %v, %v",
- test.in, out, err, test.out, test.err)
- }
-
- out, err = AtofN(test.in, 64)
- outs = FtoaN(out, 'g', -1, 64)
- if outs != test.out || !reflect.DeepEqual(err, test.err) {
- t.Errorf("AtofN(%v, 64) = %v, %v want %v, %v",
+ t.Errorf("ParseFloat(%v, 64) = %v, %v want %v, %v",
test.in, out, err, test.out, test.err)
}
if float64(float32(out)) == out {
- out32, err := Atof32(test.in)
- outs := Ftoa32(out32, 'g', -1)
- if outs != test.out || !reflect.DeepEqual(err, test.err) {
- t.Errorf("Atof32(%v) = %v, %v want %v, %v # %v",
- test.in, out32, err, test.out, test.err, out)
+ out, err := ParseFloat(test.in, 32)
+ out32 := float32(out)
+ if float64(out32) != out {
+ t.Errorf("ParseFloat(%v, 32) = %v, not a float32 (closest is %v)", test.in, out, float64(out32))
+ continue
}
-
- out, err := AtofN(test.in, 32)
- out32 = float32(out)
- outs = FtoaN(float64(out32), 'g', -1, 32)
+ outs := FormatFloat(float64(out32), 'g', -1, 32)
if outs != test.out || !reflect.DeepEqual(err, test.err) {
- t.Errorf("AtofN(%v, 32) = %v, %v want %v, %v # %v",
+ t.Errorf("ParseFloat(%v, 32) = %v, %v want %v, %v # %v",
test.in, out32, err, test.out, test.err, out)
}
}
@@ -168,24 +158,24 @@ func TestAtofSlow(t *testing.T) { testAtof(t, false) }
func BenchmarkAtof64Decimal(b *testing.B) {
for i := 0; i < b.N; i++ {
- Atof64("33909")
+ ParseFloat("33909", 64)
}
}
func BenchmarkAtof64Float(b *testing.B) {
for i := 0; i < b.N; i++ {
- Atof64("339.7784")
+ ParseFloat("339.7784", 64)
}
}
func BenchmarkAtof64FloatExp(b *testing.B) {
for i := 0; i < b.N; i++ {
- Atof64("-5.09e75")
+ ParseFloat("-5.09e75", 64)
}
}
func BenchmarkAtof64Big(b *testing.B) {
for i := 0; i < b.N; i++ {
- Atof64("123456789123456789123456789")
+ ParseFloat("123456789123456789123456789", 64)
}
}
diff --git a/libgo/go/strconv/atoi.go b/libgo/go/strconv/atoi.go
index 2c6c3d5..438d496 100644
--- a/libgo/go/strconv/atoi.go
+++ b/libgo/go/strconv/atoi.go
@@ -20,15 +20,9 @@ type NumError struct {
func (e *NumError) Error() string { return `parsing "` + e.Num + `": ` + e.Err.Error() }
-func computeIntsize() uint {
- siz := uint(8)
- for 1<<siz != 0 {
- siz *= 2
- }
- return siz
-}
+const intSize = 32 << uint(^uint(0)>>63)
-var IntSize = computeIntsize()
+const IntSize = intSize // number of bits in int, uint (32 or 64)
// Return the first number n such that n*base >= 1<<64.
func cutoff64(base int) uint64 {
@@ -38,17 +32,13 @@ func cutoff64(base int) uint64 {
return (1<<64-1)/uint64(base) + 1
}
-// Btoui64 interprets a string s in an arbitrary base b (2 to 36)
-// and returns the corresponding value n. If b == 0, the base
-// is taken from the string prefix: base 16 for "0x", base 8 for "0",
-// and base 10 otherwise.
-//
-// The errors that Btoui64 returns have concrete type *NumError
-// and include err.Num = s. If s is empty or contains invalid
-// digits, err.Error = ErrSyntax; if the value corresponding
-// to s cannot be represented by a uint64, err.Error = ErrRange.
-func Btoui64(s string, b int) (n uint64, err error) {
- var cutoff uint64
+// ParseUint is like ParseInt but for unsigned numbers.
+func ParseUint(s string, b int, bitSize int) (n uint64, err error) {
+ var cutoff, maxVal uint64
+
+ if bitSize == 0 {
+ bitSize = int(IntSize)
+ }
s0 := s
switch {
@@ -82,6 +72,7 @@ func Btoui64(s string, b int) (n uint64, err error) {
n = 0
cutoff = cutoff64(b)
+ maxVal = 1<<uint(bitSize) - 1
for i := 0; i < len(s); i++ {
var v byte
@@ -113,7 +104,7 @@ func Btoui64(s string, b int) (n uint64, err error) {
n *= uint64(b)
n1 := n + uint64(v)
- if n1 < n {
+ if n1 < n || n1 > maxVal {
// n+v overflows
n = 1<<64 - 1
err = ErrRange
@@ -128,18 +119,25 @@ Error:
return n, &NumError{s0, err}
}
-// Atoui64 interprets a string s as a decimal number and
-// returns the corresponding value n.
+// ParseInt interprets a string s in an arbitrary base b (2 to 36)
+// and returns the corresponding value n. If b == 0, the base
+// is taken from the string prefix: base 16 for "0x", base 8 for "0",
+// and base 10 otherwise.
//
-// Atoui64 returns err.Error = ErrSyntax if s is empty or contains invalid digits.
-// It returns err.Error = ErrRange if s cannot be represented by a uint64.
-func Atoui64(s string) (n uint64, err error) {
- return Btoui64(s, 10)
-}
+// The bitSize argument specifies the integer type
+// that the result must fit into. Bit sizes 0, 8, 16, 32, and 64
+// correspond to int, int8, int16, int32, and int64.
+//
+// The errors that ParseInt returns have concrete type *NumError
+// and include err.Num = s. If s is empty or contains invalid
+// digits, err.Error = ErrSyntax; if the value corresponding
+// to s cannot be represented by a signed integer of the
+// given size, err.Error = ErrRange.
+func ParseInt(s string, base int, bitSize int) (i int64, err error) {
+ if bitSize == 0 {
+ bitSize = int(IntSize)
+ }
-// Btoi64 is like Btoui64 but allows signed numbers and
-// returns its result in an int64.
-func Btoi64(s string, base int) (i int64, err error) {
// Empty string bad.
if len(s) == 0 {
return 0, &NumError{s, ErrSyntax}
@@ -157,16 +155,17 @@ func Btoi64(s string, base int) (i int64, err error) {
// Convert unsigned and check range.
var un uint64
- un, err = Btoui64(s, base)
+ un, err = ParseUint(s, base, bitSize)
if err != nil && err.(*NumError).Err != ErrRange {
err.(*NumError).Num = s0
return 0, err
}
- if !neg && un >= 1<<63 {
- return 1<<63 - 1, &NumError{s0, ErrRange}
+ cutoff := uint64(1 << uint(bitSize-1))
+ if !neg && un >= cutoff {
+ return int64(cutoff - 1), &NumError{s0, ErrRange}
}
- if neg && un > 1<<63 {
- return -1 << 63, &NumError{s0, ErrRange}
+ if neg && un > cutoff {
+ return -int64(cutoff), &NumError{s0, ErrRange}
}
n := int64(un)
if neg {
@@ -175,35 +174,8 @@ func Btoi64(s string, base int) (i int64, err error) {
return n, nil
}
-// Atoi64 is like Atoui64 but allows signed numbers and
-// returns its result in an int64.
-func Atoi64(s string) (i int64, err error) { return Btoi64(s, 10) }
-
-// Atoui is like Atoui64 but returns its result as a uint.
-func Atoui(s string) (i uint, err error) {
- i1, e1 := Atoui64(s)
- if e1 != nil && e1.(*NumError).Err != ErrRange {
- return 0, e1
- }
- i = uint(i1)
- if uint64(i) != i1 {
- return ^uint(0), &NumError{s, ErrRange}
- }
- return i, nil
-}
-
-// Atoi is like Atoi64 but returns its result as an int.
+// Atoi is shorthand for ParseInt(s, 10, 0).
func Atoi(s string) (i int, err error) {
- i1, e1 := Atoi64(s)
- if e1 != nil && e1.(*NumError).Err != ErrRange {
- return 0, e1
- }
- i = int(i1)
- if int64(i) != i1 {
- if i1 < 0 {
- return -1 << (IntSize - 1), &NumError{s, ErrRange}
- }
- return 1<<(IntSize-1) - 1, &NumError{s, ErrRange}
- }
- return i, nil
+ i64, err := ParseInt(s, 10, 0)
+ return int(i64), err
}
diff --git a/libgo/go/strconv/atoi_test.go b/libgo/go/strconv/atoi_test.go
index 9ee11b7..2d06efe 100644
--- a/libgo/go/strconv/atoi_test.go
+++ b/libgo/go/strconv/atoi_test.go
@@ -187,10 +187,10 @@ func init() {
}
}
-func TestAtoui64(t *testing.T) {
+func TestParseUint64(t *testing.T) {
for i := range atoui64tests {
test := &atoui64tests[i]
- out, err := Atoui64(test.in)
+ out, err := ParseUint(test.in, 10, 64)
if test.out != out || !reflect.DeepEqual(test.err, err) {
t.Errorf("Atoui64(%q) = %v, %v want %v, %v",
test.in, out, err, test.out, test.err)
@@ -198,21 +198,21 @@ func TestAtoui64(t *testing.T) {
}
}
-func TestBtoui64(t *testing.T) {
+func TestParseUint64Base(t *testing.T) {
for i := range btoui64tests {
test := &btoui64tests[i]
- out, err := Btoui64(test.in, 0)
+ out, err := ParseUint(test.in, 0, 64)
if test.out != out || !reflect.DeepEqual(test.err, err) {
- t.Errorf("Btoui64(%q) = %v, %v want %v, %v",
+ t.Errorf("ParseUint(%q) = %v, %v want %v, %v",
test.in, out, err, test.out, test.err)
}
}
}
-func TestAtoi64(t *testing.T) {
+func TestParseInt64(t *testing.T) {
for i := range atoi64tests {
test := &atoi64tests[i]
- out, err := Atoi64(test.in)
+ out, err := ParseInt(test.in, 10, 64)
if test.out != out || !reflect.DeepEqual(test.err, err) {
t.Errorf("Atoi64(%q) = %v, %v want %v, %v",
test.in, out, err, test.out, test.err)
@@ -220,23 +220,23 @@ func TestAtoi64(t *testing.T) {
}
}
-func TestBtoi64(t *testing.T) {
+func TestParseInt64Base(t *testing.T) {
for i := range btoi64tests {
test := &btoi64tests[i]
- out, err := Btoi64(test.in, 0)
+ out, err := ParseInt(test.in, 0, 64)
if test.out != out || !reflect.DeepEqual(test.err, err) {
- t.Errorf("Btoi64(%q) = %v, %v want %v, %v",
+ t.Errorf("ParseInt(%q) = %v, %v want %v, %v",
test.in, out, err, test.out, test.err)
}
}
}
-func TestAtoui(t *testing.T) {
+func TestParseUint(t *testing.T) {
switch IntSize {
case 32:
for i := range atoui32tests {
test := &atoui32tests[i]
- out, err := Atoui(test.in)
+ out, err := ParseUint(test.in, 10, 0)
if test.out != uint32(out) || !reflect.DeepEqual(test.err, err) {
t.Errorf("Atoui(%q) = %v, %v want %v, %v",
test.in, out, err, test.out, test.err)
@@ -245,7 +245,7 @@ func TestAtoui(t *testing.T) {
case 64:
for i := range atoui64tests {
test := &atoui64tests[i]
- out, err := Atoui(test.in)
+ out, err := ParseUint(test.in, 10, 0)
if test.out != uint64(out) || !reflect.DeepEqual(test.err, err) {
t.Errorf("Atoui(%q) = %v, %v want %v, %v",
test.in, out, err, test.out, test.err)
@@ -254,12 +254,12 @@ func TestAtoui(t *testing.T) {
}
}
-func TestAtoi(t *testing.T) {
+func TestParseInt(t *testing.T) {
switch IntSize {
case 32:
for i := range atoi32tests {
test := &atoi32tests[i]
- out, err := Atoi(test.in)
+ out, err := ParseInt(test.in, 10, 0)
if test.out != int32(out) || !reflect.DeepEqual(test.err, err) {
t.Errorf("Atoi(%q) = %v, %v want %v, %v",
test.in, out, err, test.out, test.err)
@@ -268,7 +268,7 @@ func TestAtoi(t *testing.T) {
case 64:
for i := range atoi64tests {
test := &atoi64tests[i]
- out, err := Atoi(test.in)
+ out, err := ParseInt(test.in, 10, 0)
if test.out != int64(out) || !reflect.DeepEqual(test.err, err) {
t.Errorf("Atoi(%q) = %v, %v want %v, %v",
test.in, out, err, test.out, test.err)
@@ -279,24 +279,24 @@ func TestAtoi(t *testing.T) {
func BenchmarkAtoi(b *testing.B) {
for i := 0; i < b.N; i++ {
- Atoi("12345678")
+ ParseInt("12345678", 10, 0)
}
}
func BenchmarkAtoiNeg(b *testing.B) {
for i := 0; i < b.N; i++ {
- Atoi("-12345678")
+ ParseInt("-12345678", 10, 0)
}
}
func BenchmarkAtoi64(b *testing.B) {
for i := 0; i < b.N; i++ {
- Atoi64("12345678901234")
+ ParseInt("12345678901234", 10, 64)
}
}
func BenchmarkAtoi64Neg(b *testing.B) {
for i := 0; i < b.N; i++ {
- Atoi64("-12345678901234")
+ ParseInt("-12345678901234", 10, 64)
}
}
diff --git a/libgo/go/strconv/fp_test.go b/libgo/go/strconv/fp_test.go
index 9785ca6..47877e3 100644
--- a/libgo/go/strconv/fp_test.go
+++ b/libgo/go/strconv/fp_test.go
@@ -31,7 +31,7 @@ func pow2(i int) float64 {
func myatof64(s string) (f float64, ok bool) {
a := strings.SplitN(s, "p", 2)
if len(a) == 2 {
- n, err := strconv.Atoi64(a[0])
+ n, err := strconv.ParseInt(a[0], 10, 64)
if err != nil {
return 0, false
}
@@ -63,7 +63,7 @@ func myatof64(s string) (f float64, ok bool) {
}
return v * pow2(e), true
}
- f1, err := strconv.Atof64(s)
+ f1, err := strconv.ParseFloat(s, 64)
if err != nil {
return 0, false
}
@@ -87,7 +87,8 @@ func myatof32(s string) (f float32, ok bool) {
}
return float32(float64(n) * pow2(e)), true
}
- f1, err1 := strconv.Atof32(s)
+ f64, err1 := strconv.ParseFloat(s, 32)
+ f1 := float32(f64)
if err1 != nil {
return 0, false
}
diff --git a/libgo/go/strconv/ftoa.go b/libgo/go/strconv/ftoa.go
index 8342b6a..e1ea0a35 100644
--- a/libgo/go/strconv/ftoa.go
+++ b/libgo/go/strconv/ftoa.go
@@ -22,8 +22,10 @@ type floatInfo struct {
var float32info = floatInfo{23, 8, -127}
var float64info = floatInfo{52, 11, -1023}
-// Ftoa32 converts the 32-bit floating-point number f to a string,
-// according to the format fmt and precision prec.
+// FormatFloat converts the floating-point number f to a string,
+// according to the format fmt and precision prec. It rounds the
+// result assuming that the original was obtained from a floating-point
+// value of bitSize bits (32 for float32, 64 for float64).
//
// The format fmt is one of
// 'b' (-ddddp±ddd, a binary exponent),
@@ -43,24 +45,17 @@ var float64info = floatInfo{52, 11, -1023}
// Ftoa32(f) is not the same as Ftoa64(float32(f)),
// because correct rounding and the number of digits
// needed to identify f depend on the precision of the representation.
-func Ftoa32(f float32, fmt byte, prec int) string {
- return genericFtoa(uint64(math.Float32bits(f)), fmt, prec, &float32info)
-}
-
-// Ftoa64 is like Ftoa32 but converts a 64-bit floating-point number.
-func Ftoa64(f float64, fmt byte, prec int) string {
+func FormatFloat(f float64, fmt byte, prec int, n int) string {
+ if n == 32 {
+ return genericFtoa(uint64(math.Float32bits(float32(f))), fmt, prec, &float32info)
+ }
return genericFtoa(math.Float64bits(f), fmt, prec, &float64info)
}
-// FtoaN converts the 64-bit floating-point number f to a string,
-// according to the format fmt and precision prec, but it rounds the
-// result assuming that it was obtained from a floating-point value
-// of n bits (32 or 64).
-func FtoaN(f float64, fmt byte, prec int, n int) string {
- if n == 32 {
- return Ftoa32(float32(f), fmt, prec)
- }
- return Ftoa64(f, fmt, prec)
+// AppendFloat appends the string form of the floating-point number f,
+// as generated by FormatFloat, to dst and returns the extended buffer.
+func AppendFloat(dst []byte, f float64, fmt byte, prec int, n int) []byte {
+ return append(dst, FormatFloat(f, fmt, prec, n)...)
}
func genericFtoa(bits uint64, fmt byte, prec int, flt *floatInfo) string {
diff --git a/libgo/go/strconv/ftoa_test.go b/libgo/go/strconv/ftoa_test.go
index 8bac5da..02206d5 100644
--- a/libgo/go/strconv/ftoa_test.go
+++ b/libgo/go/strconv/ftoa_test.go
@@ -128,47 +128,47 @@ var ftoatests = []ftoaTest{
func TestFtoa(t *testing.T) {
for i := 0; i < len(ftoatests); i++ {
test := &ftoatests[i]
- s := Ftoa64(test.f, test.fmt, test.prec)
- if s != test.s {
- t.Error("test", test.f, string(test.fmt), test.prec, "want", test.s, "got", s)
- }
- s = FtoaN(test.f, test.fmt, test.prec, 64)
+ s := FormatFloat(test.f, test.fmt, test.prec, 64)
if s != test.s {
t.Error("testN=64", test.f, string(test.fmt), test.prec, "want", test.s, "got", s)
}
+ x := AppendFloat([]byte("abc"), test.f, test.fmt, test.prec, 64)
+ if string(x) != "abc"+test.s {
+ t.Error("AppendFloat testN=64", test.f, string(test.fmt), test.prec, "want", "abc"+test.s, "got", string(x))
+ }
if float64(float32(test.f)) == test.f && test.fmt != 'b' {
- s := Ftoa32(float32(test.f), test.fmt, test.prec)
- if s != test.s {
- t.Error("test32", test.f, string(test.fmt), test.prec, "want", test.s, "got", s)
- }
- s = FtoaN(test.f, test.fmt, test.prec, 32)
+ s := FormatFloat(test.f, test.fmt, test.prec, 32)
if s != test.s {
t.Error("testN=32", test.f, string(test.fmt), test.prec, "want", test.s, "got", s)
}
+ x := AppendFloat([]byte("abc"), test.f, test.fmt, test.prec, 32)
+ if string(x) != "abc"+test.s {
+ t.Error("AppendFloat testN=32", test.f, string(test.fmt), test.prec, "want", "abc"+test.s, "got", string(x))
+ }
}
}
}
func BenchmarkFtoa64Decimal(b *testing.B) {
for i := 0; i < b.N; i++ {
- Ftoa64(33909, 'g', -1)
+ FormatFloat(33909, 'g', -1, 64)
}
}
func BenchmarkFtoa64Float(b *testing.B) {
for i := 0; i < b.N; i++ {
- Ftoa64(339.7784, 'g', -1)
+ FormatFloat(339.7784, 'g', -1, 64)
}
}
func BenchmarkFtoa64FloatExp(b *testing.B) {
for i := 0; i < b.N; i++ {
- Ftoa64(-5.09e75, 'g', -1)
+ FormatFloat(-5.09e75, 'g', -1, 64)
}
}
func BenchmarkFtoa64Big(b *testing.B) {
for i := 0; i < b.N; i++ {
- Ftoa64(123456789123456789123456789, 'g', -1)
+ FormatFloat(123456789123456789123456789, 'g', -1, 64)
}
}
diff --git a/libgo/go/strconv/itoa.go b/libgo/go/strconv/itoa.go
index a0a7496..65229f7 100644
--- a/libgo/go/strconv/itoa.go
+++ b/libgo/go/strconv/itoa.go
@@ -4,54 +4,110 @@
package strconv
-// Uitob64 returns the string representation of i in the given base.
-func Uitob64(u uint64, base uint) string {
- if base < 2 || 36 < base {
- panic("invalid base " + Uitoa(base))
- }
- if u == 0 {
- return "0"
- }
+// FormatUint returns the string representation of i in the given base.
+func FormatUint(i uint64, base int) string {
+ _, s := formatBits(nil, i, base, false, false)
+ return s
+}
- // Assemble decimal in reverse order.
- var buf [64]byte
- j := len(buf)
- b := uint64(base)
- for u > 0 {
- j--
- buf[j] = "0123456789abcdefghijklmnopqrstuvwxyz"[u%b]
- u /= b
- }
+// FormatInt returns the string representation of i in the given base.
+func FormatInt(i int64, base int) string {
+ _, s := formatBits(nil, uint64(i), base, i < 0, false)
+ return s
+}
+
+// Itoa is shorthand for FormatInt(i, 10).
+func Itoa(i int) string {
+ return FormatInt(int64(i), 10)
+}
+
+// AppendInt appends the string form of the integer i,
+// as generated by FormatInt, to dst and returns the extended buffer.
+func AppendInt(dst []byte, i int64, base int) []byte {
+ dst, _ = formatBits(dst, uint64(i), base, i < 0, true)
+ return dst
+}
- return string(buf[j:])
+// AppendUint appends the string form of the unsigned integer i,
+// as generated by FormatUint, to dst and returns the extended buffer.
+func AppendUint(dst []byte, i uint64, base int) []byte {
+ dst, _ = formatBits(dst, i, base, false, true)
+ return dst
}
-// Itob64 returns the string representation of i in the given base.
-func Itob64(i int64, base uint) string {
- if i == 0 {
- return "0"
+const digits = "0123456789abcdefghijklmnopqrstuvwxyz"
+
+var shifts = [len(digits) + 1]uint{
+ 1 << 1: 1,
+ 1 << 2: 2,
+ 1 << 3: 3,
+ 1 << 4: 4,
+ 1 << 5: 5,
+}
+
+// formatBits computes the string representation of u in the given base.
+// If negative is set, u is treated as negative int64 value. If append_
+// is set, the string is appended to dst and the resulting byte slice is
+// returned as the first result value; otherwise the string is returned
+// as the second result value.
+//
+func formatBits(dst []byte, u uint64, base int, negative, append_ bool) (d []byte, s string) {
+ if base < 2 || base > len(digits) {
+ panic("invalid base")
}
+ // 2 <= base && base <= len(digits)
- if i < 0 {
- return "-" + Uitob64(-uint64(i), base)
+ var a [64 + 1]byte // +1 for sign of 64bit value in base 2
+ i := len(a)
+
+ if negative {
+ u = -u
}
- return Uitob64(uint64(i), base)
-}
-// Itoa64 returns the decimal string representation of i.
-func Itoa64(i int64) string { return Itob64(i, 10) }
+ // convert bits
+ if base == 10 {
+ // common case: use constant 10 for / and % because
+ // the compiler can optimize it into a multiply+shift
+ for u >= 10 {
+ i--
+ a[i] = digits[u%10]
+ u /= 10
+ }
-// Uitoa64 returns the decimal string representation of i.
-func Uitoa64(i uint64) string { return Uitob64(i, 10) }
+ } else if s := shifts[base]; s > 0 {
+ // base is power of 2: use shifts and masks instead of / and %
+ b := uint64(base)
+ m := uintptr(b) - 1 // == 1<<s - 1
+ for u >= b {
+ i--
+ a[i] = digits[uintptr(u)&m]
+ u >>= s
+ }
-// Uitob returns the string representation of i in the given base.
-func Uitob(i uint, base uint) string { return Uitob64(uint64(i), base) }
+ } else {
+ // general case
+ b := uint64(base)
+ for u >= b {
+ i--
+ a[i] = digits[u%b]
+ u /= b
+ }
+ }
-// Itob returns the string representation of i in the given base.
-func Itob(i int, base uint) string { return Itob64(int64(i), base) }
+ // u < base
+ i--
+ a[i] = digits[uintptr(u)]
-// Itoa returns the decimal string representation of i.
-func Itoa(i int) string { return Itob64(int64(i), 10) }
+ // add sign, if any
+ if negative {
+ i--
+ a[i] = '-'
+ }
-// Uitoa returns the decimal string representation of i.
-func Uitoa(i uint) string { return Uitob64(uint64(i), 10) }
+ if append_ {
+ d = append(dst, a[i:]...)
+ return
+ }
+ s = string(a[i:])
+ return
+}
diff --git a/libgo/go/strconv/itoa_test.go b/libgo/go/strconv/itoa_test.go
index 8514b21..e0213ae 100644
--- a/libgo/go/strconv/itoa_test.go
+++ b/libgo/go/strconv/itoa_test.go
@@ -11,7 +11,7 @@ import (
type itob64Test struct {
in int64
- base uint
+ base int
out string
}
@@ -60,73 +60,43 @@ var itob64tests = []itob64Test{
func TestItoa(t *testing.T) {
for _, test := range itob64tests {
- s := Itob64(test.in, test.base)
+ s := FormatInt(test.in, test.base)
if s != test.out {
- t.Errorf("Itob64(%v, %v) = %v want %v",
+ t.Errorf("FormatInt(%v, %v) = %v want %v",
test.in, test.base, s, test.out)
}
-
- if test.in >= 0 {
- s := Uitob64(uint64(test.in), test.base)
- if s != test.out {
- t.Errorf("Uitob64(%v, %v) = %v want %v",
- test.in, test.base, s, test.out)
- }
+ x := AppendInt([]byte("abc"), test.in, test.base)
+ if string(x) != "abc"+test.out {
+ t.Errorf("AppendInt(%q, %v, %v) = %q want %v",
+ "abc", test.in, test.base, x, test.out)
}
- if int64(int(test.in)) == test.in {
- s := Itob(int(test.in), test.base)
+ if test.in >= 0 {
+ s := FormatUint(uint64(test.in), test.base)
if s != test.out {
- t.Errorf("Itob(%v, %v) = %v want %v",
+ t.Errorf("FormatUint(%v, %v) = %v want %v",
test.in, test.base, s, test.out)
}
-
- if test.in >= 0 {
- s := Uitob(uint(test.in), test.base)
- if s != test.out {
- t.Errorf("Uitob(%v, %v) = %v want %v",
- test.in, test.base, s, test.out)
- }
+ x := AppendUint(nil, uint64(test.in), test.base)
+ if string(x) != test.out {
+ t.Errorf("AppendUint(%q, %v, %v) = %q want %v",
+ "abc", uint64(test.in), test.base, x, test.out)
}
}
- if test.base == 10 {
- s := Itoa64(test.in)
+ if test.base == 10 && int64(int(test.in)) == test.in {
+ s := Itoa(int(test.in))
if s != test.out {
- t.Errorf("Itoa64(%v) = %v want %v",
+ t.Errorf("Itoa(%v) = %v want %v",
test.in, s, test.out)
}
-
- if test.in >= 0 {
- s := Uitob64(uint64(test.in), test.base)
- if s != test.out {
- t.Errorf("Uitob64(%v, %v) = %v want %v",
- test.in, test.base, s, test.out)
- }
- }
-
- if int64(int(test.in)) == test.in {
- s := Itoa(int(test.in))
- if s != test.out {
- t.Errorf("Itoa(%v) = %v want %v",
- test.in, s, test.out)
- }
-
- if test.in >= 0 {
- s := Uitoa(uint(test.in))
- if s != test.out {
- t.Errorf("Uitoa(%v) = %v want %v",
- test.in, s, test.out)
- }
- }
- }
}
}
}
type uitob64Test struct {
in uint64
- base uint
+ base int
out string
}
@@ -141,34 +111,50 @@ var uitob64tests = []uitob64Test{
func TestUitoa(t *testing.T) {
for _, test := range uitob64tests {
- s := Uitob64(test.in, test.base)
+ s := FormatUint(test.in, test.base)
if s != test.out {
- t.Errorf("Uitob64(%v, %v) = %v want %v",
+ t.Errorf("FormatUint(%v, %v) = %v want %v",
test.in, test.base, s, test.out)
}
+ x := AppendUint([]byte("abc"), test.in, test.base)
+ if string(x) != "abc"+test.out {
+ t.Errorf("AppendUint(%q, %v, %v) = %q want %v",
+ "abc", test.in, test.base, x, test.out)
+ }
- if uint64(uint(test.in)) == test.in {
- s := Uitob(uint(test.in), test.base)
- if s != test.out {
- t.Errorf("Uitob(%v, %v) = %v want %v",
- test.in, test.base, s, test.out)
- }
+ }
+}
+
+func BenchmarkFormatInt(b *testing.B) {
+ for i := 0; i < b.N; i++ {
+ for _, test := range itob64tests {
+ FormatInt(test.in, test.base)
}
+ }
+}
- if test.base == 10 {
- s := Uitoa64(test.in)
- if s != test.out {
- t.Errorf("Uitoa64(%v) = %v want %v",
- test.in, s, test.out)
- }
+func BenchmarkAppendInt(b *testing.B) {
+ dst := make([]byte, 0, 30)
+ for i := 0; i < b.N; i++ {
+ for _, test := range itob64tests {
+ AppendInt(dst, test.in, test.base)
+ }
+ }
+}
- if uint64(uint(test.in)) == test.in {
- s := Uitoa(uint(test.in))
- if s != test.out {
- t.Errorf("Uitoa(%v) = %v want %v",
- test.in, s, test.out)
- }
- }
+func BenchmarkFormatUint(b *testing.B) {
+ for i := 0; i < b.N; i++ {
+ for _, test := range uitob64tests {
+ FormatUint(test.in, test.base)
+ }
+ }
+}
+
+func BenchmarkAppendUint(b *testing.B) {
+ dst := make([]byte, 0, 30)
+ for i := 0; i < b.N; i++ {
+ for _, test := range uitob64tests {
+ AppendUint(dst, test.in, test.base)
}
}
}
diff --git a/libgo/go/strconv/quote.go b/libgo/go/strconv/quote.go
index 9b48c07..30b384d 100644
--- a/libgo/go/strconv/quote.go
+++ b/libgo/go/strconv/quote.go
@@ -92,6 +92,12 @@ func Quote(s string) string {
return quoteWith(s, '"', false)
}
+// AppendQuote appends a double-quoted Go string literal representing s,
+// as generated by Quote, to dst and returns the extended buffer.
+func AppendQuote(dst []byte, s string) []byte {
+ return append(dst, Quote(s)...)
+}
+
// QuoteToASCII returns a double-quoted Go string literal representing s.
// The returned string uses Go escape sequences (\t, \n, \xFF, \u0100) for
// non-ASCII characters and non-printable characters as defined by
@@ -100,6 +106,12 @@ func QuoteToASCII(s string) string {
return quoteWith(s, '"', true)
}
+// AppendQuoteToASCII appends a double-quoted Go string literal representing s,
+// as generated by QuoteToASCII, to dst and returns the extended buffer.
+func AppendQuoteToASCII(dst []byte, s string) []byte {
+ return append(dst, QuoteToASCII(s)...)
+}
+
// QuoteRune returns a single-quoted Go character literal representing the
// rune. The returned string uses Go escape sequences (\t, \n, \xFF, \u0100)
// for control characters and non-printable characters as defined by
@@ -109,6 +121,12 @@ func QuoteRune(rune int) string {
return quoteWith(string(rune), '\'', false)
}
+// AppendQuoteRune appends a single-quoted Go character literal representing the rune,
+// as generated by QuoteRune, to dst and returns the extended buffer.
+func AppendQuoteRune(dst []byte, rune int) []byte {
+ return append(dst, QuoteRune(rune)...)
+}
+
// QuoteRuneToASCII returns a single-quoted Go character literal representing
// the rune. The returned string uses Go escape sequences (\t, \n, \xFF,
// \u0100) for non-ASCII characters and non-printable characters as defined
@@ -118,6 +136,12 @@ func QuoteRuneToASCII(rune int) string {
return quoteWith(string(rune), '\'', true)
}
+// AppendQuoteRune appends a single-quoted Go character literal representing the rune,
+// as generated by QuoteRuneToASCII, to dst and returns the extended buffer.
+func AppendQuoteRuneToASCII(dst []byte, rune int) []byte {
+ return append(dst, QuoteRuneToASCII(rune)...)
+}
+
// CanBackquote returns whether the string s would be
// a valid Go string literal if enclosed in backquotes.
func CanBackquote(s string) bool {
diff --git a/libgo/go/strconv/quote_test.go b/libgo/go/strconv/quote_test.go
index 9a59770..e440797 100644
--- a/libgo/go/strconv/quote_test.go
+++ b/libgo/go/strconv/quote_test.go
@@ -29,6 +29,9 @@ func TestQuote(t *testing.T) {
if out := Quote(tt.in); out != tt.out {
t.Errorf("Quote(%s) = %s, want %s", tt.in, out, tt.out)
}
+ if out := AppendQuote([]byte("abc"), tt.in); string(out) != "abc"+tt.out {
+ t.Errorf("AppendQuote(%q, %s) = %s, want %s", "abc", tt.in, out, "abc"+tt.out)
+ }
}
}
@@ -37,6 +40,9 @@ func TestQuoteToASCII(t *testing.T) {
if out := QuoteToASCII(tt.in); out != tt.ascii {
t.Errorf("QuoteToASCII(%s) = %s, want %s", tt.in, out, tt.ascii)
}
+ if out := AppendQuoteToASCII([]byte("abc"), tt.in); string(out) != "abc"+tt.ascii {
+ t.Errorf("AppendQuoteToASCII(%q, %s) = %s, want %s", "abc", tt.in, out, "abc"+tt.ascii)
+ }
}
}
@@ -63,6 +69,9 @@ func TestQuoteRune(t *testing.T) {
if out := QuoteRune(tt.in); out != tt.out {
t.Errorf("QuoteRune(%U) = %s, want %s", tt.in, out, tt.out)
}
+ if out := AppendQuoteRune([]byte("abc"), tt.in); string(out) != "abc"+tt.out {
+ t.Errorf("AppendQuoteRune(%q, %U) = %s, want %s", "abc", tt.in, out, "abc"+tt.out)
+ }
}
}
@@ -71,6 +80,9 @@ func TestQuoteRuneToASCII(t *testing.T) {
if out := QuoteRuneToASCII(tt.in); out != tt.ascii {
t.Errorf("QuoteRuneToASCII(%U) = %s, want %s", tt.in, out, tt.ascii)
}
+ if out := AppendQuoteRuneToASCII([]byte("abc"), tt.in); string(out) != "abc"+tt.ascii {
+ t.Errorf("AppendQuoteRuneToASCII(%q, %U) = %s, want %s", "abc", tt.in, out, "abc"+tt.ascii)
+ }
}
}