Skip to content

Commit b2a346b

Browse files
committed
strconv: move all but Quote to internal/strconv
This will let low-level things depend on the canonical routines, even for floating-point printing. Change-Id: I31207dc6584ad90d4e365dbe6eaf20f8662ed22d Reviewed-on: https://go-review.googlesource.com/c/go/+/716000 Reviewed-by: David Chase <drchase@google.com> LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
1 parent 041f564 commit b2a346b

32 files changed

+1439
-321
lines changed

src/go/build/deps_test.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ var depsRules = `
6969
7070
internal/goarch < internal/abi;
7171
internal/byteorder, internal/cpu, internal/goarch < internal/chacha8rand;
72+
internal/goarch, math/bits < internal/strconv;
7273
7374
# RUNTIME is the core runtime group of packages, all of them very light-weight.
7475
internal/abi,
@@ -80,6 +81,7 @@ var depsRules = `
8081
internal/goexperiment,
8182
internal/goos,
8283
internal/profilerecord,
84+
internal/strconv,
8385
internal/trace/tracev2,
8486
math/bits,
8587
structs

src/strconv/atob.go renamed to src/internal/strconv/atob.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ func ParseBool(str string) (bool, error) {
1414
case "0", "f", "F", "false", "FALSE", "False":
1515
return false, nil
1616
}
17-
return false, syntaxError("ParseBool", str)
17+
return false, ErrSyntax
1818
}
1919

2020
// FormatBool returns "true" or "false" according to the value of b.

src/strconv/atob_test.go renamed to src/internal/strconv/atob_test.go

Lines changed: 3 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ package strconv_test
66

77
import (
88
"bytes"
9-
. "strconv"
9+
. "internal/strconv"
1010
"testing"
1111
)
1212

@@ -36,23 +36,8 @@ var atobtests = []atobTest{
3636
func TestParseBool(t *testing.T) {
3737
for _, test := range atobtests {
3838
b, e := ParseBool(test.in)
39-
if test.err != nil {
40-
// expect an error
41-
if e == nil {
42-
t.Errorf("ParseBool(%s) = nil; want %s", test.in, test.err)
43-
} else {
44-
// NumError assertion must succeed; it's the only thing we return.
45-
if e.(*NumError).Err != test.err {
46-
t.Errorf("ParseBool(%s) = %s; want %s", test.in, e, test.err)
47-
}
48-
}
49-
} else {
50-
if e != nil {
51-
t.Errorf("ParseBool(%s) = %s; want nil", test.in, e)
52-
}
53-
if b != test.out {
54-
t.Errorf("ParseBool(%s) = %t; want %t", test.in, b, test.out)
55-
}
39+
if b != test.out || e != test.err {
40+
t.Errorf("ParseBool(%s) = %v, %v, want %v, %v", test.in, b, e, test.out, test.err)
5641
}
5742
}
5843
}

src/strconv/atoc.go renamed to src/internal/strconv/atoc.go

Lines changed: 6 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -4,23 +4,6 @@
44

55
package strconv
66

7-
import "internal/stringslite"
8-
9-
const fnParseComplex = "ParseComplex"
10-
11-
// convErr splits an error returned by parseFloatPrefix
12-
// into a syntax or range error for ParseComplex.
13-
func convErr(err error, s string) (syntax, range_ error) {
14-
if x, ok := err.(*NumError); ok {
15-
x.Func = fnParseComplex
16-
x.Num = stringslite.Clone(s)
17-
if x.Err == ErrRange {
18-
return nil, x
19-
}
20-
}
21-
return err, nil
22-
}
23-
247
// ParseComplex converts the string s to a complex number
258
// with the precision specified by bitSize: 64 for complex64, or 128 for complex128.
269
// When bitSize=64, the result still has type complex128, but it will be
@@ -47,8 +30,6 @@ func ParseComplex(s string, bitSize int) (complex128, error) {
4730
size = 32 // complex64 uses float32 parts
4831
}
4932

50-
orig := s
51-
5233
// Remove parentheses, if any.
5334
if len(s) >= 2 && s[0] == '(' && s[len(s)-1] == ')' {
5435
s = s[1 : len(s)-1]
@@ -59,10 +40,10 @@ func ParseComplex(s string, bitSize int) (complex128, error) {
5940
// Read real part (possibly imaginary part if followed by 'i').
6041
re, n, err := parseFloatPrefix(s, size)
6142
if err != nil {
62-
err, pending = convErr(err, orig)
63-
if err != nil {
43+
if err != ErrRange {
6444
return 0, err
6545
}
46+
pending = err
6647
}
6748
s = s[n:]
6849

@@ -88,20 +69,20 @@ func ParseComplex(s string, bitSize int) (complex128, error) {
8869
}
8970
fallthrough
9071
default:
91-
return 0, syntaxError(fnParseComplex, orig)
72+
return 0, ErrSyntax
9273
}
9374

9475
// Read imaginary part.
9576
im, n, err := parseFloatPrefix(s, size)
9677
if err != nil {
97-
err, pending = convErr(err, orig)
98-
if err != nil {
78+
if err != ErrRange {
9979
return 0, err
10080
}
81+
pending = err
10182
}
10283
s = s[n:]
10384
if s != "i" {
104-
return 0, syntaxError(fnParseComplex, orig)
85+
return 0, ErrSyntax
10586
}
10687
return complex(re, im), pending
10788
}

src/strconv/atoc_test.go renamed to src/internal/strconv/atoc_test.go

Lines changed: 12 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,7 @@ package strconv_test
77
import (
88
"math"
99
"math/cmplx"
10-
"reflect"
11-
. "strconv"
10+
. "internal/strconv"
1211
"testing"
1312
)
1413

@@ -188,30 +187,24 @@ func TestParseComplex(t *testing.T) {
188187
}
189188
for i := range tests {
190189
test := &tests[i]
191-
if test.err != nil {
192-
test.err = &NumError{Func: "ParseComplex", Num: test.in, Err: test.err}
190+
c, e := ParseComplex(test.in, 128)
191+
if !sameComplex(c, test.out) || e != test.err {
192+
t.Errorf("ParseComplex(%s, 128) = %v, %v, want %v, %v", test.in, c, e, test.out, test.err)
193193
}
194-
got, err := ParseComplex(test.in, 128)
195-
if !reflect.DeepEqual(err, test.err) {
196-
t.Fatalf("ParseComplex(%q, 128) = %v, %v; want %v, %v", test.in, got, err, test.out, test.err)
197-
}
198-
if !(cmplx.IsNaN(test.out) && cmplx.IsNaN(got)) && got != test.out {
199-
t.Fatalf("ParseComplex(%q, 128) = %v, %v; want %v, %v", test.in, got, err, test.out, test.err)
200-
}
201-
202194
if complex128(complex64(test.out)) == test.out {
203-
got, err := ParseComplex(test.in, 64)
204-
if !reflect.DeepEqual(err, test.err) {
205-
t.Fatalf("ParseComplex(%q, 64) = %v, %v; want %v, %v", test.in, got, err, test.out, test.err)
206-
}
207-
got64 := complex64(got)
208-
if complex128(got64) != test.out {
209-
t.Fatalf("ParseComplex(%q, 64) = %v, %v; want %v, %v", test.in, got, err, test.out, test.err)
195+
c, e := ParseComplex(test.in, 64)
196+
c64 := complex64(c)
197+
if !sameComplex(complex128(c64) , test.out) || e != test.err {
198+
t.Errorf("ParseComplex(%s, 64) = %v, %v, want %v, %v", test.in, c, e, test.out, test.err)
210199
}
211200
}
212201
}
213202
}
214203

204+
func sameComplex(c1, c2 complex128) bool {
205+
return cmplx.IsNaN(c1) && cmplx.IsNaN(c2) || c1 == c2
206+
}
207+
215208
// Issue 42297: allow ParseComplex(s, not_32_or_64) for legacy reasons
216209
func TestParseComplexIncorrectBitSize(t *testing.T) {
217210
const s = "1.5e308+1.0e307i"

src/strconv/atof.go renamed to src/internal/strconv/atof.go

Lines changed: 15 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,6 @@ package strconv
1010
// 2) Multiply/divide decimal by powers of two until in range [0.5, 1)
1111
// 3) Multiply by 2^precision and round to get mantissa.
1212

13-
import "math"
14-
1513
var optimize = true // set to false to force slow-path conversions for testing
1614

1715
// commonPrefixLenIgnoreCase returns the length of the common
@@ -58,11 +56,11 @@ func special(s string) (f float64, n int, ok bool) {
5856
n = 3
5957
}
6058
if n == 3 || n == 8 {
61-
return math.Inf(sign), nsign + n, true
59+
return inf(sign), nsign + n, true
6260
}
6361
case 'n', 'N':
6462
if commonPrefixLenIgnoreCase(s, "nan") == 3 {
65-
return math.NaN(), 3, true
63+
return nan(), 3, true
6664
}
6765
}
6866
return 0, 0, false
@@ -546,7 +544,7 @@ func atofHex(s string, flt *floatInfo, mantissa uint64, exp int, neg, trunc bool
546544
if exp > maxExp { // infinity and range error
547545
mantissa = 1 << flt.mantbits
548546
exp = maxExp + 1
549-
err = rangeError(fnParseFloat, s)
547+
err = ErrRange
550548
}
551549

552550
bits := mantissa & (1<<flt.mantbits - 1)
@@ -555,9 +553,9 @@ func atofHex(s string, flt *floatInfo, mantissa uint64, exp int, neg, trunc bool
555553
bits |= 1 << flt.mantbits << flt.expbits
556554
}
557555
if flt == &float32info {
558-
return float64(math.Float32frombits(uint32(bits))), err
556+
return float64(float32frombits(uint32(bits))), err
559557
}
560-
return math.Float64frombits(bits), err
558+
return float64frombits(bits), err
561559
}
562560

563561
const fnParseFloat = "ParseFloat"
@@ -569,7 +567,7 @@ func atof32(s string) (f float32, n int, err error) {
569567

570568
mantissa, exp, neg, trunc, hex, n, ok := readFloat(s)
571569
if !ok {
572-
return 0, n, syntaxError(fnParseFloat, s)
570+
return 0, n, ErrSyntax
573571
}
574572

575573
if hex {
@@ -603,12 +601,12 @@ func atof32(s string) (f float32, n int, err error) {
603601
// Slow fallback.
604602
var d decimal
605603
if !d.set(s[:n]) {
606-
return 0, n, syntaxError(fnParseFloat, s)
604+
return 0, n, ErrSyntax
607605
}
608606
b, ovf := d.floatBits(&float32info)
609-
f = math.Float32frombits(uint32(b))
607+
f = float32frombits(uint32(b))
610608
if ovf {
611-
err = rangeError(fnParseFloat, s)
609+
err = ErrRange
612610
}
613611
return f, n, err
614612
}
@@ -620,7 +618,7 @@ func atof64(s string) (f float64, n int, err error) {
620618

621619
mantissa, exp, neg, trunc, hex, n, ok := readFloat(s)
622620
if !ok {
623-
return 0, n, syntaxError(fnParseFloat, s)
621+
return 0, n, ErrSyntax
624622
}
625623

626624
if hex {
@@ -654,12 +652,12 @@ func atof64(s string) (f float64, n int, err error) {
654652
// Slow fallback.
655653
var d decimal
656654
if !d.set(s[:n]) {
657-
return 0, n, syntaxError(fnParseFloat, s)
655+
return 0, n, ErrSyntax
658656
}
659657
b, ovf := d.floatBits(&float64info)
660-
f = math.Float64frombits(b)
658+
f = float64frombits(b)
661659
if ovf {
662-
err = rangeError(fnParseFloat, s)
660+
err = ErrRange
663661
}
664662
return f, n, err
665663
}
@@ -693,8 +691,8 @@ func atof64(s string) (f float64, n int, err error) {
693691
// [floating-point literals]: https://go.dev/ref/spec#Floating-point_literals
694692
func ParseFloat(s string, bitSize int) (float64, error) {
695693
f, n, err := parseFloatPrefix(s, bitSize)
696-
if n != len(s) && (err == nil || err.(*NumError).Err != ErrSyntax) {
697-
return 0, syntaxError(fnParseFloat, s)
694+
if n != len(s) {
695+
return 0, ErrSyntax
698696
}
699697
return f, err
700698
}

src/strconv/atof_test.go renamed to src/internal/strconv/atof_test.go

Lines changed: 2 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import (
88
"math"
99
"math/rand"
1010
"reflect"
11-
. "strconv"
11+
. "internal/strconv"
1212
"strings"
1313
"sync"
1414
"testing"
@@ -446,21 +446,6 @@ func initAtof() {
446446
}
447447

448448
func initAtofOnce() {
449-
// The atof routines return NumErrors wrapping
450-
// the error and the string. Convert the table above.
451-
for i := range atoftests {
452-
test := &atoftests[i]
453-
if test.err != nil {
454-
test.err = &NumError{"ParseFloat", test.in, test.err}
455-
}
456-
}
457-
for i := range atof32tests {
458-
test := &atof32tests[i]
459-
if test.err != nil {
460-
test.err = &NumError{"ParseFloat", test.in, test.err}
461-
}
462-
}
463-
464449
// Generate random inputs for tests and benchmarks
465450
if testing.Short() {
466451
atofRandomTests = make([]atofSimpleTest, 100)
@@ -497,7 +482,7 @@ func TestParseFloatPrefix(t *testing.T) {
497482
// correctly as "inf" with suffix.
498483
for _, suffix := range []string{" ", "q", "+", "-", "<", "=", ">", "(", ")", "i", "init"} {
499484
in := test.in + suffix
500-
_, n, err := ParseFloatPrefix(in, 64)
485+
_, n, err := parseFloatPrefix(in, 64)
501486
if err != nil {
502487
t.Errorf("ParseFloatPrefix(%q, 64): err = %v; want no error", in, err)
503488
}

src/strconv/eisel_lemire.go renamed to src/internal/strconv/atofeisel.go

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@ package strconv
1818
// https://github.com/nigeltao/parse-number-fxx-test-data/blob/5280dcfccf6d0b02a65ae282dad0b6d9de50e039/script/test-go-strconv.go
1919

2020
import (
21-
"math"
2221
"math/bits"
2322
)
2423

@@ -29,7 +28,7 @@ func eiselLemire64(man uint64, exp10 int, neg bool) (f float64, ok bool) {
2928
// Exp10 Range.
3029
if man == 0 {
3130
if neg {
32-
f = math.Float64frombits(0x8000000000000000) // Negative zero.
31+
f = float64frombits(0x8000000000000000) // Negative zero.
3332
}
3433
return f, true
3534
}
@@ -88,7 +87,7 @@ func eiselLemire64(man uint64, exp10 int, neg bool) (f float64, ok bool) {
8887
if neg {
8988
retBits |= 0x8000000000000000
9089
}
91-
return math.Float64frombits(retBits), true
90+
return float64frombits(retBits), true
9291
}
9392

9493
func eiselLemire32(man uint64, exp10 int, neg bool) (f float32, ok bool) {
@@ -104,7 +103,7 @@ func eiselLemire32(man uint64, exp10 int, neg bool) (f float32, ok bool) {
104103
// Exp10 Range.
105104
if man == 0 {
106105
if neg {
107-
f = math.Float32frombits(0x80000000) // Negative zero.
106+
f = float32frombits(0x80000000) // Negative zero.
108107
}
109108
return f, true
110109
}
@@ -163,5 +162,5 @@ func eiselLemire32(man uint64, exp10 int, neg bool) (f float32, ok bool) {
163162
if neg {
164163
retBits |= 0x80000000
165164
}
166-
return math.Float32frombits(uint32(retBits)), true
165+
return float32frombits(uint32(retBits)), true
167166
}

0 commit comments

Comments
 (0)