1
0
mirror of https://github.com/golang/go synced 2024-11-19 23:44:43 -07:00
go/src/pkg/runtime/string.goc
Russ Cox 0b08c9483f runtime: prepare for 64-bit ints
This CL makes the runtime understand that the type of
the len or cap of a map, slice, or string is 'int', not 'int32',
and it is also careful to distinguish between function arguments
and results of type 'int' vs type 'int32'.

In the runtime, the new typedefs 'intgo' and 'uintgo' refer
to Go int and uint. The C types int and uint continue to be
unavailable (cause intentional compile errors).

This CL does not change the meaning of int, but it should make
the eventual change of the meaning of int on amd64 a bit
smoother.

Update #2188.

R=iant, r, dave, remyoudompheng
CC=golang-dev
https://golang.org/cl/6551067
2012-09-24 14:58:34 -04:00

377 lines
5.8 KiB
Plaintext

// 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 "arch_GOARCH.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; // a hint for print
static String
gostringsize(intgo l)
{
String s;
uint32 ms;
if(l == 0)
return runtime·emptystring;
// leave room for NUL for C runtime (e.g., callers of getenv)
s.str = runtime·mallocgc(l+1, FlagNoPointers, 1, 0);
s.len = l;
s.str[l] = 0;
for(;;) {
ms = runtime·maxstring;
if((uint32)l <= ms || runtime·cas(&runtime·maxstring, ms, (uint32)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;
}
Slice
runtime·gobytes(byte *p, intgo n)
{
Slice sl;
sl.array = runtime·mallocgc(n, FlagNoPointers, 1, 0);
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;
}
static String
concatstring(intgo n, String *s)
{
intgo i, l, count;
String out;
l = 0;
count = 0;
for(i=0; i<n; i++) {
if(l + s[i].len < l)
runtime·throw("string concatenation too long");
l += s[i].len;
if(s[i].len > 0) {
count++;
out = s[i];
}
}
if(count == 0)
return runtime·emptystring;
if(count == 1) // zero or one non-empty string in concatenation
return out;
out = 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 int, s1 String) {
(&s1)[n] = concatstring(n, &s1);
}
static int32
cmpstring(String s1, String s2)
{
uintgo 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 int) {
v = cmpstring(s1, s2);
}
func eqstring(s1 String, s2 String) (v bool) {
uintgo i, l;
if(s1.len != s2.len) {
v = false;
return;
}
if(s1.str == s2.str) {
v = true;
return;
}
l = s1.len;
for(i=0; i<l; i++)
if(s1.str[i] != s2.str[i]) {
v = false;
return;
}
v = true;
}
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;
}
}
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 intstring(v int64) (s String) {
s = gostringsize(8);
s.len = runtime·runetochar(s.str, v);
s.str[s.len] = 0;
}
func slicebytetostring(b Slice) (s String) {
s = 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, 0);
b.len = s.len;
b.cap = s.len;
runtime·memmove(b.array, s.str, s.len);
}
func slicerunetostring(b Slice) (s String) {
intgo 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 = 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;
s.str[s.len] = 0;
}
func stringtoslicerune(s String) (b Slice) {
intgo n;
int32 dum, *r;
uint8 *p, *ep;
// two passes.
// unlike slicerunetostring, 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, 0);
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 int) (retk int) {
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 int) (retk int, 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:
}