Recreate base64 project
This commit is contained in:
commit
e90d14344e
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
||||
b64
|
3
README.md
Normal file
3
README.md
Normal file
@ -0,0 +1,3 @@
|
||||
# C testing projects
|
||||
|
||||
Recreating the projects from [intro-to-zig](https://git.thewizardapprentice.com/abdelrahman/intro-to-zig) in C
|
140
base64/base64.c
Normal file
140
base64/base64.c
Normal file
@ -0,0 +1,140 @@
|
||||
// vim:fileencoding=utf-8:foldmethod=marker
|
||||
|
||||
#include "base64.h"
|
||||
#include "../wapp/wapp.h"
|
||||
#include <math.h>
|
||||
|
||||
internal Str8RO alphabet = wapp_str8_lit_ro("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/");
|
||||
|
||||
internal c8 char_at(u8 index);
|
||||
internal u8 char_index(c8 c);
|
||||
internal u64 calc_encode_length(Str8RO *input);
|
||||
internal u64 calc_decode_length(Str8RO *input);
|
||||
|
||||
Str8 *encode(Allocator *allocator, Str8RO *input) {
|
||||
if (input->size == 0) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
u64 n_out = calc_encode_length(input);
|
||||
Str8 *out = wapp_str8_alloc_and_fill_buf(allocator, n_out);
|
||||
if (!out) return NULL;
|
||||
|
||||
u8 buf[3] = {0};
|
||||
u8 count = 0;
|
||||
u64 iout = 0;
|
||||
|
||||
|
||||
for (u64 i = 0; i < input->size; ++i) {
|
||||
buf[count] = wapp_str8_get(input, i);
|
||||
count += 1;
|
||||
if (count == 3) {
|
||||
wapp_str8_set(out, iout, char_at(buf[0] >> 2));
|
||||
wapp_str8_set(out, iout + 1, char_at(((buf[0] & 0x03) << 4) + (buf[1] >> 4)));
|
||||
wapp_str8_set(out, iout + 2, char_at(((buf[1] & 0x0f) << 2) + (buf[2] >> 6)));
|
||||
wapp_str8_set(out, iout + 3, char_at(buf[2] & 0x3f));
|
||||
|
||||
iout += 4;
|
||||
count = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (count == 1) {
|
||||
wapp_str8_set(out, iout, char_at(buf[0] >> 2));
|
||||
wapp_str8_set(out, iout + 1, char_at((buf[0] & 0x03) << 4));
|
||||
wapp_str8_set(out, iout + 2, '=');
|
||||
wapp_str8_set(out, iout + 3, '=');
|
||||
}
|
||||
|
||||
if (count == 2) {
|
||||
wapp_str8_set(out, iout, char_at(buf[0] >> 2));
|
||||
wapp_str8_set(out, iout + 1, char_at(((buf[0] & 0x03) << 4) + (buf[1] >> 4)));
|
||||
wapp_str8_set(out, iout + 2, char_at((buf[1] & 0x0f) << 2));
|
||||
wapp_str8_set(out, iout + 3, '=');
|
||||
|
||||
iout += 4;
|
||||
}
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
Str8 *decode(Allocator *allocator, Str8RO *input) {
|
||||
if (input->size == 0) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
u64 n_out = calc_decode_length(input);
|
||||
Str8 *out = wapp_str8_alloc_and_fill_buf(allocator, n_out);
|
||||
if (!out) return NULL;
|
||||
|
||||
u8 buf[4] = {0};
|
||||
u8 count = 0;
|
||||
u64 iout = 0;
|
||||
|
||||
for (u64 i = 0; i < input->size; ++i) {
|
||||
buf[count] = char_index(wapp_str8_get(input, i));
|
||||
count += 1;
|
||||
if (count == 4) {
|
||||
wapp_str8_set(out, iout, (buf[0] << 2) + (buf[1] >> 4));
|
||||
if (buf[2] != 64) {
|
||||
wapp_str8_set(out, iout + 1, (buf[1] << 4) + (buf[2] >> 2));
|
||||
}
|
||||
if (buf[3] != 64) {
|
||||
wapp_str8_set(out, iout + 2, (buf[2] << 6) + buf[3]);
|
||||
}
|
||||
|
||||
iout += 3;
|
||||
count = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
internal c8 char_at(u8 index) {
|
||||
return wapp_str8_get(&alphabet, index);
|
||||
}
|
||||
|
||||
internal u8 char_index(c8 c) {
|
||||
if (c == '=') {
|
||||
return 64;
|
||||
}
|
||||
|
||||
u8 index = 0;
|
||||
for (u8 i = 0; i < 63; ++i) {
|
||||
if (char_at(i) == c) {
|
||||
break;
|
||||
}
|
||||
index += 1;
|
||||
}
|
||||
|
||||
return index;
|
||||
}
|
||||
|
||||
internal u64 calc_encode_length(Str8RO *input) {
|
||||
if (input->size < 3) {
|
||||
return 4;
|
||||
}
|
||||
|
||||
u64 n_groups = (u64)(ceilf((f32)input->size / 3.0f));
|
||||
|
||||
return n_groups * 4;
|
||||
}
|
||||
|
||||
internal u64 calc_decode_length(Str8RO *input) {
|
||||
if (input->size < 4) {
|
||||
return 3;
|
||||
}
|
||||
|
||||
u64 n_groups = (u64)(floorf((f32)input->size / 4.0f));
|
||||
|
||||
u64 groups = n_groups * 3;
|
||||
|
||||
for (u64 i = input->size; i > 0; --i) {
|
||||
if (wapp_str8_get(input, i) == '=') {
|
||||
groups -= 1;
|
||||
}
|
||||
}
|
||||
|
||||
return groups;
|
||||
}
|
11
base64/base64.h
Normal file
11
base64/base64.h
Normal file
@ -0,0 +1,11 @@
|
||||
// vim:fileencoding=utf-8:foldmethod=marker
|
||||
|
||||
#ifndef BASE64_H
|
||||
#define BASE64_H
|
||||
|
||||
#include "../wapp/wapp.h"
|
||||
|
||||
Str8 *encode(Allocator *allocator, Str8RO *input);
|
||||
Str8 *decode(Allocator *allocator, Str8RO *input);
|
||||
|
||||
#endif // !BASE64_H
|
5
base64/build
Executable file
5
base64/build
Executable file
@ -0,0 +1,5 @@
|
||||
#!/bin/bash
|
||||
|
||||
script_dir="$(dirname $0)"
|
||||
|
||||
clang $script_dir/*.c $script_dir/../wapp/wapp.c -lm -o b64
|
23
base64/main.c
Normal file
23
base64/main.c
Normal file
@ -0,0 +1,23 @@
|
||||
// vim:fileencoding=utf-8:foldmethod=marker
|
||||
|
||||
#include "base64.h"
|
||||
#include "../wapp/wapp.h"
|
||||
#include <stdio.h>
|
||||
|
||||
int main(void) {
|
||||
Allocator allocator = wapp_mem_arena_allocator_init(MB(10));
|
||||
|
||||
Str8RO text = wapp_str8_lit_ro("Testing some more stuff");
|
||||
Str8RO etext = wapp_str8_lit_ro("VGVzdGluZyBzb21lIG1vcmUgc3R1ZmY=");
|
||||
|
||||
Str8 *encoded_text = encode(&allocator, &text);
|
||||
Str8 *decoded_text = decode(&allocator, &etext);
|
||||
wapp_runtime_assert(encoded_text != NULL && decoded_text != NULL, "Failed to allocate strings");
|
||||
|
||||
printf("Encoded text: " WAPP_STR8_SPEC "\n", wapp_str8_varg(*encoded_text));
|
||||
printf("Decoded text: " WAPP_STR8_SPEC "\n", wapp_str8_varg(*decoded_text));
|
||||
|
||||
wapp_mem_arena_allocator_destroy(&allocator);
|
||||
|
||||
return 0;
|
||||
}
|
67
wapp/common/aliases/aliases.h
Normal file
67
wapp/common/aliases/aliases.h
Normal file
@ -0,0 +1,67 @@
|
||||
// vim:fileencoding=utf-8:foldmethod=marker
|
||||
|
||||
#ifndef ALIASES_H
|
||||
#define ALIASES_H
|
||||
|
||||
#include "../platform/platform.h"
|
||||
#include <stdint.h>
|
||||
|
||||
#if WAPP_PLATFORM_C_VERSION >= WAPP_PLATFORM_C11_VERSION && !defined(WAPP_PLATFORM_APPLE)
|
||||
#include <uchar.h>
|
||||
|
||||
#if WAPP_PLATFORM_C_VERSION >= WAPP_PLATFORM_C23_VERSION
|
||||
#define c8 char8_t
|
||||
#else
|
||||
#define c8 uint8_t
|
||||
#endif // !WAPP_PLATFORM_C23_VERSION
|
||||
|
||||
#define c16 char16_t
|
||||
#define c32 char32_t
|
||||
#else
|
||||
#define c8 uint8_t
|
||||
#define c16 uint16_t
|
||||
#define c32 uint32_t
|
||||
#endif // !WAPP_PLATFORM_C11_VERSION
|
||||
|
||||
#define u8 uint8_t
|
||||
#define u16 uint16_t
|
||||
#define u32 uint32_t
|
||||
#define u64 uint64_t
|
||||
|
||||
#define b32 uint32_t
|
||||
|
||||
#ifndef WAPP_PLATFORM_CPP
|
||||
|
||||
#ifndef false
|
||||
#define false (b32)0
|
||||
#endif // !false
|
||||
|
||||
#ifndef true
|
||||
#define true (b32)1
|
||||
#endif // !true
|
||||
|
||||
#endif // !WAPP_PLATFORM_CPP
|
||||
|
||||
#define i8 int8_t
|
||||
#define i16 int16_t
|
||||
#define i32 int32_t
|
||||
#define i64 int64_t
|
||||
|
||||
#define f32 float
|
||||
#define f64 double
|
||||
#define f128 long double
|
||||
|
||||
#define uptr uintptr_t
|
||||
#define iptr intptr_t
|
||||
|
||||
#define external extern
|
||||
#define internal static
|
||||
#define persistent static
|
||||
|
||||
#ifdef WAPP_PLATFORM_CPP
|
||||
#define class_mem static
|
||||
#define BEGIN_C_LINKAGE extern "C" {
|
||||
#define END_C_LINKAGE }
|
||||
#endif // WAPP_PLATFORM_CPP
|
||||
|
||||
#endif // !ALIASES_H
|
41
wapp/common/assert/assert.h
Normal file
41
wapp/common/assert/assert.h
Normal file
@ -0,0 +1,41 @@
|
||||
// vim:fileencoding=utf-8:foldmethod=marker
|
||||
|
||||
#ifndef WAPP_ASSERT_H
|
||||
#define WAPP_ASSERT_H
|
||||
|
||||
#include "../aliases/aliases.h"
|
||||
#include "../platform/platform.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <inttypes.h>
|
||||
|
||||
#ifdef WAPP_PLATFORM_CPP
|
||||
BEGIN_C_LINKAGE
|
||||
#endif // !WAPP_PLATFORM_CPP
|
||||
|
||||
#define wapp_static_assert(EXPR, MSG) extern char ASSERTION_FAILED[EXPR ? 1 : -1]
|
||||
#define wapp_runtime_assert(EXPR, MSG) __wapp_runtime_assert(EXPR, MSG)
|
||||
|
||||
#ifdef WAPP_DEBUG_ASSERT
|
||||
#define wapp_debug_assert(EXPR, MSG) wapp_runtime_assert(EXPR, MSG)
|
||||
#else
|
||||
#define wapp_debug_assert(EXPR, MSG)
|
||||
#endif
|
||||
|
||||
#define __wapp_runtime_assert(EXPR, MSG) do { \
|
||||
if (!(EXPR)) { \
|
||||
fprintf( \
|
||||
stderr, \
|
||||
"%s:%d (In function `%s`): Assertion failed (%" PRIu32 ")\nDiagnostic: %s\n\n", \
|
||||
__FILE__, __LINE__, __func__, \
|
||||
EXPR, MSG \
|
||||
); \
|
||||
abort(); \
|
||||
} \
|
||||
} while(false)
|
||||
|
||||
#ifdef WAPP_PLATFORM_CPP
|
||||
END_C_LINKAGE
|
||||
#endif // !WAPP_PLATFORM_CPP
|
||||
|
||||
#endif // !WAPP_ASSERT_H
|
56
wapp/common/misc/misc_utils.h
Normal file
56
wapp/common/misc/misc_utils.h
Normal file
@ -0,0 +1,56 @@
|
||||
// vim:fileencoding=utf-8:foldmethod=marker
|
||||
|
||||
#ifndef MISC_UTILS_H
|
||||
#define MISC_UTILS_H
|
||||
|
||||
#include "../aliases/aliases.h"
|
||||
|
||||
#ifdef WAPP_PLATFORM_CPP
|
||||
BEGIN_C_LINKAGE
|
||||
#endif // !WAPP_PLATFORM_CPP
|
||||
|
||||
#define KB(SIZE) (SIZE * 1024ull)
|
||||
#define MB(SIZE) (KB(SIZE) * 1024)
|
||||
#define GB(SIZE) (MB(SIZE) * 1024)
|
||||
#define TB(SIZE) (GB(SIZE) * 1024)
|
||||
|
||||
#define wapp_misc_utils_padding_size(SIZE) u8 reserved_padding[sizeof(void *) - ((SIZE) % sizeof(void *))]
|
||||
|
||||
#define U64_RSHIFT_OR_1(X) (((u64)X) | (((u64)X) >> 1))
|
||||
#define U64_RSHIFT_OR_2(X) (((u64)X) | (((u64)X) >> 2))
|
||||
#define U64_RSHIFT_OR_4(X) (((u64)X) | (((u64)X) >> 4))
|
||||
#define U64_RSHIFT_OR_8(X) (((u64)X) | (((u64)X) >> 8))
|
||||
#define U64_RSHIFT_OR_16(X) (((u64)X) | (((u64)X) >> 16))
|
||||
#define U64_RSHIFT_OR_32(X) (((u64)X) | (((u64)X) >> 32))
|
||||
#define wapp_misc_utils_u64_round_up_pow2(X) ( \
|
||||
( \
|
||||
U64_RSHIFT_OR_32( \
|
||||
U64_RSHIFT_OR_16( \
|
||||
U64_RSHIFT_OR_8( \
|
||||
U64_RSHIFT_OR_4( \
|
||||
U64_RSHIFT_OR_2( \
|
||||
U64_RSHIFT_OR_1(X - 1) \
|
||||
) \
|
||||
) \
|
||||
) \
|
||||
) \
|
||||
) \
|
||||
) + 1 \
|
||||
)
|
||||
|
||||
#ifdef WAPP_PLATFORM_CPP
|
||||
#define wapp_misc_utils_va_args_count(T, ...) va_args_count<T>(__VA_ARGS__)
|
||||
#else
|
||||
#define wapp_misc_utils_va_args_count(T, ...) (sizeof((T[]){__VA_ARGS__})/sizeof(T))
|
||||
#endif // !WAPP_PLATFORM_CPP
|
||||
|
||||
#ifdef WAPP_PLATFORM_CPP
|
||||
END_C_LINKAGE
|
||||
|
||||
template <typename T, typename... Args>
|
||||
constexpr u64 va_args_count(Args&&...) {
|
||||
return sizeof...(Args);
|
||||
}
|
||||
#endif // !WAPP_PLATFORM_CPP
|
||||
|
||||
#endif // !MISC_UTILS_H
|
114
wapp/common/platform/platform.h
Normal file
114
wapp/common/platform/platform.h
Normal file
@ -0,0 +1,114 @@
|
||||
// vim:fileencoding=utf-8:foldmethod=marker
|
||||
|
||||
#ifndef PLATFORM_H
|
||||
#define PLATFORM_H
|
||||
|
||||
#if defined(__ANDROID__)
|
||||
#define WAPP_PLATFORM_ANDROID
|
||||
#define WAPP_PLATFORM_POSIX
|
||||
#elif defined(__FreeBSD__)
|
||||
#define WAPP_PLATFORM_FREE_BSD
|
||||
#define WAPP_PLATFORM_BSD
|
||||
#define WAPP_PLATFORM_POSIX
|
||||
#elif defined(__NetBSD__)
|
||||
#define WAPP_PLATFORM_NET_BSD
|
||||
#define WAPP_PLATFORM_BSD
|
||||
#define WAPP_PLATFORM_POSIX
|
||||
#elif defined(__OpenBSD__)
|
||||
#define WAPP_PLATFORM_OPEN_BSD
|
||||
#define WAPP_PLATFORM_BSD
|
||||
#define WAPP_PLATFORM_POSIX
|
||||
#elif defined(__DragonFly__)
|
||||
#define WAPP_PLATFORM_DRAGON_FLY
|
||||
#define WAPP_PLATFORM_BSD
|
||||
#define WAPP_PLATFORM_POSIX
|
||||
#elif defined(__bsdi__)
|
||||
#define WAPP_PLATFORM_BSD
|
||||
#define WAPP_PLATFORM_POSIX
|
||||
#elif defined(__linux__) || defined(linux) || defined(__linux) || defined(__gnu_linux__)
|
||||
#define WAPP_PLATFORM_LINUX
|
||||
#define WAPP_PLATFORM_POSIX
|
||||
#elif defined(__GNU__) || defined(__gnu_hurd__)
|
||||
#define WAPP_PLATFORM_GNU
|
||||
#define WAPP_PLATFORM_POSIX
|
||||
#elif defined(__APPLE__) || defined(__MACH__)
|
||||
#include <TargetConditionals.h>
|
||||
#if TARGET_OS_IPHONE
|
||||
#define WAPP_PLATFORM_IOS
|
||||
#define WAPP_PLATFORM_APPLE
|
||||
#define WAPP_PLATFORM_POSIX
|
||||
#elif TARGET_OS_MAC
|
||||
#define WAPP_PLATFORM_MACOS
|
||||
#define WAPP_PLATFORM_APPLE
|
||||
#define WAPP_PLATFORM_POSIX
|
||||
#else
|
||||
#error "Unrecognised Apple platform"
|
||||
#endif
|
||||
#elif defined(_WIN64)
|
||||
#define WAPP_PLATFORM_WINDOWS64
|
||||
#define WAPP_PLATFORM_WINDOWS
|
||||
#elif defined(_WIN32)
|
||||
#define WAPP_PLATFORM_WINDOWS32
|
||||
#define WAPP_PLATFORM_WINDOWS
|
||||
#elif defined(__CYGWIN__)
|
||||
#define WAPP_PLATFORM_CYGWIN
|
||||
#define WAPP_PLATFORM_WINDOWS
|
||||
#elif defined(__unix__) || defined(__unix)
|
||||
#define WAPP_PLATFORM_UNIX
|
||||
#define WAPP_PLATFORM_POSIX
|
||||
#else
|
||||
#error "Unrecognised platform"
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
#define WAPP_PLATFORM_CPP
|
||||
#define WAPP_PLATFORM_CPP_VERSION __cplusplus
|
||||
#define WAPP_PLATFORM_CPP98_VERSION 199711L
|
||||
#define WAPP_PLATFORM_CPP11_VERSION 201103L
|
||||
#define WAPP_PLATFORM_CPP14_VERSION 201402L
|
||||
#define WAPP_PLATFORM_CPP17_VERSION 201703L
|
||||
#define WAPP_PLATFORM_CPP20_VERSION 202002L
|
||||
#define WAPP_PLATFORM_CPP23_VERSION 202302L
|
||||
|
||||
#if WAPP_PLATFORM_CPP_VERSION == WAPP_PLATFORM_CPP98_VERSION
|
||||
#define WAPP_PLATFORM_CPP98
|
||||
#elif WAPP_PLATFORM_CPP_VERSION == WAPP_PLATFORM_CPP11_VERSION
|
||||
#define WAPP_PLATFORM_CPP11
|
||||
#elif WAPP_PLATFORM_CPP_VERSION == WAPP_PLATFORM_CPP14_VERSION
|
||||
#define WAPP_PLATFORM_CPP14
|
||||
#elif WAPP_PLATFORM_CPP_VERSION == WAPP_PLATFORM_CPP17_VERSION
|
||||
#define WAPP_PLATFORM_CPP17
|
||||
#elif WAPP_PLATFORM_CPP_VERSION == WAPP_PLATFORM_CPP20_VERSION
|
||||
#define WAPP_PLATFORM_CPP20
|
||||
#elif WAPP_PLATFORM_CPP_VERSION == WAPP_PLATFORM_CPP23_VERSION
|
||||
#define WAPP_PLATFORM_CPP23
|
||||
#else
|
||||
#error "Unrecognised C++ version"
|
||||
#endif
|
||||
#else
|
||||
#define WAPP_PLATFORM_C
|
||||
|
||||
#if defined(__STDC_VERSION__)
|
||||
#define WAPP_PLATFORM_C_VERSION __STDC_VERSION__
|
||||
#define WAPP_PLATFORM_C99_VERSION 199901L
|
||||
#define WAPP_PLATFORM_C11_VERSION 201112L
|
||||
#define WAPP_PLATFORM_C17_VERSION 201710L
|
||||
#define WAPP_PLATFORM_C23_VERSION 202311L
|
||||
|
||||
#if WAPP_PLATFORM_C_VERSION == WAPP_PLATFORM_C99_VERSION
|
||||
#define WAPP_PLATFORM_C99
|
||||
#elif WAPP_PLATFORM_C_VERSION == WAPP_PLATFORM_C11_VERSION
|
||||
#define WAPP_PLATFORM_C11
|
||||
#elif WAPP_PLATFORM_C_VERSION == WAPP_PLATFORM_C17_VERSION
|
||||
#define WAPP_PLATFORM_C17
|
||||
#elif WAPP_PLATFORM_C_VERSION == WAPP_PLATFORM_C23_VERSION
|
||||
#define WAPP_PLATFORM_C23
|
||||
#else
|
||||
#error "Unrecognised C version"
|
||||
#endif
|
||||
#else
|
||||
#define WAPP_PLATFORM_C89
|
||||
#endif
|
||||
#endif // !__cplusplus
|
||||
|
||||
#endif // !PLATFORM_H
|
11
wapp/common/wapp_common.h
Normal file
11
wapp/common/wapp_common.h
Normal file
@ -0,0 +1,11 @@
|
||||
// vim:fileencoding=utf-8:foldmethod=marker
|
||||
|
||||
#ifndef WAPP_COMMON_H
|
||||
#define WAPP_COMMON_H
|
||||
|
||||
#include "aliases/aliases.h"
|
||||
#include "assert/assert.h"
|
||||
#include "misc/misc_utils.h"
|
||||
#include "platform/platform.h"
|
||||
|
||||
#endif // !WAPP_COMMON_H
|
147
wapp/core/mem/arena/mem_arena.c
Normal file
147
wapp/core/mem/arena/mem_arena.c
Normal file
@ -0,0 +1,147 @@
|
||||
// vim:fileencoding=utf-8:foldmethod=marker
|
||||
|
||||
#include "mem_arena.h"
|
||||
#include "../utils/mem_utils.h"
|
||||
#include "../../../common/aliases/aliases.h"
|
||||
#include "../../../common/assert/assert.h"
|
||||
#include "../../../common/misc/misc_utils.h"
|
||||
#include "../../os/mem/mem_os.h"
|
||||
#include <stdbool.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifndef DEFAULT_ALIGNMENT
|
||||
// Why 2 * sizeof(void *) instead of sizeof(void *)
|
||||
// https://handmade.network/forums/t/6860-alignment_arena_allocator
|
||||
#define DEFAULT_ALIGNMENT (2 * sizeof(void *))
|
||||
#endif /* ifndef DEFAULT_ALIGNMENT */
|
||||
|
||||
#define ARENA_MINIMUM_CAPACITY KB(16) // Allocate minimum of 4 pages
|
||||
|
||||
struct arena {
|
||||
u8 *buf;
|
||||
u8 *offset;
|
||||
u64 capacity;
|
||||
bool committed;
|
||||
|
||||
#ifdef WAPP_PLATFORM_WINDOWS
|
||||
wapp_misc_utils_padding_size(sizeof(u8 *) * 2 + sizeof(u64) + sizeof(bool));
|
||||
#endif // ifdef WAPP_PLATFORM_WINDOWS
|
||||
};
|
||||
|
||||
bool wapp_mem_arena_init_custom(Arena **arena, u64 base_capacity, MemAllocFlags flags, bool zero_buffer) {
|
||||
if (!arena || *arena || base_capacity == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
*arena = (Arena *)calloc(1, sizeof(Arena));
|
||||
Arena *arena_ptr = *arena;
|
||||
if (!arena_ptr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
u64 arena_capacity = wapp_misc_utils_u64_round_up_pow2(
|
||||
base_capacity >= ARENA_MINIMUM_CAPACITY ?
|
||||
base_capacity :
|
||||
ARENA_MINIMUM_CAPACITY
|
||||
);
|
||||
|
||||
arena_ptr->buf = (u8 *)wapp_mem_util_alloc(NULL, arena_capacity, WAPP_MEM_ACCESS_READ_WRITE, flags,
|
||||
zero_buffer ? WAPP_MEM_INIT_INITIALISED : WAPP_MEM_INIT_UNINITIALISED);
|
||||
|
||||
if (!(arena_ptr->buf)) {
|
||||
wapp_mem_arena_destroy(arena);
|
||||
return false;
|
||||
}
|
||||
|
||||
arena_ptr->capacity = arena_capacity;
|
||||
arena_ptr->offset = arena_ptr->buf;
|
||||
arena_ptr->committed = (flags & WAPP_MEM_ALLOC_COMMIT) == WAPP_MEM_ALLOC_COMMIT;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void *wapp_mem_arena_alloc(Arena *arena, u64 size) {
|
||||
return wapp_mem_arena_alloc_aligned(arena, size, DEFAULT_ALIGNMENT);
|
||||
}
|
||||
|
||||
void *wapp_mem_arena_alloc_aligned(Arena *arena, u64 size, u64 alignment) {
|
||||
wapp_debug_assert(arena != NULL, "`arena` should not be NULL");
|
||||
|
||||
u8 *alloc_start = arena->offset;
|
||||
|
||||
u8 *output = wapp_mem_util_align_forward((void *)alloc_start, alignment);
|
||||
if (output + size >= arena->buf + arena->capacity) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
arena->offset = output + size;
|
||||
|
||||
#ifdef WAPP_PLATFORM_WINDOWS
|
||||
if (!(arena->committed)) {
|
||||
wapp_mem_util_alloc(alloc_start, (uptr)(arena->offset) - (uptr)(alloc_start),
|
||||
WAPP_MEM_ACCESS_READ_WRITE, WAPP_MEM_ALLOC_COMMIT,
|
||||
WAPP_MEM_INIT_UNINITIALISED);
|
||||
}
|
||||
#endif // ifdef WAPP_PLATFORM_WINDOWS
|
||||
|
||||
memset(output, 0, size);
|
||||
|
||||
return (void *)output;
|
||||
}
|
||||
|
||||
void *wapp_mem_arena_realloc(Arena *arena, void *ptr, u64 old_size, u64 new_size) {
|
||||
if ((u8*)ptr < arena->buf || (u8*)ptr > arena->offset ||
|
||||
arena->offset + new_size >= arena->buf + arena->capacity) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void *new_ptr = wapp_mem_arena_alloc(arena, new_size);
|
||||
if (!new_ptr) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
u64 copy_size = new_size <= old_size ? new_size : old_size;
|
||||
memcpy(new_ptr, ptr, copy_size);
|
||||
|
||||
return new_ptr;
|
||||
}
|
||||
|
||||
void *wapp_mem_arena_realloc_aligned(Arena *arena, void *ptr, u64 old_size, u64 new_size, u64 alignment) {
|
||||
if ((u8*)ptr < arena->buf || (u8*)ptr > arena->offset ||
|
||||
arena->offset + new_size >= arena->buf + arena->capacity) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void *new_ptr = wapp_mem_arena_alloc_aligned(arena, new_size, alignment);
|
||||
if (!new_ptr) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
u64 copy_size = new_size <= old_size ? new_size : old_size;
|
||||
memcpy(new_ptr, ptr, copy_size);
|
||||
|
||||
return new_ptr;
|
||||
}
|
||||
|
||||
void wapp_mem_arena_clear(Arena *arena) {
|
||||
wapp_debug_assert(arena != NULL, "`arena` should not be NULL");
|
||||
|
||||
memset(arena->buf, 0, arena->offset - arena->buf);
|
||||
arena->offset = arena->buf;
|
||||
}
|
||||
|
||||
void wapp_mem_arena_destroy(Arena **arena) {
|
||||
wapp_debug_assert(arena != NULL && (*arena) != NULL, "`arena` double pointer is not valid");
|
||||
|
||||
Arena *arena_ptr = *arena;
|
||||
if (arena_ptr->buf) {
|
||||
wapp_mem_util_free(arena_ptr->buf, arena_ptr->capacity);
|
||||
}
|
||||
|
||||
arena_ptr->buf = arena_ptr->offset = NULL;
|
||||
arena_ptr->capacity = 0;
|
||||
|
||||
free(*arena);
|
||||
*arena = NULL;
|
||||
}
|
43
wapp/core/mem/arena/mem_arena.h
Normal file
43
wapp/core/mem/arena/mem_arena.h
Normal file
@ -0,0 +1,43 @@
|
||||
// vim:fileencoding=utf-8:foldmethod=marker
|
||||
|
||||
#ifndef MEM_ARENA_H
|
||||
#define MEM_ARENA_H
|
||||
|
||||
#include "../../../common/aliases/aliases.h"
|
||||
#include "../../../common/platform/platform.h"
|
||||
#include "../../os/mem/mem_os.h"
|
||||
#include <stdbool.h>
|
||||
|
||||
#ifdef WAPP_PLATFORM_CPP
|
||||
BEGIN_C_LINKAGE
|
||||
#endif // !WAPP_PLATFORM_CPP
|
||||
|
||||
typedef struct arena Arena;
|
||||
|
||||
#define wapp_mem_arena_init(arena_dptr, base_capacity) \
|
||||
(wapp_mem_arena_init_custom(arena_dptr, base_capacity, WAPP_MEM_ALLOC_RESERVE, false))
|
||||
#define wapp_mem_arena_init_commit(arena_dptr, base_capacity) \
|
||||
(wapp_mem_arena_init_custom(arena_dptr, base_capacity, WAPP_MEM_ALLOC_RESERVE | WAPP_MEM_ALLOC_COMMIT, false))
|
||||
#define wapp_mem_arena_init_zero(arena_dptr, base_capacity) \
|
||||
(wapp_mem_arena_init_custom(arena_dptr, base_capacity, WAPP_MEM_ALLOC_RESERVE, true))
|
||||
#define wapp_mem_arena_init_commit_and_zero(arena_dptr, base_capacity) \
|
||||
(wapp_mem_arena_init_custom(arena_dptr, base_capacity, WAPP_MEM_ALLOC_RESERVE | WAPP_MEM_ALLOC_COMMIT, true))
|
||||
|
||||
/**
|
||||
* Arena initialisation function. `wapp_mem_arena_init_custom` provides the most
|
||||
* control over how the Arena is initialised. Wrapper macros are provided for
|
||||
* easier use.
|
||||
*/
|
||||
bool wapp_mem_arena_init_custom(Arena **arena, u64 base_capacity, MemAllocFlags flags, bool zero_buffer);
|
||||
void *wapp_mem_arena_alloc(Arena *arena, u64 size);
|
||||
void *wapp_mem_arena_alloc_aligned(Arena *arena, u64 size, u64 alignment);
|
||||
void *wapp_mem_arena_realloc(Arena *arena, void *ptr, u64 old_size, u64 new_size);
|
||||
void *wapp_mem_arena_realloc_aligned(Arena *arena, void *ptr, u64 old_size, u64 new_size, u64 alignment);
|
||||
void wapp_mem_arena_clear(Arena *arena);
|
||||
void wapp_mem_arena_destroy(Arena **arena);
|
||||
|
||||
#ifdef WAPP_PLATFORM_CPP
|
||||
END_C_LINKAGE
|
||||
#endif // !WAPP_PLATFORM_CPP
|
||||
|
||||
#endif // !MEM_ARENA_H
|
59
wapp/core/mem/arena/mem_arena_allocator.c
Normal file
59
wapp/core/mem/arena/mem_arena_allocator.c
Normal file
@ -0,0 +1,59 @@
|
||||
// vim:fileencoding=utf-8:foldmethod=marker
|
||||
|
||||
#include "mem_arena_allocator.h"
|
||||
#include "mem_arena.h"
|
||||
#include "../../../common/aliases/aliases.h"
|
||||
#include "../../os/mem/mem_os.h"
|
||||
|
||||
internal inline void *mem_arena_alloc(u64 size, void *alloc_obj);
|
||||
internal inline void *mem_arena_alloc_aligned(u64 size, u64 alignment, void *alloc_obj);
|
||||
internal inline void *mem_arena_realloc(void *ptr, u64 old_size, u64 new_size, void *alloc_obj);
|
||||
internal inline void *mem_arena_realloc_aligned(void *ptr, u64 old_size, u64 new_size, u64 alignment,
|
||||
void *alloc_obj);
|
||||
|
||||
|
||||
Allocator wapp_mem_arena_allocator_init_custom(u64 base_capacity, MemAllocFlags flags, bool zero_buffer) {
|
||||
Allocator allocator = {0};
|
||||
bool initialised = wapp_mem_arena_init_custom((Arena **)(&allocator.obj), base_capacity, flags, zero_buffer);
|
||||
if (!initialised) {
|
||||
return allocator;
|
||||
}
|
||||
|
||||
allocator.alloc = mem_arena_alloc;
|
||||
allocator.alloc_aligned = mem_arena_alloc_aligned;
|
||||
allocator.realloc = mem_arena_realloc;
|
||||
allocator.realloc_aligned = mem_arena_realloc_aligned;
|
||||
|
||||
return allocator;
|
||||
}
|
||||
|
||||
void wapp_mem_arena_allocator_clear(Allocator *allocator) {
|
||||
wapp_mem_arena_clear((Arena *)(allocator->obj));
|
||||
}
|
||||
|
||||
void wapp_mem_arena_allocator_destroy(Allocator *allocator) {
|
||||
wapp_mem_arena_destroy((Arena **)(&(allocator->obj)));
|
||||
*allocator = (Allocator){0};
|
||||
}
|
||||
|
||||
|
||||
internal inline void *mem_arena_alloc(u64 size, void *alloc_obj) {
|
||||
Arena *arena = (Arena *)alloc_obj;
|
||||
return wapp_mem_arena_alloc(arena, size);
|
||||
}
|
||||
|
||||
internal inline void *mem_arena_alloc_aligned(u64 size, u64 alignment, void *alloc_obj) {
|
||||
Arena *arena = (Arena *)alloc_obj;
|
||||
return wapp_mem_arena_alloc_aligned(arena, size, alignment);
|
||||
}
|
||||
|
||||
internal inline void *mem_arena_realloc(void *ptr, u64 old_size, u64 new_size, void *alloc_obj) {
|
||||
Arena *arena = (Arena *)alloc_obj;
|
||||
return wapp_mem_arena_realloc(arena, ptr, old_size, new_size);
|
||||
}
|
||||
|
||||
internal inline void *mem_arena_realloc_aligned(void *ptr, u64 old_size, u64 new_size, u64 alignment,
|
||||
void *alloc_obj) {
|
||||
Arena *arena = (Arena *)alloc_obj;
|
||||
return wapp_mem_arena_realloc_aligned(arena, ptr, old_size, new_size, alignment);
|
||||
}
|
44
wapp/core/mem/arena/mem_arena_allocator.h
Normal file
44
wapp/core/mem/arena/mem_arena_allocator.h
Normal file
@ -0,0 +1,44 @@
|
||||
// vim:fileencoding=utf-8:foldmethod=marker
|
||||
|
||||
#ifndef MEM_ARENA_ALLOCATOR_H
|
||||
#define MEM_ARENA_ALLOCATOR_H
|
||||
|
||||
#include "../../../common/aliases/aliases.h"
|
||||
#include "../../../common/platform/platform.h"
|
||||
#include "../../../primitives/mem_allocator/mem_allocator.h"
|
||||
#include "../../os/mem/mem_os.h"
|
||||
#include <stdbool.h>
|
||||
|
||||
#ifdef WAPP_PLATFORM_CPP
|
||||
BEGIN_C_LINKAGE
|
||||
#endif // !WAPP_PLATFORM_CPP
|
||||
|
||||
#define wapp_mem_arena_allocator_init(base_capacity) \
|
||||
(wapp_mem_arena_allocator_init_custom(base_capacity, WAPP_MEM_ALLOC_RESERVE, false))
|
||||
#define wapp_mem_arena_allocator_init_commit(base_capacity) \
|
||||
(wapp_mem_arena_allocator_init_custom(base_capacity, WAPP_MEM_ALLOC_RESERVE | WAPP_MEM_ALLOC_COMMIT, false))
|
||||
#define wapp_mem_arena_allocator_init_zero(base_capacity) \
|
||||
(wapp_mem_arena_allocator_init_custom(base_capacity, WAPP_MEM_ALLOC_RESERVE, true))
|
||||
#define wapp_mem_arena_allocator_init_commit_and_zero(base_capacity) \
|
||||
(wapp_mem_arena_allocator_init_custom(base_capacity, WAPP_MEM_ALLOC_RESERVE | WAPP_MEM_ALLOC_COMMIT, true))
|
||||
|
||||
/**
|
||||
* Wraps an Arena in an Allocator object. It attempts to initialise the Arena
|
||||
* and, if successful, defines the operations supported by it to be used by the
|
||||
* Allocator.
|
||||
*
|
||||
* An Arena allocator only supports normal allocation and aligned allocation.
|
||||
* Reallocation, aligned reallocation and freeing aren't implemented.
|
||||
*
|
||||
* The `wapp_mem_arena_allocator_init_custom` provides the most control over how
|
||||
* the Arena is initialised. Wrapper macros are provided for easier use.
|
||||
*/
|
||||
Allocator wapp_mem_arena_allocator_init_custom(u64 base_capacity, MemAllocFlags flags, bool zero_buffer);
|
||||
void wapp_mem_arena_allocator_clear(Allocator *allocator);
|
||||
void wapp_mem_arena_allocator_destroy(Allocator *allocator);
|
||||
|
||||
#ifdef WAPP_PLATFORM_CPP
|
||||
END_C_LINKAGE
|
||||
#endif // !WAPP_PLATFORM_CPP
|
||||
|
||||
#endif // !MEM_ARENA_ALLOCATOR_H
|
27
wapp/core/mem/utils/mem_utils.c
Normal file
27
wapp/core/mem/utils/mem_utils.c
Normal file
@ -0,0 +1,27 @@
|
||||
// vim:fileencoding=utf-8:foldmethod=marker
|
||||
|
||||
#include "mem_utils.h"
|
||||
#include "../../../common/aliases/aliases.h"
|
||||
#include "../../../common/assert/assert.h"
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
|
||||
internal bool is_power_of_two(u64 num) { return (num & (num - 1)) == 0; }
|
||||
|
||||
void *wapp_mem_util_align_forward(void *ptr, u64 alignment) {
|
||||
wapp_debug_assert(ptr != NULL, "`ptr` should not be NULL");
|
||||
wapp_runtime_assert(is_power_of_two(alignment), "`alignment` value is not a power of two");
|
||||
|
||||
uptr p = (uptr)ptr;
|
||||
uptr align = (uptr)alignment;
|
||||
|
||||
// Similar to p % align, but it's a faster implementation that works fine
|
||||
// because align is guaranteed to be a power of 2
|
||||
uptr modulo = p & (align - 1);
|
||||
|
||||
if (modulo != 0) {
|
||||
p += align - modulo;
|
||||
}
|
||||
|
||||
return (void *)p;
|
||||
}
|
19
wapp/core/mem/utils/mem_utils.h
Normal file
19
wapp/core/mem/utils/mem_utils.h
Normal file
@ -0,0 +1,19 @@
|
||||
// vim:fileencoding=utf-8:foldmethod=marker
|
||||
|
||||
#ifndef MEM_UTILS_H
|
||||
#define MEM_UTILS_H
|
||||
|
||||
#include "../../../common/aliases/aliases.h"
|
||||
#include "../../../common/platform/platform.h"
|
||||
|
||||
#ifdef WAPP_PLATFORM_CPP
|
||||
BEGIN_C_LINKAGE
|
||||
#endif // !WAPP_PLATFORM_CPP
|
||||
|
||||
void *wapp_mem_util_align_forward(void *ptr, u64 alignment);
|
||||
|
||||
#ifdef WAPP_PLATFORM_CPP
|
||||
END_C_LINKAGE
|
||||
#endif // !WAPP_PLATFORM_CPP
|
||||
|
||||
#endif // !MEM_UTILS_H
|
136
wapp/core/os/cpath/cpath.c
Normal file
136
wapp/core/os/cpath/cpath.c
Normal file
@ -0,0 +1,136 @@
|
||||
// vim:fileencoding=utf-8:foldmethod=marker
|
||||
|
||||
#include "cpath.h"
|
||||
#include "../../../common/aliases/aliases.h"
|
||||
#include "../../../common/misc/misc_utils.h"
|
||||
#include "../../mem/arena/mem_arena_allocator.h"
|
||||
#include "../../../primitives/dbl_list/dbl_list.h"
|
||||
#include "../../../primitives/mem_allocator/mem_allocator.h"
|
||||
#include "../../../primitives/strings/str8/str8.h"
|
||||
#include <stdarg.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
u32 wapp_cpath_join_path(Str8 *dst, const Str8List *parts) {
|
||||
if (!dst || !parts) {
|
||||
return CPATH_JOIN_INVALID_ARGS;
|
||||
}
|
||||
|
||||
if (parts->node_count == 0) {
|
||||
return CPATH_JOIN_EMPTY_PARTS;
|
||||
}
|
||||
|
||||
Str8 separator = wapp_str8_buf(4);
|
||||
wapp_str8_push_back(&separator, PATH_SEP);
|
||||
|
||||
u64 required_capacity = parts->node_count * separator.size + wapp_str8_list_total_size(parts);
|
||||
if (dst->capacity < required_capacity) {
|
||||
return CPATH_JOIN_INSUFFICIENT_DST_CAPACITY;
|
||||
}
|
||||
|
||||
// Handle first node
|
||||
const Str8Node *first_node = wapp_str8_list_get(parts, 0);
|
||||
wapp_str8_copy_str8_capped(dst, first_node->item);
|
||||
|
||||
// NOTE (Abdelrahman): Uses a while loop instead of a for loop to get rid of
|
||||
// MSVC Spectre mitigation warnings
|
||||
const Str8Node *node = first_node;
|
||||
u64 node_index = 1;
|
||||
bool running = node_index < parts->node_count;
|
||||
while (running && node->next) {
|
||||
node = node->next;
|
||||
if (node->item->size == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (dst->size > 0) {
|
||||
char dst_last = wapp_str8_get(dst, dst->size - 1);
|
||||
char node_start = wapp_str8_get(node->item, 0);
|
||||
bool add_path_sep = dst_last != PATH_SEP && node_start != PATH_SEP;
|
||||
|
||||
if (add_path_sep) {
|
||||
wapp_str8_concat_capped(dst, &separator);
|
||||
}
|
||||
}
|
||||
|
||||
wapp_str8_concat_capped(dst, node->item);
|
||||
|
||||
++node_index;
|
||||
running = node_index < parts->node_count;
|
||||
}
|
||||
|
||||
return CPATH_JOIN_SUCCESS;
|
||||
}
|
||||
|
||||
Str8 *dirup(const Allocator *allocator, Str8RO *path, u64 levels) {
|
||||
Str8 *output = NULL;
|
||||
if (!allocator || !path) {
|
||||
goto RETURN_DIRUP;
|
||||
}
|
||||
|
||||
bool absolute = wapp_str8_get(path, 0) == PATH_SEP;
|
||||
Str8 separator = wapp_str8_buf(4);
|
||||
wapp_str8_push_back(&separator, PATH_SEP);
|
||||
|
||||
if (path->size == 0) {
|
||||
output = wapp_str8_alloc_buf(allocator, 16);
|
||||
if (!output) {
|
||||
goto RETURN_DIRUP;
|
||||
}
|
||||
|
||||
wapp_str8_push_back(output, absolute ? PATH_SEP : '.');
|
||||
goto RETURN_DIRUP;
|
||||
}
|
||||
|
||||
if (levels < 1) {
|
||||
output = wapp_str8_alloc_str8(allocator, path);
|
||||
goto RETURN_DIRUP;
|
||||
}
|
||||
|
||||
Allocator tmp_arena = wapp_mem_arena_allocator_init(MB(8));
|
||||
if (wapp_mem_allocator_invalid(&tmp_arena)) {
|
||||
goto RETURN_DIRUP;
|
||||
}
|
||||
|
||||
Str8List *parts = wapp_str8_split(&tmp_arena, path, &separator);
|
||||
if (!parts) {
|
||||
goto RETURN_DIRUP;
|
||||
}
|
||||
|
||||
if (levels >= parts->node_count) {
|
||||
output = wapp_str8_alloc_buf(allocator, 16);
|
||||
if (!output) {
|
||||
goto LIST_CLEANUP_DIRUP;
|
||||
}
|
||||
|
||||
wapp_str8_push_back(output, absolute ? PATH_SEP : '.');
|
||||
} else {
|
||||
for (u64 i = 0; i < levels; ++i) {
|
||||
wapp_str8_list_pop_back(parts);
|
||||
}
|
||||
|
||||
u64 alignment = sizeof(void *) * 2;
|
||||
u64 alloc_size = wapp_str8_list_total_size(parts) + parts->node_count * separator.size;
|
||||
u64 modulo = alloc_size & (alignment - 1);
|
||||
alloc_size += alignment - modulo;
|
||||
|
||||
output = wapp_str8_alloc_buf(allocator, alloc_size);
|
||||
if (output) {
|
||||
if (absolute) {
|
||||
wapp_str8_push_back(output, PATH_SEP);
|
||||
}
|
||||
|
||||
Str8 *joined = wapp_str8_join(&tmp_arena, parts, &separator);
|
||||
if (joined) {
|
||||
wapp_str8_concat_capped(output, joined);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
LIST_CLEANUP_DIRUP:
|
||||
wapp_mem_arena_allocator_destroy(&tmp_arena);
|
||||
|
||||
RETURN_DIRUP:
|
||||
return output;
|
||||
}
|
40
wapp/core/os/cpath/cpath.h
Normal file
40
wapp/core/os/cpath/cpath.h
Normal file
@ -0,0 +1,40 @@
|
||||
// vim:fileencoding=utf-8:foldmethod=marker
|
||||
|
||||
#ifndef CPATH_H
|
||||
#define CPATH_H
|
||||
|
||||
#include "../../../common/aliases/aliases.h"
|
||||
#include "../../../common/platform/platform.h"
|
||||
#include "../../../primitives/mem_allocator/mem_allocator.h"
|
||||
#include "../../../primitives/strings/str8/str8.h"
|
||||
|
||||
#ifdef WAPP_PLATFORM_CPP
|
||||
BEGIN_C_LINKAGE
|
||||
#endif // !WAPP_PLATFORM_CPP
|
||||
|
||||
#ifdef WAPP_PLATFORM_POSIX
|
||||
#define PATH_SEP '/'
|
||||
#elif defined(WAPP_PLATFORM_WINDOWS)
|
||||
#define PATH_SEP '\\'
|
||||
#else
|
||||
#error "Unrecognised platform"
|
||||
#endif
|
||||
|
||||
#define wapp_cpath_dirname(ALLOCATOR, PATH) dirup(ALLOCATOR, PATH, 1)
|
||||
#define wapp_cpath_dirup(ALLOCATOR, PATH, COUNT) dirup(ALLOCATOR, PATH, COUNT)
|
||||
|
||||
enum {
|
||||
CPATH_JOIN_SUCCESS = 0,
|
||||
CPATH_JOIN_INVALID_ARGS,
|
||||
CPATH_JOIN_EMPTY_PARTS,
|
||||
CPATH_JOIN_INSUFFICIENT_DST_CAPACITY,
|
||||
};
|
||||
|
||||
u32 wapp_cpath_join_path(Str8 *dst, const Str8List *parts);
|
||||
Str8 *dirup(const Allocator *allocator, Str8RO *path, u64 levels);
|
||||
|
||||
#ifdef WAPP_PLATFORM_CPP
|
||||
END_C_LINKAGE
|
||||
#endif // !WAPP_PLATFORM_CPP
|
||||
|
||||
#endif // !CPATH_H
|
31
wapp/core/os/mem/mem_os.c
Normal file
31
wapp/core/os/mem/mem_os.c
Normal file
@ -0,0 +1,31 @@
|
||||
// vim:fileencoding=utf-8:foldmethod=marker
|
||||
|
||||
#include "mem_os.h"
|
||||
#include "mem_os_ops.h"
|
||||
#include "../../../common/aliases/aliases.h"
|
||||
#include "../../../common/platform/platform.h"
|
||||
#include <assert.h>
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
|
||||
#if defined(WAPP_PLATFORM_WINDOWS)
|
||||
#include "win/mem_os_win.h"
|
||||
#elif defined(WAPP_PLATFORM_POSIX)
|
||||
#include "posix/mem_os_posix.h"
|
||||
#else
|
||||
#error "Unrecognised platform"
|
||||
#endif
|
||||
|
||||
void *wapp_mem_util_alloc(void *addr, u64 size, MemAccess access, MemAllocFlags flags, MemInitType type) {
|
||||
void *output = mem_util_allocate(addr, size, access, flags, type);
|
||||
|
||||
if (type == WAPP_MEM_INIT_INITIALISED) {
|
||||
memset(output, 0, size);
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
void wapp_mem_util_free(void *ptr, u64 size) {
|
||||
mem_util_free(ptr, size);
|
||||
}
|
33
wapp/core/os/mem/mem_os.h
Normal file
33
wapp/core/os/mem/mem_os.h
Normal file
@ -0,0 +1,33 @@
|
||||
// vim:fileencoding=utf-8:foldmethod=marker
|
||||
|
||||
#ifndef MEM_OS_H
|
||||
#define MEM_OS_H
|
||||
|
||||
#include "../../../common/aliases/aliases.h"
|
||||
#include "../../../common/platform/platform.h"
|
||||
|
||||
#include "mem_os_ops.h"
|
||||
|
||||
#ifdef WAPP_PLATFORM_CPP
|
||||
BEGIN_C_LINKAGE
|
||||
#endif // !WAPP_PLATFORM_CPP
|
||||
|
||||
#if defined(WAPP_PLATFORM_WINDOWS)
|
||||
#include "win/mem_os_win.h"
|
||||
#elif defined(WAPP_PLATFORM_POSIX)
|
||||
#include "posix/mem_os_posix.h"
|
||||
#else
|
||||
#error "Unrecognised platform"
|
||||
#endif
|
||||
|
||||
void *wapp_mem_util_alloc(void *addr, u64 size, MemAccess access, MemAllocFlags flags, MemInitType type);
|
||||
void wapp_mem_util_free(void *ptr, u64 size);
|
||||
|
||||
external void *mem_util_allocate(void *addr, u64 size, MemAccess access, MemAllocFlags flags, MemInitType type);
|
||||
external void mem_util_free(void *ptr, u64 size);
|
||||
|
||||
#ifdef WAPP_PLATFORM_CPP
|
||||
END_C_LINKAGE
|
||||
#endif // !WAPP_PLATFORM_CPP
|
||||
|
||||
#endif // !MEM_OS_H
|
30
wapp/core/os/mem/mem_os_ops.h
Normal file
30
wapp/core/os/mem/mem_os_ops.h
Normal file
@ -0,0 +1,30 @@
|
||||
// vim:fileencoding=utf-8:foldmethod=marker
|
||||
|
||||
#ifndef MEM_OS_OPS_H
|
||||
#define MEM_OS_OPS_H
|
||||
|
||||
#include "../../../common/platform/platform.h"
|
||||
|
||||
#ifdef WAPP_PLATFORM_CPP
|
||||
BEGIN_C_LINKAGE
|
||||
#endif // !WAPP_PLATFORM_CPP
|
||||
|
||||
typedef enum mem_access {
|
||||
WAPP_MEM_ACCESS_NONE,
|
||||
WAPP_MEM_ACCESS_READ_ONLY,
|
||||
WAPP_MEM_ACCESS_EXEC_ONLY,
|
||||
WAPP_MEM_ACCESS_READ_WRITE,
|
||||
WAPP_MEM_ACCESS_READ_EXEC,
|
||||
WAPP_MEM_ACCESS_READ_WRITE_EXEC,
|
||||
} MemAccess;
|
||||
|
||||
typedef enum mem_init_type {
|
||||
WAPP_MEM_INIT_UNINITIALISED,
|
||||
WAPP_MEM_INIT_INITIALISED,
|
||||
} MemInitType;
|
||||
|
||||
#ifdef WAPP_PLATFORM_CPP
|
||||
END_C_LINKAGE
|
||||
#endif // !WAPP_PLATFORM_CPP
|
||||
|
||||
#endif // !MEM_OS_OPS_H
|
36
wapp/core/os/mem/posix/mem_os_posix.c
Normal file
36
wapp/core/os/mem/posix/mem_os_posix.c
Normal file
@ -0,0 +1,36 @@
|
||||
// vim:fileencoding=utf-8:foldmethod=marker
|
||||
|
||||
#include "../../../../common/aliases/aliases.h"
|
||||
#include "../../../../common/platform/platform.h"
|
||||
|
||||
#ifdef WAPP_PLATFORM_POSIX
|
||||
|
||||
#include "mem_os_posix.h"
|
||||
#include "../mem_os_ops.h"
|
||||
#include <sys/mman.h>
|
||||
|
||||
internal const i32 access_types[] = {
|
||||
[WAPP_MEM_ACCESS_NONE] = PROT_NONE,
|
||||
[WAPP_MEM_ACCESS_READ_ONLY] = PROT_READ,
|
||||
[WAPP_MEM_ACCESS_EXEC_ONLY] = PROT_EXEC,
|
||||
[WAPP_MEM_ACCESS_READ_WRITE] = PROT_READ | PROT_WRITE,
|
||||
[WAPP_MEM_ACCESS_READ_EXEC] = PROT_READ | PROT_EXEC,
|
||||
[WAPP_MEM_ACCESS_READ_WRITE_EXEC] = PROT_READ | PROT_WRITE | PROT_EXEC,
|
||||
};
|
||||
|
||||
void *mem_util_allocate(void *addr, u64 size, MemAccess access, MemAllocFlags flags, MemInitType type) {
|
||||
(void)type;
|
||||
i32 alloc_flags = flags | MAP_ANON | MAP_PRIVATE;
|
||||
|
||||
#if defined(WAPP_PLATFORM_LINUX) || defined(WAPP_PLATFORM_GNU) || defined(WAPP_PLATFORM_NET_BSD)
|
||||
alloc_flags |= MAP_NORESERVE;
|
||||
#endif
|
||||
|
||||
return mmap(addr, size, access_types[access], alloc_flags, -1, 0);
|
||||
}
|
||||
|
||||
void mem_util_free(void *ptr, u64 size) {
|
||||
munmap(ptr, size);
|
||||
}
|
||||
|
||||
#endif // !WAPP_PLATFORM_POSIX
|
35
wapp/core/os/mem/posix/mem_os_posix.h
Normal file
35
wapp/core/os/mem/posix/mem_os_posix.h
Normal file
@ -0,0 +1,35 @@
|
||||
// vim:fileencoding=utf-8:foldmethod=marker
|
||||
|
||||
#ifndef MEM_OS_POSIX_H
|
||||
#define MEM_OS_POSIX_H
|
||||
|
||||
#include "../../../../common/platform/platform.h"
|
||||
|
||||
#ifdef WAPP_PLATFORM_CPP
|
||||
BEGIN_C_LINKAGE
|
||||
#endif // !WAPP_PLATFORM_CPP
|
||||
|
||||
#ifdef WAPP_PLATFORM_POSIX
|
||||
|
||||
#include <sys/mman.h>
|
||||
|
||||
typedef enum mem_alloc_flags {
|
||||
#if defined(WAPP_PLATFORM_LINUX) || defined(WAPP_PLATFORM_GNU)
|
||||
WAPP_MEM_ALLOC_RESERVE = 0,
|
||||
WAPP_MEM_ALLOC_COMMIT = MAP_POPULATE,
|
||||
#elif defined(WAPP_PLATFORM_FREE_BSD)
|
||||
WAPP_MEM_ALLOC_RESERVE = 0,
|
||||
WAPP_MEM_ALLOC_COMMIT = MAP_PREFAULT_READ,
|
||||
#elif defined(WAPP_PLATFORM_BSD) || defined(WAPP_PLATFORM_UNIX) || defined(WAPP_PLATFORM_APPLE)
|
||||
WAPP_MEM_ALLOC_RESERVE = 0,
|
||||
WAPP_MEM_ALLOC_COMMIT = 0,
|
||||
#endif
|
||||
} MemAllocFlags;
|
||||
|
||||
#endif // !WAPP_PLATFORM_POSIX
|
||||
|
||||
#ifdef WAPP_PLATFORM_CPP
|
||||
END_C_LINKAGE
|
||||
#endif // !WAPP_PLATFORM_CPP
|
||||
|
||||
#endif // !MEM_OS_POSIX_H
|
37
wapp/core/os/mem/win/mem_os_win.c
Normal file
37
wapp/core/os/mem/win/mem_os_win.c
Normal file
@ -0,0 +1,37 @@
|
||||
// vim:fileencoding=utf-8:foldmethod=marker
|
||||
|
||||
#include "../../../../common/aliases/aliases.h"
|
||||
#include "../../../../common/platform/platform.h"
|
||||
|
||||
#ifdef WAPP_PLATFORM_WINDOWS
|
||||
|
||||
#include "mem_os_win.h"
|
||||
#include "../mem_os_ops.h"
|
||||
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <Windows.h>
|
||||
#include <memoryapi.h>
|
||||
|
||||
internal const i32 access_types[] = {
|
||||
[WAPP_MEM_ACCESS_NONE] = PAGE_NOACCESS,
|
||||
[WAPP_MEM_ACCESS_READ_ONLY] = PAGE_READONLY,
|
||||
[WAPP_MEM_ACCESS_EXEC_ONLY] = PAGE_EXECUTE,
|
||||
[WAPP_MEM_ACCESS_READ_WRITE] = PAGE_READWRITE,
|
||||
[WAPP_MEM_ACCESS_READ_EXEC] = PAGE_EXECUTE_READ,
|
||||
[WAPP_MEM_ACCESS_READ_WRITE_EXEC] = PAGE_EXECUTE_READWRITE,
|
||||
};
|
||||
|
||||
void *mem_util_allocate(void *addr, u64 size, MemAccess access, MemAllocFlags flags, MemInitType type) {
|
||||
// Ensure memory is committed if it's meant to be initialised
|
||||
if (type == WAPP_MEM_INIT_INITIALISED) {
|
||||
flags |= WAPP_MEM_ALLOC_COMMIT;
|
||||
}
|
||||
|
||||
return VirtualAlloc(addr, (SIZE_T)size, flags, access_types[access]);
|
||||
}
|
||||
|
||||
void mem_util_free(void *ptr, u64 size) {
|
||||
VirtualFree(ptr, size, MEM_RELEASE);
|
||||
}
|
||||
|
||||
#endif // !WAPP_PLATFORM_WINDOWS
|
29
wapp/core/os/mem/win/mem_os_win.h
Normal file
29
wapp/core/os/mem/win/mem_os_win.h
Normal file
@ -0,0 +1,29 @@
|
||||
// vim:fileencoding=utf-8:foldmethod=marker
|
||||
|
||||
#ifndef MEM_OS_WIN_H
|
||||
#define MEM_OS_WIN_H
|
||||
|
||||
#include "../../../../common/platform/platform.h"
|
||||
|
||||
#ifdef WAPP_PLATFORM_CPP
|
||||
BEGIN_C_LINKAGE
|
||||
#endif // !WAPP_PLATFORM_CPP
|
||||
|
||||
#ifdef WAPP_PLATFORM_WINDOWS
|
||||
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <Windows.h>
|
||||
#include <memoryapi.h>
|
||||
|
||||
typedef enum mem_alloc_flags {
|
||||
WAPP_MEM_ALLOC_RESERVE = MEM_RESERVE,
|
||||
WAPP_MEM_ALLOC_COMMIT = MEM_COMMIT,
|
||||
} MemAllocFlags;
|
||||
|
||||
#endif // !WAPP_PLATFORM_WINDOWS
|
||||
|
||||
#ifdef WAPP_PLATFORM_CPP
|
||||
END_C_LINKAGE
|
||||
#endif // !WAPP_PLATFORM_CPP
|
||||
|
||||
#endif // !MEM_OS_WIN_H
|
102
wapp/core/os/shell/commander/commander.c
Normal file
102
wapp/core/os/shell/commander/commander.c
Normal file
@ -0,0 +1,102 @@
|
||||
// vim:fileencoding=utf-8:foldmethod=marker
|
||||
|
||||
#include "commander.h"
|
||||
#include "commander_output.h"
|
||||
#include "../utils/shell_utils.h"
|
||||
#include "../../../mem/arena/mem_arena_allocator.h"
|
||||
#include "../../../../common/aliases/aliases.h"
|
||||
#include "../../../../common/misc/misc_utils.h"
|
||||
#include "../../../../primitives/dbl_list/dbl_list.h"
|
||||
#include "../../../../primitives/mem_allocator/mem_allocator.h"
|
||||
#include "../../../../primitives/strings/str8/str8.h"
|
||||
#include <stdarg.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#define CMD_BUF_LEN 8192
|
||||
#define OUT_BUF_LEN 4096
|
||||
|
||||
internal inline CMDResult execute_command(Str8RO *cmd, CMDOutHandling out_handling, Str8 *out_buf);
|
||||
internal inline CMDError get_command_output(FILE *fp, CMDOutHandling out_handling, Str8 *out_buf);
|
||||
|
||||
CMDResult wapp_shell_commander_execute(CMDOutHandling out_handling, Str8 *out_buf, const Str8List *cmd) {
|
||||
if (!cmd) {
|
||||
return CMD_NO_EXIT(SHELL_ERR_INVALID_ARGS);
|
||||
}
|
||||
|
||||
Allocator arena = wapp_mem_arena_allocator_init(KB(500));
|
||||
|
||||
Str8 *cmd_str = wapp_str8_join(&arena, cmd, &wapp_str8_lit_ro(" "));
|
||||
if (!cmd_str) {
|
||||
wapp_mem_arena_allocator_destroy(&arena);
|
||||
return CMD_NO_EXIT(SHELL_ERR_ALLOCATION_FAIL);
|
||||
}
|
||||
|
||||
// Redirect output
|
||||
cmd_str = wapp_str8_alloc_concat(&arena, cmd_str, &wapp_str8_lit_ro(" 2>&1"));
|
||||
|
||||
CMDResult output = execute_command(cmd_str, out_handling, out_buf);
|
||||
|
||||
wapp_mem_arena_allocator_destroy(&arena);
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
internal inline CMDResult execute_command(Str8RO *cmd, CMDOutHandling out_handling, Str8 *out_buf) {
|
||||
char cmd_buf[CMD_BUF_LEN] = {0};
|
||||
wapp_str8_copy_to_cstr(cmd_buf, cmd, CMD_BUF_LEN);
|
||||
|
||||
FILE *fp = wapp_shell_utils_popen(cmd_buf, "r");
|
||||
if (!fp) {
|
||||
return CMD_NO_EXIT(SHELL_ERR_PROC_START_FAIL);
|
||||
}
|
||||
|
||||
CMDResult output;
|
||||
|
||||
CMDError err = get_command_output(fp, out_handling, out_buf);
|
||||
if (err > SHELL_ERR_NO_ERROR) {
|
||||
output = CMD_NO_EXIT(err);
|
||||
goto EXECUTE_COMMAND_CLOSE;
|
||||
}
|
||||
|
||||
i32 st = EXIT_SUCCESS;
|
||||
err = get_output_status(fp, &st);
|
||||
if (err > SHELL_ERR_NO_ERROR) {
|
||||
output = CMD_NO_EXIT(err);
|
||||
goto EXECUTE_COMMAND_CLOSE;
|
||||
}
|
||||
|
||||
// Process is already closed in get_output_status
|
||||
fp = NULL;
|
||||
|
||||
output = (CMDResult){
|
||||
.exited = true,
|
||||
.exit_code = st,
|
||||
.error = SHELL_ERR_NO_ERROR,
|
||||
};
|
||||
|
||||
EXECUTE_COMMAND_CLOSE:
|
||||
if (fp) {
|
||||
wapp_shell_utils_pclose(fp);
|
||||
}
|
||||
return output;
|
||||
}
|
||||
|
||||
internal inline CMDError get_command_output(FILE *fp, CMDOutHandling out_handling, Str8 *out_buf) {
|
||||
Str8 out = wapp_str8_buf(OUT_BUF_LEN);
|
||||
|
||||
out.size = fread((void *)out.buf, sizeof(u8), out.capacity, fp);
|
||||
if (out_handling == SHELL_OUTPUT_CAPTURE && out_buf != NULL) {
|
||||
if (out.size >= out_buf->capacity) {
|
||||
return SHELL_ERR_OUT_BUF_FULL;
|
||||
}
|
||||
|
||||
wapp_str8_concat_capped(out_buf, &out);
|
||||
} else if (out_handling == SHELL_OUTPUT_PRINT) {
|
||||
printf(WAPP_STR8_SPEC, wapp_str8_varg(out));
|
||||
}
|
||||
|
||||
return SHELL_ERR_NO_ERROR;
|
||||
}
|
28
wapp/core/os/shell/commander/commander.h
Normal file
28
wapp/core/os/shell/commander/commander.h
Normal file
@ -0,0 +1,28 @@
|
||||
// vim:fileencoding=utf-8:foldmethod=marker
|
||||
|
||||
#ifndef COMMANDER_H
|
||||
#define COMMANDER_H
|
||||
|
||||
#include "commander_output.h"
|
||||
#include "../../../../common/aliases/aliases.h"
|
||||
#include "../../../../common/platform/platform.h"
|
||||
#include "../../../../primitives/strings/str8/str8.h"
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#ifdef WAPP_PLATFORM_CPP
|
||||
BEGIN_C_LINKAGE
|
||||
#endif // !WAPP_PLATFORM_CPP
|
||||
|
||||
#define CMD_NO_EXIT(ERR) ((CMDResult){.exited = false, .exit_code = EXIT_FAILURE, .error = ERR})
|
||||
|
||||
CMDResult wapp_shell_commander_execute(CMDOutHandling out_handling, Str8 *out_buf, const Str8List *cmd);
|
||||
|
||||
external CMDError get_output_status(FILE *fp, i32 *status_out);
|
||||
|
||||
#ifdef WAPP_PLATFORM_CPP
|
||||
END_C_LINKAGE
|
||||
#endif // !WAPP_PLATFORM_CPP
|
||||
|
||||
#endif // !COMMANDER_H
|
45
wapp/core/os/shell/commander/commander_output.h
Normal file
45
wapp/core/os/shell/commander/commander_output.h
Normal file
@ -0,0 +1,45 @@
|
||||
// vim:fileencoding=utf-8:foldmethod=marker
|
||||
|
||||
#ifndef COMMANDER_OUTPUT_H
|
||||
#define COMMANDER_OUTPUT_H
|
||||
|
||||
#include "../../../../common/aliases/aliases.h"
|
||||
#include "../../../../common/platform/platform.h"
|
||||
#include <stdbool.h>
|
||||
|
||||
#ifdef WAPP_PLATFORM_CPP
|
||||
BEGIN_C_LINKAGE
|
||||
#endif // !WAPP_PLATFORM_CPP
|
||||
|
||||
typedef enum {
|
||||
SHELL_OUTPUT_DISCARD,
|
||||
SHELL_OUTPUT_PRINT,
|
||||
SHELL_OUTPUT_CAPTURE,
|
||||
} CMDOutHandling;
|
||||
|
||||
typedef enum {
|
||||
SHELL_ERR_NO_ERROR,
|
||||
SHELL_ERR_INVALID_ARGS,
|
||||
SHELL_ERR_ALLOCATION_FAIL,
|
||||
SHELL_ERR_PROC_START_FAIL,
|
||||
SHELL_ERR_OUT_BUF_FULL,
|
||||
SHELL_ERR_PROC_EXIT_FAIL,
|
||||
} CMDError;
|
||||
|
||||
typedef struct commander_result CMDResult;
|
||||
struct commander_result {
|
||||
i32 exit_code;
|
||||
CMDError error;
|
||||
bool exited;
|
||||
|
||||
#ifdef WAPP_PLATFORM_WINDOWS
|
||||
#include "../../../../common/misc/misc_utils.h"
|
||||
wapp_misc_utils_padding_size(sizeof(bool) + sizeof(i32) + sizeof(CMDError));
|
||||
#endif // !WAPP_PLATFORM_WINDOWS
|
||||
};
|
||||
|
||||
#ifdef WAPP_PLATFORM_CPP
|
||||
END_C_LINKAGE
|
||||
#endif // !WAPP_PLATFORM_CPP
|
||||
|
||||
#endif // !COMMANDER_OUTPUT_H
|
25
wapp/core/os/shell/commander/posix/commander_posix.c
Normal file
25
wapp/core/os/shell/commander/posix/commander_posix.c
Normal file
@ -0,0 +1,25 @@
|
||||
// vim:fileencoding=utf-8:foldmethod=marker
|
||||
|
||||
#include "../../../../../common/aliases/aliases.h"
|
||||
#include "../../../../../common/platform/platform.h"
|
||||
|
||||
#ifdef WAPP_PLATFORM_POSIX
|
||||
|
||||
#include "../commander_output.h"
|
||||
#include "../../utils/shell_utils.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
CMDError get_output_status(FILE *fp, i32 *status_out) {
|
||||
*status_out = wapp_shell_utils_pclose(fp);
|
||||
|
||||
if (!WIFEXITED(*status_out)) {
|
||||
return SHELL_ERR_PROC_EXIT_FAIL;
|
||||
}
|
||||
|
||||
*status_out = WEXITSTATUS(*status_out);
|
||||
|
||||
return SHELL_ERR_NO_ERROR;
|
||||
}
|
||||
|
||||
#endif // !WAPP_PLATFORM_POSIX
|
24
wapp/core/os/shell/commander/win/commander_win.c
Normal file
24
wapp/core/os/shell/commander/win/commander_win.c
Normal file
@ -0,0 +1,24 @@
|
||||
// vim:fileencoding=utf-8:foldmethod=marker
|
||||
|
||||
#include "../../../../../common/aliases/aliases.h"
|
||||
#include "../../../../../common/platform/platform.h"
|
||||
|
||||
#ifdef WAPP_PLATFORM_WINDOWS
|
||||
|
||||
#include "../commander_output.h"
|
||||
#include "../../utils/shell_utils.h"
|
||||
#include <stdio.h>
|
||||
|
||||
CMDError get_output_status(FILE *fp, i32 *status_out) {
|
||||
if (!feof(fp)) {
|
||||
// Ensure process is closed on failure
|
||||
wapp_shell_utils_pclose(fp);
|
||||
return SHELL_ERR_PROC_EXIT_FAIL;
|
||||
}
|
||||
|
||||
*status_out = wapp_shell_utils_pclose(fp);
|
||||
|
||||
return SHELL_ERR_NO_ERROR;
|
||||
}
|
||||
|
||||
#endif // !WAPP_PLATFORM_WINDOWS
|
36
wapp/core/os/shell/termcolour/posix/termcolour_posix.c
Normal file
36
wapp/core/os/shell/termcolour/posix/termcolour_posix.c
Normal file
@ -0,0 +1,36 @@
|
||||
// vim:fileencoding=utf-8:foldmethod=marker
|
||||
|
||||
#include "../../../../../common/aliases/aliases.h"
|
||||
#include "../../../../../common/platform/platform.h"
|
||||
#include "../../../../../primitives/strings/str8/str8.h"
|
||||
|
||||
#ifdef WAPP_PLATFORM_POSIX
|
||||
|
||||
#include "../terminal_colours.h"
|
||||
#include <stdio.h>
|
||||
|
||||
internal Str8RO colours[COUNT_TERM_COLOUR] = {
|
||||
[WAPP_TERM_COLOUR_FG_BLACK] = wapp_str8_lit_ro_initialiser_list("\033[30m"),
|
||||
[WAPP_TERM_COLOUR_FG_RED] = wapp_str8_lit_ro_initialiser_list("\033[31m"),
|
||||
[WAPP_TERM_COLOUR_FG_GREEN] = wapp_str8_lit_ro_initialiser_list("\033[32m"),
|
||||
[WAPP_TERM_COLOUR_FG_BLUE] = wapp_str8_lit_ro_initialiser_list("\033[34m"),
|
||||
[WAPP_TERM_COLOUR_FG_CYAN] = wapp_str8_lit_ro_initialiser_list("\033[36m"),
|
||||
[WAPP_TERM_COLOUR_FG_MAGENTA] = wapp_str8_lit_ro_initialiser_list("\033[35m"),
|
||||
[WAPP_TERM_COLOUR_FG_YELLOW] = wapp_str8_lit_ro_initialiser_list("\033[33m"),
|
||||
[WAPP_TERM_COLOUR_FG_WHITE] = wapp_str8_lit_ro_initialiser_list("\033[37m"),
|
||||
[WAPP_TERM_COLOUR_FG_BR_BLACK] = wapp_str8_lit_ro_initialiser_list("\033[90m"),
|
||||
[WAPP_TERM_COLOUR_FG_BR_RED] = wapp_str8_lit_ro_initialiser_list("\033[91m"),
|
||||
[WAPP_TERM_COLOUR_FG_BR_GREEN] = wapp_str8_lit_ro_initialiser_list("\033[92m"),
|
||||
[WAPP_TERM_COLOUR_FG_BR_BLUE] = wapp_str8_lit_ro_initialiser_list("\033[94m"),
|
||||
[WAPP_TERM_COLOUR_FG_BR_CYAN] = wapp_str8_lit_ro_initialiser_list("\033[96m"),
|
||||
[WAPP_TERM_COLOUR_FG_BR_MAGENTA] = wapp_str8_lit_ro_initialiser_list("\033[95m"),
|
||||
[WAPP_TERM_COLOUR_FG_BR_YELLOW] = wapp_str8_lit_ro_initialiser_list("\033[93m"),
|
||||
[WAPP_TERM_COLOUR_FG_BR_WHITE] = wapp_str8_lit_ro_initialiser_list("\033[97m"),
|
||||
[WAPP_TERM_COLOUR_CLEAR] = wapp_str8_lit_ro_initialiser_list("\033[0m"),
|
||||
};
|
||||
|
||||
void print_coloured_text(Str8RO *text, TerminalColour colour) {
|
||||
printf(WAPP_STR8_SPEC WAPP_STR8_SPEC, wapp_str8_varg(colours[colour]), wapp_str8_varg((*text)));
|
||||
}
|
||||
|
||||
#endif // !WAPP_PLATFORM_POSIX
|
18
wapp/core/os/shell/termcolour/termcolour.c
Normal file
18
wapp/core/os/shell/termcolour/termcolour.c
Normal file
@ -0,0 +1,18 @@
|
||||
// vim:fileencoding=utf-8:foldmethod=marker
|
||||
|
||||
#include "termcolour.h"
|
||||
#include "terminal_colours.h"
|
||||
#include "../../../../primitives/strings/str8/str8.h"
|
||||
|
||||
void wapp_shell_termcolour_print_text(Str8RO *text, TerminalColour colour) {
|
||||
if (colour < WAPP_TERM_COLOUR_FG_BLACK || colour > WAPP_TERM_COLOUR_FG_BR_WHITE) {
|
||||
return;
|
||||
}
|
||||
|
||||
print_coloured_text(text, colour);
|
||||
}
|
||||
|
||||
void wapp_shell_termcolour_clear_colour(void) {
|
||||
Str8RO empty = wapp_str8_lit_ro("");
|
||||
print_coloured_text(&empty, WAPP_TERM_COLOUR_CLEAR);
|
||||
}
|
24
wapp/core/os/shell/termcolour/termcolour.h
Normal file
24
wapp/core/os/shell/termcolour/termcolour.h
Normal file
@ -0,0 +1,24 @@
|
||||
// vim:fileencoding=utf-8:foldmethod=marker
|
||||
|
||||
#ifndef TERM_COLOUR_H
|
||||
#define TERM_COLOUR_H
|
||||
|
||||
#include "terminal_colours.h"
|
||||
#include "../../../../common/aliases/aliases.h"
|
||||
#include "../../../../common/platform/platform.h"
|
||||
#include "../../../../primitives/strings/str8/str8.h"
|
||||
|
||||
#ifdef WAPP_PLATFORM_CPP
|
||||
BEGIN_C_LINKAGE
|
||||
#endif // !WAPP_PLATFORM_CPP
|
||||
|
||||
void wapp_shell_termcolour_print_text(Str8RO *text, TerminalColour colour);
|
||||
void wapp_shell_termcolour_clear_colour(void);
|
||||
|
||||
external void print_coloured_text(Str8RO *text, TerminalColour colour);
|
||||
|
||||
#ifdef WAPP_PLATFORM_CPP
|
||||
END_C_LINKAGE
|
||||
#endif // !WAPP_PLATFORM_CPP
|
||||
|
||||
#endif // !TERM_COLOUR_H
|
39
wapp/core/os/shell/termcolour/terminal_colours.h
Normal file
39
wapp/core/os/shell/termcolour/terminal_colours.h
Normal file
@ -0,0 +1,39 @@
|
||||
// vim:fileencoding=utf-8:foldmethod=marker
|
||||
|
||||
#ifndef TERMINAL_COLOURS_H
|
||||
#define TERMINAL_COLOURS_H
|
||||
|
||||
#include "../../../../common/aliases/aliases.h"
|
||||
#include "../../../../common/platform/platform.h"
|
||||
|
||||
#ifdef WAPP_PLATFORM_CPP
|
||||
BEGIN_C_LINKAGE
|
||||
#endif // !WAPP_PLATFORM_CPP
|
||||
|
||||
typedef enum {
|
||||
WAPP_TERM_COLOUR_FG_BLACK,
|
||||
WAPP_TERM_COLOUR_FG_RED,
|
||||
WAPP_TERM_COLOUR_FG_GREEN,
|
||||
WAPP_TERM_COLOUR_FG_BLUE,
|
||||
WAPP_TERM_COLOUR_FG_CYAN,
|
||||
WAPP_TERM_COLOUR_FG_MAGENTA,
|
||||
WAPP_TERM_COLOUR_FG_YELLOW,
|
||||
WAPP_TERM_COLOUR_FG_WHITE,
|
||||
WAPP_TERM_COLOUR_FG_BR_BLACK,
|
||||
WAPP_TERM_COLOUR_FG_BR_RED,
|
||||
WAPP_TERM_COLOUR_FG_BR_GREEN,
|
||||
WAPP_TERM_COLOUR_FG_BR_BLUE,
|
||||
WAPP_TERM_COLOUR_FG_BR_CYAN,
|
||||
WAPP_TERM_COLOUR_FG_BR_MAGENTA,
|
||||
WAPP_TERM_COLOUR_FG_BR_YELLOW,
|
||||
WAPP_TERM_COLOUR_FG_BR_WHITE,
|
||||
WAPP_TERM_COLOUR_CLEAR,
|
||||
|
||||
COUNT_TERM_COLOUR,
|
||||
} TerminalColour;
|
||||
|
||||
#ifdef WAPP_PLATFORM_CPP
|
||||
END_C_LINKAGE
|
||||
#endif // !WAPP_PLATFORM_CPP
|
||||
|
||||
#endif // !TERMINAL_COLOURS_H
|
73
wapp/core/os/shell/termcolour/win/termcolour_win.c
Normal file
73
wapp/core/os/shell/termcolour/win/termcolour_win.c
Normal file
@ -0,0 +1,73 @@
|
||||
// vim:fileencoding=utf-8:foldmethod=marker
|
||||
|
||||
#include "../../../../../common/aliases/aliases.h"
|
||||
#include "../../../../../common/platform/platform.h"
|
||||
#include "../../../../../primitives/strings/str8/str8.h"
|
||||
|
||||
#ifdef WAPP_PLATFORM_WINDOWS
|
||||
|
||||
#include "../terminal_colours.h"
|
||||
#include "../../../../../common/misc/misc_utils.h"
|
||||
#include <stdio.h>
|
||||
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <Windows.h>
|
||||
|
||||
typedef struct termcolour_data TermcolourData;
|
||||
struct termcolour_data {
|
||||
HANDLE handle;
|
||||
WORD default_colour;
|
||||
WORD current_colour;
|
||||
|
||||
wapp_misc_utils_padding_size(sizeof(HANDLE) + sizeof(WORD) + sizeof(WORD));
|
||||
};
|
||||
|
||||
internal void init_data(TermcolourData *data);
|
||||
|
||||
internal WORD colours[COUNT_TERM_COLOUR] = {
|
||||
[WAPP_TERM_COLOUR_FG_BLACK] = 0,
|
||||
[WAPP_TERM_COLOUR_FG_RED] = FOREGROUND_RED,
|
||||
[WAPP_TERM_COLOUR_FG_GREEN] = FOREGROUND_GREEN,
|
||||
[WAPP_TERM_COLOUR_FG_BLUE] = FOREGROUND_BLUE,
|
||||
[WAPP_TERM_COLOUR_FG_CYAN] = FOREGROUND_GREEN | FOREGROUND_BLUE,
|
||||
[WAPP_TERM_COLOUR_FG_MAGENTA] = FOREGROUND_RED | FOREGROUND_BLUE,
|
||||
[WAPP_TERM_COLOUR_FG_YELLOW] = FOREGROUND_RED | FOREGROUND_GREEN,
|
||||
[WAPP_TERM_COLOUR_FG_WHITE] = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE,
|
||||
[WAPP_TERM_COLOUR_FG_BR_BLACK] = FOREGROUND_INTENSITY,
|
||||
[WAPP_TERM_COLOUR_FG_BR_RED] = FOREGROUND_RED | FOREGROUND_INTENSITY,
|
||||
[WAPP_TERM_COLOUR_FG_BR_GREEN] = FOREGROUND_GREEN | FOREGROUND_INTENSITY,
|
||||
[WAPP_TERM_COLOUR_FG_BR_BLUE] = FOREGROUND_BLUE | FOREGROUND_INTENSITY,
|
||||
[WAPP_TERM_COLOUR_FG_BR_CYAN] = FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY,
|
||||
[WAPP_TERM_COLOUR_FG_BR_MAGENTA] = FOREGROUND_RED | FOREGROUND_BLUE | FOREGROUND_INTENSITY,
|
||||
[WAPP_TERM_COLOUR_FG_BR_YELLOW] = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_INTENSITY,
|
||||
[WAPP_TERM_COLOUR_FG_BR_WHITE] = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY,
|
||||
};
|
||||
|
||||
void print_coloured_text(Str8RO *text, TerminalColour colour) {
|
||||
persistent TermcolourData data = {0};
|
||||
if (data.handle == 0) {
|
||||
init_data(&data);
|
||||
}
|
||||
|
||||
if (colour == WAPP_TERM_COLOUR_CLEAR) {
|
||||
data.current_colour = data.default_colour;
|
||||
} else {
|
||||
data.current_colour = colours[colour];
|
||||
}
|
||||
|
||||
SetConsoleTextAttribute(data.handle, data.current_colour);
|
||||
printf(WAPP_STR8_SPEC, wapp_str8_varg((*text)));
|
||||
}
|
||||
|
||||
internal void init_data(TermcolourData *data) {
|
||||
// create handle
|
||||
data->handle = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||
|
||||
// get console colour information
|
||||
CONSOLE_SCREEN_BUFFER_INFO csbi;
|
||||
GetConsoleScreenBufferInfo(data->handle, &csbi);
|
||||
data->default_colour = csbi.wAttributes;
|
||||
data->current_colour = data->default_colour;
|
||||
}
|
||||
|
||||
#endif // !WAPP_PLATFORM_WINDOWS
|
26
wapp/core/os/shell/utils/shell_utils.h
Normal file
26
wapp/core/os/shell/utils/shell_utils.h
Normal file
@ -0,0 +1,26 @@
|
||||
// vim:fileencoding=utf-8:foldmethod=marker
|
||||
|
||||
#ifndef SHELL_UTILS_H
|
||||
#define SHELL_UTILS_H
|
||||
|
||||
#include "../../../../common/aliases/aliases.h"
|
||||
#include "../../../../common/platform/platform.h"
|
||||
#include <stdio.h>
|
||||
|
||||
#ifdef WAPP_PLATFORM_CPP
|
||||
BEGIN_C_LINKAGE
|
||||
#endif // !WAPP_PLATFORM_CPP
|
||||
|
||||
#ifdef WAPP_PLATFORM_WINDOWS
|
||||
#define wapp_shell_utils_popen _popen
|
||||
#define wapp_shell_utils_pclose _pclose
|
||||
#else
|
||||
#define wapp_shell_utils_popen popen
|
||||
#define wapp_shell_utils_pclose pclose
|
||||
#endif /* ifdef WAPP_PLATFORM_WINDOWS */
|
||||
|
||||
#ifdef WAPP_PLATFORM_CPP
|
||||
END_C_LINKAGE
|
||||
#endif // !WAPP_PLATFORM_CPP
|
||||
|
||||
#endif // !SHELL_UTILS_H
|
22
wapp/core/wapp_core.c
Normal file
22
wapp/core/wapp_core.c
Normal file
@ -0,0 +1,22 @@
|
||||
// vim:fileencoding=utf-8:foldmethod=marker
|
||||
|
||||
#ifndef WAPP_CORE_C
|
||||
#define WAPP_CORE_C
|
||||
|
||||
#include "wapp_core.h"
|
||||
#include "os/shell/termcolour/posix/termcolour_posix.c"
|
||||
#include "os/shell/termcolour/win/termcolour_win.c"
|
||||
#include "os/shell/termcolour/termcolour.c"
|
||||
#include "os/shell/commander/posix/commander_posix.c"
|
||||
#include "os/shell/commander/win/commander_win.c"
|
||||
#include "os/shell/commander/commander.c"
|
||||
#include "os/cpath/cpath.c"
|
||||
#include "os/mem/posix/mem_os_posix.c"
|
||||
#include "os/mem/win/mem_os_win.c"
|
||||
#include "os/mem/mem_os.c"
|
||||
#include "mem/utils/mem_utils.c"
|
||||
#include "mem/arena/mem_arena.c"
|
||||
#include "mem/arena/mem_arena_allocator.c"
|
||||
#include "../primitives/wapp_primitives.c"
|
||||
|
||||
#endif // !WAPP_CORE_C
|
22
wapp/core/wapp_core.h
Normal file
22
wapp/core/wapp_core.h
Normal file
@ -0,0 +1,22 @@
|
||||
// vim:fileencoding=utf-8:foldmethod=marker
|
||||
|
||||
#ifndef WAPP_CORE_H
|
||||
#define WAPP_CORE_H
|
||||
|
||||
#include "os/shell/termcolour/termcolour.h"
|
||||
#include "os/shell/termcolour/terminal_colours.h"
|
||||
#include "os/shell/commander/commander.h"
|
||||
#include "os/shell/commander/commander_output.h"
|
||||
#include "os/shell/utils/shell_utils.h"
|
||||
#include "os/cpath/cpath.h"
|
||||
#include "os/mem/posix/mem_os_posix.h"
|
||||
#include "os/mem/win/mem_os_win.h"
|
||||
#include "os/mem/mem_os_ops.h"
|
||||
#include "os/mem/mem_os.h"
|
||||
#include "mem/utils/mem_utils.h"
|
||||
#include "mem/arena/mem_arena_allocator.h"
|
||||
#include "mem/arena/mem_arena.h"
|
||||
#include "../common/wapp_common.h"
|
||||
#include "../primitives/wapp_primitives.h"
|
||||
|
||||
#endif // !WAPP_CORE_H
|
3011
wapp/primitives/array/array.c
Normal file
3011
wapp/primitives/array/array.c
Normal file
File diff suppressed because it is too large
Load Diff
971
wapp/primitives/array/array.h
Normal file
971
wapp/primitives/array/array.h
Normal file
@ -0,0 +1,971 @@
|
||||
/**
|
||||
* THIS FILE IS AUTOMATICALLY GENERATED. ANY MODIFICATIONS TO IT WILL BE OVERWRITTEN
|
||||
*/
|
||||
|
||||
#ifndef ARRAY_H
|
||||
#define ARRAY_H
|
||||
|
||||
#include "../../common/aliases/aliases.h"
|
||||
#include "../mem_allocator/mem_allocator.h"
|
||||
#include "../../common/misc/misc_utils.h"
|
||||
#include "../../common/aliases/aliases.h"
|
||||
#include "../../common/platform/platform.h"
|
||||
|
||||
#ifdef WAPP_PLATFORM_CPP
|
||||
BEGIN_C_LINKAGE
|
||||
#endif // !WAPP_PLATFORM_CPP
|
||||
|
||||
#define wapp_str8_array_alloc_capacity(ALLOCATOR_PTR, CAPACITY) ((Str8Array *)_array_alloc_capacity(ALLOCATOR_PTR, CAPACITY, sizeof(Str8)))
|
||||
#define wapp_void_ptr_array_alloc_capacity(ALLOCATOR_PTR, CAPACITY) ((VoidPArray *)_array_alloc_capacity(ALLOCATOR_PTR, CAPACITY, sizeof(void *)))
|
||||
#define wapp_b32_array_alloc_capacity(ALLOCATOR_PTR, CAPACITY) ((B32Array *)_array_alloc_capacity(ALLOCATOR_PTR, CAPACITY, sizeof(b32)))
|
||||
#define wapp_char_array_alloc_capacity(ALLOCATOR_PTR, CAPACITY) ((CharArray *)_array_alloc_capacity(ALLOCATOR_PTR, CAPACITY, sizeof(char)))
|
||||
#define wapp_c8_array_alloc_capacity(ALLOCATOR_PTR, CAPACITY) ((C8Array *)_array_alloc_capacity(ALLOCATOR_PTR, CAPACITY, sizeof(c8)))
|
||||
#define wapp_c16_array_alloc_capacity(ALLOCATOR_PTR, CAPACITY) ((C16Array *)_array_alloc_capacity(ALLOCATOR_PTR, CAPACITY, sizeof(c16)))
|
||||
#define wapp_c32_array_alloc_capacity(ALLOCATOR_PTR, CAPACITY) ((C32Array *)_array_alloc_capacity(ALLOCATOR_PTR, CAPACITY, sizeof(c32)))
|
||||
#define wapp_i8_array_alloc_capacity(ALLOCATOR_PTR, CAPACITY) ((I8Array *)_array_alloc_capacity(ALLOCATOR_PTR, CAPACITY, sizeof(i8)))
|
||||
#define wapp_i16_array_alloc_capacity(ALLOCATOR_PTR, CAPACITY) ((I16Array *)_array_alloc_capacity(ALLOCATOR_PTR, CAPACITY, sizeof(i16)))
|
||||
#define wapp_i32_array_alloc_capacity(ALLOCATOR_PTR, CAPACITY) ((I32Array *)_array_alloc_capacity(ALLOCATOR_PTR, CAPACITY, sizeof(i32)))
|
||||
#define wapp_i64_array_alloc_capacity(ALLOCATOR_PTR, CAPACITY) ((I64Array *)_array_alloc_capacity(ALLOCATOR_PTR, CAPACITY, sizeof(i64)))
|
||||
#define wapp_u8_array_alloc_capacity(ALLOCATOR_PTR, CAPACITY) ((U8Array *)_array_alloc_capacity(ALLOCATOR_PTR, CAPACITY, sizeof(u8)))
|
||||
#define wapp_u16_array_alloc_capacity(ALLOCATOR_PTR, CAPACITY) ((U16Array *)_array_alloc_capacity(ALLOCATOR_PTR, CAPACITY, sizeof(u16)))
|
||||
#define wapp_u32_array_alloc_capacity(ALLOCATOR_PTR, CAPACITY) ((U32Array *)_array_alloc_capacity(ALLOCATOR_PTR, CAPACITY, sizeof(u32)))
|
||||
#define wapp_u64_array_alloc_capacity(ALLOCATOR_PTR, CAPACITY) ((U64Array *)_array_alloc_capacity(ALLOCATOR_PTR, CAPACITY, sizeof(u64)))
|
||||
#define wapp_f32_array_alloc_capacity(ALLOCATOR_PTR, CAPACITY) ((F32Array *)_array_alloc_capacity(ALLOCATOR_PTR, CAPACITY, sizeof(f32)))
|
||||
#define wapp_f64_array_alloc_capacity(ALLOCATOR_PTR, CAPACITY) ((F64Array *)_array_alloc_capacity(ALLOCATOR_PTR, CAPACITY, sizeof(f64)))
|
||||
#define wapp_f128_array_alloc_capacity(ALLOCATOR_PTR, CAPACITY) ((F128Array *)_array_alloc_capacity(ALLOCATOR_PTR, CAPACITY, sizeof(f128)))
|
||||
#define wapp_iptr_array_alloc_capacity(ALLOCATOR_PTR, CAPACITY) ((IptrArray *)_array_alloc_capacity(ALLOCATOR_PTR, CAPACITY, sizeof(iptr)))
|
||||
#define wapp_uptr_array_alloc_capacity(ALLOCATOR_PTR, CAPACITY) ((UptrArray *)_array_alloc_capacity(ALLOCATOR_PTR, CAPACITY, sizeof(uptr)))
|
||||
|
||||
#ifdef WAPP_PLATFORM_CPP
|
||||
#define wapp_str8_array(...) ([&]() { \
|
||||
persistent Str8 buf[wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count(Str8, __VA_ARGS__) * 2)] = {__VA_ARGS__}; \
|
||||
return Str8Array{ \
|
||||
buf, \
|
||||
wapp_misc_utils_va_args_count(Str8, __VA_ARGS__), \
|
||||
wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count(Str8, __VA_ARGS__) * 2), \
|
||||
sizeof(Str8) \
|
||||
}; \
|
||||
}())
|
||||
#define wapp_str8_array_with_capacity(CAPACITY) ([&]() { \
|
||||
persistent Str8 buf[CAPACITY] = {}; \
|
||||
return Str8Array{buf, 0, CAPACITY, sizeof(Str8)}; \
|
||||
}())
|
||||
#define wapp_str8_array_pop(ARRAY_PTR) (ARRAY_PTR != NULL && (ARRAY_PTR)->count > 0 ? \
|
||||
*_str8_array_pop(ARRAY_PTR) : \
|
||||
Str8{} \
|
||||
)
|
||||
#define wapp_void_ptr_array(...) ([&]() { \
|
||||
persistent void * buf[wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count(void *, __VA_ARGS__) * 2)] = {__VA_ARGS__}; \
|
||||
return VoidPArray{ \
|
||||
buf, \
|
||||
wapp_misc_utils_va_args_count(void *, __VA_ARGS__), \
|
||||
wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count(void *, __VA_ARGS__) * 2), \
|
||||
sizeof(void *) \
|
||||
}; \
|
||||
}())
|
||||
#define wapp_void_ptr_array_with_capacity(CAPACITY) ([&]() { \
|
||||
persistent void * buf[CAPACITY] = {}; \
|
||||
return VoidPArray{buf, 0, CAPACITY, sizeof(void *)}; \
|
||||
}())
|
||||
#define wapp_void_ptr_array_pop(ARRAY_PTR) (ARRAY_PTR != NULL && (ARRAY_PTR)->count > 0 ? \
|
||||
*_void_ptr_array_pop(ARRAY_PTR) : \
|
||||
void *{} \
|
||||
)
|
||||
#define wapp_b32_array(...) ([&]() { \
|
||||
persistent b32 buf[wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count(b32, __VA_ARGS__) * 2)] = {__VA_ARGS__}; \
|
||||
return B32Array{ \
|
||||
buf, \
|
||||
wapp_misc_utils_va_args_count(b32, __VA_ARGS__), \
|
||||
wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count(b32, __VA_ARGS__) * 2), \
|
||||
sizeof(b32) \
|
||||
}; \
|
||||
}())
|
||||
#define wapp_b32_array_with_capacity(CAPACITY) ([&]() { \
|
||||
persistent b32 buf[CAPACITY] = {}; \
|
||||
return B32Array{buf, 0, CAPACITY, sizeof(b32)}; \
|
||||
}())
|
||||
#define wapp_b32_array_pop(ARRAY_PTR) (ARRAY_PTR != NULL && (ARRAY_PTR)->count > 0 ? \
|
||||
*_b32_array_pop(ARRAY_PTR) : \
|
||||
b32{} \
|
||||
)
|
||||
#define wapp_char_array(...) ([&]() { \
|
||||
persistent char buf[wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count(char, __VA_ARGS__) * 2)] = {__VA_ARGS__}; \
|
||||
return CharArray{ \
|
||||
buf, \
|
||||
wapp_misc_utils_va_args_count(char, __VA_ARGS__), \
|
||||
wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count(char, __VA_ARGS__) * 2), \
|
||||
sizeof(char) \
|
||||
}; \
|
||||
}())
|
||||
#define wapp_char_array_with_capacity(CAPACITY) ([&]() { \
|
||||
persistent char buf[CAPACITY] = {}; \
|
||||
return CharArray{buf, 0, CAPACITY, sizeof(char)}; \
|
||||
}())
|
||||
#define wapp_char_array_pop(ARRAY_PTR) (ARRAY_PTR != NULL && (ARRAY_PTR)->count > 0 ? \
|
||||
*_char_array_pop(ARRAY_PTR) : \
|
||||
char{} \
|
||||
)
|
||||
#define wapp_c8_array(...) ([&]() { \
|
||||
persistent c8 buf[wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count(c8, __VA_ARGS__) * 2)] = {__VA_ARGS__}; \
|
||||
return C8Array{ \
|
||||
buf, \
|
||||
wapp_misc_utils_va_args_count(c8, __VA_ARGS__), \
|
||||
wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count(c8, __VA_ARGS__) * 2), \
|
||||
sizeof(c8) \
|
||||
}; \
|
||||
}())
|
||||
#define wapp_c8_array_with_capacity(CAPACITY) ([&]() { \
|
||||
persistent c8 buf[CAPACITY] = {}; \
|
||||
return C8Array{buf, 0, CAPACITY, sizeof(c8)}; \
|
||||
}())
|
||||
#define wapp_c8_array_pop(ARRAY_PTR) (ARRAY_PTR != NULL && (ARRAY_PTR)->count > 0 ? \
|
||||
*_c8_array_pop(ARRAY_PTR) : \
|
||||
c8{} \
|
||||
)
|
||||
#define wapp_c16_array(...) ([&]() { \
|
||||
persistent c16 buf[wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count(c16, __VA_ARGS__) * 2)] = {__VA_ARGS__}; \
|
||||
return C16Array{ \
|
||||
buf, \
|
||||
wapp_misc_utils_va_args_count(c16, __VA_ARGS__), \
|
||||
wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count(c16, __VA_ARGS__) * 2), \
|
||||
sizeof(c16) \
|
||||
}; \
|
||||
}())
|
||||
#define wapp_c16_array_with_capacity(CAPACITY) ([&]() { \
|
||||
persistent c16 buf[CAPACITY] = {}; \
|
||||
return C16Array{buf, 0, CAPACITY, sizeof(c16)}; \
|
||||
}())
|
||||
#define wapp_c16_array_pop(ARRAY_PTR) (ARRAY_PTR != NULL && (ARRAY_PTR)->count > 0 ? \
|
||||
*_c16_array_pop(ARRAY_PTR) : \
|
||||
c16{} \
|
||||
)
|
||||
#define wapp_c32_array(...) ([&]() { \
|
||||
persistent c32 buf[wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count(c32, __VA_ARGS__) * 2)] = {__VA_ARGS__}; \
|
||||
return C32Array{ \
|
||||
buf, \
|
||||
wapp_misc_utils_va_args_count(c32, __VA_ARGS__), \
|
||||
wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count(c32, __VA_ARGS__) * 2), \
|
||||
sizeof(c32) \
|
||||
}; \
|
||||
}())
|
||||
#define wapp_c32_array_with_capacity(CAPACITY) ([&]() { \
|
||||
persistent c32 buf[CAPACITY] = {}; \
|
||||
return C32Array{buf, 0, CAPACITY, sizeof(c32)}; \
|
||||
}())
|
||||
#define wapp_c32_array_pop(ARRAY_PTR) (ARRAY_PTR != NULL && (ARRAY_PTR)->count > 0 ? \
|
||||
*_c32_array_pop(ARRAY_PTR) : \
|
||||
c32{} \
|
||||
)
|
||||
#define wapp_i8_array(...) ([&]() { \
|
||||
persistent i8 buf[wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count(i8, __VA_ARGS__) * 2)] = {__VA_ARGS__}; \
|
||||
return I8Array{ \
|
||||
buf, \
|
||||
wapp_misc_utils_va_args_count(i8, __VA_ARGS__), \
|
||||
wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count(i8, __VA_ARGS__) * 2), \
|
||||
sizeof(i8) \
|
||||
}; \
|
||||
}())
|
||||
#define wapp_i8_array_with_capacity(CAPACITY) ([&]() { \
|
||||
persistent i8 buf[CAPACITY] = {}; \
|
||||
return I8Array{buf, 0, CAPACITY, sizeof(i8)}; \
|
||||
}())
|
||||
#define wapp_i8_array_pop(ARRAY_PTR) (ARRAY_PTR != NULL && (ARRAY_PTR)->count > 0 ? \
|
||||
*_i8_array_pop(ARRAY_PTR) : \
|
||||
i8{} \
|
||||
)
|
||||
#define wapp_i16_array(...) ([&]() { \
|
||||
persistent i16 buf[wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count(i16, __VA_ARGS__) * 2)] = {__VA_ARGS__}; \
|
||||
return I16Array{ \
|
||||
buf, \
|
||||
wapp_misc_utils_va_args_count(i16, __VA_ARGS__), \
|
||||
wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count(i16, __VA_ARGS__) * 2), \
|
||||
sizeof(i16) \
|
||||
}; \
|
||||
}())
|
||||
#define wapp_i16_array_with_capacity(CAPACITY) ([&]() { \
|
||||
persistent i16 buf[CAPACITY] = {}; \
|
||||
return I16Array{buf, 0, CAPACITY, sizeof(i16)}; \
|
||||
}())
|
||||
#define wapp_i16_array_pop(ARRAY_PTR) (ARRAY_PTR != NULL && (ARRAY_PTR)->count > 0 ? \
|
||||
*_i16_array_pop(ARRAY_PTR) : \
|
||||
i16{} \
|
||||
)
|
||||
#define wapp_i32_array(...) ([&]() { \
|
||||
persistent i32 buf[wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count(i32, __VA_ARGS__) * 2)] = {__VA_ARGS__}; \
|
||||
return I32Array{ \
|
||||
buf, \
|
||||
wapp_misc_utils_va_args_count(i32, __VA_ARGS__), \
|
||||
wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count(i32, __VA_ARGS__) * 2), \
|
||||
sizeof(i32) \
|
||||
}; \
|
||||
}())
|
||||
#define wapp_i32_array_with_capacity(CAPACITY) ([&]() { \
|
||||
persistent i32 buf[CAPACITY] = {}; \
|
||||
return I32Array{buf, 0, CAPACITY, sizeof(i32)}; \
|
||||
}())
|
||||
#define wapp_i32_array_pop(ARRAY_PTR) (ARRAY_PTR != NULL && (ARRAY_PTR)->count > 0 ? \
|
||||
*_i32_array_pop(ARRAY_PTR) : \
|
||||
i32{} \
|
||||
)
|
||||
#define wapp_i64_array(...) ([&]() { \
|
||||
persistent i64 buf[wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count(i64, __VA_ARGS__) * 2)] = {__VA_ARGS__}; \
|
||||
return I64Array{ \
|
||||
buf, \
|
||||
wapp_misc_utils_va_args_count(i64, __VA_ARGS__), \
|
||||
wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count(i64, __VA_ARGS__) * 2), \
|
||||
sizeof(i64) \
|
||||
}; \
|
||||
}())
|
||||
#define wapp_i64_array_with_capacity(CAPACITY) ([&]() { \
|
||||
persistent i64 buf[CAPACITY] = {}; \
|
||||
return I64Array{buf, 0, CAPACITY, sizeof(i64)}; \
|
||||
}())
|
||||
#define wapp_i64_array_pop(ARRAY_PTR) (ARRAY_PTR != NULL && (ARRAY_PTR)->count > 0 ? \
|
||||
*_i64_array_pop(ARRAY_PTR) : \
|
||||
i64{} \
|
||||
)
|
||||
#define wapp_u8_array(...) ([&]() { \
|
||||
persistent u8 buf[wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count(u8, __VA_ARGS__) * 2)] = {__VA_ARGS__}; \
|
||||
return U8Array{ \
|
||||
buf, \
|
||||
wapp_misc_utils_va_args_count(u8, __VA_ARGS__), \
|
||||
wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count(u8, __VA_ARGS__) * 2), \
|
||||
sizeof(u8) \
|
||||
}; \
|
||||
}())
|
||||
#define wapp_u8_array_with_capacity(CAPACITY) ([&]() { \
|
||||
persistent u8 buf[CAPACITY] = {}; \
|
||||
return U8Array{buf, 0, CAPACITY, sizeof(u8)}; \
|
||||
}())
|
||||
#define wapp_u8_array_pop(ARRAY_PTR) (ARRAY_PTR != NULL && (ARRAY_PTR)->count > 0 ? \
|
||||
*_u8_array_pop(ARRAY_PTR) : \
|
||||
u8{} \
|
||||
)
|
||||
#define wapp_u16_array(...) ([&]() { \
|
||||
persistent u16 buf[wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count(u16, __VA_ARGS__) * 2)] = {__VA_ARGS__}; \
|
||||
return U16Array{ \
|
||||
buf, \
|
||||
wapp_misc_utils_va_args_count(u16, __VA_ARGS__), \
|
||||
wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count(u16, __VA_ARGS__) * 2), \
|
||||
sizeof(u16) \
|
||||
}; \
|
||||
}())
|
||||
#define wapp_u16_array_with_capacity(CAPACITY) ([&]() { \
|
||||
persistent u16 buf[CAPACITY] = {}; \
|
||||
return U16Array{buf, 0, CAPACITY, sizeof(u16)}; \
|
||||
}())
|
||||
#define wapp_u16_array_pop(ARRAY_PTR) (ARRAY_PTR != NULL && (ARRAY_PTR)->count > 0 ? \
|
||||
*_u16_array_pop(ARRAY_PTR) : \
|
||||
u16{} \
|
||||
)
|
||||
#define wapp_u32_array(...) ([&]() { \
|
||||
persistent u32 buf[wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count(u32, __VA_ARGS__) * 2)] = {__VA_ARGS__}; \
|
||||
return U32Array{ \
|
||||
buf, \
|
||||
wapp_misc_utils_va_args_count(u32, __VA_ARGS__), \
|
||||
wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count(u32, __VA_ARGS__) * 2), \
|
||||
sizeof(u32) \
|
||||
}; \
|
||||
}())
|
||||
#define wapp_u32_array_with_capacity(CAPACITY) ([&]() { \
|
||||
persistent u32 buf[CAPACITY] = {}; \
|
||||
return U32Array{buf, 0, CAPACITY, sizeof(u32)}; \
|
||||
}())
|
||||
#define wapp_u32_array_pop(ARRAY_PTR) (ARRAY_PTR != NULL && (ARRAY_PTR)->count > 0 ? \
|
||||
*_u32_array_pop(ARRAY_PTR) : \
|
||||
u32{} \
|
||||
)
|
||||
#define wapp_u64_array(...) ([&]() { \
|
||||
persistent u64 buf[wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count(u64, __VA_ARGS__) * 2)] = {__VA_ARGS__}; \
|
||||
return U64Array{ \
|
||||
buf, \
|
||||
wapp_misc_utils_va_args_count(u64, __VA_ARGS__), \
|
||||
wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count(u64, __VA_ARGS__) * 2), \
|
||||
sizeof(u64) \
|
||||
}; \
|
||||
}())
|
||||
#define wapp_u64_array_with_capacity(CAPACITY) ([&]() { \
|
||||
persistent u64 buf[CAPACITY] = {}; \
|
||||
return U64Array{buf, 0, CAPACITY, sizeof(u64)}; \
|
||||
}())
|
||||
#define wapp_u64_array_pop(ARRAY_PTR) (ARRAY_PTR != NULL && (ARRAY_PTR)->count > 0 ? \
|
||||
*_u64_array_pop(ARRAY_PTR) : \
|
||||
u64{} \
|
||||
)
|
||||
#define wapp_f32_array(...) ([&]() { \
|
||||
persistent f32 buf[wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count(f32, __VA_ARGS__) * 2)] = {__VA_ARGS__}; \
|
||||
return F32Array{ \
|
||||
buf, \
|
||||
wapp_misc_utils_va_args_count(f32, __VA_ARGS__), \
|
||||
wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count(f32, __VA_ARGS__) * 2), \
|
||||
sizeof(f32) \
|
||||
}; \
|
||||
}())
|
||||
#define wapp_f32_array_with_capacity(CAPACITY) ([&]() { \
|
||||
persistent f32 buf[CAPACITY] = {}; \
|
||||
return F32Array{buf, 0, CAPACITY, sizeof(f32)}; \
|
||||
}())
|
||||
#define wapp_f32_array_pop(ARRAY_PTR) (ARRAY_PTR != NULL && (ARRAY_PTR)->count > 0 ? \
|
||||
*_f32_array_pop(ARRAY_PTR) : \
|
||||
f32{} \
|
||||
)
|
||||
#define wapp_f64_array(...) ([&]() { \
|
||||
persistent f64 buf[wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count(f64, __VA_ARGS__) * 2)] = {__VA_ARGS__}; \
|
||||
return F64Array{ \
|
||||
buf, \
|
||||
wapp_misc_utils_va_args_count(f64, __VA_ARGS__), \
|
||||
wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count(f64, __VA_ARGS__) * 2), \
|
||||
sizeof(f64) \
|
||||
}; \
|
||||
}())
|
||||
#define wapp_f64_array_with_capacity(CAPACITY) ([&]() { \
|
||||
persistent f64 buf[CAPACITY] = {}; \
|
||||
return F64Array{buf, 0, CAPACITY, sizeof(f64)}; \
|
||||
}())
|
||||
#define wapp_f64_array_pop(ARRAY_PTR) (ARRAY_PTR != NULL && (ARRAY_PTR)->count > 0 ? \
|
||||
*_f64_array_pop(ARRAY_PTR) : \
|
||||
f64{} \
|
||||
)
|
||||
#define wapp_f128_array(...) ([&]() { \
|
||||
persistent f128 buf[wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count(f128, __VA_ARGS__) * 2)] = {__VA_ARGS__}; \
|
||||
return F128Array{ \
|
||||
buf, \
|
||||
wapp_misc_utils_va_args_count(f128, __VA_ARGS__), \
|
||||
wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count(f128, __VA_ARGS__) * 2), \
|
||||
sizeof(f128) \
|
||||
}; \
|
||||
}())
|
||||
#define wapp_f128_array_with_capacity(CAPACITY) ([&]() { \
|
||||
persistent f128 buf[CAPACITY] = {}; \
|
||||
return F128Array{buf, 0, CAPACITY, sizeof(f128)}; \
|
||||
}())
|
||||
#define wapp_f128_array_pop(ARRAY_PTR) (ARRAY_PTR != NULL && (ARRAY_PTR)->count > 0 ? \
|
||||
*_f128_array_pop(ARRAY_PTR) : \
|
||||
f128{} \
|
||||
)
|
||||
#define wapp_iptr_array(...) ([&]() { \
|
||||
persistent iptr buf[wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count(iptr, __VA_ARGS__) * 2)] = {__VA_ARGS__}; \
|
||||
return IptrArray{ \
|
||||
buf, \
|
||||
wapp_misc_utils_va_args_count(iptr, __VA_ARGS__), \
|
||||
wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count(iptr, __VA_ARGS__) * 2), \
|
||||
sizeof(iptr) \
|
||||
}; \
|
||||
}())
|
||||
#define wapp_iptr_array_with_capacity(CAPACITY) ([&]() { \
|
||||
persistent iptr buf[CAPACITY] = {}; \
|
||||
return IptrArray{buf, 0, CAPACITY, sizeof(iptr)}; \
|
||||
}())
|
||||
#define wapp_iptr_array_pop(ARRAY_PTR) (ARRAY_PTR != NULL && (ARRAY_PTR)->count > 0 ? \
|
||||
*_iptr_array_pop(ARRAY_PTR) : \
|
||||
iptr{} \
|
||||
)
|
||||
#define wapp_uptr_array(...) ([&]() { \
|
||||
persistent uptr buf[wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count(uptr, __VA_ARGS__) * 2)] = {__VA_ARGS__}; \
|
||||
return UptrArray{ \
|
||||
buf, \
|
||||
wapp_misc_utils_va_args_count(uptr, __VA_ARGS__), \
|
||||
wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count(uptr, __VA_ARGS__) * 2), \
|
||||
sizeof(uptr) \
|
||||
}; \
|
||||
}())
|
||||
#define wapp_uptr_array_with_capacity(CAPACITY) ([&]() { \
|
||||
persistent uptr buf[CAPACITY] = {}; \
|
||||
return UptrArray{buf, 0, CAPACITY, sizeof(uptr)}; \
|
||||
}())
|
||||
#define wapp_uptr_array_pop(ARRAY_PTR) (ARRAY_PTR != NULL && (ARRAY_PTR)->count > 0 ? \
|
||||
*_uptr_array_pop(ARRAY_PTR) : \
|
||||
uptr{} \
|
||||
)
|
||||
#else
|
||||
#define wapp_str8_array(...) ((Str8Array){ \
|
||||
.items = (Str8[wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count(Str8, __VA_ARGS__) * 2)]){__VA_ARGS__}, \
|
||||
.count = wapp_misc_utils_va_args_count(Str8, __VA_ARGS__), \
|
||||
.capacity = wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count(Str8, __VA_ARGS__) * 2), \
|
||||
.item_size = sizeof(Str8) \
|
||||
})
|
||||
#define wapp_str8_array_with_capacity(CAPACITY) ((Str8Array){.items = (Str8[CAPACITY]){0}, .count = 0, .capacity = CAPACITY, .item_size = sizeof(Str8)})
|
||||
#define wapp_str8_array_pop(ARRAY_PTR) (ARRAY_PTR != NULL && (ARRAY_PTR)->count > 0 ? \
|
||||
*_str8_array_pop(ARRAY_PTR) : \
|
||||
(Str8){0} \
|
||||
)
|
||||
#define wapp_void_ptr_array(...) ((VoidPArray){ \
|
||||
.items = (void *[wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count(void *, __VA_ARGS__) * 2)]){__VA_ARGS__}, \
|
||||
.count = wapp_misc_utils_va_args_count(void *, __VA_ARGS__), \
|
||||
.capacity = wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count(void *, __VA_ARGS__) * 2), \
|
||||
.item_size = sizeof(void *) \
|
||||
})
|
||||
#define wapp_void_ptr_array_with_capacity(CAPACITY) ((VoidPArray){.items = (void *[CAPACITY]){0}, .count = 0, .capacity = CAPACITY, .item_size = sizeof(void *)})
|
||||
#define wapp_void_ptr_array_pop(ARRAY_PTR) (ARRAY_PTR != NULL && (ARRAY_PTR)->count > 0 ? \
|
||||
*_void_ptr_array_pop(ARRAY_PTR) : \
|
||||
(void *){0} \
|
||||
)
|
||||
#define wapp_b32_array(...) ((B32Array){ \
|
||||
.items = (b32[wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count(b32, __VA_ARGS__) * 2)]){__VA_ARGS__}, \
|
||||
.count = wapp_misc_utils_va_args_count(b32, __VA_ARGS__), \
|
||||
.capacity = wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count(b32, __VA_ARGS__) * 2), \
|
||||
.item_size = sizeof(b32) \
|
||||
})
|
||||
#define wapp_b32_array_with_capacity(CAPACITY) ((B32Array){.items = (b32[CAPACITY]){0}, .count = 0, .capacity = CAPACITY, .item_size = sizeof(b32)})
|
||||
#define wapp_b32_array_pop(ARRAY_PTR) (ARRAY_PTR != NULL && (ARRAY_PTR)->count > 0 ? \
|
||||
*_b32_array_pop(ARRAY_PTR) : \
|
||||
(b32){0} \
|
||||
)
|
||||
#define wapp_char_array(...) ((CharArray){ \
|
||||
.items = (char[wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count(char, __VA_ARGS__) * 2)]){__VA_ARGS__}, \
|
||||
.count = wapp_misc_utils_va_args_count(char, __VA_ARGS__), \
|
||||
.capacity = wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count(char, __VA_ARGS__) * 2), \
|
||||
.item_size = sizeof(char) \
|
||||
})
|
||||
#define wapp_char_array_with_capacity(CAPACITY) ((CharArray){.items = (char[CAPACITY]){0}, .count = 0, .capacity = CAPACITY, .item_size = sizeof(char)})
|
||||
#define wapp_char_array_pop(ARRAY_PTR) (ARRAY_PTR != NULL && (ARRAY_PTR)->count > 0 ? \
|
||||
*_char_array_pop(ARRAY_PTR) : \
|
||||
(char){0} \
|
||||
)
|
||||
#define wapp_c8_array(...) ((C8Array){ \
|
||||
.items = (c8[wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count(c8, __VA_ARGS__) * 2)]){__VA_ARGS__}, \
|
||||
.count = wapp_misc_utils_va_args_count(c8, __VA_ARGS__), \
|
||||
.capacity = wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count(c8, __VA_ARGS__) * 2), \
|
||||
.item_size = sizeof(c8) \
|
||||
})
|
||||
#define wapp_c8_array_with_capacity(CAPACITY) ((C8Array){.items = (c8[CAPACITY]){0}, .count = 0, .capacity = CAPACITY, .item_size = sizeof(c8)})
|
||||
#define wapp_c8_array_pop(ARRAY_PTR) (ARRAY_PTR != NULL && (ARRAY_PTR)->count > 0 ? \
|
||||
*_c8_array_pop(ARRAY_PTR) : \
|
||||
(c8){0} \
|
||||
)
|
||||
#define wapp_c16_array(...) ((C16Array){ \
|
||||
.items = (c16[wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count(c16, __VA_ARGS__) * 2)]){__VA_ARGS__}, \
|
||||
.count = wapp_misc_utils_va_args_count(c16, __VA_ARGS__), \
|
||||
.capacity = wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count(c16, __VA_ARGS__) * 2), \
|
||||
.item_size = sizeof(c16) \
|
||||
})
|
||||
#define wapp_c16_array_with_capacity(CAPACITY) ((C16Array){.items = (c16[CAPACITY]){0}, .count = 0, .capacity = CAPACITY, .item_size = sizeof(c16)})
|
||||
#define wapp_c16_array_pop(ARRAY_PTR) (ARRAY_PTR != NULL && (ARRAY_PTR)->count > 0 ? \
|
||||
*_c16_array_pop(ARRAY_PTR) : \
|
||||
(c16){0} \
|
||||
)
|
||||
#define wapp_c32_array(...) ((C32Array){ \
|
||||
.items = (c32[wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count(c32, __VA_ARGS__) * 2)]){__VA_ARGS__}, \
|
||||
.count = wapp_misc_utils_va_args_count(c32, __VA_ARGS__), \
|
||||
.capacity = wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count(c32, __VA_ARGS__) * 2), \
|
||||
.item_size = sizeof(c32) \
|
||||
})
|
||||
#define wapp_c32_array_with_capacity(CAPACITY) ((C32Array){.items = (c32[CAPACITY]){0}, .count = 0, .capacity = CAPACITY, .item_size = sizeof(c32)})
|
||||
#define wapp_c32_array_pop(ARRAY_PTR) (ARRAY_PTR != NULL && (ARRAY_PTR)->count > 0 ? \
|
||||
*_c32_array_pop(ARRAY_PTR) : \
|
||||
(c32){0} \
|
||||
)
|
||||
#define wapp_i8_array(...) ((I8Array){ \
|
||||
.items = (i8[wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count(i8, __VA_ARGS__) * 2)]){__VA_ARGS__}, \
|
||||
.count = wapp_misc_utils_va_args_count(i8, __VA_ARGS__), \
|
||||
.capacity = wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count(i8, __VA_ARGS__) * 2), \
|
||||
.item_size = sizeof(i8) \
|
||||
})
|
||||
#define wapp_i8_array_with_capacity(CAPACITY) ((I8Array){.items = (i8[CAPACITY]){0}, .count = 0, .capacity = CAPACITY, .item_size = sizeof(i8)})
|
||||
#define wapp_i8_array_pop(ARRAY_PTR) (ARRAY_PTR != NULL && (ARRAY_PTR)->count > 0 ? \
|
||||
*_i8_array_pop(ARRAY_PTR) : \
|
||||
(i8){0} \
|
||||
)
|
||||
#define wapp_i16_array(...) ((I16Array){ \
|
||||
.items = (i16[wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count(i16, __VA_ARGS__) * 2)]){__VA_ARGS__}, \
|
||||
.count = wapp_misc_utils_va_args_count(i16, __VA_ARGS__), \
|
||||
.capacity = wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count(i16, __VA_ARGS__) * 2), \
|
||||
.item_size = sizeof(i16) \
|
||||
})
|
||||
#define wapp_i16_array_with_capacity(CAPACITY) ((I16Array){.items = (i16[CAPACITY]){0}, .count = 0, .capacity = CAPACITY, .item_size = sizeof(i16)})
|
||||
#define wapp_i16_array_pop(ARRAY_PTR) (ARRAY_PTR != NULL && (ARRAY_PTR)->count > 0 ? \
|
||||
*_i16_array_pop(ARRAY_PTR) : \
|
||||
(i16){0} \
|
||||
)
|
||||
#define wapp_i32_array(...) ((I32Array){ \
|
||||
.items = (i32[wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count(i32, __VA_ARGS__) * 2)]){__VA_ARGS__}, \
|
||||
.count = wapp_misc_utils_va_args_count(i32, __VA_ARGS__), \
|
||||
.capacity = wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count(i32, __VA_ARGS__) * 2), \
|
||||
.item_size = sizeof(i32) \
|
||||
})
|
||||
#define wapp_i32_array_with_capacity(CAPACITY) ((I32Array){.items = (i32[CAPACITY]){0}, .count = 0, .capacity = CAPACITY, .item_size = sizeof(i32)})
|
||||
#define wapp_i32_array_pop(ARRAY_PTR) (ARRAY_PTR != NULL && (ARRAY_PTR)->count > 0 ? \
|
||||
*_i32_array_pop(ARRAY_PTR) : \
|
||||
(i32){0} \
|
||||
)
|
||||
#define wapp_i64_array(...) ((I64Array){ \
|
||||
.items = (i64[wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count(i64, __VA_ARGS__) * 2)]){__VA_ARGS__}, \
|
||||
.count = wapp_misc_utils_va_args_count(i64, __VA_ARGS__), \
|
||||
.capacity = wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count(i64, __VA_ARGS__) * 2), \
|
||||
.item_size = sizeof(i64) \
|
||||
})
|
||||
#define wapp_i64_array_with_capacity(CAPACITY) ((I64Array){.items = (i64[CAPACITY]){0}, .count = 0, .capacity = CAPACITY, .item_size = sizeof(i64)})
|
||||
#define wapp_i64_array_pop(ARRAY_PTR) (ARRAY_PTR != NULL && (ARRAY_PTR)->count > 0 ? \
|
||||
*_i64_array_pop(ARRAY_PTR) : \
|
||||
(i64){0} \
|
||||
)
|
||||
#define wapp_u8_array(...) ((U8Array){ \
|
||||
.items = (u8[wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count(u8, __VA_ARGS__) * 2)]){__VA_ARGS__}, \
|
||||
.count = wapp_misc_utils_va_args_count(u8, __VA_ARGS__), \
|
||||
.capacity = wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count(u8, __VA_ARGS__) * 2), \
|
||||
.item_size = sizeof(u8) \
|
||||
})
|
||||
#define wapp_u8_array_with_capacity(CAPACITY) ((U8Array){.items = (u8[CAPACITY]){0}, .count = 0, .capacity = CAPACITY, .item_size = sizeof(u8)})
|
||||
#define wapp_u8_array_pop(ARRAY_PTR) (ARRAY_PTR != NULL && (ARRAY_PTR)->count > 0 ? \
|
||||
*_u8_array_pop(ARRAY_PTR) : \
|
||||
(u8){0} \
|
||||
)
|
||||
#define wapp_u16_array(...) ((U16Array){ \
|
||||
.items = (u16[wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count(u16, __VA_ARGS__) * 2)]){__VA_ARGS__}, \
|
||||
.count = wapp_misc_utils_va_args_count(u16, __VA_ARGS__), \
|
||||
.capacity = wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count(u16, __VA_ARGS__) * 2), \
|
||||
.item_size = sizeof(u16) \
|
||||
})
|
||||
#define wapp_u16_array_with_capacity(CAPACITY) ((U16Array){.items = (u16[CAPACITY]){0}, .count = 0, .capacity = CAPACITY, .item_size = sizeof(u16)})
|
||||
#define wapp_u16_array_pop(ARRAY_PTR) (ARRAY_PTR != NULL && (ARRAY_PTR)->count > 0 ? \
|
||||
*_u16_array_pop(ARRAY_PTR) : \
|
||||
(u16){0} \
|
||||
)
|
||||
#define wapp_u32_array(...) ((U32Array){ \
|
||||
.items = (u32[wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count(u32, __VA_ARGS__) * 2)]){__VA_ARGS__}, \
|
||||
.count = wapp_misc_utils_va_args_count(u32, __VA_ARGS__), \
|
||||
.capacity = wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count(u32, __VA_ARGS__) * 2), \
|
||||
.item_size = sizeof(u32) \
|
||||
})
|
||||
#define wapp_u32_array_with_capacity(CAPACITY) ((U32Array){.items = (u32[CAPACITY]){0}, .count = 0, .capacity = CAPACITY, .item_size = sizeof(u32)})
|
||||
#define wapp_u32_array_pop(ARRAY_PTR) (ARRAY_PTR != NULL && (ARRAY_PTR)->count > 0 ? \
|
||||
*_u32_array_pop(ARRAY_PTR) : \
|
||||
(u32){0} \
|
||||
)
|
||||
#define wapp_u64_array(...) ((U64Array){ \
|
||||
.items = (u64[wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count(u64, __VA_ARGS__) * 2)]){__VA_ARGS__}, \
|
||||
.count = wapp_misc_utils_va_args_count(u64, __VA_ARGS__), \
|
||||
.capacity = wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count(u64, __VA_ARGS__) * 2), \
|
||||
.item_size = sizeof(u64) \
|
||||
})
|
||||
#define wapp_u64_array_with_capacity(CAPACITY) ((U64Array){.items = (u64[CAPACITY]){0}, .count = 0, .capacity = CAPACITY, .item_size = sizeof(u64)})
|
||||
#define wapp_u64_array_pop(ARRAY_PTR) (ARRAY_PTR != NULL && (ARRAY_PTR)->count > 0 ? \
|
||||
*_u64_array_pop(ARRAY_PTR) : \
|
||||
(u64){0} \
|
||||
)
|
||||
#define wapp_f32_array(...) ((F32Array){ \
|
||||
.items = (f32[wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count(f32, __VA_ARGS__) * 2)]){__VA_ARGS__}, \
|
||||
.count = wapp_misc_utils_va_args_count(f32, __VA_ARGS__), \
|
||||
.capacity = wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count(f32, __VA_ARGS__) * 2), \
|
||||
.item_size = sizeof(f32) \
|
||||
})
|
||||
#define wapp_f32_array_with_capacity(CAPACITY) ((F32Array){.items = (f32[CAPACITY]){0}, .count = 0, .capacity = CAPACITY, .item_size = sizeof(f32)})
|
||||
#define wapp_f32_array_pop(ARRAY_PTR) (ARRAY_PTR != NULL && (ARRAY_PTR)->count > 0 ? \
|
||||
*_f32_array_pop(ARRAY_PTR) : \
|
||||
(f32){0} \
|
||||
)
|
||||
#define wapp_f64_array(...) ((F64Array){ \
|
||||
.items = (f64[wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count(f64, __VA_ARGS__) * 2)]){__VA_ARGS__}, \
|
||||
.count = wapp_misc_utils_va_args_count(f64, __VA_ARGS__), \
|
||||
.capacity = wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count(f64, __VA_ARGS__) * 2), \
|
||||
.item_size = sizeof(f64) \
|
||||
})
|
||||
#define wapp_f64_array_with_capacity(CAPACITY) ((F64Array){.items = (f64[CAPACITY]){0}, .count = 0, .capacity = CAPACITY, .item_size = sizeof(f64)})
|
||||
#define wapp_f64_array_pop(ARRAY_PTR) (ARRAY_PTR != NULL && (ARRAY_PTR)->count > 0 ? \
|
||||
*_f64_array_pop(ARRAY_PTR) : \
|
||||
(f64){0} \
|
||||
)
|
||||
#define wapp_f128_array(...) ((F128Array){ \
|
||||
.items = (f128[wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count(f128, __VA_ARGS__) * 2)]){__VA_ARGS__}, \
|
||||
.count = wapp_misc_utils_va_args_count(f128, __VA_ARGS__), \
|
||||
.capacity = wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count(f128, __VA_ARGS__) * 2), \
|
||||
.item_size = sizeof(f128) \
|
||||
})
|
||||
#define wapp_f128_array_with_capacity(CAPACITY) ((F128Array){.items = (f128[CAPACITY]){0}, .count = 0, .capacity = CAPACITY, .item_size = sizeof(f128)})
|
||||
#define wapp_f128_array_pop(ARRAY_PTR) (ARRAY_PTR != NULL && (ARRAY_PTR)->count > 0 ? \
|
||||
*_f128_array_pop(ARRAY_PTR) : \
|
||||
(f128){0} \
|
||||
)
|
||||
#define wapp_iptr_array(...) ((IptrArray){ \
|
||||
.items = (iptr[wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count(iptr, __VA_ARGS__) * 2)]){__VA_ARGS__}, \
|
||||
.count = wapp_misc_utils_va_args_count(iptr, __VA_ARGS__), \
|
||||
.capacity = wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count(iptr, __VA_ARGS__) * 2), \
|
||||
.item_size = sizeof(iptr) \
|
||||
})
|
||||
#define wapp_iptr_array_with_capacity(CAPACITY) ((IptrArray){.items = (iptr[CAPACITY]){0}, .count = 0, .capacity = CAPACITY, .item_size = sizeof(iptr)})
|
||||
#define wapp_iptr_array_pop(ARRAY_PTR) (ARRAY_PTR != NULL && (ARRAY_PTR)->count > 0 ? \
|
||||
*_iptr_array_pop(ARRAY_PTR) : \
|
||||
(iptr){0} \
|
||||
)
|
||||
#define wapp_uptr_array(...) ((UptrArray){ \
|
||||
.items = (uptr[wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count(uptr, __VA_ARGS__) * 2)]){__VA_ARGS__}, \
|
||||
.count = wapp_misc_utils_va_args_count(uptr, __VA_ARGS__), \
|
||||
.capacity = wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count(uptr, __VA_ARGS__) * 2), \
|
||||
.item_size = sizeof(uptr) \
|
||||
})
|
||||
#define wapp_uptr_array_with_capacity(CAPACITY) ((UptrArray){.items = (uptr[CAPACITY]){0}, .count = 0, .capacity = CAPACITY, .item_size = sizeof(uptr)})
|
||||
#define wapp_uptr_array_pop(ARRAY_PTR) (ARRAY_PTR != NULL && (ARRAY_PTR)->count > 0 ? \
|
||||
*_uptr_array_pop(ARRAY_PTR) : \
|
||||
(uptr){0} \
|
||||
)
|
||||
#endif // !WAPP_PLATFORM_CPP
|
||||
|
||||
typedef struct str8 Str8;
|
||||
|
||||
typedef struct Str8Array Str8Array;
|
||||
struct Str8Array {
|
||||
Str8 *items;
|
||||
u64 count;
|
||||
u64 capacity;
|
||||
u64 item_size;
|
||||
};
|
||||
|
||||
typedef struct VoidPArray VoidPArray;
|
||||
struct VoidPArray {
|
||||
void * *items;
|
||||
u64 count;
|
||||
u64 capacity;
|
||||
u64 item_size;
|
||||
};
|
||||
|
||||
typedef struct B32Array B32Array;
|
||||
struct B32Array {
|
||||
b32 *items;
|
||||
u64 count;
|
||||
u64 capacity;
|
||||
u64 item_size;
|
||||
};
|
||||
|
||||
typedef struct CharArray CharArray;
|
||||
struct CharArray {
|
||||
char *items;
|
||||
u64 count;
|
||||
u64 capacity;
|
||||
u64 item_size;
|
||||
};
|
||||
|
||||
typedef struct C8Array C8Array;
|
||||
struct C8Array {
|
||||
c8 *items;
|
||||
u64 count;
|
||||
u64 capacity;
|
||||
u64 item_size;
|
||||
};
|
||||
|
||||
typedef struct C16Array C16Array;
|
||||
struct C16Array {
|
||||
c16 *items;
|
||||
u64 count;
|
||||
u64 capacity;
|
||||
u64 item_size;
|
||||
};
|
||||
|
||||
typedef struct C32Array C32Array;
|
||||
struct C32Array {
|
||||
c32 *items;
|
||||
u64 count;
|
||||
u64 capacity;
|
||||
u64 item_size;
|
||||
};
|
||||
|
||||
typedef struct I8Array I8Array;
|
||||
struct I8Array {
|
||||
i8 *items;
|
||||
u64 count;
|
||||
u64 capacity;
|
||||
u64 item_size;
|
||||
};
|
||||
|
||||
typedef struct I16Array I16Array;
|
||||
struct I16Array {
|
||||
i16 *items;
|
||||
u64 count;
|
||||
u64 capacity;
|
||||
u64 item_size;
|
||||
};
|
||||
|
||||
typedef struct I32Array I32Array;
|
||||
struct I32Array {
|
||||
i32 *items;
|
||||
u64 count;
|
||||
u64 capacity;
|
||||
u64 item_size;
|
||||
};
|
||||
|
||||
typedef struct I64Array I64Array;
|
||||
struct I64Array {
|
||||
i64 *items;
|
||||
u64 count;
|
||||
u64 capacity;
|
||||
u64 item_size;
|
||||
};
|
||||
|
||||
typedef struct U8Array U8Array;
|
||||
struct U8Array {
|
||||
u8 *items;
|
||||
u64 count;
|
||||
u64 capacity;
|
||||
u64 item_size;
|
||||
};
|
||||
|
||||
typedef struct U16Array U16Array;
|
||||
struct U16Array {
|
||||
u16 *items;
|
||||
u64 count;
|
||||
u64 capacity;
|
||||
u64 item_size;
|
||||
};
|
||||
|
||||
typedef struct U32Array U32Array;
|
||||
struct U32Array {
|
||||
u32 *items;
|
||||
u64 count;
|
||||
u64 capacity;
|
||||
u64 item_size;
|
||||
};
|
||||
|
||||
typedef struct U64Array U64Array;
|
||||
struct U64Array {
|
||||
u64 *items;
|
||||
u64 count;
|
||||
u64 capacity;
|
||||
u64 item_size;
|
||||
};
|
||||
|
||||
typedef struct F32Array F32Array;
|
||||
struct F32Array {
|
||||
f32 *items;
|
||||
u64 count;
|
||||
u64 capacity;
|
||||
u64 item_size;
|
||||
};
|
||||
|
||||
typedef struct F64Array F64Array;
|
||||
struct F64Array {
|
||||
f64 *items;
|
||||
u64 count;
|
||||
u64 capacity;
|
||||
u64 item_size;
|
||||
};
|
||||
|
||||
typedef struct F128Array F128Array;
|
||||
struct F128Array {
|
||||
f128 *items;
|
||||
u64 count;
|
||||
u64 capacity;
|
||||
u64 item_size;
|
||||
};
|
||||
|
||||
typedef struct IptrArray IptrArray;
|
||||
struct IptrArray {
|
||||
iptr *items;
|
||||
u64 count;
|
||||
u64 capacity;
|
||||
u64 item_size;
|
||||
};
|
||||
|
||||
typedef struct UptrArray UptrArray;
|
||||
struct UptrArray {
|
||||
uptr *items;
|
||||
u64 count;
|
||||
u64 capacity;
|
||||
u64 item_size;
|
||||
};
|
||||
|
||||
Str8 *wapp_str8_array_get(const Str8Array *array, u64 index);
|
||||
void wapp_str8_array_set(Str8Array *array, u64 index, Str8 *item);
|
||||
void wapp_str8_array_append_capped(Str8Array *array, Str8 *item);
|
||||
void wapp_str8_array_extend_capped(Str8Array *array, const Str8Array *other);
|
||||
void wapp_str8_array_clear(Str8Array *array);
|
||||
void wapp_str8_array_copy_capped(const Str8Array *src, Str8Array *dst);
|
||||
Str8Array *wapp_str8_array_append_alloc(const Allocator *allocator, Str8Array *array, Str8 *item);
|
||||
Str8Array *wapp_str8_array_extend_alloc(const Allocator *allocator, Str8Array *array, const Str8Array *other);
|
||||
Str8Array *wapp_str8_array_copy_alloc(const Allocator *allocator, const Str8Array *src, Str8Array *dst);
|
||||
Str8 *_str8_array_pop(Str8Array *array);
|
||||
void * *wapp_void_ptr_array_get(const VoidPArray *array, u64 index);
|
||||
void wapp_void_ptr_array_set(VoidPArray *array, u64 index, void * *item);
|
||||
void wapp_void_ptr_array_append_capped(VoidPArray *array, void * *item);
|
||||
void wapp_void_ptr_array_extend_capped(VoidPArray *array, const VoidPArray *other);
|
||||
void wapp_void_ptr_array_clear(VoidPArray *array);
|
||||
void wapp_void_ptr_array_copy_capped(const VoidPArray *src, VoidPArray *dst);
|
||||
VoidPArray *wapp_void_ptr_array_append_alloc(const Allocator *allocator, VoidPArray *array, void * *item);
|
||||
VoidPArray *wapp_void_ptr_array_extend_alloc(const Allocator *allocator, VoidPArray *array, const VoidPArray *other);
|
||||
VoidPArray *wapp_void_ptr_array_copy_alloc(const Allocator *allocator, const VoidPArray *src, VoidPArray *dst);
|
||||
void * *_void_ptr_array_pop(VoidPArray *array);
|
||||
b32 *wapp_b32_array_get(const B32Array *array, u64 index);
|
||||
void wapp_b32_array_set(B32Array *array, u64 index, b32 *item);
|
||||
void wapp_b32_array_append_capped(B32Array *array, b32 *item);
|
||||
void wapp_b32_array_extend_capped(B32Array *array, const B32Array *other);
|
||||
void wapp_b32_array_clear(B32Array *array);
|
||||
void wapp_b32_array_copy_capped(const B32Array *src, B32Array *dst);
|
||||
B32Array *wapp_b32_array_append_alloc(const Allocator *allocator, B32Array *array, b32 *item);
|
||||
B32Array *wapp_b32_array_extend_alloc(const Allocator *allocator, B32Array *array, const B32Array *other);
|
||||
B32Array *wapp_b32_array_copy_alloc(const Allocator *allocator, const B32Array *src, B32Array *dst);
|
||||
b32 *_b32_array_pop(B32Array *array);
|
||||
char *wapp_char_array_get(const CharArray *array, u64 index);
|
||||
void wapp_char_array_set(CharArray *array, u64 index, char *item);
|
||||
void wapp_char_array_append_capped(CharArray *array, char *item);
|
||||
void wapp_char_array_extend_capped(CharArray *array, const CharArray *other);
|
||||
void wapp_char_array_clear(CharArray *array);
|
||||
void wapp_char_array_copy_capped(const CharArray *src, CharArray *dst);
|
||||
CharArray *wapp_char_array_append_alloc(const Allocator *allocator, CharArray *array, char *item);
|
||||
CharArray *wapp_char_array_extend_alloc(const Allocator *allocator, CharArray *array, const CharArray *other);
|
||||
CharArray *wapp_char_array_copy_alloc(const Allocator *allocator, const CharArray *src, CharArray *dst);
|
||||
char *_char_array_pop(CharArray *array);
|
||||
c8 *wapp_c8_array_get(const C8Array *array, u64 index);
|
||||
void wapp_c8_array_set(C8Array *array, u64 index, c8 *item);
|
||||
void wapp_c8_array_append_capped(C8Array *array, c8 *item);
|
||||
void wapp_c8_array_extend_capped(C8Array *array, const C8Array *other);
|
||||
void wapp_c8_array_clear(C8Array *array);
|
||||
void wapp_c8_array_copy_capped(const C8Array *src, C8Array *dst);
|
||||
C8Array *wapp_c8_array_append_alloc(const Allocator *allocator, C8Array *array, c8 *item);
|
||||
C8Array *wapp_c8_array_extend_alloc(const Allocator *allocator, C8Array *array, const C8Array *other);
|
||||
C8Array *wapp_c8_array_copy_alloc(const Allocator *allocator, const C8Array *src, C8Array *dst);
|
||||
c8 *_c8_array_pop(C8Array *array);
|
||||
c16 *wapp_c16_array_get(const C16Array *array, u64 index);
|
||||
void wapp_c16_array_set(C16Array *array, u64 index, c16 *item);
|
||||
void wapp_c16_array_append_capped(C16Array *array, c16 *item);
|
||||
void wapp_c16_array_extend_capped(C16Array *array, const C16Array *other);
|
||||
void wapp_c16_array_clear(C16Array *array);
|
||||
void wapp_c16_array_copy_capped(const C16Array *src, C16Array *dst);
|
||||
C16Array *wapp_c16_array_append_alloc(const Allocator *allocator, C16Array *array, c16 *item);
|
||||
C16Array *wapp_c16_array_extend_alloc(const Allocator *allocator, C16Array *array, const C16Array *other);
|
||||
C16Array *wapp_c16_array_copy_alloc(const Allocator *allocator, const C16Array *src, C16Array *dst);
|
||||
c16 *_c16_array_pop(C16Array *array);
|
||||
c32 *wapp_c32_array_get(const C32Array *array, u64 index);
|
||||
void wapp_c32_array_set(C32Array *array, u64 index, c32 *item);
|
||||
void wapp_c32_array_append_capped(C32Array *array, c32 *item);
|
||||
void wapp_c32_array_extend_capped(C32Array *array, const C32Array *other);
|
||||
void wapp_c32_array_clear(C32Array *array);
|
||||
void wapp_c32_array_copy_capped(const C32Array *src, C32Array *dst);
|
||||
C32Array *wapp_c32_array_append_alloc(const Allocator *allocator, C32Array *array, c32 *item);
|
||||
C32Array *wapp_c32_array_extend_alloc(const Allocator *allocator, C32Array *array, const C32Array *other);
|
||||
C32Array *wapp_c32_array_copy_alloc(const Allocator *allocator, const C32Array *src, C32Array *dst);
|
||||
c32 *_c32_array_pop(C32Array *array);
|
||||
i8 *wapp_i8_array_get(const I8Array *array, u64 index);
|
||||
void wapp_i8_array_set(I8Array *array, u64 index, i8 *item);
|
||||
void wapp_i8_array_append_capped(I8Array *array, i8 *item);
|
||||
void wapp_i8_array_extend_capped(I8Array *array, const I8Array *other);
|
||||
void wapp_i8_array_clear(I8Array *array);
|
||||
void wapp_i8_array_copy_capped(const I8Array *src, I8Array *dst);
|
||||
I8Array *wapp_i8_array_append_alloc(const Allocator *allocator, I8Array *array, i8 *item);
|
||||
I8Array *wapp_i8_array_extend_alloc(const Allocator *allocator, I8Array *array, const I8Array *other);
|
||||
I8Array *wapp_i8_array_copy_alloc(const Allocator *allocator, const I8Array *src, I8Array *dst);
|
||||
i8 *_i8_array_pop(I8Array *array);
|
||||
i16 *wapp_i16_array_get(const I16Array *array, u64 index);
|
||||
void wapp_i16_array_set(I16Array *array, u64 index, i16 *item);
|
||||
void wapp_i16_array_append_capped(I16Array *array, i16 *item);
|
||||
void wapp_i16_array_extend_capped(I16Array *array, const I16Array *other);
|
||||
void wapp_i16_array_clear(I16Array *array);
|
||||
void wapp_i16_array_copy_capped(const I16Array *src, I16Array *dst);
|
||||
I16Array *wapp_i16_array_append_alloc(const Allocator *allocator, I16Array *array, i16 *item);
|
||||
I16Array *wapp_i16_array_extend_alloc(const Allocator *allocator, I16Array *array, const I16Array *other);
|
||||
I16Array *wapp_i16_array_copy_alloc(const Allocator *allocator, const I16Array *src, I16Array *dst);
|
||||
i16 *_i16_array_pop(I16Array *array);
|
||||
i32 *wapp_i32_array_get(const I32Array *array, u64 index);
|
||||
void wapp_i32_array_set(I32Array *array, u64 index, i32 *item);
|
||||
void wapp_i32_array_append_capped(I32Array *array, i32 *item);
|
||||
void wapp_i32_array_extend_capped(I32Array *array, const I32Array *other);
|
||||
void wapp_i32_array_clear(I32Array *array);
|
||||
void wapp_i32_array_copy_capped(const I32Array *src, I32Array *dst);
|
||||
I32Array *wapp_i32_array_append_alloc(const Allocator *allocator, I32Array *array, i32 *item);
|
||||
I32Array *wapp_i32_array_extend_alloc(const Allocator *allocator, I32Array *array, const I32Array *other);
|
||||
I32Array *wapp_i32_array_copy_alloc(const Allocator *allocator, const I32Array *src, I32Array *dst);
|
||||
i32 *_i32_array_pop(I32Array *array);
|
||||
i64 *wapp_i64_array_get(const I64Array *array, u64 index);
|
||||
void wapp_i64_array_set(I64Array *array, u64 index, i64 *item);
|
||||
void wapp_i64_array_append_capped(I64Array *array, i64 *item);
|
||||
void wapp_i64_array_extend_capped(I64Array *array, const I64Array *other);
|
||||
void wapp_i64_array_clear(I64Array *array);
|
||||
void wapp_i64_array_copy_capped(const I64Array *src, I64Array *dst);
|
||||
I64Array *wapp_i64_array_append_alloc(const Allocator *allocator, I64Array *array, i64 *item);
|
||||
I64Array *wapp_i64_array_extend_alloc(const Allocator *allocator, I64Array *array, const I64Array *other);
|
||||
I64Array *wapp_i64_array_copy_alloc(const Allocator *allocator, const I64Array *src, I64Array *dst);
|
||||
i64 *_i64_array_pop(I64Array *array);
|
||||
u8 *wapp_u8_array_get(const U8Array *array, u64 index);
|
||||
void wapp_u8_array_set(U8Array *array, u64 index, u8 *item);
|
||||
void wapp_u8_array_append_capped(U8Array *array, u8 *item);
|
||||
void wapp_u8_array_extend_capped(U8Array *array, const U8Array *other);
|
||||
void wapp_u8_array_clear(U8Array *array);
|
||||
void wapp_u8_array_copy_capped(const U8Array *src, U8Array *dst);
|
||||
U8Array *wapp_u8_array_append_alloc(const Allocator *allocator, U8Array *array, u8 *item);
|
||||
U8Array *wapp_u8_array_extend_alloc(const Allocator *allocator, U8Array *array, const U8Array *other);
|
||||
U8Array *wapp_u8_array_copy_alloc(const Allocator *allocator, const U8Array *src, U8Array *dst);
|
||||
u8 *_u8_array_pop(U8Array *array);
|
||||
u16 *wapp_u16_array_get(const U16Array *array, u64 index);
|
||||
void wapp_u16_array_set(U16Array *array, u64 index, u16 *item);
|
||||
void wapp_u16_array_append_capped(U16Array *array, u16 *item);
|
||||
void wapp_u16_array_extend_capped(U16Array *array, const U16Array *other);
|
||||
void wapp_u16_array_clear(U16Array *array);
|
||||
void wapp_u16_array_copy_capped(const U16Array *src, U16Array *dst);
|
||||
U16Array *wapp_u16_array_append_alloc(const Allocator *allocator, U16Array *array, u16 *item);
|
||||
U16Array *wapp_u16_array_extend_alloc(const Allocator *allocator, U16Array *array, const U16Array *other);
|
||||
U16Array *wapp_u16_array_copy_alloc(const Allocator *allocator, const U16Array *src, U16Array *dst);
|
||||
u16 *_u16_array_pop(U16Array *array);
|
||||
u32 *wapp_u32_array_get(const U32Array *array, u64 index);
|
||||
void wapp_u32_array_set(U32Array *array, u64 index, u32 *item);
|
||||
void wapp_u32_array_append_capped(U32Array *array, u32 *item);
|
||||
void wapp_u32_array_extend_capped(U32Array *array, const U32Array *other);
|
||||
void wapp_u32_array_clear(U32Array *array);
|
||||
void wapp_u32_array_copy_capped(const U32Array *src, U32Array *dst);
|
||||
U32Array *wapp_u32_array_append_alloc(const Allocator *allocator, U32Array *array, u32 *item);
|
||||
U32Array *wapp_u32_array_extend_alloc(const Allocator *allocator, U32Array *array, const U32Array *other);
|
||||
U32Array *wapp_u32_array_copy_alloc(const Allocator *allocator, const U32Array *src, U32Array *dst);
|
||||
u32 *_u32_array_pop(U32Array *array);
|
||||
u64 *wapp_u64_array_get(const U64Array *array, u64 index);
|
||||
void wapp_u64_array_set(U64Array *array, u64 index, u64 *item);
|
||||
void wapp_u64_array_append_capped(U64Array *array, u64 *item);
|
||||
void wapp_u64_array_extend_capped(U64Array *array, const U64Array *other);
|
||||
void wapp_u64_array_clear(U64Array *array);
|
||||
void wapp_u64_array_copy_capped(const U64Array *src, U64Array *dst);
|
||||
U64Array *wapp_u64_array_append_alloc(const Allocator *allocator, U64Array *array, u64 *item);
|
||||
U64Array *wapp_u64_array_extend_alloc(const Allocator *allocator, U64Array *array, const U64Array *other);
|
||||
U64Array *wapp_u64_array_copy_alloc(const Allocator *allocator, const U64Array *src, U64Array *dst);
|
||||
u64 *_u64_array_pop(U64Array *array);
|
||||
f32 *wapp_f32_array_get(const F32Array *array, u64 index);
|
||||
void wapp_f32_array_set(F32Array *array, u64 index, f32 *item);
|
||||
void wapp_f32_array_append_capped(F32Array *array, f32 *item);
|
||||
void wapp_f32_array_extend_capped(F32Array *array, const F32Array *other);
|
||||
void wapp_f32_array_clear(F32Array *array);
|
||||
void wapp_f32_array_copy_capped(const F32Array *src, F32Array *dst);
|
||||
F32Array *wapp_f32_array_append_alloc(const Allocator *allocator, F32Array *array, f32 *item);
|
||||
F32Array *wapp_f32_array_extend_alloc(const Allocator *allocator, F32Array *array, const F32Array *other);
|
||||
F32Array *wapp_f32_array_copy_alloc(const Allocator *allocator, const F32Array *src, F32Array *dst);
|
||||
f32 *_f32_array_pop(F32Array *array);
|
||||
f64 *wapp_f64_array_get(const F64Array *array, u64 index);
|
||||
void wapp_f64_array_set(F64Array *array, u64 index, f64 *item);
|
||||
void wapp_f64_array_append_capped(F64Array *array, f64 *item);
|
||||
void wapp_f64_array_extend_capped(F64Array *array, const F64Array *other);
|
||||
void wapp_f64_array_clear(F64Array *array);
|
||||
void wapp_f64_array_copy_capped(const F64Array *src, F64Array *dst);
|
||||
F64Array *wapp_f64_array_append_alloc(const Allocator *allocator, F64Array *array, f64 *item);
|
||||
F64Array *wapp_f64_array_extend_alloc(const Allocator *allocator, F64Array *array, const F64Array *other);
|
||||
F64Array *wapp_f64_array_copy_alloc(const Allocator *allocator, const F64Array *src, F64Array *dst);
|
||||
f64 *_f64_array_pop(F64Array *array);
|
||||
f128 *wapp_f128_array_get(const F128Array *array, u64 index);
|
||||
void wapp_f128_array_set(F128Array *array, u64 index, f128 *item);
|
||||
void wapp_f128_array_append_capped(F128Array *array, f128 *item);
|
||||
void wapp_f128_array_extend_capped(F128Array *array, const F128Array *other);
|
||||
void wapp_f128_array_clear(F128Array *array);
|
||||
void wapp_f128_array_copy_capped(const F128Array *src, F128Array *dst);
|
||||
F128Array *wapp_f128_array_append_alloc(const Allocator *allocator, F128Array *array, f128 *item);
|
||||
F128Array *wapp_f128_array_extend_alloc(const Allocator *allocator, F128Array *array, const F128Array *other);
|
||||
F128Array *wapp_f128_array_copy_alloc(const Allocator *allocator, const F128Array *src, F128Array *dst);
|
||||
f128 *_f128_array_pop(F128Array *array);
|
||||
iptr *wapp_iptr_array_get(const IptrArray *array, u64 index);
|
||||
void wapp_iptr_array_set(IptrArray *array, u64 index, iptr *item);
|
||||
void wapp_iptr_array_append_capped(IptrArray *array, iptr *item);
|
||||
void wapp_iptr_array_extend_capped(IptrArray *array, const IptrArray *other);
|
||||
void wapp_iptr_array_clear(IptrArray *array);
|
||||
void wapp_iptr_array_copy_capped(const IptrArray *src, IptrArray *dst);
|
||||
IptrArray *wapp_iptr_array_append_alloc(const Allocator *allocator, IptrArray *array, iptr *item);
|
||||
IptrArray *wapp_iptr_array_extend_alloc(const Allocator *allocator, IptrArray *array, const IptrArray *other);
|
||||
IptrArray *wapp_iptr_array_copy_alloc(const Allocator *allocator, const IptrArray *src, IptrArray *dst);
|
||||
iptr *_iptr_array_pop(IptrArray *array);
|
||||
uptr *wapp_uptr_array_get(const UptrArray *array, u64 index);
|
||||
void wapp_uptr_array_set(UptrArray *array, u64 index, uptr *item);
|
||||
void wapp_uptr_array_append_capped(UptrArray *array, uptr *item);
|
||||
void wapp_uptr_array_extend_capped(UptrArray *array, const UptrArray *other);
|
||||
void wapp_uptr_array_clear(UptrArray *array);
|
||||
void wapp_uptr_array_copy_capped(const UptrArray *src, UptrArray *dst);
|
||||
UptrArray *wapp_uptr_array_append_alloc(const Allocator *allocator, UptrArray *array, uptr *item);
|
||||
UptrArray *wapp_uptr_array_extend_alloc(const Allocator *allocator, UptrArray *array, const UptrArray *other);
|
||||
UptrArray *wapp_uptr_array_copy_alloc(const Allocator *allocator, const UptrArray *src, UptrArray *dst);
|
||||
uptr *_uptr_array_pop(UptrArray *array);
|
||||
VoidPArray *_array_alloc_capacity(const Allocator *allocator, u64 capacity, u64 item_size);
|
||||
|
||||
#ifdef WAPP_PLATFORM_CPP
|
||||
END_C_LINKAGE
|
||||
#endif // !WAPP_PLATFORM_CPP
|
||||
|
||||
#endif // !ARRAY_H
|
3813
wapp/primitives/dbl_list/dbl_list.c
Normal file
3813
wapp/primitives/dbl_list/dbl_list.c
Normal file
File diff suppressed because it is too large
Load Diff
507
wapp/primitives/dbl_list/dbl_list.h
Normal file
507
wapp/primitives/dbl_list/dbl_list.h
Normal file
@ -0,0 +1,507 @@
|
||||
/**
|
||||
* THIS FILE IS AUTOMATICALLY GENERATED. ANY MODIFICATIONS TO IT WILL BE OVERWRITTEN
|
||||
*/
|
||||
|
||||
#ifndef DBL_LIST_H
|
||||
#define DBL_LIST_H
|
||||
|
||||
#include "../../common/aliases/aliases.h"
|
||||
#include "../../common/aliases/aliases.h"
|
||||
#include "../../common/platform/platform.h"
|
||||
|
||||
#ifdef WAPP_PLATFORM_CPP
|
||||
BEGIN_C_LINKAGE
|
||||
#endif // !WAPP_PLATFORM_CPP
|
||||
|
||||
#ifdef WAPP_PLATFORM_CPP
|
||||
#define wapp_str8_list_node(ITEM_PTR) Str8Node{ITEM_PTR, nullptr, nullptr}
|
||||
#define wapp_void_ptr_list_node(ITEM_PTR) VoidPNode{ITEM_PTR, nullptr, nullptr}
|
||||
#define wapp_b32_list_node(ITEM_PTR) B32Node{ITEM_PTR, nullptr, nullptr}
|
||||
#define wapp_char_list_node(ITEM_PTR) CharNode{ITEM_PTR, nullptr, nullptr}
|
||||
#define wapp_c8_list_node(ITEM_PTR) C8Node{ITEM_PTR, nullptr, nullptr}
|
||||
#define wapp_c16_list_node(ITEM_PTR) C16Node{ITEM_PTR, nullptr, nullptr}
|
||||
#define wapp_c32_list_node(ITEM_PTR) C32Node{ITEM_PTR, nullptr, nullptr}
|
||||
#define wapp_i8_list_node(ITEM_PTR) I8Node{ITEM_PTR, nullptr, nullptr}
|
||||
#define wapp_i16_list_node(ITEM_PTR) I16Node{ITEM_PTR, nullptr, nullptr}
|
||||
#define wapp_i32_list_node(ITEM_PTR) I32Node{ITEM_PTR, nullptr, nullptr}
|
||||
#define wapp_i64_list_node(ITEM_PTR) I64Node{ITEM_PTR, nullptr, nullptr}
|
||||
#define wapp_u8_list_node(ITEM_PTR) U8Node{ITEM_PTR, nullptr, nullptr}
|
||||
#define wapp_u16_list_node(ITEM_PTR) U16Node{ITEM_PTR, nullptr, nullptr}
|
||||
#define wapp_u32_list_node(ITEM_PTR) U32Node{ITEM_PTR, nullptr, nullptr}
|
||||
#define wapp_u64_list_node(ITEM_PTR) U64Node{ITEM_PTR, nullptr, nullptr}
|
||||
#define wapp_f32_list_node(ITEM_PTR) F32Node{ITEM_PTR, nullptr, nullptr}
|
||||
#define wapp_f64_list_node(ITEM_PTR) F64Node{ITEM_PTR, nullptr, nullptr}
|
||||
#define wapp_f128_list_node(ITEM_PTR) F128Node{ITEM_PTR, nullptr, nullptr}
|
||||
#define wapp_iptr_list_node(ITEM_PTR) IptrNode{ITEM_PTR, nullptr, nullptr}
|
||||
#define wapp_uptr_list_node(ITEM_PTR) UptrNode{ITEM_PTR, nullptr, nullptr}
|
||||
#else
|
||||
#define wapp_str8_list_node(ITEM_PTR) ((Str8Node){.item = ITEM_PTR})
|
||||
#define wapp_void_ptr_list_node(ITEM_PTR) ((VoidPNode){.item = ITEM_PTR})
|
||||
#define wapp_b32_list_node(ITEM_PTR) ((B32Node){.item = ITEM_PTR})
|
||||
#define wapp_char_list_node(ITEM_PTR) ((CharNode){.item = ITEM_PTR})
|
||||
#define wapp_c8_list_node(ITEM_PTR) ((C8Node){.item = ITEM_PTR})
|
||||
#define wapp_c16_list_node(ITEM_PTR) ((C16Node){.item = ITEM_PTR})
|
||||
#define wapp_c32_list_node(ITEM_PTR) ((C32Node){.item = ITEM_PTR})
|
||||
#define wapp_i8_list_node(ITEM_PTR) ((I8Node){.item = ITEM_PTR})
|
||||
#define wapp_i16_list_node(ITEM_PTR) ((I16Node){.item = ITEM_PTR})
|
||||
#define wapp_i32_list_node(ITEM_PTR) ((I32Node){.item = ITEM_PTR})
|
||||
#define wapp_i64_list_node(ITEM_PTR) ((I64Node){.item = ITEM_PTR})
|
||||
#define wapp_u8_list_node(ITEM_PTR) ((U8Node){.item = ITEM_PTR})
|
||||
#define wapp_u16_list_node(ITEM_PTR) ((U16Node){.item = ITEM_PTR})
|
||||
#define wapp_u32_list_node(ITEM_PTR) ((U32Node){.item = ITEM_PTR})
|
||||
#define wapp_u64_list_node(ITEM_PTR) ((U64Node){.item = ITEM_PTR})
|
||||
#define wapp_f32_list_node(ITEM_PTR) ((F32Node){.item = ITEM_PTR})
|
||||
#define wapp_f64_list_node(ITEM_PTR) ((F64Node){.item = ITEM_PTR})
|
||||
#define wapp_f128_list_node(ITEM_PTR) ((F128Node){.item = ITEM_PTR})
|
||||
#define wapp_iptr_list_node(ITEM_PTR) ((IptrNode){.item = ITEM_PTR})
|
||||
#define wapp_uptr_list_node(ITEM_PTR) ((UptrNode){.item = ITEM_PTR})
|
||||
#endif // !WAPP_PLATFORM_CPP
|
||||
|
||||
typedef struct str8 Str8;
|
||||
|
||||
typedef struct Str8Node Str8Node;
|
||||
struct Str8Node {
|
||||
Str8 *item;
|
||||
Str8Node *prev;
|
||||
Str8Node *next;
|
||||
};
|
||||
|
||||
typedef struct Str8List Str8List;
|
||||
struct Str8List {
|
||||
Str8Node *first;
|
||||
Str8Node *last;
|
||||
u64 node_count;
|
||||
};
|
||||
|
||||
typedef struct VoidPNode VoidPNode;
|
||||
struct VoidPNode {
|
||||
void * *item;
|
||||
VoidPNode *prev;
|
||||
VoidPNode *next;
|
||||
};
|
||||
|
||||
typedef struct VoidPList VoidPList;
|
||||
struct VoidPList {
|
||||
VoidPNode *first;
|
||||
VoidPNode *last;
|
||||
u64 node_count;
|
||||
};
|
||||
|
||||
typedef struct B32Node B32Node;
|
||||
struct B32Node {
|
||||
b32 *item;
|
||||
B32Node *prev;
|
||||
B32Node *next;
|
||||
};
|
||||
|
||||
typedef struct B32List B32List;
|
||||
struct B32List {
|
||||
B32Node *first;
|
||||
B32Node *last;
|
||||
u64 node_count;
|
||||
};
|
||||
|
||||
typedef struct CharNode CharNode;
|
||||
struct CharNode {
|
||||
char *item;
|
||||
CharNode *prev;
|
||||
CharNode *next;
|
||||
};
|
||||
|
||||
typedef struct CharList CharList;
|
||||
struct CharList {
|
||||
CharNode *first;
|
||||
CharNode *last;
|
||||
u64 node_count;
|
||||
};
|
||||
|
||||
typedef struct C8Node C8Node;
|
||||
struct C8Node {
|
||||
c8 *item;
|
||||
C8Node *prev;
|
||||
C8Node *next;
|
||||
};
|
||||
|
||||
typedef struct C8List C8List;
|
||||
struct C8List {
|
||||
C8Node *first;
|
||||
C8Node *last;
|
||||
u64 node_count;
|
||||
};
|
||||
|
||||
typedef struct C16Node C16Node;
|
||||
struct C16Node {
|
||||
c16 *item;
|
||||
C16Node *prev;
|
||||
C16Node *next;
|
||||
};
|
||||
|
||||
typedef struct C16List C16List;
|
||||
struct C16List {
|
||||
C16Node *first;
|
||||
C16Node *last;
|
||||
u64 node_count;
|
||||
};
|
||||
|
||||
typedef struct C32Node C32Node;
|
||||
struct C32Node {
|
||||
c32 *item;
|
||||
C32Node *prev;
|
||||
C32Node *next;
|
||||
};
|
||||
|
||||
typedef struct C32List C32List;
|
||||
struct C32List {
|
||||
C32Node *first;
|
||||
C32Node *last;
|
||||
u64 node_count;
|
||||
};
|
||||
|
||||
typedef struct I8Node I8Node;
|
||||
struct I8Node {
|
||||
i8 *item;
|
||||
I8Node *prev;
|
||||
I8Node *next;
|
||||
};
|
||||
|
||||
typedef struct I8List I8List;
|
||||
struct I8List {
|
||||
I8Node *first;
|
||||
I8Node *last;
|
||||
u64 node_count;
|
||||
};
|
||||
|
||||
typedef struct I16Node I16Node;
|
||||
struct I16Node {
|
||||
i16 *item;
|
||||
I16Node *prev;
|
||||
I16Node *next;
|
||||
};
|
||||
|
||||
typedef struct I16List I16List;
|
||||
struct I16List {
|
||||
I16Node *first;
|
||||
I16Node *last;
|
||||
u64 node_count;
|
||||
};
|
||||
|
||||
typedef struct I32Node I32Node;
|
||||
struct I32Node {
|
||||
i32 *item;
|
||||
I32Node *prev;
|
||||
I32Node *next;
|
||||
};
|
||||
|
||||
typedef struct I32List I32List;
|
||||
struct I32List {
|
||||
I32Node *first;
|
||||
I32Node *last;
|
||||
u64 node_count;
|
||||
};
|
||||
|
||||
typedef struct I64Node I64Node;
|
||||
struct I64Node {
|
||||
i64 *item;
|
||||
I64Node *prev;
|
||||
I64Node *next;
|
||||
};
|
||||
|
||||
typedef struct I64List I64List;
|
||||
struct I64List {
|
||||
I64Node *first;
|
||||
I64Node *last;
|
||||
u64 node_count;
|
||||
};
|
||||
|
||||
typedef struct U8Node U8Node;
|
||||
struct U8Node {
|
||||
u8 *item;
|
||||
U8Node *prev;
|
||||
U8Node *next;
|
||||
};
|
||||
|
||||
typedef struct U8List U8List;
|
||||
struct U8List {
|
||||
U8Node *first;
|
||||
U8Node *last;
|
||||
u64 node_count;
|
||||
};
|
||||
|
||||
typedef struct U16Node U16Node;
|
||||
struct U16Node {
|
||||
u16 *item;
|
||||
U16Node *prev;
|
||||
U16Node *next;
|
||||
};
|
||||
|
||||
typedef struct U16List U16List;
|
||||
struct U16List {
|
||||
U16Node *first;
|
||||
U16Node *last;
|
||||
u64 node_count;
|
||||
};
|
||||
|
||||
typedef struct U32Node U32Node;
|
||||
struct U32Node {
|
||||
u32 *item;
|
||||
U32Node *prev;
|
||||
U32Node *next;
|
||||
};
|
||||
|
||||
typedef struct U32List U32List;
|
||||
struct U32List {
|
||||
U32Node *first;
|
||||
U32Node *last;
|
||||
u64 node_count;
|
||||
};
|
||||
|
||||
typedef struct U64Node U64Node;
|
||||
struct U64Node {
|
||||
u64 *item;
|
||||
U64Node *prev;
|
||||
U64Node *next;
|
||||
};
|
||||
|
||||
typedef struct U64List U64List;
|
||||
struct U64List {
|
||||
U64Node *first;
|
||||
U64Node *last;
|
||||
u64 node_count;
|
||||
};
|
||||
|
||||
typedef struct F32Node F32Node;
|
||||
struct F32Node {
|
||||
f32 *item;
|
||||
F32Node *prev;
|
||||
F32Node *next;
|
||||
};
|
||||
|
||||
typedef struct F32List F32List;
|
||||
struct F32List {
|
||||
F32Node *first;
|
||||
F32Node *last;
|
||||
u64 node_count;
|
||||
};
|
||||
|
||||
typedef struct F64Node F64Node;
|
||||
struct F64Node {
|
||||
f64 *item;
|
||||
F64Node *prev;
|
||||
F64Node *next;
|
||||
};
|
||||
|
||||
typedef struct F64List F64List;
|
||||
struct F64List {
|
||||
F64Node *first;
|
||||
F64Node *last;
|
||||
u64 node_count;
|
||||
};
|
||||
|
||||
typedef struct F128Node F128Node;
|
||||
struct F128Node {
|
||||
f128 *item;
|
||||
F128Node *prev;
|
||||
F128Node *next;
|
||||
};
|
||||
|
||||
typedef struct F128List F128List;
|
||||
struct F128List {
|
||||
F128Node *first;
|
||||
F128Node *last;
|
||||
u64 node_count;
|
||||
};
|
||||
|
||||
typedef struct IptrNode IptrNode;
|
||||
struct IptrNode {
|
||||
iptr *item;
|
||||
IptrNode *prev;
|
||||
IptrNode *next;
|
||||
};
|
||||
|
||||
typedef struct IptrList IptrList;
|
||||
struct IptrList {
|
||||
IptrNode *first;
|
||||
IptrNode *last;
|
||||
u64 node_count;
|
||||
};
|
||||
|
||||
typedef struct UptrNode UptrNode;
|
||||
struct UptrNode {
|
||||
uptr *item;
|
||||
UptrNode *prev;
|
||||
UptrNode *next;
|
||||
};
|
||||
|
||||
typedef struct UptrList UptrList;
|
||||
struct UptrList {
|
||||
UptrNode *first;
|
||||
UptrNode *last;
|
||||
u64 node_count;
|
||||
};
|
||||
|
||||
Str8Node *wapp_str8_list_get(const Str8List *list, u64 index);
|
||||
void wapp_str8_list_push_front(Str8List *list, Str8Node *node);
|
||||
void wapp_str8_list_push_back(Str8List *list, Str8Node *node);
|
||||
void wapp_str8_list_insert(Str8List *list, Str8Node *node, u64 index);
|
||||
Str8Node *wapp_str8_list_pop_front(Str8List *list);
|
||||
Str8Node *wapp_str8_list_pop_back(Str8List *list);
|
||||
Str8Node *wapp_str8_list_remove(Str8List *list, u64 index);
|
||||
void wapp_str8_list_empty(Str8List *list);
|
||||
VoidPNode *wapp_void_ptr_list_get(const VoidPList *list, u64 index);
|
||||
void wapp_void_ptr_list_push_front(VoidPList *list, VoidPNode *node);
|
||||
void wapp_void_ptr_list_push_back(VoidPList *list, VoidPNode *node);
|
||||
void wapp_void_ptr_list_insert(VoidPList *list, VoidPNode *node, u64 index);
|
||||
VoidPNode *wapp_void_ptr_list_pop_front(VoidPList *list);
|
||||
VoidPNode *wapp_void_ptr_list_pop_back(VoidPList *list);
|
||||
VoidPNode *wapp_void_ptr_list_remove(VoidPList *list, u64 index);
|
||||
void wapp_void_ptr_list_empty(VoidPList *list);
|
||||
B32Node *wapp_b32_list_get(const B32List *list, u64 index);
|
||||
void wapp_b32_list_push_front(B32List *list, B32Node *node);
|
||||
void wapp_b32_list_push_back(B32List *list, B32Node *node);
|
||||
void wapp_b32_list_insert(B32List *list, B32Node *node, u64 index);
|
||||
B32Node *wapp_b32_list_pop_front(B32List *list);
|
||||
B32Node *wapp_b32_list_pop_back(B32List *list);
|
||||
B32Node *wapp_b32_list_remove(B32List *list, u64 index);
|
||||
void wapp_b32_list_empty(B32List *list);
|
||||
CharNode *wapp_char_list_get(const CharList *list, u64 index);
|
||||
void wapp_char_list_push_front(CharList *list, CharNode *node);
|
||||
void wapp_char_list_push_back(CharList *list, CharNode *node);
|
||||
void wapp_char_list_insert(CharList *list, CharNode *node, u64 index);
|
||||
CharNode *wapp_char_list_pop_front(CharList *list);
|
||||
CharNode *wapp_char_list_pop_back(CharList *list);
|
||||
CharNode *wapp_char_list_remove(CharList *list, u64 index);
|
||||
void wapp_char_list_empty(CharList *list);
|
||||
C8Node *wapp_c8_list_get(const C8List *list, u64 index);
|
||||
void wapp_c8_list_push_front(C8List *list, C8Node *node);
|
||||
void wapp_c8_list_push_back(C8List *list, C8Node *node);
|
||||
void wapp_c8_list_insert(C8List *list, C8Node *node, u64 index);
|
||||
C8Node *wapp_c8_list_pop_front(C8List *list);
|
||||
C8Node *wapp_c8_list_pop_back(C8List *list);
|
||||
C8Node *wapp_c8_list_remove(C8List *list, u64 index);
|
||||
void wapp_c8_list_empty(C8List *list);
|
||||
C16Node *wapp_c16_list_get(const C16List *list, u64 index);
|
||||
void wapp_c16_list_push_front(C16List *list, C16Node *node);
|
||||
void wapp_c16_list_push_back(C16List *list, C16Node *node);
|
||||
void wapp_c16_list_insert(C16List *list, C16Node *node, u64 index);
|
||||
C16Node *wapp_c16_list_pop_front(C16List *list);
|
||||
C16Node *wapp_c16_list_pop_back(C16List *list);
|
||||
C16Node *wapp_c16_list_remove(C16List *list, u64 index);
|
||||
void wapp_c16_list_empty(C16List *list);
|
||||
C32Node *wapp_c32_list_get(const C32List *list, u64 index);
|
||||
void wapp_c32_list_push_front(C32List *list, C32Node *node);
|
||||
void wapp_c32_list_push_back(C32List *list, C32Node *node);
|
||||
void wapp_c32_list_insert(C32List *list, C32Node *node, u64 index);
|
||||
C32Node *wapp_c32_list_pop_front(C32List *list);
|
||||
C32Node *wapp_c32_list_pop_back(C32List *list);
|
||||
C32Node *wapp_c32_list_remove(C32List *list, u64 index);
|
||||
void wapp_c32_list_empty(C32List *list);
|
||||
I8Node *wapp_i8_list_get(const I8List *list, u64 index);
|
||||
void wapp_i8_list_push_front(I8List *list, I8Node *node);
|
||||
void wapp_i8_list_push_back(I8List *list, I8Node *node);
|
||||
void wapp_i8_list_insert(I8List *list, I8Node *node, u64 index);
|
||||
I8Node *wapp_i8_list_pop_front(I8List *list);
|
||||
I8Node *wapp_i8_list_pop_back(I8List *list);
|
||||
I8Node *wapp_i8_list_remove(I8List *list, u64 index);
|
||||
void wapp_i8_list_empty(I8List *list);
|
||||
I16Node *wapp_i16_list_get(const I16List *list, u64 index);
|
||||
void wapp_i16_list_push_front(I16List *list, I16Node *node);
|
||||
void wapp_i16_list_push_back(I16List *list, I16Node *node);
|
||||
void wapp_i16_list_insert(I16List *list, I16Node *node, u64 index);
|
||||
I16Node *wapp_i16_list_pop_front(I16List *list);
|
||||
I16Node *wapp_i16_list_pop_back(I16List *list);
|
||||
I16Node *wapp_i16_list_remove(I16List *list, u64 index);
|
||||
void wapp_i16_list_empty(I16List *list);
|
||||
I32Node *wapp_i32_list_get(const I32List *list, u64 index);
|
||||
void wapp_i32_list_push_front(I32List *list, I32Node *node);
|
||||
void wapp_i32_list_push_back(I32List *list, I32Node *node);
|
||||
void wapp_i32_list_insert(I32List *list, I32Node *node, u64 index);
|
||||
I32Node *wapp_i32_list_pop_front(I32List *list);
|
||||
I32Node *wapp_i32_list_pop_back(I32List *list);
|
||||
I32Node *wapp_i32_list_remove(I32List *list, u64 index);
|
||||
void wapp_i32_list_empty(I32List *list);
|
||||
I64Node *wapp_i64_list_get(const I64List *list, u64 index);
|
||||
void wapp_i64_list_push_front(I64List *list, I64Node *node);
|
||||
void wapp_i64_list_push_back(I64List *list, I64Node *node);
|
||||
void wapp_i64_list_insert(I64List *list, I64Node *node, u64 index);
|
||||
I64Node *wapp_i64_list_pop_front(I64List *list);
|
||||
I64Node *wapp_i64_list_pop_back(I64List *list);
|
||||
I64Node *wapp_i64_list_remove(I64List *list, u64 index);
|
||||
void wapp_i64_list_empty(I64List *list);
|
||||
U8Node *wapp_u8_list_get(const U8List *list, u64 index);
|
||||
void wapp_u8_list_push_front(U8List *list, U8Node *node);
|
||||
void wapp_u8_list_push_back(U8List *list, U8Node *node);
|
||||
void wapp_u8_list_insert(U8List *list, U8Node *node, u64 index);
|
||||
U8Node *wapp_u8_list_pop_front(U8List *list);
|
||||
U8Node *wapp_u8_list_pop_back(U8List *list);
|
||||
U8Node *wapp_u8_list_remove(U8List *list, u64 index);
|
||||
void wapp_u8_list_empty(U8List *list);
|
||||
U16Node *wapp_u16_list_get(const U16List *list, u64 index);
|
||||
void wapp_u16_list_push_front(U16List *list, U16Node *node);
|
||||
void wapp_u16_list_push_back(U16List *list, U16Node *node);
|
||||
void wapp_u16_list_insert(U16List *list, U16Node *node, u64 index);
|
||||
U16Node *wapp_u16_list_pop_front(U16List *list);
|
||||
U16Node *wapp_u16_list_pop_back(U16List *list);
|
||||
U16Node *wapp_u16_list_remove(U16List *list, u64 index);
|
||||
void wapp_u16_list_empty(U16List *list);
|
||||
U32Node *wapp_u32_list_get(const U32List *list, u64 index);
|
||||
void wapp_u32_list_push_front(U32List *list, U32Node *node);
|
||||
void wapp_u32_list_push_back(U32List *list, U32Node *node);
|
||||
void wapp_u32_list_insert(U32List *list, U32Node *node, u64 index);
|
||||
U32Node *wapp_u32_list_pop_front(U32List *list);
|
||||
U32Node *wapp_u32_list_pop_back(U32List *list);
|
||||
U32Node *wapp_u32_list_remove(U32List *list, u64 index);
|
||||
void wapp_u32_list_empty(U32List *list);
|
||||
U64Node *wapp_u64_list_get(const U64List *list, u64 index);
|
||||
void wapp_u64_list_push_front(U64List *list, U64Node *node);
|
||||
void wapp_u64_list_push_back(U64List *list, U64Node *node);
|
||||
void wapp_u64_list_insert(U64List *list, U64Node *node, u64 index);
|
||||
U64Node *wapp_u64_list_pop_front(U64List *list);
|
||||
U64Node *wapp_u64_list_pop_back(U64List *list);
|
||||
U64Node *wapp_u64_list_remove(U64List *list, u64 index);
|
||||
void wapp_u64_list_empty(U64List *list);
|
||||
F32Node *wapp_f32_list_get(const F32List *list, u64 index);
|
||||
void wapp_f32_list_push_front(F32List *list, F32Node *node);
|
||||
void wapp_f32_list_push_back(F32List *list, F32Node *node);
|
||||
void wapp_f32_list_insert(F32List *list, F32Node *node, u64 index);
|
||||
F32Node *wapp_f32_list_pop_front(F32List *list);
|
||||
F32Node *wapp_f32_list_pop_back(F32List *list);
|
||||
F32Node *wapp_f32_list_remove(F32List *list, u64 index);
|
||||
void wapp_f32_list_empty(F32List *list);
|
||||
F64Node *wapp_f64_list_get(const F64List *list, u64 index);
|
||||
void wapp_f64_list_push_front(F64List *list, F64Node *node);
|
||||
void wapp_f64_list_push_back(F64List *list, F64Node *node);
|
||||
void wapp_f64_list_insert(F64List *list, F64Node *node, u64 index);
|
||||
F64Node *wapp_f64_list_pop_front(F64List *list);
|
||||
F64Node *wapp_f64_list_pop_back(F64List *list);
|
||||
F64Node *wapp_f64_list_remove(F64List *list, u64 index);
|
||||
void wapp_f64_list_empty(F64List *list);
|
||||
F128Node *wapp_f128_list_get(const F128List *list, u64 index);
|
||||
void wapp_f128_list_push_front(F128List *list, F128Node *node);
|
||||
void wapp_f128_list_push_back(F128List *list, F128Node *node);
|
||||
void wapp_f128_list_insert(F128List *list, F128Node *node, u64 index);
|
||||
F128Node *wapp_f128_list_pop_front(F128List *list);
|
||||
F128Node *wapp_f128_list_pop_back(F128List *list);
|
||||
F128Node *wapp_f128_list_remove(F128List *list, u64 index);
|
||||
void wapp_f128_list_empty(F128List *list);
|
||||
IptrNode *wapp_iptr_list_get(const IptrList *list, u64 index);
|
||||
void wapp_iptr_list_push_front(IptrList *list, IptrNode *node);
|
||||
void wapp_iptr_list_push_back(IptrList *list, IptrNode *node);
|
||||
void wapp_iptr_list_insert(IptrList *list, IptrNode *node, u64 index);
|
||||
IptrNode *wapp_iptr_list_pop_front(IptrList *list);
|
||||
IptrNode *wapp_iptr_list_pop_back(IptrList *list);
|
||||
IptrNode *wapp_iptr_list_remove(IptrList *list, u64 index);
|
||||
void wapp_iptr_list_empty(IptrList *list);
|
||||
UptrNode *wapp_uptr_list_get(const UptrList *list, u64 index);
|
||||
void wapp_uptr_list_push_front(UptrList *list, UptrNode *node);
|
||||
void wapp_uptr_list_push_back(UptrList *list, UptrNode *node);
|
||||
void wapp_uptr_list_insert(UptrList *list, UptrNode *node, u64 index);
|
||||
UptrNode *wapp_uptr_list_pop_front(UptrList *list);
|
||||
UptrNode *wapp_uptr_list_pop_back(UptrList *list);
|
||||
UptrNode *wapp_uptr_list_remove(UptrList *list, u64 index);
|
||||
void wapp_uptr_list_empty(UptrList *list);
|
||||
|
||||
#ifdef WAPP_PLATFORM_CPP
|
||||
END_C_LINKAGE
|
||||
#endif // !WAPP_PLATFORM_CPP
|
||||
|
||||
#endif // !DBL_LIST_H
|
35
wapp/primitives/mem_allocator/mem_allocator.c
Normal file
35
wapp/primitives/mem_allocator/mem_allocator.c
Normal file
@ -0,0 +1,35 @@
|
||||
// vim:fileencoding=utf-8:foldmethod=marker
|
||||
|
||||
#include "mem_allocator.h"
|
||||
#include "../../common/aliases/aliases.h"
|
||||
#include "../../common/assert/assert.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
void *wapp_mem_allocator_alloc(const Allocator *allocator, u64 size) {
|
||||
wapp_debug_assert(allocator != NULL && (allocator->alloc) != NULL, "`allocator` and `allocator->alloc` should not be NULL");
|
||||
return allocator->alloc(size, allocator->obj);
|
||||
}
|
||||
|
||||
void *wapp_mem_allocator_alloc_aligned(const Allocator *allocator, u64 size, u64 alignment) {
|
||||
wapp_debug_assert(allocator != NULL && (allocator->alloc_aligned) != NULL, "`allocator` and `allocator->alloc_aligned` should not be NULL");
|
||||
return allocator->alloc_aligned(size, alignment, allocator->obj);
|
||||
}
|
||||
|
||||
void *wapp_mem_allocator_realloc(const Allocator *allocator, void *ptr, u64 old_size, u64 new_size) {
|
||||
wapp_debug_assert(allocator != NULL && (allocator->realloc) != NULL, "`allocator` and `allocator->realloc` should not be NULL");
|
||||
return allocator->realloc(ptr, old_size, new_size, allocator->obj);
|
||||
}
|
||||
|
||||
void *wapp_mem_allocator_realloc_aligned(const Allocator *allocator, void *ptr, u64 old_size,
|
||||
u64 new_size, u64 alignment) {
|
||||
wapp_debug_assert(allocator != NULL && (allocator->realloc_aligned) != NULL, "`allocator` and `allocator->realloc_aligned` should not be NULL");
|
||||
return allocator->realloc_aligned(ptr, old_size, new_size, alignment, allocator->obj);
|
||||
}
|
||||
|
||||
void wapp_mem_allocator_free(const Allocator *allocator, void **ptr, u64 size) {
|
||||
if (!allocator || !(allocator->free)) {
|
||||
return;
|
||||
}
|
||||
|
||||
allocator->free(ptr, size, allocator->obj);
|
||||
}
|
50
wapp/primitives/mem_allocator/mem_allocator.h
Normal file
50
wapp/primitives/mem_allocator/mem_allocator.h
Normal file
@ -0,0 +1,50 @@
|
||||
// vim:fileencoding=utf-8:foldmethod=marker
|
||||
|
||||
#ifndef MEM_ALLOCATOR_H
|
||||
#define MEM_ALLOCATOR_H
|
||||
|
||||
#include "../../common/aliases/aliases.h"
|
||||
#include "../../common/platform/platform.h"
|
||||
#include <string.h>
|
||||
|
||||
#ifdef WAPP_PLATFORM_CPP
|
||||
BEGIN_C_LINKAGE
|
||||
#endif // !WAPP_PLATFORM_CPP
|
||||
|
||||
typedef void *(MemAllocFunc)(u64 size, void *alloc_obj);
|
||||
typedef void *(MemAllocAlignedFunc)(u64 size, u64 alignment, void *alloc_obj);
|
||||
typedef void *(MemReallocFunc)(void *ptr, u64 old_size, u64 new_size, void *alloc_obj);
|
||||
typedef void *(MemReallocAlignedFunc)(void *ptr, u64 old_size, u64 new_size, u64 alignment, void *alloc_obj);
|
||||
typedef void (MemFreeFunc)(void **ptr, u64 size, void *alloc_obj);
|
||||
|
||||
typedef struct allocator Allocator;
|
||||
struct allocator {
|
||||
void *obj;
|
||||
MemAllocFunc *alloc;
|
||||
MemAllocAlignedFunc *alloc_aligned;
|
||||
MemReallocFunc *realloc;
|
||||
MemReallocAlignedFunc *realloc_aligned;
|
||||
MemFreeFunc *free;
|
||||
};
|
||||
|
||||
#ifdef WAPP_PLATFORM_CPP
|
||||
#define wapp_mem_allocator_invalid(ALLOCATOR) ([&]() { \
|
||||
Allocator alloc{}; \
|
||||
return memcmp(ALLOCATOR, &alloc, sizeof(Allocator)) == 0; \
|
||||
}())
|
||||
#else
|
||||
#define wapp_mem_allocator_invalid(ALLOCATOR) (memcmp(ALLOCATOR, &((Allocator){0}), sizeof(Allocator)) == 0)
|
||||
#endif // !WAPP_PLATFORM_CPP
|
||||
|
||||
void *wapp_mem_allocator_alloc(const Allocator *allocator, u64 size);
|
||||
void *wapp_mem_allocator_alloc_aligned(const Allocator *allocator, u64 size, u64 alignment);
|
||||
void *wapp_mem_allocator_realloc(const Allocator *allocator, void *ptr, u64 old_size, u64 new_size);
|
||||
void *wapp_mem_allocator_realloc_aligned(const Allocator *allocator, void *ptr, u64 old_size,
|
||||
u64 new_size, u64 alignment);
|
||||
void wapp_mem_allocator_free(const Allocator *allocator, void **ptr, u64 size);
|
||||
|
||||
#ifdef WAPP_PLATFORM_CPP
|
||||
END_C_LINKAGE
|
||||
#endif // !WAPP_PLATFORM_CPP
|
||||
|
||||
#endif // !MEM_ALLOCATOR_H
|
446
wapp/primitives/strings/str8/str8.c
Normal file
446
wapp/primitives/strings/str8/str8.c
Normal file
@ -0,0 +1,446 @@
|
||||
// vim:fileencoding=utf-8:foldmethod=marker
|
||||
|
||||
#include "str8.h"
|
||||
#include "../../../common/aliases/aliases.h"
|
||||
#include "../../../common/assert/assert.h"
|
||||
#include "../../mem_allocator/mem_allocator.h"
|
||||
#include <stdarg.h>
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#define STR8_BUF_ALLOC_SIZE(CAPACITY) (sizeof(Str8) + sizeof(c8) * CAPACITY)
|
||||
|
||||
Str8 *wapp_str8_alloc_buf(const Allocator *allocator, u64 capacity) {
|
||||
wapp_debug_assert(allocator != NULL, "`allocator` should not be NULL");
|
||||
|
||||
Str8 *str = wapp_mem_allocator_alloc(allocator, STR8_BUF_ALLOC_SIZE(capacity));
|
||||
if (!str) {
|
||||
goto RETURN_STR8;
|
||||
}
|
||||
|
||||
str->buf = (u8 *)str + sizeof(Str8);
|
||||
str->size = 0;
|
||||
str->capacity = capacity;
|
||||
|
||||
RETURN_STR8:
|
||||
return str;
|
||||
}
|
||||
|
||||
Str8 *wapp_str8_alloc_and_fill_buf(const Allocator *allocator, u64 capacity) {
|
||||
Str8 *out = wapp_str8_alloc_buf(allocator, capacity);
|
||||
if (out) {
|
||||
memset(out->buf, 0, capacity);
|
||||
out->size = capacity;
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
Str8 *wapp_str8_alloc_cstr(const Allocator *allocator, const char *str) {
|
||||
wapp_debug_assert(allocator != NULL && str != NULL, "`allocator` and `str` should not be NULL");
|
||||
|
||||
u64 length = strlen(str);
|
||||
Str8 *output = wapp_str8_alloc_buf(allocator, length * 2);
|
||||
if (!output) {
|
||||
goto RETURN_ALLOC_CSTR;
|
||||
}
|
||||
|
||||
output->size = length;
|
||||
memcpy(output->buf, str, length);
|
||||
|
||||
RETURN_ALLOC_CSTR:
|
||||
return output;
|
||||
}
|
||||
|
||||
Str8 *wapp_str8_alloc_str8(const Allocator *allocator, Str8RO *str) {
|
||||
wapp_debug_assert(allocator != NULL && str != NULL, "`allocator` and `str` should not be NULL");
|
||||
|
||||
Str8 *output = wapp_str8_alloc_buf(allocator, str->capacity);
|
||||
if (!output) {
|
||||
goto RETURN_ALLOC_STR8;
|
||||
}
|
||||
|
||||
output->size = str->size;
|
||||
memcpy(output->buf, str->buf, str->size);
|
||||
|
||||
RETURN_ALLOC_STR8:
|
||||
return output;
|
||||
}
|
||||
|
||||
Str8 *wapp_str8_alloc_substr(const Allocator *allocator, Str8RO *str, u64 start, u64 end) {
|
||||
wapp_debug_assert(allocator != NULL && str != NULL, "`allocator` and `str` should not be NULL");
|
||||
|
||||
Str8 *output = NULL;
|
||||
|
||||
if (start >= str->size || start >= end) {
|
||||
goto RETURN_ALLOC_SUBSTR;
|
||||
}
|
||||
|
||||
if (end > str->size) {
|
||||
end = str->size;
|
||||
}
|
||||
|
||||
output = wapp_str8_alloc_buf(allocator, str->capacity);
|
||||
if (!output) {
|
||||
goto RETURN_ALLOC_SUBSTR;
|
||||
}
|
||||
|
||||
output->size = end - start;
|
||||
memcpy(output->buf, str->buf + start, output->size);
|
||||
|
||||
RETURN_ALLOC_SUBSTR:
|
||||
return output;
|
||||
}
|
||||
|
||||
void wapp_str8_dealloc_buf(const Allocator *allocator, Str8 **str) {
|
||||
wapp_debug_assert(allocator != NULL && str != NULL && (*str) != NULL, "Either `allocator` is NULL or `str` is an invalid double pointer");
|
||||
wapp_mem_allocator_free(allocator, (void **)str, STR8_BUF_ALLOC_SIZE((*str)->capacity));
|
||||
}
|
||||
|
||||
c8 wapp_str8_get(const Str8 *str, u64 index) {
|
||||
if (index >= str->size) {
|
||||
return '\0';
|
||||
}
|
||||
|
||||
return str->buf[index];
|
||||
}
|
||||
|
||||
void wapp_str8_set(Str8 *str, u64 index, c8 c) {
|
||||
if (index >= str->size) {
|
||||
return;
|
||||
}
|
||||
|
||||
str->buf[index] = c;
|
||||
}
|
||||
|
||||
void wapp_str8_push_back(Str8 *str, c8 c) {
|
||||
if (!(str->size < str->capacity)) {
|
||||
return;
|
||||
}
|
||||
|
||||
u64 index = (str->size)++;
|
||||
wapp_str8_set(str, index, c);
|
||||
}
|
||||
|
||||
bool wapp_str8_equal(Str8RO *s1, Str8RO *s2) {
|
||||
if (s1->size != s2->size) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return wapp_str8_equal_to_count(s1, s2, s1->size);
|
||||
}
|
||||
|
||||
bool wapp_str8_equal_to_count(Str8RO* s1, Str8RO* s2, u64 count) {
|
||||
if (!s1 || !s2) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return memcmp(s1->buf, s2->buf, count) == 0;
|
||||
}
|
||||
|
||||
Str8 wapp_str8_slice(Str8RO *str, u64 start, u64 end) {
|
||||
if (start >= str->size || start >= end) {
|
||||
start = str->size;
|
||||
end = str->size;
|
||||
}
|
||||
|
||||
if (end > str->size) {
|
||||
end = str->size;
|
||||
}
|
||||
|
||||
return (Str8RO){
|
||||
.capacity = end - start,
|
||||
.size = end - start,
|
||||
.buf = str->buf + start,
|
||||
};
|
||||
}
|
||||
|
||||
Str8 *wapp_str8_alloc_concat(const Allocator *allocator, Str8 *dst, Str8RO *src) {
|
||||
wapp_debug_assert(allocator != NULL && dst != NULL && src != NULL, "`allocator`, `dst` and `src` should not be NULL");
|
||||
|
||||
Str8 *output = NULL;
|
||||
u64 remaining = dst->capacity - dst->size;
|
||||
if (src->size <= remaining) {
|
||||
output = dst;
|
||||
goto COPY_STRING_STR8_CONCAT;
|
||||
}
|
||||
|
||||
u64 capacity = dst->capacity + src->size;
|
||||
|
||||
output = wapp_str8_alloc_buf(allocator, capacity);
|
||||
if (!output) {
|
||||
goto RETURN_STR8_CONCAT;
|
||||
}
|
||||
|
||||
wapp_str8_concat_capped(output, dst);
|
||||
|
||||
COPY_STRING_STR8_CONCAT:
|
||||
wapp_str8_concat_capped(output, src);
|
||||
|
||||
RETURN_STR8_CONCAT:
|
||||
return output;
|
||||
}
|
||||
|
||||
void wapp_str8_concat_capped(Str8 *dst, Str8RO *src) {
|
||||
wapp_debug_assert(dst != NULL && src != NULL, "`dst` and `src` should not be NULL");
|
||||
|
||||
u64 remaining = dst->capacity - dst->size;
|
||||
u64 to_copy = remaining < src->size ? remaining : src->size;
|
||||
|
||||
memcpy(dst->buf + dst->size, src->buf, to_copy);
|
||||
dst->size += to_copy;
|
||||
}
|
||||
|
||||
void wapp_str8_copy_cstr_capped(Str8 *dst, const char *src) {
|
||||
wapp_debug_assert(dst != NULL && src != NULL, "`dst` and `src` should not be NULL");
|
||||
|
||||
u64 length = strlen(src);
|
||||
u64 to_copy = length <= dst->capacity ? length : dst->capacity;
|
||||
|
||||
memset(dst->buf, 0, dst->size);
|
||||
memcpy(dst->buf, src, to_copy);
|
||||
dst->size = to_copy;
|
||||
}
|
||||
|
||||
void wapp_str8_copy_str8_capped(Str8 *dst, Str8RO *src) {
|
||||
wapp_debug_assert(dst != NULL && src != NULL, "`dst` and `src` should not be NULL");
|
||||
|
||||
u64 to_copy = src->size <= dst->capacity ? src->size : dst->capacity;
|
||||
|
||||
memset(dst->buf, 0, dst->size);
|
||||
memcpy(dst->buf, src->buf, to_copy);
|
||||
dst->size = to_copy;
|
||||
}
|
||||
|
||||
void wapp_str8_copy_to_cstr(char *dst, Str8RO *src, u64 dst_capacity) {
|
||||
wapp_debug_assert(dst != NULL && src != NULL, "`dst` and `src` should not be NULL");
|
||||
|
||||
u64 to_copy = src->size < dst_capacity ? src->size : dst_capacity - 1;
|
||||
|
||||
memset(dst, 0, dst_capacity);
|
||||
memcpy(dst, src->buf, to_copy);
|
||||
}
|
||||
|
||||
void wapp_str8_format(Str8 *dst, const char *format, ...) {
|
||||
wapp_debug_assert(dst != NULL && format != NULL, "`dst` and `format` should not be NULL");
|
||||
|
||||
va_list args1;
|
||||
va_list args2;
|
||||
|
||||
va_start(args1, format);
|
||||
va_copy(args2, args1);
|
||||
|
||||
u64 total_size = vsnprintf(NULL, 0, format, args1);
|
||||
dst->size = total_size <= dst->capacity ? total_size : dst->capacity;
|
||||
|
||||
vsnprintf((char *)(dst->buf), dst->capacity, format, args2);
|
||||
|
||||
va_end(args1);
|
||||
va_end(args2);
|
||||
}
|
||||
|
||||
i64 wapp_str8_find(Str8RO *str, Str8RO substr) {
|
||||
if (!str || substr.size > str->size) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
// NOTE (Abdelrahman): Uses a while loop instead of a for loop to get rid of
|
||||
// MSVC Spectre mitigation warnings
|
||||
u64 char_index = 0;
|
||||
bool running = char_index < str->size;
|
||||
while (running) {
|
||||
const c8 *sub = str->buf + char_index;
|
||||
if (memcmp(sub, substr.buf, substr.size) == 0) {
|
||||
return char_index;
|
||||
}
|
||||
|
||||
++char_index;
|
||||
running = char_index < str->size;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
i64 wapp_str8_rfind(Str8RO *str, Str8RO substr) {
|
||||
if (!str || substr.size > str->size) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
// NOTE (Abdelrahman): Uses a while loop instead of a for loop to get rid of
|
||||
// MSVC Spectre mitigation warnings
|
||||
i64 char_index = str->size - substr.size;
|
||||
bool running = char_index >= 0;
|
||||
while (running) {
|
||||
const c8 *sub = str->buf + char_index;
|
||||
if (memcmp(sub, substr.buf, substr.size) == 0) {
|
||||
return char_index;
|
||||
}
|
||||
|
||||
--char_index;
|
||||
running = char_index >= 0;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
Str8List *wapp_str8_split_with_max(const Allocator *allocator, Str8RO *str, Str8RO *delimiter, i64 max_splits) {
|
||||
wapp_debug_assert(allocator != NULL && str != NULL && delimiter != NULL, "`allocator`, `str` and `delimiter` should not be NULL");
|
||||
|
||||
Str8List *output = wapp_mem_allocator_alloc(allocator, sizeof(Str8List));
|
||||
|
||||
if (delimiter->size > str->size) {
|
||||
Str8 *full = wapp_str8_alloc_str8(allocator, str);
|
||||
Str8Node *node = wapp_mem_allocator_alloc(allocator, sizeof(Str8Node));
|
||||
if (node) {
|
||||
node->item = full;
|
||||
wapp_str8_list_push_back(output, node);
|
||||
}
|
||||
|
||||
goto RETURN_STR8_SPLIT;
|
||||
}
|
||||
|
||||
i64 start = 0;
|
||||
i64 end = 0;
|
||||
i64 splits = 0;
|
||||
Str8 *rest = wapp_str8_alloc_str8(allocator, str);
|
||||
Str8 *before_str;
|
||||
|
||||
while ((end = wapp_str8_find(rest, *delimiter)) != -1) {
|
||||
if (max_splits > 0 && splits >= max_splits) {
|
||||
break;
|
||||
}
|
||||
|
||||
before_str = wapp_str8_alloc_substr(allocator, str, start, start + end);
|
||||
Str8Node *node = wapp_mem_allocator_alloc(allocator, sizeof(Str8Node));
|
||||
if (node && before_str) {
|
||||
node->item = before_str;
|
||||
wapp_str8_list_push_back(output, node);
|
||||
}
|
||||
|
||||
wapp_mem_allocator_free(allocator, (void **)&rest, sizeof(Str8));
|
||||
rest = wapp_str8_alloc_substr(allocator, str, start + end + delimiter->size, str->size);
|
||||
start += end + delimiter->size;
|
||||
|
||||
++splits;
|
||||
}
|
||||
|
||||
// Ensure the last part of the string after the delimiter is added to the list
|
||||
rest = wapp_str8_alloc_substr(allocator, str, start, str->size);
|
||||
Str8Node *node = wapp_mem_allocator_alloc(allocator, sizeof(Str8Node));
|
||||
if (node && rest) {
|
||||
node->item = rest;
|
||||
wapp_str8_list_push_back(output, node);
|
||||
}
|
||||
|
||||
RETURN_STR8_SPLIT:
|
||||
return output;
|
||||
}
|
||||
|
||||
Str8List *wapp_str8_rsplit_with_max(const Allocator *allocator, Str8RO *str, Str8RO *delimiter, i64 max_splits) {
|
||||
wapp_debug_assert(allocator != NULL && str != NULL && delimiter != NULL, "`allocator`, `str` and `delimiter` should not be NULL");
|
||||
|
||||
Str8List *output = wapp_mem_allocator_alloc(allocator, sizeof(Str8List));
|
||||
|
||||
if (delimiter->size > str->size) {
|
||||
Str8 *full = wapp_str8_alloc_str8(allocator, str);
|
||||
Str8Node *node = wapp_mem_allocator_alloc(allocator, sizeof(Str8Node));
|
||||
if (node && full) {
|
||||
node->item = full;
|
||||
wapp_str8_list_push_back(output, node);
|
||||
}
|
||||
|
||||
goto RETURN_STR8_SPLIT;
|
||||
}
|
||||
|
||||
i64 end = 0;
|
||||
i64 splits = 0;
|
||||
Str8 *rest = wapp_str8_alloc_str8(allocator, str);
|
||||
Str8 *after_str;
|
||||
|
||||
while ((end = wapp_str8_rfind(rest, *delimiter)) != -1) {
|
||||
if (max_splits > 0 && splits >= max_splits) {
|
||||
break;
|
||||
}
|
||||
|
||||
after_str = wapp_str8_alloc_substr(allocator, rest, end + delimiter->size, str->size);
|
||||
Str8Node *node = wapp_mem_allocator_alloc(allocator, sizeof(Str8Node));
|
||||
if (node) {
|
||||
node->item = after_str;
|
||||
wapp_str8_list_push_front(output, node);
|
||||
}
|
||||
|
||||
wapp_mem_allocator_free(allocator, (void **)&rest, sizeof(Str8));
|
||||
rest = wapp_str8_alloc_substr(allocator, rest, 0, end);
|
||||
|
||||
++splits;
|
||||
}
|
||||
|
||||
rest = wapp_str8_alloc_substr(allocator, str, 0, rest->size);
|
||||
Str8Node *node = wapp_mem_allocator_alloc(allocator, sizeof(Str8Node));
|
||||
if (node && rest) {
|
||||
node->item = rest;
|
||||
wapp_str8_list_push_front(output, node);
|
||||
}
|
||||
|
||||
RETURN_STR8_SPLIT:
|
||||
return output;
|
||||
}
|
||||
|
||||
Str8 *wapp_str8_join(const Allocator *allocator, const Str8List *list, Str8RO *delimiter) {
|
||||
wapp_debug_assert(allocator != NULL && list != NULL && delimiter != NULL, "`allocator`, `list` and `delimiter` should not be NULL");
|
||||
|
||||
u64 capacity = wapp_str8_list_total_size(list) + (delimiter->size * (list->node_count - 1));
|
||||
Str8 *output = wapp_str8_alloc_buf(allocator, capacity * 2);
|
||||
|
||||
// NOTE (Abdelrahman): Uses a while loop instead of a for loop to get rid of
|
||||
// MSVC Spectre mitigation warnings
|
||||
Str8Node *node;
|
||||
u64 node_index = 0;
|
||||
bool running = node_index < list->node_count;
|
||||
while (running) {
|
||||
node = wapp_str8_list_get(list, node_index);
|
||||
if (!node) {
|
||||
break;
|
||||
}
|
||||
|
||||
wapp_str8_concat_capped(output, node->item);
|
||||
|
||||
// NOTE (Abdelrahman): Comparison extracted to variable to silence
|
||||
// MSVC Spectre mitigation warnings
|
||||
bool not_last = node_index + 1 < list->node_count;
|
||||
if (not_last) {
|
||||
wapp_str8_concat_capped(output, delimiter);
|
||||
}
|
||||
|
||||
++node_index;
|
||||
running = node_index < list->node_count;
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
u64 wapp_str8_list_total_size(const Str8List *list) {
|
||||
if (!list) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// NOTE (Abdelrahman): Uses a while loop instead of a for loop to get rid of
|
||||
// MSVC Spectre mitigation warnings
|
||||
Str8Node* node;
|
||||
u64 node_index = 0;
|
||||
u64 output = 0;
|
||||
bool running = node_index < list->node_count;
|
||||
while (running) {
|
||||
node = wapp_str8_list_get(list, node_index);
|
||||
if (!node) {
|
||||
break;
|
||||
}
|
||||
|
||||
output += node->item->size;
|
||||
++node_index;
|
||||
running = node_index < list->node_count;
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
138
wapp/primitives/strings/str8/str8.h
Normal file
138
wapp/primitives/strings/str8/str8.h
Normal file
@ -0,0 +1,138 @@
|
||||
// vim:fileencoding=utf-8:foldmethod=marker
|
||||
|
||||
#ifndef STR8_H
|
||||
#define STR8_H
|
||||
|
||||
#include "../../../common/aliases/aliases.h"
|
||||
#include "../../../common/assert/assert.h"
|
||||
#include "../../../common/platform/platform.h"
|
||||
#include "../../../primitives/dbl_list/dbl_list.h"
|
||||
#include "../../mem_allocator/mem_allocator.h"
|
||||
#include <string.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#ifdef WAPP_PLATFORM_CPP
|
||||
BEGIN_C_LINKAGE
|
||||
#endif // !WAPP_PLATFORM_CPP
|
||||
|
||||
typedef struct str8 Str8;
|
||||
struct str8 {
|
||||
u64 capacity;
|
||||
u64 size;
|
||||
c8 *buf;
|
||||
};
|
||||
|
||||
typedef const Str8 Str8RO;
|
||||
|
||||
/**
|
||||
* Utilities to be used with printf functions
|
||||
*/
|
||||
#define WAPP_STR8_SPEC "%.*s"
|
||||
#define wapp_str8_varg(STRING) (int)((STRING).size), (STRING).buf
|
||||
|
||||
/**
|
||||
* Str8 stack buffers
|
||||
*/
|
||||
|
||||
#ifdef WAPP_PLATFORM_CPP
|
||||
// Uses a lambda to achieve the same behaviour achieved by the C macro
|
||||
#define wapp_str8_buf(CAPACITY) ([&](){ \
|
||||
persistent c8 buf[CAPACITY] = {}; \
|
||||
memset(buf, 0, CAPACITY); \
|
||||
return Str8{CAPACITY, 0, buf}; \
|
||||
}())
|
||||
|
||||
// Uses a lambda to achieve the same behaviour achieved by the C macro
|
||||
#define wapp_str8_lit(STRING) ([&]() { \
|
||||
persistent c8 buf[sizeof(STRING) * 2] = {}; \
|
||||
memcpy(buf, STRING, sizeof(STRING)); \
|
||||
return Str8{(sizeof(STRING) - 1) * 2, sizeof(STRING) - 1, buf}; \
|
||||
}())
|
||||
|
||||
#define wapp_str8_lit_ro(STRING) Str8RO{sizeof(STRING) - 1, sizeof(STRING) - 1, (c8 *)STRING}
|
||||
#define wapp_str8_lit_ro_initialiser_list(STRING) {sizeof(STRING) - 1, sizeof(STRING) - 1, (c8 *)STRING}
|
||||
#else
|
||||
#define wapp_str8_buf(CAPACITY) ((Str8){.capacity = CAPACITY, .size = 0, .buf = (c8[CAPACITY]){0}})
|
||||
|
||||
// Utilises the fact that memcpy returns pointer to dest buffer and that getting
|
||||
// address of compound literals is valid in C to create a string on the stack
|
||||
#define wapp_str8_lit(STRING) ((Str8){.capacity = (sizeof(STRING) - 1) * 2, \
|
||||
.size = sizeof(STRING) - 1, \
|
||||
.buf = memcpy(&((c8 [sizeof(STRING) * 2]){0}), STRING, sizeof(STRING))})
|
||||
#define wapp_str8_lit_ro(STRING) ((Str8RO){.capacity = sizeof(STRING) - 1, \
|
||||
.size = sizeof(STRING) - 1, \
|
||||
.buf = (c8 *)STRING})
|
||||
// To be used only when initialising a static storage variable in compilers that don't support
|
||||
// initialisers with the syntax of wapp_str8_lit_ro (e.g. gcc). Should only be used when necessary
|
||||
// and only be assigned to a Str8RO variable to avoid any attempt at modifying the string
|
||||
#define wapp_str8_lit_ro_initialiser_list(STRING) {.capacity = sizeof(STRING) - 1, \
|
||||
.size = sizeof(STRING) - 1, \
|
||||
.buf = (c8 *)STRING}
|
||||
#endif // !WAPP_PLATFORM_CPP
|
||||
|
||||
/**
|
||||
* Str8 allocated buffers
|
||||
*/
|
||||
Str8 *wapp_str8_alloc_buf(const Allocator *allocator, u64 capacity);
|
||||
Str8 *wapp_str8_alloc_and_fill_buf(const Allocator *allocator, u64 capacity);
|
||||
Str8 *wapp_str8_alloc_cstr(const Allocator *allocator, const char *str);
|
||||
Str8 *wapp_str8_alloc_str8(const Allocator *allocator, Str8RO *str);
|
||||
Str8 *wapp_str8_alloc_substr(const Allocator *allocator, Str8RO *str, u64 start, u64 end);
|
||||
Str8 *wapp_str8_alloc_concat(const Allocator *allocator, Str8 *dst, Str8RO *src);
|
||||
// Only needed for allocators like malloc where each allocation has to be freed on its own.
|
||||
// No need to use it for allocators like Arena.
|
||||
void wapp_str8_dealloc_buf(const Allocator *allocator, Str8 **str);
|
||||
|
||||
/**
|
||||
* Str8 utilities
|
||||
*/
|
||||
c8 wapp_str8_get(Str8RO *str, u64 index);
|
||||
void wapp_str8_set(Str8 *str, u64 index, c8 c);
|
||||
void wapp_str8_push_back(Str8 *str, c8 c);
|
||||
bool wapp_str8_equal(Str8RO *s1, Str8RO *s2);
|
||||
bool wapp_str8_equal_to_count(Str8RO* s1, Str8RO* s2, u64 count);
|
||||
Str8 wapp_str8_slice(Str8RO *str, u64 start, u64 end);
|
||||
void wapp_str8_concat_capped(Str8 *dst, Str8RO *src);
|
||||
void wapp_str8_copy_cstr_capped(Str8 *dst, const char *src);
|
||||
void wapp_str8_copy_str8_capped(Str8 *dst, Str8RO *src);
|
||||
void wapp_str8_copy_to_cstr(char *dst, Str8RO *src, u64 dst_capacity);
|
||||
void wapp_str8_format(Str8 *dst, const char *format, ...);
|
||||
|
||||
/**
|
||||
* Str8 find functions
|
||||
*/
|
||||
i64 wapp_str8_find(Str8RO *str, Str8RO substr);
|
||||
i64 wapp_str8_rfind(Str8RO *str, Str8RO substr);
|
||||
|
||||
/**
|
||||
* Str8 split and join
|
||||
*/
|
||||
#define wapp_str8_split(ALLOCATOR, STR, DELIMITER) wapp_str8_split_with_max(ALLOCATOR, STR, DELIMITER, -1)
|
||||
#define wapp_str8_rsplit(ALLOCATOR, STR, DELIMITER) wapp_str8_rsplit_with_max(ALLOCATOR, STR, DELIMITER, -1)
|
||||
Str8List *wapp_str8_split_with_max(const Allocator *allocator, Str8RO *str, Str8RO *delimiter, i64 max_splits);
|
||||
Str8List *wapp_str8_rsplit_with_max(const Allocator *allocator, Str8RO *str, Str8RO *delimiter, i64 max_splits);
|
||||
Str8 *wapp_str8_join(const Allocator *allocator, const Str8List *list, Str8RO *delimiter);
|
||||
|
||||
/**
|
||||
* Str8 list utilities
|
||||
*/
|
||||
#ifdef WAPP_PLATFORM_CPP
|
||||
#define wapp_str8_node_from_cstr(STRING) wapp_str8_list_node([&]() { \
|
||||
persistent Str8 str = wapp_str8_lit(STRING); \
|
||||
return &str; \
|
||||
}())
|
||||
#define wapp_str8_node_from_str8(STRING) wapp_str8_list_node([&]() { \
|
||||
persistent Str8 str = STRING; \
|
||||
return &str; \
|
||||
}())
|
||||
#else
|
||||
#define wapp_str8_node_from_cstr(STRING) wapp_str8_list_node(&wapp_str8_lit(STRING))
|
||||
#define wapp_str8_node_from_str8(STRING) wapp_str8_list_node(&(STRING))
|
||||
#endif // !WAPP_PLATFORM_CPP
|
||||
u64 wapp_str8_list_total_size(const Str8List *list);
|
||||
|
||||
#ifdef WAPP_PLATFORM_CPP
|
||||
END_C_LINKAGE
|
||||
#endif // !WAPP_PLATFORM_CPP
|
||||
|
||||
#endif // !STR8_H
|
12
wapp/primitives/wapp_primitives.c
Normal file
12
wapp/primitives/wapp_primitives.c
Normal file
@ -0,0 +1,12 @@
|
||||
// vim:fileencoding=utf-8:foldmethod=marker
|
||||
|
||||
#ifndef WAPP_PRIMITIVES_C
|
||||
#define WAPP_PRIMITIVES_C
|
||||
|
||||
#include "wapp_primitives.h"
|
||||
#include "array/array.c"
|
||||
#include "dbl_list/dbl_list.c"
|
||||
#include "mem_allocator/mem_allocator.c"
|
||||
#include "strings/str8/str8.c"
|
||||
|
||||
#endif // !WAPP_PRIMITIVES_C
|
12
wapp/primitives/wapp_primitives.h
Normal file
12
wapp/primitives/wapp_primitives.h
Normal file
@ -0,0 +1,12 @@
|
||||
// vim:fileencoding=utf-8:foldmethod=marker
|
||||
|
||||
#ifndef WAPP_PRIMITIVES_H
|
||||
#define WAPP_PRIMITIVES_H
|
||||
|
||||
#include "dbl_list/dbl_list.h"
|
||||
#include "array/array.h"
|
||||
#include "mem_allocator/mem_allocator.h"
|
||||
#include "strings/str8/str8.h"
|
||||
#include "../common/wapp_common.h"
|
||||
|
||||
#endif // !WAPP_PRIMITIVES_H
|
8
wapp/prng/wapp_prng.c
Normal file
8
wapp/prng/wapp_prng.c
Normal file
@ -0,0 +1,8 @@
|
||||
// vim:fileencoding=utf-8:foldmethod=marker
|
||||
|
||||
#ifndef WAPP_PRNG_C
|
||||
#define WAPP_PRNG_C
|
||||
|
||||
#include "xorshift/xorshift.c"
|
||||
|
||||
#endif // !WAPP_PRNG_C
|
9
wapp/prng/wapp_prng.h
Normal file
9
wapp/prng/wapp_prng.h
Normal file
@ -0,0 +1,9 @@
|
||||
// vim:fileencoding=utf-8:foldmethod=marker
|
||||
|
||||
#ifndef WAPP_PRNG_H
|
||||
#define WAPP_PRNG_H
|
||||
|
||||
#include "xorshift/xorshift.h"
|
||||
#include "../common/wapp_common.h"
|
||||
|
||||
#endif // !WAPP_PRNG_H
|
136
wapp/prng/xorshift/xorshift.c
Normal file
136
wapp/prng/xorshift/xorshift.c
Normal file
@ -0,0 +1,136 @@
|
||||
// vim:fileencoding=utf-8:foldmethod=marker
|
||||
|
||||
#include "xorshift.h"
|
||||
#include "../../common/aliases/aliases.h"
|
||||
#include "../../common/assert/assert.h"
|
||||
#include "../../common/platform/platform.h"
|
||||
#include <stdbool.h>
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
|
||||
typedef struct split_mix_64_state SplitMix64State;
|
||||
struct split_mix_64_state {
|
||||
u64 seed;
|
||||
};
|
||||
|
||||
internal u64 rol64(u64 x, u64 bits);
|
||||
internal u64 split_mix_64(SplitMix64State *state);
|
||||
internal void seed_os_generator(void);
|
||||
internal u64 generate_random_number(void);
|
||||
|
||||
XOR256State wapp_prng_xorshift_init_state(void) {
|
||||
persistent bool seeded = false;
|
||||
if (!seeded) {
|
||||
seeded = true;
|
||||
seed_os_generator();
|
||||
}
|
||||
|
||||
SplitMix64State sm64 = {.seed = generate_random_number()};
|
||||
|
||||
return (XOR256State){
|
||||
.x = split_mix_64(&sm64),
|
||||
.y = split_mix_64(&sm64),
|
||||
.z = split_mix_64(&sm64),
|
||||
.w = split_mix_64(&sm64),
|
||||
};
|
||||
}
|
||||
|
||||
u64 wapp_prng_xorshift_256(XOR256State *state) {
|
||||
u64 t = state->x ^ (state->x << 11);
|
||||
|
||||
state->x = state->y;
|
||||
state->y = state->z;
|
||||
state->z = state->w;
|
||||
state->w = (state->w ^ (state->w >> 19)) ^ (t ^ (t >> 8));
|
||||
|
||||
return state->w;
|
||||
}
|
||||
|
||||
u64 wapp_prng_xorshift_256ss(XOR256State *state) {
|
||||
const u64 result = rol64(state->z * 5, 7) * 9;
|
||||
const u64 t = state->z << 17;
|
||||
|
||||
state->y ^= state->w;
|
||||
state->x ^= state->z;
|
||||
state->z ^= state->y;
|
||||
state->w ^= state->x;
|
||||
|
||||
state->y ^= t;
|
||||
state->x = rol64(state->x, 45);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
u64 wapp_prng_xorshift_256p(XOR256State *state) {
|
||||
const u64 result = state->w + state->x;
|
||||
const u64 t = state->z << 17;
|
||||
|
||||
state->y ^= state->w;
|
||||
state->x ^= state->z;
|
||||
state->z ^= state->y;
|
||||
state->w ^= state->x;
|
||||
|
||||
state->y ^= t;
|
||||
state->x = rol64(state->x, 45);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
internal u64 rol64(u64 x, u64 bits) {
|
||||
return (x << bits) | (x >> (64 - bits));
|
||||
}
|
||||
|
||||
internal u64 split_mix_64(SplitMix64State *state) {
|
||||
state->seed += 0x9E3779B97f4A7C15;
|
||||
|
||||
u64 result = state->seed;
|
||||
result = (result ^ (result >> 30)) * 0xBF58476D1CE4E5B9;
|
||||
result = (result ^ (result >> 27)) * 0x94D049BB133111EB;
|
||||
|
||||
return result ^ (result >> 31);
|
||||
}
|
||||
|
||||
#if defined(WAPP_PLATFORM_C) && WAPP_PLATFORM_C_VERSION >= WAPP_PLATFORM_C11_VERSION
|
||||
#ifdef WAPP_PLATFORM_POSIX
|
||||
internal void seed_os_generator(void) {
|
||||
struct timespec ts = {0};
|
||||
int result = clock_gettime(CLOCK_MONOTONIC_RAW, &ts);
|
||||
wapp_runtime_assert(result == 0, "Invalid seed value");
|
||||
|
||||
srand48(ts.tv_nsec);
|
||||
}
|
||||
|
||||
internal u64 generate_random_number(void) {
|
||||
return lrand48();
|
||||
}
|
||||
#else
|
||||
internal void seed_os_generator(void) {
|
||||
struct timespec ts = {0};
|
||||
int result = timespec_get(&ts, TIME_UTC);
|
||||
wapp_runtime_assert(result != 0, "Invalid seed value");
|
||||
|
||||
srand(ts.tv_nsec);
|
||||
}
|
||||
|
||||
internal u64 generate_random_number(void) {
|
||||
i32 n1 = rand();
|
||||
i32 n2 = rand();
|
||||
|
||||
return (((u64)n1) << 32 | (u64)n2);
|
||||
}
|
||||
#endif // !WAPP_PLATFORM_POSIX
|
||||
#else
|
||||
internal void seed_os_generator(void) {
|
||||
time_t result = time(NULL);
|
||||
wapp_runtime_assert(result != (time_t)(-1), "Invalid seed value");
|
||||
|
||||
srand(result);
|
||||
}
|
||||
|
||||
internal u64 generate_random_number(void) {
|
||||
i32 n1 = rand();
|
||||
i32 n2 = rand();
|
||||
|
||||
return (((u64)n1) << 32 | (u64)n2);
|
||||
}
|
||||
#endif // !WAPP_PLATFORM_C
|
30
wapp/prng/xorshift/xorshift.h
Normal file
30
wapp/prng/xorshift/xorshift.h
Normal file
@ -0,0 +1,30 @@
|
||||
// vim:fileencoding=utf-8:foldmethod=marker
|
||||
|
||||
#ifndef XORSHIFT_H
|
||||
#define XORSHIFT_H
|
||||
|
||||
#include "../../common/aliases/aliases.h"
|
||||
#include "../../common/platform/platform.h"
|
||||
|
||||
#ifdef WAPP_PLATFORM_CPP
|
||||
BEGIN_C_LINKAGE
|
||||
#endif // !WAPP_PLATFORM_CPP
|
||||
|
||||
typedef struct xor_256_state XOR256State;
|
||||
struct xor_256_state {
|
||||
u64 x;
|
||||
u64 y;
|
||||
u64 z;
|
||||
u64 w;
|
||||
};
|
||||
|
||||
XOR256State wapp_prng_xorshift_init_state(void);
|
||||
u64 wapp_prng_xorshift_256(XOR256State *state);
|
||||
u64 wapp_prng_xorshift_256ss(XOR256State *state);
|
||||
u64 wapp_prng_xorshift_256p(XOR256State *state);
|
||||
|
||||
#ifdef WAPP_PLATFORM_CPP
|
||||
END_C_LINKAGE
|
||||
#endif // !WAPP_PLATFORM_CPP
|
||||
|
||||
#endif // !XORSHIFT_H
|
55
wapp/testing/tester/tester.c
Normal file
55
wapp/testing/tester/tester.c
Normal file
@ -0,0 +1,55 @@
|
||||
// vim:fileencoding=utf-8:foldmethod=marker
|
||||
|
||||
#include "tester.h"
|
||||
#include "../../common/aliases/aliases.h"
|
||||
#include "../../core/os/shell/termcolour/termcolour.h"
|
||||
#include "../../primitives/strings/str8/str8.h"
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
internal void handle_test_result(TestFuncResult result);
|
||||
|
||||
void run_tests(TestFunc *func1, ...) {
|
||||
printf("\n");
|
||||
|
||||
handle_test_result(func1());
|
||||
|
||||
va_list args;
|
||||
va_start(args, func1);
|
||||
|
||||
TestFunc *func = va_arg(args, TestFunc *);
|
||||
|
||||
while (func) {
|
||||
TestFuncResult result = func();
|
||||
handle_test_result(result);
|
||||
|
||||
func = va_arg(args, TestFunc *);
|
||||
}
|
||||
|
||||
va_end(args);
|
||||
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
internal void handle_test_result(TestFuncResult result) {
|
||||
TerminalColour colour;
|
||||
Str8 result_text = wapp_str8_buf(64);
|
||||
|
||||
if (result.passed) {
|
||||
colour = WAPP_TERM_COLOUR_FG_BR_GREEN;
|
||||
wapp_str8_copy_cstr_capped(&result_text, "PASSED");
|
||||
} else {
|
||||
colour = WAPP_TERM_COLOUR_FG_BR_RED;
|
||||
wapp_str8_copy_cstr_capped(&result_text, "FAILED");
|
||||
}
|
||||
|
||||
printf("[");
|
||||
wapp_shell_termcolour_print_text(&result_text, colour);
|
||||
wapp_shell_termcolour_clear_colour();
|
||||
printf("] " WAPP_STR8_SPEC "\n", wapp_str8_varg(result.name));
|
||||
|
||||
if (!result.passed) {
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
41
wapp/testing/tester/tester.h
Normal file
41
wapp/testing/tester/tester.h
Normal file
@ -0,0 +1,41 @@
|
||||
// vim:fileencoding=utf-8:foldmethod=marker
|
||||
|
||||
#ifndef TESTER_H
|
||||
#define TESTER_H
|
||||
|
||||
#include "../../common/misc/misc_utils.h"
|
||||
#include "../../common/platform/platform.h"
|
||||
#include "../../primitives/strings/str8/str8.h"
|
||||
#include <stdbool.h>
|
||||
|
||||
#ifdef WAPP_PLATFORM_CPP
|
||||
BEGIN_C_LINKAGE
|
||||
#endif // !WAPP_PLATFORM_CPP
|
||||
|
||||
#ifdef WAPP_PLATFORM_CPP
|
||||
#define wapp_tester_result(PASSED) (TestFuncResult{wapp_str8_lit_ro(__func__), PASSED})
|
||||
#else
|
||||
#define wapp_tester_result(PASSED) ((TestFuncResult){.name = wapp_str8_lit_ro(__func__), .passed = PASSED})
|
||||
#endif // !WAPP_PLATFORM_CPP
|
||||
|
||||
#define wapp_tester_run_tests(...) run_tests(__VA_ARGS__, NULL)
|
||||
|
||||
typedef struct test_func_result TestFuncResult;
|
||||
struct test_func_result {
|
||||
Str8RO name;
|
||||
bool passed;
|
||||
|
||||
#ifdef WAPP_PLATFORM_WINDOWS
|
||||
wapp_misc_utils_padding_size(sizeof(Str8RO) + sizeof(bool));
|
||||
#endif // WAPP_PLATFORM_WINDOWS
|
||||
};
|
||||
|
||||
typedef TestFuncResult(TestFunc)(void);
|
||||
|
||||
void run_tests(TestFunc *func1, ...);
|
||||
|
||||
#ifdef WAPP_PLATFORM_CPP
|
||||
END_C_LINKAGE
|
||||
#endif // !WAPP_PLATFORM_CPP
|
||||
|
||||
#endif // !TESTER_H
|
10
wapp/testing/wapp_testing.c
Normal file
10
wapp/testing/wapp_testing.c
Normal file
@ -0,0 +1,10 @@
|
||||
// vim:fileencoding=utf-8:foldmethod=marker
|
||||
|
||||
#ifndef WAPP_TESTING_C
|
||||
#define WAPP_TESTING_C
|
||||
|
||||
#include "wapp_testing.h"
|
||||
#include "tester/tester.c"
|
||||
#include "../core/wapp_core.c"
|
||||
|
||||
#endif // !WAPP_TESTING_C
|
10
wapp/testing/wapp_testing.h
Normal file
10
wapp/testing/wapp_testing.h
Normal file
@ -0,0 +1,10 @@
|
||||
// vim:fileencoding=utf-8:foldmethod=marker
|
||||
|
||||
#ifndef WAPP_TESTING_H
|
||||
#define WAPP_TESTING_H
|
||||
|
||||
#include "tester/tester.h"
|
||||
#include "../common/wapp_common.h"
|
||||
#include "../core/wapp_core.h"
|
||||
|
||||
#endif // !WAPP_TESTING_H
|
59
wapp/uuid/uuid.c
Normal file
59
wapp/uuid/uuid.c
Normal file
@ -0,0 +1,59 @@
|
||||
// vim:fileencoding=utf-8:foldmethod=marker
|
||||
|
||||
#include "uuid.h"
|
||||
#include "../common/aliases/aliases.h"
|
||||
#include "../common/assert/assert.h"
|
||||
#include "../primitives/strings/str8/str8.h"
|
||||
#include "../prng/xorshift/xorshift.h"
|
||||
#include <stdbool.h>
|
||||
#include <inttypes.h>
|
||||
|
||||
#define UUID_STR_FORMAT ("%.8" PRIx64 "-%.4" PRIx64 "-%.4" PRIx64 "-%.4" PRIx64 "-%.12" PRIx64)
|
||||
|
||||
typedef struct uuid4 UUID4;
|
||||
struct uuid4 {
|
||||
u64 high;
|
||||
u64 low;
|
||||
};
|
||||
|
||||
internal UUID4 generate_uuid4(void);
|
||||
internal void uuid4_to_uuid(const UUID4* uuid4, UUID *uuid);
|
||||
|
||||
UUID *wapp_uuid_init_uuid4(UUID *uuid) {
|
||||
wapp_debug_assert(uuid != NULL, "`uuid` should not be NULL");
|
||||
|
||||
UUID4 uuid4 = generate_uuid4();
|
||||
uuid4_to_uuid(&uuid4, uuid);
|
||||
|
||||
return uuid;
|
||||
}
|
||||
|
||||
internal UUID4 generate_uuid4(void) {
|
||||
persistent XOR256State state = {0};
|
||||
persistent bool initialised = false;
|
||||
|
||||
if (!initialised) {
|
||||
initialised = true;
|
||||
state = wapp_prng_xorshift_init_state();
|
||||
}
|
||||
|
||||
UUID4 uuid = (UUID4){
|
||||
.high = wapp_prng_xorshift_256(&state),
|
||||
.low = wapp_prng_xorshift_256(&state),
|
||||
};
|
||||
|
||||
uuid.high = (uuid.high & 0xffffffffffff0fff) | 0x0000000000004000;
|
||||
uuid.low = (uuid.low & 0x3fffffffffffffff) | 0x8000000000000000;
|
||||
|
||||
return uuid;
|
||||
}
|
||||
|
||||
internal void uuid4_to_uuid(const UUID4* uuid4, UUID *uuid) {
|
||||
u64 grp1 = uuid4->high >> 32;
|
||||
u64 grp2 = (uuid4->high << 32) >> 48;
|
||||
u64 grp3 = (uuid4->high << 48) >> 48;
|
||||
u64 grp4 = uuid4->low >> 48;
|
||||
u64 grp5 = (uuid4->low << 16) >> 16;
|
||||
|
||||
wapp_str8_format(&(uuid->uuid), UUID_STR_FORMAT, grp1, grp2, grp3, grp4, grp5);
|
||||
}
|
37
wapp/uuid/uuid.h
Normal file
37
wapp/uuid/uuid.h
Normal file
@ -0,0 +1,37 @@
|
||||
// vim:fileencoding=utf-8:foldmethod=marker
|
||||
|
||||
#ifndef UUID_H
|
||||
#define UUID_H
|
||||
|
||||
#include "../common/aliases/aliases.h"
|
||||
#include "../common/platform/platform.h"
|
||||
#include "../primitives/strings/str8/str8.h"
|
||||
|
||||
#ifdef WAPP_PLATFORM_CPP
|
||||
BEGIN_C_LINKAGE
|
||||
#endif // !WAPP_PLATFORM_CPP
|
||||
|
||||
#define UUID_BUF_LENGTH 48
|
||||
#define WAPP_UUID_SPEC WAPP_STR8_SPEC
|
||||
#define wapp_uuid_varg(UUID) wapp_str8_varg((UUID).uuid)
|
||||
|
||||
typedef struct uuid UUID;
|
||||
struct uuid {
|
||||
Str8 uuid;
|
||||
};
|
||||
|
||||
#define wapp_uuid_gen_uuid4() *(wapp_uuid_init_uuid4(&wapp_uuid_create()))
|
||||
|
||||
/* Low level UUID API */
|
||||
|
||||
#define wapp_uuid_create() ((UUID){.uuid = wapp_str8_buf(UUID_BUF_LENGTH)})
|
||||
|
||||
// Just returns the same pointer that was passed in with the UUID initialised.
|
||||
// Fails when passed a NULL pointer.
|
||||
UUID *wapp_uuid_init_uuid4(UUID *uuid);
|
||||
|
||||
#ifdef WAPP_PLATFORM_CPP
|
||||
END_C_LINKAGE
|
||||
#endif // !WAPP_PLATFORM_CPP
|
||||
|
||||
#endif // !UUID_H
|
10
wapp/uuid/wapp_uuid.c
Normal file
10
wapp/uuid/wapp_uuid.c
Normal file
@ -0,0 +1,10 @@
|
||||
// vim:fileencoding=utf-8:foldmethod=marker
|
||||
|
||||
#ifndef WAPP_UUID_C
|
||||
#define WAPP_UUID_C
|
||||
|
||||
#include "uuid.c"
|
||||
#include "../primitives/wapp_primitives.c"
|
||||
#include "../prng/wapp_prng.c"
|
||||
|
||||
#endif // !WAPP_UUID_C
|
11
wapp/uuid/wapp_uuid.h
Normal file
11
wapp/uuid/wapp_uuid.h
Normal file
@ -0,0 +1,11 @@
|
||||
// vim:fileencoding=utf-8:foldmethod=marker
|
||||
|
||||
#ifndef WAPP_UUID_H
|
||||
#define WAPP_UUID_H
|
||||
|
||||
#include "uuid.h"
|
||||
#include "../common/wapp_common.h"
|
||||
#include "../primitives/wapp_primitives.h"
|
||||
#include "../prng/wapp_prng.h"
|
||||
|
||||
#endif // !WAPP_UUID_H
|
13
wapp/wapp.c
Normal file
13
wapp/wapp.c
Normal file
@ -0,0 +1,13 @@
|
||||
// vim:fileencoding=utf-8:foldmethod=marker
|
||||
|
||||
#ifndef WAPP_C
|
||||
#define WAPP_C
|
||||
|
||||
#include "wapp.h"
|
||||
#include "primitives/wapp_primitives.c"
|
||||
#include "core/wapp_core.c"
|
||||
#include "prng/wapp_prng.c"
|
||||
#include "uuid/uuid.c"
|
||||
#include "testing/wapp_testing.c"
|
||||
|
||||
#endif // !WAPP_C
|
13
wapp/wapp.h
Normal file
13
wapp/wapp.h
Normal file
@ -0,0 +1,13 @@
|
||||
// vim:fileencoding=utf-8:foldmethod=marker
|
||||
|
||||
#ifndef WAPP_H
|
||||
#define WAPP_H
|
||||
|
||||
#include "common/wapp_common.h"
|
||||
#include "primitives/wapp_primitives.h"
|
||||
#include "core/wapp_core.h"
|
||||
#include "prng/wapp_prng.h"
|
||||
#include "uuid/wapp_uuid.h"
|
||||
#include "testing/wapp_testing.h"
|
||||
|
||||
#endif // !WAPP_H
|
Loading…
x
Reference in New Issue
Block a user