1 #include <string.h> 2 #include <wchar.h> 3 #include <wctype.h> 4 #include <assert.h> 5 6 // Returns 1 if 'wc' is in the 'delim' string, 0 otherwise. 7 static int _wc_indelim(wchar_t wc, const wchar_t* delim) { 8 while (*delim) { 9 if (wc == *delim) 10 return 1; 11 delim++; 12 } 13 return 0; 14 } 15 16 wchar_t *wcpcpy(wchar_t *to, const wchar_t *from) { 17 size_t n = 0; 18 for (;;) { 19 wchar_t wc = from[n]; 20 to[n] = wc; 21 if (wc == L'\0') 22 break; 23 n++; 24 } 25 return to + n; 26 } 27 28 wchar_t *wcpncpy(wchar_t *dst, const wchar_t *src, size_t n) { 29 size_t i; 30 for (i = 0; i < n; ++i) { 31 wchar_t wc = src[i]; 32 dst[i] = wc; 33 if (wc == L'\0') 34 break; 35 } 36 while (i < n) { 37 dst[i] = L'\0'; 38 ++i; 39 } 40 return &dst[n-1]; 41 } 42 43 int wcscasecmp(const wchar_t *s1, const wchar_t *s2) { 44 size_t n = 0; 45 for (;;) { 46 wchar_t wc1 = towlower(s1[n]); 47 wchar_t wc2 = towlower(s2[n]); 48 if (wc1 != wc2) 49 return (wc1 > wc2) ? +1 : -1; 50 if (wc1 == L'\0') 51 return 0; 52 n++; 53 } 54 } 55 56 wchar_t *wcscat(wchar_t *s1, const wchar_t *s2) { 57 size_t n = 0; 58 while (s1[n] != L'\0') 59 n++; 60 61 size_t i = 0; 62 for (;;) { 63 wchar_t wc = s2[i]; 64 s1[n+i] = wc; 65 if (wc == L'\0') 66 break; 67 i++; 68 } 69 return s1; 70 } 71 72 size_t wcslcat(wchar_t *dst, const wchar_t *src, size_t siz) { 73 // Sanity check simplifies code below 74 if (siz == 0) 75 return 0; 76 77 // Skip dst characters. 78 size_t n = 0; 79 while (n < siz && dst[n] != L'\0') 80 n++; 81 82 if (n == siz) 83 return n + wcslen(src); 84 85 // Copy as much source characters as they fit into siz-1 bytes. 86 size_t i; 87 for (i = 0; n+i+1 < siz && src[i] != L'\0'; ++i) 88 dst[n+i] = src[i]; 89 90 // Always zero terminate destination 91 dst[n+i] = L'\0'; 92 93 // Skip remaining source characters 94 while (src[i] != L'\0') 95 i++; 96 97 return n+i; 98 } 99 100 size_t wcslcpy(wchar_t *dst, const wchar_t *src, size_t siz) { 101 size_t i; 102 103 // Copy all non-zero bytes that fit into siz-1 destination bytes 104 for (i = 0; i + 1 < siz && src[i] != L'\0'; ++i) 105 dst[i] = src[i]; 106 107 // Always zero-terminate destination buffer 108 dst[i] = L'\0'; 109 110 // Skip other source characters. 111 while (src[i] != L'\0') 112 ++i; 113 114 return i; 115 } 116 117 size_t wcslen(const wchar_t *s) { 118 size_t n = 0; 119 for (;;) { 120 wchar_t wc = s[n]; 121 if (wc == L'\0') 122 return n; 123 n++; 124 } 125 } 126 127 int wcsncasecmp(const wchar_t *s1, const wchar_t *s2, size_t n) { 128 size_t i; 129 for (i = 0; i < n; ++i) { 130 wchar_t wc1 = towlower(s1[i]); 131 wchar_t wc2 = towlower(s2[i]); 132 if (wc1 != wc2) 133 return (wc1 > wc2) ? +1 : -1; 134 } 135 return 0; 136 } 137 138 wchar_t *wcsncat(wchar_t *s1, const wchar_t *s2, size_t n) { 139 size_t start = 0; 140 while (s1[start] != L'\0') 141 start++; 142 143 // Append s2. 144 size_t i; 145 for (i = 0; i < n; ++i) { 146 wchar_t wc = s2[i]; 147 s1[start + i] = wc; 148 if (wc == L'\0') 149 break; 150 } 151 return (wchar_t*)s1; 152 } 153 154 int wcsncmp(const wchar_t *s1, const wchar_t *s2, size_t n) { 155 size_t i; 156 for (i = 0; i < n; ++i) { 157 wchar_t wc = s1[i]; 158 if (wc != s2[i]) 159 return (wc > s2[i]) ? +1 : -1; 160 if (wc == L'\0') 161 break; 162 } 163 return 0; 164 } 165 166 wchar_t *wcsncpy(wchar_t *dst, const wchar_t *src, size_t n) { 167 // Copy initial characters. 168 size_t i; 169 for (i = 0; i < n; ++i) { 170 wchar_t wc = src[i]; 171 if (wc == L'\0') 172 break; 173 dst[i] = wc; 174 } 175 // zero-pad the remainder. 176 for ( ; i < n; ++i) 177 dst[i] = L'\0'; 178 179 return dst; 180 } 181 182 size_t wcsnlen(const wchar_t *s, size_t maxlen) { 183 size_t n; 184 for (n = 0; n < maxlen; ++n) { 185 if (s[n] == L'\0') 186 break; 187 } 188 return n; 189 } 190 191 wchar_t *wcspbrk(const wchar_t *s, const wchar_t *set) { 192 size_t n = 0; 193 for (;;) { 194 wchar_t wc = s[n]; 195 if (!wc) 196 return NULL; 197 if (_wc_indelim(wc, set)) 198 return (wchar_t*)&s[n]; 199 n++; 200 } 201 } 202 203 wchar_t *wcschr(const wchar_t *s, wchar_t c) { 204 size_t n = 0; 205 for (;;) { 206 wchar_t wc = s[n]; 207 if (wc == c) 208 return (wchar_t*)s + n; 209 if (wc == L'\0') 210 return NULL; 211 n++; 212 } 213 } 214 215 wchar_t *wcsrchr(const wchar_t *s, wchar_t c) { 216 size_t n = 0; 217 wchar_t* last = NULL; 218 for (;;) { 219 wchar_t wc = s[n]; 220 if (wc == c) 221 last = (wchar_t*)s + n; 222 if (wc == L'\0') 223 break; 224 n++; 225 } 226 return last; 227 } 228 229 size_t wcsspn(const wchar_t *s, const wchar_t *set) { 230 size_t n = 0; 231 for (;;) { 232 wchar_t wc = s[n]; 233 if (wc == L'\0') 234 break; 235 if (!_wc_indelim(wc, set)) 236 break; 237 ++n; 238 } 239 return n; 240 } 241 242 wchar_t *wcsstr(const wchar_t *s, const wchar_t *find) { 243 wchar_t find_c; 244 245 // Always find the empty string 246 find_c = *find++; 247 if (!find_c) 248 return (wchar_t*)s; 249 250 size_t find_len = wcslen(find); 251 252 for (;;) { 253 wchar_t* p = wcschr(s, find_c); 254 if (p == NULL) 255 return NULL; 256 257 if (!wmemcmp(p, find, find_len)) 258 return p; 259 260 s = p + 1; 261 } 262 return NULL; 263 } 264 265 wchar_t *wcstok(wchar_t *s, const wchar_t *delim, wchar_t **last) { 266 if (s == NULL) { 267 s = *last; 268 if (s == NULL) 269 return NULL; 270 } 271 272 // Skip leading delimiters first. 273 size_t i = 0; 274 wchar_t wc; 275 for (;;) { 276 wc = s[i]; 277 if (wc && _wc_indelim(wc, delim)) { 278 i++; 279 continue; 280 } 281 break; 282 } 283 284 if (!wc) { 285 // Nothing left. 286 *last = NULL; 287 return NULL; 288 } 289 290 size_t tok_start = i; 291 292 // Skip non delimiters now. 293 for (;;) { 294 wc = s[i]; 295 if (wc && !_wc_indelim(wc, delim)) { 296 i++; 297 continue; 298 } 299 break; 300 } 301 302 if (!wc) { 303 *last = NULL; 304 } else { 305 s[i] = L'\0'; 306 *last = &s[i+1]; 307 } 308 return &s[tok_start]; 309 } 310 311 wchar_t * wmemchr(const wchar_t *s, wchar_t c, size_t n) { 312 size_t i; 313 for (i = 0; i < n; ++i) { 314 if (s[i] == c) 315 return (wchar_t*)&s[i]; 316 } 317 return NULL; 318 } 319 320 int wmemcmp(const wchar_t *s1, const wchar_t *s2, size_t n) { 321 size_t i; 322 for (i = 0; i < n; ++i) { 323 if (s1[i] == s2[i]) 324 continue; 325 if (s1[i] > s2[i]) 326 return 1; 327 else 328 return -1; 329 } 330 return 0; 331 } 332 333 wchar_t * wmemcpy(wchar_t *d, const wchar_t *s, size_t n) { 334 return (wchar_t *)memcpy((char*)d, 335 (const char*)s, 336 n * sizeof(wchar_t)); 337 } 338 339 wchar_t* wmemmove(wchar_t* d, const wchar_t* s, size_t n) { 340 return (wchar_t* )memmove((char*)d, 341 (const char*)s, 342 n * sizeof(wchar_t)); 343 } 344 345 wchar_t* wmemset(wchar_t* s, wchar_t c, size_t n) { 346 size_t i; 347 for (i = 0; i < n; ++i) 348 s[i] = c; 349 return s; 350 } 351