mirror of
https://github.com/golang/go
synced 2024-11-19 23:44:43 -07:00
0b08c9483f
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
377 lines
5.8 KiB
Plaintext
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:
|
|
}
|