#ifndef COMMON_CC #define COMMON_CC #include #include #include #include #include /* 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 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->total_length()); return this->ptr + index; } inline usize total_length() const { return this->length * sizeof(T); } }; typedef Slice 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); 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