diff options
Diffstat (limited to 'src/pkg/runtime/string.goc')
-rw-r--r-- | src/pkg/runtime/string.goc | 102 |
1 files changed, 84 insertions, 18 deletions
diff --git a/src/pkg/runtime/string.goc b/src/pkg/runtime/string.goc index b79acbe1c..97a69d07b 100644 --- a/src/pkg/runtime/string.goc +++ b/src/pkg/runtime/string.goc @@ -46,10 +46,8 @@ gostringsize(intgo l) if(l == 0) return runtime·emptystring; - // leave room for NUL for C runtime (e.g., callers of getenv) - s.str = runtime·mallocgc(l+1, 0, FlagNoScan|FlagNoZero); + s.str = runtime·mallocgc(l, 0, FlagNoScan|FlagNoZero); s.len = l; - s.str[l] = 0; for(;;) { ms = runtime·maxstring; if((uintptr)l <= ms || runtime·casp((void**)&runtime·maxstring, (void*)ms, (void*)l)) @@ -80,6 +78,7 @@ runtime·gostringn(byte *str, intgo l) return s; } +// used by cmd/cgo Slice runtime·gobytes(byte *p, intgo n) { @@ -102,11 +101,8 @@ runtime·gostringnocopy(byte *str) return s; } -void -runtime·cstringToGo(byte *str, String s) -{ +func cstringToGo(str *byte) (s String) { s = runtime·gostringnocopy(str); - FLUSH(&s); } String @@ -179,14 +175,35 @@ concatstring(intgo n, String *s) return out; } -// NOTE: Cannot use func syntax, because we need the ..., -// to signal to the garbage collector that this function does -// not have a fixed size argument count. #pragma textflag NOSPLIT -void -runtime·concatstring(intgo n, String s1, ...) -{ - (&s1)[n] = concatstring(n, &s1); +func concatstring2(s1 String, s2 String) (res String) { + USED(&s2); + res = concatstring(2, &s1); +} +#pragma textflag NOSPLIT +func concatstring3(s1 String, s2 String, s3 String) (res String) { + USED(&s2); + USED(&s3); + res = concatstring(3, &s1); +} +#pragma textflag NOSPLIT +func concatstring4(s1 String, s2 String, s3 String, s4 String) (res String) { + USED(&s2); + USED(&s3); + USED(&s4); + res = concatstring(4, &s1); +} +#pragma textflag NOSPLIT +func concatstring5(s1 String, s2 String, s3 String, s4 String, s5 String) (res String) { + USED(&s2); + USED(&s3); + USED(&s4); + USED(&s5); + res = concatstring(5, &s1); +} +#pragma textflag NOSPLIT +func concatstrings(s Slice) (res String) { + res = concatstring(s.len, (String*)s.array); } func eqstring(s1 String, s2 String) (v bool) { @@ -219,6 +236,25 @@ runtime·strcmp(byte *s1, byte *s2) } } +int32 +runtime·strncmp(byte *s1, byte *s2, uintptr n) +{ + uintptr i; + byte c1, c2; + + for(i=0; i<n; i++) { + c1 = s1[i]; + c2 = s2[i]; + if(c1 < c2) + return -1; + if(c1 > c2) + return +1; + if(c1 == 0) + break; + } + return 0; +} + byte* runtime·strstr(byte *s1, byte *s2) { @@ -258,11 +294,35 @@ func slicebytetostring(b Slice) (s String) { runtime·memmove(s.str, b.array, s.len); } +func slicebytetostringtmp(b Slice) (s String) { + void *pc; + + if(raceenabled) { + pc = runtime·getcallerpc(&b); + runtime·racereadrangepc(b.array, b.len, pc, runtime·slicebytetostringtmp); + } + + // Return a "string" referring to the actual []byte bytes. + // This is only for use by internal compiler optimizations + // that know that the string form will be discarded before + // the calling goroutine could possibly modify the original + // slice or synchronize with another goroutine. + // Today, the only such case is a m[string(k)] lookup where + // m is a string-keyed map and k is a []byte. + s.str = b.array; + s.len = b.len; +} + func stringtoslicebyte(s String) (b Slice) { - b.array = runtime·mallocgc(s.len, 0, FlagNoScan|FlagNoZero); + uintptr cap; + + cap = runtime·roundupsize(s.len); + b.array = runtime·mallocgc(cap, 0, FlagNoScan|FlagNoZero); b.len = s.len; - b.cap = s.len; + b.cap = cap; runtime·memmove(b.array, s.str, s.len); + if(cap != b.len) + runtime·memclr(b.array+b.len, cap-b.len); } func slicerunetostring(b Slice) (s String) { @@ -297,6 +357,7 @@ func stringtoslicerune(s String) (b Slice) { intgo n; int32 dum, *r; uint8 *p, *ep; + uintptr mem; // two passes. // unlike slicerunetostring, no race because strings are immutable. @@ -308,13 +369,18 @@ func stringtoslicerune(s String) (b Slice) { n++; } - b.array = runtime·mallocgc(n*sizeof(r[0]), 0, FlagNoScan|FlagNoZero); + if(n > MaxMem/sizeof(r[0])) + runtime·throw("out of memory"); + mem = runtime·roundupsize(n*sizeof(r[0])); + b.array = runtime·mallocgc(mem, 0, FlagNoScan|FlagNoZero); b.len = n; - b.cap = n; + b.cap = mem/sizeof(r[0]); p = s.str; r = (int32*)b.array; while(p < ep) p += runtime·charntorune(r++, p, ep-p); + if(b.cap > b.len) + runtime·memclr(b.array+b.len*sizeof(r[0]), (b.cap-b.len)*sizeof(r[0])); } enum |