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 }