This commit is contained in:
Abdulmujeeb Raji 2025-01-29 15:23:13 +00:00
parent 515c1200a7
commit 71bf582ba6
Signed by: midnadimple
GPG key ID: EB02C582F8C3962B
7 changed files with 159 additions and 61 deletions

View file

@ -27,7 +27,8 @@ of making the region of memory allocated to more explicit.
operations are included by default. operations are included by default.
- [x] Generic data-structures. The premier one is the - [x] Generic data-structures. The premier one is the
[Dynamic Array](https://dylanfalconer.com/articles/dynamic-arrays-in-c), which [Dynamic Array](https://dylanfalconer.com/articles/dynamic-arrays-in-c), which
brings the power of C++'s `std::vector` to C. brings the power of C++'s `std::vector` to C. There is also a HashMap, which is
implemented as a [4-ary hash-trie](https://nullprogram.com/blog/2023/09/30/).
- [x] A I/O system that supports both standard input/output and file - [x] A I/O system that supports both standard input/output and file
input/output. It's built on a basic buffer type that you can flush to output input/output. It's built on a basic buffer type that you can flush to output
data. This buffer type also acts as a **string builder**, by letting you append data. This buffer type also acts as a **string builder**, by letting you append
@ -38,6 +39,7 @@ primitives.
- [ ] A 3D Math API with supports for Vectors and Matricies using SIMD. - [ ] A 3D Math API with supports for Vectors and Matricies using SIMD.
- [ ] A simple GUI initialization system that gets you a window with immediate-mode - [ ] A simple GUI initialization system that gets you a window with immediate-mode
input and a Direct3D11 (Win32) / OpenGL (Linux) context to build a renderer with. input and a Direct3D11 (Win32) / OpenGL (Linux) context to build a renderer with.
- [ ] A simple immediate mode GUI with support for custom widgets.
- [ ] An audio library. Windows implementation uses WASAPI, Linux uses ALSA. - [ ] An audio library. Windows implementation uses WASAPI, Linux uses ALSA.
--- ---

View file

@ -0,0 +1,89 @@
#define BASTD_CLI
#include "../../bastd.c"
/* The sl_TYPE macro defines the type of the generic. It is cleared after every
include of "../slice.c"
*/
#define sl_TYPE I64
#include "../slice.c"
// SLICE types
FUNCTION void
fib_slice(Buffer *output, m_Allocator *perm)
{
// Slices can be created with a backing array to start with.
I64 init[] = {0, 1};
sl_I64 fib = sl_I64_create(init, 2);
for (;;) {
// The data in a slice can be accessed like a normal array
I64 a = fib.elems[fib.len - 2];
I64 b = fib.elems[fib.len - 1];
if (a + b > 255) {
break;
}
/* The sl_TYPE_push function automatically doubles the capacity of the
array if the slice is full and returns a pointer to a new element
*/
*sl_I64_push(&fib, perm) = a + b;
}
for (int i = 0; i < fib.len; i++) {
Buffer_appendI64(output, fib.elems[i]);
Buffer_appendU8(output, '\n');
}
Buffer_standardOutput(output);
}
/* These generic structures may have more than one required macro */
#define hm_KEY_TYPE S8
#define hm_KEY_HASHPROC S8_hash_prime19
#define hm_KEY_EQUALSPROC S8_equal
#define hm_VAL_TYPE U64
#include "../hashmap.c" // will define hm_S8_U64
// HASHMAPS
FUNCTION void
citypopulus_hashmap(Buffer *output, m_Allocator *perm)
{
// We always store a hashmap pointer, NOT the actual hashmap
hm_S8_U64 *database = hm_EMPTY;
*hm_S8_U64_upsert(&database, S8("London"), perm) = 8800000;
*hm_S8_U64_upsert(&database, S8("Lahore"), perm) = 13000000;
*hm_S8_U64_upsert(&database, S8("Dhaka"), perm) = 21280000;
*hm_S8_U64_upsert(&database, S8("Washington D.C."), perm) = 679000;
*hm_S8_U64_upsert(&database, S8("Taxila"), perm) = 739000;
// Can't iterate through hashmap, but in exchange, accessing values is fast
// NOTE: passing no allocator implies that you should NOT insert a value if it doesnt exist
U64 dc_population = *hm_S8_U64_upsert(&database, S8("Washington D.C."), NIL);
U64 lahore_population = *hm_S8_U64_upsert(&database, S8("Lahore"), NIL);
U64 london_population = *hm_S8_U64_upsert(&database, S8("London"), NIL);
Buffer_appendI64(output, dc_population);
Buffer_appendU8(output, '\n');
Buffer_appendI64(output, lahore_population);
Buffer_appendU8(output, '\n');
Buffer_appendI64(output, london_population);
Buffer_appendU8(output, '\n');
Buffer_standardOutput(output);
}
CALLBACK_EXPORT os_ErrorCode
os_entry(void)
{
m_Buddy buddy = m_Buddy_create(os_alloc(MEGA(2)), MEGA(2));
m_Allocator perm = m_BUDDY_ALLOCATOR(buddy);
Buffer output = BUFFER(m_MAKE(U8, KILO(2), &perm), KILO(2));
fib_slice(&output, &perm);
citypopulus_hashmap(&output, &perm);
return os_ErrorCode_success;
}

View file

@ -1,59 +0,0 @@
#define BASTD_CLI
#include "../../bastd.c"
/* The sl_TYPE macro defines the type of the generic. It is cleared after every
include of "../slice.c"
*/
#define sl_TYPE I64
#include "../slice.c"
CALLBACK_EXPORT os_ErrorCode
os_entry(void)
{
m_Buddy buddy = m_Buddy_create(os_alloc(MEGA(2)), MEGA(2));
m_Allocator perm = m_BUDDY_ALLOCATOR(buddy);
// Slices can be created with a backing array to start with.
I64 init[] = {0, 1};
sl_I64 fib = sl_I64_create(init, 2);
for (;;) {
// The data in a slice can be accessed like a normal array
I64 a = fib.elems[fib.len - 2];
I64 b = fib.elems[fib.len - 1];
if (a + b > 255) {
break;
}
/* The sl_TYPE_push function automatically doubles the capacity of the
array if the slice is full and returns a pointer to a new element
*/
*sl_I64_push(&fib, &perm) = a + b;
}
Buffer output = BUFFER(m_MAKE(U8, KILO(2), &perm), KILO(2));
for (int i = 0; i < fib.len; i++) {
Buffer_appendI64(&output, fib.elems[i]);
Buffer_appendU8(&output, '\n');
}
Buffer_standardOutput(&output);
// Wait for you to press enter
Buffer_appendS8(&output, S8("I've got a message for you. Press Enter to see it: "));
Buffer_standardOutput(&output);
Buffer_appendStandardInput(&output, 1024, &perm);
sl_S8 msgs = sl_S8_create(NIL, 0);
*sl_S8_push(&msgs, &perm) = S8("C standard library!");
*sl_S8_push(&msgs, &perm) = S8("a Bravely Arranged ");
*sl_S8_push(&msgs, &perm) = S8("This is ");
*sl_S8_push(&msgs, &perm) = S8("World! ");
*sl_S8_push(&msgs, &perm) = S8("Hello, ");
for (; msgs.len > 0;) {
Buffer_appendS8(&output, sl_S8_pop(&msgs));
}
Buffer_standardOutput(&output);
return os_ErrorCode_success;
}

53
bastd/hashmap.c Normal file
View file

@ -0,0 +1,53 @@
// GENERIC FILE, REDEFINED EVERY INCLUDE
#ifndef hm_KEY_TYPE
#error "No hm_KEY_TYPE given"
#endif
// hm_KEY_HASHPROC need signature "U64 procname(hm_KEY_TYPE)"
#ifndef hm_KEY_HASHPROC
#error "No hm_KEY_HASHPROC given"
#endif
#ifndef hm_KEY_EQUALSPROC
#error "No hm_KEY_EQUALSPROC given"
#endif
#ifndef hm_VAL_TYPE
#error "No hm_VAL_TYPE given"
#endif
#define hm_NAME CONCAT(CONCAT(hm_, hm_KEY_TYPE), CONCAT(_, hm_VAL_TYPE))
typedef struct hm_NAME hm_NAME;
struct hm_NAME {
hm_NAME *child[4];
hm_KEY_TYPE key;
hm_VAL_TYPE val;
};
// always store a pointer to the hashmap, not the actual value
#define hm_EMPTY NIL
FUNCTION hm_VAL_TYPE *
CONCAT(hm_NAME, _upsert) (hm_NAME **m, hm_KEY_TYPE key, m_Allocator *perm)
{
for (U64 h = hm_KEY_HASHPROC(key); *m; h <<= 2) {
if (hm_KEY_EQUALSPROC(key, (*m)->key)) {
return &(*m)->val;
}
m = &(*m)->child[h>>62];
}
if (perm == NIL) {
// just searching, dont insert a new value
return NIL;
}
*m = m_MAKE(hm_NAME, 1, perm);
(*m)->key = key;
return &(*m)->val;
}
#undef hm_NAME
#undef hm_VAL_TYPE
#undef hm_KEY_EQUALSPROC
#undef hm_KEY_HASHPROC
#undef hm_KEY_TYPE

View file

@ -352,6 +352,7 @@ m_Buddy_alloc(void *ctx, void *ptr, U64 old_size, U64 new_size) {
if (found != NIL) { if (found != NIL) {
found->is_free = FALSE; found->is_free = FALSE;
U8 *p = (U8 *)found + b->alignment; U8 *p = (U8 *)found + b->alignment;
m_memorySet(p, 0, new_size);
if (ptr != NIL) { if (ptr != NIL) {
m_memoryCopy(p, ptr, old_size); m_memoryCopy(p, ptr, old_size);
} }

View file

@ -203,4 +203,16 @@ S8_join(sl_S8 s, S8 join, m_Allocator *perm) {
return (S8){total_length, mem}; return (S8){total_length, mem};
} }
// Should probably get a better hashing func, but oh well
FUNCTION U64
S8_hash_prime19(S8 s)
{
U64 h = 0x100;
for (U64 i = 0; i < s.len; i++) {
h ^= s.raw[i];
h *= 1111111111111111111u;
}
return h;
}
#endif//BASTD_STRING_C #endif//BASTD_STRING_C

View file

@ -7,7 +7,7 @@ set debugflags=/nologo /W3 /MTd /Od /Zi /RTC1 /fsanitize=address /link /incremen
REM Uncomment one of these to run an example. Try it! They're great documentation. REM Uncomment one of these to run an example. Try it! They're great documentation.
REM cl ..\bastd\examples\memory.c %debugflags% REM cl ..\bastd\examples\memory.c %debugflags%
REM cl ..\bastd\examples\fib_slice.c %debugflags% REM cl ..\bastd\examples\data_structs.c %debugflags%
REM cl ..\bastd\examples\string.c %debugflags% REM cl ..\bastd\examples\string.c %debugflags%
REM cl ..\bastd\examples\buffer.c %debugflags% REM cl ..\bastd\examples\buffer.c %debugflags%
REM cl ..\bastd\examples\job_random.c %debugflags% REM cl ..\bastd\examples\job_random.c %debugflags%