Files
tetris-os/src/util.h

203 lines
4.2 KiB
C

#ifndef UTIL_H
#define UTIL_H
// fixed width integer types
typedef unsigned char u8;
typedef unsigned short u16;
typedef unsigned int u32;
typedef unsigned long long u64;
typedef char i8;
typedef short i16;
typedef int i32;
typedef long long i64;
typedef u32 size_t;
typedef u32 uintptr_t;
typedef float f32;
typedef double f64;
typedef u8 bool;
#define true (1)
#define false (0)
#define NULL (0)
#define CONCAT_IMPL(x, y) x##y
#define CONCAT(x, y) CONCAT_IMPL(x, y)
#define __MIN_IMPL(_x, _y, _xn, _yn) __extension__({\
__typeof__(_x) _xn = (_x);\
__typeof__(_y) _yn = (_y);\
(_xn < _yn ? _xn : _yn);\
})
#define MIN(_x, _y) __MIN_IMPL(_x, _y, CONCAT(__x, __COUNTER__), CONCAT(__y, __COUNTER__))
#define __MAX_IMPL(_x, _y, _xn, _yn) __extension__({\
__typeof__(_x) _xn = (_x);\
__typeof__(_y) _yn = (_y);\
(_xn > _yn ? _xn : _yn);\
})
#define MAX(_x, _y) __MAX_IMPL(_x, _y, CONCAT(__x, __COUNTER__), CONCAT(__y, __COUNTER__))
#define CLAMP(_x, _mi, _ma) (MAX(_mi, MIN(_x, _ma)))
// returns the highest set bit of x
// i.e. if x == 0xF, HIBIT(x) == 3 (4th index)
// WARNING: currently only works for up to 32-bit types
#define HIBIT(_x) (31 - __builtin_clz((_x)))
// returns the lowest set bit of x
#define LOBIT(_x)\
__extension__({ __typeof__(_x) __x = (_x); HIBIT(__x & -__x); })
// returns _v with _n-th bit = _x
#define BIT_SET(_v, _n, _x) __extension__({\
__typeof__(_v) __v = (_v);\
(__v ^ ((-(_x) ^ __v) & (1 << (_n))));\
})
#define PACKED __attribute__((packed))
#ifndef asm
#define asm __asm__ volatile
#endif
#define CLI() asm ("cli")
#define STI() asm ("sti")
static inline u16 inports(u16 port) {
u16 r;
asm("inw %1, %0" : "=a" (r) : "dN" (port));
return r;
}
static inline void outports(u16 port, u16 data) {
asm("outw %1, %0" : : "dN" (port), "a" (data));
}
static inline u8 inportb(u16 port) {
u8 r;
asm("inb %1, %0" : "=a" (r) : "dN" (port));
return r;
}
static inline void outportb(u16 port, u8 data) {
asm("outb %1, %0" : : "dN" (port), "a" (data));
}
static inline size_t strlen(const char *str) {
size_t l = 0;
while (*str++ != 0) {
l++;
}
return l;
}
static inline char *itoa(i32 x, char *s, size_t sz) {
// TODO: holy god this is bad code we need some error handling here
if (sz < 20) {
extern void panic(const char *);
panic("ITOA BUFFER TOO SMALL");
}
u32 tmp;
i32 i, j;
tmp = x;
i = 0;
do {
tmp = x % 10;
s[i++] = (tmp < 10) ? (tmp + '0') : (tmp + 'a' - 10);
} while (x /= 10);
s[i--] = 0;
for (j = 0; j < i; j++, i--) {
tmp = s[j];
s[j] = s[i];
s[i] = tmp;
}
return s;
}
static inline void memset(void *dst, u8 value, size_t n) {
u8 *d = dst;
while (n-- > 0) {
*d++ = value;
}
}
static inline void *memcpy(void *dst, const void *src, size_t n) {
u8 *d = dst;
const u8 *s = src;
while (n-- > 0) {
*d++ = *s++;
}
return d;
}
static inline void *memmove(void *dst, const void *src, size_t n) {
// OK since we know that memcpy copies forwards
if (dst < src) {
return memcpy(dst, src, n);
}
u8 *d = dst;
const u8 *s = src;
for (size_t i = n; i > 0; i--) {
d[i - 1] = s[i - 1];
}
return dst;
}
// SEE: https://opensource.apple.com/source/Libc/Libc-1158.30.7/string/strlcat.c.auto.html
static inline size_t strlcat(char *dst, const char *src, size_t size) {
const size_t sl = strlen(src),
dl = strlen(dst);
if (dl == size) {
return size + sl;
}
if (sl < (size - dl)) {
memcpy(dst + dl, src, sl + 1);
} else {
memcpy(dst + dl, src, size - dl - 1);
dst[size - 1] = '\0';
}
return sl + dl;
}
static inline size_t strlcpy(char *dst, const char *src, size_t n) {
// copy as many bytes as can fit
char *d = dst;
const char *s = src;
size_t size = n;
while (--n > 0) {
if ((*d++ = *s++) == 0) {
break;
}
}
// if we ran out of space, null terminate
if (n == 0) {
if (size != 0) {
*d = 0;
}
// traverse the rest of s
while (*s++);
}
return s - src - 1;
}
#endif