summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--example/UTF-8-demo.html213
-rwxr-xr-xexample/build.sh7
-rwxr-xr-xexample/examplebin0 -> 65664 bytes
-rw-r--r--example/example.c260
-rw-r--r--prb.h26
-rw-r--r--prb_macros.h61
-rw-r--r--prb_math.c385
-rw-r--r--prb_math.h64
-rw-r--r--prb_memory.c42
-rw-r--r--prb_memory.h11
-rw-r--r--prb_os_io.c31
-rw-r--r--prb_os_io.h6
-rw-r--r--prb_string.c115
-rw-r--r--prb_string.h22
-rw-r--r--prb_types.h84
15 files changed, 1327 insertions, 0 deletions
diff --git a/example/UTF-8-demo.html b/example/UTF-8-demo.html
new file mode 100644
index 0000000..b8157db
--- /dev/null
+++ b/example/UTF-8-demo.html
@@ -0,0 +1,213 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head><title>UTF-8 test file</title></head>
+ <body>
+ <p>Original by Markus Kuhn, adapted for HTML by Martin D&uuml;rst.</p>
+<pre>
+UTF-8 encoded sample plain-text file
+‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾
+
+Markus Kuhn [ˈmaʳkʊs kuːn] &lt;mkuhn@acm.org> — 1999-08-20
+
+
+The ASCII compatible UTF-8 encoding of ISO 10646 and Unicode
+plain-text files is defined in RFC 2279 and in ISO 10646-1 Annex R.
+
+
+Using Unicode/UTF-8, you can write in emails and source code things such as
+
+Mathematics and Sciences:
+
+ ∮ E⋅da = Q, n → ∞, ∑ f(i) = ∏ g(i), ∀x∈ℝ: ⌈x⌉ = −⌊−x⌋, α ∧ ¬β = ¬(¬α ∨ β),
+
+ ℕ ⊆ ℕ₀ ⊂ ℤ ⊂ ℚ ⊂ ℝ ⊂ ℂ, ⊥ &lt; a ≠ b ≡ c ≤ d ≪ ⊤ ⇒ (A ⇔ B),
+
+ 2H₂ + O₂ ⇌ 2H₂O, R = 4.7 kΩ, ⌀ 200 mm
+
+Linguistics and dictionaries:
+
+ ði ıntəˈnæʃənəl fəˈnɛtık əsoʊsiˈeıʃn
+ Y [ˈʏpsilɔn], Yen [jɛn], Yoga [ˈjoːgɑ]
+
+APL:
+
+ ((V⍳V)=⍳⍴V)/V←,V ⌷←⍳→⍴∆∇⊃‾⍎⍕⌈
+
+Nicer typography in plain text files:
+
+ ╔══════════════════════════════════════════╗
+ ║ ║
+ ║ • ‘single’ and “double” quotes ║
+ ║ ║
+ ║ • Curly apostrophes: “We’ve been here” ║
+ ║ ║
+ ║ • Latin-1 apostrophe and accents: '´` ║
+ ║ ║
+ ║ • ‚deutsche‘ „Anführungszeichen“ ║
+ ║ ║
+ ║ • †, ‡, ‰, •, 3–4, —, −5/+5, ™, … ║
+ ║ ║
+ ║ • ASCII safety test: 1lI|, 0OD, 8B ║
+ ║ ╭─────────╮ ║
+ ║ • the euro symbol: │ 14.95 € │ ║
+ ║ ╰─────────╯ ║
+ ╚══════════════════════════════════════════╝
+
+Greek (in Polytonic):
+
+ The Greek anthem:
+
+ Σὲ γνωρίζω ἀπὸ τὴν κόψη
+ τοῦ σπαθιοῦ τὴν τρομερή,
+ σὲ γνωρίζω ἀπὸ τὴν ὄψη
+ ποὺ μὲ βία μετράει τὴ γῆ.
+
+ ᾿Απ᾿ τὰ κόκκαλα βγαλμένη
+ τῶν ῾Ελλήνων τὰ ἱερά
+ καὶ σὰν πρῶτα ἀνδρειωμένη
+ χαῖρε, ὦ χαῖρε, ᾿Ελευθεριά!
+
+ From a speech of Demosthenes in the 4th century BC:
+
+ Οὐχὶ ταὐτὰ παρίσταταί μοι γιγνώσκειν, ὦ ἄνδρες ᾿Αθηναῖοι,
+ ὅταν τ᾿ εἰς τὰ πράγματα ἀποβλέψω καὶ ὅταν πρὸς τοὺς
+ λόγους οὓς ἀκούω· τοὺς μὲν γὰρ λόγους περὶ τοῦ
+ τιμωρήσασθαι Φίλιππον ὁρῶ γιγνομένους, τὰ δὲ πράγματ᾿
+ εἰς τοῦτο προήκοντα, ὥσθ᾿ ὅπως μὴ πεισόμεθ᾿ αὐτοὶ
+ πρότερον κακῶς σκέψασθαι δέον. οὐδέν οὖν ἄλλο μοι δοκοῦσιν
+ οἱ τὰ τοιαῦτα λέγοντες ἢ τὴν ὑπόθεσιν, περὶ ἧς βουλεύεσθαι,
+ οὐχὶ τὴν οὖσαν παριστάντες ὑμῖν ἁμαρτάνειν. ἐγὼ δέ, ὅτι μέν
+ ποτ᾿ ἐξῆν τῇ πόλει καὶ τὰ αὑτῆς ἔχειν ἀσφαλῶς καὶ Φίλιππον
+ τιμωρήσασθαι, καὶ μάλ᾿ ἀκριβῶς οἶδα· ἐπ᾿ ἐμοῦ γάρ, οὐ πάλαι
+ γέγονεν ταῦτ᾿ ἀμφότερα· νῦν μέντοι πέπεισμαι τοῦθ᾿ ἱκανὸν
+ προλαβεῖν ἡμῖν εἶναι τὴν πρώτην, ὅπως τοὺς συμμάχους
+ σώσομεν. ἐὰν γὰρ τοῦτο βεβαίως ὑπάρξῃ, τότε καὶ περὶ τοῦ
+ τίνα τιμωρήσεταί τις καὶ ὃν τρόπον ἐξέσται σκοπεῖν· πρὶν δὲ
+ τὴν ἀρχὴν ὀρθῶς ὑποθέσθαι, μάταιον ἡγοῦμαι περὶ τῆς
+ τελευτῆς ὁντινοῦν ποιεῖσθαι λόγον.
+
+ Δημοσθένους, Γ´ ᾿Ολυνθιακὸς
+
+Georgian:
+
+ From a Unicode conference invitation:
+
+ გთხოვთ ახლავე გაიაროთ რეგისტრაცია Unicode-ის მეათე საერთაშორისო
+ კონფერენციაზე დასასწრებად, რომელიც გაიმართება 10-12 მარტს,
+ ქ. მაინცში, გერმანიაში. კონფერენცია შეჰკრებს ერთად მსოფლიოს
+ ექსპერტებს ისეთ დარგებში როგორიცაა ინტერნეტი და Unicode-ი,
+ ინტერნაციონალიზაცია და ლოკალიზაცია, Unicode-ის გამოყენება
+ ოპერაციულ სისტემებსა, და გამოყენებით პროგრამებში, შრიფტებში,
+ ტექსტების დამუშავებასა და მრავალენოვან კომპიუტერულ სისტემებში.
+
+Russian:
+
+ From a Unicode conference invitation:
+
+ Зарегистрируйтесь сейчас на Десятую Международную Конференцию по
+ Unicode, которая состоится 10-12 марта 1997 года в Майнце в Германии.
+ Конференция соберет широкий круг экспертов по вопросам глобального
+ Интернета и Unicode, локализации и интернационализации, воплощению и
+ применению Unicode в различных операционных системах и программных
+ приложениях, шрифтах, верстке и многоязычных компьютерных системах.
+
+Thai (UCS Level 2):
+
+ Excerpt from a poetry on The Romance of The Three Kingdoms (a Chinese
+ classic 'San Gua'):
+
+ [----------------------------|------------------------]
+ ๏ แผ่นดินฮั่นเสื่อมโทรมแสนสังเวช พระปกเกศกองบู๊กู้ขึ้นใหม่
+ สิบสองกษัตริย์ก่อนหน้าแลถัดไป สององค์ไซร้โง่เขลาเบาปัญญา
+ ทรงนับถือขันทีเป็นที่พึ่ง บ้านเมืองจึงวิปริตเป็นนักหนา
+ โฮจิ๋นเรียกทัพทั่วหัวเมืองมา หมายจะฆ่ามดชั่วตัวสำคัญ
+ เหมือนขับไสไล่เสือจากเคหา รับหมาป่าเข้ามาเลยอาสัญ
+ ฝ่ายอ้องอุ้นยุแยกให้แตกกัน ใช้สาวนั้นเป็นชนวนชื่นชวนใจ
+ พลันลิฉุยกุยกีกลับก่อเหตุ ช่างอาเพศจริงหนาฟ้าร้องไห้
+ ต้องรบราฆ่าฟันจนบรรลัย ฤๅหาใครค้ำชูกู้บรรลังก์ ฯ
+
+ (The above is a two-column text. If combining characters are handled
+ correctly, the lines of the second column should be aligned with the
+ | character above.)
+
+Ethiopian:
+
+ Proverbs in the Amharic language:
+
+ ሰማይ አይታረስ ንጉሥ አይከሰስ።
+ ብላ ካለኝ እንደአባቴ በቆመጠኝ።
+ ጌጥ ያለቤቱ ቁምጥና ነው።
+ ደሀ በሕልሙ ቅቤ ባይጠጣ ንጣት በገደለው።
+ የአፍ ወለምታ በቅቤ አይታሽም።
+ አይጥ በበላ ዳዋ ተመታ።
+ ሲተረጉሙ ይደረግሙ።
+ ቀስ በቀስ፥ ዕንቁላል በእግሩ ይሄዳል።
+ ድር ቢያብር አንበሳ ያስር።
+ ሰው እንደቤቱ እንጅ እንደ ጉረቤቱ አይተዳደርም።
+ እግዜር የከፈተውን ጉሮሮ ሳይዘጋው አይድርም።
+ የጎረቤት ሌባ፥ ቢያዩት ይስቅ ባያዩት ያጠልቅ።
+ ሥራ ከመፍታት ልጄን ላፋታት።
+ ዓባይ ማደሪያ የለው፥ ግንድ ይዞ ይዞራል።
+ የእስላም አገሩ መካ የአሞራ አገሩ ዋርካ።
+ ተንጋሎ ቢተፉ ተመልሶ ባፉ።
+ ወዳጅህ ማር ቢሆን ጨርስህ አትላሰው።
+ እግርህን በፍራሽህ ልክ ዘርጋ።
+
+Runes:
+
+ ᚻᛖ ᚳᚹᚫᚦ ᚦᚫᛏ ᚻᛖ ᛒᚢᛞᛖ ᚩᚾ ᚦᚫᛗ ᛚᚪᚾᛞᛖ ᚾᚩᚱᚦᚹᛖᚪᚱᛞᚢᛗ ᚹᛁᚦ ᚦᚪ ᚹᛖᛥᚫ
+
+ (Old English, which transcribed into Latin reads 'He cwaeth that he
+ bude thaem lande northweardum with tha Westsae.' and means 'He said
+ that he lived in the northern land near the Western Sea.')
+
+Braille:
+
+ ⡌⠁⠧⠑ ⠼⠁⠒ ⡍⠜⠇⠑⠹⠰⠎ ⡣⠕⠌
+
+ ⡍⠜⠇⠑⠹ ⠺⠁⠎ ⠙⠑⠁⠙⠒ ⠞⠕ ⠃⠑⠛⠔ ⠺⠊⠹⠲ ⡹⠻⠑ ⠊⠎ ⠝⠕ ⠙⠳⠃⠞
+ ⠱⠁⠞⠑⠧⠻ ⠁⠃⠳⠞ ⠹⠁⠞⠲ ⡹⠑ ⠗⠑⠛⠊⠌⠻ ⠕⠋ ⠙⠊⠎ ⠃⠥⠗⠊⠁⠇ ⠺⠁⠎
+ ⠎⠊⠛⠝⠫ ⠃⠹ ⠹⠑ ⠊⠇⠻⠛⠹⠍⠁⠝⠂ ⠹⠑ ⠊⠇⠻⠅⠂ ⠹⠑ ⠥⠝⠙⠻⠞⠁⠅⠻⠂
+ ⠁⠝⠙ ⠹⠑ ⠡⠊⠑⠋ ⠍⠳⠗⠝⠻⠲ ⡎⠊⠗⠕⠕⠛⠑ ⠎⠊⠛⠝⠫ ⠊⠞⠲ ⡁⠝⠙
+ ⡎⠊⠗⠕⠕⠛⠑⠰⠎ ⠝⠁⠍⠑ ⠺⠁⠎ ⠛⠕⠕⠙ ⠥⠏⠕⠝ ⠰⡡⠁⠝⠛⠑⠂ ⠋⠕⠗ ⠁⠝⠹⠹⠔⠛ ⠙⠑
+ ⠡⠕⠎⠑ ⠞⠕ ⠏⠥⠞ ⠙⠊⠎ ⠙⠁⠝⠙ ⠞⠕⠲
+
+ ⡕⠇⠙ ⡍⠜⠇⠑⠹ ⠺⠁⠎ ⠁⠎ ⠙⠑⠁⠙ ⠁⠎ ⠁ ⠙⠕⠕⠗⠤⠝⠁⠊⠇⠲
+
+ ⡍⠔⠙⠖ ⡊ ⠙⠕⠝⠰⠞ ⠍⠑⠁⠝ ⠞⠕ ⠎⠁⠹ ⠹⠁⠞ ⡊ ⠅⠝⠪⠂ ⠕⠋ ⠍⠹
+ ⠪⠝ ⠅⠝⠪⠇⠫⠛⠑⠂ ⠱⠁⠞ ⠹⠻⠑ ⠊⠎ ⠏⠜⠞⠊⠊⠥⠇⠜⠇⠹ ⠙⠑⠁⠙ ⠁⠃⠳⠞
+ ⠁ ⠙⠕⠕⠗⠤⠝⠁⠊⠇⠲ ⡊ ⠍⠊⠣⠞ ⠙⠁⠧⠑ ⠃⠑⠲ ⠔⠊⠇⠔⠫⠂ ⠍⠹⠎⠑⠇⠋⠂ ⠞⠕
+ ⠗⠑⠛⠜⠙ ⠁ ⠊⠕⠋⠋⠔⠤⠝⠁⠊⠇ ⠁⠎ ⠹⠑ ⠙⠑⠁⠙⠑⠌ ⠏⠊⠑⠊⠑ ⠕⠋ ⠊⠗⠕⠝⠍⠕⠝⠛⠻⠹
+ ⠔ ⠹⠑ ⠞⠗⠁⠙⠑⠲ ⡃⠥⠞ ⠹⠑ ⠺⠊⠎⠙⠕⠍ ⠕⠋ ⠳⠗ ⠁⠝⠊⠑⠌⠕⠗⠎
+ ⠊⠎ ⠔ ⠹⠑ ⠎⠊⠍⠊⠇⠑⠆ ⠁⠝⠙ ⠍⠹ ⠥⠝⠙⠁⠇⠇⠪⠫ ⠙⠁⠝⠙⠎
+ ⠩⠁⠇⠇ ⠝⠕⠞ ⠙⠊⠌⠥⠗⠃ ⠊⠞⠂ ⠕⠗ ⠹⠑ ⡊⠳⠝⠞⠗⠹⠰⠎ ⠙⠕⠝⠑ ⠋⠕⠗⠲ ⡹⠳
+ ⠺⠊⠇⠇ ⠹⠻⠑⠋⠕⠗⠑ ⠏⠻⠍⠊⠞ ⠍⠑ ⠞⠕ ⠗⠑⠏⠑⠁⠞⠂ ⠑⠍⠏⠙⠁⠞⠊⠊⠁⠇⠇⠹⠂ ⠹⠁⠞
+ ⡍⠜⠇⠑⠹ ⠺⠁⠎ ⠁⠎ ⠙⠑⠁⠙ ⠁⠎ ⠁ ⠙⠕⠕⠗⠤⠝⠁⠊⠇⠲
+
+ (The first couple of paragraphs of "A Christmas Carol" by Dickens)
+
+Compact font selection example text:
+
+ ABCDEFGHIJKLMNOPQRSTUVWXYZ /0123456789
+ abcdefghijklmnopqrstuvwxyz £©µÀÆÖÞßéöÿ
+ –—‘“”„†•…‰™œŠŸž€ ΑΒΓΔΩαβγδω АБВГДабвгд
+ ∀∂∈ℝ∧∪≡∞ ↑↗↨↻⇣ ┐┼╔╘░►☺♀ fi�⑀₂ἠḂӥẄɐː⍎אԱა
+
+Greetings in various languages:
+
+ Hello world, Καλημέρα κόσμε, コンニチハ
+
+Box drawing alignment tests: █
+ ▉
+ ╔══╦══╗ ┌──┬──┐ ╭──┬──╮ ╭──┬──╮ ┏━━┳━━┓ ┎┒┏┑ ╷ ╻ ┏┯┓ ┌┰┐ ▊ ╱╲╱╲╳╳╳
+ ║┌─╨─┐║ │╔═╧═╗│ │╒═╪═╕│ │╓─╁─╖│ ┃┌─╂─┐┃ ┗╃╄┙ ╶┼╴╺╋╸┠┼┨ ┝╋┥ ▋ ╲╱╲╱╳╳╳
+ ║│╲ ╱│║ │║ ║│ ││ │ ││ │║ ┃ ║│ ┃│ ╿ │┃ ┍╅╆┓ ╵ ╹ ┗┷┛ └┸┘ ▌ ╱╲╱╲╳╳╳
+ ╠╡ ╳ ╞╣ ├╢ ╟┤ ├┼─┼─┼┤ ├╫─╂─╫┤ ┣┿╾┼╼┿┫ ┕┛┖┚ ┌┄┄┐ ╎ ┏┅┅┓ ┋ ▍ ╲╱╲╱╳╳╳
+ ║│╱ ╲│║ │║ ║│ ││ │ ││ │║ ┃ ║│ ┃│ ╽ │┃ ░░▒▒▓▓██ ┊ ┆ ╎ ╏ ┇ ┋ ▎
+ ║└─╥─┘║ │╚═╤═╝│ │╘═╪═╛│ │╙─╀─╜│ ┃└─╂─┘┃ ░░▒▒▓▓██ ┊ ┆ ╎ ╏ ┇ ┋ ▏
+ ╚══╩══╝ └──┴──┘ ╰──┴──╯ ╰──┴──╯ ┗━━┻━━┛ └╌╌┘ ╎ ┗╍╍┛ ┋ ▁▂▃▄▅▆▇█
+
+</pre>
+</body>
+</html>
diff --git a/example/build.sh b/example/build.sh
new file mode 100755
index 0000000..172aa69
--- /dev/null
+++ b/example/build.sh
@@ -0,0 +1,7 @@
+#!/bin/sh
+CFLAGS='-g -Wall'
+INCLUDE='-I..'
+LIBS='-lm'
+set -x
+#tcc $CFLAGS $INCLUDE $LIBS -o example example.c && ./example
+gcc $CFLAGS $INCLUDE $LIBS -o example example.c && ./example
diff --git a/example/example b/example/example
new file mode 100755
index 0000000..15b5b35
--- /dev/null
+++ b/example/example
Binary files differ
diff --git a/example/example.c b/example/example.c
new file mode 100644
index 0000000..1fa85b3
--- /dev/null
+++ b/example/example.c
@@ -0,0 +1,260 @@
+#include "prb.h"
+
+typedef struct {
+ S32 first;
+ S32 second;
+ B32 flags;
+} SomeStruct;
+
+typedef struct SLLNode {
+ S32 val;
+ struct SLLNode *next;
+} SLLNode;
+
+typedef struct DLLNode {
+ S32 val;
+ struct DLLNode *next;
+ struct DLLNode *prev;
+} DLLNode;
+
+int main(void)
+{
+ F32 verts[] = {
+ 1.0f, 0.0f, 0.0f,
+ 0.0f, 1.0f, 0.0f,
+ 0.0f, 0.0f, 1.0f
+ };
+
+ Assert(v3a(1.0f).y);
+ U64 memory_size = Kilobytes(4);
+ void *some_memory = malloc(memory_size);
+ *(S32 *)some_memory = 69;
+ U64 ptr_as_int = IntFromPtr(some_memory);
+ void *ptr_to_memory = PtrFromInt(ptr_as_int);
+ printf("IntFromPtr: %lu\n", ptr_as_int);
+ printf("Using PtrFromInt(%lu) to get the first element of some_memory: %d\n\n",
+ ptr_as_int, *(S32 *)ptr_to_memory);
+ free(some_memory);
+
+ printf("OffsetOfMember(SomeStruct, flags): %lld\n\n",
+ OffsetOfMember(SomeStruct, flags));
+
+ F32 range_min = 0.0f, range_max = 1.0f;
+ F32 clamped_number = 1.5f;
+ F32 another_clamped_number = -0.2f;
+ printf("ClampBottom(%f, %f): %f\n", range_min,
+ another_clamped_number, ClampBottom(another_clamped_number, range_min));
+ printf("ClampTop(%f, %f): %f\n", range_max,
+ clamped_number, ClampTop(clamped_number, range_max));
+
+ printf("Clamp(%f, %f, %f): %f\n", range_min, clamped_number, range_max,
+ Clamp(range_min, clamped_number, range_max));
+ printf("Clamp(%f, %f, %f): %f\n\n", range_min, another_clamped_number, range_max,
+ Clamp(range_min, another_clamped_number, range_max));
+
+ F32 swap_test_first = 10.0f, swap_test_second = 20.0f;
+ printf("Before Swap: swap_test_first = %f, swap_test_second = %f\n",
+ swap_test_first, swap_test_second);
+ Swap(F32, swap_test_first, swap_test_second);
+ printf("After Swap: swap_test_first = %f, swap_test_second = %f\n\n",
+ swap_test_first, swap_test_second);
+
+ SomeStruct some_stuct = { 10, 20, 30 };
+ printf("SomeStruct: first: %d, second: %d, flags: %d\n",
+ some_stuct.first, some_stuct.second, some_stuct.flags);
+ MemoryZero(&some_stuct, sizeof(SomeStruct));
+ printf("After MemoryZero(&some_stuct, sizeof(SomeStruct)):\n");
+ printf("some_stuct: first: %d, second: %d, flags: %d\n\n",
+ some_stuct.first, some_stuct.second, some_stuct.flags);
+
+ some_stuct = (SomeStruct){ 10, 20, 30 };
+ printf("some_stuct: first: %d, second: %d, flags: %d\n",
+ some_stuct.first, some_stuct.second, some_stuct.flags);
+ MemoryZeroStruct(&some_stuct);
+ printf("After MemoryZeroStruct(&some_stuct):\n");
+ printf("some_stuct: first: %d, second: %d, flags: %d\n\n",
+ some_stuct.first, some_stuct.second, some_stuct.flags);
+
+ printf("Before MemoryZeroArray:\n");
+ for (S32 i = 0; i < ArrayCount(verts); ++i)
+ printf("%f%c", verts[i], (((i+1)%4 == 0) ||
+ (i == ArrayCount(verts)-1)) ? '\n' : ' ');
+ MemoryZeroArray(verts);
+ printf("After:\n");
+ for (S32 i = 0; i < ArrayCount(verts); ++i)
+ printf("%f%c", verts[i], (((i+1)%4 == 0) ||
+ (i == ArrayCount(verts)-1)) ? '\n' : ' ');
+ printf("\n");
+
+ S32 dynamic_array_length = 10;
+ U64 dynamic_array_size = dynamic_array_length*sizeof(S32);
+ F32 *dynamic_array_first = malloc(dynamic_array_size);
+ F32 *dynamic_array_second = malloc(dynamic_array_size);
+ printf("first dynamic array:\n");
+ for (S32 i = 0; i < dynamic_array_length; ++i) {
+ F32 *element = dynamic_array_first+i;
+ *element = i+420;
+ printf("%f%c", *element, (i == dynamic_array_length-1) ? '\n' : ' ');
+ }
+ printf("second dynamic array:\n");
+ for (S32 i = 0; i < dynamic_array_length; ++i) {
+ F32 *element = dynamic_array_second+i;
+ printf("%f%c", *element, (i == dynamic_array_length-1) ? '\n' : ' ');
+ }
+ MemoryCopy(dynamic_array_second, dynamic_array_first, dynamic_array_size);
+ printf("After MemoryCopy(dynamic_array_second, dynamic_array_first, dynamic_array_size):\n");
+ printf("second dynamic array:\n");
+ for (S32 i = 0; i < dynamic_array_length; ++i) {
+ F32 *element = dynamic_array_second+i;
+ printf("%f%c", *element, (i == dynamic_array_length-1) ? '\n' : ' ');
+ }
+ S32 memory_match = MemoryMatch(dynamic_array_first, dynamic_array_second, dynamic_array_size);
+ printf("And MemoryMatch(MemoryMatch(dynamic_array_first, dynamic_array_second, dynamic_array_size): %d\n\n", memory_match);
+ free(dynamic_array_first);
+ free(dynamic_array_second);
+
+ printf("Linked Lists:\n");
+ printf("Singly linked list: ");
+ S32 list_length = 5;
+ U64 list_size = list_length*sizeof(SLLNode);
+ SLLNode *sllist = malloc(list_size);
+ SLLNode *sllfirst = 0;
+ SLLNode *slllast = 0;
+ for (S32 i = 0; i < list_length; ++i) {
+ SLLNode *new = sllist+i;
+ new->val = i;
+ SLLPush(sllfirst, slllast, new);
+ }
+ for (SLLNode *node = sllfirst; node; node = node->next)
+ printf("%d%s", node->val, ((node->next) ? " -> " : "\n"));
+ SLLPop(sllfirst, slllast);
+ printf("After SLLPop(sllfirst, slllast): ");
+ for (SLLNode *node = sllfirst; node; node = node->next)
+ printf("%d%s", node->val, ((node->next) ? " -> " : "\n"));
+ free(sllist);
+
+ printf("Doubly linked list: ");
+ list_length = 8;
+ list_size = list_length*sizeof(DLLNode);
+ DLLNode *dllist = malloc(list_size);
+ DLLNode *dllfirst = 0;
+ DLLNode *dlllast = 0;
+ for (S32 i = 0; i < list_length; ++i) {
+ DLLNode *new = dllist+i;
+ new->val = i;
+ DLLPushBack(dllfirst, dlllast, new);
+ }
+ for (DLLNode *node = dllfirst; node; node = node->next)
+ printf("%d%s", node->val, ((node->next) ? " -> " : "\n"));
+ printf("Remove odd numbers: ");
+ for (DLLNode *node = dllfirst; node; node = node->next)
+ if (node->val % 2 == 1)
+ DLLRemove(dllfirst, dlllast, node);
+ for (DLLNode *node = dllfirst; node; node = node->next)
+ printf("%d%s", node->val, ((node->next) ? " -> " : "\n"));
+ free(dllist);
+ printf("\n");
+
+ printf("I'm pretty sure the vectors are fine.\nAt least for the last few months :)\n\n");
+
+ printf("Matrices:\n");
+ printf("Identity:\n");
+ Mat4 m = MAT4_IDENTITY;
+ mat4print(m);
+ m = mat4scale(m, v3a(10.0f));
+ m = mat4translate(m, v3a(1.0f));
+ m = mat4translate(m, v3(0.0f, 68.0f, 0.0f));
+ mat4print(m);
+ printf("Determinant: %f\n", mat4det(m));
+ printf("Transpose:\n"); mat4print(mat4transpose(m));
+ printf("mat4rotate(MAT4_IDENTITY, v3(0.0f, 45.0f, 0.0f)):\n");
+ mat4print(mat4rotate(MAT4_IDENTITY, v3(0.0f, 45.0f, 0.0f)));
+
+ printf("Using Arenas:\n");
+ Arena *a = arena_alloc(0);
+ SLLNode *first = 0;
+ SLLNode *last = 0;
+ S32 node_count = 10;
+ for (S32 i = 0; i < node_count; ++i) {
+ SLLNode *new = arena_push(a, sizeof(SLLNode));
+ new->val = i;
+ SLLPush(first, last, new);
+ }
+ for (SLLNode *node = first; node; node = node->next)
+ printf("%d%s", node->val, ((node->next) ? " -> " : "\n"));
+ arena_release(a);
+
+ a = arena_alloc(sizeof(verts));
+ S32 verts_count = ArrayCount(verts);
+ F32 *dynamic_verts = arena_push(a, sizeof(verts));
+ MemoryZero(dynamic_verts, verts_count*sizeof(F32));
+ for (S32 i = 0; i < verts_count; ++i) {
+ F32 *vert = dynamic_verts+i;
+ printf("%f%c", *vert, (i == verts_count-1) ? '\n' : ' ');
+ }
+ arena_release(a);
+ printf("\n");
+
+ Arena *str_arena = arena_alloc(0);
+ printf("Strings:\n");
+ char *cstr = "This is a C str\n";
+ Str8 str = str8_from_cstr(cstr);
+ str = str8_chop_start(str, 10);
+ cstr = str8_to_cstr(a, str);
+ printf("%s", cstr);
+ str8print(str);
+ Str8 choped_str = str8_chop_end(str, 3);
+ str8print(choped_str);
+ printf("\n");
+ Str8List *list = str8_list(str_arena);
+ str8_list_push(str_arena, list, str, 0);
+ str8_list_push(str_arena, list, str8_from_cstr("test"), 0);
+ str8_list_push(str_arena, list, str8_from_cstr("and this is also a test\n"), 0);
+ str8_list_push(str_arena, list, str8_from_cstr("Kinda works!"), 1);
+ printf("Str8List: ");
+ str8_list_print(list);
+ arena_release(str_arena);
+ str8_list_print(list);
+
+ str_arena = arena_alloc(Kilobytes(10));
+ memory_size = 512;
+ U32 count = memory_size/sizeof(S32);
+ S32 *some = arena_push(str_arena, memory_size);
+ printf("str_arena(size): %ld\nMemory:\n", str_arena->cap);
+ for (S32 i = 0; i < count; i++) {
+ S32 *e = some+i;
+ *e = 69;
+ printf("%d: %d%c", i, *e, ((i == count-1) ? '\n' : ' '));
+ }
+ printf("Memory used: %lu\n", str_arena->used);
+ printf("Remaining memory: %lu\n",
+ str_arena->cap-str_arena->used);
+
+ arena_pop(str_arena, memory_size);
+
+ printf("After arena pop\n");
+ printf("Memory used: %lu\n", str_arena->used);
+ printf("Remaining memory: %lu\n",
+ str_arena->cap-str_arena->used);
+ printf("some ptr is %s\n", some ? "not null" : "null");
+ printf("str_arena(size): %lu\nMemory:\n", str_arena->cap);
+
+ Str8 new_str = str8_pushf(str_arena, "Test of the formatted string: %d\n", 69);
+ str8print(new_str);
+
+ list = str8_list(str_arena);
+ str8_list_pushf(str_arena, list, 0, "This is a list %d", 34);
+ str8_list_pushf(str_arena, list, 0, " of formatted strings: %d", 35);
+ str8_list_pushf(str_arena, list, 1, "And you can push to the start");
+ str8_list_print(list);
+
+ arena_release(str_arena);
+
+ a = arena_alloc(Megabytes(1));
+ str8print(str8lit("build.sh content:\n"));
+ Str8 file_content = str8_read_entire_file(a, str8lit("build.sh"));
+ str8print(file_content);
+ arena_release(a);
+
+ return(0);
+}
diff --git a/prb.h b/prb.h
new file mode 100644
index 0000000..65f3244
--- /dev/null
+++ b/prb.h
@@ -0,0 +1,26 @@
+#ifndef PRB_H
+#define PRB_H
+
+#include <string.h>
+#include <stdio.h>
+#include <math.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <stdarg.h>
+
+#include "prb_macros.h"
+#include "prb_types.h"
+
+#include "prb_math.h"
+#include "prb_math.c"
+
+#include "prb_memory.h"
+#include "prb_memory.c"
+
+#include "prb_string.h"
+#include "prb_string.c"
+
+#include "prb_os_io.h"
+#include "prb_os_io.c"
+
+#endif /* PRB_H */
diff --git a/prb_macros.h b/prb_macros.h
new file mode 100644
index 0000000..a9a465d
--- /dev/null
+++ b/prb_macros.h
@@ -0,0 +1,61 @@
+#ifndef PRB_MACROS_H
+#define PRB_MACROS_H
+
+#define Assert(e) if (!(e)) { *(int *)0 = 0; }
+
+#define ArrayCount(a) (sizeof(a)/sizeof(*(a)))
+
+#define IntFromPtr(p) (unsigned long long)((char *)(p)-(char *)0)
+#define PtrFromInt(n) (void *)((char *)0+(n))
+
+#define Member(t, m) (((t *)0)->m)
+#define OffsetOfMember(t, m) (IntFromPtr(&Member(t, m)))
+
+#define Min(a, b) (((a) < (b)) ? (a) : (b))
+#define Max(a, b) (((a) > (b)) ? (a) : (b))
+
+#define Clamp(a, x, b) (((x) < (a)) ? (a) : \
+ (((x) > (b)) ? (b) : (x)))
+#define ClampTop(a, b) Min(a, b)
+#define ClampBottom(a, b) Max(a, b)
+
+#define Swap(t, a, b) { t temp = a; a = b; b = temp; }
+
+/* NOTE(pryazha): Memory */
+#define MemoryZero(p, n) memset((p), 0, (n))
+#define MemoryZeroStruct(p) MemoryZero((p), sizeof(*(p)))
+#define MemoryZeroArray(p) MemoryZero((p), sizeof(p))
+
+#define MemoryCopy(d, s, n) memmove((d), (s), (n))
+#define MemoryCopyStruct(d, s) MemoryCopy((d), (s), Min(sizeof(*(d)), sizeof(*(s))))
+#define MemoryCopyArray(d, s) MemoryCopy((d), (s), Min(sizeof(d), sizeof(s)))
+
+#define MemoryMatch(a, b, n) (memcmp((a), (b), (n)) == 0)
+
+#define Kilobytes(n) n*1024
+#define Megabytes(n) Kilobytes(n)*1024
+#define Gigabytes(n) Megabytes(n)*1024
+
+/* NOTE(pryazha): Linked lists */
+#define SLLPush(f, l, n) \
+ ((f) == 0 ? \
+ ((f) = (l) = (n), (n)->next = 0) : \
+ ((l)->next = (n), (l) = (n), (n)->next = 0))
+#define SLLPop(f, l) \
+ ((f) == (l) ? \
+ ((f) = (l) = 0) : \
+ ((f) = (f)->next))
+
+#define DLLPushBack_NP(f, l, n, next, prev) \
+ ((f) == 0 ? \
+ ((f) = (l) = (n), (n)->next = (n)->prev = 0) : \
+ ((n)->prev = (l), (l)->next = (n), (l) = (n), (n)->next = 0))
+#define DLLPushBack(f, l, n) DLLPushBack_NP(f, l, n, next, prev)
+#define DLLPushFront(f, l, n) DLLPushBack_NP(l, f, n, prev, next)
+#define DLLRemove(f, l, n) \
+ ((f) == (n) ? \
+ ((f) == (l) ? (f) = (l) = 0 : ((f) = (f)->next, (f)->prev = 0)) : \
+ ((l) == (n) ? ((l) = (l)->prev, (l)->next = 0) : \
+ ((n)->next->prev = (n)->prev, (n)->prev->next = (n)->next)))
+
+#endif /* PRB_MACROS_H */
diff --git a/prb_math.c b/prb_math.c
new file mode 100644
index 0000000..a2d58bc
--- /dev/null
+++ b/prb_math.c
@@ -0,0 +1,385 @@
+F32 f32sin(F32 a)
+{
+ F32 r = sinf(a);
+ return r;
+}
+
+F32 f32cos(F32 a)
+{
+ F32 r = cosf(a);
+ return r;
+}
+
+F32 f32sqrt(F32 a)
+{
+ F32 r = sqrtf(a);
+ return r;
+}
+
+/* NOTE(pryazha): Vectors */
+V2 v2(F32 x, F32 y)
+{
+ V2 r = { x, y };
+ return r;
+}
+
+V2 v2a(F32 x)
+{
+ V2 r = { x, x };
+ return r;
+}
+
+V2 v2neg(V2 a)
+{
+ V2 r = { -a.x, -a.y };
+ return r;
+}
+
+V2 v2add(V2 a, V2 b)
+{
+ V2 r = { a.x+b.x, a.y+b.y };
+ return r;
+}
+
+V2 v2sub(V2 a, V2 b)
+{
+ V2 r = { a.x-b.x, a.y-b.y };
+ return r;
+}
+
+V2 v2scalef(V2 a, F32 s)
+{
+ V2 r = { a.x*s, a.y*s };
+ return r;
+}
+
+V2 v2scale(V2 a, V2 s)
+{
+ V2 r = { a.x*s.x, a.y*s.y };
+ return r;
+}
+
+F32 v2dot(V2 a, V2 b)
+{
+ F32 r = a.x*b.x+a.y*b.y;
+ return r;
+}
+
+F32 v2len2(V2 a)
+{
+ F32 r = v2dot(a, a);
+ return r;
+}
+
+F32 v2len(V2 a)
+{
+ F32 r = f32sqrt(v2len2(a));
+ return r;
+}
+
+void v2print(V2 a)
+{
+ fprintf(stdout, "{%f, %f}\n", a.x, a.y);
+}
+
+V3 v3(F32 x, F32 y, F32 z)
+{
+ V3 r = { x, y, z };
+ return r;
+}
+
+V3 v3a(F32 x)
+{
+ V3 r = { x, x, x };
+ return r;
+}
+
+V3 v3neg(V3 a)
+{
+ V3 r = { -a.x, -a.y, -a.z };
+ return r;
+}
+
+V3 v3add(V3 a, V3 b)
+{
+ V3 r = { a.x+b.x, a.y+b.y, a.z+b.z };
+ return r;
+}
+
+V3 v3sub(V3 a, V3 b)
+{
+ V3 r = { a.x-b.x, a.y-b.y, a.z-b.z };
+ return r;
+}
+
+V3 v3scalef(V3 a, F32 s)
+{
+ V3 r = { a.x*s, a.y*s, a.z*s };
+ return r;
+}
+
+V3 v3scale(V3 a, V3 s)
+{
+ V3 r = { a.x*s.x, a.y*s.y, a.z*s.z };
+ return r;
+}
+
+F32 v3dot(V3 a, V3 b)
+{
+ F32 r = a.x*b.x+a.y*b.y+a.z*b.z;
+ return r;
+}
+
+V3 v3cross(V3 left, V3 right)
+{
+ V3 r = {
+ (left.y*right.z-right.y*left.z),
+ (right.x*left.z-left.x*right.z),
+ (left.x*right.y-right.x*left.y)
+ };
+ return r;
+}
+
+F32 v3len2(V3 a)
+{
+ F32 r = v3dot(a, a);
+ return r;
+}
+
+F32 v3len(V3 a)
+{
+ F32 r = f32sqrt(v3len2(a));
+ return r;
+}
+
+void v3print(V3 a)
+{
+ fprintf(stdout, "{%f, %f, %f}\n", a.x, a.y, a.z);
+}
+
+V4 v4(F32 x, F32 y, F32 z, F32 w)
+{
+ V4 r = { x, y, z, w };
+ return r;
+}
+
+V4 v4a(F32 x)
+{
+ V4 r = { x, x, x, x };
+ return r;
+}
+
+V4 v4fromv3(V3 a)
+{
+ V4 r = { a.x, a.y, a.z, 0.0f };
+ return r;
+}
+
+V4 v4neg(V4 a)
+{
+ V4 r = { -a.x, -a.y, -a.z, -a.w };
+ return r;
+}
+
+V4 v4add(V4 a, V4 b)
+{
+ V4 r = { a.x+b.x, a.y+b.y, a.z+b.z, a.w+b.w };
+ return r;
+}
+
+V4 v4sub(V4 a, V4 b)
+{
+ V4 r = { a.x-b.x, a.y-b.y, a.z-b.z, a.w-b.w };
+ return r;
+}
+
+V4 v4scalef(V4 a, F32 s)
+{
+ V4 r = { a.x*s, a.y*s, a.z*s, a.w*s };
+ return r;
+}
+
+V4 v4scale(V4 a, V4 s)
+{
+ V4 r = { a.x*s.x, a.y*s.y, a.z*s.z, a.w*s.w };
+ return r;
+}
+
+F32 v4dot(V4 a, V4 b)
+{
+ F32 r = a.x*b.x+a.y*b.y+a.z*b.z+a.w*b.w;
+ return r;
+}
+
+F32 v4len2(V4 a)
+{
+ F32 r = v4dot(a, a);
+ return r;
+}
+
+F32 v4len(V4 a)
+{
+ F32 r = f32sqrt(v4len2(a));
+ return r;
+}
+
+void v4print(V4 a)
+{
+ fprintf(stdout, "{%f, %f, %f, %f}\n", a.x, a.y, a.z, a.w);
+}
+
+/* NOTE(pryazha): Matrices */
+F32 mat4det(Mat4 m)
+{
+ F32 r, m00minor, m01minor, m02minor, m03minor;
+
+ F32 m00 = m.m0.x, m10 = m.m0.y, m20 = m.m0.z, m30 = m.m0.w;
+ F32 m01 = m.m1.x, m11 = m.m1.y, m21 = m.m1.z, m31 = m.m1.w;
+ F32 m02 = m.m2.x, m12 = m.m2.y, m22 = m.m2.z, m32 = m.m2.w;
+ F32 m03 = m.m3.x, m13 = m.m3.y, m23 = m.m3.z, m33 = m.m3.w;
+
+ m00minor = ((m11*m22*m33)+(m12*m23*m31)+(m21*m32*m13)-
+ (m31*m22*m13)-(m21*m12*m33)-(m11*m32*m23));
+
+ m01minor = ((m10*m22*m33)+(m12*m23*m30)+(m20*m32*m13)-
+ (m13*m22*m30)-(m23*m32*m10)-(m12*m20*m33));
+
+ m02minor = ((m10*m21*m33)+(m20*m31*m13)+(m11*m23*m31)-
+ (m13*m21*m30)-(m23*m31*m10)-(m11*m20*m33));
+
+ m03minor = ((m10*m21*m32)+(m20*m31*m12)+(m11*m22*m30)-
+ (m12*m21*m30)-(m11*m20*m32)-(m22*m31*m10));
+
+ r = m00*m00minor+m01*m01minor-m02*m02minor+m03*m03minor;
+
+ return r;
+}
+
+Mat4 mat4transpose(Mat4 m)
+{
+ Mat4 r = m;
+
+ Swap(F32, r.m0.y, r.m1.x);
+ Swap(F32, r.m0.z, r.m2.x);
+ Swap(F32, r.m0.w, r.m3.x);
+
+ Swap(F32, r.m1.z, r.m2.y);
+ Swap(F32, r.m1.w, r.m3.y);
+
+ Swap(F32, r.m2.w, r.m3.z);
+
+ return r;
+}
+
+Mat4 mat4mul(Mat4 left, Mat4 right)
+{
+ F32 l00 = left.m0.x, l01 = left.m0.y, l02 = left.m0.z, l03 = left.m0.w;
+ F32 l10 = left.m1.x, l11 = left.m1.y, l12 = left.m1.z, l13 = left.m1.w;
+ F32 l20 = left.m2.x, l21 = left.m2.y, l22 = left.m2.z, l23 = left.m2.w;
+ F32 l30 = left.m3.x, l31 = left.m3.y, l32 = left.m3.z, l33 = left.m3.w;
+
+ F32 r00 = right.m0.x, r01 = right.m0.y, r02 = right.m0.z, r03 = right.m0.w;
+ F32 r10 = right.m1.x, r11 = right.m1.y, r12 = right.m1.z, r13 = right.m1.w;
+ F32 r20 = right.m2.x, r21 = right.m2.y, r22 = right.m2.z, r23 = right.m2.w;
+ F32 r30 = right.m3.x, r31 = right.m3.y, r32 = right.m3.z, r33 = right.m3.w;
+
+ Mat4 r;
+
+ r.m0.x = l00*r00+l10*r01+l20*r02+l30*r03;
+ r.m0.y = l01*r00+l11*r01+l21*r02+l31*r03;
+ r.m0.z = l02*r00+l12*r01+l22*r02+l32*r03;
+ r.m0.w = l03*r00+l13*r01+l23*r02+l33*r03;
+
+ r.m1.x = l00*r10+l10*r11+l20*r12+l30*r13;
+ r.m1.y = l01*r10+l11*r11+l21*r12+l31*r13;
+ r.m1.z = l02*r10+l12*r11+l22*r12+l32*r13;
+ r.m1.w = l03*r10+l13*r11+l23*r12+l33*r13;
+
+ r.m2.x = l00*r20+l10*r21+l20*r22+l30*r23;
+ r.m2.y = l01*r20+l11*r21+l21*r22+l31*r23;
+ r.m2.z = l02*r20+l12*r21+l22*r22+l32*r23;
+ r.m2.w = l03*r20+l13*r21+l23*r22+l33*r23;
+
+ r.m3.x = l00*r30+l10*r31+l20*r32+l30*r33;
+ r.m3.y = l01*r30+l11*r31+l21*r32+l31*r33;
+ r.m3.z = l02*r30+l12*r31+l22*r32+l32*r33;
+ r.m3.w = l03*r30+l13*r31+l23*r32+l33*r33;
+
+ return r;
+}
+
+Mat4 mat4translate(Mat4 m, V3 v)
+{
+ Mat4 t = MAT4_IDENTITY;
+ t.m3 = v4fromv3(v);
+ Mat4 r = mat4mul(t, m);
+ return r;
+}
+
+Mat4 mat4scale(Mat4 m, V3 v)
+{
+ Mat4 s = MAT4_IDENTITY;
+ s.m0 = v4fromv3(v);
+ Mat4 r = mat4mul(s, m);
+ return r;
+}
+
+Mat4 mat4_change_basis(V3 x, V3 y, V3 z)
+{
+ Mat4 r = MAT4_IDENTITY;
+ r.m0 = v4(x.x, x.y, x.z, 0.0f);
+ r.m1 = v4(y.x, y.y, y.z, 0.0f);
+ r.m2 = v4(z.x, z.y, z.z, 0.0f);
+ return r;
+}
+
+/*
+ * NOTE(pryazha): Angles in degrees
+ * | 1 0 0 | | cy 0 sy | | cz -sz 0 | | cy*cz -cy*sz sy |
+ * | 0 cx -sx |*| 0 1 0 |*| sz cz 0 |=| sx*sy*cz+cx*sz -sx*sy*sz+cx*cz -sx*cy |
+ * | 0 sx cx | | -sy 0 cy | | 0 0 1 | | -cx*sy*cz+sx*sz cx*sy*sz+sx*cz cx*cy |
+ */
+Mat4 mat4rotate(Mat4 m, V3 angles)
+{
+ F32 angle, cx, sx, cy, sy, cz, sz;
+ Mat4 rotate, r;
+ V3 newx, newy, newz;
+
+ angle = DEG2RAD*angles.x;
+ cx = f32cos(angle);
+ sx = f32sin(angle);
+ angle = DEG2RAD*angles.y;
+ cy = f32cos(angle);
+ sy = f32sin(angle);
+ angle = DEG2RAD*angles.z;
+ cz = f32cos(angle);
+ sz = f32sin(angle);
+
+ newx = v3(cy*cz, sx*sy*cz+cx*sz, -cx*sy*cz+sx*sz);
+ newy = v3(-cy*sz, -sx*sy*sz+cx*cz, cx*sy*sz+sx*cz);
+ newz = v3(sy, -sx*cy, cx*cy);
+ rotate = mat4_change_basis(newx, newy, newz);
+
+ r = mat4mul(rotate, m);
+
+ return r;
+}
+
+V4 mat4v4mul(Mat4 m, V4 v)
+{
+ V4 r = {
+ m.m0.x*v.x+m.m1.x*v.y+m.m2.x*v.z+m.m3.x*v.w,
+ m.m0.y*v.x+m.m1.y*v.y+m.m2.y*v.z+m.m3.y*v.w,
+ m.m0.z*v.x+m.m1.z*v.y+m.m2.z*v.z+m.m3.z*v.w,
+ m.m0.w*v.x+m.m1.w*v.y+m.m2.w*v.z+m.m3.w*v.w
+ };
+ return r;
+}
+
+void mat4print(Mat4 m)
+{
+ printf("| %.4f %.4f %.4f %.4f |\n", m.m0.x, m.m1.x, m.m2.x, m.m3.x);
+ printf("| %.4f %.4f %.4f %.4f |\n", m.m0.y, m.m1.y, m.m2.y, m.m3.y);
+ printf("| %.4f %.4f %.4f %.4f |\n", m.m0.z, m.m1.z, m.m2.z, m.m3.z);
+ printf("| %.4f %.4f %.4f %.4f |\n\n", m.m0.w, m.m1.w, m.m2.w, m.m3.w);
+}
diff --git a/prb_math.h b/prb_math.h
new file mode 100644
index 0000000..efa0fab
--- /dev/null
+++ b/prb_math.h
@@ -0,0 +1,64 @@
+#ifndef PRB_MATH_H
+#define PRB_MATH_H
+
+/* NOTE(pryazha): Numeric */
+#define F32_PI 3.14159265359f
+
+#define DEG2RAD F32_PI/180.0f
+#define RAD2DEG 182.0f/F32_PI
+
+F32 f32sin(F32 a);
+F32 f32cos(F32 a);
+F32 f32sqrt(F32 a);
+
+/* NOTE(pryazha): Vectors */
+V2 v2(F32 x, F32 y);
+V2 v2a(F32 x);
+V2 v2neg(V2 a);
+V2 v2add(V2 a, V2 b);
+V2 v2sub(V2 a, V2 b);
+V2 v2scalef(V2 a, F32 s);
+V2 v2scale(V2 a, V2 s);
+F32 v2dot(V2 a, V2 b);
+F32 v2len2(V2 a);
+F32 v2len(V2 a);
+void v2print(V2 a);
+
+V3 v3(F32 x, F32 y, F32 z);
+V3 v3a(F32 x);
+V3 v3neg(V3 a);
+V3 v3add(V3 a, V3 b);
+V3 v3sub(V3 a, V3 b);
+V3 v3scalef(V3 a, F32 s);
+V3 v3scale(V3 a, V3 s);
+F32 v3dot(V3 a, V3 b);
+V3 v3cross(V3 l, V3 r);
+F32 v3len2(V3 a);
+F32 v3len(V3 a);
+void v3print(V3 a);
+
+V4 v4(F32 x, F32 y, F32 z, F32 w);
+V4 v4a(F32 x);
+V4 v4fromv3(V3 a);
+V4 v4neg(V4 a);
+V4 v4add(V4 a, V4 b);
+V4 v4sub(V4 a, V4 b);
+V4 v4scalef(V4 a, F32 s);
+V4 v4scale(V4 a, V4 s);
+F32 v4dot(V4 a, V4 b);
+F32 v4len2(V4 a);
+F32 v4len(V4 a);
+void v4print(V4 a);
+
+/* NOTE(pryazha): Matrices */
+F32 mat4det(Mat4 m);
+Mat4 mat4transpose(Mat4 m);
+Mat4 mat4mul(Mat4 left, Mat4 right);
+Mat4 mat4translate(Mat4 m, V3 v);
+Mat4 mat4scale(Mat4 m, V3 v);
+Mat4 mat4_change_basis(V3 x, V3 y, V3 z);
+Mat4 mat4rotate(Mat4 m, V3 angles); /* NOTE(pryazha): Angles in degrees */
+V4 mat4v4mul(Mat4 m, V4 v);
+void mat4print(Mat4 m);
+
+#endif /* PRB_MATH_H */
diff --git a/prb_memory.c b/prb_memory.c
new file mode 100644
index 0000000..4bceccc
--- /dev/null
+++ b/prb_memory.c
@@ -0,0 +1,42 @@
+Arena *arena_alloc(U64 cap)
+{
+ Arena *arena = 0;
+
+ /* TODO(pryazha): Use OS related memory allocator (like VirtualAlloc on Windows) */
+ arena = malloc(sizeof(Arena));
+ Assert(arena);
+
+ if (!cap)
+ cap = DEFAULT_ALLOC_SIZE;
+
+ arena->mem = malloc(cap);
+ Assert(arena->mem);
+ arena->cap = cap;
+ arena->used = 0;
+
+ return arena;
+}
+
+void arena_release(Arena *arena)
+{
+ free(arena->mem);
+ arena->mem = 0;
+ arena->cap = 0;
+ arena->used = 0;
+ free(arena);
+}
+
+void *arena_push(Arena *arena, U64 size)
+{
+ Assert(arena->used+size <= arena->cap);
+ void *r = arena->mem+arena->used;
+ arena->used += size;
+ return r;
+}
+
+void arena_pop(Arena *arena, U64 amount)
+{
+ Assert(arena);
+ U64 clamped = ClampTop(amount, arena->used);
+ arena->used = arena->used-clamped;
+}
diff --git a/prb_memory.h b/prb_memory.h
new file mode 100644
index 0000000..40a00dc
--- /dev/null
+++ b/prb_memory.h
@@ -0,0 +1,11 @@
+#ifndef PRB_MEMORY_H
+#define PRB_MEMORY_H
+
+#define DEFAULT_ALLOC_SIZE Kilobytes(4)
+
+Arena *arena_alloc(U64 cap);
+void arena_release(Arena *arena);
+void *arena_push(Arena *arena, U64 size);
+void arena_pop(Arena *arena, U64 amount);
+
+#endif /* PRB_MEMORY_H */
diff --git a/prb_os_io.c b/prb_os_io.c
new file mode 100644
index 0000000..d35b73f
--- /dev/null
+++ b/prb_os_io.c
@@ -0,0 +1,31 @@
+Str8 str8_read_entire_file(Arena *arena, Str8 filename)
+{
+ /* TODO(pryazha): Make it crossplatform already */
+ Assert(filename.ptr);
+ Assert(filename.length);
+
+ Str8 result = {0};
+ Arena *tmp = arena_alloc(0);
+
+ char *cfilename = str8_to_cstr(tmp, filename);
+
+ FILE *f = fopen(cfilename, "rb");
+ if (!f)
+ return result;
+
+ fseek(f, 0, SEEK_END);
+ U64 size = ftell(f);
+ rewind(f);
+
+ U8 *mem = arena_push(arena, size+1);
+ fread(mem, size, 1, f);
+ fclose(f);
+
+ mem[size] = 0;
+
+ result = str8(mem, size);
+
+ arena_release(tmp);
+
+ return result;
+}
diff --git a/prb_os_io.h b/prb_os_io.h
new file mode 100644
index 0000000..811778c
--- /dev/null
+++ b/prb_os_io.h
@@ -0,0 +1,6 @@
+#ifndef PRB_OS_IO_H
+#define PRB_OS_IO_H
+
+Str8 str8_read_entire_file(Arena *arena, Str8 filename);
+
+#endif /* PRB_OS_IO_H */
diff --git a/prb_string.c b/prb_string.c
new file mode 100644
index 0000000..061731c
--- /dev/null
+++ b/prb_string.c
@@ -0,0 +1,115 @@
+Str8 str8(U8 *ptr, U64 length)
+{
+ Assert(ptr);
+ Str8 r = { ptr, length };
+ return r;
+}
+
+Str8 str8_range(U8 *start, U8 *end)
+{
+ Str8 r = { start, end-start };
+ return r;
+}
+
+Str8 str8_from_cstr(char *cstr)
+{
+ U8 *ptr = (U8 *)cstr;
+ for (; *ptr; ++ptr);
+ Str8 r = str8_range((U8 *)cstr, ptr);
+ return r;
+}
+
+char *str8_to_cstr(Arena *arena, Str8 s)
+{
+ U64 length = s.length+1;
+ char *r = arena_push(arena, length*sizeof(U8));
+ MemoryCopy(r, s.ptr, length*sizeof(U8));
+ *(r+s.length) = 0;
+ return r;
+}
+
+Str8 str8_chop_end(Str8 s, U64 count)
+{
+ U64 length = s.length-ClampTop(count, s.length);
+ Str8 r = str8(s.ptr, length);
+ return r;
+}
+
+Str8 str8_chop_start(Str8 s, U64 count)
+{
+ U64 clamped = ClampTop(count, s.length);
+ U64 length = s.length-ClampTop(count, s.length);
+ Str8 r = str8(s.ptr+clamped, length);
+ return r;
+}
+
+Str8 str8_pushfv(Arena *arena, char *fmt, va_list args)
+{
+ Str8 r = {0};
+
+ va_list args2;
+ va_copy(args2, args);
+
+ U32 buf_size = 1024;
+ U8 *buf = arena_push(arena, buf_size);
+
+ S32 n = vsnprintf((char *)buf, buf_size, fmt, args);
+ va_end(args2);
+
+ if (n > 0)
+ r = str8(buf, n);
+
+ return r;
+}
+
+Str8 str8_pushf(Arena *arena, char *fmt, ...)
+{
+ va_list args;
+ va_start(args, fmt);
+ Str8 r = str8_pushfv(arena, fmt, args);
+ va_end(args);
+ return r;
+}
+
+void str8print(Str8 s)
+{
+ for (U64 i = 0; i < s.length; ++i)
+ printf("%c", (char)(*(s.ptr+i)));
+}
+
+Str8List *str8_list(Arena *arena)
+{
+ Str8List *list = arena_push(arena, sizeof(Str8List));
+ MemoryZero(list, sizeof(Str8List));
+ return list;
+}
+
+void str8_list_push(Arena *arena, Str8List *list, Str8 str, B32 to_front)
+{
+ Assert(arena && list);
+ Str8Node *n = arena_push(arena, sizeof(Str8Node));
+ n->str = str;
+ if (to_front)
+ DLLPushFront(list->first, list->last, n);
+ else
+ DLLPushBack(list->first, list->last, n);
+ list->total_length += str.length;
+ list->node_count++;
+}
+
+void str8_list_pushf(Arena *arena, Str8List *list, B32 to_front, char *fmt, ...)
+{
+ va_list args;
+ va_start(args, fmt);
+ Str8 str = str8_pushfv(arena, fmt, args);
+ va_end(args);
+ str8_list_push(arena, list, str, to_front);
+}
+
+void str8_list_print(Str8List *list)
+{
+ for (Str8Node *n = list->first; n; n = n->next) {
+ str8print(n->str);
+ printf("%s", (n->next) ? " -> " : "\n");
+ }
+}
diff --git a/prb_string.h b/prb_string.h
new file mode 100644
index 0000000..85496cb
--- /dev/null
+++ b/prb_string.h
@@ -0,0 +1,22 @@
+#ifndef PRB_STRING_H
+#define PRB_STRING_H
+
+#define str8lit(s) str8((U8 *)(s), sizeof(s)-1)
+#define str8expand(s) (int)((s).length), ((s).ptr)
+
+Str8 str8(U8 *ptr, U64 length);
+Str8 str8_range(U8 *start, U8 *end);
+Str8 str8_from_cstr(char *cstr);
+char *str8_to_cstr(Arena *arena, Str8 s);
+Str8 str8_chop_end(Str8 s, U64 count);
+Str8 str8_chop_start(Str8 s, U64 count);
+Str8 str8_pushfv(Arena *arena, char *fmt, va_list args);
+Str8 str8_pushf(Arena *arena, char *fmt, ...);
+void str8print(Str8 s);
+
+Str8List *str8_list(Arena *arena);
+void str8_list_push(Arena *arena, Str8List *list, Str8 str, B32 to_front);
+void str8_list_pushf(Arena *arena, Str8List *list, B32 to_front, char *fmt, ...);
+void str8_list_print(Str8List *list);
+
+#endif /* PRB_STRING_H */
diff --git a/prb_types.h b/prb_types.h
new file mode 100644
index 0000000..a1ac3ba
--- /dev/null
+++ b/prb_types.h
@@ -0,0 +1,84 @@
+#ifndef PRB_TYPES_H
+#define PRB_TYPES_H
+
+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;
+typedef S32 B32;
+typedef float F32;
+typedef double F64;
+
+/* NOTE(pryazha): The library uses a right-handed coordiante system (for now) */
+
+typedef struct {
+ F32 x, y;
+} V2;
+
+#define V2_ZERO (V2){ 0.0f, 0.0f }
+#define V2_ONE (V2){ 1.0f, 1.0f }
+#define V2_RIGHT (V2){ 1.0f, 0.0f }
+#define V2_UP (V2){ 0.0f, 1.0f }
+#define V2_LEFT (V2){-1.0f, 0.0f }
+#define V2_DOWN (V2){ 0.0f, -1.0f }
+
+typedef struct {
+ F32 x, y, z;
+} V3;
+
+#define V3_ZERO (V3){ 0.0f, 0.0f, 0.0f }
+#define V3_ONE (V3){ 1.0f, 1.0f, 1.0f }
+#define V3_RIGHT (V3){ 1.0f, 0.0f, 0.0f }
+#define V3_UP (V3){ 0.0f, 1.0f, 0.0f }
+#define V3_LEFT (V3){-1.0f, 0.0f, 0.0f }
+#define V3_DOWN (V3){ 0.0f, -1.0f, 0.0f }
+#define V3_FORWARD (V3){ 0.0f, 0.0f, 1.0f }
+#define V3_BACKWARD (V3){ 0.0f, 0.0f, -1.0f }
+
+typedef struct {
+ F32 x, y, z, w;
+} V4;
+
+#define V4_ZERO (V4){ 0.0f, 0.0f, 0.0f, 0.0f }
+#define V4_ONE (V4){ 1.0f, 1.0f, 1.0f, 1.0f }
+
+typedef struct {
+ V4 m0, m1, m2, m3;
+} Mat4;
+
+#define MAT4_IDENTITY (Mat4) { \
+ { 1.0f, 0.0f, 0.0f, 0.0f }, \
+ { 0.0f, 1.0f, 0.0f, 0.0f }, \
+ { 0.0f, 0.0f, 1.0f, 0.0f }, \
+ { 0.0f, 0.0f, 0.0f, 1.0f } }
+
+typedef struct {
+ U8 *mem;
+ U64 cap;
+ U64 used;
+} Arena;
+
+/* NOTE(pryazha): Strings */
+typedef struct {
+ U8 *ptr;
+ U64 length;
+} Str8;
+
+typedef struct Str8Node {
+ Str8 str;
+ struct Str8Node *next;
+ struct Str8Node *prev;
+} Str8Node;
+
+typedef struct {
+ Str8Node *first;
+ Str8Node *last;
+ U64 total_length;
+ U32 node_count;
+} Str8List;
+
+#endif /* PRB_TYPES_H */