diff options
author | Ian Lance Taylor <ian@gcc.gnu.org> | 2016-07-22 18:15:38 +0000 |
---|---|---|
committer | Ian Lance Taylor <ian@gcc.gnu.org> | 2016-07-22 18:15:38 +0000 |
commit | 22b955cca564a9a3a5b8c9d9dd1e295b7943c128 (patch) | |
tree | abdbd898676e1f853fca2d7e031d105d7ebcf676 /libgo/go/strconv | |
parent | 9d04a3af4c6491536badf6bde9707c907e4d196b (diff) | |
download | gcc-22b955cca564a9a3a5b8c9d9dd1e295b7943c128.zip gcc-22b955cca564a9a3a5b8c9d9dd1e295b7943c128.tar.gz gcc-22b955cca564a9a3a5b8c9d9dd1e295b7943c128.tar.bz2 |
libgo: update to go1.7rc3
Reviewed-on: https://go-review.googlesource.com/25150
From-SVN: r238662
Diffstat (limited to 'libgo/go/strconv')
-rw-r--r-- | libgo/go/strconv/atob.go | 2 | ||||
-rw-r--r-- | libgo/go/strconv/atof.go | 13 | ||||
-rw-r--r-- | libgo/go/strconv/atof_test.go | 26 | ||||
-rw-r--r-- | libgo/go/strconv/atoi.go | 14 | ||||
-rw-r--r-- | libgo/go/strconv/atoi_test.go | 2 | ||||
-rw-r--r-- | libgo/go/strconv/extfloat.go | 4 | ||||
-rw-r--r-- | libgo/go/strconv/fp_test.go | 2 | ||||
-rw-r--r-- | libgo/go/strconv/ftoa.go | 2 | ||||
-rw-r--r-- | libgo/go/strconv/ftoa_test.go | 85 | ||||
-rw-r--r-- | libgo/go/strconv/isprint.go | 82 | ||||
-rw-r--r-- | libgo/go/strconv/makeisprint.go | 2 | ||||
-rw-r--r-- | libgo/go/strconv/quote.go | 150 | ||||
-rw-r--r-- | libgo/go/strconv/quote_test.go | 28 |
13 files changed, 250 insertions, 162 deletions
diff --git a/libgo/go/strconv/atob.go b/libgo/go/strconv/atob.go index d0cb097..879ceb3 100644 --- a/libgo/go/strconv/atob.go +++ b/libgo/go/strconv/atob.go @@ -7,7 +7,7 @@ package strconv // 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 ParseBool(str string) (value bool, err error) { +func ParseBool(str string) (bool, error) { switch str { case "1", "t", "T", "true", "TRUE", "True": return true, nil diff --git a/libgo/go/strconv/atof.go b/libgo/go/strconv/atof.go index a4f4862..fdcb8b3 100644 --- a/libgo/go/strconv/atof.go +++ b/libgo/go/strconv/atof.go @@ -245,7 +245,9 @@ func readFloat(s string) (mantissa uint64, exp int, neg, trunc, ok bool) { return } - exp = dp - ndMant + if mantissa != 0 { + exp = dp - ndMant + } ok = true return @@ -534,11 +536,10 @@ func atof64(s string) (f float64, err error) { // 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.Err = ErrRange. -func ParseFloat(s string, bitSize int) (f float64, err error) { +func ParseFloat(s string, bitSize int) (float64, error) { if bitSize == 32 { - f1, err1 := atof32(s) - return float64(f1), err1 + f, err := atof32(s) + return float64(f), err } - f1, err1 := atof64(s) - return f1, err1 + return atof64(s) } diff --git a/libgo/go/strconv/atof_test.go b/libgo/go/strconv/atof_test.go index ba493321..0a89c3e 100644 --- a/libgo/go/strconv/atof_test.go +++ b/libgo/go/strconv/atof_test.go @@ -42,6 +42,30 @@ var atoftests = []atofTest{ {"1e-20", "1e-20", nil}, {"625e-3", "0.625", nil}, + // zeros + {"0", "0", nil}, + {"0e0", "0", nil}, + {"-0e0", "-0", nil}, + {"+0e0", "0", nil}, + {"0e-0", "0", nil}, + {"-0e-0", "-0", nil}, + {"+0e-0", "0", nil}, + {"0e+0", "0", nil}, + {"-0e+0", "-0", nil}, + {"+0e+0", "0", nil}, + {"0e+01234567890123456789", "0", nil}, + {"0.00e-01234567890123456789", "0", nil}, + {"-0e+01234567890123456789", "-0", nil}, + {"-0.00e-01234567890123456789", "-0", nil}, + {"0e291", "0", nil}, // issue 15364 + {"0e292", "0", nil}, // issue 15364 + {"0e347", "0", nil}, // issue 15364 + {"0e348", "0", nil}, // issue 15364 + {"-0e291", "-0", nil}, + {"-0e292", "-0", nil}, + {"-0e347", "-0", nil}, + {"-0e348", "-0", nil}, + // NaNs {"nan", "NaN", nil}, {"NaN", "NaN", nil}, @@ -196,7 +220,7 @@ var ( func init() { // The atof routines return NumErrors wrapping - // the error and the string. Convert the table above. + // the error and the string. Convert the table above. for i := range atoftests { test := &atoftests[i] if test.err != nil { diff --git a/libgo/go/strconv/atoi.go b/libgo/go/strconv/atoi.go index 965e3a2..a236de4 100644 --- a/libgo/go/strconv/atoi.go +++ b/libgo/go/strconv/atoi.go @@ -39,7 +39,9 @@ const IntSize = intSize const maxUint64 = (1<<64 - 1) // ParseUint is like ParseInt but for unsigned numbers. -func ParseUint(s string, base int, bitSize int) (n uint64, err error) { +func ParseUint(s string, base int, bitSize int) (uint64, error) { + var n uint64 + var err error var cutoff, maxVal uint64 if bitSize == 0 { @@ -136,16 +138,16 @@ Error: } // ParseInt interprets a string s in the given base (2 to 36) and -// returns the corresponding value i. If base == 0, the base is +// returns the corresponding value i. If base == 0, the base is // implied by the string's prefix: base 16 for "0x", base 8 for // "0", and base 10 otherwise. // // The bitSize argument specifies the integer type -// that the result must fit into. Bit sizes 0, 8, 16, 32, and 64 +// 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 +// and include err.Num = s. If s is empty or contains invalid // digits, err.Err = ErrSyntax and the returned value is 0; // if the value corresponding to s cannot be represented by a // signed integer of the given size, err.Err = ErrRange and the @@ -195,8 +197,8 @@ func ParseInt(s string, base int, bitSize int) (i int64, err error) { return n, nil } -// Atoi is shorthand for ParseInt(s, 10, 0). -func Atoi(s string) (i int, err error) { +// Atoi returns the result of ParseInt(s, 10, 0) converted to type int. +func Atoi(s string) (int, error) { 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 bd6a6a0..d608505 100644 --- a/libgo/go/strconv/atoi_test.go +++ b/libgo/go/strconv/atoi_test.go @@ -196,7 +196,7 @@ var numErrorTests = []numErrorTest{ func init() { // The atoi routines return NumErrors wrapping - // the error and the string. Convert the tables above. + // the error and the string. Convert the tables above. for i := range atoui64tests { test := &atoui64tests[i] if test.err != nil { diff --git a/libgo/go/strconv/extfloat.go b/libgo/go/strconv/extfloat.go index 019b4ee..7033e96 100644 --- a/libgo/go/strconv/extfloat.go +++ b/libgo/go/strconv/extfloat.go @@ -311,9 +311,9 @@ func (f *extFloat) AssignDecimal(mantissa uint64, exp10 int, neg bool, trunc boo var extrabits uint if f.exp <= denormalExp { // f.mant * 2^f.exp is smaller than 2^(flt.bias+1). - extrabits = uint(63 - flt.mantbits + 1 + uint(denormalExp-f.exp)) + extrabits = 63 - flt.mantbits + 1 + uint(denormalExp-f.exp) } else { - extrabits = uint(63 - flt.mantbits) + extrabits = 63 - flt.mantbits } halfway := uint64(1) << (extrabits - 1) diff --git a/libgo/go/strconv/fp_test.go b/libgo/go/strconv/fp_test.go index 6de2f8b..39dd9c4 100644 --- a/libgo/go/strconv/fp_test.go +++ b/libgo/go/strconv/fp_test.go @@ -41,7 +41,7 @@ func myatof64(s string) (f float64, ok bool) { } v := float64(n) // We expect that v*pow2(e) fits in a float64, - // but pow2(e) by itself may not. Be careful. + // but pow2(e) by itself may not. Be careful. if e <= -1000 { v *= pow2(-1000) e += 1000 diff --git a/libgo/go/strconv/ftoa.go b/libgo/go/strconv/ftoa.go index 9ff5d10..8b3d33e 100644 --- a/libgo/go/strconv/ftoa.go +++ b/libgo/go/strconv/ftoa.go @@ -23,7 +23,7 @@ var float32info = floatInfo{23, 8, -127} var float64info = floatInfo{52, 11, -1023} // FormatFloat converts the floating-point number f to a string, -// according to the format fmt and precision prec. It rounds the +// 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). // diff --git a/libgo/go/strconv/ftoa_test.go b/libgo/go/strconv/ftoa_test.go index 0b9f0fe..1d25242 100644 --- a/libgo/go/strconv/ftoa_test.go +++ b/libgo/go/strconv/ftoa_test.go @@ -183,59 +183,50 @@ func TestFtoaRandom(t *testing.T) { } } -func BenchmarkFormatFloatDecimal(b *testing.B) { - for i := 0; i < b.N; i++ { - FormatFloat(33909, 'g', -1, 64) - } +var ftoaBenches = []struct { + name string + float float64 + fmt byte + prec int + bitSize int +}{ + {"Decimal", 33909, 'g', -1, 64}, + {"Float", 339.7784, 'g', -1, 64}, + {"Exp", -5.09e75, 'g', -1, 64}, + {"NegExp", -5.11e-95, 'g', -1, 64}, + + {"Big", 123456789123456789123456789, 'g', -1, 64}, + {"BinaryExp", -1, 'b', -1, 64}, + + {"32Integer", 33909, 'g', -1, 32}, + {"32ExactFraction", 3.375, 'g', -1, 32}, + {"32Point", 339.7784, 'g', -1, 32}, + {"32Exp", -5.09e25, 'g', -1, 32}, + {"32NegExp", -5.11e-25, 'g', -1, 32}, + + {"64Fixed1", 123456, 'e', 3, 64}, + {"64Fixed2", 123.456, 'e', 3, 64}, + {"64Fixed3", 1.23456e+78, 'e', 3, 64}, + {"64Fixed4", 1.23456e-78, 'e', 3, 64}, } func BenchmarkFormatFloat(b *testing.B) { - for i := 0; i < b.N; i++ { - FormatFloat(339.7784, 'g', -1, 64) - } -} - -func BenchmarkFormatFloatExp(b *testing.B) { - for i := 0; i < b.N; i++ { - FormatFloat(-5.09e75, 'g', -1, 64) - } -} - -func BenchmarkFormatFloatNegExp(b *testing.B) { - for i := 0; i < b.N; i++ { - FormatFloat(-5.11e-95, 'g', -1, 64) - } -} - -func BenchmarkFormatFloatBig(b *testing.B) { - for i := 0; i < b.N; i++ { - FormatFloat(123456789123456789123456789, 'g', -1, 64) + for _, c := range ftoaBenches { + b.Run(c.name, func(b *testing.B) { + for i := 0; i < b.N; i++ { + FormatFloat(c.float, c.fmt, c.prec, c.bitSize) + } + }) } } -func benchmarkAppendFloat(b *testing.B, f float64, fmt byte, prec, bitSize int) { +func BenchmarkAppendFloat(b *testing.B) { dst := make([]byte, 30) - for i := 0; i < b.N; i++ { - AppendFloat(dst[:0], f, fmt, prec, bitSize) + for _, c := range ftoaBenches { + b.Run(c.name, func(b *testing.B) { + for i := 0; i < b.N; i++ { + AppendFloat(dst[:0], c.float, c.fmt, c.prec, c.bitSize) + } + }) } } - -func BenchmarkAppendFloatDecimal(b *testing.B) { benchmarkAppendFloat(b, 33909, 'g', -1, 64) } -func BenchmarkAppendFloat(b *testing.B) { benchmarkAppendFloat(b, 339.7784, 'g', -1, 64) } -func BenchmarkAppendFloatExp(b *testing.B) { benchmarkAppendFloat(b, -5.09e75, 'g', -1, 64) } -func BenchmarkAppendFloatNegExp(b *testing.B) { benchmarkAppendFloat(b, -5.11e-95, 'g', -1, 64) } -func BenchmarkAppendFloatBig(b *testing.B) { - benchmarkAppendFloat(b, 123456789123456789123456789, 'g', -1, 64) -} -func BenchmarkAppendFloatBinaryExp(b *testing.B) { benchmarkAppendFloat(b, -1, 'b', -1, 64) } - -func BenchmarkAppendFloat32Integer(b *testing.B) { benchmarkAppendFloat(b, 33909, 'g', -1, 32) } -func BenchmarkAppendFloat32ExactFraction(b *testing.B) { benchmarkAppendFloat(b, 3.375, 'g', -1, 32) } -func BenchmarkAppendFloat32Point(b *testing.B) { benchmarkAppendFloat(b, 339.7784, 'g', -1, 32) } -func BenchmarkAppendFloat32Exp(b *testing.B) { benchmarkAppendFloat(b, -5.09e25, 'g', -1, 32) } -func BenchmarkAppendFloat32NegExp(b *testing.B) { benchmarkAppendFloat(b, -5.11e-25, 'g', -1, 32) } - -func BenchmarkAppendFloat64Fixed1(b *testing.B) { benchmarkAppendFloat(b, 123456, 'e', 3, 64) } -func BenchmarkAppendFloat64Fixed2(b *testing.B) { benchmarkAppendFloat(b, 123.456, 'e', 3, 64) } -func BenchmarkAppendFloat64Fixed3(b *testing.B) { benchmarkAppendFloat(b, 1.23456e+78, 'e', 3, 64) } -func BenchmarkAppendFloat64Fixed4(b *testing.B) { benchmarkAppendFloat(b, 1.23456e-78, 'e', 3, 64) } diff --git a/libgo/go/strconv/isprint.go b/libgo/go/strconv/isprint.go index 20a02de..a30d8d8 100644 --- a/libgo/go/strconv/isprint.go +++ b/libgo/go/strconv/isprint.go @@ -7,7 +7,7 @@ package strconv -// (470+136+73)*2 + (342)*4 = 2726 bytes +// (462+139+82)*2 + (378)*4 = 2878 bytes var isPrint16 = []uint16{ 0x0020, 0x007e, @@ -26,8 +26,8 @@ var isPrint16 = []uint16{ 0x0800, 0x082d, 0x0830, 0x085b, 0x085e, 0x085e, - 0x08a0, 0x08b4, - 0x08e3, 0x098c, + 0x08a0, 0x08bd, + 0x08d4, 0x098c, 0x098f, 0x0990, 0x0993, 0x09b2, 0x09b6, 0x09b9, @@ -83,11 +83,9 @@ var isPrint16 = []uint16{ 0x0cde, 0x0ce3, 0x0ce6, 0x0cf2, 0x0d01, 0x0d3a, - 0x0d3d, 0x0d4e, - 0x0d57, 0x0d57, - 0x0d5f, 0x0d63, - 0x0d66, 0x0d75, - 0x0d79, 0x0d7f, + 0x0d3d, 0x0d4f, + 0x0d54, 0x0d63, + 0x0d66, 0x0d7f, 0x0d82, 0x0d96, 0x0d9a, 0x0dbd, 0x0dc0, 0x0dc6, @@ -153,11 +151,11 @@ var isPrint16 = []uint16{ 0x1b80, 0x1bf3, 0x1bfc, 0x1c37, 0x1c3b, 0x1c49, - 0x1c4d, 0x1c7f, + 0x1c4d, 0x1c88, 0x1cc0, 0x1cc7, 0x1cd0, 0x1cf9, 0x1d00, 0x1df5, - 0x1dfc, 0x1f15, + 0x1dfb, 0x1f15, 0x1f18, 0x1f1d, 0x1f20, 0x1f45, 0x1f48, 0x1f4d, @@ -172,8 +170,7 @@ var isPrint16 = []uint16{ 0x20a0, 0x20be, 0x20d0, 0x20f0, 0x2100, 0x218b, - 0x2190, 0x23fa, - 0x2400, 0x2426, + 0x2190, 0x2426, 0x2440, 0x244a, 0x2460, 0x2b73, 0x2b76, 0x2b95, @@ -186,7 +183,7 @@ var isPrint16 = []uint16{ 0x2d30, 0x2d67, 0x2d6f, 0x2d70, 0x2d7f, 0x2d96, - 0x2da0, 0x2e42, + 0x2da0, 0x2e44, 0x2e80, 0x2ef3, 0x2f00, 0x2fd5, 0x2ff0, 0x2ffb, @@ -201,12 +198,11 @@ var isPrint16 = []uint16{ 0xa490, 0xa4c6, 0xa4d0, 0xa62b, 0xa640, 0xa6f7, - 0xa700, 0xa7ad, - 0xa7b0, 0xa7b7, + 0xa700, 0xa7b7, 0xa7f7, 0xa82b, 0xa830, 0xa839, 0xa840, 0xa877, - 0xa880, 0xa8c4, + 0xa880, 0xa8c5, 0xa8ce, 0xa8d9, 0xa8e0, 0xa8fd, 0xa900, 0xa953, @@ -258,6 +254,8 @@ var isNotPrint16 = []uint16{ 0x0590, 0x06dd, 0x083f, + 0x08b5, + 0x08e2, 0x0984, 0x09a9, 0x09b1, @@ -294,7 +292,6 @@ var isNotPrint16 = []uint16{ 0x0c45, 0x0c49, 0x0c57, - 0x0c80, 0x0c84, 0x0c8d, 0x0c91, @@ -354,6 +351,7 @@ var isNotPrint16 = []uint16{ 0x1fdc, 0x1ff5, 0x208f, + 0x23ff, 0x2bc9, 0x2c2f, 0x2c5f, @@ -371,6 +369,7 @@ var isNotPrint16 = []uint16{ 0x318f, 0x321f, 0x32ff, + 0xa7af, 0xa9ce, 0xa9ff, 0xab27, @@ -392,8 +391,7 @@ var isPrint32 = []uint32{ 0x010080, 0x0100fa, 0x010100, 0x010102, 0x010107, 0x010133, - 0x010137, 0x01018c, - 0x010190, 0x01019b, + 0x010137, 0x01019b, 0x0101a0, 0x0101a0, 0x0101d0, 0x0101fd, 0x010280, 0x01029c, @@ -406,6 +404,8 @@ var isPrint32 = []uint32{ 0x0103c8, 0x0103d5, 0x010400, 0x01049d, 0x0104a0, 0x0104a9, + 0x0104b0, 0x0104d3, + 0x0104d8, 0x0104fb, 0x010500, 0x010527, 0x010530, 0x010563, 0x01056f, 0x01056f, @@ -451,7 +451,7 @@ var isPrint32 = []uint32{ 0x011150, 0x011176, 0x011180, 0x0111cd, 0x0111d0, 0x0111f4, - 0x011200, 0x01123d, + 0x011200, 0x01123e, 0x011280, 0x0112a9, 0x0112b0, 0x0112ea, 0x0112f0, 0x0112f9, @@ -466,12 +466,14 @@ var isPrint32 = []uint32{ 0x01135d, 0x011363, 0x011366, 0x01136c, 0x011370, 0x011374, + 0x011400, 0x01145d, 0x011480, 0x0114c7, 0x0114d0, 0x0114d9, 0x011580, 0x0115b5, 0x0115b8, 0x0115dd, 0x011600, 0x011644, 0x011650, 0x011659, + 0x011660, 0x01166c, 0x011680, 0x0116b7, 0x0116c0, 0x0116c9, 0x011700, 0x011719, @@ -480,6 +482,10 @@ var isPrint32 = []uint32{ 0x0118a0, 0x0118f2, 0x0118ff, 0x0118ff, 0x011ac0, 0x011af8, + 0x011c00, 0x011c45, + 0x011c50, 0x011c6c, + 0x011c70, 0x011c8f, + 0x011c92, 0x011cb6, 0x012000, 0x012399, 0x012400, 0x012474, 0x012480, 0x012543, @@ -496,6 +502,9 @@ var isPrint32 = []uint32{ 0x016f00, 0x016f44, 0x016f50, 0x016f7e, 0x016f8f, 0x016f9f, + 0x016fe0, 0x016fe0, + 0x017000, 0x0187ec, + 0x018800, 0x018af2, 0x01b000, 0x01b001, 0x01bc00, 0x01bc6a, 0x01bc70, 0x01bc7c, @@ -518,8 +527,13 @@ var isPrint32 = []uint32{ 0x01d6a8, 0x01d7cb, 0x01d7ce, 0x01da8b, 0x01da9b, 0x01daaf, + 0x01e000, 0x01e018, + 0x01e01b, 0x01e02a, 0x01e800, 0x01e8c4, 0x01e8c7, 0x01e8d6, + 0x01e900, 0x01e94a, + 0x01e950, 0x01e959, + 0x01e95e, 0x01e95f, 0x01ee00, 0x01ee24, 0x01ee27, 0x01ee3b, 0x01ee42, 0x01ee42, @@ -534,14 +548,14 @@ var isPrint32 = []uint32{ 0x01f0b1, 0x01f0f5, 0x01f100, 0x01f10c, 0x01f110, 0x01f16b, - 0x01f170, 0x01f19a, + 0x01f170, 0x01f1ac, 0x01f1e6, 0x01f202, - 0x01f210, 0x01f23a, + 0x01f210, 0x01f23b, 0x01f240, 0x01f248, 0x01f250, 0x01f251, - 0x01f300, 0x01f6d0, + 0x01f300, 0x01f6d2, 0x01f6e0, 0x01f6ec, - 0x01f6f0, 0x01f6f3, + 0x01f6f0, 0x01f6f6, 0x01f700, 0x01f773, 0x01f780, 0x01f7d4, 0x01f800, 0x01f80b, @@ -549,8 +563,11 @@ var isPrint32 = []uint32{ 0x01f850, 0x01f859, 0x01f860, 0x01f887, 0x01f890, 0x01f8ad, - 0x01f910, 0x01f918, - 0x01f980, 0x01f984, + 0x01f910, 0x01f927, + 0x01f930, 0x01f930, + 0x01f933, 0x01f94b, + 0x01f950, 0x01f95e, + 0x01f980, 0x01f991, 0x01f9c0, 0x01f9c0, 0x020000, 0x02a6d6, 0x02a700, 0x02b734, @@ -565,6 +582,7 @@ var isNotPrint32 = []uint16{ // add 0x10000 to each entry 0x0027, 0x003b, 0x003e, + 0x018f, 0x039e, 0x0809, 0x0836, @@ -585,6 +603,11 @@ var isNotPrint32 = []uint16{ // add 0x10000 to each entry 0x1329, 0x1331, 0x1334, + 0x145a, + 0x145c, + 0x1c09, + 0x1c37, + 0x1ca8, 0x246f, 0x6a5f, 0x6b5a, @@ -603,6 +626,9 @@ var isNotPrint32 = []uint16{ // add 0x10000 to each entry 0xd545, 0xd551, 0xdaa0, + 0xe007, + 0xe022, + 0xe025, 0xee04, 0xee20, 0xee23, @@ -632,8 +658,8 @@ var isNotPrint32 = []uint16{ // add 0x10000 to each entry 0xf0c0, 0xf0d0, 0xf12f, - 0xf57a, - 0xf5a4, + 0xf91f, + 0xf93f, } // isGraphic lists the graphic runes not matched by IsPrint. diff --git a/libgo/go/strconv/makeisprint.go b/libgo/go/strconv/makeisprint.go index 5142580..0a3e5b2 100644 --- a/libgo/go/strconv/makeisprint.go +++ b/libgo/go/strconv/makeisprint.go @@ -1,4 +1,4 @@ -// Copyright 2012 The Go Authors. All rights reserved. +// Copyright 2012 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. diff --git a/libgo/go/strconv/quote.go b/libgo/go/strconv/quote.go index 40d0667..becfe1d 100644 --- a/libgo/go/strconv/quote.go +++ b/libgo/go/strconv/quote.go @@ -6,15 +6,19 @@ package strconv -import ( - "unicode/utf8" -) +import "unicode/utf8" const lowerhex = "0123456789abcdef" func quoteWith(s string, quote byte, ASCIIonly, graphicOnly bool) string { - var runeTmp [utf8.UTFMax]byte - buf := make([]byte, 0, 3*len(s)/2) // Try to avoid more allocations. + return string(appendQuotedWith(make([]byte, 0, 3*len(s)/2), s, quote, ASCIIonly, graphicOnly)) +} + +func quoteRuneWith(r rune, quote byte, ASCIIonly, graphicOnly bool) string { + return string(appendQuotedRuneWith(nil, r, quote, ASCIIonly, graphicOnly)) +} + +func appendQuotedWith(buf []byte, s string, quote byte, ASCIIonly, graphicOnly bool) []byte { buf = append(buf, quote) for width := 0; len(s) > 0; s = s[width:] { r := rune(s[0]) @@ -28,64 +32,79 @@ func quoteWith(s string, quote byte, ASCIIonly, graphicOnly bool) string { buf = append(buf, lowerhex[s[0]&0xF]) continue } - if r == rune(quote) || r == '\\' { // always backslashed - buf = append(buf, '\\') + buf = appendEscapedRune(buf, r, width, quote, ASCIIonly, graphicOnly) + } + buf = append(buf, quote) + return buf +} + +func appendQuotedRuneWith(buf []byte, r rune, quote byte, ASCIIonly, graphicOnly bool) []byte { + buf = append(buf, quote) + if !utf8.ValidRune(r) { + r = utf8.RuneError + } + buf = appendEscapedRune(buf, r, utf8.RuneLen(r), quote, ASCIIonly, graphicOnly) + buf = append(buf, quote) + return buf +} + +func appendEscapedRune(buf []byte, r rune, width int, quote byte, ASCIIonly, graphicOnly bool) []byte { + var runeTmp [utf8.UTFMax]byte + if r == rune(quote) || r == '\\' { // always backslashed + buf = append(buf, '\\') + buf = append(buf, byte(r)) + return buf + } + if ASCIIonly { + if r < utf8.RuneSelf && IsPrint(r) { buf = append(buf, byte(r)) - continue + return buf } - if ASCIIonly { - if r < utf8.RuneSelf && IsPrint(r) { - buf = append(buf, byte(r)) - continue + } else if IsPrint(r) || graphicOnly && isInGraphicList(r) { + n := utf8.EncodeRune(runeTmp[:], r) + buf = append(buf, runeTmp[:n]...) + return buf + } + switch r { + case '\a': + buf = append(buf, `\a`...) + case '\b': + buf = append(buf, `\b`...) + case '\f': + buf = append(buf, `\f`...) + case '\n': + buf = append(buf, `\n`...) + case '\r': + buf = append(buf, `\r`...) + case '\t': + buf = append(buf, `\t`...) + case '\v': + buf = append(buf, `\v`...) + default: + switch { + case r < ' ': + buf = append(buf, `\x`...) + buf = append(buf, lowerhex[byte(r)>>4]) + buf = append(buf, lowerhex[byte(r)&0xF]) + case r > utf8.MaxRune: + r = 0xFFFD + fallthrough + case r < 0x10000: + buf = append(buf, `\u`...) + for s := 12; s >= 0; s -= 4 { + buf = append(buf, lowerhex[r>>uint(s)&0xF]) } - } else if IsPrint(r) || graphicOnly && isInGraphicList(r) { - n := utf8.EncodeRune(runeTmp[:], r) - buf = append(buf, runeTmp[:n]...) - continue - } - switch r { - case '\a': - buf = append(buf, `\a`...) - case '\b': - buf = append(buf, `\b`...) - case '\f': - buf = append(buf, `\f`...) - case '\n': - buf = append(buf, `\n`...) - case '\r': - buf = append(buf, `\r`...) - case '\t': - buf = append(buf, `\t`...) - case '\v': - buf = append(buf, `\v`...) default: - switch { - case r < ' ': - buf = append(buf, `\x`...) - buf = append(buf, lowerhex[s[0]>>4]) - buf = append(buf, lowerhex[s[0]&0xF]) - case r > utf8.MaxRune: - r = 0xFFFD - fallthrough - case r < 0x10000: - buf = append(buf, `\u`...) - for s := 12; s >= 0; s -= 4 { - buf = append(buf, lowerhex[r>>uint(s)&0xF]) - } - default: - buf = append(buf, `\U`...) - for s := 28; s >= 0; s -= 4 { - buf = append(buf, lowerhex[r>>uint(s)&0xF]) - } + buf = append(buf, `\U`...) + for s := 28; s >= 0; s -= 4 { + buf = append(buf, lowerhex[r>>uint(s)&0xF]) } } } - buf = append(buf, quote) - return string(buf) - + return buf } -// Quote returns a double-quoted Go string literal representing s. The +// Quote returns a double-quoted Go string literal representing s. The // returned string uses Go escape sequences (\t, \n, \xFF, \u0100) for // control characters and non-printable characters as defined by // IsPrint. @@ -96,7 +115,7 @@ func Quote(s string) string { // 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)...) + return appendQuotedWith(dst, s, '"', false, false) } // QuoteToASCII returns a double-quoted Go string literal representing s. @@ -109,7 +128,7 @@ func QuoteToASCII(s string) string { // 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)...) + return appendQuotedWith(dst, s, '"', true, false) } // QuoteToGraphic returns a double-quoted Go string literal representing s. @@ -122,21 +141,20 @@ func QuoteToGraphic(s string) string { // AppendQuoteToGraphic appends a double-quoted Go string literal representing s, // as generated by QuoteToGraphic, to dst and returns the extended buffer. func AppendQuoteToGraphic(dst []byte, s string) []byte { - return append(dst, QuoteToGraphic(s)...) + return appendQuotedWith(dst, s, '"', false, true) } // 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 IsPrint. func QuoteRune(r rune) string { - // TODO: avoid the allocation here. - return quoteWith(string(r), '\'', false, false) + return quoteRuneWith(r, '\'', false, 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, r rune) []byte { - return append(dst, QuoteRune(r)...) + return appendQuotedRuneWith(dst, r, '\'', false, false) } // QuoteRuneToASCII returns a single-quoted Go character literal representing @@ -144,14 +162,13 @@ func AppendQuoteRune(dst []byte, r rune) []byte { // \u0100) for non-ASCII characters and non-printable characters as defined // by IsPrint. func QuoteRuneToASCII(r rune) string { - // TODO: avoid the allocation here. - return quoteWith(string(r), '\'', true, false) + return quoteRuneWith(r, '\'', true, false) } // AppendQuoteRuneToASCII 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, r rune) []byte { - return append(dst, QuoteRuneToASCII(r)...) + return appendQuotedRuneWith(dst, r, '\'', true, false) } // QuoteRuneToGraphic returns a single-quoted Go character literal representing @@ -159,14 +176,13 @@ func AppendQuoteRuneToASCII(dst []byte, r rune) []byte { // \u0100) for non-ASCII characters and non-printable characters as defined // by IsGraphic. func QuoteRuneToGraphic(r rune) string { - // TODO: avoid the allocation here. - return quoteWith(string(r), '\'', false, true) + return quoteRuneWith(r, '\'', false, true) } // AppendQuoteRuneToGraphic appends a single-quoted Go character literal representing the rune, // as generated by QuoteRuneToGraphic, to dst and returns the extended buffer. func AppendQuoteRuneToGraphic(dst []byte, r rune) []byte { - return append(dst, QuoteRuneToGraphic(r)...) + return appendQuotedRuneWith(dst, r, '\'', false, true) } // CanBackquote reports whether the string s can be represented @@ -331,7 +347,7 @@ func UnquoteChar(s string, quote byte) (value rune, multibyte bool, tail string, // that s quotes. (If s is single-quoted, it would be a Go // character literal; Unquote returns the corresponding // one-character string.) -func Unquote(s string) (t string, err error) { +func Unquote(s string) (string, error) { n := len(s) if n < 2 { return "", ErrSyntax diff --git a/libgo/go/strconv/quote_test.go b/libgo/go/strconv/quote_test.go index 3e8ec2c..10735e3 100644 --- a/libgo/go/strconv/quote_test.go +++ b/libgo/go/strconv/quote_test.go @@ -89,6 +89,34 @@ func TestQuoteToGraphic(t *testing.T) { } } +func BenchmarkQuote(b *testing.B) { + for i := 0; i < b.N; i++ { + Quote("\a\b\f\r\n\t\v\a\b\f\r\n\t\v\a\b\f\r\n\t\v") + } +} + +func BenchmarkQuoteRune(b *testing.B) { + for i := 0; i < b.N; i++ { + QuoteRune('\a') + } +} + +var benchQuoteBuf []byte + +func BenchmarkAppendQuote(b *testing.B) { + for i := 0; i < b.N; i++ { + benchQuoteBuf = AppendQuote(benchQuoteBuf[:0], "\a\b\f\r\n\t\v\a\b\f\r\n\t\v\a\b\f\r\n\t\v") + } +} + +var benchQuoteRuneBuf []byte + +func BenchmarkAppendQuoteRune(b *testing.B) { + for i := 0; i < b.N; i++ { + benchQuoteRuneBuf = AppendQuoteRune(benchQuoteRuneBuf[:0], '\a') + } +} + type quoteRuneTest struct { in rune out string |