net/ip, syscall/errno: Reduce code duplication by switching to internal/itoa.

internal/itoa wasn't around back in go 1.12 days when tinygo's syscall/errno.go was written.
It was only added as of go 1.17 ( https://github.com/golang/go/commit/061a6903a232cb868780b )
so we have to have an internal copy for now.
The internal copy should be deleted when tinygo drops support for go 1.16.

FWIW, the new version seems nicer.
It uses no allocations when converting 0,
and although the optimizer might make this moot, uses
a multiplication x 10 instead of a mod operation.
Этот коммит содержится в:
Dan Kegel 2021-11-14 20:51:54 -08:00 коммит произвёл Ayke
родитель 7b41d92198
коммит b70b6076e3
9 изменённых файлов: 85 добавлений и 40 удалений

Просмотреть файл

@ -216,6 +216,7 @@ TEST_PACKAGES = \
hash/crc64 \ hash/crc64 \
html \ html \
index/suffixarray \ index/suffixarray \
internal/itoa \
math \ math \
math/cmplx \ math/cmplx \
net/mail \ net/mail \

Просмотреть файл

@ -228,6 +228,7 @@ func pathsToOverride(needsSyscallPackage bool) map[string]bool {
"internal/bytealg/": false, "internal/bytealg/": false,
"internal/reflectlite/": false, "internal/reflectlite/": false,
"internal/task/": false, "internal/task/": false,
"internal/itoa/": false, // TODO: Remove when we drop support for go 1.16
"machine/": false, "machine/": false,
"net/": true, "net/": true,
"os/": true, "os/": true,

2
src/internal/itoa/README.md Обычный файл
Просмотреть файл

@ -0,0 +1,2 @@
internal/itoa is new to go as of 1.17.
This directory should be removed when tinygo drops support for go 1.16.

33
src/internal/itoa/itoa.go Обычный файл
Просмотреть файл

@ -0,0 +1,33 @@
// Copyright 2021 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.
// Simple conversions to avoid depending on strconv.
package itoa
// Itoa converts val to a decimal string.
func Itoa(val int) string {
if val < 0 {
return "-" + Uitoa(uint(-val))
}
return Uitoa(uint(val))
}
// Uitoa converts val to a decimal string.
func Uitoa(val uint) string {
if val == 0 { // avoid string allocation
return "0"
}
var buf [20]byte // big enough for 64bit value base 10
i := len(buf) - 1
for val >= 10 {
q := val / 10
buf[i] = byte('0' + val - q*10)
i--
val = q
}
// val < 10
buf[i] = byte('0' + val)
return string(buf[i:])
}

40
src/internal/itoa/itoa_test.go Обычный файл
Просмотреть файл

@ -0,0 +1,40 @@
// Copyright 2021 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.
package itoa_test
import (
"fmt"
"internal/itoa"
"math"
"testing"
)
var (
minInt64 int64 = math.MinInt64
maxInt64 int64 = math.MaxInt64
maxUint64 uint64 = math.MaxUint64
)
func TestItoa(t *testing.T) {
tests := []int{int(minInt64), math.MinInt32, -999, -100, -1, 0, 1, 100, 999, math.MaxInt32, int(maxInt64)}
for _, tt := range tests {
got := itoa.Itoa(tt)
want := fmt.Sprint(tt)
if want != got {
t.Fatalf("Itoa(%d) = %s, want %s", tt, got, want)
}
}
}
func TestUitoa(t *testing.T) {
tests := []uint{0, 1, 100, 999, math.MaxUint32, uint(maxUint64)}
for _, tt := range tests {
got := itoa.Uitoa(tt)
want := fmt.Sprint(tt)
if want != got {
t.Fatalf("Uitoa(%d) = %s, want %s", tt, got, want)
}
}
}

Просмотреть файл

@ -14,7 +14,10 @@
package net package net
import "internal/bytealg" import (
"internal/bytealg"
"internal/itoa"
)
// IP address lengths (bytes). // IP address lengths (bytes).
const ( const (
@ -533,7 +536,7 @@ func (n *IPNet) String() string {
if l == -1 { if l == -1 {
return nn.String() + "/" + m.String() return nn.String() + "/" + m.String()
} }
return nn.String() + "/" + uitoa(uint(l)) return nn.String() + "/" + itoa.Uitoa(uint(l))
} }
// Parse IPv4 address (d.d.d.d). // Parse IPv4 address (d.d.d.d).

Просмотреть файл

@ -64,24 +64,6 @@ func xtoi2(s string, e byte) (byte, bool) {
return byte(n), ok && ei == 2 return byte(n), ok && ei == 2
} }
// Convert unsigned integer to decimal string.
func uitoa(val uint) string {
if val == 0 { // avoid string allocation
return "0"
}
var buf [20]byte // big enough for 64bit value base 10
i := len(buf) - 1
for val >= 10 {
q := val / 10
buf[i] = byte('0' + val - q*10)
i--
val = q
}
// val < 10
buf[i] = byte('0' + val)
return string(buf[i:])
}
// Convert i to a hexadecimal string. Leading zeros are not printed. // Convert i to a hexadecimal string. Leading zeros are not printed.
func appendHex(dst []byte, i uint32) []byte { func appendHex(dst []byte, i uint32) []byte {
if i == 0 { if i == 0 {

Просмотреть файл

@ -1,5 +1,7 @@
package syscall package syscall
import "internal/itoa"
// Most code here has been copied from the Go sources: // Most code here has been copied from the Go sources:
// https://github.com/golang/go/blob/go1.12/src/syscall/syscall_js.go // https://github.com/golang/go/blob/go1.12/src/syscall/syscall_js.go
// It has the following copyright note: // It has the following copyright note:
@ -18,7 +20,7 @@ package syscall
type Errno uintptr type Errno uintptr
func (e Errno) Error() string { func (e Errno) Error() string {
return "errno " + itoa(int(e)) return "errno " + itoa.Itoa(int(e))
} }
func (e Errno) Temporary() bool { func (e Errno) Temporary() bool {

Просмотреть файл

@ -4,25 +4,6 @@
package syscall package syscall
func itoa(val int) string { // do it here rather than with fmt to avoid dependency
if val < 0 {
return "-" + uitoa(uint(-val))
}
return uitoa(uint(val))
}
func uitoa(val uint) string {
var buf [32]byte // big enough for int64
i := len(buf) - 1
for val >= 10 {
buf[i] = byte(val%10 + '0')
i--
val /= 10
}
buf[i] = byte(val + '0')
return string(buf[i:])
}
// clen returns the index of the first NULL byte in n or len(n) if n contains no NULL byte. // clen returns the index of the first NULL byte in n or len(n) if n contains no NULL byte.
func clen(n []byte) int { func clen(n []byte) int {
for i := 0; i < len(n); i++ { for i := 0; i < len(n); i++ {