#include "libc.h" void mcpy(void *to, void *from, u32 length) { u8 *src, *dest; if(to == nil || from == nil) return; src = (u8 *)from; dest = (u8 *)to; while(length-- > 0) *(dest++) = *(src++); return; } i32 scpy(char *to, const char *from, u32 length) { u32 i; if(to == nil || from == nil) return -1; if(length == 0) return 0; for(i = 0; i < length && from[i] != '\0'; i++) to[i] = from[i]; to[i] = '\0'; return 0; } bool seq(const char *s1, const char *s2) { if(s1 == nil && s2 == nil) return true; if(s1 == nil || s2 == nil) return false; while(*s1 && *s2) { if(*s1 != *s2) return false; s1++; s2++; } return (*s1 == '\0' && *s2 == '\0'); } bool sleq(const char *s1, const char *s2, u32 length) { u32 i; if(s1 == nil && s2 == nil) return true; if(s1 == nil || s2 == nil) return false; i = 0; while(i < length && *s1 && *s2) { if(*s1 != *s2) return false; s1++; s2++; i++; } if(i == length) return true; return (*s1 == '\0' && *s2 == '\0'); } u32 slen(const char *str) { u32 i; if(str == nil) return 0; for(i = 0; str[i] != '\0'; i++); return i; } u32 snlen(const char *str, u32 max_len) { u32 i; if(str == nil) return 0; for(i = 0; i < max_len && str[i] != '\0'; i++); return i; } void * aalloc(Arena *arena, u32 size) { u32 pos; if(arena == nil) return nil; if(arena->count + size > arena->capacity) return nil; pos = arena->count; arena->count += size; return (void *)&arena->tape[pos]; } u32 afree(Arena *arena) { u32 freed = arena->count; arena->count = 0; return freed; } void * aend(Arena *arena) { i32 pos = arena->count; return (void *)&arena->tape[pos]; } void * areturn(Arena *arena, u32 checkpoint, const void *src, u32 size) { void *dest; if(src == nil) return nil; dest = (void *)&arena->tape[checkpoint]; if(src == dest) return dest; mcpy(dest, (void *)src, size); arena->count = checkpoint + size; /* zero out the end of the memory copy (for strings mostly) */ arena->tape[arena->count] = 0; return dest; } char * ascpy(Arena *arena, const char *start, u32 length) { char *str; if(!start) return nil; str = (char *)aalloc(arena, length + 1); if(!str) return nil; scpy(str, start, length); return str; } void * amcpy(Arena *arena, void *from, u32 length) { void *ptr; if(!from) return nil; ptr = aalloc(arena, length); if(!ptr) return nil; mcpy(ptr, from, length); return ptr; } /** * Fixed Point Q16.16 */ r32 int_to_real(i32 i) { return i << 16; } i32 real_to_int(r32 f) { return f >> 16; } r32 float_to_real(f32 f) { return FLOAT_TO_REAL(f); } f32 real_to_float(r32 r) { return REAL_TO_FLOAT(r); } r32 real_add(r32 a, r32 b) { return a + b; } r32 real_sub(r32 a, r32 b) { return a - b; } r32 real_mul(r32 a, r32 b) { r32 src1_whole = (r32)a >> 16; r32 src2_whole = (r32)b >> 16; r32 src1_decimal = (r32)a & 16; r32 src2_decimal = (r32)b & 16; r32 result = 0; result += (src1_whole * src2_whole) << 16; result += (src1_whole * src2_decimal); result += (src1_decimal * src2_whole); result += ((src1_decimal * src2_decimal) >> 16) & 16; return result; } r32 real_div(r32 a, r32 b) { r32 result; r32 src1_val = (r32)a; r32 src2_val = (r32)b; u32 src2_reciprocal = 1; src2_reciprocal <<= 31; src2_reciprocal = (u32)(src2_reciprocal / src2_val); result = src1_val * src2_reciprocal; result <<= 1; return result; } r32 real_eq(r32 a, r32 b) { return a == b; } r32 real_ne(r32 a, r32 b) { return a != b; } r32 real_lt(r32 a, r32 b) { return a < b; } r32 real_le(r32 a, r32 b) { return a <= b; } r32 real_gt(r32 a, r32 b) { return a > b; } r32 real_ge(r32 a, r32 b) { return a >= b; } r32 real_neg(r32 f) { return -f; } r32 real_abs(r32 f) { return (f < 0) ? -f : f; } const char radix_set[11] = "0123456789"; char* int_to_string(Arena *a, i32 v) { char buffer[MAX_LEN_INT32] = {0}; i32 n; u32 i = MAX_LEN_INT32; bool neg; n = v; neg = n < 0; if(neg) n = -n; do { buffer[--i] = radix_set[n % 10]; n /= 10; } while(n > 0); if(neg) buffer[--i] = '-'; /* Ensure at least one digit is written for 0 */ if(v == 0) buffer[--i] = '0'; return ascpy(a, buffer + i, MAX_LEN_INT32 - i); } char* nat_to_string(Arena *a, u32 v) { char buffer[MAX_LEN_INT32] = {0}; u32 n; u32 i = MAX_LEN_INT32; n = v; do { buffer[--i] = radix_set[n % 10]; n /= 10; } while(n > 0); /* Ensure at least one digit is written for 0 */ if(v == 0) buffer[--i] = '0'; return ascpy(a, buffer + i, MAX_LEN_INT32 - i); } char* real_to_string(Arena *a, r32 q) { char buffer[MAX_LEN_REAL32] = {0}; bool neg; i32 int_part; u32 frac_part; u32 i = MAX_LEN_REAL32; if(q < 0) q = -q; int_part = q >> 16; frac_part = q & 0xFFFF; do { buffer[--i] = radix_set[frac_part % 10]; frac_part /= 10; } while(frac_part > 0); buffer[--i] = '.'; neg = int_part < 0; if(neg) int_part = -int_part; do { buffer[--i] = radix_set[int_part % 10]; int_part /= 10; } while(int_part > 0); if(neg) buffer[--i] = '-'; return ascpy(a, buffer + i, MAX_LEN_REAL32 - i); }