summaryrefslogtreecommitdiff
path: root/src/pkg/runtime/string.goc
diff options
context:
space:
mode:
Diffstat (limited to 'src/pkg/runtime/string.goc')
-rw-r--r--src/pkg/runtime/string.goc360
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:
+}