#ifndef _AL_WSTR_H #define _AL_WSTR_H #include "types.h" #include "lib.h" #include "str.h" #include typedef struct { u32 len; u32 alloc; wchar_t *data; } wstr; #define al_wstr_zero() (wstr){ 0, 0, NULL } #define al_wstr_at(w, i) (w)->data[i] #define al_wstr_atr(w, i) (w)->data[(w)->len + i] #define al_wide_string_if_literal(w) ((wchar_t *)(L"" w)) // use al_wstr_cr for runtime. #define al_wstr_c(w) (&((wstr){ (u32)((sizeof(w) / sizeof(wchar_t)) - 1), 0, al_wide_string_if_literal(w) })) #define al_wstr_cr(w) (&((wstr){ (u32)wcslen(w), 0, ((wchar_t *)(w)) })) // runtime #define al_wstr_w(w, i, n) (&((wstr){ ((u32)(n)), 0, &al_wstr_at(w, i) })) #define al_wstr_substr(w, start, end) al_wstr_w(w, start, ((end) - (start))) #define AL_WSTR_FMT "%.*ls" #define AL_WSTR_PRINTF(w) (w)->len, (w)->data #define AL_WSTR_PRINTF_MAXLEN(w, l) AL_MIN((w)->len, (l)), (w)->data AL_UNUSED_FUNCTION_PUSH static inline s32 al_wchar_width(wchar_t wc) { #ifdef AL_HAVE_WIDE_STRING return wcwidth(wc); #else (void)wc; return 0; #endif } static inline void al_wstr_free(wstr *w) { if (w->alloc > 0) al_free(w->data); } static inline u32 al_wstr_reserve(wstr *w, u32 size) { if (size < al_grow_limit) { size = al_next_power_of_two(size + 1); } else { size = (size + al_grow_limit) & ~al_grow_limit; } if (size <= w->alloc) return w->alloc; w->data = (wchar_t *)((!w->data) ? al_malloc(size) : al_realloc(w->data, size)); return size; } static inline void al_wstr_sized(wstr *w, u32 size) { *w = al_wstr_zero(); w->alloc = al_wstr_reserve(w, size * sizeof(wchar_t)); al_memset(w->data, 0, w->alloc); } static inline void al_wstr_clone(wstr *dest, wstr *src) { al_wstr_sized(dest, src->len); al_memcpy(dest->data, src->data, src->len * sizeof(wchar_t)); dest->len = src->len; } static inline void al_wstr_from_cstr(wstr *w, char *c) { size_t n = mbstowcs(NULL, c, 0) + 1; al_wstr_sized(w, n); w->len = mbstowcs(w->data, c, n); w->data[w->len] = L'\0'; } static inline void al_wstr_from_str(wstr *w, str *s) { char *c_str = al_str_to_c_str(s); al_wstr_from_cstr(w, c_str); al_free(c_str); } static inline void al_wstr_to_str(wstr *w, str *s) { u32 len = (u32)wcstombs(NULL, w->data, 0); al_str_sized(s, len); s->len = len; wcstombs(s->data, w->data, s->len); } static inline s32 al_wstr_width(wstr *w) { #ifdef AL_HAVE_WIDE_STRING return wcswidth(w->data, w->len); #else (void)w; return 0; #endif } static inline s32 al_wstr_cmp(wstr *w, wstr *c, u32 start, u32 len) { return wcsncmp(&al_wstr_at(w, start), c->data, len); } static inline s32 al_wstr_rfind(wstr *w, wchar_t c) { for (s32 i = w->len - 1; i >= 0; i--) { if (al_wstr_at(w, i) == c) return i; } return -1; } AL_UNUSED_FUNCTION_POP #endif // _AL_WSTR_H