// Copyright 2009 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 #include "runtime.h" #include "arch_GOARCH.h" #include "malloc.h" #include "race.h" String runtime·emptystring; int32 runtime·findnull(byte *s) { int32 l; if(s == nil) return 0; for(l=0; s[l]!=0; l++) ; return l; } int32 runtime·findnullw(uint16 *s) { int32 l; if(s == nil) return 0; for(l=0; s[l]!=0; l++) ; return l; } uint32 runtime·maxstring = 256; // a hint for print static String gostringsize(intgo l) { String s; uint32 ms; if(l == 0) return runtime·emptystring; // leave room for NUL for C runtime (e.g., callers of getenv) s.str = runtime·mallocgc(l+1, FlagNoPointers, 1, 0); s.len = l; s.str[l] = 0; for(;;) { ms = runtime·maxstring; if((uint32)l <= ms || runtime·cas(&runtime·maxstring, ms, (uint32)l)) break; } return s; } String runtime·gostring(byte *str) { intgo l; String s; l = runtime·findnull(str); s = gostringsize(l); runtime·memmove(s.str, str, l); return s; } String runtime·gostringn(byte *str, intgo l) { String s; s = gostringsize(l); runtime·memmove(s.str, str, l); return s; } Slice runtime·gobytes(byte *p, intgo n) { Slice sl; sl.array = runtime·mallocgc(n, FlagNoPointers, 1, 0); sl.len = n; sl.cap = n; runtime·memmove(sl.array, p, n); return sl; } String runtime·gostringnocopy(byte *str) { String s; s.str = str; s.len = runtime·findnull(str); return s; } String runtime·gostringw(uint16 *str) { intgo n1, n2, i; byte buf[8]; String s; n1 = 0; for(i=0; str[i]; i++) n1 += runtime·runetochar(buf, str[i]); s = gostringsize(n1+4); n2 = 0; for(i=0; str[i]; i++) { // check for race if(n2 >= n1) break; n2 += runtime·runetochar(s.str+n2, str[i]); } s.len = n2; s.str[s.len] = 0; return s; } String runtime·catstring(String s1, String s2) { String s3; if(s1.len == 0) return s2; if(s2.len == 0) return s1; s3 = gostringsize(s1.len + s2.len); runtime·memmove(s3.str, s1.str, s1.len); runtime·memmove(s3.str+s1.len, s2.str, s2.len); return s3; } static String concatstring(intgo n, String *s) { intgo i, l, count; String out; l = 0; count = 0; for(i=0; i 0) { count++; out = s[i]; } } if(count == 0) return runtime·emptystring; if(count == 1) // zero or one non-empty string in concatenation return out; out = gostringsize(l); l = 0; for(i=0; i c2) return +1; } if(s1.len < s2.len) return -1; if(s1.len > s2.len) return +1; return 0; } func cmpstring(s1 String, s2 String) (v int) { v = cmpstring(s1, s2); } func eqstring(s1 String, s2 String) (v bool) { if(s1.len != s2.len) { v = false; return; } if(s1.str == s2.str) { v = true; return; } v = runtime·memeq(s1.str, s2.str, s1.len); } int32 runtime·strcmp(byte *s1, byte *s2) { uintptr i; byte c1, c2; for(i=0;; i++) { c1 = s1[i]; c2 = s2[i]; if(c1 < c2) return -1; if(c1 > c2) return +1; if(c1 == 0) return 0; } } byte* runtime·strstr(byte *s1, byte *s2) { byte *sp1, *sp2; if(*s2 == 0) return s1; for(; *s1; s1++) { if(*s1 != *s2) continue; sp1 = s1; sp2 = s2; for(;;) { if(*sp2 == 0) return s1; if(*sp1++ != *sp2++) break; } } return nil; } func intstring(v int64) (s String) { s = gostringsize(8); s.len = runtime·runetochar(s.str, v); s.str[s.len] = 0; } func slicebytetostring(b Slice) (s String) { void *pc; if(raceenabled) { pc = runtime·getcallerpc(&b); runtime·racereadrangepc(b.array, b.len, 1, pc, runtime·slicebytetostring); } s = gostringsize(b.len); runtime·memmove(s.str, b.array, s.len); } func stringtoslicebyte(s String) (b Slice) { b.array = runtime·mallocgc(s.len, FlagNoPointers, 1, 0); b.len = s.len; b.cap = s.len; runtime·memmove(b.array, s.str, s.len); } func slicerunetostring(b Slice) (s String) { intgo siz1, siz2, i; int32 *a; byte dum[8]; void *pc; if(raceenabled) { pc = runtime·getcallerpc(&b); runtime·racereadrangepc(b.array, b.len*sizeof(*a), sizeof(*a), pc, runtime·slicerunetostring); } a = (int32*)b.array; siz1 = 0; for(i=0; i= siz1) break; siz2 += runtime·runetochar(s.str+siz2, a[i]); } s.len = siz2; s.str[s.len] = 0; } func stringtoslicerune(s String) (b Slice) { intgo n; int32 dum, *r; uint8 *p, *ep; // two passes. // unlike slicerunetostring, no race because strings are immutable. p = s.str; ep = s.str+s.len; n = 0; while(p < ep) { p += runtime·charntorune(&dum, p, ep-p); n++; } b.array = runtime·mallocgc(n*sizeof(r[0]), FlagNoPointers, 1, 0); b.len = n; b.cap = n; p = s.str; r = (int32*)b.array; while(p < ep) p += runtime·charntorune(r++, p, ep-p); } enum { Runeself = 0x80, }; func stringiter(s String, k int) (retk int) { int32 l; if(k >= s.len) { // retk=0 is end of iteration retk = 0; goto out; } l = s.str[k]; if(l < Runeself) { retk = k+1; goto out; } // multi-char rune retk = k + runtime·charntorune(&l, s.str+k, s.len-k); out: } func stringiter2(s String, k int) (retk int, retv int32) { if(k >= s.len) { // retk=0 is end of iteration retk = 0; retv = 0; goto out; } retv = s.str[k]; if(retv < Runeself) { retk = k+1; goto out; } // multi-char rune retk = k + runtime·charntorune(&retv, s.str+k, s.len-k); out: }