summaryrefslogtreecommitdiff
path: root/typeutils.h
blob: e7aee6f5f8df406ce73b77cb133f23279f4f1cd2 (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
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
#pragma once

#include <ctype.h>
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
#include <stdio.h>


#define DECLARE_VEC(T, Name)                                         \
    typedef struct {                                                 \
        T **blocks;                                                  \
        size_t count;                                                \
        size_t used;                                                 \
        size_t cap;                                                  \
        size_t block_size;                                           \
    } Name;                                                          \
                                                                     \
    static inline Name make_##Name(size_t block_size) {              \
        return (Name){                                               \
            .blocks = NULL,                                          \
            .count = 0,                                              \
            .used = 0,                                               \
            .cap = 0,                                                \
            .block_size = block_size,                                \
        };                                                           \
    }                                                                \
                                                                     \
    static inline T *push_to_##Name(Name *vec, T item) {             \
        size_t block_index = vec->count / vec->block_size;           \
        size_t item_index  = vec->count % vec->block_size;           \
                                                                     \
        if (block_index == vec->used) {                              \
            if (vec->used == vec->cap) {                             \
                size_t new_cap = vec->cap                            \
                    ? vec->cap * 2                                   \
                    : 8;                                             \
                                                                     \
                T **new_blocks = realloc(                            \
                    vec->blocks,                                     \
                    new_cap * sizeof(T *)                            \
                );                                                   \
                                                                     \
                if (!new_blocks) abort();                            \
                                                                     \
                vec->blocks = new_blocks;                            \
                vec->cap = new_cap;                                  \
            }                                                        \
                                                                     \
            vec->blocks[vec->used] =                                 \
                malloc(vec->block_size * sizeof(T));                 \
                                                                     \
            if (!vec->blocks[vec->used]) abort();                    \
                                                                     \
            vec->used++;                                             \
        }                                                            \
                                                                     \
        T *ptr = &vec->blocks[block_index][item_index];              \
        *ptr = item;                                                 \
                                                                     \
        vec->count++;                                                \
        return ptr;                                                  \
    }                                                                \
                                                                     \
    static inline T* get_from_##Name(Name *vec, size_t index) {      \
        if (index >= vec->count) return NULL;                        \
                                                                     \
        return &vec->blocks                                          \
            [index / vec->block_size]                                \
            [index % vec->block_size];                               \
    }


DECLARE_VEC(char, String);


static void append_str_to_String(String* target, const char* src_str) {
    size_t len = strlen(src_str);

    for (size_t i = 0; i < len; i++) {
        push_to_String(target, src_str[i]);
    }
}

static inline char* inner(String* str) {
    char *out = malloc(str->count + 1);
    if (!out) abort();

    for (size_t i = 0; i < str->count; i++) {
        out[i] = *get_from_String(str, i);
    }

    out[str->count] = '\0';
    return out;
}


#define DECLARE_MAYBE(T)                                            \
    typedef struct {                                                \
        bool some;                                                  \
        T value;                                                    \
    } Maybe##T;