diff options
| author | Keith Randall <khr@golang.org> | 2014-06-16 23:03:03 -0700 |
|---|---|---|
| committer | Keith Randall <khr@golang.org> | 2014-06-16 23:03:03 -0700 |
| commit | 61dca94e107170d2ff3beb13bb9fa5ce49d8d6fd (patch) | |
| tree | 83dadbcc4200dbb0e014f366cf07302a25011ed3 /src/pkg/runtime/string.c | |
| parent | b36ed9056ff57c04c34240f2dc6b1bb59e84d0c7 (diff) | |
| download | go-61dca94e107170d2ff3beb13bb9fa5ce49d8d6fd.tar.xz | |
runtime: implement string ops in Go
Also implement go:nosplit annotation. Not really needed
for now, but we'll definitely need it for other conversions.
benchmark old ns/op new ns/op delta
BenchmarkRuneIterate 534 474 -11.24%
BenchmarkRuneIterate2 535 470 -12.15%
LGTM=bradfitz
R=golang-codereviews, dave, bradfitz, minux
CC=golang-codereviews
https://golang.org/cl/93380044
Diffstat (limited to 'src/pkg/runtime/string.c')
| -rw-r--r-- | src/pkg/runtime/string.c | 199 |
1 files changed, 199 insertions, 0 deletions
diff --git a/src/pkg/runtime/string.c b/src/pkg/runtime/string.c new file mode 100644 index 0000000000..d5b668bd61 --- /dev/null +++ b/src/pkg/runtime/string.c @@ -0,0 +1,199 @@ +// 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" +#include "arch_GOARCH.h" +#include "malloc.h" +#include "race.h" +#include "../../cmd/ld/textflag.h" + +String runtime·emptystring; + +#pragma textflag NOSPLIT +intgo +runtime·findnull(byte *s) +{ + intgo l; + + if(s == nil) + return 0; + for(l=0; s[l]!=0; l++) + ; + return l; +} + +intgo +runtime·findnullw(uint16 *s) +{ + intgo l; + + if(s == nil) + return 0; + for(l=0; s[l]!=0; l++) + ; + return l; +} + +uintptr runtime·maxstring = 256; // a hint for print + +static String +gostringsize(intgo l) +{ + String s; + uintptr ms; + + if(l == 0) + return runtime·emptystring; + s.str = runtime·mallocgc(l, 0, FlagNoScan|FlagNoZero); + s.len = l; + for(;;) { + ms = runtime·maxstring; + if((uintptr)l <= ms || runtime·casp((void**)&runtime·maxstring, (void*)ms, (void*)l)) + break; + } + return s; +} + +String +runtime·gostring(byte *str) +{ + intgo l; + String s; + + l = runtime·findnull(str); + s = gostringsize(l); + runtime·memmove(s.str, str, l); + return s; +} + +String +runtime·gostringn(byte *str, intgo l) +{ + String s; + + s = gostringsize(l); + runtime·memmove(s.str, str, l); + return s; +} + +// used by cmd/cgo +Slice +runtime·gobytes(byte *p, intgo n) +{ + Slice sl; + + sl.array = runtime·mallocgc(n, 0, FlagNoScan|FlagNoZero); + sl.len = n; + sl.cap = n; + 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) +{ + intgo n1, n2, i; + byte buf[8]; + String s; + + n1 = 0; + for(i=0; str[i]; i++) + n1 += runtime·runetochar(buf, str[i]); + s = gostringsize(n1+4); + n2 = 0; + for(i=0; str[i]; i++) { + // check for race + if(n2 >= n1) + break; + n2 += runtime·runetochar(s.str+n2, str[i]); + } + s.len = n2; + s.str[s.len] = 0; + return s; +} + +String +runtime·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); + runtime·memmove(s3.str, s1.str, s1.len); + runtime·memmove(s3.str+s1.len, s2.str, s2.len); + return s3; +} + +int32 +runtime·strcmp(byte *s1, byte *s2) +{ + uintptr 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; + } +} + +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) +{ + 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; +} |
