summaryrefslogtreecommitdiff
path: root/include/al/wstr.h
blob: 97568db4b3a2c7b9a75670a91a6d34ba74f842a1 (plain)
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
#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_EMPTY (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_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

static inline s32 al_wchar_width(wchar_t wc)
{
    return wcwidth(wc);
}

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_EMPTY;
    w->alloc = al_wstr_reserve(w, size * sizeof(wchar_t));
    al_memset(w->data, 0, w->alloc);
}

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 s32 al_wstr_width(wstr *w)
{
    s32 width = 0;
    for (u32 i = 0; i < w->len; i++) {
        width += al_wchar_width(al_wstr_at(w, i));
    }
    return width;
}

#endif // _AL_WSTR_H