package runtime
import (
"internal/bytealg"
"runtime/internal/sys"
"unsafe"
)
const tmpStringBufSize = 32
type tmpBuf [tmpStringBufSize ]byte
func concatstrings (buf *tmpBuf , a []string ) string {
idx := 0
l := 0
count := 0
for i , x := range a {
n := len (x )
if n == 0 {
continue
}
if l +n < l {
throw ("string concatenation too long" )
}
l += n
count ++
idx = i
}
if count == 0 {
return ""
}
if count == 1 && (buf != nil || !stringDataOnStack (a [idx ])) {
return a [idx ]
}
s , b := rawstringtmp (buf , l )
for _ , x := range a {
copy (b , x )
b = b [len (x ):]
}
return s
}
func concatstring2 (buf *tmpBuf , a [2 ]string ) string {
return concatstrings (buf , a [:])
}
func concatstring3 (buf *tmpBuf , a [3 ]string ) string {
return concatstrings (buf , a [:])
}
func concatstring4 (buf *tmpBuf , a [4 ]string ) string {
return concatstrings (buf , a [:])
}
func concatstring5 (buf *tmpBuf , a [5 ]string ) string {
return concatstrings (buf , a [:])
}
func slicebytetostring (buf *tmpBuf , ptr *byte , n int ) (str string ) {
if n == 0 {
return ""
}
if raceenabled {
racereadrangepc (unsafe .Pointer (ptr ),
uintptr (n ),
getcallerpc (),
funcPC (slicebytetostring ))
}
if msanenabled {
msanread (unsafe .Pointer (ptr ), uintptr (n ))
}
if n == 1 {
p := unsafe .Pointer (&staticuint64s [*ptr ])
if sys .BigEndian {
p = add (p , 7 )
}
stringStructOf (&str ).str = p
stringStructOf (&str ).len = 1
return
}
var p unsafe .Pointer
if buf != nil && n <= len (buf ) {
p = unsafe .Pointer (buf )
} else {
p = mallocgc (uintptr (n ), nil , false )
}
stringStructOf (&str ).str = p
stringStructOf (&str ).len = n
memmove (p , unsafe .Pointer (ptr ), uintptr (n ))
return
}
func stringDataOnStack (s string ) bool {
ptr := uintptr (stringStructOf (&s ).str )
stk := getg ().stack
return stk .lo <= ptr && ptr < stk .hi
}
func rawstringtmp (buf *tmpBuf , l int ) (s string , b []byte ) {
if buf != nil && l <= len (buf ) {
b = buf [:l ]
s = slicebytetostringtmp (&b [0 ], len (b ))
} else {
s , b = rawstring (l )
}
return
}
func slicebytetostringtmp (ptr *byte , n int ) (str string ) {
if raceenabled && n > 0 {
racereadrangepc (unsafe .Pointer (ptr ),
uintptr (n ),
getcallerpc (),
funcPC (slicebytetostringtmp ))
}
if msanenabled && n > 0 {
msanread (unsafe .Pointer (ptr ), uintptr (n ))
}
stringStructOf (&str ).str = unsafe .Pointer (ptr )
stringStructOf (&str ).len = n
return
}
func stringtoslicebyte (buf *tmpBuf , s string ) []byte {
var b []byte
if buf != nil && len (s ) <= len (buf ) {
*buf = tmpBuf {}
b = buf [:len (s )]
} else {
b = rawbyteslice (len (s ))
}
copy (b , s )
return b
}
func stringtoslicerune (buf *[tmpStringBufSize ]rune , s string ) []rune {
n := 0
for range s {
n ++
}
var a []rune
if buf != nil && n <= len (buf ) {
*buf = [tmpStringBufSize ]rune {}
a = buf [:n ]
} else {
a = rawruneslice (n )
}
n = 0
for _ , r := range s {
a [n ] = r
n ++
}
return a
}
func slicerunetostring (buf *tmpBuf , a []rune ) string {
if raceenabled && len (a ) > 0 {
racereadrangepc (unsafe .Pointer (&a [0 ]),
uintptr (len (a ))*unsafe .Sizeof (a [0 ]),
getcallerpc (),
funcPC (slicerunetostring ))
}
if msanenabled && len (a ) > 0 {
msanread (unsafe .Pointer (&a [0 ]), uintptr (len (a ))*unsafe .Sizeof (a [0 ]))
}
var dum [4 ]byte
size1 := 0
for _ , r := range a {
size1 += encoderune (dum [:], r )
}
s , b := rawstringtmp (buf , size1 +3 )
size2 := 0
for _ , r := range a {
if size2 >= size1 {
break
}
size2 += encoderune (b [size2 :], r )
}
return s [:size2 ]
}
type stringStruct struct {
str unsafe .Pointer
len int
}
type stringStructDWARF struct {
str *byte
len int
}
func stringStructOf (sp *string ) *stringStruct {
return (*stringStruct )(unsafe .Pointer (sp ))
}
func intstring (buf *[4 ]byte , v int64 ) (s string ) {
var b []byte
if buf != nil {
b = buf [:]
s = slicebytetostringtmp (&b [0 ], len (b ))
} else {
s , b = rawstring (4 )
}
if int64 (rune (v )) != v {
v = runeError
}
n := encoderune (b , rune (v ))
return s [:n ]
}
func rawstring (size int ) (s string , b []byte ) {
p := mallocgc (uintptr (size ), nil , false )
stringStructOf (&s ).str = p
stringStructOf (&s ).len = size
*(*slice )(unsafe .Pointer (&b )) = slice {p , size , size }
return
}
func rawbyteslice (size int ) (b []byte ) {
cap := roundupsize (uintptr (size ))
p := mallocgc (cap , nil , false )
if cap != uintptr (size ) {
memclrNoHeapPointers (add (p , uintptr (size )), cap -uintptr (size ))
}
*(*slice )(unsafe .Pointer (&b )) = slice {p , size , int (cap )}
return
}
func rawruneslice (size int ) (b []rune ) {
if uintptr (size ) > maxAlloc /4 {
throw ("out of memory" )
}
mem := roundupsize (uintptr (size ) * 4 )
p := mallocgc (mem , nil , false )
if mem != uintptr (size )*4 {
memclrNoHeapPointers (add (p , uintptr (size )*4 ), mem -uintptr (size )*4 )
}
*(*slice )(unsafe .Pointer (&b )) = slice {p , size , int (mem / 4 )}
return
}
func gobytes (p *byte , n int ) (b []byte ) {
if n == 0 {
return make ([]byte , 0 )
}
if n < 0 || uintptr (n ) > maxAlloc {
panic (errorString ("gobytes: length out of range" ))
}
bp := mallocgc (uintptr (n ), nil , false )
memmove (bp , unsafe .Pointer (p ), uintptr (n ))
*(*slice )(unsafe .Pointer (&b )) = slice {bp , n , n }
return
}
func gostring (p *byte ) string {
l := findnull (p )
if l == 0 {
return ""
}
s , b := rawstring (l )
memmove (unsafe .Pointer (&b [0 ]), unsafe .Pointer (p ), uintptr (l ))
return s
}
func gostringn (p *byte , l int ) string {
if l == 0 {
return ""
}
s , b := rawstring (l )
memmove (unsafe .Pointer (&b [0 ]), unsafe .Pointer (p ), uintptr (l ))
return s
}
func hasPrefix (s , prefix string ) bool {
return len (s ) >= len (prefix ) && s [:len (prefix )] == prefix
}
const (
maxUint = ^uint (0 )
maxInt = int (maxUint >> 1 )
)
func atoi (s string ) (int , bool ) {
if s == "" {
return 0 , false
}
neg := false
if s [0 ] == '-' {
neg = true
s = s [1 :]
}
un := uint (0 )
for i := 0 ; i < len (s ); i ++ {
c := s [i ]
if c < '0' || c > '9' {
return 0 , false
}
if un > maxUint /10 {
return 0 , false
}
un *= 10
un1 := un + uint (c ) - '0'
if un1 < un {
return 0 , false
}
un = un1
}
if !neg && un > uint (maxInt ) {
return 0 , false
}
if neg && un > uint (maxInt )+1 {
return 0 , false
}
n := int (un )
if neg {
n = -n
}
return n , true
}
func atoi32 (s string ) (int32 , bool ) {
if n , ok := atoi (s ); n == int (int32 (n )) {
return int32 (n ), ok
}
return 0 , false
}
func findnull (s *byte ) int {
if s == nil {
return 0
}
if GOOS == "plan9" {
p := (*[maxAlloc /2 - 1 ]byte )(unsafe .Pointer (s ))
l := 0
for p [l ] != 0 {
l ++
}
return l
}
const pageSize = 4096
offset := 0
ptr := unsafe .Pointer (s )
safeLen := int (pageSize - uintptr (ptr )%pageSize )
for {
t := *(*string )(unsafe .Pointer (&stringStruct {ptr , safeLen }))
if i := bytealg .IndexByteString (t , 0 ); i != -1 {
return offset + i
}
ptr = unsafe .Pointer (uintptr (ptr ) + uintptr (safeLen ))
offset += safeLen
safeLen = pageSize
}
}
func findnullw (s *uint16 ) int {
if s == nil {
return 0
}
p := (*[maxAlloc /2 /2 - 1 ]uint16 )(unsafe .Pointer (s ))
l := 0
for p [l ] != 0 {
l ++
}
return l
}
func gostringnocopy (str *byte ) string {
ss := stringStruct {str : unsafe .Pointer (str ), len : findnull (str )}
s := *(*string )(unsafe .Pointer (&ss ))
return s
}
func gostringw (strw *uint16 ) string {
var buf [8 ]byte
str := (*[maxAlloc /2 /2 - 1 ]uint16 )(unsafe .Pointer (strw ))
n1 := 0
for i := 0 ; str [i ] != 0 ; i ++ {
n1 += encoderune (buf [:], rune (str [i ]))
}
s , b := rawstring (n1 + 4 )
n2 := 0
for i := 0 ; str [i ] != 0 ; i ++ {
if n2 >= n1 {
break
}
n2 += encoderune (b [n2 :], rune (str [i ]))
}
b [n2 ] = 0
return s [:n2 ]
}
The pages are generated with Golds v0.3.6 . (GOOS=darwin GOARCH=amd64)
Golds is a Go 101 project developed by Tapir Liu .
PR and bug reports are welcome and can be submitted to the issue list .
Please follow @Go100and1 (reachable from the left QR code) to get the latest news of Golds .