| // Copyright 2009, 2010 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.h" |
| #include "malloc.h" |
| #include "go-string.h" |
| |
| #define charntorune(pv, str, len) __go_get_rune(str, len, pv) |
| |
| const String runtime_emptystring; |
| |
| intgo |
| runtime_findnull(const byte *s) |
| { |
| if(s == nil) |
| return 0; |
| return __builtin_strlen((const char*) s); |
| } |
| |
| intgo |
| runtime_findnullw(const uint16 *s) |
| { |
| intgo l; |
| |
| if(s == nil) |
| return 0; |
| for(l=0; s[l]!=0; l++) |
| ; |
| return l; |
| } |
| |
| static String |
| gostringsize(intgo l, byte** pmem) |
| { |
| String s; |
| byte *mem; |
| |
| if(l == 0) { |
| *pmem = nil; |
| return runtime_emptystring; |
| } |
| mem = runtime_mallocgc(l, 0, FlagNoScan|FlagNoZero); |
| s.str = mem; |
| s.len = l; |
| *pmem = mem; |
| return s; |
| } |
| |
| String |
| runtime_gostring(const byte *str) |
| { |
| intgo l; |
| String s; |
| byte *mem; |
| |
| l = runtime_findnull(str); |
| s = gostringsize(l, &mem); |
| runtime_memmove(mem, str, l); |
| return s; |
| } |
| |
| String |
| runtime_gostringnocopy(const byte *str) |
| { |
| String s; |
| |
| s.str = str; |
| s.len = runtime_findnull(str); |
| return s; |
| } |
| |
| func cstringToGo(str *byte) (s String) { |
| s = runtime_gostringnocopy(str); |
| } |
| |
| 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 + 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 + charntorune(&retv, s.str+k, s.len-k); |
| |
| out: |
| } |