// 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. #include "runtime.h" #include "arch_GOARCH.h" #include "malloc.h" #include "race.h" #include "textflag.h" String runtime·emptystring; #pragma textflag NOSPLIT intgo runtime·findnull(byte *s) { intgo l; if(s == nil) return 0; for(l=0; s[l]!=0; l++) ; return l; } intgo runtime·findnullw(uint16 *s) { intgo l; if(s == nil) return 0; for(l=0; s[l]!=0; l++) ; return l; } uintptr runtime·maxstring = 256; // a hint for print static String gostringsize(intgo l) { String s; uintptr ms; if(l == 0) return runtime·emptystring; s.str = runtime·mallocgc(l, 0, FlagNoScan|FlagNoZero); s.len = l; for(;;) { ms = runtime·maxstring; if((uintptr)l <= ms || runtime·casp((void**)&runtime·maxstring, (void*)ms, (void*)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; } // used by cmd/cgo Slice runtime·gobytes(byte *p, intgo n) { Slice sl; sl.array = runtime·mallocgc(n, 0, FlagNoScan|FlagNoZero); sl.len = n; sl.cap = n; runtime·memmove(sl.array, p, n); return sl; } #pragma textflag NOSPLIT String runtime·gostringnocopy(byte *str) { String s; s.str = str; s.len = runtime·findnull(str); return s; } // TODO: move this elsewhere enum { Bit1 = 7, Bitx = 6, Bit2 = 5, Bit3 = 4, Bit4 = 3, Bit5 = 2, Tx = ((1<<(Bitx+1))-1) ^ 0xFF, /* 1000 0000 */ T2 = ((1<<(Bit2+1))-1) ^ 0xFF, /* 1100 0000 */ T3 = ((1<<(Bit3+1))-1) ^ 0xFF, /* 1110 0000 */ T4 = ((1<<(Bit4+1))-1) ^ 0xFF, /* 1111 0000 */ Rune1 = (1<<(Bit1+0*Bitx))-1, /* 0000 0000 0111 1111 */ Rune2 = (1<<(Bit2+1*Bitx))-1, /* 0000 0111 1111 1111 */ Rune3 = (1<<(Bit3+2*Bitx))-1, /* 1111 1111 1111 1111 */ Maskx = (1< 00-7F */ c = rune; if(c <= Rune1) { str[0] = c; return 1; } /* * two character sequence * 0080-07FF => T2 Tx */ if(c <= Rune2) { str[0] = T2 | (c >> 1*Bitx); str[1] = Tx | (c & Maskx); return 2; } /* * If the Rune is out of range or a surrogate half, convert it to the error rune. * Do this test here because the error rune encodes to three bytes. * Doing it earlier would duplicate work, since an out of range * Rune wouldn't have fit in one or two bytes. */ if (c > Runemax) c = Runeerror; if (SurrogateMin <= c && c <= SurrogateMax) c = Runeerror; /* * three character sequence * 0800-FFFF => T3 Tx Tx */ if (c <= Rune3) { str[0] = T3 | (c >> 2*Bitx); str[1] = Tx | ((c >> 1*Bitx) & Maskx); str[2] = Tx | (c & Maskx); return 3; } /* * four character sequence (21-bit value) * 10000-1FFFFF => T4 Tx Tx Tx */ str[0] = T4 | (c >> 3*Bitx); str[1] = Tx | ((c >> 2*Bitx) & Maskx); str[2] = Tx | ((c >> 1*Bitx) & Maskx); str[3] = Tx | (c & Maskx); return 4; } String runtime·gostringw(uint16 *str) { intgo n1, n2, i; byte buf[8]; String s; n1 = 0; for(i=0; str[i]; i++) n1 += runetochar(buf, str[i]); s = gostringsize(n1+4); n2 = 0; for(i=0; str[i]; i++) { // check for race if(n2 >= n1) break; n2 += 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; } 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; } } int32 runtime·strncmp(byte *s1, byte *s2, uintptr n) { uintptr i; byte c1, c2; for(i=0; i c2) return +1; if(c1 == 0) break; } 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; }