diff options
Diffstat (limited to 'src/pkg/runtime/string.goc')
-rw-r--r-- | src/pkg/runtime/string.goc | 360 |
1 files changed, 360 insertions, 0 deletions
diff --git a/src/pkg/runtime/string.goc b/src/pkg/runtime/string.goc new file mode 100644 index 000000000..48bf3183b --- /dev/null +++ b/src/pkg/runtime/string.goc @@ -0,0 +1,360 @@ +// 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 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; + +String +runtime·gostringsize(int32 l) +{ + String s; + uint32 ms; + + if(l == 0) + return runtime·emptystring; + s.str = runtime·mal(l+1); // leave room for NUL for C runtime (e.g., callers of getenv) + s.len = l; + for(;;) { + ms = runtime·maxstring; + if((uint32)l <= ms || runtime·cas(&runtime·maxstring, ms, (uint32)l)) + break; + } + return s; +} + +String +runtime·gostring(byte *str) +{ + int32 l; + String s; + + l = runtime·findnull(str); + s = runtime·gostringsize(l); + runtime·memmove(s.str, str, l); + return s; +} + +String +runtime·gostringn(byte *str, int32 l) +{ + String s; + + s = runtime·gostringsize(l); + runtime·memmove(s.str, str, l); + return s; +} + +Slice +runtime·gobytes(byte *p, int32 n) +{ + Slice sl; + + sl.array = runtime·mallocgc(n, FlagNoPointers, 1, 0); + 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) +{ + int32 n, i; + byte buf[8]; + String s; + + n = 0; + for(i=0; str[i]; i++) + n += runtime·runetochar(buf, str[i]); + s = runtime·gostringsize(n+4); + n = 0; + for(i=0; str[i]; i++) + n += runtime·runetochar(s.str+n, str[i]); + s.len = n; + return s; +} + +String +runtime·catstring(String s1, String s2) +{ + String s3; + + if(s1.len == 0) + return s2; + if(s2.len == 0) + return s1; + + s3 = runtime·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(int32 n, String *s) +{ + int32 i, l; + String out; + + l = 0; + for(i=0; i<n; i++) { + if(l + s[i].len < l) + runtime·throw("string concatenation too long"); + l += s[i].len; + } + + out = runtime·gostringsize(l); + l = 0; + for(i=0; i<n; i++) { + runtime·memmove(out.str+l, s[i].str, s[i].len); + l += s[i].len; + } + return out; +} + +#pragma textflag 7 +// s1 is the first of n strings. +// the output string follows. +func concatstring(n int32, s1 String) { + (&s1)[n] = concatstring(n, &s1); +} + +static int32 +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 +runtime·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; + } +} + +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 slicestring(si String, lindex int32, hindex int32) (so String) { + int32 l; + + if(lindex < 0 || lindex > si.len || + hindex < lindex || hindex > si.len) { + runtime·panicslice(); + } + + l = hindex-lindex; + so.str = si.str + lindex; + so.len = l; +} + +func slicestring1(si String, lindex int32) (so String) { + int32 l; + + if(lindex < 0 || lindex > si.len) { + runtime·panicslice(); + } + + l = si.len-lindex; + so.str = si.str + lindex; + so.len = l; +} + +func intstring(v int64) (s String) { + s = runtime·gostringsize(8); + s.len = runtime·runetochar(s.str, v); +} + +func slicebytetostring(b Slice) (s String) { + s = runtime·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, 1); + b.len = s.len; + b.cap = s.len; + runtime·memmove(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 += runtime·runetochar(dum, a[i]); + } + + s = runtime·gostringsize(siz1+4); + siz2 = 0; + for(i=0; i<b.len; i++) { + // check for race + if(siz2 >= siz1) + break; + siz2 += runtime·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 += runtime·charntorune(&dum, p, ep-p); + n++; + } + + b.array = runtime·mallocgc(n*sizeof(r[0]), FlagNoPointers, 1, 1); + 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 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 + runtime·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 + runtime·charntorune(&retv, s.str+k, s.len-k); + +out: +} |