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
124
125
126
127
128
129
130
131
|
#ifndef COMMON_CC
#define COMMON_CC
#include <cstdarg>
#include <cstdint>
#include <cstdio>
#include <cstdlib>
#include <cstring>
/* typedefs for common types */
typedef uint8_t u8;
typedef uint16_t u16;
typedef uint32_t u32;
typedef uint64_t u64;
typedef int8_t i8;
typedef int16_t i16;
typedef int32_t i32;
typedef int64_t i64;
typedef uintptr_t usize;
typedef intptr_t isize;
/* intrinsics */
#define likely(cond) __builtin_expect(!!(cond), 1)
#define unlikely(cond) __builtin_expect(!!(cond), 0)
#define containerof(type, member, ptr) \
((type*)((char*)(ptr) - offsetof(type, member)))
/* error handling sort of */
[[noreturn]] void panic_impl(const char* file, i32 line, const char* fmt, ...) {
fprintf(stderr, "PANIC at %s:%d: ", file, line);
va_list args;
va_start(args, fmt);
vfprintf(stderr, fmt, args);
va_end(args);
fputc('\n', stderr);
fflush(stderr);
abort();
}
#define panic(fmt, ...) panic_impl(__FILE__, __LINE__, fmt, __VA_ARGS__)
#define spanic(msg) panic("%s", msg)
#undef assert
#define assert(cond) \
do { \
if (unlikely(!(cond))) panic("assertion failed: %s", #cond); \
} while (0)
#define assert_neq(x, y) assert(x != y)
#define assert_st(x, y) assert(x < y)
#define assert_ste(x, y) assert(x <= y)
/* slice and string handling */
template <typename T>
struct Slice {
T* ptr;
usize length;
Slice() : Slice(nullptr, 0) {}
Slice(T* ptr, usize length) : ptr(ptr), length(length) {}
Slice(const char* str) : ptr((u8*)str), length(strlen(str)) {}
T* operator[](usize index) {
assert(index < this->length);
return this->ptr + index;
}
const T* operator[](usize index) const {
assert(index < this->length);
return this->ptr + index;
}
inline usize total_length() const { return this->length * sizeof(T); }
};
typedef Slice<const u8> String;
bool string_write(const String* s, FILE* stream) {
assert_neq(s, nullptr);
assert_neq(stream, nullptr);
i32 rc = fprintf(stream, "%.*s", (i32)s->length, s->ptr);
if (unlikely(rc < 0)) return false;
return true;
}
/* linked list */
struct Link {
Link* next;
Link* prev;
Link() : Link(nullptr, nullptr) {}
Link(Link* next, Link* prev) : next(next), prev(prev) {}
};
static inline void link_after(Link* prev, Link* nlink) {
assert_neq(prev, nullptr);
assert_neq(nlink, nullptr);
assert_neq(prev, nlink);
assert(nlink->prev == nullptr && nlink->next == nullptr);
Link* next = prev->next;
nlink->prev = prev;
nlink->next = next;
prev->next = nlink;
if (next == nullptr) return;
next->prev = nlink;
}
static inline void link_remove(Link* item) {
assert_neq(item, nullptr);
Link* prev = item->prev;
Link* next = item->next;
if (prev != nullptr) prev->next = next;
if (next != nullptr) next->prev = prev;
item->prev = item->next = nullptr;
}
#endif
|