http://web.archive.org/web/20210423124630/https://github.com/jdah/tetris-os/blob/master/README.md
203 lines
4.2 KiB
C
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
|