| // 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<l; i++) { | |
| c1 = s1.str[i]; | |
| c2 = s2.str[i]; | |
| if(c1 < c2) | |
| return -1; | |
| if(c1 > 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<b.len; i++) { | |
| siz1 += runetochar(dum, a[i]); | |
| } | |
| s = gostringsize(siz1+4); | |
| siz2 = 0; | |
| for(i=0; i<b.len; i++) { | |
| // check for race | |
| if(siz2 >= 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: | |
| } |