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 }