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

View as plain text