aboutsummaryrefslogtreecommitdiff
path: root/src/stdlib/tables.h
blob: eac8c7d86f5472b9dd88b309086e8098a5ee383e (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
104
105
106
#pragma once

// Hash table datastructure with methods and type information

#include <stdint.h>
#include <stdbool.h>
#include <string.h>

#include "lists.h"
#include "datatypes.h"
#include "types.h"
#include "util.h"

#define Table(key_t, val_t, key_info, value_info, fb, N, ...)  ({ \
    struct { key_t k; val_t v; } ents[N] = {__VA_ARGS__}; \
    Table_t table = Tableヽfrom_entries((List_t){ \
                       .data=memcpy(GC_MALLOC(sizeof(ents)), ents, sizeof(ents)), \
                       .length=sizeof(ents)/sizeof(ents[0]), \
                       .stride=(void*)&ents[1] - (void*)&ents[0], \
                       }, Tableヽinfo(key_info, value_info)); \
    table.fallback = fb; \
    table; })
#define Set(item_t, item_info, N, ...)  ({ \
    item_t ents[N] = {__VA_ARGS__}; \
    Table_t set = Tableヽfrom_entries((List_t){ \
                       .data=memcpy(GC_MALLOC(sizeof(ents)), ents, sizeof(ents)), \
                       .length=sizeof(ents)/sizeof(ents[0]), \
                       .stride=(void*)&ents[1] - (void*)&ents[0], \
                       }, Setヽinfo(item_info)); \
    set; })

Table_t Tableヽfrom_entries(List_t entries, const TypeInfo_t *type);
void *Tableヽget(Table_t t, const void *key, const TypeInfo_t *type);
#define Tableヽget_optional(table_expr, key_t, val_t, key_expr, nonnull_var, nonnull_expr, null_expr, info_expr) ({ \
    const Table_t t = table_expr; const key_t k = key_expr; \
    val_t *nonnull_var = Tableヽget(t, &k, info_expr); \
    nonnull_var ? nonnull_expr : null_expr; })
#define Tableヽget_or_setdefault(table_expr, key_t, val_t, key_expr, default_expr, info_expr) ({ \
    Table_t *t = table_expr; const key_t k = key_expr; \
    if (t->entries.data_refcount > 0) Listヽcompact(&t->entries, sizeof(struct {key_t k; val_t v;})); \
    val_t *v = Tableヽget(*t, &k, info_expr); \
    v ? v : (val_t*)Tableヽreserve(t, &k, (val_t[1]){default_expr}, info_expr); })
#define Tableヽget_or_default(table_expr, key_t, val_t, key_expr, default_expr, info_expr) ({ \
    const Table_t t = table_expr; const key_t k = key_expr; \
    val_t *v = Tableヽget(t, &k, info_expr); \
    v ? *v : default_expr; })
#define Tableヽhas_value(table_expr, key_expr, info_expr) ({ \
    const Table_t t = table_expr; __typeof(key_expr) k = key_expr; \
    (Tableヽget(t, &k, info_expr) != NULL); })
PUREFUNC void *Tableヽget_raw(Table_t t, const void *key, const TypeInfo_t *type);
CONSTFUNC void *Tableヽentry(Table_t t, int64_t n);
void *Tableヽreserve(Table_t *t, const void *key, const void *value, const TypeInfo_t *type);
void Tableヽset(Table_t *t, const void *key, const void *value, const TypeInfo_t *type);
#define Tableヽset_value(t, key_expr, value_expr, type) ({ __typeof(key_expr) k = key_expr; __typeof(value_expr) v = value_expr; \
                                                        Tableヽset(t, &k, &v, type); })
void Tableヽremove(Table_t *t, const void *key, const TypeInfo_t *type);
#define Tableヽremove_value(t, key_expr, type) ({ __typeof(key_expr) k = key_expr; Tableヽremove(t, &k, type); })

Table_t Tableヽoverlap(Table_t a, Table_t b, const TypeInfo_t *type);
Table_t Tableヽwith(Table_t a, Table_t b, const TypeInfo_t *type);
Table_t Tableヽwithout(Table_t a, Table_t b, const TypeInfo_t *type);
Table_t Tableヽxor(Table_t a, Table_t b, const TypeInfo_t *type);
Table_t Tableヽwith_fallback(Table_t t, OptionalTable_t fallback);
PUREFUNC bool Tableヽis_subset_of(Table_t a, Table_t b, bool strict, const TypeInfo_t *type);
PUREFUNC bool Tableヽis_superset_of(Table_t a, Table_t b, bool strict, const TypeInfo_t *type);

void Tableヽclear(Table_t *t);
Table_t Tableヽsorted(Table_t t, const TypeInfo_t *type);
void Tableヽmark_copy_on_write(Table_t *t);
#define TABLE_INCREF(t) ({ LIST_INCREF((t).entries); if ((t).bucket_info) (t).bucket_info->data_refcount += ((t).bucket_info->data_refcount < TABLE_MAX_DATA_REFCOUNT); })
#define TABLE_COPY(t) ({ TABLE_INCREF(t); t; })
PUREFUNC int32_t Tableヽcompare(const void *x, const void *y, const TypeInfo_t *type);
PUREFUNC bool Tableヽequal(const void *x, const void *y, const TypeInfo_t *type);
PUREFUNC uint64_t Tableヽhash(const void *t, const TypeInfo_t *type);
Text_t Tableヽas_text(const void *t, bool colorize, const TypeInfo_t *type);
PUREFUNC bool Tableヽis_none(const void *obj, const TypeInfo_t*);

CONSTFUNC void *Tableヽstr_entry(Table_t t, int64_t n);
PUREFUNC void *Tableヽstr_get(Table_t t, const char *key);
PUREFUNC void *Tableヽstr_get_raw(Table_t t, const char *key);
void Tableヽstr_set(Table_t *t, const char *key, const void *value);
void *Tableヽstr_reserve(Table_t *t, const char *key, const void *value);
void Tableヽstr_remove(Table_t *t, const char *key);
void Tableヽserialize(const void *obj, FILE *out, Table_t *pointers, const TypeInfo_t *type);
void Tableヽdeserialize(FILE *in, void *outval, List_t *pointers, const TypeInfo_t *type);

#define Tableヽlength(t) ((t).entries.length)

extern const TypeInfo_t CStrToVoidStarTable;

#define Tableヽmetamethods { \
    .as_text=Tableヽas_text, \
    .compare=Tableヽcompare, \
    .equal=Tableヽequal, \
    .hash=Tableヽhash, \
    .is_none=Tableヽis_none, \
    .serialize=Tableヽserialize, \
    .deserialize=Tableヽdeserialize, \
}

#define Tableヽinfo(key_expr, value_expr) &((TypeInfo_t){.size=sizeof(Table_t), .align=__alignof__(Table_t), \
                                           .tag=TableInfo, .TableInfo.key=key_expr, .TableInfo.value=value_expr, .metamethods=Tableヽmetamethods})
#define Setヽinfo(item_info) &((TypeInfo_t){.size=sizeof(Table_t), .align=__alignof__(Table_t), \
                              .tag=TableInfo, .TableInfo.key=item_info, .TableInfo.value=&Voidヽinfo, .metamethods=Tableヽmetamethods})

// vim: ts=4 sw=0 et cino=L2,l1,(0,W4,m1