System info & network

This commit is contained in:
2023-09-26 19:40:16 +02:00
commit 504ba77654
89 changed files with 39577 additions and 0 deletions

12
code/lib/all.h Normal file
View File

@@ -0,0 +1,12 @@
#ifndef _PIUMA_LIB_ALL_H_
#define _PIUMA_LIB_ALL_H_
#include "types.h"
#include "ds.h"
#include "queue.h"
#include "math.h"
#include "geometry.h"
#include "color.h"
#include "text.h"
#endif

26
code/lib/bits.h Normal file
View File

@@ -0,0 +1,26 @@
#ifndef _PIUMA_LIB_BITS_H_
#define _PIUMA_LIB_BITS_H_
#include "types.h"
inline u32 bits_endian_swap(u32 x)
{
return
(x << 24 ) |
(x << 8 & 0x00FF0000) |
(x >> 8 & 0x0000FF00) |
(x >> 24 );
}
inline u32 bits_reverse(u32 x)
{
u32 result = 0;
for(int i = 0; i < 32; i++)
{
result = result << 1 | (x & 1);
x = x >> 1;
}
return result;
}
#endif

25
code/lib/color.h Normal file
View File

@@ -0,0 +1,25 @@
#ifndef _PIUMA_LIB_COLOR_H_
#define _PIUMA_LIB_COLOR_H_
#include "math.h"
#include "types.h"
inline u32 convert_color_to_ABGR_u32(v4 color)
{
u32 r = 0xFF * color.r;
u32 g = 0xFF * color.g;
u32 b = 0xFF * color.b;
u32 a = 0xFF * color.a;
return (a << 24) | (b << 16) | (g << 8) | (r);
}
inline v4 convert_ABGR_u32_to_color(u32 color)
{
f32 r = (f32)((color >> 0) & 0xFF) / (f32)(0xFF);
f32 g = (f32)((color >> 8) & 0xFF) / (f32)(0xFF);
f32 b = (f32)((color >> 16) & 0xFF) / (f32)(0xFF);
f32 a = (f32)((color >> 24) & 0xFF) / (f32)(0xFF);
return v4{r, g, b, a};
}
#endif

87
code/lib/ds.cpp Normal file
View File

@@ -0,0 +1,87 @@
#include "ds.h"
#include <string.h>
int char_cmp(const void *a, const void *b)
{
char _a = *(char*)a;
char _b = *(char*)b;
if(_a < _b) return -1;
if(_a > _b) return +1;
return 0;
}
int u8_cmp (const void *a, const void *b)
{
u8 _a = *(u8*)a;
u8 _b = *(u8*)b;
if(_a < _b) return -1;
if(_a > _b) return +1;
return 0;
}
int u32_cmp(const void *a, const void *b)
{
u32 _a = *(u32*)a;
u32 _b = *(u32*)b;
if(_a < _b) return -1;
if(_a > _b) return +1;
return 0;
}
int u64_cmp(const void *a, const void *b)
{
u64 _a = *(u64*)a;
u64 _b = *(u64*)b;
if(_a < _b) return -1;
if(_a > _b) return +1;
return 0;
}
int s32_cmp(const void *a, const void *b)
{
s32 _a = *(s32*)a;
s32 _b = *(s32*)b;
if(_a < _b) return -1;
if(_a > _b) return +1;
return 0;
}
int s64_cmp(const void *a, const void *b)
{
s64 _a = *(s64*)a;
s64 _b = *(s64*)b;
if(_a < _b) return -1;
if(_a > _b) return +1;
return 0;
}
u64 make_unique(void *array, u64 count, u64 element_size, compare_fn *cmp)
{
qsort(array, count, element_size, cmp);
// Remove duplicates
u8 *start = (u8*)array;
u8 *end = start + element_size * count;
u64 deleted = 0;
u8 *prev = start;
u8 *curr = start + element_size;
while(curr < end)
{
if(cmp(prev, curr) == 0)
{
deleted++;
}
else
{
prev += element_size;
memcpy(prev, curr, element_size);
}
curr += element_size;
}
return count - deleted;
}

29
code/lib/ds.h Normal file
View File

@@ -0,0 +1,29 @@
#ifndef _PIUMA_LIB_DS_H_
#define _PIUMA_LIB_DS_H_
#include "types.h"
#include "stdlib.h"
typedef int compare_fn(const void *, const void *);
// Basic compare functions
int char_cmp(const void *a, const void *b);
int u8_cmp (const void *a, const void *b);
int u32_cmp(const void *a, const void *b);
int u64_cmp(const void *a, const void *b);
int s32_cmp(const void *a, const void *b);
int s64_cmp(const void *a, const void *b);
// Modifies "array" and returns the number of unique things
u64 make_unique(void *array, u64 count, u64 element_size, compare_fn *cmp);
// @Cleanup: put this in the right place
template<typename T>
void swap(T &a, T &b)
{
T tmp = a;
a = b;
b = tmp;
}
#endif

220
code/lib/event.h Normal file
View File

@@ -0,0 +1,220 @@
#ifndef _PIUMA_LIB_EVENT_H_
#define _PIUMA_LIB_EVENT_H_
#include "types.h"
#include "math.h"
// Mouse events
// Keyboard events
// Window events (resize, hide, focus)
// Quit
// Other OS events (signals?)
enum Event_Type
{
EVENT_NONE,
EVENT_QUIT,
EVENT_MOUSE_MOVE,
EVENT_KEY,
EVENT_RESIZE,
EVENT_FOCUS,
EVENT_UNFOCUS,
EVENT_TEXT,
EVENT_COUNT
};
// @Performance: a lot of this codes are sequential in Linux. Check with other OSs if that's the case. If it is, we can have faster mapping by subtracting and adding an offset.
enum Key_Code
{
KEY_UNKNOWN = 0,
// @Correctness: check all ascii characters that are on a keyboard
KEY_ENTER = '\r',
KEY_ESCAPE = '\e',
KEY_BACKSPACE = '\b',
KEY_TAB = '\t',
KEY_SPACE = ' ',
KEY_EXCLAMATION = '!',
KEY_DOUBLE_QUOTE = '"',
KEY_HASH = '#',
KEY_PERCENT = '%',
KEY_DOLLAR = '$',
KEY_AMPERSAND = '&',
KEY_SINGLE_QUOTE = '\'',
KEY_LEFT_PARENTHESIS = '(',
KEY_RIGHT_PARENTHESIS = ')',
KEY_ASTERISK = '*',
KEY_PLUS = '+',
KEY_COMMA = ',',
KEY_MINUS = '-',
KEY_PERIOD = '.',
KEY_SLASH = '/',
KEY_0 = '0',
KEY_1 = '1',
KEY_2 = '2',
KEY_3 = '3',
KEY_4 = '4',
KEY_5 = '5',
KEY_6 = '6',
KEY_7 = '7',
KEY_8 = '8',
KEY_9 = '9',
KEY_COLON = ':',
KEY_SEMICOLON = ';',
KEY_LESS = '<',
KEY_EQUALS = '=',
KEY_GREATER = '>',
KEY_QUESTION = '?',
KEY_AT = '@',
KEY_LEFT_BRACKET = '[',
KEY_RIGHT_BRACKET = ']',
KEY_BACKSLASH = '\\',
KEY_CARET = '^',
KEY_UNDERSCORE = '_',
KEY_BACKQUOTE = '`',
KEY_A = 'A',
KEY_B = 'B',
KEY_C = 'C',
KEY_D = 'D',
KEY_E = 'E',
KEY_F = 'F',
KEY_G = 'G',
KEY_H = 'H',
KEY_I = 'I',
KEY_J = 'J',
KEY_K = 'K',
KEY_L = 'L',
KEY_M = 'M',
KEY_N = 'N',
KEY_O = 'O',
KEY_P = 'P',
KEY_Q = 'Q',
KEY_R = 'R',
KEY_S = 'S',
KEY_T = 'T',
KEY_U = 'U',
KEY_V = 'V',
KEY_W = 'W',
KEY_X = 'X',
KEY_Y = 'Y',
KEY_Z = 'Z',
KEY_CAPSLOCK = 1000,
KEY_F1,
KEY_F2,
KEY_F3,
KEY_F4,
KEY_F5,
KEY_F6,
KEY_F7,
KEY_F8,
KEY_F9,
KEY_F10,
KEY_F11,
KEY_F12,
KEY_PRINTSCREEN,
KEY_SCROLLLOCK,
KEY_PAUSE,
KEY_INSERT,
KEY_DELETE,
KEY_HOME,
KEY_END,
KEY_PAGEUP,
KEY_PAGEDOWN,
KEY_ARROW_UP,
KEY_ARROW_DOWN,
KEY_ARROW_LEFT,
KEY_ARROW_RIGHT,
KEY_NUMLOCK,
KEY_PAD_DIVIDE,
KEY_PAD_MULTIPLY,
KEY_PAD_MINUS,
KEY_PAD_PLUS,
KEY_PAD_ENTER,
KEY_PAD_1,
KEY_PAD_2,
KEY_PAD_3,
KEY_PAD_4,
KEY_PAD_5,
KEY_PAD_6,
KEY_PAD_7,
KEY_PAD_8,
KEY_PAD_9,
KEY_PAD_0,
KEY_PAD_PERIOD,
KEY_LEFT_CTRL,
KEY_RIGHT_CTRL,
KEY_LEFT_SHIFT,
KEY_RIGHT_SHIFT,
KEY_LEFT_ALT,
KEY_RIGHT_ALT,
KEY_MOUSE_LEFT,
KEY_MOUSE_MIDDLE,
KEY_MOUSE_RIGHT,
KEY_MOUSE_WHEEL_UP,
KEY_MOUSE_WHEEL_DOWN,
KEY_MOUSE_4,
KEY_MOUSE_5,
// @Correctness: check for more keys in: USB spec, linux libinput/x11/wayland/whatever, windows win32
};
struct Event_Key
{
bool pressed;
Key_Code key_code;
};
struct Event_Mouse_Move
{
bool relative;
union
{
v2 position;
v2 delta;
};
};
struct Event_Resize
{
s32 width, height;
};
struct Event_Text
{
char data[16]; // @Correctness: We have a bug if the os sends text that is longer
};
struct Event
{
Event_Type type;
union
{
Event_Key key;
Event_Mouse_Move mouse_move;
Event_Resize resize;
Event_Text text;
};
};
#endif

319
code/lib/geometry.h Normal file
View File

@@ -0,0 +1,319 @@
#ifndef _PIUMA_LIB_GEOMETRY_H_
#define _PIUMA_LIB_GEOMETRY_H_
#include "types.h"
#include "math.h"
// Rect
union Rect
{
struct
{
f32 x, y;
f32 w, h;
};
struct
{
v2 position; // Usually, the top-left corner of the rectangle
v2 size;
};
};
inline bool is_inside(Rect rect, v2 p)
{
bool in_range_x = rect.x <= p.x && p.x <= (rect.x + rect.w);
bool in_range_y = rect.y <= p.y && p.y <= (rect.y + rect.h);
return in_range_x && in_range_y;
}
// @Feature: add Cube/Parallelepiped? Unlike Box, it has rotations
// Box
struct Box
{
v3 min;
v3 max;
};
inline bool is_inside(Box b, v3 p)
{
return
(p.x < b.min.x || p.x > b.max.x) ||
(p.y < b.min.y || p.y > b.max.y) ||
(p.z < b.min.z || p.z > b.max.z);
}
inline bool overlaps(Box a, Box b)
{
if(a.min.x > b.max.x) // no overlap
return false;
if(a.max.x < b.min.x) // no overlap
return false;
if(a.min.y > b.max.y) // no overlap
return false;
if(a.max.y < b.min.y) // no overlap
return false;
if(a.min.z > b.max.z) // no overlap
return false;
if(a.max.z < b.min.z) // no overlap
return false;
return true;
}
inline Box box_from_point_cloud(v3 *points, u32 count)
{
if(count == 0)
return Box{.min = {0,0,0}, .max = {0,0,0}};
Box box;
box.min = points[0];
box.max = points[0];
for(u32 i = 0; i < count; i++)
{
v3 p = points[i];
box.min.x = minimum(box.min.x, p.x);
box.min.y = minimum(box.min.y, p.y);
box.min.z = minimum(box.min.z, p.z);
box.max.x = maximum(box.max.x, p.x);
box.max.y = maximum(box.max.y, p.y);
box.max.z = maximum(box.max.z, p.z);
}
return box;
}
inline v3 box_closest_point(Box b, v3 point);
inline f32 box_SDF(Box b, v3 point, v3* res_closest = NULL)
{
v3 closest = box_closest_point(b, point);
f32 sign = -1 * is_inside(b, point);
if(res_closest)
*res_closest = closest;
return sign * distance(closest, point);
}
// Ray
struct Ray
{
v3 position;
v3 direction;
};
// Circle
// @Cleanup: Should Circle be merged with Sphere?
struct Circle
{
v2 center;
f32 radius;
};
inline bool is_inside(Circle c, v2 p)
{
v2 v = p - c.center;
return dot(v, v) <= square(c.radius);
}
// Sphere
struct Sphere
{
v3 center;
f32 radius;
};
inline bool is_inside(Sphere s, v3 p)
{
v3 v = p - s.center;
return dot(v, v) <= square(s.radius); // distance² <= radius²
}
inline f32 sphere_SDF(Sphere s, v3 point)
{
return distance(s.center, point) - s.radius;
}
// Segment
struct Segment
{
v3 a;
v3 b;
};
// Plane
struct Plane
{
v3 normal;
f32 offset;
};
inline f32 plane_SDF(Plane plane, v3 point)
{
f32 projected = dot(point, plane.normal);
return plane.offset - projected;
}
// Projections
inline f32 project_point_on_vector(v3 vector, v3 point)
{
return dot(vector, point);
}
inline v3 project_point_on_plane(Plane plane, v3 point)
{
f32 distance = plane_SDF(plane, point);
return point - plane.normal * distance;
}
// Closest point
inline v3 segment_closest_point(Segment seg, v3 point)
{
v3 ab = seg.b - seg.a;
v3 ap = point - seg.a;
f32 u = dot(ab, ap);
return seg.a + ab * clamp(0.0, 1.0, u);
}
inline v3 box_closest_point(Box b, v3 point)
{
v3 closest;
// Closest point on the box is the one with coords closer to the ones of the point,
// so for each axis we can clamp to the nearest point of the border.
f32 dx1 = abs(b.min.x - point.x);
f32 dx2 = abs(b.max.x - point.x);
closest.x = (dx1 < dx2) ? b.min.x : b.max.x;
f32 dy1 = abs(b.min.y - point.y);
f32 dy2 = abs(b.max.y - point.y);
closest.y = (dy1 < dy2) ? b.min.y : b.max.y;
f32 dz1 = abs(b.min.z - point.z);
f32 dz2 = abs(b.max.z - point.z);
closest.z = (dz1 < dz2) ? b.min.z : b.max.z;
return closest;
}
// Triangles functions
inline v3 triangle_normal(v3 a, v3 b, v3 c)
{
v3 ba = b - a;
v3 ca = c - a;
v3 orthogonal = cross(ba, ca);
return normalize(orthogonal);
}
// Transformations (all angles in radians)
inline m4 rotation_x(f32 angle)
{
f32 c = cos(angle);
f32 s = sin(angle);
m4 result = m4_identity;
result.E[1][1] = c;
result.E[1][2] = -s;
result.E[2][1] = s;
result.E[2][2] = c;
return result;
}
inline m4 rotation_y(f32 angle)
{
f32 c = cos(angle);
f32 s = sin(angle);
m4 result = m4_identity;
result.E[0][0] = c;
result.E[0][2] = s;
result.E[2][0] = -s;
result.E[2][2] = c;
return result;
}
inline m4 rotation_z(f32 angle)
{
f32 c = cos(angle);
f32 s = sin(angle);
m4 result = m4_identity;
result.E[0][0] = c;
result.E[0][1] = -s;
result.E[1][0] = s;
result.E[1][1] = c;
return result;
}
inline m4 rotation(f32 x, f32 y, f32 z)
{
return rotation_z(z) * rotation_y(y) * rotation_x(x);
}
inline m4 rotation_v3(v3 angle)
{
return rotation(angle.x, angle.y, angle.z);
}
inline m4 translation(f32 x, f32 y, f32 z)
{
m4 result = m4_identity;
result.E[0][3] = x;
result.E[1][3] = y;
result.E[2][3] = z;
return result;
}
inline m4 translation_v3(v3 t)
{
return translation(t.x, t.y, t.z);
}
inline m4 scale(f32 x, f32 y, f32 z)
{
m4 result = m4_zero;
result.E[0][0] = x;
result.E[1][1] = y;
result.E[2][2] = z;
result.E[3][3] = 1.0;
return result;
}
inline m4 scale_v3(v3 factor)
{
return scale(factor.x, factor.y, factor.z);
}
inline m4 scale(f32 factor)
{
return scale(factor, factor, factor);
}
// Primitives
// Pass array of 8 elements to fill with coordinates
inline void build_cube_vertices(v3 *vertices)
{
for(int x = 0; x < 2; x++)
for(int y = 0; y < 2; y++)
for(int z = 0; z < 2; z++)
vertices[x*2*2 + y*2 + z] = v3{.x = x - 0.5f, .y = y - 0.5f, .z = z - 0.5f};
}
#endif

97
code/lib/hashing.h Normal file
View File

@@ -0,0 +1,97 @@
#ifndef _PIUMA_LIB_HASHING_H_
#define _PIUMA_LIB_HASHING_H_
//#include "bits.h"
static const u32 hash_crc32_table[256] = {
0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3,
0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988, 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91,
0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE, 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7,
0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC, 0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5,
0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172, 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B,
0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940, 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59,
0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F,
0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924, 0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D,
0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433,
0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, 0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01,
0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E, 0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457,
0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA, 0xFCB9887C, 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65,
0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2, 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB,
0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0, 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9,
0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086, 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F,
0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, 0x2EB40D81, 0xB7BD5C3B, 0xC0BA6CAD,
0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A, 0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683,
0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8, 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1,
0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, 0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7,
0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC, 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5,
0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252, 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B,
0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, 0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79,
0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236, 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F,
0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D,
0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, 0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713,
0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38, 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21,
0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E, 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777,
0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, 0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45,
0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2, 0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB,
0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9,
0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, 0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF,
0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94, 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D
};
/*
// Code to compute the lookup table for CRC32
// table needs 256 spaces
static const u32 hash_crc32_polynomial = 0x04C11DB7;
inline void hash_crc32_make_table(u32 *table)
{
u32 polynomial = bits_reverse(hash_crc32_polynomial);
for(u32 byte = 0; byte <= 0xFF; byte++)
{
u32 crc = byte;
for(u8 bit = 0; bit < 8; bit++)
{
if(crc & 1)
crc = (crc >> 1) ^ polynomial;
else
crc = (crc >> 1);
}
table[byte] = crc;
}
}
*/
inline u32 hash_crc32(const void *data, u64 size, u32 seed = 0xFFFFFFFF)
{
u32 crc = seed;
u8 *d = (u8*)data;
while(size--)
{
crc = hash_crc32_table[(crc & 0xFF) ^ *d] ^ (crc >> 8);
d++;
}
return ~crc;
}
/*
// Simpler code to compute CRC32, one bit at a time.
// The version with the lookup table computes 8 bit at a time.
inline u32 hash_crc32(const void *data, u64 size, u32 seed = 0xFFFFFFFF)
{
u8 *d = (u8*)data;
u32 crc = seed;
while(size--)
{
crc = crc ^ (*d++ << 24);
for(int i = 0; i < 8; i++)
{
if(crc & (1L<<31))
crc = (crc << 1) ^ hash_crc32_polynomial;
else
crc = (crc << 1);
}
}
return bits_endian_swap(~crc);
}
*/
#endif

1432
code/lib/math.h Normal file

File diff suppressed because it is too large Load Diff

10
code/lib/memory.h Normal file
View File

@@ -0,0 +1,10 @@
#ifndef _PIUMA_LIB_MEMORY_H_
#define _PIUMA_LIB_MEMORY_H_
#include <stddef.h>
typedef void *(*alloc_t)(size_t size);
typedef void *(*realloc_t)(void *ptr, size_t size);
typedef void (*free_t)(void *ptr);
#endif

93
code/lib/queue.h Normal file
View File

@@ -0,0 +1,93 @@
#ifndef _PIUMA_LIB_QUEUE_H_
#define _PIUMA_LIB_QUEUE_H_
#include "types.h"
#include <assert.h>
struct queue_header
{
u64 start;
u64 size;
u64 capacity;
};
#define QUEUE_HEADER_PTR(queue) ((queue_header *)(((u8*)queue) - sizeof(queue_header)))
#define QUEUE_TYPE(type) type *
#define Queue_Alloc(alloc_func, type, capacity) ((type*) _queue_alloc(alloc_func, sizeof(type), capacity))
#define Queue_Free(free_func, queue) free_func(QUEUE_HEADER_PTR(queue))
#define Queue_Pop(queue) (queue[_queue_pop_index((u8*)queue)])
#define Queue_Push(queue, element) { queue[_queue_at_index((u8*)queue, QUEUE_HEADER_PTR(queue)->size)] = element; _queue_push_fix_indices((u8*)queue); }
#define Queue_At(queue, index) (queue[_queue_at_index((u8*)queue, index)])
#define Queue_Size(queue) _queue_size((u8*)queue)
#define Queue_Capacity(queue) _queue_capacity((u8*)queue)
typedef void * (*alloc_func_t)(u64);
typedef void (*free_func_t)(void *);
inline u8 * _queue_alloc(alloc_func_t alloc_func, u64 sizeof_type, u64 capacity)
{
u8 *data;
queue_header *header;
data = (u8 *)alloc_func(sizeof(queue_header) + sizeof_type * capacity);
header = (queue_header *)data;
header->capacity = capacity;
header->start = 0;
header->size = 0;
return data + sizeof(queue_header);
}
inline u64 _queue_pop_index(u8 *queue)
{
queue_header *header = QUEUE_HEADER_PTR(queue);
assert(header->size > 0);
u64 element_index = header->start;
header->start = (header->start + 1) % header->capacity;
header->size--;
return element_index;
}
inline void _queue_push_fix_indices(u8 *queue)
{
queue_header *header = QUEUE_HEADER_PTR(queue);
header->size++;
if(header->size > header->capacity)
{
// Queue is full. Remove oldest element
header->start = (header->start + 1) % header->capacity;
header->size = header->capacity;
}
}
inline u64 _queue_at_index(u8 *queue, u64 index)
{
queue_header *header = QUEUE_HEADER_PTR(queue);
return (header->start + index) % header->capacity;
}
inline u64 _queue_size(u8 *queue)
{
queue_header *header = QUEUE_HEADER_PTR(queue);
return header->size;
}
inline u64 _queue_capacity(u8 *queue)
{
queue_header *header = QUEUE_HEADER_PTR(queue);
return header->capacity;
}
#endif

196
code/lib/text.cpp Normal file
View File

@@ -0,0 +1,196 @@
#include "text.h"
u64 utf8_codepoint_count(const char *s)
{
u64 count = 0;
while(*s)
{
if(utf8_is_codepoint_start(s))
count++;
s++;
}
return count;
}
bool utf8_is_codepoint_start(const char *s)
{
return (*s & 0b11000000) != 0b10000000;
}
u32 utf8_codepoint_bytes(const char *s)
{
if(!utf8_is_codepoint_start(s))
return 0; // Error: This byte belongs to a previous codepoint
if((*s & 0b10000000) == 0b00000000) //1 byte codepoint
return 1;
else if((*s & 0b11100000) == 0b11000000) //2 bytes codepoint
return 2;
else if((*s & 0b11110000) == 0b11100000) //3 bytes codepoint
return 3;
else if((*s & 0b11111000) == 0b11110000) //4 bytes codepoint
return 4;
return 0;
}
/* If bytes_read returns 0, we either reached the end of the string or there was a decoding error */
utf8_codepoint utf8_extract_codepoint(const char *s, u64 current_index, u32 *bytes_read)
{
s += current_index;
// UTF8:
// First byte: (0xxxxxxx = 1 byte, 110xxxxx = 2 byte, 1110xxxx = 3 byte, 11110xxx = 4 byte)
// Next bytes: 10xxxxxx
// To get a Codepoint: concatenate all the xxxx
utf8_codepoint codepoint = 0;
*bytes_read = 0;
u8 next_bytes = 0;
if(!utf8_is_codepoint_start(s))
{
// Error: This byte belongs to a previous codepoint
return 0;
}
if((*s & 0b10000000) == 0b00000000) //1 byte codepoint
{
codepoint = *s;
next_bytes = 0;
}
else if((*s & 0b11100000) == 0b11000000) //2 bytes codepoint
{
codepoint = (*s & 0b00011111);
next_bytes = 1;
}
else if((*s & 0b11110000) == 0b11100000) //3 bytes codepoint
{
codepoint = (*s & 0b00001111);
next_bytes = 2;
}
else if((*s & 0b11111000) == 0b11110000) //4 bytes codepoint
{
codepoint = (*s & 0b00000111);
next_bytes = 3;
}
for(u8 i = 0; i < next_bytes; i++)
{
s++;
if(*s == 0)
{
// Error: End of string reached before completing codepoint
return 0;
}
if((*s & 0b11000000) != 0b10000000)
{
// Error: Byte prefix does not match with the expected one. Broken codepoint
return 0;
}
codepoint = codepoint << 6;
codepoint |= (*s & 0b00111111);
}
*bytes_read = next_bytes + 1;
return codepoint;
}
u32 utf8_bytes_to_next_valid_codepoint(const char *s, u64 current_index)
{
s += current_index;
u64 bytes = 1;
while(*(s + bytes))
{
if(utf8_is_codepoint_start(s + bytes))
break;
bytes++;
}
return bytes;
}
u32 utf8_bytes_to_prev_valid_codepoint(const char *s, u64 current_index)
{
s += current_index;
u64 bytes = 0;
while(bytes < current_index)
{
bytes++;
if(utf8_is_codepoint_start(s - bytes))
break;
}
return bytes;
}
u64 utf8_from_string(const char *s, u64 *bytes_read, utf8_codepoint *result, u64 result_size)
{
u64 decoded = 0;
bytes_read = 0;
while(*s && decoded < result_size)
{
u32 read = 0;
result[decoded] = utf8_extract_codepoint(s, 0, &read);
if(read == 0)
{
bytes_read = 0;
break;
}
s += read;
bytes_read += read;
decoded++;
}
return decoded;
}
u64 utf8_to_string(utf8_codepoint *codepoints, u64 count, char *result, u64 result_size)
{
result_size--; // Reserve space for zero-terminator
u64 i = 0;
u64 result_i = 0;
for(i = 0; i < count; i++)
{
utf8_codepoint cp = codepoints[i];
if((cp & 0xFFFFFF80) == 0) // 1 byte
{
if(result_i + 1 >= result_size) // Not enought space left
break;
result[result_i++] = cp & 0b01111111;
}
else if((cp & 0xFFFFF800) == 0) // 2 bytes
{
if(result_i + 2 >= result_size) // Not enought space left
break;
result[result_i++] = 0b11000000 | ((cp >> 6) & 0b00011111);
result[result_i++] = 0b10000000 | ((cp ) & 0b00111111);
}
else if((cp & 0xFFFF0000) == 0) // 3 bytes
{
if(result_i + 3 >= result_size) // Not enought space left
break;
result[result_i++] = 0b11100000 | ((cp >> 12) & 0b00001111);
result[result_i++] = 0b10000000 | ((cp >> 6) & 0b00111111);
result[result_i++] = 0b10000000 | ((cp ) & 0b00111111);
}
else if((cp & 0xFFE00000) == 0) // 4 bytes
{
if(result_i + 4 >= result_size) // Not enought space left
break;
result[result_i++] = 0b11110000 | ((cp >> 18) & 0b00000111);
result[result_i++] = 0b10000000 | ((cp >> 12) & 0b00111111);
result[result_i++] = 0b10000000 | ((cp >> 6) & 0b00111111);
result[result_i++] = 0b10000000 | ((cp ) & 0b00111111);
}
else
{
// Invalid codepoint
break;
}
}
result[result_i] = 0;
return i;
}

22
code/lib/text.h Normal file
View File

@@ -0,0 +1,22 @@
#ifndef _PIUMA_LIB_TEXT_H_
#define _PIUMA_LIB_TEXT_H_
#include "types.h"
typedef u32 utf8_codepoint;
u64 utf8_codepoint_count(const char *s);
bool utf8_is_codepoint_start(const char *s);
u32 utf8_codepoint_bytes(const char *s);
/* If bytes_read returns 0, we either reached the end of the string or there was a decoding error */
utf8_codepoint utf8_extract_codepoint(const char *s, u64 current_index, u32 *bytes_read);
u32 utf8_bytes_to_next_valid_codepoint(const char *s, u64 current_index);
u32 utf8_bytes_to_prev_valid_codepoint(const char *s, u64 current_index);
/* Returns the number of codepoints read. If bytes_read returns 0, there was a decoding error */
u64 utf8_from_string(const char *s, u64 *bytes_read, utf8_codepoint *result, u64 result_size);
/* Returns the number of codepoints written. */
u64 utf8_to_string(utf8_codepoint *codepoints, u64 count, char *result, u64 result_size);
#endif

42
code/lib/types.h Normal file
View File

@@ -0,0 +1,42 @@
#ifndef _PIUMA_LIB_TYPES_H_
#define _PIUMA_LIB_TYPES_H_
#include <stdint.h>
#include <stddef.h>
// Integers
typedef int8_t s8;
typedef int16_t s16;
typedef int32_t s32;
typedef int64_t s64;
typedef uint8_t u8;
typedef uint16_t u16;
typedef uint32_t u32;
typedef uint64_t u64;
// Real numbers
typedef float f32;
typedef double f64;
// Binary
typedef u8 b8;
typedef u16 b16;
typedef u32 b32;
typedef u64 b64;
// Buffer
struct Buffer
{
u64 size;
u8 *data;
};
struct String
{
u64 size;
u8 *text;
};
#endif