github.com/xushiwei/go@v0.0.0-20130601165731-2b9d83f45bc9/src/pkg/runtime/string.goc (about)

     1  // Copyright 2009 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package runtime
     6  #include "runtime.h"
     7  #include "arch_GOARCH.h"
     8  #include "malloc.h"
     9  #include "race.h"
    10  
    11  String	runtime·emptystring;
    12  
    13  int32
    14  runtime·findnull(byte *s)
    15  {
    16  	int32 l;
    17  
    18  	if(s == nil)
    19  		return 0;
    20  	for(l=0; s[l]!=0; l++)
    21  		;
    22  	return l;
    23  }
    24  
    25  int32
    26  runtime·findnullw(uint16 *s)
    27  {
    28  	int32 l;
    29  
    30  	if(s == nil)
    31  		return 0;
    32  	for(l=0; s[l]!=0; l++)
    33  		;
    34  	return l;
    35  }
    36  
    37  uint32 runtime·maxstring = 256; // a hint for print
    38  
    39  static String
    40  gostringsize(intgo l)
    41  {
    42  	String s;
    43  	uint32 ms;
    44  
    45  	if(l == 0)
    46  		return runtime·emptystring;
    47  	// leave room for NUL for C runtime (e.g., callers of getenv)
    48  	s.str = runtime·mallocgc(l+1, FlagNoPointers, 1, 0);
    49  	s.len = l;
    50  	s.str[l] = 0;
    51  	for(;;) {
    52  		ms = runtime·maxstring;
    53  		if((uint32)l <= ms || runtime·cas(&runtime·maxstring, ms, (uint32)l))
    54  			break;
    55  	}
    56  	return s;
    57  }
    58  
    59  String
    60  runtime·gostring(byte *str)
    61  {
    62  	intgo l;
    63  	String s;
    64  
    65  	l = runtime·findnull(str);
    66  	s = gostringsize(l);
    67  	runtime·memmove(s.str, str, l);
    68  	return s;
    69  }
    70  
    71  String
    72  runtime·gostringn(byte *str, intgo l)
    73  {
    74  	String s;
    75  
    76  	s = gostringsize(l);
    77  	runtime·memmove(s.str, str, l);
    78  	return s;
    79  }
    80  
    81  Slice
    82  runtime·gobytes(byte *p, intgo n)
    83  {
    84  	Slice sl;
    85  
    86  	sl.array = runtime·mallocgc(n, FlagNoPointers, 1, 0);
    87  	sl.len = n;
    88  	sl.cap = n;
    89  	runtime·memmove(sl.array, p, n);
    90  	return sl;
    91  }
    92  
    93  String
    94  runtime·gostringnocopy(byte *str)
    95  {
    96  	String s;
    97  	
    98  	s.str = str;
    99  	s.len = runtime·findnull(str);
   100  	return s;
   101  }
   102  
   103  String
   104  runtime·gostringw(uint16 *str)
   105  {
   106  	intgo n1, n2, i;
   107  	byte buf[8];
   108  	String s;
   109  
   110  	n1 = 0;
   111  	for(i=0; str[i]; i++)
   112  		n1 += runtime·runetochar(buf, str[i]);
   113  	s = gostringsize(n1+4);
   114  	n2 = 0;
   115  	for(i=0; str[i]; i++) {
   116  		// check for race
   117  		if(n2 >= n1)
   118  			break;
   119  		n2 += runtime·runetochar(s.str+n2, str[i]);
   120  	}
   121  	s.len = n2;
   122  	s.str[s.len] = 0;
   123  	return s;
   124  }
   125  
   126  String
   127  runtime·catstring(String s1, String s2)
   128  {
   129  	String s3;
   130  
   131  	if(s1.len == 0)
   132  		return s2;
   133  	if(s2.len == 0)
   134  		return s1;
   135  
   136  	s3 = gostringsize(s1.len + s2.len);
   137  	runtime·memmove(s3.str, s1.str, s1.len);
   138  	runtime·memmove(s3.str+s1.len, s2.str, s2.len);
   139  	return s3;
   140  }
   141  
   142  static String
   143  concatstring(intgo n, String *s)
   144  {
   145  	intgo i, l, count;
   146  	String out;
   147  
   148  	l = 0;
   149  	count = 0;
   150  	for(i=0; i<n; i++) {
   151  		if(l + s[i].len < l)
   152  			runtime·throw("string concatenation too long");
   153  		l += s[i].len;
   154  		if(s[i].len > 0) {
   155  			count++;
   156  			out = s[i];
   157  		}
   158  	}
   159  	if(count == 0)
   160  		return runtime·emptystring;
   161  	if(count == 1) // zero or one non-empty string in concatenation
   162  		return out;
   163  	
   164  	out = gostringsize(l);
   165  	l = 0;
   166  	for(i=0; i<n; i++) {
   167  		runtime·memmove(out.str+l, s[i].str, s[i].len);
   168  		l += s[i].len;
   169  	}
   170  	return out;
   171  }
   172  
   173  #pragma textflag 7
   174  // s1 is the first of n strings.
   175  // the output string follows.
   176  func concatstring(n int, s1 String) {
   177  	(&s1)[n] = concatstring(n, &s1);
   178  }
   179  
   180  static int32
   181  cmpstring(String s1, String s2)
   182  {
   183  	uintgo i, l;
   184  	byte c1, c2;
   185  
   186  	l = s1.len;
   187  	if(s2.len < l)
   188  		l = s2.len;
   189  	for(i=0; i<l; i++) {
   190  		c1 = s1.str[i];
   191  		c2 = s2.str[i];
   192  		if(c1 < c2)
   193  			return -1;
   194  		if(c1 > c2)
   195  			return +1;
   196  	}
   197  	if(s1.len < s2.len)
   198  		return -1;
   199  	if(s1.len > s2.len)
   200  		return +1;
   201  	return 0;
   202  }
   203  
   204  func cmpstring(s1 String, s2 String) (v int) {
   205  	v = cmpstring(s1, s2);
   206  }
   207  
   208  func eqstring(s1 String, s2 String) (v bool) {
   209  	if(s1.len != s2.len) {
   210  		v = false;
   211  		return;
   212  	}
   213  	if(s1.str == s2.str) {
   214  		v = true;
   215  		return;
   216  	}
   217  	v = runtime·memeq(s1.str, s2.str, s1.len);
   218  }
   219  
   220  int32
   221  runtime·strcmp(byte *s1, byte *s2)
   222  {
   223  	uintptr i;
   224  	byte c1, c2;
   225  
   226  	for(i=0;; i++) {
   227  		c1 = s1[i];
   228  		c2 = s2[i];
   229  		if(c1 < c2)
   230  			return -1;
   231  		if(c1 > c2)
   232  			return +1;
   233  		if(c1 == 0)
   234  			return 0;
   235  	}
   236  }
   237  
   238  byte*
   239  runtime·strstr(byte *s1, byte *s2)
   240  {
   241  	byte *sp1, *sp2;
   242  
   243  	if(*s2 == 0)
   244  		return s1;
   245  	for(; *s1; s1++) {
   246  		if(*s1 != *s2)
   247  			continue;
   248  		sp1 = s1;
   249  		sp2 = s2;
   250  		for(;;) {
   251  			if(*sp2 == 0)
   252  				return s1;
   253  			if(*sp1++ != *sp2++)
   254  				break;
   255  		}
   256  	}
   257  	return nil;
   258  }
   259  
   260  func intstring(v int64) (s String) {
   261  	s = gostringsize(8);
   262  	s.len = runtime·runetochar(s.str, v);
   263  	s.str[s.len] = 0;
   264  }
   265  
   266  func slicebytetostring(b Slice) (s String) {
   267  	void *pc;
   268  
   269  	if(raceenabled) {
   270  		pc = runtime·getcallerpc(&b);
   271  		runtime·racereadrangepc(b.array, b.len, 1, pc, runtime·slicebytetostring);
   272  	}
   273  	s = gostringsize(b.len);
   274  	runtime·memmove(s.str, b.array, s.len);
   275  }
   276  
   277  func stringtoslicebyte(s String) (b Slice) {
   278  	b.array = runtime·mallocgc(s.len, FlagNoPointers, 1, 0);
   279  	b.len = s.len;
   280  	b.cap = s.len;
   281  	runtime·memmove(b.array, s.str, s.len);
   282  }
   283  
   284  func slicerunetostring(b Slice) (s String) {
   285  	intgo siz1, siz2, i;
   286  	int32 *a;
   287  	byte dum[8];
   288  	void *pc;
   289  
   290  	if(raceenabled) {
   291  		pc = runtime·getcallerpc(&b);
   292  		runtime·racereadrangepc(b.array, b.len*sizeof(*a), sizeof(*a), pc, runtime·slicerunetostring);
   293  	}
   294  	a = (int32*)b.array;
   295  	siz1 = 0;
   296  	for(i=0; i<b.len; i++) {
   297  		siz1 += runtime·runetochar(dum, a[i]);
   298  	}
   299  
   300  	s = gostringsize(siz1+4);
   301  	siz2 = 0;
   302  	for(i=0; i<b.len; i++) {
   303  		// check for race
   304  		if(siz2 >= siz1)
   305  			break;
   306  		siz2 += runtime·runetochar(s.str+siz2, a[i]);
   307  	}
   308  	s.len = siz2;
   309  	s.str[s.len] = 0;
   310  }
   311  
   312  func stringtoslicerune(s String) (b Slice) {
   313  	intgo n;
   314  	int32 dum, *r;
   315  	uint8 *p, *ep;
   316  
   317  	// two passes.
   318  	// unlike slicerunetostring, no race because strings are immutable.
   319  	p = s.str;
   320  	ep = s.str+s.len;
   321  	n = 0;
   322  	while(p < ep) {
   323  		p += runtime·charntorune(&dum, p, ep-p);
   324  		n++;
   325  	}
   326  
   327  	b.array = runtime·mallocgc(n*sizeof(r[0]), FlagNoPointers, 1, 0);
   328  	b.len = n;
   329  	b.cap = n;
   330  	p = s.str;
   331  	r = (int32*)b.array;
   332  	while(p < ep)
   333  		p += runtime·charntorune(r++, p, ep-p);
   334  }
   335  
   336  enum
   337  {
   338  	Runeself	= 0x80,
   339  };
   340  
   341  func stringiter(s String, k int) (retk int) {
   342  	int32 l;
   343  
   344  	if(k >= s.len) {
   345  		// retk=0 is end of iteration
   346  		retk = 0;
   347  		goto out;
   348  	}
   349  
   350  	l = s.str[k];
   351  	if(l < Runeself) {
   352  		retk = k+1;
   353  		goto out;
   354  	}
   355  
   356  	// multi-char rune
   357  	retk = k + runtime·charntorune(&l, s.str+k, s.len-k);
   358  
   359  out:
   360  }
   361  
   362  func stringiter2(s String, k int) (retk int, retv int32) {
   363  	if(k >= s.len) {
   364  		// retk=0 is end of iteration
   365  		retk = 0;
   366  		retv = 0;
   367  		goto out;
   368  	}
   369  
   370  	retv = s.str[k];
   371  	if(retv < Runeself) {
   372  		retk = k+1;
   373  		goto out;
   374  	}
   375  
   376  	// multi-char rune
   377  	retk = k + runtime·charntorune(&retv, s.str+k, s.len-k);
   378  
   379  out:
   380  }