Source file src/runtime/string.go

     1  // Copyright 2014 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package runtime
     6  
     7  import (
     8  	"internal/abi"
     9  	"internal/bytealg"
    10  	"internal/goarch"
    11  	"internal/runtime/math"
    12  	"internal/runtime/strconv"
    13  	"internal/runtime/sys"
    14  	"unsafe"
    15  )
    16  
    17  // The constant is known to the compiler.
    18  // There is no fundamental theory behind this number.
    19  const tmpStringBufSize = 32
    20  
    21  type tmpBuf [tmpStringBufSize]byte
    22  
    23  // concatstrings implements a Go string concatenation x+y+z+...
    24  // The operands are passed in the slice a.
    25  // If buf != nil, the compiler has determined that the result does not
    26  // escape the calling function, so the string data can be stored in buf
    27  // if small enough.
    28  func concatstrings(buf *tmpBuf, a []string) string {
    29  	idx := 0
    30  	l := 0
    31  	count := 0
    32  	for i, x := range a {
    33  		n := len(x)
    34  		if n == 0 {
    35  			continue
    36  		}
    37  		if l+n < l {
    38  			throw("string concatenation too long")
    39  		}
    40  		l += n
    41  		count++
    42  		idx = i
    43  	}
    44  	if count == 0 {
    45  		return ""
    46  	}
    47  
    48  	// If there is just one string and either it is not on the stack
    49  	// or our result does not escape the calling frame (buf != nil),
    50  	// then we can return that string directly.
    51  	if count == 1 && (buf != nil || !stringDataOnStack(a[idx])) {
    52  		return a[idx]
    53  	}
    54  	s, b := rawstringtmp(buf, l)
    55  	for _, x := range a {
    56  		n := copy(b, x)
    57  		b = b[n:]
    58  	}
    59  	return s
    60  }
    61  
    62  func concatstring2(buf *tmpBuf, a0, a1 string) string {
    63  	return concatstrings(buf, []string{a0, a1})
    64  }
    65  
    66  func concatstring3(buf *tmpBuf, a0, a1, a2 string) string {
    67  	return concatstrings(buf, []string{a0, a1, a2})
    68  }
    69  
    70  func concatstring4(buf *tmpBuf, a0, a1, a2, a3 string) string {
    71  	return concatstrings(buf, []string{a0, a1, a2, a3})
    72  }
    73  
    74  func concatstring5(buf *tmpBuf, a0, a1, a2, a3, a4 string) string {
    75  	return concatstrings(buf, []string{a0, a1, a2, a3, a4})
    76  }
    77  
    78  // concatbytes implements a Go string concatenation x+y+z+... returning a slice
    79  // of bytes.
    80  // The operands are passed in the slice a.
    81  func concatbytes(buf *tmpBuf, a []string) []byte {
    82  	l := 0
    83  	for _, x := range a {
    84  		n := len(x)
    85  		if l+n < l {
    86  			throw("string concatenation too long")
    87  		}
    88  		l += n
    89  	}
    90  	if l == 0 {
    91  		// This is to match the return type of the non-optimized concatenation.
    92  		return []byte{}
    93  	}
    94  
    95  	var b []byte
    96  	if buf != nil && l <= len(buf) {
    97  		*buf = tmpBuf{}
    98  		b = buf[:l]
    99  	} else {
   100  		b = rawbyteslice(l)
   101  	}
   102  	offset := 0
   103  	for _, x := range a {
   104  		copy(b[offset:], x)
   105  		offset += len(x)
   106  	}
   107  
   108  	return b
   109  }
   110  
   111  func concatbyte2(buf *tmpBuf, a0, a1 string) []byte {
   112  	return concatbytes(buf, []string{a0, a1})
   113  }
   114  
   115  func concatbyte3(buf *tmpBuf, a0, a1, a2 string) []byte {
   116  	return concatbytes(buf, []string{a0, a1, a2})
   117  }
   118  
   119  func concatbyte4(buf *tmpBuf, a0, a1, a2, a3 string) []byte {
   120  	return concatbytes(buf, []string{a0, a1, a2, a3})
   121  }
   122  
   123  func concatbyte5(buf *tmpBuf, a0, a1, a2, a3, a4 string) []byte {
   124  	return concatbytes(buf, []string{a0, a1, a2, a3, a4})
   125  }
   126  
   127  // slicebytetostring converts a byte slice to a string.
   128  // It is inserted by the compiler into generated code.
   129  // ptr is a pointer to the first element of the slice;
   130  // n is the length of the slice.
   131  // Buf is a fixed-size buffer for the result,
   132  // it is not nil if the result does not escape.
   133  func slicebytetostring(buf *tmpBuf, ptr *byte, n int) string {
   134  	if n == 0 {
   135  		// Turns out to be a relatively common case.
   136  		// Consider that you want to parse out data between parens in "foo()bar",
   137  		// you find the indices and convert the subslice to string.
   138  		return ""
   139  	}
   140  	if raceenabled {
   141  		racereadrangepc(unsafe.Pointer(ptr),
   142  			uintptr(n),
   143  			sys.GetCallerPC(),
   144  			abi.FuncPCABIInternal(slicebytetostring))
   145  	}
   146  	if msanenabled {
   147  		msanread(unsafe.Pointer(ptr), uintptr(n))
   148  	}
   149  	if asanenabled {
   150  		asanread(unsafe.Pointer(ptr), uintptr(n))
   151  	}
   152  	if n == 1 {
   153  		p := unsafe.Pointer(&staticuint64s[*ptr])
   154  		if goarch.BigEndian {
   155  			p = add(p, 7)
   156  		}
   157  		return unsafe.String((*byte)(p), 1)
   158  	}
   159  
   160  	var p unsafe.Pointer
   161  	if buf != nil && n <= len(buf) {
   162  		p = unsafe.Pointer(buf)
   163  	} else {
   164  		p = mallocgc(uintptr(n), nil, false)
   165  	}
   166  	memmove(p, unsafe.Pointer(ptr), uintptr(n))
   167  	return unsafe.String((*byte)(p), n)
   168  }
   169  
   170  // stringDataOnStack reports whether the string's data is
   171  // stored on the current goroutine's stack.
   172  func stringDataOnStack(s string) bool {
   173  	ptr := uintptr(unsafe.Pointer(unsafe.StringData(s)))
   174  	stk := getg().stack
   175  	return stk.lo <= ptr && ptr < stk.hi
   176  }
   177  
   178  func rawstringtmp(buf *tmpBuf, l int) (s string, b []byte) {
   179  	if buf != nil && l <= len(buf) {
   180  		b = buf[:l]
   181  		s = slicebytetostringtmp(&b[0], len(b))
   182  	} else {
   183  		s, b = rawstring(l)
   184  	}
   185  	return
   186  }
   187  
   188  // slicebytetostringtmp returns a "string" referring to the actual []byte bytes.
   189  //
   190  // Callers need to ensure that the returned string will not be used after
   191  // the calling goroutine modifies the original slice or synchronizes with
   192  // another goroutine.
   193  //
   194  // The function is only called when instrumenting
   195  // and otherwise intrinsified by the compiler.
   196  //
   197  // Some internal compiler optimizations use this function.
   198  //   - Used for m[T1{... Tn{..., string(k), ...} ...}] and m[string(k)]
   199  //     where k is []byte, T1 to Tn is a nesting of struct and array literals.
   200  //   - Used for "<"+string(b)+">" concatenation where b is []byte.
   201  //   - Used for string(b)=="foo" comparison where b is []byte.
   202  func slicebytetostringtmp(ptr *byte, n int) string {
   203  	if raceenabled && n > 0 {
   204  		racereadrangepc(unsafe.Pointer(ptr),
   205  			uintptr(n),
   206  			sys.GetCallerPC(),
   207  			abi.FuncPCABIInternal(slicebytetostringtmp))
   208  	}
   209  	if msanenabled && n > 0 {
   210  		msanread(unsafe.Pointer(ptr), uintptr(n))
   211  	}
   212  	if asanenabled && n > 0 {
   213  		asanread(unsafe.Pointer(ptr), uintptr(n))
   214  	}
   215  	return unsafe.String(ptr, n)
   216  }
   217  
   218  func stringtoslicebyte(buf *tmpBuf, s string) []byte {
   219  	var b []byte
   220  	if buf != nil && len(s) <= len(buf) {
   221  		*buf = tmpBuf{}
   222  		b = buf[:len(s)]
   223  	} else {
   224  		b = rawbyteslice(len(s))
   225  	}
   226  	copy(b, s)
   227  	return b
   228  }
   229  
   230  func stringtoslicerune(buf *[tmpStringBufSize]rune, s string) []rune {
   231  	// two passes.
   232  	// unlike slicerunetostring, no race because strings are immutable.
   233  	n := 0
   234  	for range s {
   235  		n++
   236  	}
   237  
   238  	var a []rune
   239  	if buf != nil && n <= len(buf) {
   240  		*buf = [tmpStringBufSize]rune{}
   241  		a = buf[:n]
   242  	} else {
   243  		a = rawruneslice(n)
   244  	}
   245  
   246  	n = 0
   247  	for _, r := range s {
   248  		a[n] = r
   249  		n++
   250  	}
   251  	return a
   252  }
   253  
   254  func slicerunetostring(buf *tmpBuf, a []rune) string {
   255  	if raceenabled && len(a) > 0 {
   256  		racereadrangepc(unsafe.Pointer(&a[0]),
   257  			uintptr(len(a))*unsafe.Sizeof(a[0]),
   258  			sys.GetCallerPC(),
   259  			abi.FuncPCABIInternal(slicerunetostring))
   260  	}
   261  	if msanenabled && len(a) > 0 {
   262  		msanread(unsafe.Pointer(&a[0]), uintptr(len(a))*unsafe.Sizeof(a[0]))
   263  	}
   264  	if asanenabled && len(a) > 0 {
   265  		asanread(unsafe.Pointer(&a[0]), uintptr(len(a))*unsafe.Sizeof(a[0]))
   266  	}
   267  	var dum [4]byte
   268  	size1 := 0
   269  	for _, r := range a {
   270  		size1 += encoderune(dum[:], r)
   271  	}
   272  	s, b := rawstringtmp(buf, size1+3)
   273  	size2 := 0
   274  	for _, r := range a {
   275  		// check for race
   276  		if size2 >= size1 {
   277  			break
   278  		}
   279  		size2 += encoderune(b[size2:], r)
   280  	}
   281  	return s[:size2]
   282  }
   283  
   284  type stringStruct struct {
   285  	str unsafe.Pointer
   286  	len int
   287  }
   288  
   289  // Variant with *byte pointer type for DWARF debugging.
   290  type stringStructDWARF struct {
   291  	str *byte
   292  	len int
   293  }
   294  
   295  func stringStructOf(sp *string) *stringStruct {
   296  	return (*stringStruct)(unsafe.Pointer(sp))
   297  }
   298  
   299  func intstring(buf *[4]byte, v int64) (s string) {
   300  	var b []byte
   301  	if buf != nil {
   302  		b = buf[:]
   303  		s = slicebytetostringtmp(&b[0], len(b))
   304  	} else {
   305  		s, b = rawstring(4)
   306  	}
   307  	if int64(rune(v)) != v {
   308  		v = runeError
   309  	}
   310  	n := encoderune(b, rune(v))
   311  	return s[:n]
   312  }
   313  
   314  // rawstring allocates storage for a new string. The returned
   315  // string and byte slice both refer to the same storage.
   316  // The storage is not zeroed. Callers should use
   317  // b to set the string contents and then drop b.
   318  func rawstring(size int) (s string, b []byte) {
   319  	p := mallocgc(uintptr(size), nil, false)
   320  	return unsafe.String((*byte)(p), size), unsafe.Slice((*byte)(p), size)
   321  }
   322  
   323  // rawbyteslice allocates a new byte slice. The byte slice is not zeroed.
   324  func rawbyteslice(size int) (b []byte) {
   325  	cap := roundupsize(uintptr(size), true)
   326  	p := mallocgc(cap, nil, false)
   327  	if cap != uintptr(size) {
   328  		memclrNoHeapPointers(add(p, uintptr(size)), cap-uintptr(size))
   329  	}
   330  
   331  	*(*slice)(unsafe.Pointer(&b)) = slice{p, size, int(cap)}
   332  	return
   333  }
   334  
   335  // rawruneslice allocates a new rune slice. The rune slice is not zeroed.
   336  func rawruneslice(size int) (b []rune) {
   337  	if uintptr(size) > maxAlloc/4 {
   338  		throw("out of memory")
   339  	}
   340  	mem := roundupsize(uintptr(size)*4, true)
   341  	p := mallocgc(mem, nil, false)
   342  	if mem != uintptr(size)*4 {
   343  		memclrNoHeapPointers(add(p, uintptr(size)*4), mem-uintptr(size)*4)
   344  	}
   345  
   346  	*(*slice)(unsafe.Pointer(&b)) = slice{p, size, int(mem / 4)}
   347  	return
   348  }
   349  
   350  // used by cmd/cgo
   351  func gobytes(p *byte, n int) (b []byte) {
   352  	if n == 0 {
   353  		return make([]byte, 0)
   354  	}
   355  
   356  	if n < 0 || uintptr(n) > maxAlloc {
   357  		panic(errorString("gobytes: length out of range"))
   358  	}
   359  
   360  	bp := mallocgc(uintptr(n), nil, false)
   361  	memmove(bp, unsafe.Pointer(p), uintptr(n))
   362  
   363  	*(*slice)(unsafe.Pointer(&b)) = slice{bp, n, n}
   364  	return
   365  }
   366  
   367  // This is exported via linkname to assembly in syscall (for Plan9) and cgo.
   368  //
   369  //go:linkname gostring
   370  func gostring(p *byte) string {
   371  	l := findnull(p)
   372  	if l == 0 {
   373  		return ""
   374  	}
   375  	s, b := rawstring(l)
   376  	memmove(unsafe.Pointer(&b[0]), unsafe.Pointer(p), uintptr(l))
   377  	return s
   378  }
   379  
   380  // internal_syscall_gostring is a version of gostring for internal/syscall/unix.
   381  //
   382  //go:linkname internal_syscall_gostring internal/syscall/unix.gostring
   383  func internal_syscall_gostring(p *byte) string {
   384  	return gostring(p)
   385  }
   386  
   387  func gostringn(p *byte, l int) string {
   388  	if l == 0 {
   389  		return ""
   390  	}
   391  	s, b := rawstring(l)
   392  	memmove(unsafe.Pointer(&b[0]), unsafe.Pointer(p), uintptr(l))
   393  	return s
   394  }
   395  
   396  // parseByteCount parses a string that represents a count of bytes.
   397  //
   398  // s must match the following regular expression:
   399  //
   400  //	^[0-9]+(([KMGT]i)?B)?$
   401  //
   402  // In other words, an integer byte count with an optional unit
   403  // suffix. Acceptable suffixes include one of
   404  // - KiB, MiB, GiB, TiB which represent binary IEC/ISO 80000 units, or
   405  // - B, which just represents bytes.
   406  //
   407  // Returns an int64 because that's what its callers want and receive,
   408  // but the result is always non-negative.
   409  func parseByteCount(s string) (int64, bool) {
   410  	// The empty string is not valid.
   411  	if s == "" {
   412  		return 0, false
   413  	}
   414  	// Handle the easy non-suffix case.
   415  	last := s[len(s)-1]
   416  	if last >= '0' && last <= '9' {
   417  		n, ok := strconv.Atoi64(s)
   418  		if !ok || n < 0 {
   419  			return 0, false
   420  		}
   421  		return n, ok
   422  	}
   423  	// Failing a trailing digit, this must always end in 'B'.
   424  	// Also at this point there must be at least one digit before
   425  	// that B.
   426  	if last != 'B' || len(s) < 2 {
   427  		return 0, false
   428  	}
   429  	// The one before that must always be a digit or 'i'.
   430  	if c := s[len(s)-2]; c >= '0' && c <= '9' {
   431  		// Trivial 'B' suffix.
   432  		n, ok := strconv.Atoi64(s[:len(s)-1])
   433  		if !ok || n < 0 {
   434  			return 0, false
   435  		}
   436  		return n, ok
   437  	} else if c != 'i' {
   438  		return 0, false
   439  	}
   440  	// Finally, we need at least 4 characters now, for the unit
   441  	// prefix and at least one digit.
   442  	if len(s) < 4 {
   443  		return 0, false
   444  	}
   445  	power := 0
   446  	switch s[len(s)-3] {
   447  	case 'K':
   448  		power = 1
   449  	case 'M':
   450  		power = 2
   451  	case 'G':
   452  		power = 3
   453  	case 'T':
   454  		power = 4
   455  	default:
   456  		// Invalid suffix.
   457  		return 0, false
   458  	}
   459  	m := uint64(1)
   460  	for i := 0; i < power; i++ {
   461  		m *= 1024
   462  	}
   463  	n, ok := strconv.Atoi64(s[:len(s)-3])
   464  	if !ok || n < 0 {
   465  		return 0, false
   466  	}
   467  	un := uint64(n)
   468  	if un > math.MaxUint64/m {
   469  		// Overflow.
   470  		return 0, false
   471  	}
   472  	un *= m
   473  	if un > uint64(math.MaxInt64) {
   474  		// Overflow.
   475  		return 0, false
   476  	}
   477  	return int64(un), true
   478  }
   479  
   480  //go:nosplit
   481  func findnull(s *byte) int {
   482  	if s == nil {
   483  		return 0
   484  	}
   485  
   486  	// Avoid IndexByteString on Plan 9 because it uses SSE instructions
   487  	// on x86 machines, and those are classified as floating point instructions,
   488  	// which are illegal in a note handler.
   489  	if GOOS == "plan9" {
   490  		p := (*[maxAlloc/2 - 1]byte)(unsafe.Pointer(s))
   491  		l := 0
   492  		for p[l] != 0 {
   493  			l++
   494  		}
   495  		return l
   496  	}
   497  
   498  	// pageSize is the unit we scan at a time looking for NULL.
   499  	// It must be the minimum page size for any architecture Go
   500  	// runs on. It's okay (just a minor performance loss) if the
   501  	// actual system page size is larger than this value.
   502  	const pageSize = 4096
   503  
   504  	offset := 0
   505  	ptr := unsafe.Pointer(s)
   506  	// IndexByteString uses wide reads, so we need to be careful
   507  	// with page boundaries. Call IndexByteString on
   508  	// [ptr, endOfPage) interval.
   509  	safeLen := int(pageSize - uintptr(ptr)%pageSize)
   510  
   511  	for {
   512  		t := *(*string)(unsafe.Pointer(&stringStruct{ptr, safeLen}))
   513  		// Check one page at a time.
   514  		if i := bytealg.IndexByteString(t, 0); i != -1 {
   515  			return offset + i
   516  		}
   517  		// Move to next page
   518  		ptr = unsafe.Pointer(uintptr(ptr) + uintptr(safeLen))
   519  		offset += safeLen
   520  		safeLen = pageSize
   521  	}
   522  }
   523  
   524  func findnullw(s *uint16) int {
   525  	if s == nil {
   526  		return 0
   527  	}
   528  	p := (*[maxAlloc/2/2 - 1]uint16)(unsafe.Pointer(s))
   529  	l := 0
   530  	for p[l] != 0 {
   531  		l++
   532  	}
   533  	return l
   534  }
   535  
   536  //go:nosplit
   537  func gostringnocopy(str *byte) string {
   538  	ss := stringStruct{str: unsafe.Pointer(str), len: findnull(str)}
   539  	s := *(*string)(unsafe.Pointer(&ss))
   540  	return s
   541  }
   542  
   543  func gostringw(strw *uint16) string {
   544  	var buf [8]byte
   545  	str := (*[maxAlloc/2/2 - 1]uint16)(unsafe.Pointer(strw))
   546  	n1 := 0
   547  	for i := 0; str[i] != 0; i++ {
   548  		n1 += encoderune(buf[:], rune(str[i]))
   549  	}
   550  	s, b := rawstring(n1 + 4)
   551  	n2 := 0
   552  	for i := 0; str[i] != 0; i++ {
   553  		// check for race
   554  		if n2 >= n1 {
   555  			break
   556  		}
   557  		n2 += encoderune(b[n2:], rune(str[i]))
   558  	}
   559  	b[n2] = 0 // for luck
   560  	return s[:n2]
   561  }
   562  

View as plain text