// 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 "malloc.h" String emptystring; int32 findnull(byte *s) { int32 l; if(s == nil) return 0; for(l=0; s[l]!=0; l++) ; return l; } int32 findnullw(uint16 *s) { int32 l; if(s == nil) return 0; for(l=0; s[l]!=0; l++) ; return l; } int32 maxstring = 256; String gostringsize(int32 l) { String s; if(l == 0) return emptystring; s.str = mal(l+1); // leave room for NUL for C runtime (e.g., callers of getenv) s.len = l; if(l > maxstring) maxstring = l; return s; } String gostring(byte *str) { int32 l; String s; l = findnull(str); s = gostringsize(l); mcpy(s.str, str, l); return s; } String gostringnocopy(byte *str) { String s; s.str = str; s.len = findnull(str); return s; } String gostringw(uint16 *str) { int32 n, i; byte buf[8]; String s; n = 0; for(i=0; str[i]; i++) n += runetochar(buf, str[i]); s = gostringsize(n+4); n = 0; for(i=0; str[i]; i++) n += runetochar(s.str+n, str[i]); s.len = n; return s; } String 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); mcpy(s3.str, s1.str, s1.len); mcpy(s3.str+s1.len, s2.str, s2.len); return s3; } func catstring(s1 String, s2 String) (s3 String) { s3 = catstring(s1, s2); } uint32 cmpstring(String s1, String s2) { uint32 i, l; byte c1, c2; l = s1.len; if(s2.len < l) l = s2.len; 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 int32) { v = cmpstring(s1, s2); } int32 strcmp(byte *s1, byte *s2) { uint32 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; } } func slicestring(si String, lindex int32, hindex int32) (so String) { int32 l; if(lindex < 0 || lindex > si.len || hindex < lindex || hindex > si.len) { ·panicslice(); } l = hindex-lindex; so.str = si.str + lindex; so.len = l; // alternate to create a new string // so = gostringsize(l); // mcpy(so.str, si.str+lindex, l); } func slicestring1(si String, lindex int32) (so String) { int32 l; if(lindex < 0 || lindex > si.len) { ·panicslice(); } l = si.len-lindex; so.str = si.str + lindex; so.len = l; // alternate to create a new string // so = gostringsize(l); // mcpy(so.str, si.str+lindex, l); } func indexstring(s String, i int32) (b byte) { if(i < 0 || i >= s.len) { ·panicindex(); } b = s.str[i]; } func intstring(v int64) (s String) { s = gostringsize(8); s.len = runetochar(s.str, v); } func slicebytetostring(b Slice) (s String) { s = gostringsize(b.len); mcpy(s.str, b.array, s.len); } func stringtoslicebyte(s String) (b Slice) { b.array = mallocgc(s.len, RefNoPointers, 1, 1); b.len = s.len; b.cap = s.len; mcpy(b.array, s.str, s.len); } func sliceinttostring(b Slice) (s String) { int32 siz1, siz2, i; int32 *a; byte dum[8]; a = (int32*)b.array; siz1 = 0; for(i=0; i= siz1) break; siz2 += runetochar(s.str+siz2, a[i]); } s.len = siz2; } func stringtosliceint(s String) (b Slice) { int32 n; int32 dum, *r; uint8 *p, *ep; // two passes. // unlike sliceinttostring, no race because strings are immutable. p = s.str; ep = s.str+s.len; n = 0; while(p < ep) { p += charntorune(&dum, p, ep-p); n++; } b.array = mallocgc(n*sizeof(r[0]), RefNoPointers, 1, 1); b.len = n; b.cap = n; p = s.str; r = (int32*)b.array; while(p < ep) p += charntorune(r++, p, ep-p); } enum { Runeself = 0x80, }; func stringiter(s String, k int32) (retk int32) { 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 + charntorune(&l, s.str+k, s.len-k); out: } func stringiter2(s String, k int32) (retk int32, 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 + charntorune(&retv, s.str+k, s.len-k); out: }