tinygo/src/runtime/print.go

296 строки
4,6 КиБ
Go

package runtime
import (
"unsafe"
)
type stringer interface {
String() string
}
//go:nobounds
func printstring(s string) {
for i := 0; i < len(s); i++ {
putchar(s[i])
}
}
func printuint8(n uint8) {
if TargetBits >= 32 {
printuint32(uint32(n))
} else {
prevdigits := n / 10
if prevdigits != 0 {
printuint8(prevdigits)
}
putchar(byte((n % 10) + '0'))
}
}
func printint8(n int8) {
if TargetBits >= 32 {
printint32(int32(n))
} else {
if n < 0 {
putchar('-')
n = -n
}
printuint8(uint8(n))
}
}
func printuint16(n uint16) {
printuint32(uint32(n))
}
func printint16(n int16) {
printint32(int32(n))
}
//go:nobounds
func printuint32(n uint32) {
digits := [10]byte{} // enough to hold (2^32)-1
// Fill in all 10 digits.
firstdigit := 9 // digit index that isn't zero (by default, the last to handle '0' correctly)
for i := 9; i >= 0; i-- {
digit := byte(n%10 + '0')
digits[i] = digit
if digit != '0' {
firstdigit = i
}
n /= 10
}
// Print digits without the leading zeroes.
for i := firstdigit; i < 10; i++ {
putchar(digits[i])
}
}
func printint32(n int32) {
// Print integer in signed big-endian base-10 notation, for humans to
// read.
if n < 0 {
putchar('-')
n = -n
}
printuint32(uint32(n))
}
func printuint64(n uint64) {
prevdigits := n / 10
if prevdigits != 0 {
printuint64(prevdigits)
}
putchar(byte((n % 10) + '0'))
}
func printint64(n int64) {
if n < 0 {
putchar('-')
n = -n
}
printuint64(uint64(n))
}
func printfloat32(v float32) {
// TODO: write an implementation like printfloat64, as some systems have
// 32-bit floats but only software emulation for 64-bit floats.
printfloat64(float64(v))
}
// printfloat64() was copied from the relevant source in the original Go
// implementation. It is copyright by the Go authors, licensed under the same
// BSD 3-clause license. See https://golang.org/LICENSE for details.
//
// Source:
// https://github.com/golang/go/blob/master/src/runtime/print.go
func printfloat64(v float64) {
switch {
case v != v:
printstring("NaN")
return
case v+v == v && v > 0:
printstring("+Inf")
return
case v+v == v && v < 0:
printstring("-Inf")
return
}
const n = 7 // digits printed
var buf [n + 7]byte
buf[0] = '+'
e := 0 // exp
if v == 0 {
if 1/v < 0 {
buf[0] = '-'
}
} else {
if v < 0 {
v = -v
buf[0] = '-'
}
// normalize
for v >= 10 {
e++
v /= 10
}
for v < 1 {
e--
v *= 10
}
// round
h := 5.0
for i := 0; i < n; i++ {
h /= 10
}
v += h
if v >= 10 {
e++
v /= 10
}
}
// format +d.dddd+edd
for i := 0; i < n; i++ {
s := int(v)
buf[i+2] = byte(s + '0')
v -= float64(s)
v *= 10
}
buf[1] = buf[2]
buf[2] = '.'
buf[n+2] = 'e'
buf[n+3] = '+'
if e < 0 {
e = -e
buf[n+3] = '-'
}
buf[n+4] = byte(e/100) + '0'
buf[n+5] = byte(e/10)%10 + '0'
buf[n+6] = byte(e%10) + '0'
for _, c := range buf {
putchar(c)
}
}
func printcomplex64(c complex64) {
putchar('(')
printfloat32(real(c))
printfloat32(imag(c))
printstring("i)")
}
func printcomplex128(c complex128) {
putchar('(')
printfloat64(real(c))
printfloat64(imag(c))
printstring("i)")
}
func printspace() {
putchar(' ')
}
func printnl() {
putchar('\r')
putchar('\n')
}
func printitf(msg interface{}) {
switch msg := msg.(type) {
case bool:
print(msg)
case int:
print(msg)
case int8:
print(msg)
case int16:
print(msg)
case int32:
print(msg)
case int64:
print(msg)
case uint:
print(msg)
case uint8:
print(msg)
case uint16:
print(msg)
case uint32:
print(msg)
case uint64:
print(msg)
case uintptr:
print(msg)
case float32:
print(msg)
case float64:
print(msg)
case complex64:
print(msg)
case complex128:
print(msg)
case string:
print(msg)
case error:
print(msg.Error())
case stringer:
print(msg.String())
default:
// cast to underlying type
itf := *(*_interface)(unsafe.Pointer(&msg))
putchar('(')
switch unsafe.Sizeof(itf.typecode) {
case 2:
printuint16(uint16(itf.typecode))
case 4:
printuint32(uint32(itf.typecode))
case 8:
printuint64(uint64(itf.typecode))
}
putchar(':')
print(itf.value)
putchar(')')
}
}
func printmap(m *hashmap) {
print("map[")
if m == nil {
print("nil")
} else {
print(uint(m.count))
}
putchar(']')
}
func printptr(ptr uintptr) {
if ptr == 0 {
print("nil")
return
}
putchar('0')
putchar('x')
for i := 0; i < int(unsafe.Sizeof(ptr))*2; i++ {
nibble := byte(ptr >> (unsafe.Sizeof(ptr)*8 - 4))
if nibble < 10 {
putchar(nibble + '0')
} else {
putchar(nibble - 10 + 'a')
}
ptr <<= 4
}
}
func printbool(b bool) {
if b {
printstring("true")
} else {
printstring("false")
}
}