1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
|
#ifndef _AL_WSTR_H
#define _AL_WSTR_H
#include "types.h"
#include "lib.h"
#include "str.h"
#include <wchar.h>
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
|