2014-06-17 00:03:03 -06:00
|
|
|
// Copyright 2014 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 runtime
|
|
|
|
|
|
|
|
import (
|
|
|
|
"unsafe"
|
|
|
|
)
|
|
|
|
|
|
|
|
func concatstrings(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 {
|
2014-09-01 15:25:26 -06:00
|
|
|
gothrow("string concatenation too long")
|
2014-06-17 00:03:03 -06:00
|
|
|
}
|
|
|
|
l += n
|
|
|
|
count++
|
|
|
|
idx = i
|
|
|
|
}
|
|
|
|
if count == 0 {
|
|
|
|
return ""
|
|
|
|
}
|
|
|
|
if count == 1 {
|
|
|
|
return a[idx]
|
|
|
|
}
|
|
|
|
s, b := rawstring(l)
|
|
|
|
l = 0
|
|
|
|
for _, x := range a {
|
|
|
|
copy(b[l:], x)
|
|
|
|
l += len(x)
|
|
|
|
}
|
|
|
|
return s
|
|
|
|
}
|
|
|
|
|
|
|
|
//go:nosplit
|
|
|
|
func concatstring2(a [2]string) string {
|
|
|
|
return concatstrings(a[:])
|
|
|
|
}
|
|
|
|
|
|
|
|
//go:nosplit
|
|
|
|
func concatstring3(a [3]string) string {
|
|
|
|
return concatstrings(a[:])
|
|
|
|
}
|
|
|
|
|
|
|
|
//go:nosplit
|
|
|
|
func concatstring4(a [4]string) string {
|
|
|
|
return concatstrings(a[:])
|
|
|
|
}
|
|
|
|
|
|
|
|
//go:nosplit
|
|
|
|
func concatstring5(a [5]string) string {
|
|
|
|
return concatstrings(a[:])
|
|
|
|
}
|
|
|
|
|
|
|
|
func slicebytetostring(b []byte) string {
|
|
|
|
if raceenabled && len(b) > 0 {
|
|
|
|
fn := slicebytetostring
|
|
|
|
racereadrangepc(unsafe.Pointer(&b[0]),
|
|
|
|
len(b),
|
cmd/cc, runtime: preserve C runtime type names in generated Go
uintptr or uint64 in the runtime C were turning into uint in the Go,
bool was turning into uint8, and so on. Fix that.
Also delete Go wrappers for C functions.
The C functions can be called directly now
(but still eventually need to be converted to Go).
LGTM=bradfitz, minux, iant
R=golang-codereviews, bradfitz, iant, minux
CC=golang-codereviews, khr, r
https://golang.org/cl/138740043
2014-08-27 19:59:49 -06:00
|
|
|
getcallerpc(unsafe.Pointer(&b)),
|
2014-06-17 00:03:03 -06:00
|
|
|
**(**uintptr)(unsafe.Pointer(&fn)))
|
|
|
|
}
|
|
|
|
s, c := rawstring(len(b))
|
|
|
|
copy(c, b)
|
|
|
|
return s
|
|
|
|
}
|
|
|
|
|
|
|
|
func slicebytetostringtmp(b []byte) string {
|
|
|
|
// Return a "string" referring to the actual []byte bytes.
|
|
|
|
// This is only for use by internal compiler optimizations
|
|
|
|
// that know that the string form will be discarded before
|
|
|
|
// the calling goroutine could possibly modify the original
|
|
|
|
// slice or synchronize with another goroutine.
|
|
|
|
// Today, the only such case is a m[string(k)] lookup where
|
|
|
|
// m is a string-keyed map and k is a []byte.
|
|
|
|
|
|
|
|
if raceenabled && len(b) > 0 {
|
|
|
|
fn := slicebytetostringtmp
|
|
|
|
racereadrangepc(unsafe.Pointer(&b[0]),
|
|
|
|
len(b),
|
cmd/cc, runtime: preserve C runtime type names in generated Go
uintptr or uint64 in the runtime C were turning into uint in the Go,
bool was turning into uint8, and so on. Fix that.
Also delete Go wrappers for C functions.
The C functions can be called directly now
(but still eventually need to be converted to Go).
LGTM=bradfitz, minux, iant
R=golang-codereviews, bradfitz, iant, minux
CC=golang-codereviews, khr, r
https://golang.org/cl/138740043
2014-08-27 19:59:49 -06:00
|
|
|
getcallerpc(unsafe.Pointer(&b)),
|
2014-06-17 00:03:03 -06:00
|
|
|
**(**uintptr)(unsafe.Pointer(&fn)))
|
|
|
|
}
|
|
|
|
return *(*string)(unsafe.Pointer(&b))
|
|
|
|
}
|
|
|
|
|
|
|
|
func stringtoslicebyte(s string) []byte {
|
|
|
|
b := rawbyteslice(len(s))
|
|
|
|
copy(b, s)
|
|
|
|
return b
|
|
|
|
}
|
|
|
|
|
|
|
|
func stringtoslicerune(s string) []rune {
|
|
|
|
// two passes.
|
|
|
|
// unlike slicerunetostring, no race because strings are immutable.
|
|
|
|
n := 0
|
|
|
|
t := s
|
|
|
|
for len(s) > 0 {
|
|
|
|
_, k := charntorune(s)
|
|
|
|
s = s[k:]
|
|
|
|
n++
|
|
|
|
}
|
|
|
|
a := rawruneslice(n)
|
|
|
|
n = 0
|
|
|
|
for len(t) > 0 {
|
|
|
|
r, k := charntorune(t)
|
|
|
|
t = t[k:]
|
|
|
|
a[n] = r
|
|
|
|
n++
|
|
|
|
}
|
|
|
|
return a
|
|
|
|
}
|
|
|
|
|
|
|
|
func slicerunetostring(a []rune) string {
|
|
|
|
if raceenabled && len(a) > 0 {
|
|
|
|
fn := slicerunetostring
|
|
|
|
racereadrangepc(unsafe.Pointer(&a[0]),
|
|
|
|
len(a)*int(unsafe.Sizeof(a[0])),
|
cmd/cc, runtime: preserve C runtime type names in generated Go
uintptr or uint64 in the runtime C were turning into uint in the Go,
bool was turning into uint8, and so on. Fix that.
Also delete Go wrappers for C functions.
The C functions can be called directly now
(but still eventually need to be converted to Go).
LGTM=bradfitz, minux, iant
R=golang-codereviews, bradfitz, iant, minux
CC=golang-codereviews, khr, r
https://golang.org/cl/138740043
2014-08-27 19:59:49 -06:00
|
|
|
getcallerpc(unsafe.Pointer(&a)),
|
2014-06-17 00:03:03 -06:00
|
|
|
**(**uintptr)(unsafe.Pointer(&fn)))
|
|
|
|
}
|
|
|
|
var dum [4]byte
|
|
|
|
size1 := 0
|
|
|
|
for _, r := range a {
|
|
|
|
size1 += runetochar(dum[:], r)
|
|
|
|
}
|
|
|
|
s, b := rawstring(size1 + 3)
|
|
|
|
size2 := 0
|
|
|
|
for _, r := range a {
|
|
|
|
// check for race
|
|
|
|
if size2 >= size1 {
|
|
|
|
break
|
|
|
|
}
|
|
|
|
size2 += runetochar(b[size2:], r)
|
|
|
|
}
|
|
|
|
return s[:size2]
|
|
|
|
}
|
|
|
|
|
2014-06-17 22:59:50 -06:00
|
|
|
type stringStruct struct {
|
2014-07-16 15:16:19 -06:00
|
|
|
str unsafe.Pointer
|
2014-06-17 22:59:50 -06:00
|
|
|
len int
|
|
|
|
}
|
|
|
|
|
2014-08-24 18:28:29 -06:00
|
|
|
func cstringToGo(str unsafe.Pointer) (s string) {
|
2014-06-17 22:59:50 -06:00
|
|
|
i := 0
|
2014-06-17 00:03:03 -06:00
|
|
|
for ; ; i++ {
|
2014-08-24 18:28:29 -06:00
|
|
|
if *(*byte)(unsafe.Pointer(uintptr(str) + uintptr(i))) == 0 {
|
2014-06-17 00:03:03 -06:00
|
|
|
break
|
|
|
|
}
|
|
|
|
}
|
2014-06-17 22:59:50 -06:00
|
|
|
t := (*stringStruct)(unsafe.Pointer(&s))
|
2014-07-16 15:16:19 -06:00
|
|
|
t.str = unsafe.Pointer(str)
|
2014-06-17 00:03:03 -06:00
|
|
|
t.len = i
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
func intstring(v int64) string {
|
|
|
|
s, b := rawstring(4)
|
|
|
|
n := runetochar(b, rune(v))
|
|
|
|
return s[:n]
|
|
|
|
}
|
|
|
|
|
|
|
|
// stringiter returns the index of the next
|
|
|
|
// rune after the rune that starts at s[k].
|
|
|
|
func stringiter(s string, k int) int {
|
|
|
|
if k >= len(s) {
|
|
|
|
// 0 is end of iteration
|
|
|
|
return 0
|
|
|
|
}
|
|
|
|
|
|
|
|
c := s[k]
|
|
|
|
if c < runeself {
|
|
|
|
return k + 1
|
|
|
|
}
|
|
|
|
|
|
|
|
// multi-char rune
|
|
|
|
_, n := charntorune(s[k:])
|
|
|
|
return k + n
|
|
|
|
}
|
|
|
|
|
|
|
|
// stringiter2 returns the rune that starts at s[k]
|
|
|
|
// and the index where the next rune starts.
|
|
|
|
func stringiter2(s string, k int) (int, rune) {
|
|
|
|
if k >= len(s) {
|
|
|
|
// 0 is end of iteration
|
|
|
|
return 0, 0
|
|
|
|
}
|
|
|
|
|
|
|
|
c := s[k]
|
|
|
|
if c < runeself {
|
|
|
|
return k + 1, rune(c)
|
|
|
|
}
|
|
|
|
|
|
|
|
// multi-char rune
|
|
|
|
r, n := charntorune(s[k:])
|
|
|
|
return k + n, r
|
|
|
|
}
|
2014-07-30 10:01:52 -06:00
|
|
|
|
|
|
|
// rawstring allocates storage for a new string. The returned
|
|
|
|
// string and byte slice both refer to the same storage.
|
|
|
|
// The storage is not zeroed. Callers should use
|
|
|
|
// b to set the string contents and then drop b.
|
|
|
|
func rawstring(size int) (s string, b []byte) {
|
|
|
|
p := gomallocgc(uintptr(size), nil, flagNoScan|flagNoZero)
|
|
|
|
|
|
|
|
(*stringStruct)(unsafe.Pointer(&s)).str = p
|
|
|
|
(*stringStruct)(unsafe.Pointer(&s)).len = size
|
|
|
|
|
|
|
|
(*slice)(unsafe.Pointer(&b)).array = (*uint8)(p)
|
|
|
|
(*slice)(unsafe.Pointer(&b)).len = uint(size)
|
|
|
|
(*slice)(unsafe.Pointer(&b)).cap = uint(size)
|
|
|
|
|
|
|
|
for {
|
|
|
|
ms := maxstring
|
cmd/cc, runtime: preserve C runtime type names in generated Go
uintptr or uint64 in the runtime C were turning into uint in the Go,
bool was turning into uint8, and so on. Fix that.
Also delete Go wrappers for C functions.
The C functions can be called directly now
(but still eventually need to be converted to Go).
LGTM=bradfitz, minux, iant
R=golang-codereviews, bradfitz, iant, minux
CC=golang-codereviews, khr, r
https://golang.org/cl/138740043
2014-08-27 19:59:49 -06:00
|
|
|
if uintptr(size) <= uintptr(ms) || casuintptr((*uintptr)(unsafe.Pointer(&maxstring)), uintptr(ms), uintptr(size)) {
|
2014-07-30 10:01:52 -06:00
|
|
|
return
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// rawbyteslice allocates a new byte slice. The byte slice is not zeroed.
|
|
|
|
func rawbyteslice(size int) (b []byte) {
|
|
|
|
cap := goroundupsize(uintptr(size))
|
|
|
|
p := gomallocgc(cap, nil, flagNoScan|flagNoZero)
|
|
|
|
if cap != uintptr(size) {
|
|
|
|
memclr(add(p, uintptr(size)), cap-uintptr(size))
|
|
|
|
}
|
|
|
|
|
|
|
|
(*slice)(unsafe.Pointer(&b)).array = (*uint8)(p)
|
|
|
|
(*slice)(unsafe.Pointer(&b)).len = uint(size)
|
|
|
|
(*slice)(unsafe.Pointer(&b)).cap = uint(cap)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
// rawruneslice allocates a new rune slice. The rune slice is not zeroed.
|
|
|
|
func rawruneslice(size int) (b []rune) {
|
|
|
|
if uintptr(size) > maxMem/4 {
|
|
|
|
gothrow("out of memory")
|
|
|
|
}
|
|
|
|
mem := goroundupsize(uintptr(size) * 4)
|
|
|
|
p := gomallocgc(mem, nil, flagNoScan|flagNoZero)
|
|
|
|
if mem != uintptr(size)*4 {
|
|
|
|
memclr(add(p, uintptr(size)*4), mem-uintptr(size)*4)
|
|
|
|
}
|
|
|
|
|
|
|
|
(*slice)(unsafe.Pointer(&b)).array = (*uint8)(p)
|
|
|
|
(*slice)(unsafe.Pointer(&b)).len = uint(size)
|
|
|
|
(*slice)(unsafe.Pointer(&b)).cap = uint(mem / 4)
|
|
|
|
return
|
|
|
|
}
|