diff options
Diffstat (limited to 'src/pkg/runtime/string.c')
-rw-r--r-- | src/pkg/runtime/string.c | 263 |
1 files changed, 263 insertions, 0 deletions
diff --git a/src/pkg/runtime/string.c b/src/pkg/runtime/string.c new file mode 100644 index 000000000..5bfe8196f --- /dev/null +++ b/src/pkg/runtime/string.c @@ -0,0 +1,263 @@ +// 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" + +String emptystring; + +int32 +findnull(byte *s) +{ + int32 l; + + if(s == nil) + return 0; + for(l=0; s[l]!=0; l++) + ; + return l; +} + +int32 maxstring; + +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; +} + +void +sys·catstring(String s1, String s2, String s3) +{ + if(s1.len == 0) { + s3 = s2; + goto out; + } + if(s2.len == 0) { + s3 = s1; + goto out; + } + + s3 = gostringsize(s1.len + s2.len); + mcpy(s3.str, s1.str, s1.len); + mcpy(s3.str+s1.len, s2.str, s2.len); + +out: + FLUSH(&s3); +} + +static void +prbounds(int8* s, int32 a, int32 b, int32 c) +{ + prints(s); + prints(" "); + sys·printint(a); + prints("<"); + sys·printint(b); + prints(">"); + sys·printint(c); + prints("\n"); + throw("string bounds"); +} + +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; +} + +void +sys·cmpstring(String s1, String s2, int32 v) +{ + v = cmpstring(s1, s2); + FLUSH(&v); +} + +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; + } +} + +void +sys·slicestring(String si, int32 lindex, int32 hindex, String so) +{ + int32 l; + + if(lindex < 0 || lindex > si.len || + hindex < lindex || hindex > si.len) { + sys·printpc(&si); + prints(" "); + prbounds("slice", lindex, si.len, hindex); + } + + 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); + + FLUSH(&so); +} + +void +sys·indexstring(String s, int32 i, byte b) +{ + if(i < 0 || i >= s.len) { + sys·printpc(&s); + prints(" "); + prbounds("index", 0, i, s.len); + } + + b = s.str[i]; + FLUSH(&b); +} + +void +sys·intstring(int64 v, String s) +{ + s = gostringsize(8); + s.len = runetochar(s.str, v); + FLUSH(&s); +} + +void +sys·arraystring(Array b, String s) +{ + s = gostringsize(b.nel); + mcpy(s.str, b.array, s.len); + FLUSH(&s); +} + +void +sys·arraystringi(Array b, String s) +{ + int32 siz1, siz2, i; + int32 *a; + byte dum[8]; + + a = (int32*)b.array; + siz1 = 0; + for(i=0; i<b.nel; i++) { + siz1 += runetochar(dum, a[i]); + } + + s = gostringsize(siz1+4); + siz2 = 0; + for(i=0; i<b.nel; i++) { + // check for race + if(siz2 >= siz1) + break; + siz2 += runetochar(s.str+siz2, a[i]); + } + s.len = siz2; + + FLUSH(&s); +} + +enum +{ + Runeself = 0x80, +}; + +// func stringiter(string, int) (retk int); +void +sys·stringiter(String s, int32 k, int32 retk) +{ + 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: + FLUSH(&retk); +} + +// func stringiter2(string, int) (retk int, retv any); +void +sys·stringiter2(String s, int32 k, int32 retk, int32 retv) +{ + 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: + FLUSH(&retk); + FLUSH(&retv); +} |