github.com/gotranspile/cxgo@v0.3.7/runtime/libc/wstring.go (about) 1 package libc 2 3 import ( 4 "strconv" 5 "strings" 6 "unicode/utf8" 7 "unsafe" 8 ) 9 10 const WCharSize = int(unsafe.Sizeof(WChar(0))) 11 12 // IndexWCharPtr unsafely moves a wide char pointer by i elements. An offset may be negative. 13 // 14 // Deprecated: use unsafe.Add 15 func IndexWCharPtr(p *WChar, i int) *WChar { 16 return (*WChar)(unsafe.Add(unsafe.Pointer(p), i*WCharSize)) 17 } 18 19 // UnsafeWCharN makes a slice of a given size starting at ptr. 20 // 21 // Deprecated: use unsafe.Slice 22 func UnsafeWCharN(ptr unsafe.Pointer, sz uint64) []WChar { 23 return unsafe.Slice((*WChar)(ptr), sz) 24 } 25 26 // WCharN makes a slice of a given size starting at ptr. 27 // It accepts a *WChar instead of unsafe pointer as UnsafeWCharN does, which allows to avoid unsafe import. 28 // 29 // Deprecated: use unsafe.Slice 30 func WCharN(p *WChar, sz uint64) []WChar { 31 return unsafe.Slice(p, sz) 32 } 33 34 // CWString makes a new zero-terminated wide char array containing a given string. 35 func CWString(s string) *WChar { 36 sz := utf8.RuneCountInString(s) 37 p := makePad((sz+2)*int(unsafe.Sizeof(WChar(0))), 0) 38 39 w := unsafe.Slice((*WChar)(unsafe.Pointer(&p[0])), uint64(sz)) 40 w = w[:0] 41 for _, r := range s { 42 w = append(w, WChar(r)) 43 } 44 if cap(w) != sz { 45 panic("must not happen") 46 } 47 return &w[0] 48 } 49 50 func WStrLen(str *WChar) uint64 { 51 return uint64(findnullw(str)) 52 } 53 54 func GoWSlice(ptr *WChar) []WChar { 55 n := WStrLen(ptr) 56 if n == 0 { 57 return nil 58 } 59 return unsafe.Slice(ptr, n) 60 } 61 62 func GoWString(s *WChar) string { 63 return gostringw(s) 64 } 65 66 func WStrCpy(dst, src *WChar) *WChar { 67 s := GoWSlice(src) 68 d := unsafe.Slice(dst, len(s)+1) 69 n := copy(d, s) 70 d[n] = 0 71 return dst 72 } 73 74 func WStrNCpy(dst, src *WChar, sz uint32) *WChar { 75 d := unsafe.Slice(dst, sz) 76 s := GoWSlice(src) 77 pad := 0 78 if len(s) > int(sz) { 79 s = s[:sz] 80 } else if len(s) < int(sz) { 81 pad = int(sz) - len(s) 82 } 83 n := copy(d, s) 84 for i := 0; i < pad; i++ { 85 d[n+i] = 0 86 } 87 return dst 88 } 89 90 func WStrChr(str *WChar, ch int64) *WChar { 91 if ch < 0 || ch > 0xffff { 92 panic(ch) 93 } 94 if str == nil { 95 return nil 96 } 97 b := GoWSlice(str) 98 for i, c := range b { 99 if c == WChar(ch) { 100 return &b[i] 101 } 102 } 103 return nil 104 } 105 106 func WStrCat(dst, src *WChar) *WChar { 107 s := GoWSlice(src) 108 i := WStrLen(dst) 109 n := int(i) + len(s) 110 d := unsafe.Slice(dst, n+1) 111 copy(d[i:], s) 112 d[n] = 0 113 return &d[0] 114 } 115 116 func WStrCmp(a, b *WChar) int { 117 s1 := GoWString(a) 118 s2 := GoWString(b) 119 return strings.Compare(s1, s2) 120 } 121 122 func WStrCaseCmp(a, b *WChar) int { 123 s1 := strings.ToLower(GoWString(a)) 124 s2 := strings.ToLower(GoWString(b)) 125 return strings.Compare(s1, s2) 126 } 127 128 func WStrtol(s *WChar, end **WChar, base int) int { 129 if end != nil { 130 panic("TODO") 131 } 132 str := GoWString(s) 133 v, err := strconv.ParseInt(str, base, 32) 134 if err != nil { 135 return 0 136 } 137 return int(v) 138 } 139 140 func Mbstowcs(a1 *WChar, a2 *byte, a3 uint32) uint32 { 141 panic("TODO") 142 } 143 144 func wIndexAny(s, chars []WChar) int { 145 for i, c1 := range s { 146 for _, c2 := range chars { 147 if c1 == c2 { 148 return i 149 } 150 } 151 } 152 return -1 153 } 154 155 func wIndex(s []WChar, c WChar) int { 156 for i, c1 := range s { 157 if c1 == c { 158 return i 159 } 160 } 161 return -1 162 } 163 164 var wstrtok struct { 165 data []WChar 166 ind int 167 } 168 169 func WStrTok(src, delim *WChar) *WChar { 170 if src != nil { 171 wstrtok.data = GoWSlice(src) 172 wstrtok.ind = 0 173 } 174 d := GoWSlice(delim) 175 for ; wstrtok.ind < len(wstrtok.data); wstrtok.ind++ { 176 if wIndex(d, wstrtok.data[wstrtok.ind]) < 0 { 177 // start of a new token 178 tok := wstrtok.data[wstrtok.ind:] 179 if i := wIndexAny(tok, d); i >= 0 { 180 tok[i] = 0 181 wstrtok.ind += i + 1 182 } else { 183 wstrtok.data = nil 184 wstrtok.ind = 0 185 } 186 return &tok[0] 187 } 188 // skip delimiters 189 } 190 wstrtok.data = nil 191 wstrtok.ind = 0 192 return nil 193 }