...

Source file src/runtime/string.go

Documentation: runtime

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

View as plain text