#ifndef COMMON_CC #define COMMON_CC #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) /* 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) /* slice and string handling */ template struct Slice { T* ptr; usize length; Slice() : ptr(nullptr), length(0) {} Slice(T* ptr, usize length) : ptr(ptr), length(length) {} T* operator[](usize index) { assert(index < this->length); return this->ptr + index; } const T* operator[](usize index) const { assert(index < this->size()); return this->ptr + index; } inline usize size() const { return this->length * sizeof(T); } }; template bool slice_write(const Slice* slice, FILE* stream) { usize rc = fwrite(slice->ptr, sizeof(T), slice->length, stream); if (rc == 0 || slice->size() > rc) return false; return true; } typedef Slice String; /* linked list */ struct Link { Link* next; Link* prev; Link(Link* next, Link* prev) : next(next), prev(prev) {} }; struct List { Link head; Link tail; }; static inline void link_after(Link* prev, Link* nlink) { assert(prev != nullptr); assert(nlink != nullptr); Link* next = prev->next; nlink->prev = prev; nlink->next = next; prev->next = nlink; if(next == nullptr) return; next->prev = nlink; } #endif