// 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 (
	
	
	
)

// The constant is known to the compiler.
// There is no fundamental theory behind this number.
const tmpStringBufSize = 32

type tmpBuf [tmpStringBufSize]byte

// concatstrings implements a Go string concatenation x+y+z+...
// The operands are passed in the slice a.
// If buf != nil, the compiler has determined that the result does not
// escape the calling function, so the string data can be stored in buf
// if small enough.
func concatstrings( *tmpBuf,  []string) string {
	 := 0
	 := 0
	 := 0
	for ,  := range  {
		 := len()
		if  == 0 {
			continue
		}
		if + <  {
			throw("string concatenation too long")
		}
		 += 
		++
		 = 
	}
	if  == 0 {
		return ""
	}

	// If there is just one string and either it is not on the stack
	// or our result does not escape the calling frame (buf != nil),
	// then we can return that string directly.
	if  == 1 && ( != nil || !stringDataOnStack([])) {
		return []
	}
	,  := rawstringtmp(, )
	for ,  := range  {
		copy(, )
		 = [len():]
	}
	return 
}

func concatstring2( *tmpBuf,  [2]string) string {
	return concatstrings(, [:])
}

func concatstring3( *tmpBuf,  [3]string) string {
	return concatstrings(, [:])
}

func concatstring4( *tmpBuf,  [4]string) string {
	return concatstrings(, [:])
}

func concatstring5( *tmpBuf,  [5]string) string {
	return concatstrings(, [:])
}

// slicebytetostring converts a byte slice to a string.
// It is inserted by the compiler into generated code.
// ptr is a pointer to the first element of the slice;
// n is the length of the slice.
// Buf is a fixed-size buffer for the result,
// it is not nil if the result does not escape.
func slicebytetostring( *tmpBuf,  *byte,  int) ( string) {
	if  == 0 {
		// Turns out to be a relatively common case.
		// Consider that you want to parse out data between parens in "foo()bar",
		// you find the indices and convert the subslice to string.
		return ""
	}
	if raceenabled {
		racereadrangepc(unsafe.Pointer(),
			uintptr(),
			getcallerpc(),
			funcPC())
	}
	if msanenabled {
		msanread(unsafe.Pointer(), uintptr())
	}
	if  == 1 {
		 := unsafe.Pointer(&staticuint64s[*])
		if sys.BigEndian {
			 = add(, 7)
		}
		stringStructOf(&).str = 
		stringStructOf(&).len = 1
		return
	}

	var  unsafe.Pointer
	if  != nil &&  <= len() {
		 = unsafe.Pointer()
	} else {
		 = mallocgc(uintptr(), nil, false)
	}
	stringStructOf(&).str = 
	stringStructOf(&).len = 
	memmove(, unsafe.Pointer(), uintptr())
	return
}

// stringDataOnStack reports whether the string's data is
// stored on the current goroutine's stack.
func stringDataOnStack( string) bool {
	 := uintptr(stringStructOf(&).str)
	 := getg().stack
	return .lo <=  &&  < .hi
}

func rawstringtmp( *tmpBuf,  int) ( string,  []byte) {
	if  != nil &&  <= len() {
		 = [:]
		 = slicebytetostringtmp(&[0], len())
	} else {
		,  = rawstring()
	}
	return
}

// slicebytetostringtmp returns a "string" referring to the actual []byte bytes.
//
// Callers need to ensure that the returned string will not be used after
// the calling goroutine modifies the original slice or synchronizes with
// another goroutine.
//
// The function is only called when instrumenting
// and otherwise intrinsified by the compiler.
//
// Some internal compiler optimizations use this function.
// - Used for m[T1{... Tn{..., string(k), ...} ...}] and m[string(k)]
//   where k is []byte, T1 to Tn is a nesting of struct and array literals.
// - Used for "<"+string(b)+">" concatenation where b is []byte.
// - Used for string(b)=="foo" comparison where b is []byte.
func slicebytetostringtmp( *byte,  int) ( string) {
	if raceenabled &&  > 0 {
		racereadrangepc(unsafe.Pointer(),
			uintptr(),
			getcallerpc(),
			funcPC())
	}
	if msanenabled &&  > 0 {
		msanread(unsafe.Pointer(), uintptr())
	}
	stringStructOf(&).str = unsafe.Pointer()
	stringStructOf(&).len = 
	return
}

func stringtoslicebyte( *tmpBuf,  string) []byte {
	var  []byte
	if  != nil && len() <= len() {
		* = tmpBuf{}
		 = [:len()]
	} else {
		 = rawbyteslice(len())
	}
	copy(, )
	return 
}

func stringtoslicerune( *[tmpStringBufSize]rune,  string) []rune {
	// two passes.
	// unlike slicerunetostring, no race because strings are immutable.
	 := 0
	for range  {
		++
	}

	var  []rune
	if  != nil &&  <= len() {
		* = [tmpStringBufSize]rune{}
		 = [:]
	} else {
		 = rawruneslice()
	}

	 = 0
	for ,  := range  {
		[] = 
		++
	}
	return 
}

func slicerunetostring( *tmpBuf,  []rune) string {
	if raceenabled && len() > 0 {
		racereadrangepc(unsafe.Pointer(&[0]),
			uintptr(len())*unsafe.Sizeof([0]),
			getcallerpc(),
			funcPC())
	}
	if msanenabled && len() > 0 {
		msanread(unsafe.Pointer(&[0]), uintptr(len())*unsafe.Sizeof([0]))
	}
	var  [4]byte
	 := 0
	for ,  := range  {
		 += encoderune([:], )
	}
	,  := rawstringtmp(, +3)
	 := 0
	for ,  := range  {
		// check for race
		if  >=  {
			break
		}
		 += encoderune([:], )
	}
	return [:]
}

type stringStruct struct {
	str unsafe.Pointer
	len int
}

// Variant with *byte pointer type for DWARF debugging.
type stringStructDWARF struct {
	str *byte
	len int
}

func stringStructOf( *string) *stringStruct {
	return (*stringStruct)(unsafe.Pointer())
}

func intstring( *[4]byte,  int64) ( string) {
	var  []byte
	if  != nil {
		 = [:]
		 = slicebytetostringtmp(&[0], len())
	} else {
		,  = rawstring(4)
	}
	if int64(rune()) !=  {
		 = runeError
	}
	 := encoderune(, rune())
	return [:]
}

// 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( int) ( string,  []byte) {
	 := mallocgc(uintptr(), nil, false)

	stringStructOf(&).str = 
	stringStructOf(&).len = 

	*(*slice)(unsafe.Pointer(&)) = slice{, , }

	return
}

// rawbyteslice allocates a new byte slice. The byte slice is not zeroed.
func rawbyteslice( int) ( []byte) {
	 := roundupsize(uintptr())
	 := mallocgc(, nil, false)
	if  != uintptr() {
		memclrNoHeapPointers(add(, uintptr()), -uintptr())
	}

	*(*slice)(unsafe.Pointer(&)) = slice{, , int()}
	return
}

// rawruneslice allocates a new rune slice. The rune slice is not zeroed.
func rawruneslice( int) ( []rune) {
	if uintptr() > maxAlloc/4 {
		throw("out of memory")
	}
	 := roundupsize(uintptr() * 4)
	 := mallocgc(, nil, false)
	if  != uintptr()*4 {
		memclrNoHeapPointers(add(, uintptr()*4), -uintptr()*4)
	}

	*(*slice)(unsafe.Pointer(&)) = slice{, , int( / 4)}
	return
}

// used by cmd/cgo
func gobytes( *byte,  int) ( []byte) {
	if  == 0 {
		return make([]byte, 0)
	}

	if  < 0 || uintptr() > maxAlloc {
		panic(errorString("gobytes: length out of range"))
	}

	 := mallocgc(uintptr(), nil, false)
	memmove(, unsafe.Pointer(), uintptr())

	*(*slice)(unsafe.Pointer(&)) = slice{, , }
	return
}

// This is exported via linkname to assembly in syscall (for Plan9).
//go:linkname gostring
func gostring( *byte) string {
	 := findnull()
	if  == 0 {
		return ""
	}
	,  := rawstring()
	memmove(unsafe.Pointer(&[0]), unsafe.Pointer(), uintptr())
	return 
}

func gostringn( *byte,  int) string {
	if  == 0 {
		return ""
	}
	,  := rawstring()
	memmove(unsafe.Pointer(&[0]), unsafe.Pointer(), uintptr())
	return 
}

func hasPrefix(,  string) bool {
	return len() >= len() && [:len()] == 
}

const (
	maxUint = ^uint(0)
	maxInt  = int(maxUint >> 1)
)

// atoi parses an int from a string s.
// The bool result reports whether s is a number
// representable by a value of type int.
func atoi( string) (int, bool) {
	if  == "" {
		return 0, false
	}

	 := false
	if [0] == '-' {
		 = true
		 = [1:]
	}

	 := uint(0)
	for  := 0;  < len(); ++ {
		 := []
		if  < '0' ||  > '9' {
			return 0, false
		}
		if  > maxUint/10 {
			// overflow
			return 0, false
		}
		 *= 10
		 :=  + uint() - '0'
		if  <  {
			// overflow
			return 0, false
		}
		 = 
	}

	if ! &&  > uint(maxInt) {
		return 0, false
	}
	if  &&  > uint(maxInt)+1 {
		return 0, false
	}

	 := int()
	if  {
		 = -
	}

	return , true
}

// atoi32 is like atoi but for integers
// that fit into an int32.
func atoi32( string) (int32, bool) {
	if ,  := atoi();  == int(int32()) {
		return int32(), 
	}
	return 0, false
}

//go:nosplit
func findnull( *byte) int {
	if  == nil {
		return 0
	}

	// Avoid IndexByteString on Plan 9 because it uses SSE instructions
	// on x86 machines, and those are classified as floating point instructions,
	// which are illegal in a note handler.
	if GOOS == "plan9" {
		 := (*[maxAlloc/2 - 1]byte)(unsafe.Pointer())
		 := 0
		for [] != 0 {
			++
		}
		return 
	}

	// pageSize is the unit we scan at a time looking for NULL.
	// It must be the minimum page size for any architecture Go
	// runs on. It's okay (just a minor performance loss) if the
	// actual system page size is larger than this value.
	const  = 4096

	 := 0
	 := unsafe.Pointer()
	// IndexByteString uses wide reads, so we need to be careful
	// with page boundaries. Call IndexByteString on
	// [ptr, endOfPage) interval.
	 := int( - uintptr()%)

	for {
		 := *(*string)(unsafe.Pointer(&stringStruct{, }))
		// Check one page at a time.
		if  := bytealg.IndexByteString(, 0);  != -1 {
			return  + 
		}
		// Move to next page
		 = unsafe.Pointer(uintptr() + uintptr())
		 += 
		 = 
	}
}

func findnullw( *uint16) int {
	if  == nil {
		return 0
	}
	 := (*[maxAlloc/2/2 - 1]uint16)(unsafe.Pointer())
	 := 0
	for [] != 0 {
		++
	}
	return 
}

//go:nosplit
func gostringnocopy( *byte) string {
	 := stringStruct{str: unsafe.Pointer(), len: findnull()}
	 := *(*string)(unsafe.Pointer(&))
	return 
}

func gostringw( *uint16) string {
	var  [8]byte
	 := (*[maxAlloc/2/2 - 1]uint16)(unsafe.Pointer())
	 := 0
	for  := 0; [] != 0; ++ {
		 += encoderune([:], rune([]))
	}
	,  := rawstring( + 4)
	 := 0
	for  := 0; [] != 0; ++ {
		// check for race
		if  >=  {
			break
		}
		 += encoderune([:], rune([]))
	}
	[] = 0 // for luck
	return [:]
}