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 "unsafe" 9 ) 10 11 // The constant is known to the compiler. 12 // There is no fundamental theory behind this number. 13 const tmpStringBufSize = 32 14 15 type tmpBuf [tmpStringBufSize]byte 16 17 // concatstrings implements a Go string concatenation x+y+z+... 18 // The operands are passed in the slice a. 19 // If buf != nil, the compiler has determined that the result does not 20 // escape the calling function, so the string data can be stored in buf 21 // if small enough. 22 func concatstrings(buf *tmpBuf, a []string) string { 23 idx := 0 24 l := 0 25 count := 0 26 for i, x := range a { 27 n := len(x) 28 if n == 0 { 29 continue 30 } 31 if l+n < l { 32 throw("string concatenation too long") 33 } 34 l += n 35 count++ 36 idx = i 37 } 38 if count == 0 { 39 return "" 40 } 41 42 // If there is just one string and either it is not on the stack 43 // or our result does not escape the calling frame (buf != nil), 44 // then we can return that string directly. 45 if count == 1 && (buf != nil || !stringDataOnStack(a[idx])) { 46 return a[idx] 47 } 48 s, b := rawstringtmp(buf, l) 49 l = 0 50 for _, x := range a { 51 copy(b[l:], x) 52 l += len(x) 53 } 54 return s 55 } 56 57 func concatstring2(buf *tmpBuf, a [2]string) string { 58 return concatstrings(buf, a[:]) 59 } 60 61 func concatstring3(buf *tmpBuf, a [3]string) string { 62 return concatstrings(buf, a[:]) 63 } 64 65 func concatstring4(buf *tmpBuf, a [4]string) string { 66 return concatstrings(buf, a[:]) 67 } 68 69 func concatstring5(buf *tmpBuf, a [5]string) string { 70 return concatstrings(buf, a[:]) 71 } 72 73 // Buf is a fixed-size buffer for the result, 74 // it is not nil if the result does not escape. 75 func slicebytetostring(buf *tmpBuf, b []byte) string { 76 l := len(b) 77 if l == 0 { 78 // Turns out to be a relatively common case. 79 // Consider that you want to parse out data between parens in "foo()bar", 80 // you find the indices and convert the subslice to string. 81 return "" 82 } 83 if raceenabled && l > 0 { 84 racereadrangepc(unsafe.Pointer(&b[0]), 85 uintptr(l), 86 getcallerpc(unsafe.Pointer(&b)), 87 funcPC(slicebytetostring)) 88 } 89 s, c := rawstringtmp(buf, l) 90 copy(c, b) 91 return s 92 } 93 94 // stringDataOnStack reports whether the string's data is 95 // stored on the current goroutine's stack. 96 func stringDataOnStack(s string) bool { 97 ptr := uintptr((*stringStruct)(unsafe.Pointer(&s)).str) 98 stk := getg().stack 99 return stk.lo <= ptr && ptr < stk.hi 100 } 101 102 func rawstringtmp(buf *tmpBuf, l int) (s string, b []byte) { 103 if buf != nil && l <= len(buf) { 104 b = buf[:l] 105 s = slicebytetostringtmp(b) 106 } else { 107 s, b = rawstring(l) 108 } 109 return 110 } 111 112 func slicebytetostringtmp(b []byte) string { 113 // Return a "string" referring to the actual []byte bytes. 114 // This is only for use by internal compiler optimizations 115 // that know that the string form will be discarded before 116 // the calling goroutine could possibly modify the original 117 // slice or synchronize with another goroutine. 118 // First such case is a m[string(k)] lookup where 119 // m is a string-keyed map and k is a []byte. 120 // Second such case is "<"+string(b)+">" concatenation where b is []byte. 121 // Third such case is string(b)=="foo" comparison where b is []byte. 122 123 if raceenabled && len(b) > 0 { 124 racereadrangepc(unsafe.Pointer(&b[0]), 125 uintptr(len(b)), 126 getcallerpc(unsafe.Pointer(&b)), 127 funcPC(slicebytetostringtmp)) 128 } 129 return *(*string)(unsafe.Pointer(&b)) 130 } 131 132 func stringtoslicebyte(buf *tmpBuf, s string) []byte { 133 var b []byte 134 if buf != nil && len(s) <= len(buf) { 135 b = buf[:len(s)] 136 } else { 137 b = rawbyteslice(len(s)) 138 } 139 copy(b, s) 140 return b 141 } 142 143 func stringtoslicebytetmp(s string) []byte { 144 // Return a slice referring to the actual string bytes. 145 // This is only for use by internal compiler optimizations 146 // that know that the slice won't be mutated. 147 // The only such case today is: 148 // for i, c := range []byte(str) 149 150 str := (*stringStruct)(unsafe.Pointer(&s)) 151 ret := slice{array: unsafe.Pointer(str.str), len: str.len, cap: str.len} 152 return *(*[]byte)(unsafe.Pointer(&ret)) 153 } 154 155 func stringtoslicerune(buf *[tmpStringBufSize]rune, s string) []rune { 156 // two passes. 157 // unlike slicerunetostring, no race because strings are immutable. 158 n := 0 159 t := s 160 for len(s) > 0 { 161 _, k := charntorune(s) 162 s = s[k:] 163 n++ 164 } 165 var a []rune 166 if buf != nil && n <= len(buf) { 167 a = buf[:n] 168 } else { 169 a = rawruneslice(n) 170 } 171 n = 0 172 for len(t) > 0 { 173 r, k := charntorune(t) 174 t = t[k:] 175 a[n] = r 176 n++ 177 } 178 return a 179 } 180 181 func slicerunetostring(buf *tmpBuf, a []rune) string { 182 if raceenabled && len(a) > 0 { 183 racereadrangepc(unsafe.Pointer(&a[0]), 184 uintptr(len(a))*unsafe.Sizeof(a[0]), 185 getcallerpc(unsafe.Pointer(&a)), 186 funcPC(slicerunetostring)) 187 } 188 var dum [4]byte 189 size1 := 0 190 for _, r := range a { 191 size1 += runetochar(dum[:], r) 192 } 193 s, b := rawstringtmp(buf, size1+3) 194 size2 := 0 195 for _, r := range a { 196 // check for race 197 if size2 >= size1 { 198 break 199 } 200 size2 += runetochar(b[size2:], r) 201 } 202 return s[:size2] 203 } 204 205 type stringStruct struct { 206 str unsafe.Pointer 207 len int 208 } 209 210 func intstring(buf *[4]byte, v int64) string { 211 var s string 212 var b []byte 213 if buf != nil { 214 b = buf[:] 215 s = slicebytetostringtmp(b) 216 } else { 217 s, b = rawstring(4) 218 } 219 n := runetochar(b, rune(v)) 220 return s[:n] 221 } 222 223 // stringiter returns the index of the next 224 // rune after the rune that starts at s[k]. 225 func stringiter(s string, k int) int { 226 if k >= len(s) { 227 // 0 is end of iteration 228 return 0 229 } 230 231 c := s[k] 232 if c < runeself { 233 return k + 1 234 } 235 236 // multi-char rune 237 _, n := charntorune(s[k:]) 238 return k + n 239 } 240 241 // stringiter2 returns the rune that starts at s[k] 242 // and the index where the next rune starts. 243 func stringiter2(s string, k int) (int, rune) { 244 if k >= len(s) { 245 // 0 is end of iteration 246 return 0, 0 247 } 248 249 c := s[k] 250 if c < runeself { 251 return k + 1, rune(c) 252 } 253 254 // multi-char rune 255 r, n := charntorune(s[k:]) 256 return k + n, r 257 } 258 259 // rawstring allocates storage for a new string. The returned 260 // string and byte slice both refer to the same storage. 261 // The storage is not zeroed. Callers should use 262 // b to set the string contents and then drop b. 263 func rawstring(size int) (s string, b []byte) { 264 p := mallocgc(uintptr(size), nil, flagNoScan|flagNoZero) 265 266 (*stringStruct)(unsafe.Pointer(&s)).str = p 267 (*stringStruct)(unsafe.Pointer(&s)).len = size 268 269 *(*slice)(unsafe.Pointer(&b)) = slice{p, size, size} 270 271 for { 272 ms := maxstring 273 if uintptr(size) <= uintptr(ms) || casuintptr((*uintptr)(unsafe.Pointer(&maxstring)), uintptr(ms), uintptr(size)) { 274 return 275 } 276 } 277 } 278 279 // rawbyteslice allocates a new byte slice. The byte slice is not zeroed. 280 func rawbyteslice(size int) (b []byte) { 281 cap := roundupsize(uintptr(size)) 282 p := mallocgc(cap, nil, flagNoScan|flagNoZero) 283 if cap != uintptr(size) { 284 memclr(add(p, uintptr(size)), cap-uintptr(size)) 285 } 286 287 *(*slice)(unsafe.Pointer(&b)) = slice{p, size, int(cap)} 288 return 289 } 290 291 // rawruneslice allocates a new rune slice. The rune slice is not zeroed. 292 func rawruneslice(size int) (b []rune) { 293 if uintptr(size) > _MaxMem/4 { 294 throw("out of memory") 295 } 296 mem := roundupsize(uintptr(size) * 4) 297 p := mallocgc(mem, nil, flagNoScan|flagNoZero) 298 if mem != uintptr(size)*4 { 299 memclr(add(p, uintptr(size)*4), mem-uintptr(size)*4) 300 } 301 302 *(*slice)(unsafe.Pointer(&b)) = slice{p, size, int(mem / 4)} 303 return 304 } 305 306 // used by cmd/cgo 307 func gobytes(p *byte, n int) []byte { 308 if n == 0 { 309 return make([]byte, 0) 310 } 311 x := make([]byte, n) 312 memmove(unsafe.Pointer(&x[0]), unsafe.Pointer(p), uintptr(n)) 313 return x 314 } 315 316 func gostring(p *byte) string { 317 l := findnull(p) 318 if l == 0 { 319 return "" 320 } 321 s, b := rawstring(l) 322 memmove(unsafe.Pointer(&b[0]), unsafe.Pointer(p), uintptr(l)) 323 return s 324 } 325 326 func gostringn(p *byte, l int) string { 327 if l == 0 { 328 return "" 329 } 330 s, b := rawstring(l) 331 memmove(unsafe.Pointer(&b[0]), unsafe.Pointer(p), uintptr(l)) 332 return s 333 } 334 335 func index(s, t string) int { 336 if len(t) == 0 { 337 return 0 338 } 339 for i := 0; i < len(s); i++ { 340 if s[i] == t[0] && hasprefix(s[i:], t) { 341 return i 342 } 343 } 344 return -1 345 } 346 347 func contains(s, t string) bool { 348 return index(s, t) >= 0 349 } 350 351 func hasprefix(s, t string) bool { 352 return len(s) >= len(t) && s[:len(t)] == t 353 } 354 355 func atoi(s string) int { 356 n := 0 357 for len(s) > 0 && '0' <= s[0] && s[0] <= '9' { 358 n = n*10 + int(s[0]) - '0' 359 s = s[1:] 360 } 361 return n 362 } 363