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