3 Commits

Author SHA1 Message Date
Abdelrahman Said
1108ed686e Switch to using snprintf instead of sprintf 2024-10-07 08:01:33 +01:00
36e88ba84d Remove old strings implementation 2024-10-06 22:41:43 +01:00
0617ca2316 Update compile script 2024-10-06 22:06:57 +01:00
122 changed files with 1617 additions and 8438 deletions

View File

@@ -1,2 +0,0 @@
CompileFlags:
Add: -ferror-limit=0

6
.gitignore vendored
View File

@@ -1,14 +1,10 @@
.cache
.vscode
.venv
test
test.*
*.dSYM
.DS_Store
*.pdb
*.obj
compile_commands.json
libwapp-build
dist
*.vs
__pycache__
libwapp.so

180
Makefile
View File

@@ -1,180 +0,0 @@
.PHONY: help full base os prng testing uuid all clean builddir build-test run-test install build-lib
# External variables
CC = clang
CXX = clang++
AR = ar
BUILD_TYPE = Debug
BUILD_DIR = libwapp-build/$(PLATFORM)-$(BUILD_TYPE)
INSTALL_PREFIX = dist
RUNTIME_ASSERT = true
# Internal variables
override CFLAGS = -Wall -Wextra -Werror -pedantic -Isrc -D_LARGEFILE64_SOURCE
override LIBFLAGS = -fPIC
override CSTD := -std=gnu11
override CXXSTD := -std=gnu++11
override KERNEL := $(shell uname -s)
override MACHINE := $(shell uname -m)
override PLATFORM := $(KERNEL)_$(MACHINE)
override TEST_INCLUDE := -Isrc $(shell find tests -type d | xargs -I{} echo -n "-I{} ")
override TEST_SRC := $(shell find tests -type f -name "*.c" | xargs -I{} echo -n "{} ")
override TEST_C_SRC := src/wapp.c $(TEST_SRC)
override TEST_CXX_SRC := $(shell find tests -type f -name "*.cc" | xargs -I{} echo -n "{} ")
override LIB_BASENAME := wapp
override OBJ_OUT := $(BUILD_DIR)/$(LIB_BASENAME).o
override LIB_STATIC_NAME := lib$(LIB_BASENAME).a
override LIB_OUT := $(BUILD_DIR)/$(LIB_STATIC_NAME)
override TEST_C_OUT := $(BUILD_DIR)/wapptest
override TEST_CXX_OUT := $(BUILD_DIR)/wapptestcc
override ABS_INSTALL_PREFIX := $(shell mkdir -p $(INSTALL_PREFIX) && realpath $(INSTALL_PREFIX))
override INCLUDE_INSTALL := $(ABS_INSTALL_PREFIX)/include/$(LIB_BASENAME)
override LIB_INSTALL := $(ABS_INSTALL_PREFIX)/lib
override HEADER_INSTALL_CMD := scripts/header_install.sh
ifeq ($(origin BUILD_FLAGS), undefined)
ifeq ($(BUILD_TYPE),Debug)
BUILD_FLAGS += -g -fsanitize=address,undefined -DWAPP_DEBUG_ASSERT
else ifeq ($(BUILD_TYPE),RelWithDebInfo)
BUILD_FLAGS += -g -O2 -fsanitize=address,undefined -DWAPP_DEBUG_ASSERT
else ifeq ($(BUILD_TYPE),Release)
BUILD_FLAGS += -O3
else
$(error Invalid BUILD type '$(BUILD_TYPE)'. Use 'Debug', 'RelWithDebInfo' or 'Release')
endif
endif
# Disable runtime asserts
ifeq ($(RUNTIME_ASSERT), false)
override BUILD_FLAGS += WAPP_NO_RUNTIME_ASSERT
endif
ifeq ($(CC),gcc)
# Used to disable the "ASan runtime does not come first in initial library list" error when compiling with gcc
export ASAN_OPTIONS=verify_asan_link_order=0
endif
# Escape sequences
BOLD = \033[1m
BLACK = \033[30m
BG_BLACK = \033[40m
RED = \033[31m
BG_RED = \033[41m
GREEN = \033[32m
BG_GREEN = \033[42m
YELLOW = \033[33m
BG_YELLOW = \033[43m
BLUE = \033[34m
BG_BLUE = \033[44m
MAGENTA = \033[35m
BG_MAGENTA = \033[45m
CYAN = \033[36m
BG_CYAN = \033[46m
WHITE = \033[37m
BG_WHITE = \033[47m
GRAY = \033[90m
BG_GRAY = \033[100m
BRIGHT_RED = \033[91m
BG_BRIGHT_RED = \033[101m
BRIGHT_GREEN = \033[92m
BG_BRIGHT_GREEN = \033[102m
BRIGHT_YELLOW = \033[93m
BG_BRIGHT_YELLOW = \033[103m
BRIGHT_BLUE = \033[94m
BG_BRIGHT_BLUE = \033[104m
BRIGHT_MAGENTA = \033[95m
BG_BRIGHT_MAGENTA = \033[105m
BRIGHT_CYAN = \033[96m
BG_BRIGHT_CYAN = \033[106m
BRIGHT_WHITE = \033[97m
BG_BRIGHT_WHITE = \033[107m
RESET = \033[0m
ECHO_E = echo -e
ifeq ($(KERNEL), Darwin)
ECHO_E = echo
endif
all: clean builddir run-c-test full run-cc-test
help:
@$(ECHO_E) "$(BOLD)$(BLUE)Available build variables:$(RESET)"
@$(ECHO_E) " $(GREEN)CC$(RESET) C compiler to use $(YELLOW)(Default: clang)$(RESET)."
@$(ECHO_E) " $(GREEN)CXX$(RESET) C++ compiler to use $(YELLOW)(Default: clang++)$(RESET)."
@$(ECHO_E) " $(GREEN)AR$(RESET) Archiving utility to use for building static libraries $(YELLOW)(Default: ar)$(RESET)."
@$(ECHO_E) " $(GREEN)BUILD_TYPE$(RESET) Build type $(MAGENTA)[Debug | RelWithDebInfo | Release] $(YELLOW)(Default: Debug)$(RESET)."
@$(ECHO_E) " $(GREEN)BUILD_DIR$(RESET) Directory where build files will be written."
@$(ECHO_E) " $(GREEN)INSTALL_PREFIX$(RESET) Prefix where library and include files will be installed."
@$(ECHO_E) " $(GREEN)RUNTIME_ASSERT$(RESET) Whether runtime asserts are enabled $(MAGENTA)[true | false] $(YELLOW)(Default: true)$(RESET)."
@$(ECHO_E) " $(GREEN)$(RESET) $(BOLD)$(BG_RED)DISCLAIMER:$(RESET) Using this flag is not recommended as it disables safety checks"
@$(ECHO_E) " $(GREEN)$(RESET) potentially leading to Undefined Behaviour."
@$(ECHO_E)
@$(ECHO_E) "$(BOLD)$(BLUE)Available targets:$(RESET)"
@$(ECHO_E) " $(GREEN)make$(RESET) Build, install and test the full wapp library."
@$(ECHO_E) " $(GREEN)make full$(RESET) Build and install the full wapp library."
@$(ECHO_E) " $(GREEN)make base$(RESET) Build and install only the $(CYAN)base$(RESET) component of the wapp library with all its dependencies."
@$(ECHO_E) " $(GREEN)make os$(RESET) Build and install only the $(CYAN)os$(RESET) component of the wapp library with all its dependencies."
@$(ECHO_E) " $(GREEN)make prng$(RESET) Build and install only the $(CYAN)prng$(RESET) component of the wapp library with all its dependencies."
@$(ECHO_E) " $(GREEN)make uuid$(RESET) Build and install only the $(CYAN)uuid$(RESET) component of the wapp library with all its dependencies."
@$(ECHO_E) " $(GREEN)make testing$(RESET) Build and install only the $(CYAN)testing$(RESET) component of the wapp library with all its dependencies."
@$(ECHO_E) " $(GREEN)make clean$(RESET) Clean the build directory."
@$(ECHO_E) " $(GREEN)make help$(RESET) Print this help message and exit."
full: LIB_SRC = src/wapp.c
full: INCLUDES = common os base prng testing uuid
full: install
base: LIB_SRC = src/base/wapp_base.c
base: INCLUDES = common base
base: install
os: LIB_SRC = src/os/wapp_os.c
os: INCLUDES = common os base
os: install
prng: LIB_SRC = src/prng/wapp_prng.c
prng: INCLUDES = common prng
prng: install
testing: LIB_SRC = src/testing/wapp_testing.c
testing: INCLUDES = common os testing
testing: install
uuid: LIB_SRC = src/uuid/wapp_uuid.c
uuid: INCLUDES = common base prng
uuid: install
clean:
@rm -rf "$(BUILD_DIR)"
@rm -rf "$(INCLUDE_INSTALL)"
@rm -f "$(LIB_INSTALL)/$(LIB_STATIC_NAME)"
builddir:
@mkdir -p "$(BUILD_DIR)"
build-c-test:
$(CC) $(CSTD) $(CFLAGS) $(BUILD_FLAGS) $(TEST_INCLUDE) $(TEST_C_SRC) -o "$(TEST_C_OUT)"
run-c-test: build-c-test
@echo -e "\n\033[34;1mRUNNING C TESTS\033[0m"
@"$(TEST_C_OUT)"
@rm "$(TEST_C_OUT)"
build-cc-test:
$(CXX) $(CXXSTD) $(CFLAGS) $(BUILD_FLAGS) $(TEST_INCLUDE) $(TEST_CXX_SRC) "$(LIB_OUT)" -o "$(TEST_CXX_OUT)"
run-cc-test: build-cc-test
@echo -e "\n\033[34;1mRUNNING C++ TESTS\033[0m"
@export LD_LIBRARY_PATH=$$LD_LIBRARY_PATH:"$(BUILD_DIR)" && "$(TEST_CXX_OUT)"
@rm "$(TEST_CXX_OUT)"
install: build-lib
@mkdir -p "$(LIB_INSTALL)"
@cp -v "$(LIB_OUT)" "$(LIB_INSTALL)"
@mkdir -p "$(INCLUDE_INSTALL)"
@bash $(HEADER_INSTALL_CMD) $(LIB_SRC) "$(INCLUDE_INSTALL)" $(INCLUDES)
build-lib: builddir
$(CC) -c $(CSTD) $(CFLAGS) $(BUILD_FLAGS) $(LIBFLAGS) $(LIB_SRC) -o "$(OBJ_OUT)"
$(AR) r "$(LIB_OUT)" "$(OBJ_OUT)"
@rm "$(OBJ_OUT)"

View File

@@ -1,3 +1,3 @@
# Wizard Apprentice Standard Library
A group of utilities for C/C++ projects
A collection of useful C/C++ utilities for my projects

57
build
View File

@@ -1,58 +1,3 @@
#!/bin/bash
# Colors
RED="\033[0;31m"
BOLD="\033[1m"
NC="\033[0m" # No Color
BUILD_TYPE="Debug"
ACCEPTED_BUILD_TYPES=("Debug" "RelWithDebInfo" "Release")
KERNEL="$(uname -s)"
ARGS=""
join_array_elements() {
local IFS=","
echo "$*"
}
contains() {
local item="$1"; shift
local e
for e; do
[[ "$e" == "$item" ]] && return 0
done
return 1
}
print_usage() {
echo -e "Usage: build [-b build_type] ..."
echo -e " Options:"
echo -e " -b, --build-type Choose from $(join_array_elements ${ACCEPTED_BUILD_TYPES[*]}) (Default: Debug)."
echo -e " -h, --help Print this message and exit"
}
while [[ $# > 0 ]];do
case $1 in
-b|--build-type)
BUILD_TYPE="$2"
shift 2
;;
-h|--help)
print_usage
exit 0
;;
*|-*|--*)
rest=("$@")
ARGS+=" ${rest[0]}"
shift
;;
esac
done
if ! contains ${BUILD_TYPE} "${ACCEPTED_BUILD_TYPES[@]}"; then
echo -e "${RED}${BOLD}Unknown build type: ${BUILD_TYPE}${NC}\n"
print_usage
exit 1
fi
bear -- make BUILD_TYPE=$BUILD_TYPE $ARGS
bear -- ./compile $@

View File

@@ -3,46 +3,35 @@ Param(
)
$Compiler = "cl.exe"
$Linker = "lib.exe"
$GeneralFlags = "/Wall /WX /wd4996 /wd4464 /wd5105 /EHs"
$CStd = "/std:c11"
$CppStd = "/std:c++14"
$LibraryFlags = "/c"
$GeneralFlags = "/Wall /WX /wd4996"
$LibraryFlags = "/LD"
$Kernel = (Get-ChildItem Env:OS).Value
$Machine = (Get-ChildItem Env:PROCESSOR_ARCHITECTURE).Value
$Platform = "${Kernel}_${Machine}"
$IncludeDirs = "/I src"
$SrcFiles = "src/wapp.c"
$IncludeDirs = Get-ChildItem -Path src -Recurse -Directory -ErrorAction SilentlyContinue -Force | %{$("/I " + '"' + $_.FullName + '"')}
$SrcFiles = Get-ChildItem -Path src -Recurse -Filter *.c -ErrorAction SilentlyContinue -Force | %{$('"' + $_.FullName + '"')}
$TestIncludeDirs = Get-ChildItem -Path tests -Recurse -Directory -ErrorAction SilentlyContinue -Force | %{$("/I " + '"' + $_.FullName + '"')}
$TestCSrcFiles = Get-ChildItem -Path tests -Recurse -Filter *.c -ErrorAction SilentlyContinue -Force | %{$('"' + $_.FullName + '"')}
$TestCppSrcFiles = Get-ChildItem -Path tests -Recurse -Filter *.cc -ErrorAction SilentlyContinue -Force | %{$('"' + $_.FullName + '"')}
$TestSrcFiles = Get-ChildItem -Path tests -Recurse -Filter *.c -ErrorAction SilentlyContinue -Force | %{$('"' + $_.FullName + '"')}
If ($Release -eq $True) {
$GeneralFlags += " /O2 /Og"
$BuildType = "Release"
$BuildType = "release"
} Else {
$GeneralFlags += " /Zi /Od /fsanitize=address"
$BuildType = "Debug"
$BuildType = "debug"
}
$BuildDir = "./libwapp-build/${Platform}-${BuildType}"
$BuildDir = "./libwapp-build/windows-$BuildType"
$ObjDir = "$BuildDir/objects"
$OutDir = "$BuildDir/output"
$TestsDir = "$BuildDir/tests"
$LibOutput = "$OutDir/libwapp.lib"
$OutBasename = "libwapp"
$Objects = "/Fo:$ObjDir/"
$LibOutputFlags = "/OUT:$LibOutput"
$Outputs = "/Fd:$OutDir/$OutBasename /Fe:$OutDir/$OutBasename"
$TestCOutputBasename = "wapptest"
$TestCOutputFlags = "/Fo:$TestsDir/ /Fe:$TestsDir/$TestCOutputBasename"
$TestCppOutputBasename = "wapptestcc"
$TestCppOutputFlags = "/Fo:$TestsDir/ /Fe:$TestsDir/$TestCppOutputBasename"
$TestOutBasename = "wapptest"
$TestOutputs = "/Fo:$TestsDir/ /Fe:$TestsDir/$TestOutBasename"
If (Test-Path $BuildDir) {
Remove-Item $BuildDir -Recurse -Force
@@ -52,23 +41,18 @@ mkdir -p $ObjDir > $null
mkdir -p $OutDir > $null
mkdir -p $TestsDir > $null
# Build and run C tests
Invoke-Expression "$Compiler $GeneralFlags $CStd $IncludeDirs $TestIncludeDirs $SrcFiles $TestCSrcFiles $TestCOutputFlags" -ErrorAction Stop
Invoke-Expression "$TestsDir/$TestCOutputBasename.exe"
# Build and run tests
Invoke-Expression "$Compiler $GeneralFlags $IncludeDirs $TestIncludeDirs $SrcFiles $TestSrcFiles $TestOutputs" -ErrorAction Stop
Invoke-Expression "$TestsDir/$TestOutBasename.exe"
$Status = $LASTEXITCODE
If ($Status -ne 0) {
Remove-Item $TestsDir -Recurse -Force
If ($Status -ne 0) {
Write-Error "Tests failed"
Exit 1
}
# Build library
Invoke-Expression "$Compiler $GeneralFlags $CStd $LibraryFlags $SrcFiles $Objects"
Invoke-Expression "$Linker $ObjDir/*.obj $LibOutputFlags"
# Build and run C++ tests
Invoke-Expression "$Compiler $GeneralFlags $CppStd $IncludeDirs $TestIncludeDirs $LibOutput $TestCppSrcFiles $TestCppOutputFlags" -ErrorAction Stop
Invoke-Expression "$TestsDir/$TestCppOutputBasename.exe"
Remove-Item $TestsDir -Recurse -Force
Invoke-Expression "$Compiler $GeneralFlags $LibraryFlags $IncludeDirs $SrcFiles $Objects $Outputs"

61
compile Executable file
View File

@@ -0,0 +1,61 @@
#!/bin/bash
BUILD_TYPE="debug"
while [[ $# > 0 ]];do
case $1 in
--release)
BUILD_TYPE="release"
shift
;;
*|-*|--*)
echo "Unknown option $1"
exit 1
;;
esac
done
CC=clang
CFLAGS="-Wall -Werror -pedantic"
LIBFLAGS="-fPIC -shared"
INCLUDE="$(find src -type d | xargs -I{} echo -n "-I{} ")"
SRC="$(find src -type f -name "*.c" | xargs -I{} echo -n "{} ")"
TEST_INCLUDE="$(find tests -type d | xargs -I{} echo -n "-I{} ")"
TEST_SRC="$(find tests -type f -name "*.c" | xargs -I{} echo -n "{} ")"
BUILD_DIR="libwapp-build/posix-$BUILD_TYPE"
if [[ -d $BUILD_DIR ]]; then
rm -rf $BUILD_DIR
fi
mkdir -p $BUILD_DIR
if [[ $BUILD_TYPE == "release" ]]; then
CFLAGS+=" -O3"
else
CFLAGS+=" -g -fsanitize=address -fsanitize=undefined"
fi
OUT="$BUILD_DIR/libwapp.so"
TEST_OUT="$BUILD_DIR/wapptest"
# Compile tests
if [[ $(echo $TEST_SRC | xargs) != "" ]]; then
(set -x ; $CC $CFLAGS $INCLUDE $TEST_INCLUDE $SRC $TEST_SRC -o $TEST_OUT)
fi
# Run tests and exit on failure
if [[ -f $TEST_OUT ]]; then
$TEST_OUT
STATUS="$?"
rm $TEST_OUT
if [[ $STATUS != "0" ]]; then
exit 1
fi
fi
# Compile library
(set -x ; $CC $CFLAGS $LIBFLAGS $INCLUDE $SRC -o $OUT)

View File

@@ -1,21 +0,0 @@
#!/bin/bash
SCRIPT_DIR="$(dirname $0)"
LIB_SRC="$1"
INSTALL_PREFIX="$2"
shift 2
INCLUDES="$@"
mkdir -p "$INSTALL_PREFIX"
BASE_INCLUDE_DIR="$(dirname "$LIB_SRC")"
find $BASE_INCLUDE_DIR -maxdepth 1 -type f -name "*.h" -exec cp -v {} "$INSTALL_PREFIX" \;
cd "$SCRIPT_DIR/../src"
for INCLUDE in $INCLUDES; do
for f in $(find "$INCLUDE" -type f -name "*.h"); do
DST="$INSTALL_PREFIX/$(dirname $f)"
mkdir -p "$DST"
cp -v "$f" "$DST"
done
done

View File

@@ -1,266 +0,0 @@
// vim:fileencoding=utf-8:foldmethod=marker
#include "./array.h"
#include "../../common/assert/assert.h"
#include "../mem/allocator/mem_allocator.h"
#include "../../common/misc/misc_utils.h"
#include "../../common/aliases/aliases.h"
#include <stddef.h>
#define _array_header(ARRAY) (ArrayHeader *)(wapp_pointer_offset(ARRAY, (i64)sizeof(ArrayHeader) * -1))
wapp_persist inline void _array_validate(const GenericArray array, u64 item_size);
u64 _array_count(GenericArray array) {
wapp_debug_assert(array != NULL, "`array` should not be NULL");
ArrayHeader *header = _array_header(array);
wapp_runtime_assert(WAPP_ARRAY_MAGIC == header->magic, "`array` is not a valid wapp array");
return header->count;
}
u64 _array_capacity(GenericArray array) {
wapp_debug_assert(array != NULL, "`array` should not be NULL");
ArrayHeader *header = _array_header(array);
wapp_runtime_assert(WAPP_ARRAY_MAGIC == header->magic, "`array` is not a valid wapp array");
return header->capacity;
}
u64 _array_item_size(GenericArray array) {
wapp_debug_assert(array != NULL, "`array` should not be NULL");
ArrayHeader *header = _array_header(array);
wapp_runtime_assert(WAPP_ARRAY_MAGIC == header->magic, "`array` is not a valid wapp array");
return header->item_size;
}
void _array_set_count(GenericArray array, u64 count) {
wapp_debug_assert(array != NULL, "`array` should not be NULL");
ArrayHeader *header = _array_header(array);
wapp_runtime_assert(WAPP_ARRAY_MAGIC == header->magic, "`array` is not a valid wapp array");
header->count = count;
}
void *_array_get(GenericArray array, u64 index, u64 item_size) {
wapp_runtime_assert(array != NULL, "`array` should not be NULL");
_array_validate(array, item_size);
ArrayHeader *header = _array_header(array);
wapp_runtime_assert(index < header->count, "`index` is out of bounds");
return wapp_pointer_offset(array, header->item_size * index);
}
void _array_set(GenericArray array, u64 index, void *value, u64 item_size) {
void *item = _array_get(array, index, item_size);
ArrayHeader *header = _array_header(array);
memcpy(item, value, header->item_size);
}
void _array_append_capped(GenericArray array, void *value, u64 item_size) {
wapp_runtime_assert(array != NULL, "`array` should not be NULL");
_array_validate(array, item_size);
ArrayHeader *header = _array_header(array);
if (header->count >= header->capacity) { return; }
u64 index = (header->count)++;
_array_set(array, index, value, item_size);
}
void _array_extend_capped(GenericArray dst, const GenericArray src, u64 item_size) {
wapp_runtime_assert(dst != NULL && src != NULL, "`dst` and `src` should not be NULL");
_array_validate(dst, item_size);
_array_validate(src, item_size);
ArrayHeader *src_header = _array_header(src);
ArrayHeader *dst_header = _array_header(dst);
u64 remaining_capacity = dst_header->capacity - dst_header->count;
u64 copy_count = src_header->count < remaining_capacity ? src_header->count : remaining_capacity;
void *dst_ptr = wapp_pointer_offset(dst, dst_header->count * dst_header->item_size);
memcpy(dst_ptr, src, copy_count * src_header->item_size);
dst_header->count += copy_count;
}
void _array_copy_capped(GenericArray dst, const GenericArray src, u64 item_size) {
wapp_runtime_assert(dst != NULL && src != NULL, "`dst` and `src` should not be NULL");
_array_validate(dst, item_size);
_array_validate(src, item_size);
_array_clear(dst, item_size);
ArrayHeader *src_header = _array_header(src);
ArrayHeader *dst_header = _array_header(dst);
u64 copy_count = src_header->count < dst_header->capacity ? src_header->count : dst_header->capacity;
memcpy((void *)dst, (void *)src, copy_count * src_header->item_size);
dst_header->count = copy_count;
}
GenericArray _array_append_alloc(const Allocator *allocator, GenericArray array, void *value,
ArrayInitFlags flags, u64 item_size) {
wapp_runtime_assert(allocator != NULL && array != NULL, "`allocator` and `array` should not be NULL");
_array_validate(array, item_size);
GenericArray output = array;
ArrayHeader *header = _array_header(array);
if (header->count >= header->capacity) {
u64 new_capacity = wapp_misc_utils_u64_round_up_pow2(header->capacity * 2);
output = (GenericArray )_array_alloc_capacity(allocator, new_capacity, flags,
header->item_size);
if (!output) {
output = array;
goto RETURN_ARRAY_APPEND_ALLOC;
}
_array_copy_capped(output, array, item_size);
}
_array_append_capped(output, value, item_size);
if ((flags & ARRAY_INIT_FILLED) == ARRAY_INIT_FILLED) {
_array_set_count(output, _array_capacity(output));
}
RETURN_ARRAY_APPEND_ALLOC:
return output;
}
GenericArray _array_extend_alloc(const Allocator *allocator, GenericArray dst, const GenericArray src,
ArrayInitFlags flags, u64 item_size) {
wapp_runtime_assert(allocator != NULL && dst != NULL && src != NULL, "`allocator`, `dst` and `src` should not be NULL");
_array_validate(dst, item_size);
_array_validate(src, item_size);
GenericArray output = dst;
ArrayHeader *src_header = _array_header(src);
ArrayHeader *dst_header = _array_header(dst);
u64 remaining_capacity = dst_header->capacity - dst_header->count;
if (src_header->count >= remaining_capacity) {
u64 new_capacity = wapp_misc_utils_u64_round_up_pow2(dst_header->capacity * 2);
output = (GenericArray )_array_alloc_capacity(allocator, new_capacity,
flags, dst_header->item_size);
if (!output) {
output = dst;
goto RETURN_ARRAY_EXTEND_ALLOC;
}
_array_copy_capped(output, dst, item_size);
}
_array_extend_capped(output, src, item_size);
if ((flags & ARRAY_INIT_FILLED) == ARRAY_INIT_FILLED) {
_array_set_count(output, _array_capacity(output));
}
RETURN_ARRAY_EXTEND_ALLOC:
return output;
}
GenericArray _array_copy_alloc(const Allocator *allocator, GenericArray dst, const GenericArray src,
ArrayInitFlags flags, u64 item_size) {
wapp_runtime_assert(allocator != NULL && dst != NULL && src != NULL, "`allocator`, `dst` and `src` should not be NULL");
_array_validate(dst, item_size);
_array_validate(src, item_size);
GenericArray output = dst;
ArrayHeader *src_header = _array_header(src);
ArrayHeader *dst_header = _array_header(dst);
if (src_header->count >= dst_header->capacity) {
u64 new_capacity = wapp_misc_utils_u64_round_up_pow2(dst_header->capacity * 2);
output = (GenericArray )_array_alloc_capacity(allocator, new_capacity,
flags, src_header->item_size);
if (!output) {
output = dst;
goto RETURN_ARRAY_COPY_ALLOC;
}
}
_array_copy_capped(output, src, item_size);
if ((flags & ARRAY_INIT_FILLED) == ARRAY_INIT_FILLED) {
_array_set_count(output, _array_capacity(output));
}
RETURN_ARRAY_COPY_ALLOC:
return output;
}
void *_array_pop(GenericArray array, u64 item_size) {
wapp_runtime_assert(array != NULL, "`array` should not be NULL");
_array_validate(array, item_size);
ArrayHeader *header = _array_header(array);
if (header->count == 0) { return NULL; }
u64 index = header->count - 1;
void *out = _array_get(array, index, item_size);
--(header->count);
return out;
}
void _array_clear(GenericArray array, u64 item_size) {
wapp_runtime_assert(array != NULL, "`array` should not be NULL");
_array_validate(array, item_size);
ArrayHeader *header = _array_header(array);
header->count = 0;
}
u64 _array_calc_alloc_size(u64 capacity, u64 item_size) {
return sizeof(ArrayHeader) + item_size * capacity;
}
GenericArray _array_alloc_capacity(const Allocator *allocator, u64 capacity, ArrayInitFlags flags,
u64 item_size) {
wapp_runtime_assert(allocator != NULL, "`allocator` should not be NULL");
GenericArray output = NULL;
u64 allocation_size = _array_calc_alloc_size(capacity, item_size);
void *buffer = wapp_mem_allocator_alloc(allocator, allocation_size);
if (!buffer) {
goto RETURN_ARRAY_ALLOC;
}
output = _array_from_preallocated_buffer(buffer, allocation_size, flags, item_size);
RETURN_ARRAY_ALLOC:
return output;
}
GenericArray _array_from_preallocated_buffer(void *buffer, u64 buffer_size, ArrayInitFlags flags,
u64 item_size) {
wapp_runtime_assert(buffer != NULL, "`buffer` should not be NULL");
i64 data_buffer_size = (i64)buffer_size - (i64)(sizeof(ArrayHeader));
if (data_buffer_size <= 0) {
return NULL;
}
u64 item_capacity = (u64)data_buffer_size / item_size;
ArrayHeader *header = (ArrayHeader *)buffer;
GenericArray output = (u8 *)(header + 1);
header->magic = WAPP_ARRAY_MAGIC;
header->count = flags & ARRAY_INIT_FILLED ? item_capacity : 0;
header->capacity = item_capacity;
header->item_size = item_size;
return output;
}
wapp_persist inline void _array_validate(const GenericArray array, u64 item_size) {
ArrayHeader *header = _array_header(array);
wapp_runtime_assert(WAPP_ARRAY_MAGIC == header->magic, "`array` is not a valid wapp array");
wapp_runtime_assert(item_size == header->item_size, "Invalid item type provided");
}

View File

@@ -1,216 +0,0 @@
// vim:fileencoding=utf-8:foldmethod=marker
#ifndef ARRAY_H
#define ARRAY_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_ARRAY_MAGIC (u64)0x57415f415252
#define _calc_array_count(TYPE, ...) wapp_misc_utils_va_args_count(TYPE, __VA_ARGS__)
#define _calc_array_capacity(TYPE, ...) wapp_misc_utils_u64_round_up_pow2(_calc_array_count(TYPE, __VA_ARGS__) * 2)
typedef struct Str8 Str8;
// NOTE (Abdelrahman): Typedefs to distinguish arrays from regular pointers
typedef void *GenericArray;
typedef void **VoidPtrArray;
typedef c8 *C8Array;
typedef c16 *C16Array;
typedef c32 *C32Array;
typedef u8 *U8Array;
typedef u16 *U16Array;
typedef u32 *U32Array;
typedef u64 *U64Array;
typedef b8 *B8Array;
typedef i8 *I8Array;
typedef i16 *I16Array;
typedef i32 *I32Array;
typedef i64 *I64Array;
typedef f32 *F32Array;
typedef f64 *F64Array;
typedef f128 *F128Array;
typedef uptr *UptrArray;
typedef iptr *IptrArray;
typedef Str8 *Str8Array;
typedef enum {
ARRAY_INIT_NONE = 0,
ARRAY_INIT_FILLED = 1 << 1,
} ArrayInitFlags;
#ifdef WAPP_PLATFORM_CPP
#define wapp_array(TYPE, ...) ([&]() { \
u64 capacity = _calc_array_capacity(TYPE, __VA_ARGS__); \
\
TYPE items[_calc_array_capacity(TYPE, __VA_ARGS__)] = {__VA_ARGS__}; \
\
wapp_persist u8 array[ \
sizeof(ArrayHeader) + _calc_array_capacity(TYPE, __VA_ARGS__) * sizeof(TYPE) \
] = {0}; \
ArrayHeader *header = (ArrayHeader *)array; \
header->magic = WAPP_ARRAY_MAGIC; \
header->count = _calc_array_count(TYPE, __VA_ARGS__); \
header->capacity = _calc_array_capacity(TYPE, __VA_ARGS__); \
header->item_size = sizeof(TYPE); \
\
u8 *buf = (u8 *)(header + 1); \
memcpy(buf, items, capacity * sizeof(TYPE)); \
return (TYPE *)buf; \
}())
#define wapp_array_with_capacity(TYPE, CAPACITY, FLAGS) ([&]() { \
wapp_persist u8 array[ \
sizeof(ArrayHeader) + CAPACITY * sizeof(TYPE) \
] = {0}; \
ArrayHeader *header = (ArrayHeader *)array; \
header->magic = WAPP_ARRAY_MAGIC; \
header->count = (FLAGS & ARRAY_INIT_FILLED) ? CAPACITY : 0; \
header->capacity = CAPACITY; \
header->item_size = sizeof(TYPE); \
\
return (TYPE *)(header + 1); \
}())
#define wapp_array_pop(TYPE, ARRAY) ([&]() { \
if (ARRAY == NULL || _array_count((GenericArray)ARRAY) == 0) { \
TYPE result{}; \
return result; \
} \
\
return *((TYPE *)_array_pop((GenericArray)ARRAY, sizeof(TYPE))); \
}())
#else
#define _stack_array(TYPE, SIZE) struct {ArrayHeader header; \
TYPE items[SIZE]; \
wapp_misc_utils_reserve_padding(sizeof(ArrayHeader) + \
sizeof(TYPE) * SIZE);}
#define wapp_array(TYPE, ...) \
((TYPE *)( \
(_stack_array(TYPE, _calc_array_capacity(TYPE, __VA_ARGS__))){ \
.header = { \
.magic = WAPP_ARRAY_MAGIC, \
.count = _calc_array_count(TYPE, __VA_ARGS__), \
.capacity = _calc_array_capacity(TYPE, __VA_ARGS__), \
.item_size = sizeof(TYPE), \
}, \
.items = {__VA_ARGS__}, \
}.items \
))
#define wapp_array_with_capacity(TYPE, CAPACITY, FLAGS) \
((TYPE *)( \
(_stack_array(TYPE, CAPACITY)){ \
.header = { \
.magic = WAPP_ARRAY_MAGIC, \
.count = (FLAGS & ARRAY_INIT_FILLED) ? CAPACITY : 0, \
.capacity = CAPACITY, \
.item_size = sizeof(TYPE), \
}, \
.items = {0}, \
}.items \
))
#define wapp_array_pop(TYPE, ARRAY) \
(ARRAY == NULL || _array_count((GenericArray)ARRAY) == 0 ? \
(TYPE){0} : \
*((TYPE *)_array_pop((GenericArray)ARRAY, sizeof(TYPE))) \
)
#endif // !WAPP_PLATFORM_CPP
#define wapp_array_count(ARRAY) \
(_array_count((GenericArray)ARRAY))
#define wapp_array_capacity(ARRAY) \
(_array_capacity((GenericArray)ARRAY))
#define wapp_array_item_size(ARRAY) \
(_array_item_size((GenericArray)ARRAY))
#define wapp_array_set_count(ARRAY, COUNT) \
(_array_set_count((GenericArray)ARRAY, COUNT))
#define wapp_array_get(TYPE, ARRAY, INDEX) \
((TYPE *)_array_get((GenericArray)ARRAY, \
INDEX, \
sizeof(TYPE)))
#define wapp_array_set(TYPE, ARRAY, INDEX, VALUE_PTR) \
(_array_set((GenericArray)ARRAY, \
INDEX, \
(u8 *)VALUE_PTR, \
sizeof(TYPE)))
#define wapp_array_append_capped(TYPE, ARRAY, VALUE_PTR) \
(_array_append_capped((GenericArray)ARRAY, \
(u8 *)VALUE_PTR, \
sizeof(TYPE)))
#define wapp_array_extend_capped(TYPE, DST_ARRAY, SRC_ARRAY) \
(_array_extend_capped((GenericArray)DST_ARRAY, \
(GenericArray)SRC_ARRAY, \
sizeof(TYPE)))
#define wapp_array_copy_capped(TYPE, DST_ARRAY, SRC_ARRAY) \
(_array_copy_capped((GenericArray)DST_ARRAY, \
(GenericArray)SRC_ARRAY, \
sizeof(TYPE)))
#define wapp_array_append_alloc(TYPE, ALLOCATOR_PTR, ARRAY, VALUE_PTR, FLAGS) \
((TYPE *)_array_append_alloc(ALLOCATOR_PTR, \
(GenericArray)ARRAY, \
(u8 *)VALUE_PTR, \
FLAGS, \
sizeof(TYPE)))
#define wapp_array_extend_alloc(TYPE, ALLOCATOR_PTR, DST_ARRAY, SRC_ARRAY, FLAGS) \
((TYPE *)_array_extend_alloc(ALLOCATOR_PTR, \
(GenericArray)DST_ARRAY, \
(GenericArray)SRC_ARRAY, \
FLAGS, \
sizeof(TYPE)))
#define wapp_array_copy_alloc(TYPE, ALLOCATOR_PTR, DST_ARRAY, SRC_ARRAY, FLAGS) \
((TYPE *)_array_copy_alloc(ALLOCATOR_PTR, \
(GenericArray)DST_ARRAY, \
(GenericArray)SRC_ARRAY, \
FLAGS, \
sizeof(TYPE)))
#define wapp_array_clear(TYPE, ARRAY) \
(_array_clear((GenericArray)ARRAY, \
sizeof(TYPE)))
#define wapp_array_calc_alloc_size(TYPE, CAPACITY) _array_calc_alloc_size(CAPACITY, sizeof(TYPE))
#define wapp_array_alloc_capacity(TYPE, ALLOCATOR_PTR, CAPACITY, FLAGS) \
((TYPE *)_array_alloc_capacity(ALLOCATOR_PTR, CAPACITY, FLAGS, sizeof(TYPE)))
#define wapp_array_from_preallcated_buffer(TYPE, BUFFER, BUFFER_SIZE) \
((TYPE *)_array_from_preallcated_buffer(BUFFER, BUFFER_SIZE, sizeof(TYPE)))
typedef struct header ArrayHeader;
struct header {
u64 magic;
u64 count;
u64 capacity;
u64 item_size;
};
u64 _array_count(GenericArray array);
u64 _array_capacity(GenericArray array);
u64 _array_item_size(GenericArray array);
void _array_set_count(GenericArray array, u64 count);
void *_array_get(GenericArray array, u64 index, u64 item_size);
void _array_set(GenericArray array, u64 index, void *value, u64 item_size);
void _array_append_capped(GenericArray array, void *value, u64 item_size);
void _array_extend_capped(GenericArray dst, const GenericArray src, u64 item_size);
void _array_copy_capped(GenericArray dst, const GenericArray src, u64 item_size);
GenericArray _array_append_alloc(const Allocator *allocator, GenericArray array, void *value,
ArrayInitFlags flags, u64 item_size);
GenericArray _array_extend_alloc(const Allocator *allocator, GenericArray dst, const GenericArray src,
ArrayInitFlags flags, u64 item_size);
GenericArray _array_copy_alloc(const Allocator *allocator, GenericArray dst, const GenericArray src,
ArrayInitFlags flags, u64 item_size);
void *_array_pop(GenericArray array, u64 item_size);
void _array_clear(GenericArray array, u64 item_size);
u64 _array_calc_alloc_size(u64 capacity, u64 item_size);
GenericArray _array_alloc_capacity(const Allocator *allocator, u64 capacity, ArrayInitFlags flags,
u64 item_size);
GenericArray _array_from_preallocated_buffer(void *buffer, u64 buffer_size, ArrayInitFlags flags,
u64 item_size);
#ifdef WAPP_PLATFORM_CPP
END_C_LINKAGE
#endif // !WAPP_PLATFORM_CPP
#endif // !ARRAY_H

View File

@@ -1,259 +0,0 @@
// vim:fileencoding=utf-8:foldmethod=marker
#include "./dbl_list.h"
#include "../mem/allocator/mem_allocator.h"
#include "../../common/assert/assert.h"
#include "../../common/aliases/aliases.h"
#include "../../common/platform/platform.h"
#include <stddef.h>
wapp_intern GenericList _node_to_list(GenericNode *node, u64 item_size);
wapp_intern inline void _dbl_list_validate(const GenericList *list, u64 item_size);
wapp_intern inline void _dbl_list_node_validate(const GenericList *list, const GenericNode *node, u64 item_size);
GenericList *_dbl_list_alloc(const Allocator *allocator, u64 item_size) {
wapp_debug_assert(allocator != NULL, "`allocator` should not be NULL");
GenericList *list = wapp_mem_allocator_alloc(allocator, sizeof(GenericList));
if (!list) { goto DBL_LIST_ALLOC_RETURN; }
memset((void *)list, 0, sizeof(GenericList));
list->magic = WAPP_DBL_LIST_MAGIC;
list->item_size = item_size;
DBL_LIST_ALLOC_RETURN:
return list;
}
GenericNode *_dbl_list_node_alloc(const Allocator *allocator, void *item, u64 item_size) {
wapp_debug_assert(allocator != NULL, "`allocator` should not be NULL");
GenericNode *node = wapp_mem_allocator_alloc(allocator, sizeof(GenericNode));
if (!node) { goto DBL_LIST_NODE_ALLOC_RETURN; }
memset((void *)node, 0, sizeof(GenericNode));
node->item = item;
node->header.magic = WAPP_DBL_NODE_MAGIC;
node->header.item_size = item_size;
DBL_LIST_NODE_ALLOC_RETURN:
return node;
}
GenericNode *_dbl_list_get(const GenericList *list, u64 index, u64 item_size) {
wapp_debug_assert(list != NULL, "`list` should not be NULL");
_dbl_list_validate(list, item_size);
wapp_runtime_assert(index < list->node_count, "`index` is out of bounds");
GenericNode *output = NULL;
GenericNode *current = list->first;
for (u64 i = 1; i <= index; ++i) {
current = current->header.next;
}
output = current;
return output;
}
void _dbl_list_push_front(GenericList *list, GenericNode *node, u64 item_size) {
wapp_debug_assert(list != NULL && node != NULL && (node->item) != NULL, "`list`, `node` and `node->item` should not be NULL");
_dbl_list_validate(list, item_size);
_dbl_list_node_validate(list, node, item_size);
GenericList node_list = _node_to_list(node, item_size);
if (list->node_count == 0) {
*list = node_list;
return;
}
list->node_count += node_list.node_count;
GenericNode *first = list->first;
if (first) {
first->header.prev = node_list.last;
}
list->first = node_list.first;
node_list.last->header.next = first;
}
void _dbl_list_push_back(GenericList *list, GenericNode *node, u64 item_size) {
wapp_debug_assert(list != NULL && node != NULL && (node->item) != NULL, "`list`, `node` and `node->item` should not be NULL");
_dbl_list_validate(list, item_size);
_dbl_list_node_validate(list, node, item_size);
GenericList node_list = _node_to_list(node, item_size);
if (list->node_count == 0) {
*list = node_list;
return;
}
list->node_count += node_list.node_count;
GenericNode *last = list->last;
if (last) {
last->header.next = node_list.first;
}
list->last = node_list.last;
node_list.first->header.prev = last;
}
void _dbl_list_insert(GenericList *list, GenericNode *node, u64 index, u64 item_size) {
wapp_debug_assert(list != NULL && node != NULL && (node->item) != NULL, "`list`, `node` and `node->item` should not be NULL");
_dbl_list_validate(list, item_size);
_dbl_list_node_validate(list, node, item_size);
if (index == 0) {
_dbl_list_push_front(list, node, item_size);
return;
} else if (index == list->node_count) {
_dbl_list_push_back(list, node, item_size);
return;
}
GenericNode *dst_node = _dbl_list_get(list, index, item_size);
if (!dst_node) {
return;
}
GenericList node_list = _node_to_list(node, item_size);
list->node_count += node_list.node_count;
GenericNode *prev = dst_node->header.prev;
dst_node->header.prev = node_list.last;
prev->header.next = node_list.first;
node_list.first->header.prev = prev;
node_list.last->header.next = dst_node;
}
GenericNode *_dbl_list_pop_front(GenericList *list, u64 item_size) {
wapp_debug_assert(list != NULL, "`list` should not be NULL");
_dbl_list_validate(list, item_size);
GenericNode *output = NULL;
if (list->node_count == 0) {
goto RETURN_LIST_POP_FRONT;
}
output = list->first;
if (list->node_count == 1) {
*list = (GenericList){.magic = WAPP_DBL_LIST_MAGIC, .item_size = item_size};
goto RETURN_LIST_POP_FRONT;
}
--(list->node_count);
list->first = output->header.next;
output->header.prev = output->header.next = NULL;
RETURN_LIST_POP_FRONT:
return output;
}
GenericNode *_dbl_list_pop_back(GenericList *list, u64 item_size) {
wapp_debug_assert(list != NULL, "`list` should not be NULL");
_dbl_list_validate(list, item_size);
GenericNode *output = NULL;
if (list->node_count == 0) {
goto RETURN_LIST_POP_BACK;
}
output = list->last;
if (list->node_count == 1) {
*list = (GenericList){.magic = WAPP_DBL_LIST_MAGIC, .item_size = item_size};
goto RETURN_LIST_POP_BACK;
}
--(list->node_count);
list->last = output->header.prev;
output->header.prev = output->header.next = NULL;
RETURN_LIST_POP_BACK:
return output;
}
GenericNode *_dbl_list_remove(GenericList *list, u64 index, u64 item_size) {
wapp_debug_assert(list != NULL, "`list` should not be NULL");
_dbl_list_validate(list, item_size);
GenericNode *output = NULL;
if (index == 0) {
output = _dbl_list_pop_front(list, item_size);
goto RETURN_LIST_REMOVE;
} else if (index == list->node_count) {
output = _dbl_list_pop_back(list, item_size);
goto RETURN_LIST_REMOVE;
}
output = _dbl_list_get(list, index, item_size);
if (!output) {
goto RETURN_LIST_REMOVE;
}
output->header.prev->header.next = output->header.next;
output->header.next->header.prev = output->header.prev;
--(list->node_count);
output->header.prev = output->header.next = NULL;
RETURN_LIST_REMOVE:
return output;
}
void _dbl_list_empty(GenericList *list, u64 item_size) {
wapp_debug_assert(list != NULL, "`list` should not be NULL");
_dbl_list_validate(list, item_size);
u64 count = list->node_count;
for (u64 i = 0; i < count; ++i) {
_dbl_list_pop_back(list, item_size);
}
}
wapp_intern GenericList _node_to_list(GenericNode *node, u64 item_size) {
GenericList output = {
.magic = WAPP_DBL_LIST_MAGIC,
.first = node,
.last = node,
.node_count = 1,
.item_size = item_size,
};
while (output.first->header.prev != NULL) {
output.first = output.first->header.prev;
++(output.node_count);
}
while (output.last->header.next != NULL) {
output.last = output.last->header.next;
++(output.node_count);
}
return output;
}
wapp_intern inline void _dbl_list_validate(const GenericList *list, u64 item_size) {
wapp_runtime_assert(list->magic == WAPP_DBL_LIST_MAGIC, "`list` isn't a valid wapp list type");
wapp_runtime_assert(list->item_size == item_size, "Invalid item provided");
}
wapp_intern inline void _dbl_list_node_validate(const GenericList *list, const GenericNode *node, u64 item_size) {
wapp_runtime_assert(node->header.magic == WAPP_DBL_NODE_MAGIC, "`node` isn't a valid wapp node type");
wapp_runtime_assert(list->item_size == node->header.item_size, "Mismatched `list` and `node` types");
wapp_runtime_assert(node->header.item_size == item_size, "Invalid item provided");
}

View File

@@ -1,184 +0,0 @@
// vim:fileencoding=utf-8:foldmethod=marker
#ifndef DBL_LIST_H
#define DBL_LIST_H
#include "../mem/allocator/mem_allocator.h"
#include "../../common/aliases/aliases.h"
#include "../../common/platform/platform.h"
#ifdef WAPP_PLATFORM_CPP
BEGIN_C_LINKAGE
#endif // !WAPP_PLATFORM_CPP
#define WAPP_DBL_LIST_MAGIC (u64)0x57415f444c5354
#define WAPP_DBL_NODE_MAGIC (u64)0x57415f444e44
typedef struct GenericNode GenericNode;
typedef struct {
u64 magic;
u64 item_size;
GenericNode *prev;
GenericNode *next;
} NodeHeader;
struct GenericNode {
NodeHeader header;
void *item;
};
typedef struct {
u64 magic;
u64 node_count;
u64 item_size;
GenericNode *first;
GenericNode *last;
} GenericList;
// NOTE (Abdelrahman): GenericList typedefs for readability
typedef GenericList VoidPtrList;
typedef GenericList C8List;
typedef GenericList C16List;
typedef GenericList C32List;
typedef GenericList U8List;
typedef GenericList U16List;
typedef GenericList U32List;
typedef GenericList U64List;
typedef GenericList B8List;
typedef GenericList I8List;
typedef GenericList I16List;
typedef GenericList I32List;
typedef GenericList I64List;
typedef GenericList F32List;
typedef GenericList F64List;
typedef GenericList F128List;
typedef GenericList UptrList;
typedef GenericList IptrList;
typedef GenericList Str8List;
// NOTE (Abdelrahman): GenericNode typedefs for readability
typedef GenericNode VoidPtrNode;
typedef GenericNode C8Node;
typedef GenericNode C16Node;
typedef GenericNode C32Node;
typedef GenericNode U8Node;
typedef GenericNode U16Node;
typedef GenericNode U32Node;
typedef GenericNode U64Node;
typedef GenericNode B8Node;
typedef GenericNode I8Node;
typedef GenericNode I16Node;
typedef GenericNode I32Node;
typedef GenericNode I64Node;
typedef GenericNode F32Node;
typedef GenericNode F64Node;
typedef GenericNode F128Node;
typedef GenericNode UptrNode;
typedef GenericNode IptrNode;
typedef GenericNode Str8Node;
#ifdef WAPP_PLATFORM_CPP
#define wapp_dbl_list(TYPE) \
GenericList{WAPP_DBL_LIST_MAGIC, 0, sizeof(TYPE), nullptr, nullptr}
#define _dbl_list_node(TYPE, ITEM_PTR) ([&]() { \
wapp_persist GenericNode node = { \
NodeHeader{WAPP_DBL_NODE_MAGIC, sizeof(TYPE), nullptr, nullptr}, \
ITEM_PTR, \
}; \
\
return &node; \
}())
#else
#define wapp_dbl_list(TYPE) ( \
(GenericList){.magic = WAPP_DBL_LIST_MAGIC, .item_size = sizeof(TYPE)} \
)
#define _dbl_list_node(TYPE, ITEM_PTR) ( \
&((GenericNode){.header = {.magic = WAPP_DBL_NODE_MAGIC, .item_size = sizeof(TYPE)}, \
.item = ITEM_PTR}) \
)
#endif // !WAPP_PLATFORM_CPP
#define wapp_dbl_list_alloc(TYPE, ALLOCATOR) \
(_dbl_list_alloc(ALLOCATOR, sizeof(TYPE)))
#define wapp_dbl_list_get(TYPE, LIST_PTR, ITEM_INDEX) \
((TYPE *)(_dbl_list_get(LIST_PTR, ITEM_INDEX, sizeof(TYPE))->item))
#define wapp_dbl_list_get_node(TYPE, LIST_PTR, ITEM_INDEX) \
(_dbl_list_get(LIST_PTR, ITEM_INDEX, sizeof(TYPE)))
#define wapp_dbl_list_get_node_item(TYPE, NODE_PTR) \
((TYPE *)( \
(NODE_PTR == NULL) ? \
NULL : \
(NODE_PTR)->item \
))
#define wapp_dbl_list_push_front(TYPE, LIST_PTR, ITEM_PTR) \
(_dbl_list_push_front(LIST_PTR, _dbl_list_node(TYPE, ITEM_PTR), sizeof(TYPE)))
#define wapp_dbl_list_push_back(TYPE, LIST_PTR, ITEM_PTR) \
(_dbl_list_push_back(LIST_PTR, _dbl_list_node(TYPE, ITEM_PTR), sizeof(TYPE)))
#define wapp_dbl_list_insert(TYPE, LIST_PTR, ITEM_PTR, ITEM_INDEX) \
(_dbl_list_insert(LIST_PTR, _dbl_list_node(TYPE, ITEM_PTR), \
ITEM_INDEX, sizeof(TYPE)))
#define wapp_dbl_list_push_front_alloc(TYPE, ALLOCATOR, LIST_PTR, ITEM_PTR) \
(_dbl_list_push_front(LIST_PTR, _dbl_list_node_alloc(ALLOCATOR, ITEM_PTR, sizeof(TYPE)), \
sizeof(TYPE)))
#define wapp_dbl_list_push_back_alloc(TYPE, ALLOCATOR, LIST_PTR, ITEM_PTR) \
(_dbl_list_push_back(LIST_PTR, _dbl_list_node_alloc(ALLOCATOR, ITEM_PTR, sizeof(TYPE)), \
sizeof(TYPE)))
#define wapp_dbl_list_insert_alloc(TYPE, ALLOCATOR, LIST_PTR, ITEM_PTR, ITEM_INDEX) \
(_dbl_list_insert(LIST_PTR, _dbl_list_node_alloc(ALLOCATOR, ITEM_PTR, sizeof(TYPE)), \
ITEM_INDEX, sizeof(TYPE)))
#define wapp_dbl_list_pop_front(TYPE, LIST_PTR) \
((TYPE *)( \
(LIST_PTR == NULL || (LIST_PTR)->node_count == 0) ? \
NULL : \
_dbl_list_pop_front(LIST_PTR, sizeof(TYPE))->item \
))
#define wapp_dbl_list_pop_back(TYPE, LIST_PTR) \
((TYPE *)( \
(LIST_PTR == NULL || (LIST_PTR)->node_count == 0) ? \
NULL : \
_dbl_list_pop_back(LIST_PTR, sizeof(TYPE))->item \
))
#define wapp_dbl_list_remove(TYPE, LIST_PTR, ITEM_INDEX) \
((TYPE *)( \
(LIST_PTR == NULL || (LIST_PTR)->node_count == 0 || ITEM_INDEX >= (LIST_PTR)->node_count) ? \
NULL : \
_dbl_list_remove(LIST_PTR, ITEM_INDEX, sizeof(TYPE))->item \
))
#define wapp_dbl_list_pop_front_node(TYPE, LIST_PTR) \
( \
(LIST_PTR == NULL || (LIST_PTR)->node_count == 0) ? \
NULL : \
_dbl_list_pop_front(LIST_PTR, sizeof(TYPE)) \
)
#define wapp_dbl_list_pop_back_node(TYPE, LIST_PTR) \
( \
(LIST_PTR == NULL || (LIST_PTR)->node_count == 0) ? \
NULL : \
_dbl_list_pop_back(LIST_PTR, sizeof(TYPE)) \
)
#define wapp_dbl_list_remove_node(TYPE, LIST_PTR, ITEM_INDEX) \
( \
(LIST_PTR == NULL || (LIST_PTR)->node_count == 0 || ITEM_INDEX >= (LIST_PTR)->node_count) ? \
NULL : \
_dbl_list_remove(LIST_PTR, ITEM_INDEX, sizeof(TYPE)) \
)
#define wapp_dbl_list_empty(TYPE, LIST_PTR) \
(_dbl_list_empty(LIST_PTR, sizeof(TYPE)))
GenericList *_dbl_list_alloc(const Allocator *allocator, u64 item_size);
GenericNode *_dbl_list_node_alloc(const Allocator *allocator, void *item, u64 item_size);
GenericNode *_dbl_list_get(const GenericList *list, u64 index, u64 item_size);
void _dbl_list_push_front(GenericList *list, GenericNode *node, u64 item_size);
void _dbl_list_push_back(GenericList *list, GenericNode *node, u64 item_size);
void _dbl_list_insert(GenericList *list, GenericNode *node, u64 index, u64 item_size);
GenericNode *_dbl_list_pop_front(GenericList *list, u64 item_size);
GenericNode *_dbl_list_pop_back(GenericList *list, u64 item_size);
GenericNode *_dbl_list_remove(GenericList *list, u64 index, u64 item_size);
void _dbl_list_empty(GenericList *list, u64 item_size);
#ifdef WAPP_PLATFORM_CPP
END_C_LINKAGE
#endif // !WAPP_PLATFORM_CPP
#endif // !DBL_LIST_H

View File

@@ -1,35 +0,0 @@
// 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);
}

View File

@@ -1,50 +0,0 @@
// 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

View File

@@ -1,25 +0,0 @@
// vim:fileencoding=utf-8:foldmethod=marker
#include "mem_utils.h"
#include "../../../common/aliases/aliases.h"
#include "../../../common/assert/assert.h"
#include "../../../common/misc/misc_utils.h"
#include <stddef.h>
void *wapp_mem_util_align_forward(void *ptr, u64 alignment) {
wapp_debug_assert(ptr != NULL, "`ptr` should not be NULL");
wapp_runtime_assert(wapp_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;
}

View File

@@ -1,19 +0,0 @@
// 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

View File

@@ -1,85 +0,0 @@
// vim:fileencoding=utf-8:foldmethod=marker
#include "queue.h"
#include "../array/array.h"
#include "../../common/assert/assert.h"
#include "../../common/misc/misc_utils.h"
#include <string.h>
void _queue_push(GenericQueue *queue, void *item, u64 item_size) {
wapp_debug_assert(queue != NULL, "`queue` should not be NULL");
wapp_runtime_assert(item_size == wapp_array_item_size(queue->items), "Invalid type");
u64 capacity = wapp_array_capacity(queue->items);
if (queue->count >= capacity) { return; }
u64 index = (queue->back)++;
_array_set(queue->items, index, item, item_size);
++(queue->count);
if (queue->back >= capacity) {
queue->back = 0;
}
}
GenericQueue *_queue_push_alloc(const Allocator *allocator, GenericQueue *queue, void *item, u64 item_size) {
wapp_debug_assert(allocator != NULL && queue != NULL && item != NULL,
"`allocator`, `queue` and `item` should not be NULL");
wapp_runtime_assert(item_size == wapp_array_item_size(queue->items), "Invalid type");
GenericQueue *output = queue;
u64 capacity = wapp_array_capacity(queue->items);
if (queue->count >= capacity) {
u64 new_capacity = wapp_misc_utils_u64_round_up_pow2(capacity * 2);
u64 array_size = _array_calc_alloc_size(new_capacity, item_size);
u64 alloc_size = sizeof(GenericQueue) + array_size;
void *buffer = wapp_mem_allocator_alloc(allocator, alloc_size);
if (!buffer) {
goto RETURN_QUEUE_PUSH_ALLOC;
}
memset((void *)buffer, 0, alloc_size);
output = (GenericQueue *)buffer;
output->items = _array_from_preallocated_buffer((void *)(output + 1), array_size, ARRAY_INIT_FILLED, item_size);
// NOTE (Abdelrahman): When the queue is full, the front and back indices should
// always be the same
u64 front_count = capacity - queue->front;
u64 back_count = queue->back;
void *copy_boundary = (void *)((uptr)(queue->items) + (queue->front * item_size));
memcpy(output->items, copy_boundary, front_count * item_size);
if (back_count > 0) {
void *back_copy_dst = (void *)((uptr)(output->items) + (front_count * item_size));
memcpy(back_copy_dst, queue->items, back_count * item_size);
}
output->front = 0;
output->back = front_count + back_count;
output->count = queue->count;
}
_queue_push(output, item, item_size);
RETURN_QUEUE_PUSH_ALLOC:
return output;
}
void *_queue_pop(GenericQueue *queue, u64 item_size) {
wapp_debug_assert(queue != NULL, "`queue` should not be NULL");
wapp_runtime_assert(item_size == wapp_array_item_size(queue->items), "Invalid type");
if (queue->count == 0) { return NULL; }
u64 index = (queue->front)++;
--(queue->count);
u64 capacity = wapp_array_capacity(queue->items);
if (queue->front >= capacity) {
queue->front = 0;
}
return _array_get(queue->items, index, item_size);
}

View File

@@ -1,100 +0,0 @@
// vim:fileencoding=utf-8:foldmethod=marker
#ifndef QUEUE_H
#define QUEUE_H
#include "../array/array.h"
#include "../mem/allocator/mem_allocator.h"
#include "../../common/aliases/aliases.h"
#include "../../common/platform/platform.h"
#ifdef WAPP_PLATFORM_CPP
BEGIN_C_LINKAGE
#endif // !WAPP_PLATFORM_CPP
typedef struct {
GenericArray items;
u64 front;
u64 back;
u64 count;
} GenericQueue;
// NOTE (Abdelrahman): GenericQueue typedefs for readability
typedef GenericQueue VoidPtrQueue;
typedef GenericQueue C8Queue;
typedef GenericQueue C16Queue;
typedef GenericQueue C32Queue;
typedef GenericQueue U8Queue;
typedef GenericQueue U16Queue;
typedef GenericQueue U32Queue;
typedef GenericQueue U64Queue;
typedef GenericQueue B8Queue;
typedef GenericQueue I8Queue;
typedef GenericQueue I16Queue;
typedef GenericQueue I32Queue;
typedef GenericQueue I64Queue;
typedef GenericQueue F32Queue;
typedef GenericQueue F64Queue;
typedef GenericQueue F128Queue;
typedef GenericQueue UptrQueue;
typedef GenericQueue IptrQueue;
typedef GenericQueue Str8Queue;
#ifdef WAPP_PLATFORM_CPP
#define wapp_queue(TYPE, CAPACITY) ([&]() { \
wapp_persist GenericArray arr = wapp_array_with_capacity(TYPE, CAPACITY, ARRAY_INIT_FILLED); \
wapp_persist GenericQueue queue = { \
arr, \
0, \
0, \
0, \
}; \
\
return queue; \
}())
#define wapp_queue_alloc(TYPE, ALLOCATOR_PTR, CAPACITY) ([&]() { \
wapp_persist GenericQueue queue = { \
wapp_array_alloc_capacity(TYPE, ALLOCATOR_PTR, CAPACITY, ARRAY_INIT_FILLED) \
0, \
0, \
0, \
}; \
\
return queue; \
}())
#else
#define wapp_queue(TYPE, CAPACITY) ((GenericQueue){ \
.items = wapp_array_with_capacity(TYPE, CAPACITY, ARRAY_INIT_FILLED), \
.front = 0, \
.back = 0, \
.count = 0, \
})
#define wapp_queue_alloc(TYPE, ALLOCATOR_PTR, CAPACITY) ((GenericQueue){ \
.items = wapp_array_alloc_capacity(TYPE, ALLOCATOR_PTR, CAPACITY, ARRAY_INIT_FILLED), \
.front = 0, \
.back = 0, \
.count = 0, \
})
#endif // !WAPP_PLATFORM_CPP
#define wapp_queue_capacity(QUEUE_PTR) (wapp_array_capacity((QUEUE_PTR)->items))
#define wapp_queue_item_size(QUEUE_PTR) (wapp_array_item_size((QUEUE_PTR)->items))
#define wapp_queue_push(TYPE, QUEUE_PTR, VALUE_PTR) ( \
_queue_push(QUEUE_PTR, VALUE_PTR, sizeof(TYPE)) \
)
#define wapp_queue_push_alloc(TYPE, ALLOCATOR_PTR, QUEUE_PTR, VALUE_PTR) ( \
_queue_push_alloc(ALLOCATOR_PTR, QUEUE_PTR, VALUE_PTR, sizeof(TYPE)) \
)
#define wapp_queue_pop(TYPE, QUEUE_PTR) ( \
(TYPE *)_queue_pop(QUEUE_PTR, sizeof(TYPE)) \
)
void _queue_push(GenericQueue *queue, void *item, u64 item_size);
GenericQueue *_queue_push_alloc(const Allocator *allocator, GenericQueue *queue, void *item, u64 item_size);
void *_queue_pop(GenericQueue *queue, u64 item_size);
#ifdef WAPP_PLATFORM_CPP
END_C_LINKAGE
#endif // !WAPP_PLATFORM_CPP
#endif // !QUEUE_H

View File

@@ -1,480 +0,0 @@
// vim:fileencoding=utf-8:foldmethod=marker
#include "str8.h"
#include "../../array/array.h"
#include "../../mem/allocator/mem_allocator.h"
#include "../../../common/aliases/aliases.h"
#include "../../../common/assert/assert.h"
#include <ctype.h>
#include <stdarg.h>
#include <stddef.h>
#include <stdio.h>
#include <string.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);
}
b8 wapp_str8_equal(Str8RO *s1, Str8RO *s2) {
if (s1->size != s2->size) {
return false;
}
return wapp_str8_equal_to_count(s1, s2, s1->size);
}
b8 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 SOURCE_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);
SOURCE_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);
}
void wapp_str8_to_lower(Str8 *dst, Str8RO *src) {
wapp_debug_assert(src != NULL && dst != NULL, "`dst` and `src` should not be NULL");
wapp_debug_assert(dst->capacity >= src->capacity, "`dst` does not have enough capacity");
dst->size = src->size;
// NOTE (Abdelrahman): Uses a while loop instead of a for loop to get rid of
// MSVC Spectre mitigation warnings
u64 index = 0;
b8 running = true;
while (running) {
wapp_str8_set(dst, index, (u8)tolower(wapp_str8_get(src, index)));
++index;
running = index < src->size;
}
}
void wapp_str8_to_upper(Str8 *dst, Str8RO *src) {
wapp_debug_assert(src != NULL && dst != NULL, "`dst` and `src` should not be NULL");
wapp_debug_assert(dst->capacity >= src->capacity, "`dst` does not have enough capacity");
dst->size = src->size;
// NOTE (Abdelrahman): Uses a while loop instead of a for loop to get rid of
// MSVC Spectre mitigation warnings
u64 index = 0;
b8 running = true;
while (running) {
wapp_str8_set(dst, index, (u8)toupper(wapp_str8_get(src, index)));
++index;
running = index < src->size;
}
}
void wapp_str8_from_bytes(Str8 *dst, const U8Array src) {
wapp_debug_assert(src != NULL && dst != NULL, "`dst` and `src` should not be NULL");
u64 size = wapp_array_count(src) * wapp_array_item_size(src);
wapp_debug_assert(dst->capacity >= size, "`dst` does not have enough capacity");
dst->size = size;
memcpy(dst->buf, src, size);
}
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;
b8 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;
b8 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_dbl_list_alloc(Str8, allocator);
if (delimiter->size > str->size) {
Str8 *full = wapp_str8_alloc_str8(allocator, str);
if (full) {
wapp_dbl_list_push_back_alloc(Str8, allocator, output, full);
}
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);
if (before_str) {
wapp_dbl_list_push_back_alloc(Str8, allocator, output, before_str);
}
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);
if (rest) {
wapp_dbl_list_push_back_alloc(Str8, allocator, output, rest);
}
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_dbl_list_alloc(Str8, allocator);
if (delimiter->size > str->size) {
Str8 *full = wapp_str8_alloc_str8(allocator, str);
if (full) {
wapp_dbl_list_push_back_alloc(Str8, allocator, output, full);
}
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);
if (after_str) {
wapp_dbl_list_push_front_alloc(Str8, allocator, output, after_str);
}
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);
if (rest) {
wapp_dbl_list_push_front_alloc(Str8, allocator, output, rest);
}
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
Str8 *node;
u64 node_index = 0;
b8 running = node_index < list->node_count;
while (running) {
node = wapp_dbl_list_get(Str8, list, node_index);
if (!node) {
break;
}
wapp_str8_concat_capped(output, node);
// NOTE (Abdelrahman): Comparison extracted to variable to silence
// MSVC Spectre mitigation warnings
b8 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
Str8 *node;
u64 node_index = 0;
u64 output = 0;
b8 running = node_index < list->node_count;
while (running) {
node = wapp_dbl_list_get(Str8, list, node_index);
if (!node) {
break;
}
output += node->size;
++node_index;
running = node_index < list->node_count;
}
return output;
}

View File

@@ -1,130 +0,0 @@
// 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 "../../array/array.h"
#include "../../dbl_list/dbl_list.h"
#include "../../mem/allocator/mem_allocator.h"
#include <string.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) ([&](){ \
wapp_persist 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) ([&]() { \
wapp_persist 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);
b8 wapp_str8_equal(Str8RO *s1, Str8RO *s2);
b8 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, ...);
void wapp_str8_to_lower(Str8 *dst, Str8RO *src);
void wapp_str8_to_upper(Str8 *dst, Str8RO *src);
void wapp_str8_from_bytes(Str8 *dst, const U8Array src);
/**
* 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
*/
u64 wapp_str8_list_total_size(const Str8List *list);
#ifdef WAPP_PLATFORM_CPP
END_C_LINKAGE
#endif // !WAPP_PLATFORM_CPP
#endif // !STR8_H

View File

@@ -1,14 +0,0 @@
// vim:fileencoding=utf-8:foldmethod=marker
#ifndef WAPP_BASE_C
#define WAPP_BASE_C
#include "wapp_base.h"
#include "array/array.c"
#include "dbl_list/dbl_list.c"
#include "queue/queue.c"
#include "mem/allocator/mem_allocator.c"
#include "mem/utils/mem_utils.c"
#include "strings/str8/str8.c"
#endif // !WAPP_BASE_C

View File

@@ -1,14 +0,0 @@
// vim:fileencoding=utf-8:foldmethod=marker
#ifndef WAPP_BASE_H
#define WAPP_BASE_H
#include "array/array.h"
#include "dbl_list/dbl_list.h"
#include "queue/queue.h"
#include "mem/allocator/mem_allocator.h"
#include "mem/utils/mem_utils.h"
#include "strings/str8/str8.h"
#include "../common/wapp_common.h"
#endif // !WAPP_BASE_H

View File

@@ -1,67 +1,33 @@
// vim:fileencoding=utf-8:foldmethod=marker
#ifndef ALIASES_H
#define ALIASES_H
#include "../platform/platform.h"
#include <stdint.h>
#if defined(WAPP_PLATFORM_C) && WAPP_PLATFORM_C_VERSION >= WAPP_PLATFORM_C11_VERSION && !defined(WAPP_PLATFORM_APPLE)
#include <uchar.h>
#define u8 uint8_t
#define u16 uint16_t
#define u32 uint32_t
#define u64 uint64_t
#if WAPP_PLATFORM_C_VERSION >= WAPP_PLATFORM_C23_VERSION
typedef char8_t c8;
#else
typedef uint8_t c8;
#endif // !WAPP_PLATFORM_C23_VERSION
#define i8 int8_t
#define i16 int16_t
#define i32 int32_t
#define i64 int64_t
typedef char16_t c16;
typedef char32_t c32;
#else
typedef uint8_t c8;
typedef uint16_t c16;
typedef uint32_t c32;
#endif // !WAPP_PLATFORM_C
#define f32 float
#define f64 double
#define f128 long double
typedef uint8_t u8;
typedef uint16_t u16;
typedef uint32_t u32;
typedef uint64_t u64;
#define uptr uintptr_t
#define iptr intptr_t
typedef uint8_t b8;
#define external extern
#define internal static
#define persistent static
#ifndef WAPP_PLATFORM_CPP
#ifndef false
#define false (b8)0
#endif // !false
#ifndef true
#define true (b8)1
#endif // !true
#endif // !WAPP_PLATFORM_CPP
typedef int8_t i8;
typedef int16_t i16;
typedef int32_t i32;
typedef int64_t i64;
typedef float f32;
typedef double f64;
typedef long double f128;
typedef uintptr_t uptr;
typedef intptr_t iptr;
#define wapp_extern extern
#define wapp_intern static
#define wapp_persist static
#ifdef WAPP_PLATFORM_CPP
#define wapp_class_mem static
#ifdef __cplusplus
#define class_mem static
#define BEGIN_C_LINKAGE extern "C" {
#define END_C_LINKAGE }
#endif // WAPP_PLATFORM_CPP
#endif // __cplusplus
#endif // !ALIASES_H

View File

@@ -1,61 +0,0 @@
// 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]
#ifndef WAPP_NO_RUNTIME_ASSERT
#define wapp_runtime_assert(EXPR, MSG) __wapp_runtime_assert(EXPR, MSG)
#else
#define wapp_runtime_assert(EXPR, MSG)
#endif
#ifdef WAPP_DEBUG_ASSERT
#define wapp_debug_assert(EXPR, MSG) wapp_runtime_assert(EXPR, MSG)
#else
#define wapp_debug_assert(EXPR, MSG)
#endif
#ifdef WAPP_PLATFORM_WINDOWS
#define __wapp_runtime_assert(EXPR, MSG) do { \
__pragma(warning(push)) \
__pragma(warning(disable:4127)) \
if (!(EXPR)) { \
__pragma(warning(pop)) \
__runtime_assert_failed(EXPR, MSG); \
} \
} while(false)
#else
#define __wapp_runtime_assert(EXPR, MSG) do { \
if (!(EXPR)) { \
__runtime_assert_failed(EXPR, MSG); \
} \
} while(false)
#endif // !WAPP_PLATFORM_WINDOWS
#define __runtime_assert_failed(EXPR, MSG) do { \
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

View File

@@ -1,63 +1,13 @@
// vim:fileencoding=utf-8:foldmethod=marker
#ifndef MISC_UTILS_H
#define MISC_UTILS_H
#include "../aliases/aliases.h"
#include "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 KiB(SIZE) (((u64)SIZE) << 10)
#define MiB(SIZE) (((u64)SIZE) << 20)
#define GiB(SIZE) (((u64)SIZE) << 30)
#define TiB(SIZE) (((u64)SIZE) << 40)
#define PiB(SIZE) (((u64)SIZE) << 50)
#define EiB(SIZE) (((u64)SIZE) << 60)
#define KB(SIZE) (((u64)SIZE) * 1000llu)
#define MB(SIZE) (KB(SIZE) * 1000llu)
#define GB(SIZE) (MB(SIZE) * 1000llu)
#define TB(SIZE) (GB(SIZE) * 1000llu)
#define PB(SIZE) (TB(SIZE) * 1000llu)
#define EB(SIZE) (PB(SIZE) * 1000llu)
#define wapp_misc_utils_reserve_padding(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 \
)
#define wapp_is_power_of_two(NUM) ((NUM & (NUM - 1)) == 0)
#define wapp_pointer_offset(PTR, OFFSET) ((void *)((uptr)(PTR) + (OFFSET)))
#ifdef WAPP_PLATFORM_CPP
END_C_LINKAGE
#include <tuple>
#define wapp_misc_utils_va_args_count(T, ...) (std::tuple_size<decltype(std::make_tuple(__VA_ARGS__))>::value)
#else
#define wapp_misc_utils_va_args_count(T, ...) (sizeof((T[]){__VA_ARGS__})/sizeof(T))
#endif // !WAPP_PLATFORM_CPP
#define wapp_misc_utils_padding_size(SIZE) u8 reserved_padding[sizeof(void *) - ((SIZE) % sizeof(void *))]
#endif // !MISC_UTILS_H

View File

@@ -1,5 +1,3 @@
// vim:fileencoding=utf-8:foldmethod=marker
#ifndef PLATFORM_H
#define PLATFORM_H
@@ -60,55 +58,4 @@
#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

View File

@@ -1,11 +0,0 @@
// 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

View File

@@ -0,0 +1,49 @@
#include "mem_allocator.h"
#include <stdlib.h>
/***************************************************************************/ //
////////////////////////////////////////////////////////////////////////////////
////// Allocator API definitions
////////////////////////////////////////////////////////////////////////////////
/***************************************************************************/ //
void *wapp_mem_allocator_alloc(const Allocator *allocator, u64 size) {
if (!allocator || !(allocator->alloc)) {
return NULL;
}
return allocator->alloc(size, allocator->obj);
}
void *wapp_mem_allocator_alloc_aligned(const Allocator *allocator, u64 size, u64 alignment) {
if (!allocator || !(allocator->alloc_aligned)) {
return 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) {
if (!allocator || !(allocator->realloc)) {
return 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) {
if (!allocator || !(allocator->realloc_aligned)) {
return NULL;
}
return allocator->realloc_aligned(ptr, old_size, new_size, alignment, allocator->obj);
}
void wapp_mem_allocator_free(const Allocator *allocator, void **ptr) {
if (!allocator || !(allocator->free)) {
return;
}
allocator->free(ptr, allocator->obj);
}

View File

@@ -0,0 +1,55 @@
#ifndef MEM_ALLOCATOR_H
#define MEM_ALLOCATOR_H
#include "aliases.h"
#ifdef __cplusplus
BEGIN_C_LINKAGE
#endif // __cplusplus
/***************************************************************************/ //
////////////////////////////////////////////////////////////////////////////////
////// Allocator function pointer types
////////////////////////////////////////////////////////////////////////////////
/***************************************************************************/ //
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, void *alloc_obj);
/***************************************************************************/ //
////////////////////////////////////////////////////////////////////////////////
////// Allocator type
////////////////////////////////////////////////////////////////////////////////
/***************************************************************************/ //
typedef struct allocator Allocator;
struct allocator {
void *obj;
MemAllocFunc *alloc;
MemAllocAlignedFunc *alloc_aligned;
MemReallocFunc *realloc;
MemReallocAlignedFunc *realloc_aligned;
MemFreeFunc *free;
};
/***************************************************************************/ //
////////////////////////////////////////////////////////////////////////////////
////// Allocator API declarations
////////////////////////////////////////////////////////////////////////////////
/***************************************************************************/ //
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);
#ifdef __cplusplus
END_C_LINKAGE
#endif // __cplusplus
#endif // !MEM_ALLOCATOR_H

View File

@@ -0,0 +1,145 @@
#include "mem_arena.h"
#include "aliases.h"
#include "misc_utils.h"
#include "mem_utils.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 = 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) {
if (!arena) {
return 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)) {
output = (u8 *)wapp_mem_util_alloc(alloc_start, (uptr)(arena->offset) - (uptr)(alloc_start),
WAPP_MEM_ACCESS_READ_WRITE, WAPP_MEM_ALLOC_COMMIT,
WAPP_MEM_INIT_INITIALISED);
}
#else
memset(output, 0, size);
#endif // ifdef WAPP_PLATFORM_WINDOWS
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) {
if (!arena) {
return;
}
memset(arena->buf, 0, arena->offset - arena->buf);
arena->offset = arena->buf;
}
void wapp_mem_arena_destroy(Arena **arena) {
if (!arena) {
return;
}
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;
}

View File

@@ -0,0 +1,40 @@
#ifndef MEM_ARENA_H
#define MEM_ARENA_H
#include "aliases.h"
#include "mem_utils.h"
#include <stdbool.h>
#ifdef __cplusplus
BEGIN_C_LINKAGE
#endif // __cplusplus
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 __cplusplus
END_C_LINKAGE
#endif // __cplusplus
#endif // !MEM_ARENA_H

View File

@@ -0,0 +1,71 @@
#include "mem_arena_allocator.h"
#include "mem_arena.h"
/***************************************************************************/ //
////////////////////////////////////////////////////////////////////////////////
////// Arena Allocator wrappers declarations
////////////////////////////////////////////////////////////////////////////////
/***************************************************************************/ //
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);
/***************************************************************************/ //
////////////////////////////////////////////////////////////////////////////////
////// Arena Allocator API definitions
////////////////////////////////////////////////////////////////////////////////
/***************************************************************************/ //
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};
}
/***************************************************************************/ //
////////////////////////////////////////////////////////////////////////////////
////// Arena Allocator wrappers definitions
////////////////////////////////////////////////////////////////////////////////
/***************************************************************************/ //
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);
}

View File

@@ -0,0 +1,41 @@
#ifndef MEM_ARENA_ALLOCATOR_H
#define MEM_ARENA_ALLOCATOR_H
#include "aliases.h"
#include "mem_utils.h"
#include "mem_allocator.h"
#include <stdbool.h>
#ifdef __cplusplus
BEGIN_C_LINKAGE
#endif // __cplusplus
#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 __cplusplus
END_C_LINKAGE
#endif // __cplusplus
#endif // !MEM_ARENA_ALLOCATOR_H

View File

@@ -0,0 +1,62 @@
#include "mem_libc_allocator.h"
#include "aliases.h"
#include "mem_allocator.h"
#include <stdlib.h>
#include <string.h>
internal inline void *mem_libc_alloc(u64 size, void *alloc_obj);
// TODO (Abdelrahman): aligned_alloc isn't implemented on Windows. Revisit later
#if 0
internal inline void *mem_libc_alloc_aligned(u64 size, u64 alignment, void *alloc_obj);
#endif
internal inline void *mem_libc_realloc(void *ptr, u64 old_size, u64 new_size, void *alloc_obj);
internal inline void mem_libc_free(void **ptr, void *alloc_obj);
Allocator wapp_mem_libc_allocator(void) {
return (Allocator){
.obj = NULL,
.alloc = mem_libc_alloc,
.alloc_aligned = NULL,
.realloc = mem_libc_realloc,
.realloc_aligned = NULL,
.free = mem_libc_free,
};
}
internal inline void *mem_libc_alloc(u64 size, void *alloc_obj) {
(void)alloc_obj; // Silence unused warnings
return calloc(1, size);
}
#if 0
internal inline void *mem_libc_alloc_aligned(u64 size, u64 alignment,
void *alloc_obj) {
(void)alloc_obj; // Silence unused warnings
void *output = aligned_alloc(alignment, size);
if (output) {
memset(output, 0, size);
}
return output;
}
#endif
internal inline void *mem_libc_realloc(void *ptr, u64 old_size, u64 new_size, void *alloc_obj) {
// Silence unused warnings
(void)alloc_obj;
(void)new_size;
return realloc(ptr, old_size);
}
internal inline void mem_libc_free(void **ptr, void *alloc_obj) {
(void)alloc_obj; // Silence unused warnings
if (!ptr || !(*ptr)) {
return;
}
free(*ptr);
*ptr = NULL;
}

View File

@@ -0,0 +1,16 @@
#ifndef MEM_LIBC_H
#define MEM_LIBC_H
#include "mem_allocator.h"
#ifdef __cplusplus
BEGIN_C_LINKAGE
#endif // __cplusplus
Allocator wapp_mem_libc_allocator(void);
#ifdef __cplusplus
END_C_LINKAGE
#endif // __cplusplus
#endif // !MEM_LIBC_H

View File

@@ -1,192 +0,0 @@
// vim:fileencoding=utf-8:foldmethod=marker
#include "mem_arena.h"
#include "../../mem/mem_os.h"
#include "../../../common/aliases/aliases.h"
#include "../../../common/assert/assert.h"
#include "../../../common/misc/misc_utils.h"
#include "../../../base/mem/utils/mem_utils.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 KiB(16) // Allocate minimum of 4 pages
typedef enum {
ARENA_STORAGE_TYPE_ALLOCATED,
ARENA_STORAGE_TYPE_BUFFER,
} ArenaStorageType;
struct Arena {
u8 *buf;
u8 *offset;
u8 *prev_offset;
u64 capacity;
ArenaStorageType type;
b8 committed;
wapp_misc_utils_reserve_padding(sizeof(u8 *) * 3 + sizeof(u64) + sizeof(ArenaStorageType) + sizeof(b8));
};
b8 wapp_mem_arena_init_buffer(Arena **arena, u8 *buffer, u64 buffer_size) {
if (!arena || *arena || buffer_size < sizeof(Arena)) {
return false;
}
*arena = (Arena *)buffer;
Arena *arena_ptr = *arena;
arena_ptr->buf = (u8 *)(arena_ptr + 1);
arena_ptr->offset = arena_ptr->buf;
arena_ptr->prev_offset = NULL;
arena_ptr->capacity = buffer_size - sizeof(Arena);
arena_ptr->type = ARENA_STORAGE_TYPE_BUFFER;
arena_ptr->committed = true;
return true;
}
b8 wapp_mem_arena_init_allocated_custom(Arena **arena, u64 base_capacity, MemAllocFlags flags, b8 zero_buffer) {
if (!arena || *arena || base_capacity == 0) {
return false;
}
u64 size = sizeof(Arena) + (base_capacity >= ARENA_MINIMUM_CAPACITY ? base_capacity : ARENA_MINIMUM_CAPACITY);
u64 alloc_size = wapp_misc_utils_u64_round_up_pow2(size);
u8 *allocated = (u8 *)wapp_os_mem_alloc(NULL, alloc_size, WAPP_MEM_ACCESS_READ_WRITE, flags,
zero_buffer ? WAPP_MEM_INIT_INITIALISED : WAPP_MEM_INIT_UNINITIALISED);
if (!allocated) {
return false;
}
b8 committed = (flags & WAPP_MEM_ALLOC_COMMIT) == WAPP_MEM_ALLOC_COMMIT;
#ifdef WAPP_PLATFORM_WINDOWS
if (!committed) {
wapp_os_mem_alloc(allocated, sizeof(Arena), WAPP_MEM_ACCESS_READ_WRITE, WAPP_MEM_ALLOC_COMMIT,
WAPP_MEM_INIT_INITIALISED);
}
#endif // ifdef WAPP_PLATFORM_WINDOWS
if (!wapp_mem_arena_init_buffer(arena, allocated, alloc_size)) {
wapp_mem_arena_destroy(arena);
return false;
}
Arena *arena_ptr = *arena;
arena_ptr->type = ARENA_STORAGE_TYPE_ALLOCATED;
arena_ptr->committed = committed;
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->type == ARENA_STORAGE_TYPE_ALLOCATED && !(arena->committed)) {
wapp_os_mem_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) {
wapp_debug_assert(arena != NULL, "`arena` should not be NULL");
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) {
wapp_debug_assert(arena != NULL, "`arena` should not be NULL");
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_temp_begin(Arena *arena) {
wapp_debug_assert(arena != NULL, "`arena` should not be NULL");
if (arena->prev_offset != NULL) {
return;
}
arena->prev_offset = arena->offset;
}
void wapp_mem_arena_temp_end(Arena *arena) {
wapp_debug_assert(arena != NULL, "`arena` should not be NULL");
if (arena->prev_offset == NULL) {
return;
}
arena->offset = arena->prev_offset;
arena->prev_offset = NULL;
}
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->type == ARENA_STORAGE_TYPE_ALLOCATED) {
wapp_os_mem_free(*arena, sizeof(Arena) + arena_ptr->capacity);
}
*arena = NULL;
}

View File

@@ -1,45 +0,0 @@
// vim:fileencoding=utf-8:foldmethod=marker
#ifndef MEM_ARENA_H
#define MEM_ARENA_H
#include "../../mem/mem_os.h"
#include "../../../common/aliases/aliases.h"
#include "../../../common/platform/platform.h"
#ifdef WAPP_PLATFORM_CPP
BEGIN_C_LINKAGE
#endif // !WAPP_PLATFORM_CPP
typedef struct Arena Arena;
#define wapp_mem_arena_init_allocated(arena_dptr, base_capacity) \
(wapp_mem_arena_init_allocated_custom(arena_dptr, base_capacity, WAPP_MEM_ALLOC_RESERVE, false))
#define wapp_mem_arena_init_allocated_commit(arena_dptr, base_capacity) \
(wapp_mem_arena_init_allocated_custom(arena_dptr, base_capacity, WAPP_MEM_ALLOC_RESERVE | WAPP_MEM_ALLOC_COMMIT, false))
#define wapp_mem_arena_init_allocated_zero(arena_dptr, base_capacity) \
(wapp_mem_arena_init_allocated_custom(arena_dptr, base_capacity, WAPP_MEM_ALLOC_RESERVE, true))
#define wapp_mem_arena_init_allocated_commit_and_zero(arena_dptr, base_capacity) \
(wapp_mem_arena_init_allocated_custom(arena_dptr, base_capacity, WAPP_MEM_ALLOC_RESERVE | WAPP_MEM_ALLOC_COMMIT, true))
/**
* Arena initialisation function. `wapp_mem_arena_init_allocated_custom` provides the most
* control over how the Arena is initialised. Wrapper macros are provided for
* easier use.
*/
b8 wapp_mem_arena_init_allocated_custom(Arena **arena, u64 base_capacity, MemAllocFlags flags, b8 zero_buffer);
b8 wapp_mem_arena_init_buffer(Arena **arena, u8 *buffer, u64 buffer_size);
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_temp_begin(Arena *arena);
void wapp_mem_arena_temp_end(Arena *arena);
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

View File

@@ -1,87 +0,0 @@
// vim:fileencoding=utf-8:foldmethod=marker
#include "mem_arena_allocator.h"
#include "mem_arena.h"
#include "../../mem/mem_os.h"
#include "../../../common/aliases/aliases.h"
#include "../../../common/assert/assert.h"
wapp_intern void initialise_arena_allocator(Allocator *allocator);
wapp_intern void *mem_arena_alloc(u64 size, void *alloc_obj);
wapp_intern void *mem_arena_alloc_aligned(u64 size, u64 alignment, void *alloc_obj);
wapp_intern void *mem_arena_realloc(void *ptr, u64 old_size, u64 new_size, void *alloc_obj);
wapp_intern void *mem_arena_realloc_aligned(void *ptr, u64 old_size, u64 new_size, u64 alignment,
void *alloc_obj);
Allocator wapp_mem_arena_allocator_init_with_buffer(u8 *buffer, u64 buffer_size) {
Allocator allocator = {0};
b8 initialised = wapp_mem_arena_init_buffer((Arena **)(&allocator.obj), buffer, buffer_size);
if (!initialised) {
return allocator;
}
initialise_arena_allocator(&allocator);
return allocator;
}
Allocator wapp_mem_arena_allocator_init_custom(u64 base_capacity, MemAllocFlags flags, b8 zero_buffer) {
Allocator allocator = {0};
b8 initialised = wapp_mem_arena_init_allocated_custom((Arena **)(&allocator.obj), base_capacity, flags, zero_buffer);
if (!initialised) {
return allocator;
}
initialise_arena_allocator(&allocator);
return allocator;
}
void wapp_mem_arena_allocator_temp_begin(const Allocator *allocator) {
wapp_debug_assert(allocator != NULL, "`allocator` should not be NULL");
wapp_mem_arena_temp_begin((Arena *)(allocator->obj));
}
void wapp_mem_arena_allocator_temp_end(const Allocator *allocator) {
wapp_debug_assert(allocator != NULL, "`allocator` should not be NULL");
wapp_mem_arena_temp_end((Arena *)(allocator->obj));
}
void wapp_mem_arena_allocator_clear(Allocator *allocator) {
wapp_debug_assert(allocator != NULL, "`allocator` should not be NULL");
wapp_mem_arena_clear((Arena *)(allocator->obj));
}
void wapp_mem_arena_allocator_destroy(Allocator *allocator) {
wapp_debug_assert(allocator != NULL, "`allocator` should not be NULL");
wapp_mem_arena_destroy((Arena **)(&(allocator->obj)));
*allocator = (Allocator){0};
}
wapp_intern void initialise_arena_allocator(Allocator *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;
}
wapp_intern void *mem_arena_alloc(u64 size, void *alloc_obj) {
Arena *arena = (Arena *)alloc_obj;
return wapp_mem_arena_alloc(arena, size);
}
wapp_intern 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);
}
wapp_intern 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);
}
wapp_intern 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);
}

View File

@@ -1,46 +0,0 @@
// vim:fileencoding=utf-8:foldmethod=marker
#ifndef MEM_ARENA_ALLOCATOR_H
#define MEM_ARENA_ALLOCATOR_H
#include "../../mem/mem_os.h"
#include "../../../common/aliases/aliases.h"
#include "../../../common/platform/platform.h"
#include "../../../base/mem/allocator/mem_allocator.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, b8 zero_buffer);
Allocator wapp_mem_arena_allocator_init_with_buffer(u8 *buffer, u64 buffer_size);
void wapp_mem_arena_allocator_temp_begin(const Allocator *allocator);
void wapp_mem_arena_allocator_temp_end(const Allocator *allocator);
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

View File

@@ -1,136 +1,92 @@
// vim:fileencoding=utf-8:foldmethod=marker
#include "cpath.h"
#include "../allocators/arena/mem_arena_allocator.h"
#include "../../common/aliases/aliases.h"
#include "../../common/misc/misc_utils.h"
#include "../../base/dbl_list/dbl_list.h"
#include "../../base/mem/allocator/mem_allocator.h"
#include "../../base/strings/str8/str8.h"
#include "aliases.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;
void join_root_and_leaf(const char *root, const char *leaf, char *dst);
void join_path(char *dst, u64 count, ...) {
va_list args;
va_start(args, count);
for (u64 i = 0; i < count; ++i) {
join_root_and_leaf(dst, va_arg(args, const char *), dst);
}
if (parts->node_count == 0) {
return CPATH_JOIN_EMPTY_PARTS;
}
Str8 separator = wapp_str8_buf(4);
wapp_str8_push_back(&separator, WAPP_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
Str8 *first_node = wapp_dbl_list_get(Str8, parts, 0);
wapp_str8_copy_str8_capped(dst, first_node);
// NOTE (Abdelrahman): Uses a while loop instead of a for loop to get rid of
// MSVC Spectre mitigation warnings
Str8 *node = first_node;
u64 node_index = 1;
b8 running = node_index < parts->node_count;
while (running) {
node = wapp_dbl_list_get(Str8, parts, node_index);
if (node->size == 0) {
goto CPATH_JOIN_LOOP_END;
}
if (dst->size > 0) {
char dst_last = wapp_str8_get(dst, dst->size - 1);
char node_start = wapp_str8_get(node, 0);
b8 add_path_sep = dst_last != WAPP_PATH_SEP && node_start != WAPP_PATH_SEP;
if (add_path_sep) {
wapp_str8_concat_capped(dst, &separator);
}
}
wapp_str8_concat_capped(dst, node);
CPATH_JOIN_LOOP_END:
++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;
}
b8 absolute = wapp_str8_get(path, 0) == WAPP_PATH_SEP;
Str8 separator = wapp_str8_buf(4);
wapp_str8_push_back(&separator, WAPP_PATH_SEP);
if (path->size == 0) {
output = wapp_str8_alloc_buf(allocator, 16);
if (!output) {
goto RETURN_DIRUP;
}
wapp_str8_push_back(output, absolute ? WAPP_PATH_SEP : '.');
goto RETURN_DIRUP;
va_end(args);
}
void dirup(char *dst, u64 levels, const char *path) {
if (levels < 1) {
output = wapp_str8_alloc_str8(allocator, path);
goto RETURN_DIRUP;
return;
}
Allocator tmp_arena = wapp_mem_arena_allocator_init(MiB(8));
if (wapp_mem_allocator_invalid(&tmp_arena)) {
goto RETURN_DIRUP;
u64 copy_count = 0;
u64 sep_count = 0;
u64 full_length;
u64 length;
length = full_length = strlen(path);
if (length > 1 && path[length - 1] == PATH_SEP) {
--length;
}
Str8List *parts = wapp_str8_split(&tmp_arena, path, &separator);
if (!parts) {
goto RETURN_DIRUP;
for (i64 i = length - 1; i >= 0; --i) {
if (path[i] == PATH_SEP) {
++sep_count;
copy_count = i + 1;
if (sep_count == levels) {
break;
}
}
}
if (levels >= parts->node_count) {
output = wapp_str8_alloc_buf(allocator, 16);
if (!output) {
goto LIST_CLEANUP_DIRUP;
char tmp[256];
snprintf(tmp, 2, "%c", PATH_SEP);
// NOTE (Abdelrahman): Conditions stored in variables to silence MSVC warning C5045
bool insufficient_levels = sep_count < levels;
bool path_to_copy_is_separator = strncmp(path, tmp, copy_count) != 0;
if (insufficient_levels && path_to_copy_is_separator) {
copy_count = 0;
}
wapp_str8_push_back(output, absolute ? WAPP_PATH_SEP : '.');
if (dst == path) {
memset(&dst[copy_count], 0, full_length - copy_count);
} else {
for (u64 i = 0; i < levels; ++i) {
wapp_dbl_list_pop_back(Str8, parts);
u64 dst_length = strlen(dst);
memset(dst, 0, dst_length);
strncpy(dst, path, copy_count);
}
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, WAPP_PATH_SEP);
}
Str8 *joined = wapp_str8_join(&tmp_arena, parts, &separator);
if (joined) {
wapp_str8_concat_capped(output, joined);
}
u64 final_length = strlen(dst);
if (final_length > 1) {
dst[final_length - 1] = '\0';
} else if (final_length == 0) {
dst[0] = '.';
}
}
LIST_CLEANUP_DIRUP:
wapp_mem_arena_allocator_destroy(&tmp_arena);
void join_root_and_leaf(const char *root, const char *leaf, char *dst) {
u64 root_length = strlen(root);
u64 leaf_length = strlen(leaf);
RETURN_DIRUP:
return output;
memcpy(dst, root, root_length);
if (leaf_length == 0) {
return;
}
u64 copy_start = root_length;
if (root_length > 0 && root[root_length - 1] != PATH_SEP && leaf[0] != PATH_SEP) {
dst[root_length] = PATH_SEP;
++copy_start;
}
memcpy(&(dst[copy_start]), leaf, leaf_length);
}

View File

@@ -1,45 +1,32 @@
// vim:fileencoding=utf-8:foldmethod=marker
#ifndef CPATH_H
#define CPATH_H
#include "../../common/aliases/aliases.h"
#include "../../common/platform/platform.h"
#include "../../base/mem/allocator/mem_allocator.h"
#include "../../base/strings/str8/str8.h"
#include "aliases.h"
#include "platform.h"
#ifdef WAPP_PLATFORM_CPP
#ifdef __cplusplus
BEGIN_C_LINKAGE
#endif // !WAPP_PLATFORM_CPP
#endif // __cplusplus
#ifdef WAPP_PLATFORM_POSIX
#include <limits.h>
#define WAPP_PATH_SEP '/'
#define WAPP_PATH_MAX PATH_MAX
#define PATH_SEP '/'
#elif defined(WAPP_PLATFORM_WINDOWS)
#define WIN32_LEAN_AND_MEAN
#include <Windows.h>
#define WAPP_PATH_SEP '\\'
#define WAPP_PATH_MAX MAX_PATH
#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)
#define NUMPARTS(...) (sizeof((const char *[]){"", __VA_ARGS__}) / sizeof(const char *) - 1)
enum {
CPATH_JOIN_SUCCESS = 0,
CPATH_JOIN_INVALID_ARGS,
CPATH_JOIN_EMPTY_PARTS,
CPATH_JOIN_INSUFFICIENT_DST_CAPACITY,
};
#define wapp_cpath_join_path(DST, ...) join_path(DST, NUMPARTS(__VA_ARGS__), __VA_ARGS__)
#define wapp_cpath_dirname(DST, PATH) dirup(DST, 1, PATH)
#define wapp_cpath_dirup(DST, COUNT, PATH) dirup(DST, COUNT, PATH)
u32 wapp_cpath_join_path(Str8 *dst, const Str8List *parts);
Str8 *dirup(const Allocator *allocator, Str8RO *path, u64 levels);
void join_path(char *dst, u64 count, ...);
void dirup(char *dst, u64 levels, const char *path);
#ifdef WAPP_PLATFORM_CPP
#ifdef __cplusplus
END_C_LINKAGE
#endif // !WAPP_PLATFORM_CPP
#endif // __cplusplus
#endif // !CPATH_H

View File

@@ -1,129 +0,0 @@
// vim:fileencoding=utf-8:foldmethod=marker
#include "file.h"
#include "../cpath/cpath.h"
#include "../../common/assert/assert.h"
#include "../../common/aliases/aliases.h"
#include "../../base/array/array.h"
#include "../../base/strings/str8/str8.h"
WFile *wapp_file_open(const Allocator *allocator, Str8RO *filepath, FileAccessMode mode) {
wapp_debug_assert(allocator != NULL && filepath != NULL, "`allocator` and `filepath` should not be NULL");
wapp_debug_assert(filepath->size < WAPP_PATH_MAX, "`filepath` exceeds max path limit.");
return _file_open(allocator, filepath, mode);
}
i64 wapp_file_get_current_position(WFile *file) {
wapp_debug_assert(file != NULL, "`file` should not be NULL.");
return _file_seek(file, 0, WAPP_SEEK_CURRENT);
}
i64 wapp_file_seek(WFile *file, i64 offset, FileSeekOrigin origin) {
wapp_debug_assert(file != NULL, "`file` should not be NULL.");
return _file_seek(file, offset, origin);
}
i64 wapp_file_get_length(WFile *file) {
wapp_debug_assert(file != NULL, "`file` should not be NULL.");
i64 current = wapp_file_get_current_position(file);
_file_seek(file, 0, WAPP_SEEK_END);
i64 output = wapp_file_get_current_position(file);
// Restore position
_file_seek(file, current, WAPP_SEEK_START);
return output;
}
u64 wapp_file_read(void *dst_buf, WFile *file, u64 byte_count) {
wapp_debug_assert(dst_buf != NULL && file != NULL,
"`dst_buf` and `file` should not be NULL.");
i64 file_length = wapp_file_get_length(file);
if (file_length < 0) {
return 0;
}
return _file_read(dst_buf, byte_count, file, file_length);
}
i64 wapp_file_write(const void *src_buf, WFile *file, u64 byte_count) {
wapp_debug_assert(src_buf != NULL && file != NULL,
"`src_buf` and `file` should not be NULL.");
return _file_write(src_buf, file, byte_count);
}
u64 wapp_file_read_array(GenericArray dst_buf, WFile *file, u64 item_count) {
wapp_debug_assert(dst_buf != NULL && file != NULL,
"`dst_buf` and `file` should not be NULL.");
i64 _file_length = wapp_file_get_length(file);
if (_file_length < 0) {
return 0;
}
u64 file_length = (u64)_file_length;
u64 item_size = wapp_array_item_size(dst_buf);
u64 dst_byte_capacity = wapp_array_capacity(dst_buf) * item_size;
u64 req_byte_count = item_count * item_size;
u64 copy_byte_count = 0;
if (req_byte_count <= file_length && req_byte_count <= dst_byte_capacity) {
copy_byte_count = req_byte_count;
} else {
copy_byte_count = file_length <= dst_byte_capacity ? file_length : dst_byte_capacity;
}
u64 byte_count = _file_read(dst_buf, copy_byte_count, file, file_length);
if (byte_count == 0) {
return 0;
}
wapp_array_set_count(dst_buf, byte_count / item_size);
return wapp_array_count(dst_buf);
}
i64 wapp_file_write_array(const GenericArray src_buf, WFile *file, u64 item_count) {
wapp_debug_assert(src_buf != NULL && file != NULL,
"`src_buf` and `file` should not be NULL.");
u64 item_size = wapp_array_item_size(src_buf);
u64 src_byte_count = wapp_array_count(src_buf) * item_size;
u64 req_byte_count = item_count * item_size;
u64 to_copy = req_byte_count <= src_byte_count ? req_byte_count : src_byte_count;
i64 bytes_written = _file_write(src_buf, file, to_copy);
if (bytes_written < 0) {
return 0;
}
return (u64)bytes_written / item_size;
}
i32 wapp_file_flush(WFile *file) {
wapp_debug_assert(file != NULL, "`file` should not be NULL.");
return _file_flush(file);
}
i32 wapp_file_close(WFile *file) {
wapp_debug_assert(file != NULL, "`file` should not be NULL.");
return _file_close(file);
}
i32 wapp_file_rename(Str8RO *old_filepath, Str8RO *new_filepath) {
wapp_debug_assert(old_filepath != NULL && new_filepath != NULL,
"`old_filepath` and `new_filepath` should not be NULL");
wapp_debug_assert(old_filepath->size < WAPP_PATH_MAX, "`old_filepath` exceeds max path limit.");
wapp_debug_assert(new_filepath->size < WAPP_PATH_MAX, "`new_filepath` exceeds max path limit.");
return _file_rename(old_filepath, new_filepath);
}
i32 wapp_file_remove(Str8RO *filepath) {
wapp_debug_assert(filepath != NULL, "`filepath` should not be NULL");
wapp_debug_assert(filepath->size < WAPP_PATH_MAX, "`filepath` exceeds max path limit.");
return _file_remove(filepath);
}

View File

@@ -1,63 +0,0 @@
// vim:fileencoding=utf-8:foldmethod=marker
#ifndef FILE_H
#define FILE_H
#include "../../base/mem/allocator/mem_allocator.h"
#include "../../common/aliases/aliases.h"
#include "../../base/strings/str8/str8.h"
#ifdef WAPP_PLATFORM_CPP
BEGIN_C_LINKAGE
#endif // !WAPP_PLATFORM_CPP
typedef struct WFile WFile;
typedef enum {
WAPP_ACCESS_READ, // Equivalent to r
WAPP_ACCESS_WRITE, // Equivalent to w
WAPP_ACCESS_APPEND, // Equivalent to a
WAPP_ACCESS_READ_EX, // Equivalent to r+
WAPP_ACCESS_WRITE_EX, // Equivalent to w+
WAPP_ACCESS_APPEND_EX, // Equivalent to a+
WAPP_ACCESS_WRITE_FAIL_ON_EXIST, // Equivalent to wx
WAPP_ACCESS_WRITE_FAIL_ON_EXIST_EX, // Equivalent to wx+
FILE_ACCESS_MODE_COUNT,
} FileAccessMode;
typedef enum {
WAPP_SEEK_START,
WAPP_SEEK_CURRENT,
WAPP_SEEK_END,
FILE_SEEK_ORIGIN_COUNT,
} FileSeekOrigin;
WFile *wapp_file_open(const Allocator *allocator, Str8RO *filepath, FileAccessMode mode);
i64 wapp_file_get_current_position(WFile *file);
i64 wapp_file_seek(WFile *file, i64 offset, FileSeekOrigin origin);
i64 wapp_file_get_length(WFile *file);
u64 wapp_file_read(void *dst_buf, WFile *file, u64 byte_count);
i64 wapp_file_write(const void *src_buf, WFile *file, u64 byte_count);
u64 wapp_file_read_array(GenericArray dst_buf, WFile *file, u64 item_count);
i64 wapp_file_write_array(const GenericArray src_buf, WFile *file, u64 item_count);
i32 wapp_file_flush(WFile *file);
i32 wapp_file_close(WFile *file);
i32 wapp_file_rename(Str8RO *old_filepath, Str8RO *new_filepath);
i32 wapp_file_remove(Str8RO *filepath);
extern WFile *_file_open(const Allocator *allocator, Str8RO *filepath, FileAccessMode mode);
extern i64 _file_seek(WFile *file, i64 offset, FileSeekOrigin origin);
extern u64 _file_read(void *dst_buf, u64 byte_count, WFile *file, u64 file_length);
extern i64 _file_write(const void *src_buf, WFile *file, u64 byte_count);
extern i32 _file_flush(WFile *file);
extern i32 _file_close(WFile *file);
extern i32 _file_rename(Str8RO *old_filepath, Str8RO *new_filepath);
extern i32 _file_remove(Str8RO *filepath);
#ifdef WAPP_PLATFORM_CPP
END_C_LINKAGE
#endif // !WAPP_PLATFORM_CPP
#endif // !FILE_H

View File

@@ -1,118 +0,0 @@
// vim:fileencoding=utf-8:foldmethod=marker
#include "file_posix.h"
#include "../../../common/platform/platform.h"
#ifdef WAPP_PLATFORM_POSIX
#include "../file.h"
#include "../../cpath/cpath.h"
#include "../../../common/aliases/aliases.h"
#include "../../../base/array/array.h"
#include "../../../base/strings/str8/str8.h"
#ifdef WAPP_PLATFORM_APPLE
#define _FILE_OFFSET_BITS 64
#define lseek64 lseek
#endif // !WAPP_PLATFORM_APPLE
#include <fcntl.h>
#include <unistd.h>
#include <sys/types.h>
wapp_intern i32 file_flags[FILE_ACCESS_MODE_COUNT] = {
[WAPP_ACCESS_READ] = O_RDONLY,
[WAPP_ACCESS_WRITE] = O_WRONLY | O_CREAT,
[WAPP_ACCESS_APPEND] = O_WRONLY | O_APPEND | O_CREAT,
[WAPP_ACCESS_READ_EX] = O_RDWR,
[WAPP_ACCESS_WRITE_EX] = O_RDWR | O_CREAT,
[WAPP_ACCESS_APPEND_EX] = O_RDWR | O_APPEND | O_CREAT,
[WAPP_ACCESS_WRITE_FAIL_ON_EXIST] = O_WRONLY | O_CREAT | O_EXCL,
[WAPP_ACCESS_WRITE_FAIL_ON_EXIST_EX] = O_RDWR | O_CREAT | O_EXCL,
};
wapp_intern mode_t file_modes[FILE_ACCESS_MODE_COUNT] = {
[WAPP_ACCESS_READ] = 0,
[WAPP_ACCESS_WRITE] = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP,
[WAPP_ACCESS_APPEND] = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP,
[WAPP_ACCESS_READ_EX] = 0,
[WAPP_ACCESS_WRITE_EX] = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP,
[WAPP_ACCESS_APPEND_EX] = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP,
[WAPP_ACCESS_WRITE_FAIL_ON_EXIST] = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP,
[WAPP_ACCESS_WRITE_FAIL_ON_EXIST_EX] = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP,
};
wapp_intern i32 file_seek_origins[FILE_SEEK_ORIGIN_COUNT] = {
[WAPP_SEEK_START] = SEEK_SET,
[WAPP_SEEK_CURRENT] = SEEK_CUR,
[WAPP_SEEK_END] = SEEK_END,
};
WFile *_file_open(const Allocator *allocator, Str8RO *filepath, FileAccessMode mode) {
wapp_persist c8 tmp[WAPP_PATH_MAX] = {0};
memset(tmp, 0, WAPP_PATH_MAX);
memcpy(tmp, filepath->buf, filepath->size);
i32 fd = open((const char *)tmp, file_flags[mode], file_modes[mode]);
if (fd < 0) {
return NULL;
}
WFile *output = wapp_mem_allocator_alloc(allocator, sizeof(WFile));
if (output) {
output->fd = fd;
}
return output;
}
i64 _file_seek(WFile *file, i64 offset, FileSeekOrigin origin) {
return lseek64(file->fd, offset, file_seek_origins[origin]);
}
u64 _file_read(void *dst_buf, u64 byte_count, WFile *file, u64 file_length) {
u64 copy_byte_count = file_length <= byte_count ? file_length : byte_count;
i64 count = read(file->fd, dst_buf, copy_byte_count);
if (count < 0) { return 0; }
return count;
}
i64 _file_write(const void *src_buf, WFile *file, u64 byte_count) {
return write(file->fd, src_buf, byte_count);
}
i32 _file_flush(WFile *file) {
return fsync(file->fd);
}
i32 _file_close(WFile *file) {
return close(file->fd);
}
i32 _file_rename(Str8RO *old_filepath, Str8RO *new_filepath) {
wapp_persist c8 old_tmp[WAPP_PATH_MAX] = {0};
wapp_persist c8 new_tmp[WAPP_PATH_MAX] = {0};
memset(old_tmp, 0, WAPP_PATH_MAX);
memcpy(old_tmp, old_filepath->buf, old_filepath->size);
memset(new_tmp, 0, WAPP_PATH_MAX);
memcpy(new_tmp, new_filepath->buf, new_filepath->size);
i32 link_result = link((const char *)old_tmp, (const char *)new_tmp);
if (link_result == 0) {
_file_remove(old_filepath);
}
return link_result;
}
i32 _file_remove(Str8RO *filepath) {
wapp_persist c8 tmp[WAPP_PATH_MAX] = {0};
memset(tmp, 0, WAPP_PATH_MAX);
memcpy(tmp, filepath->buf, filepath->size);
return unlink((const char *)tmp);
}
#endif // !WAPP_PLATFORM_POSIX

View File

@@ -1,27 +0,0 @@
// vim:fileencoding=utf-8:foldmethod=marker
#ifndef FILE_POSIX_H
#define FILE_POSIX_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_POSIX
#define END_OF_LINE "\n"
struct WFile {
i32 fd;
};
#endif // !WAPP_PLATFORM_POSIX
#ifdef WAPP_PLATFORM_CPP
END_C_LINKAGE
#endif // !WAPP_PLATFORM_CPP
#endif // !FILE_POSIX_H

View File

@@ -1,159 +0,0 @@
// vim:fileencoding=utf-8:foldmethod=marker
#include "file_win.h"
#include "../../../common/platform/platform.h"
#ifdef WAPP_PLATFORM_WINDOWS
#include "../file.h"
#include "../../cpath/cpath.h"
#include "../../../common/aliases/aliases.h"
#include "../../../base/array/array.h"
#include "../../../base/strings/str8/str8.h"
#define WIN32_LEAN_AND_MEAN
#include <Windows.h>
#include <fileapi.h>
#include <intsafe.h>
wapp_intern DWORD file_accesses[FILE_ACCESS_MODE_COUNT] = {
[WAPP_ACCESS_READ] = FILE_READ_DATA,
[WAPP_ACCESS_WRITE] = FILE_WRITE_DATA,
[WAPP_ACCESS_APPEND] = FILE_APPEND_DATA,
[WAPP_ACCESS_READ_EX] = FILE_READ_DATA | FILE_WRITE_DATA,
[WAPP_ACCESS_WRITE_EX] = FILE_READ_DATA | FILE_WRITE_DATA,
[WAPP_ACCESS_APPEND_EX] = FILE_READ_DATA | FILE_APPEND_DATA,
[WAPP_ACCESS_WRITE_FAIL_ON_EXIST] = FILE_WRITE_DATA,
[WAPP_ACCESS_WRITE_FAIL_ON_EXIST_EX] = FILE_READ_DATA | FILE_WRITE_DATA,
};
wapp_intern DWORD creation_dispositions[FILE_ACCESS_MODE_COUNT] = {
[WAPP_ACCESS_READ] = OPEN_EXISTING,
[WAPP_ACCESS_WRITE] = CREATE_ALWAYS,
[WAPP_ACCESS_APPEND] = OPEN_ALWAYS,
[WAPP_ACCESS_READ_EX] = OPEN_EXISTING,
[WAPP_ACCESS_WRITE_EX] = CREATE_ALWAYS,
[WAPP_ACCESS_APPEND_EX] = OPEN_ALWAYS,
[WAPP_ACCESS_WRITE_FAIL_ON_EXIST] = CREATE_NEW,
[WAPP_ACCESS_WRITE_FAIL_ON_EXIST_EX] = CREATE_NEW,
};
wapp_intern DWORD sharing_modes[FILE_ACCESS_MODE_COUNT] = {
[WAPP_ACCESS_READ] = FILE_SHARE_READ | FILE_SHARE_WRITE,
[WAPP_ACCESS_WRITE] = FILE_SHARE_READ,
[WAPP_ACCESS_APPEND] = FILE_SHARE_READ,
[WAPP_ACCESS_READ_EX] = FILE_SHARE_READ | FILE_SHARE_WRITE,
[WAPP_ACCESS_WRITE_EX] = FILE_SHARE_READ,
[WAPP_ACCESS_APPEND_EX] = FILE_SHARE_READ,
[WAPP_ACCESS_WRITE_FAIL_ON_EXIST] = FILE_SHARE_READ,
[WAPP_ACCESS_WRITE_FAIL_ON_EXIST_EX] = FILE_SHARE_READ,
};
wapp_intern DWORD file_seek_origins[FILE_SEEK_ORIGIN_COUNT] = {
[WAPP_SEEK_START] = FILE_BEGIN,
[WAPP_SEEK_CURRENT] = FILE_CURRENT,
[WAPP_SEEK_END] = FILE_END,
};
WFile *_file_open(const Allocator *allocator, Str8RO *filepath, FileAccessMode mode) {
wapp_persist c8 tmp[WAPP_PATH_MAX] = {0};
memset(tmp, 0, WAPP_PATH_MAX);
memcpy(tmp, filepath->buf, filepath->size);
HANDLE fh = CreateFileA((LPCSTR)tmp,
file_accesses[mode],
sharing_modes[mode],
NULL,
creation_dispositions[mode],
FILE_ATTRIBUTE_NORMAL,
NULL);
if (fh == INVALID_HANDLE_VALUE) {
return NULL;
}
WFile *output = wapp_mem_allocator_alloc(allocator, sizeof(WFile));
if (output) {
output->fh = fh;
}
return output;
}
i64 _file_seek(WFile *file, i64 offset, FileSeekOrigin origin) {
LARGE_INTEGER distance = {0};
LARGE_INTEGER output = {0};
distance.QuadPart = offset;
if (!SetFilePointerEx(file->fh, distance, &output, file_seek_origins[origin])) {
return -1;
}
return output.QuadPart;
}
u64 _file_read(void* dst_buf, u64 byte_count, WFile* file, u64 file_length) {
u64 copy_byte_count = file_length <= byte_count ? file_length : byte_count;
wapp_debug_assert(copy_byte_count <= DWORD_MAX, "Attempting to read large number of bytes at once");
DWORD read_count = 0;
if (!ReadFile(file->fh, dst_buf, (DWORD)copy_byte_count, &read_count, NULL)) {
return 0;
}
return (u64)read_count;
}
i64 _file_write(const void *src_buf, WFile *file, u64 byte_count) {
wapp_debug_assert(byte_count <= DWORD_MAX, "Attempting to write large number of bytes at once");
DWORD write_count = 0;
if (!WriteFile(file->fh, src_buf, (DWORD)byte_count, &write_count, NULL)) {
return 0;
}
return (i64)write_count;
}
i32 _file_flush(WFile *file) {
if (!FlushFileBuffers(file->fh)) {
return -1;
}
return 0;
}
i32 _file_close(WFile *file) {
if (!CloseHandle(file->fh)) {
return -1;
}
return 0;
}
i32 _file_rename(Str8RO *old_filepath, Str8RO *new_filepath) {
wapp_persist c8 old_tmp[WAPP_PATH_MAX] = {0};
wapp_persist c8 new_tmp[WAPP_PATH_MAX] = {0};
memset(old_tmp, 0, WAPP_PATH_MAX);
memcpy(old_tmp, old_filepath->buf, old_filepath->size);
memset(new_tmp, 0, WAPP_PATH_MAX);
memcpy(new_tmp, new_filepath->buf, new_filepath->size);
if (!MoveFile((LPCSTR)old_tmp, (LPCSTR)new_tmp)) {
return -1;
}
return 0;
}
i32 _file_remove(Str8RO *filepath) {
wapp_persist c8 tmp[WAPP_PATH_MAX] = {0};
memset(tmp, 0, WAPP_PATH_MAX);
memcpy(tmp, filepath->buf, filepath->size);
if (!DeleteFile((LPCSTR)tmp)) {
return -1;
}
return 0;
}
#endif // !WAPP_PLATFORM_WINDOWS

View File

@@ -1,31 +0,0 @@
// vim:fileencoding=utf-8:foldmethod=marker
#ifndef FILE_WIN_H
#define FILE_WIN_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_WINDOWS
#define END_OF_LINE "\r\n"
#define WIN32_LEAN_AND_MEAN
#include <Windows.h>
#include <fileapi.h>
struct WFile {
HANDLE fh;
};
#endif // !WAPP_PLATFORM_WINDOWS
#ifdef WAPP_PLATFORM_CPP
END_C_LINKAGE
#endif // !WAPP_PLATFORM_CPP
#endif // !FILE_WIN_H

View File

@@ -1,30 +0,0 @@
// 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 <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_os_mem_alloc(void *addr, u64 size, MemAccess access, MemAllocFlags flags, MemInitType type) {
void *output = os_mem_allocate(addr, size, access, flags, type);
if (type == WAPP_MEM_INIT_INITIALISED) {
memset(output, 0, size);
}
return output;
}
void wapp_os_mem_free(void *ptr, u64 size) {
os_mem_free(ptr, size);
}

View File

@@ -1,33 +0,0 @@
// 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_os_mem_alloc(void *addr, u64 size, MemAccess access, MemAllocFlags flags, MemInitType type);
void wapp_os_mem_free(void *ptr, u64 size);
wapp_extern void *os_mem_allocate(void *addr, u64 size, MemAccess access, MemAllocFlags flags, MemInitType type);
wapp_extern void os_mem_free(void *ptr, u64 size);
#ifdef WAPP_PLATFORM_CPP
END_C_LINKAGE
#endif // !WAPP_PLATFORM_CPP
#endif // !MEM_OS_H

View File

@@ -1,30 +0,0 @@
// 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

53
src/os/mem/mem_utils.c Normal file
View File

@@ -0,0 +1,53 @@
#include "mem_utils.h"
#include "mem_utils_ops.h"
#include "aliases.h"
#include "platform.h"
#include <assert.h>
#include <stdbool.h>
#include <stdlib.h>
#include <string.h>
#if defined(WAPP_PLATFORM_WINDOWS)
#include "mem_utils_win.h"
#elif defined(WAPP_PLATFORM_POSIX)
#include "mem_utils_posix.h"
#else
#error "Unrecognised platform"
#endif
internal bool is_power_of_two(u64 num) { return (num & (num - 1)) == 0; }
void *wapp_mem_util_align_forward(void *ptr, u64 alignment) {
if (!ptr) {
return NULL;
}
assert(is_power_of_two(alignment));
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;
}
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);
}

32
src/os/mem/mem_utils.h Normal file
View File

@@ -0,0 +1,32 @@
#ifndef MEM_UTILS_H
#define MEM_UTILS_H
#include "aliases.h"
#include "platform.h"
#ifdef __cplusplus
BEGIN_C_LINKAGE
#endif // __cplusplus
#include "mem_utils_ops.h"
#if defined(WAPP_PLATFORM_WINDOWS)
#include "mem_utils_win.h"
#elif defined(WAPP_PLATFORM_POSIX)
#include "mem_utils_posix.h"
#else
#error "Unrecognised platform"
#endif
void *wapp_mem_util_align_forward(void *ptr, u64 alignment);
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 __cplusplus
END_C_LINKAGE
#endif // __cplusplus
#endif // !MEM_UTILS_H

View File

@@ -0,0 +1,26 @@
#ifndef MEM_UTILS_OPS_H
#define MEM_UTILS_OPS_H
#ifdef __cplusplus
BEGIN_C_LINKAGE
#endif // __cplusplus
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 __cplusplus
END_C_LINKAGE
#endif // __cplusplus
#endif // !MEM_UTILS_OPS_H

View File

@@ -1,36 +0,0 @@
// 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>
wapp_intern 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 *os_mem_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 os_mem_free(void *ptr, u64 size) {
munmap(ptr, size);
}
#endif // !WAPP_PLATFORM_POSIX

View File

@@ -1,35 +0,0 @@
// 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

View File

@@ -0,0 +1,33 @@
#include "aliases.h"
#include "platform.h"
#ifdef WAPP_PLATFORM_POSIX
#include "mem_utils_ops.h"
#include "mem_utils_posix.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) {
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

View File

@@ -0,0 +1,33 @@
#ifndef MEM_UTILS_POSIX_H
#define MEM_UTILS_POSIX_H
#include "platform.h"
#ifdef __cplusplus
BEGIN_C_LINKAGE
#endif // !__cplusplus
#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 __cplusplus
END_C_LINKAGE
#endif // !__cplusplus
#endif // !MEM_UTILS_POSIX_H

View File

@@ -1,37 +0,0 @@
// 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>
wapp_intern 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 *os_mem_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 os_mem_free(void *ptr, u64 size) {
VirtualFree(ptr, size, MEM_RELEASE);
}
#endif // !WAPP_PLATFORM_WINDOWS

View File

@@ -1,29 +0,0 @@
// 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

View File

@@ -0,0 +1,35 @@
#include "aliases.h"
#include "platform.h"
#ifdef WAPP_PLATFORM_WINDOWS
#include "mem_utils_ops.h"
#include "mem_utils_win.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

View File

@@ -0,0 +1,27 @@
#ifndef MEM_UTILS_WIN_H
#define MEM_UTILS_WIN_H
#include "platform.h"
#ifdef __cplusplus
BEGIN_C_LINKAGE
#endif // !__cplusplus
#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 __cplusplus
END_C_LINKAGE
#endif // !__cplusplus
#endif // !MEM_UTILS_WIN_H

View File

@@ -1,15 +1,8 @@
// vim:fileencoding=utf-8:foldmethod=marker
#include "commander.h"
#include "commander_output.h"
#include "../utils/shell_utils.h"
#include "../../allocators/arena/mem_arena_allocator.h"
#include "../../../common/aliases/aliases.h"
#include "../../../common/misc/misc_utils.h"
#include "../../../base/dbl_list/dbl_list.h"
#include "../../../base/mem/allocator/mem_allocator.h"
#include "../../../base/strings/str8/str8.h"
#include "aliases.h"
#include "shell_utils.h"
#include <stdarg.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -17,44 +10,62 @@
#define CMD_BUF_LEN 8192
#define OUT_BUF_LEN 4096
wapp_intern CMDResult execute_command(Str8RO *cmd, CMDOutHandling out_handling, Str8 *out_buf);
wapp_intern CMDError get_command_output(FILE *fp, CMDOutHandling out_handling, Str8 *out_buf);
internal inline CMDError build_command_from_args(char *cmd, u64 buf_len, va_list args);
internal inline CMDResult execute_command(const char *cmd, CMDOutHandling out_handling, char *out_buf,
u64 buf_size);
internal inline CMDError get_command_output(FILE *fp, CMDOutHandling out_handling, char *out_buf,
u64 buf_size);
CMDResult wapp_shell_commander_execute(CMDOutHandling out_handling, Str8 *out_buf, const Str8List *cmd) {
if (!cmd) {
return CMD_NO_EXIT(SHELL_ERR_INVALID_ARGS);
CMDResult run_command(CMDOutHandling out_handling, char *out_buf, u64 buf_size, ...) {
va_list args;
va_start(args, buf_size);
char cmd[CMD_BUF_LEN] = {0};
CMDError err = build_command_from_args(cmd, CMD_BUF_LEN, args);
if (err > SHELL_ERR_NO_ERROR) {
va_end(args);
return CMD_NO_EXIT(err);
}
Allocator arena = wapp_mem_arena_allocator_init(KiB(500));
va_end(args);
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);
return execute_command(cmd, out_handling, out_buf, buf_size);
}
// Redirect output
cmd_str = wapp_str8_alloc_concat(&arena, cmd_str, &wapp_str8_lit_ro(" 2>&1"));
internal inline CMDError build_command_from_args(char *cmd, u64 buf_len,
va_list args) {
u64 size = 0;
u64 arg_len = 0;
CMDResult output = execute_command(cmd_str, out_handling, out_buf);
wapp_mem_arena_allocator_destroy(&arena);
return output;
const char *arg = va_arg(args, const char *);
while (arg) {
arg_len = strlen(arg);
if (arg_len >= buf_len - size) {
return SHELL_ERR_CMD_BUF_FULL;
}
wapp_intern 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);
strcat(cmd, arg);
cmd[size + arg_len] = ' ';
FILE *fp = wapp_shell_utils_popen(cmd_buf, "r");
size += arg_len + 1;
arg = va_arg(args, const char *);
}
return SHELL_ERR_NO_ERROR;
}
internal inline CMDResult execute_command(const char *cmd,
CMDOutHandling out_handling,
char *out_buf, u64 buf_size) {
FILE *fp = wapp_shell_utils_popen(cmd, "r");
if (!fp) {
return CMD_NO_EXIT(SHELL_ERR_PROC_START_FAIL);
}
CMDResult output;
CMDError err = get_command_output(fp, out_handling, out_buf);
CMDError err = get_command_output(fp, out_handling, out_buf, buf_size);
if (err > SHELL_ERR_NO_ERROR) {
output = CMD_NO_EXIT(err);
goto EXECUTE_COMMAND_CLOSE;
@@ -83,18 +94,24 @@ EXECUTE_COMMAND_CLOSE:
return output;
}
wapp_intern CMDError get_command_output(FILE *fp, CMDOutHandling out_handling, Str8 *out_buf) {
Str8 out = wapp_str8_buf(OUT_BUF_LEN);
internal inline CMDError get_command_output(FILE *fp,
CMDOutHandling out_handling,
char *out_buf, u64 buf_size) {
char out[OUT_BUF_LEN] = {0};
u64 max_out_length = OUT_BUF_LEN - 1;
out.size = fread((void *)out.buf, sizeof(u8), out.capacity, fp);
u64 buf_filled = 0;
while (fgets(out, (i32)max_out_length, fp)) {
if (out_handling == SHELL_OUTPUT_CAPTURE && out_buf != NULL) {
if (out.size >= out_buf->capacity) {
buf_filled += strlen(out);
if (buf_filled >= buf_size) {
return SHELL_ERR_OUT_BUF_FULL;
}
wapp_str8_concat_capped(out_buf, &out);
strcat(out_buf, out);
} else if (out_handling == SHELL_OUTPUT_PRINT) {
printf(WAPP_STR8_SPEC, wapp_str8_varg(out));
printf("%s", out);
}
}
return SHELL_ERR_NO_ERROR;

View File

@@ -1,27 +1,26 @@
// vim:fileencoding=utf-8:foldmethod=marker
#ifndef COMMANDER_H
#define COMMANDER_H
#include "aliases.h"
#include "commander_output.h"
#include "../../../common/aliases/aliases.h"
#include "../../../common/platform/platform.h"
#include "../../../base/strings/str8/str8.h"
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#ifdef WAPP_PLATFORM_CPP
#ifdef __cplusplus
BEGIN_C_LINKAGE
#endif // !WAPP_PLATFORM_CPP
#endif // __cplusplus
#define CMD_NO_EXIT(ERR) ((CMDResult){.exited = false, .exit_code = EXIT_FAILURE, .error = ERR})
#define wapp_shell_commander_execute(HANDLE_OUTPUT, OUT_BUF, BUF_SIZE, ...) \
run_command(HANDLE_OUTPUT, OUT_BUF, BUF_SIZE, __VA_ARGS__, "2>&1", NULL)
CMDResult wapp_shell_commander_execute(CMDOutHandling out_handling, Str8 *out_buf, const Str8List *cmd);
CMDResult run_command(CMDOutHandling out_handling, char *out_buf, u64 buf_size, ...);
wapp_extern CMDError get_output_status(FILE *fp, i32 *status_out);
external CMDError get_output_status(FILE *fp, i32 *status_out);
#ifdef WAPP_PLATFORM_CPP
#ifdef __cplusplus
END_C_LINKAGE
#endif // !WAPP_PLATFORM_CPP
#endif // __cplusplus
#endif // !COMMANDER_H

View File

@@ -1,15 +1,13 @@
// 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 "../../../common/misc/misc_utils.h"
#include "aliases.h"
#include "platform.h"
#include <stdbool.h>
#ifdef WAPP_PLATFORM_CPP
#ifdef __cplusplus
BEGIN_C_LINKAGE
#endif // !WAPP_PLATFORM_CPP
#endif // __cplusplus
typedef enum {
SHELL_OUTPUT_DISCARD,
@@ -19,24 +17,26 @@ typedef enum {
typedef enum {
SHELL_ERR_NO_ERROR,
SHELL_ERR_INVALID_ARGS,
SHELL_ERR_ALLOCATION_FAIL,
SHELL_ERR_CMD_BUF_FULL,
SHELL_ERR_PROC_START_FAIL,
SHELL_ERR_OUT_BUF_FULL,
SHELL_ERR_PROC_EXIT_FAIL,
} CMDError;
typedef struct CMDResult CMDResult;
struct CMDResult {
typedef struct commander_result CMDResult;
struct commander_result {
i32 exit_code;
CMDError error;
b8 exited;
bool exited;
wapp_misc_utils_reserve_padding(sizeof(b8) + sizeof(i32) + sizeof(CMDError));
#ifdef WAPP_PLATFORM_WINDOWS
#include "misc_utils.h"
wapp_misc_utils_padding_size(sizeof(bool) + sizeof(i32) + sizeof(CMDError));
#endif // !WAPP_PLATFORM_WINDOWS
};
#ifdef WAPP_PLATFORM_CPP
#ifdef __cplusplus
END_C_LINKAGE
#endif // !WAPP_PLATFORM_CPP
#endif // __cplusplus
#endif // !COMMANDER_OUTPUT_H

View File

@@ -1,12 +1,10 @@
// vim:fileencoding=utf-8:foldmethod=marker
#include "../../../../common/aliases/aliases.h"
#include "../../../../common/platform/platform.h"
#include "aliases.h"
#include "platform.h"
#ifdef WAPP_PLATFORM_POSIX
#include "../commander_output.h"
#include "../../utils/shell_utils.h"
#include "commander_output.h"
#include "shell_utils.h"
#include <stdio.h>
#include <stdlib.h>

View File

@@ -1,12 +1,10 @@
// vim:fileencoding=utf-8:foldmethod=marker
#include "../../../../common/aliases/aliases.h"
#include "../../../../common/platform/platform.h"
#include "aliases.h"
#include "platform.h"
#ifdef WAPP_PLATFORM_WINDOWS
#include "../commander_output.h"
#include "../../utils/shell_utils.h"
#include "commander_output.h"
#include "shell_utils.h"
#include <stdio.h>
CMDError get_output_status(FILE *fp, i32 *status_out) {

View File

@@ -1,36 +1,33 @@
// vim:fileencoding=utf-8:foldmethod=marker
#include "../../../../common/aliases/aliases.h"
#include "../../../../common/platform/platform.h"
#include "../../../../base/strings/str8/str8.h"
#include "aliases.h"
#include "platform.h"
#ifdef WAPP_PLATFORM_POSIX
#include "../terminal_colours.h"
#include "terminal_colours.h"
#include <stdio.h>
wapp_intern 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"),
internal const char *colours[COUNT_TERM_COLOUR] = {
[WAPP_TERM_COLOUR_FG_BLACK] = "\033[30m",
[WAPP_TERM_COLOUR_FG_RED] = "\033[31m",
[WAPP_TERM_COLOUR_FG_GREEN] = "\033[32m",
[WAPP_TERM_COLOUR_FG_BLUE] = "\033[34m",
[WAPP_TERM_COLOUR_FG_CYAN] = "\033[36m",
[WAPP_TERM_COLOUR_FG_MAGENTA] = "\033[35m",
[WAPP_TERM_COLOUR_FG_YELLOW] = "\033[33m",
[WAPP_TERM_COLOUR_FG_WHITE] = "\033[37m",
[WAPP_TERM_COLOUR_FG_BR_BLACK] = "\033[90m",
[WAPP_TERM_COLOUR_FG_BR_RED] = "\033[91m",
[WAPP_TERM_COLOUR_FG_BR_GREEN] = "\033[92m",
[WAPP_TERM_COLOUR_FG_BR_BLUE] = "\033[94m",
[WAPP_TERM_COLOUR_FG_BR_CYAN] = "\033[96m",
[WAPP_TERM_COLOUR_FG_BR_MAGENTA] = "\033[95m",
[WAPP_TERM_COLOUR_FG_BR_YELLOW] = "\033[93m",
[WAPP_TERM_COLOUR_FG_BR_WHITE] = "\033[97m",
[WAPP_TERM_COLOUR_CLEAR] = "\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)));
void print_coloured_text(const char *text, TerminalColour colour) {
printf("%s%s", colours[colour], text);
}
#endif // !WAPP_PLATFORM_POSIX

View File

@@ -1,10 +1,7 @@
// vim:fileencoding=utf-8:foldmethod=marker
#include "termcolour.h"
#include "terminal_colours.h"
#include "../../../base/strings/str8/str8.h"
void wapp_shell_termcolour_print_text(Str8RO *text, TerminalColour colour) {
void wapp_shell_termcolour_print_text(const char *text, TerminalColour colour) {
if (colour < WAPP_TERM_COLOUR_FG_BLACK || colour > WAPP_TERM_COLOUR_FG_BR_WHITE) {
return;
}
@@ -13,6 +10,5 @@ void wapp_shell_termcolour_print_text(Str8RO *text, TerminalColour colour) {
}
void wapp_shell_termcolour_clear_colour(void) {
Str8RO empty = wapp_str8_lit_ro("");
print_coloured_text(&empty, WAPP_TERM_COLOUR_CLEAR);
print_coloured_text("", WAPP_TERM_COLOUR_CLEAR);
}

View File

@@ -1,24 +1,20 @@
// vim:fileencoding=utf-8:foldmethod=marker
#ifndef TERM_COLOUR_H
#define TERM_COLOUR_H
#include "aliases.h"
#include "terminal_colours.h"
#include "../../../common/aliases/aliases.h"
#include "../../../common/platform/platform.h"
#include "../../../base/strings/str8/str8.h"
#ifdef WAPP_PLATFORM_CPP
#ifdef __cplusplus
BEGIN_C_LINKAGE
#endif // !WAPP_PLATFORM_CPP
#endif // __cplusplus
void wapp_shell_termcolour_print_text(Str8RO *text, TerminalColour colour);
void wapp_shell_termcolour_print_text(const char *text, TerminalColour colour);
void wapp_shell_termcolour_clear_colour(void);
wapp_extern void print_coloured_text(Str8RO *text, TerminalColour colour);
external void print_coloured_text(const char *text, TerminalColour colour);
#ifdef WAPP_PLATFORM_CPP
#ifdef __cplusplus
END_C_LINKAGE
#endif // !WAPP_PLATFORM_CPP
#endif // __cplusplus
#endif // !TERM_COLOUR_H

View File

@@ -1,14 +1,9 @@
// 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
#ifdef __cplusplus
BEGIN_C_LINKAGE
#endif // !WAPP_PLATFORM_CPP
#endif // __cplusplus
typedef enum {
WAPP_TERM_COLOUR_FG_BLACK,
@@ -32,8 +27,8 @@ typedef enum {
COUNT_TERM_COLOUR,
} TerminalColour;
#ifdef WAPP_PLATFORM_CPP
#ifdef __cplusplus
END_C_LINKAGE
#endif // !WAPP_PLATFORM_CPP
#endif // __cplusplus
#endif // !TERMINAL_COLOURS_H

View File

@@ -1,30 +1,27 @@
// vim:fileencoding=utf-8:foldmethod=marker
#include "../../../../common/aliases/aliases.h"
#include "../../../../common/platform/platform.h"
#include "../../../../base/strings/str8/str8.h"
#include "aliases.h"
#include "platform.h"
#ifdef WAPP_PLATFORM_WINDOWS
#include "../terminal_colours.h"
#include "../../../../common/misc/misc_utils.h"
#include "misc_utils.h"
#include "terminal_colours.h"
#include <stdio.h>
#define WIN32_LEAN_AND_MEAN
#include <Windows.h>
typedef struct TermcolourData TermcolourData;
struct TermcolourData {
typedef struct termcolour_data TermcolourData;
struct termcolour_data {
HANDLE handle;
WORD default_colour;
WORD current_colour;
wapp_misc_utils_reserve_padding(sizeof(HANDLE) + sizeof(WORD) + sizeof(WORD));
wapp_misc_utils_padding_size(sizeof(HANDLE) + sizeof(WORD) + sizeof(WORD));
};
wapp_intern void init_data(TermcolourData *data);
internal void init_data(TermcolourData *data);
wapp_intern WORD colours[COUNT_TERM_COLOUR] = {
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,
@@ -43,8 +40,8 @@ wapp_intern WORD colours[COUNT_TERM_COLOUR] = {
[WAPP_TERM_COLOUR_FG_BR_WHITE] = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY,
};
void print_coloured_text(Str8RO *text, TerminalColour colour) {
wapp_persist TermcolourData data = {0};
void print_coloured_text(const char *text, TerminalColour colour) {
persistent TermcolourData data = {0};
if (data.handle == 0) {
init_data(&data);
}
@@ -56,10 +53,10 @@ void print_coloured_text(Str8RO *text, TerminalColour colour) {
}
SetConsoleTextAttribute(data.handle, data.current_colour);
printf(WAPP_STR8_SPEC, wapp_str8_varg((*text)));
printf("%s", text);
}
wapp_intern void init_data(TermcolourData *data) {
internal void init_data(TermcolourData *data) {
// create handle
data->handle = GetStdHandle(STD_OUTPUT_HANDLE);

View File

@@ -1,16 +1,9 @@
// 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 "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
@@ -19,8 +12,4 @@ BEGIN_C_LINKAGE
#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

View File

@@ -1,24 +0,0 @@
// vim:fileencoding=utf-8:foldmethod=marker
#ifndef WAPP_OS_C
#define WAPP_OS_C
#include "wapp_os.h"
#include "file/file.c"
#include "file/posix/file_posix.c"
#include "file/win/file_win.c"
#include "shell/termcolour/posix/termcolour_posix.c"
#include "shell/termcolour/win/termcolour_win.c"
#include "shell/termcolour/termcolour.c"
#include "shell/commander/posix/commander_posix.c"
#include "shell/commander/win/commander_win.c"
#include "shell/commander/commander.c"
#include "cpath/cpath.c"
#include "allocators/arena/mem_arena.c"
#include "allocators/arena/mem_arena_allocator.c"
#include "mem/posix/mem_os_posix.c"
#include "mem/win/mem_os_win.c"
#include "mem/mem_os.c"
#include "../base/wapp_base.c"
#endif // !WAPP_OS_C

View File

@@ -1,24 +0,0 @@
// vim:fileencoding=utf-8:foldmethod=marker
#ifndef WAPP_CORE_H
#define WAPP_CORE_H
#include "file/file.h"
#include "file/posix/file_posix.h"
#include "file/win/file_win.h"
#include "shell/termcolour/termcolour.h"
#include "shell/termcolour/terminal_colours.h"
#include "shell/commander/commander.h"
#include "shell/commander/commander_output.h"
#include "shell/utils/shell_utils.h"
#include "cpath/cpath.h"
#include "allocators/arena/mem_arena.h"
#include "allocators/arena/mem_arena_allocator.h"
#include "mem/posix/mem_os_posix.h"
#include "mem/win/mem_os_win.h"
#include "mem/mem_os_ops.h"
#include "mem/mem_os.h"
#include "../common/wapp_common.h"
#include "../base/wapp_base.h"
#endif // !WAPP_CORE_H

View File

@@ -1,8 +0,0 @@
// vim:fileencoding=utf-8:foldmethod=marker
#ifndef WAPP_PRNG_C
#define WAPP_PRNG_C
#include "xorshift/xorshift.c"
#endif // !WAPP_PRNG_C

View File

@@ -1,9 +0,0 @@
// 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

View File

@@ -1,135 +0,0 @@
// 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 <stdlib.h>
#include <time.h>
typedef struct SplitMix64State SplitMix64State;
struct SplitMix64State {
u64 seed;
};
wapp_intern u64 rol64(u64 x, u64 bits);
wapp_intern u64 split_mix_64(SplitMix64State *state);
wapp_intern void seed_os_generator(void);
wapp_intern u64 generate_random_number(void);
XOR256State wapp_prng_xorshift_init_state(void) {
wapp_persist b8 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;
}
wapp_intern u64 rol64(u64 x, u64 bits) {
return (x << bits) | (x >> (64 - bits));
}
wapp_intern 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
wapp_intern 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);
}
wapp_intern u64 generate_random_number(void) {
return lrand48();
}
#else
wapp_intern 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);
}
wapp_intern u64 generate_random_number(void) {
i32 n1 = rand();
i32 n2 = rand();
return (((u64)n1) << 32 | (u64)n2);
}
#endif // !WAPP_PLATFORM_POSIX
#else
wapp_intern void seed_os_generator(void) {
time_t result = time(NULL);
wapp_runtime_assert(result != (time_t)(-1), "Invalid seed value");
srand(result);
}
wapp_intern u64 generate_random_number(void) {
i32 n1 = rand();
i32 n2 = rand();
return (((u64)n1) << 32 | (u64)n2);
}
#endif // !WAPP_PLATFORM_C

View File

@@ -1,30 +0,0 @@
// 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 XOR256State XOR256State;
struct XOR256State {
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

52
src/tester/tester.c Normal file
View File

@@ -0,0 +1,52 @@
#include "tester.h"
#include "aliases.h"
#include "termcolour.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;
const char *result_text;
if (result.passed) {
colour = WAPP_TERM_COLOUR_FG_BR_GREEN;
result_text = "PASSED";
} else {
colour = WAPP_TERM_COLOUR_FG_BR_RED;
result_text = "FAILED";
}
printf("[");
wapp_shell_termcolour_print_text(result_text, colour);
wapp_shell_termcolour_clear_colour();
printf("] %s\n", result.name);
if (!result.passed) {
exit(EXIT_FAILURE);
}
}

33
src/tester/tester.h Normal file
View File

@@ -0,0 +1,33 @@
#ifndef TESTER_H
#define TESTER_H
#include "misc_utils.h"
#include "platform.h"
#include <stdbool.h>
#ifdef __cplusplus
BEGIN_C_LINKAGE
#endif // __cplusplus
#define wapp_tester_result(PASSED) ((TestFuncResult){.name = __func__, .passed = PASSED})
#define wapp_tester_run_tests(...) run_tests(__VA_ARGS__, NULL)
typedef struct test_func_result TestFuncResult;
struct test_func_result {
const char *name;
bool passed;
#ifdef WAPP_PLATFORM_WINDOWS
wapp_misc_utils_padding_size(sizeof(const char *) + sizeof(bool));
#endif // WAPP_PLATFORM_WINDOWS
};
typedef TestFuncResult(TestFunc)(void);
void run_tests(TestFunc *func1, ...);
#ifdef __cplusplus
END_C_LINKAGE
#endif // __cplusplus
#endif // !TESTER_H

View File

@@ -1,55 +0,0 @@
// vim:fileencoding=utf-8:foldmethod=marker
#include "tester.h"
#include "../../common/aliases/aliases.h"
#include "../../os/shell/termcolour/termcolour.h"
#include "../../base/strings/str8/str8.h"
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
wapp_intern 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");
}
wapp_intern 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);
}
}

View File

@@ -1,36 +0,0 @@
// vim:fileencoding=utf-8:foldmethod=marker
#ifndef TESTER_H
#define TESTER_H
#include "../../common/misc/misc_utils.h"
#include "../../common/platform/platform.h"
#include "../../base/strings/str8/str8.h"
#ifdef WAPP_PLATFORM_CPP
BEGIN_C_LINKAGE
#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 TestFuncResult TestFuncResult;
struct TestFuncResult {
Str8 name;
b8 passed;
wapp_misc_utils_reserve_padding(sizeof(Str8) + sizeof(b8));
};
typedef TestFuncResult(TestFunc)(void);
void run_tests(TestFunc *func1, ...);
#ifdef WAPP_PLATFORM_CPP
END_C_LINKAGE
#endif // !WAPP_PLATFORM_CPP
#endif // !TESTER_H

View File

@@ -1,10 +0,0 @@
// vim:fileencoding=utf-8:foldmethod=marker
#ifndef WAPP_TESTING_C
#define WAPP_TESTING_C
#include "wapp_testing.h"
#include "tester/tester.c"
#include "../os/wapp_os.c"
#endif // !WAPP_TESTING_C

View File

@@ -1,10 +0,0 @@
// vim:fileencoding=utf-8:foldmethod=marker
#ifndef WAPP_TESTING_H
#define WAPP_TESTING_H
#include "tester/tester.h"
#include "../common/wapp_common.h"
#include "../os/wapp_os.h"
#endif // !WAPP_TESTING_H

View File

@@ -1,58 +0,0 @@
// vim:fileencoding=utf-8:foldmethod=marker
#include "uuid.h"
#include "../common/aliases/aliases.h"
#include "../common/assert/assert.h"
#include "../base/strings/str8/str8.h"
#include "../prng/xorshift/xorshift.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;
};
wapp_intern UUID4 generate_uuid4(void);
wapp_intern void uuid4_to_uuid(const UUID4* uuid4, WUUID *uuid);
WUUID *wapp_uuid_init_uuid4(WUUID *uuid) {
wapp_debug_assert(uuid != NULL, "`uuid` should not be NULL");
UUID4 uuid4 = generate_uuid4();
uuid4_to_uuid(&uuid4, uuid);
return uuid;
}
wapp_intern UUID4 generate_uuid4(void) {
wapp_persist XOR256State state = {0};
wapp_persist b8 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;
}
wapp_intern void uuid4_to_uuid(const UUID4* uuid4, WUUID *uuid) {
u64 group1 = uuid4->high >> 32;
u64 group2 = (uuid4->high << 32) >> 48;
u64 group3 = (uuid4->high << 48) >> 48;
u64 group4 = uuid4->low >> 48;
u64 group5 = (uuid4->low << 16) >> 16;
wapp_str8_format(&(uuid->uuid), UUID_STR_FORMAT, group1, group2, group3, group4, group5);
}

View File

@@ -1,37 +0,0 @@
// vim:fileencoding=utf-8:foldmethod=marker
#ifndef UUID_H
#define UUID_H
#include "../common/aliases/aliases.h"
#include "../common/platform/platform.h"
#include "../base/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(WUUID) wapp_str8_varg((WUUID).uuid)
typedef struct WUUID WUUID;
struct WUUID {
Str8 uuid;
};
#define wapp_uuid_gen_uuid4() *(wapp_uuid_init_uuid4(&wapp_uuid_create()))
/* Low level UUID API */
#define wapp_uuid_create() ((WUUID){.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.
WUUID *wapp_uuid_init_uuid4(WUUID *uuid);
#ifdef WAPP_PLATFORM_CPP
END_C_LINKAGE
#endif // !WAPP_PLATFORM_CPP
#endif // !UUID_H

View File

@@ -1,10 +0,0 @@
// vim:fileencoding=utf-8:foldmethod=marker
#ifndef WAPP_UUID_C
#define WAPP_UUID_C
#include "uuid.c"
#include "../base/wapp_base.c"
#include "../prng/wapp_prng.c"
#endif // !WAPP_UUID_C

View File

@@ -1,11 +0,0 @@
// vim:fileencoding=utf-8:foldmethod=marker
#ifndef WAPP_UUID_H
#define WAPP_UUID_H
#include "uuid.h"
#include "../common/wapp_common.h"
#include "../base/wapp_base.h"
#include "../prng/wapp_prng.h"
#endif // !WAPP_UUID_H

View File

@@ -1,13 +0,0 @@
// vim:fileencoding=utf-8:foldmethod=marker
#ifndef WAPP_C
#define WAPP_C
#include "wapp.h"
#include "base/wapp_base.c"
#include "os/wapp_os.c"
#include "prng/wapp_prng.c"
#include "uuid/uuid.c"
#include "testing/wapp_testing.c"
#endif // !WAPP_C

View File

@@ -1,13 +0,0 @@
// vim:fileencoding=utf-8:foldmethod=marker
#ifndef WAPP_H
#define WAPP_H
#include "common/wapp_common.h"
#include "base/wapp_base.h"
#include "os/wapp_os.h"
#include "prng/wapp_prng.h"
#include "uuid/wapp_uuid.h"
#include "testing/wapp_testing.h"
#endif // !WAPP_H

View File

@@ -1,17 +1,30 @@
#include "test_allocator.h"
#include "wapp.h"
#include "libc/mem_libc_allocator.h"
#include "mem_allocator.h"
#include "mem_arena_allocator.h"
#include "tester.h"
#include <stdbool.h>
#include <stdlib.h>
// NOTE (Abdelrahman): Cannot query size of Arena here so it's hardcoded. Similarly, since arena
// allocation are aligned to power of 2 boundaries, the number of i32 values needed is hardcoded.
#define TEMP_BUF_SIZE (40 + sizeof(i32) * 8)
TestFuncResult test_libc_allocator(void) {
Allocator allocator = wapp_mem_libc_allocator();
bool result = allocator.obj == NULL && allocator.alloc != NULL &&
allocator.alloc_aligned == NULL && allocator.realloc != NULL &&
allocator.realloc_aligned == NULL && allocator.free != NULL;
void *ptr = wapp_mem_allocator_alloc(&allocator, 20);
result = result && (ptr != NULL);
wapp_intern u8 temp_buf[TEMP_BUF_SIZE] = {0};
wapp_intern Allocator temp_allocator = {0};
if (ptr != NULL) {
wapp_mem_allocator_free(&allocator, &ptr);
result = result && (ptr == NULL);
}
return wapp_tester_result(result);
}
TestFuncResult test_arena_allocator(void) {
Allocator allocator = wapp_mem_arena_allocator_init(4096);
b8 result = allocator.obj != NULL && allocator.alloc != NULL &&
bool result = allocator.obj != NULL && allocator.alloc != NULL &&
allocator.alloc_aligned != NULL &&
allocator.realloc != NULL && allocator.realloc_aligned != NULL &&
allocator.free == NULL;
@@ -22,46 +35,3 @@ TestFuncResult test_arena_allocator(void) {
return wapp_tester_result(result);
}
TestFuncResult test_arena_allocator_with_buffer(void) {
u8 buffer[KiB(4)] = {0};
Allocator allocator = wapp_mem_arena_allocator_init_with_buffer(buffer, KiB(4));
b8 result = allocator.obj != NULL && allocator.alloc != NULL &&
allocator.alloc_aligned != NULL &&
allocator.realloc != NULL && allocator.realloc_aligned != NULL &&
allocator.free == NULL;
void *ptr = wapp_mem_allocator_alloc(&allocator, 20);
result = result && (ptr != NULL);
wapp_mem_arena_allocator_destroy(&allocator);
return wapp_tester_result(result);
}
TestFuncResult test_arena_allocator_temp_begin(void) {
temp_allocator = wapp_mem_arena_allocator_init_with_buffer(temp_buf, TEMP_BUF_SIZE);
i32 *num1 = (i32 *)wapp_mem_allocator_alloc(&temp_allocator, sizeof(i32));
b8 result = num1 != NULL;
wapp_mem_arena_allocator_temp_begin(&temp_allocator);
i32 *num2 = (i32 *)wapp_mem_allocator_alloc(&temp_allocator, sizeof(i32));
result = result && num2 != NULL;
i32 *num3 = (i32 *)wapp_mem_allocator_alloc(&temp_allocator, sizeof(i32));
result = result && num3 == NULL;
return wapp_tester_result(result);
}
TestFuncResult test_arena_allocator_temp_end(void) {
wapp_mem_arena_allocator_temp_end(&temp_allocator);
i32 *num1 = (i32 *)wapp_mem_allocator_alloc(&temp_allocator, sizeof(i32));
b8 result = num1 != NULL;
i32 *num2 = (i32 *)wapp_mem_allocator_alloc(&temp_allocator, sizeof(i32));
result = result && num2 == NULL;
wapp_mem_arena_allocator_destroy(&temp_allocator);
return wapp_tester_result(result);
}

View File

@@ -1,67 +0,0 @@
#include "test_allocator.h"
#include "wapp.h"
#include <stdlib.h>
// NOTE (Abdelrahman): Cannot query size of Arena here so it's hardcoded. Similarly, since arena
// allocation are aligned to power of 2 boundaries, the number of i32 values needed is hardcoded.
#define TEMP_BUF_SIZE (40 + sizeof(i32) * 8)
wapp_intern u8 temp_buf[TEMP_BUF_SIZE] = {};
wapp_intern Allocator temp_allocator = {};
TestFuncResult test_arena_allocator(void) {
Allocator allocator = wapp_mem_arena_allocator_init(4096);
b8 result = allocator.obj != nullptr && allocator.alloc != nullptr &&
allocator.alloc_aligned != nullptr &&
allocator.realloc != nullptr && allocator.realloc_aligned != nullptr &&
allocator.free == nullptr;
void *ptr = wapp_mem_allocator_alloc(&allocator, 20);
result = result && (ptr != nullptr);
wapp_mem_arena_allocator_destroy(&allocator);
return wapp_tester_result(result);
}
TestFuncResult test_arena_allocator_with_buffer(void) {
u8 buffer[KiB(4)] = {0};
Allocator allocator = wapp_mem_arena_allocator_init_with_buffer(buffer, KiB(4));
b8 result = allocator.obj != NULL && allocator.alloc != NULL &&
allocator.alloc_aligned != NULL &&
allocator.realloc != NULL && allocator.realloc_aligned != NULL &&
allocator.free == NULL;
void *ptr = wapp_mem_allocator_alloc(&allocator, 20);
result = result && (ptr != NULL);
wapp_mem_arena_allocator_destroy(&allocator);
return wapp_tester_result(result);
}
TestFuncResult test_arena_allocator_temp_begin(void) {
temp_allocator = wapp_mem_arena_allocator_init_with_buffer(temp_buf, TEMP_BUF_SIZE);
i32 *num1 = (i32 *)wapp_mem_allocator_alloc(&temp_allocator, sizeof(i32));
b8 result = num1 != NULL;
wapp_mem_arena_allocator_temp_begin(&temp_allocator);
i32 *num2 = (i32 *)wapp_mem_allocator_alloc(&temp_allocator, sizeof(i32));
result = result && num2 != NULL;
i32 *num3 = (i32 *)wapp_mem_allocator_alloc(&temp_allocator, sizeof(i32));
result = result && num3 == NULL;
return wapp_tester_result(result);
}
TestFuncResult test_arena_allocator_temp_end(void) {
wapp_mem_arena_allocator_temp_end(&temp_allocator);
i32 *num1 = (i32 *)wapp_mem_allocator_alloc(&temp_allocator, sizeof(i32));
b8 result = num1 != NULL;
i32 *num2 = (i32 *)wapp_mem_allocator_alloc(&temp_allocator, sizeof(i32));
result = result && num2 == NULL;
wapp_mem_arena_allocator_destroy(&temp_allocator);
return wapp_tester_result(result);
}

View File

@@ -1,11 +1,17 @@
#ifndef TEST_ALLOCATOR_H
#define TEST_ALLOCATOR_H
#include "wapp.h"
#include "tester.h"
#ifdef __cplusplus
BEGIN_C_LINKAGE
#endif // __cplusplus
TestFuncResult test_libc_allocator(void);
TestFuncResult test_arena_allocator(void);
TestFuncResult test_arena_allocator_with_buffer(void);
TestFuncResult test_arena_allocator_temp_begin(void);
TestFuncResult test_arena_allocator_temp_end(void);
#ifdef __cplusplus
END_C_LINKAGE
#endif // __cplusplus
#endif // !TEST_ALLOCATOR_H

View File

@@ -1,36 +1,27 @@
#include "test_arena.h"
#include "wapp.h"
#include "aliases.h"
#include "mem_arena.h"
#include "misc_utils.h"
#include "tester.h"
#include <stdbool.h>
#include <stdlib.h>
#define ARENA_CAPACITY KiB(16)
#define ARENA_BUF_SIZE KiB(4)
// NOTE (Abdelrahman): Cannot query size of Arena here so it's hardcoded. Similarly, since arena
// allocation are aligned to power of 2 boundaries, the number of i32 values needed is hardcoded.
#define TEMP_BUF_SIZE (40 + sizeof(i32) * 8)
#define ARENA_CAPACITY KB(16)
wapp_intern Arena *arena = NULL;
wapp_intern i32 count = 20;
wapp_intern i32 *array = NULL;
wapp_intern Arena *buf_arena = NULL;
wapp_intern u8 buf[ARENA_BUF_SIZE] = {0};
wapp_intern Arena *temp_arena = NULL;
wapp_intern u8 temp_buf[TEMP_BUF_SIZE] = {0};
internal Arena *arena = NULL;
internal i32 count = 20;
internal i32 *array = NULL;
TestFuncResult test_arena_init_buffer(void) {
b8 result = wapp_mem_arena_init_buffer(&buf_arena, buf, ARENA_BUF_SIZE);
return wapp_tester_result(result);
}
TestFuncResult test_arena_init_allocated(void) {
b8 result = wapp_mem_arena_init_allocated(&arena, ARENA_CAPACITY);
TestFuncResult test_arena_init(void) {
bool result = wapp_mem_arena_init(&arena, ARENA_CAPACITY);
return wapp_tester_result(result);
}
TestFuncResult test_arena_init_succeeds_when_reserving_very_large_size(void) {
Arena *large_arena = NULL;
u64 capacity = GiB(512);
b8 result = wapp_mem_arena_init_allocated(&large_arena, capacity);
u64 capacity = GB(512);
bool result = wapp_mem_arena_init(&large_arena, capacity);
if (result) {
wapp_mem_arena_destroy(&large_arena);
}
@@ -38,20 +29,9 @@ TestFuncResult test_arena_init_succeeds_when_reserving_very_large_size(void) {
return wapp_tester_result(result);
}
TestFuncResult test_arena_alloc_with_buffer(void) {
i32 *arr = (i32 *)wapp_mem_arena_alloc(arena, count * sizeof(i32));
b8 result = arr != NULL;
for (i32 i = 0; i < count; ++i) {
arr[i] = i * 10;
}
return wapp_tester_result(result);
}
TestFuncResult test_arena_alloc_succeeds_when_within_capacity(void) {
array = wapp_mem_arena_alloc(arena, count * sizeof(i32));
b8 result = array != NULL;
bool result = array != NULL;
for (i32 i = 0; i < count; ++i) {
array[i] = i * 10;
@@ -62,7 +42,7 @@ TestFuncResult test_arena_alloc_succeeds_when_within_capacity(void) {
TestFuncResult test_arena_alloc_fails_when_over_capacity(void) {
u8 *bytes = wapp_mem_arena_alloc(arena, ARENA_CAPACITY * 2);
b8 result = bytes == NULL;
bool result = bytes == NULL;
return wapp_tester_result(result);
}
@@ -113,35 +93,9 @@ TestFuncResult test_arena_realloc_smaller_size(void) {
return wapp_tester_result(true);
}
TestFuncResult test_arena_temp_begin(void) {
b8 result = wapp_mem_arena_init_buffer(&temp_arena, temp_buf, TEMP_BUF_SIZE);
i32 *num1 = (i32 *)wapp_mem_arena_alloc(temp_arena, sizeof(i32));
result = result && num1 != NULL;
wapp_mem_arena_temp_begin(temp_arena);
i32 *num2 = (i32 *)wapp_mem_arena_alloc(temp_arena, sizeof(i32));
result = result && num2 != NULL;
i32 *num3 = (i32 *)wapp_mem_arena_alloc(temp_arena, sizeof(i32));
result = result && num3 == NULL;
return wapp_tester_result(result);
}
TestFuncResult test_arena_temp_end(void) {
wapp_mem_arena_temp_end(temp_arena);
i32 *num1 = (i32 *)wapp_mem_arena_alloc(temp_arena, sizeof(i32));
b8 result = num1 != NULL;
i32 *num2 = (i32 *)wapp_mem_arena_alloc(temp_arena, sizeof(i32));
result = result && num2 == NULL;
wapp_mem_arena_destroy(&temp_arena);
return wapp_tester_result(result);
}
TestFuncResult test_arena_clear(void) {
wapp_mem_arena_clear(arena);
b8 result = true;
bool result = true;
for (i32 i = 0; i < count; ++i) {
if (array[i] != 0) {
@@ -153,16 +107,9 @@ TestFuncResult test_arena_clear(void) {
return wapp_tester_result(result);
}
TestFuncResult test_arena_destroy_buffer(void) {
wapp_mem_arena_destroy(&buf_arena);
b8 result = buf_arena == NULL;
return wapp_tester_result(result);
}
TestFuncResult test_arena_destroy_allocated(void) {
TestFuncResult test_arena_destroy(void) {
wapp_mem_arena_destroy(&arena);
b8 result = arena == NULL;
bool result = arena == NULL;
return wapp_tester_result(result);
}

View File

@@ -1,168 +0,0 @@
#include "test_arena.h"
#include "wapp.h"
#include <stdlib.h>
#define ARENA_CAPACITY KiB(16)
#define ARENA_BUF_SIZE KiB(4)
// NOTE (Abdelrahman): Cannot query size of Arena here so it's hardcoded. Similarly, since arena
// allocation are aligned to power of 2 boundaries, the number of i32 values needed is hardcoded.
#define TEMP_BUF_SIZE (40 + sizeof(i32) * 8)
wapp_intern Arena *arena = NULL;
wapp_intern i32 count = 20;
wapp_intern i32 *array = NULL;
wapp_intern Arena *buf_arena = NULL;
wapp_intern u8 buf[ARENA_BUF_SIZE] = {};
wapp_intern Arena *temp_arena = NULL;
wapp_intern u8 temp_buf[TEMP_BUF_SIZE] = {};
TestFuncResult test_arena_init_buffer(void) {
b8 result = wapp_mem_arena_init_buffer(&buf_arena, buf, ARENA_BUF_SIZE);
return wapp_tester_result(result);
}
TestFuncResult test_arena_init_allocated(void) {
b8 result = wapp_mem_arena_init_allocated(&arena, ARENA_CAPACITY);
return wapp_tester_result(result);
}
TestFuncResult test_arena_init_succeeds_when_reserving_very_large_size(void) {
Arena *large_arena = nullptr;
u64 capacity = GiB(512);
b8 result = wapp_mem_arena_init_allocated(&large_arena, capacity);
if (result) {
wapp_mem_arena_destroy(&large_arena);
}
return wapp_tester_result(result);
}
TestFuncResult test_arena_alloc_with_buffer(void) {
i32 *arr = (i32 *)wapp_mem_arena_alloc(arena, count * sizeof(i32));
b8 result = arr != NULL;
for (i32 i = 0; i < count; ++i) {
arr[i] = i * 10;
}
return wapp_tester_result(result);
}
TestFuncResult test_arena_alloc_succeeds_when_within_capacity(void) {
array = (i32 *)wapp_mem_arena_alloc(arena, count * sizeof(i32));
b8 result = array != nullptr;
for (i32 i = 0; i < count; ++i) {
array[i] = i * 10;
}
return wapp_tester_result(result);
}
TestFuncResult test_arena_alloc_fails_when_over_capacity(void) {
u8 *bytes = (u8 *)wapp_mem_arena_alloc(arena, ARENA_CAPACITY * 2);
b8 result = bytes == nullptr;
return wapp_tester_result(result);
}
TestFuncResult test_arena_realloc_bigger_size(void) {
u64 old_count = 10;
u64 new_count = 20;
i32 *bytes = (i32 *)wapp_mem_arena_alloc(arena, old_count * sizeof(i32));
for (u64 i = 0; i < old_count; ++i) {
bytes[i] = (i32)i;
}
i32 *new_bytes = (i32 *)wapp_mem_arena_realloc(arena, bytes, old_count * sizeof(i32), new_count * sizeof(i32));
if (!new_bytes) {
return wapp_tester_result(false);
}
for (u64 i = 0; i < new_count; ++i) {
if (i < old_count && new_bytes[i] != bytes[i]) {
return wapp_tester_result(false);
}
}
return wapp_tester_result(true);
}
TestFuncResult test_arena_realloc_smaller_size(void) {
u64 old_count = 10;
u64 new_count = 5;
i32 *bytes = (i32 *)wapp_mem_arena_alloc(arena, old_count * sizeof(i32));
for (u64 i = 0; i < old_count; ++i) {
bytes[i] = (i32)i;
}
i32 *new_bytes = (i32 *)wapp_mem_arena_realloc(arena, bytes, old_count * sizeof(i32), new_count * sizeof(i32));
if (!new_bytes) {
return wapp_tester_result(false);
}
for (u64 i = 0; i < new_count; ++i) {
if (i < new_count && new_bytes[i] != bytes[i]) {
return wapp_tester_result(false);
}
}
return wapp_tester_result(true);
}
TestFuncResult test_arena_temp_begin(void) {
b8 result = wapp_mem_arena_init_buffer(&temp_arena, temp_buf, TEMP_BUF_SIZE);
i32 *num1 = (i32 *)wapp_mem_arena_alloc(temp_arena, sizeof(i32));
result = result && num1 != NULL;
wapp_mem_arena_temp_begin(temp_arena);
i32 *num2 = (i32 *)wapp_mem_arena_alloc(temp_arena, sizeof(i32));
result = result && num2 != NULL;
i32 *num3 = (i32 *)wapp_mem_arena_alloc(temp_arena, sizeof(i32));
result = result && num3 == NULL;
return wapp_tester_result(result);
}
TestFuncResult test_arena_temp_end(void) {
wapp_mem_arena_temp_end(temp_arena);
i32 *num1 = (i32 *)wapp_mem_arena_alloc(temp_arena, sizeof(i32));
b8 result = num1 != NULL;
i32 *num2 = (i32 *)wapp_mem_arena_alloc(temp_arena, sizeof(i32));
result = result && num2 == NULL;
wapp_mem_arena_destroy(&temp_arena);
return wapp_tester_result(result);
}
TestFuncResult test_arena_clear(void) {
wapp_mem_arena_clear(arena);
b8 result = true;
for (i32 i = 0; i < count; ++i) {
if (array[i] != 0) {
result = false;
break;
}
}
return wapp_tester_result(result);
}
TestFuncResult test_arena_destroy_buffer(void) {
wapp_mem_arena_destroy(&buf_arena);
b8 result = buf_arena == NULL;
return wapp_tester_result(result);
}
TestFuncResult test_arena_destroy_allocated(void) {
wapp_mem_arena_destroy(&arena);
b8 result = arena == nullptr;
return wapp_tester_result(result);
}

View File

@@ -1,20 +1,23 @@
#ifndef TEST_ARENA_H
#define TEST_ARENA_H
#include "wapp.h"
#include "tester.h"
TestFuncResult test_arena_init_buffer(void);
TestFuncResult test_arena_init_allocated(void);
#ifdef __cplusplus
BEGIN_C_LINKAGE
#endif // __cplusplus
TestFuncResult test_arena_init(void);
TestFuncResult test_arena_init_succeeds_when_reserving_very_large_size(void);
TestFuncResult test_arena_alloc_with_buffer(void);
TestFuncResult test_arena_alloc_succeeds_when_within_capacity(void);
TestFuncResult test_arena_alloc_fails_when_over_capacity(void);
TestFuncResult test_arena_realloc_bigger_size(void);
TestFuncResult test_arena_realloc_smaller_size(void);
TestFuncResult test_arena_clear(void);
TestFuncResult test_arena_temp_begin(void);
TestFuncResult test_arena_temp_end(void);
TestFuncResult test_arena_destroy_buffer(void);
TestFuncResult test_arena_destroy_allocated(void);
TestFuncResult test_arena_destroy(void);
#ifdef __cplusplus
END_C_LINKAGE
#endif // __cplusplus
#endif // !TEST_ARENA_H

View File

@@ -1,273 +0,0 @@
#include "test_i32_array.h"
#include "wapp.h"
TestFuncResult test_i32_array(void) {
b8 result;
I32Array array = wapp_array(i32, 1, 2, 3, 4, 5, 6, 7);
result = wapp_array_count(array) == 7 && wapp_array_capacity(array) == 16;
i32 *item;
u64 count = wapp_array_count(array);
u64 index = 0;
b8 running = true;
while (running) {
item = wapp_array_get(i32, array, index);
result = result && item && *item == (i32)(index + 1);
++index;
running = index < count;
}
return wapp_tester_result(result);
}
TestFuncResult test_i32_array_with_capacity(void) {
b8 result;
I32Array array1 = wapp_array_with_capacity(i32, 64, ARRAY_INIT_NONE);
result = wapp_array_count(array1) == 0 && wapp_array_capacity(array1) == 64;
I32Array array2 = wapp_array_with_capacity(i32, 64, ARRAY_INIT_FILLED);
result = wapp_array_count(array2) == 64 && wapp_array_capacity(array2) == 64;
return wapp_tester_result(result);
}
TestFuncResult test_i32_array_get(void) {
b8 result = true;
I32Array array = wapp_array(i32, 0, 1, 2, 3, 4, 5, 6, 7, 8);
i32 *item;
u64 count = wapp_array_count(array);
u64 index = 0;
b8 running = true;
while (running) {
item = wapp_array_get(i32, array, index);
result = result && item && *item == (i32)index;
++index;
running = index < count;
}
return wapp_tester_result(result);
}
TestFuncResult test_i32_array_set(void) {
b8 result = true;
I32Array array = wapp_array(i32, 0, 1, 2, 3, 4, 5, 6, 7, 8);
i32 *item;
u64 count = wapp_array_count(array);
u64 index = 0;
b8 running = true;
while (running) {
i32 num = (i32)(index * 2);
wapp_array_set(i32, array, index, &num);
item = wapp_array_get(i32, array, index);
result = result && item && *item == (i32)(index * 2);
++index;
running = index < count;
}
return wapp_tester_result(result);
}
TestFuncResult test_i32_array_append_capped(void) {
b8 result;
I32Array array = wapp_array_with_capacity(i32, 64, ARRAY_INIT_NONE);
wapp_array_append_capped(i32, array, &((i32){10}));
result = wapp_array_count(array) == 1;
i32 *item = wapp_array_get(i32, array, 0);
result = result && item && *item == 10;
array = wapp_array(i32, 1);
wapp_array_append_capped(i32, array, &((i32){10}));
result = result && wapp_array_count(array) == 2;
return wapp_tester_result(result);
}
TestFuncResult test_i32_array_extend_capped(void) {
b8 result;
I32Array array1 = wapp_array(i32, 1, 2, 3, 4);
I32Array array2 = wapp_array(i32, 10, 20);
result = wapp_array_count(array1) == 4 && wapp_array_count(array2) == 2;
wapp_array_extend_capped(i32, array1, array2);
result = result && wapp_array_count(array1) == 6;
return wapp_tester_result(result);
}
TestFuncResult test_i32_array_copy_capped(void) {
b8 result;
I32Array src = wapp_array(i32, 1, 2, 3, 4, 5);
I32Array dst1 = wapp_array(i32, 1, 2, 3, 4, 5, 6);
I32Array dst2 = wapp_array(i32, 1, 2);
u64 expected_count = 5;
wapp_array_copy_capped(i32, dst1, src);
result = wapp_array_count(dst1) == expected_count;
u64 index = 0;
b8 running = true;
while (running) {
result = result && *wapp_array_get(i32, src, index) == *wapp_array_get(i32, dst1, index);
++index;
running = index < expected_count;
}
expected_count = 4;
wapp_array_copy_capped(i32, dst2, src);
result = result && wapp_array_count(dst2) == expected_count;
index = 0;
running = true;
while (running) {
result = result && *wapp_array_get(i32, src, index) == *wapp_array_get(i32, dst2, index);
++index;
running = index < expected_count;
}
return wapp_tester_result(result);
}
TestFuncResult test_i32_array_alloc_capacity(void) {
b8 result;
Allocator allocator = wapp_mem_arena_allocator_init(MiB(4));
u64 capacity = 32;
I32Array array = wapp_array_alloc_capacity(i32, &allocator, capacity, ARRAY_INIT_NONE);
result = array && wapp_array_capacity(array) == capacity;
wapp_mem_arena_allocator_destroy(&allocator);
return wapp_tester_result(result);
}
TestFuncResult test_i32_array_append_alloc(void) {
b8 result;
Allocator allocator = wapp_mem_arena_allocator_init(MiB(4));
I32Array array1 = wapp_array(i32, 1, 2, 3, 4, 5, 6, 7, 8);
I32Array array2 = wapp_array(i32, 1, 2);
I32Array arr_ptr = wapp_array_append_alloc(i32, &allocator, array1, &((i32){10}), ARRAY_INIT_NONE);
result = arr_ptr == array1;
u64 count = 4;
u64 index = 0;
b8 running = true;
while (running) {
i32 num = (i32)index;
arr_ptr = wapp_array_append_alloc(i32, &allocator, array2, &num, ARRAY_INIT_NONE);
++index;
running = index < count;
}
result = result && arr_ptr != array2;
wapp_mem_arena_allocator_destroy(&allocator);
return wapp_tester_result(result);
}
TestFuncResult test_i32_array_extend_alloc(void) {
b8 result;
Allocator allocator = wapp_mem_arena_allocator_init(MiB(4));
I32Array array1 = wapp_array(i32, 1, 2, 3, 4, 5, 6, 7, 8);
I32Array array2 = wapp_array(i32, 1, 2);
I32Array array3 = wapp_array(i32, 1, 2, 3, 4);
I32Array arr_ptr = wapp_array_extend_alloc(i32, &allocator, array1, array3, ARRAY_INIT_NONE);
result = arr_ptr == array1;
arr_ptr = wapp_array_extend_alloc(i32, &allocator, array2, array3, ARRAY_INIT_NONE);
result = result && arr_ptr != array2;
wapp_mem_arena_allocator_destroy(&allocator);
return wapp_tester_result(result);
}
TestFuncResult test_i32_array_copy_alloc(void) {
b8 result;
Allocator allocator = wapp_mem_arena_allocator_init(MiB(4));
I32Array src = wapp_array(i32, 1, 2, 3, 4, 5);
I32Array dst1 = wapp_array(i32, 1, 2, 3, 4, 5, 6);
I32Array dst2 = wapp_array(i32, 1, 2);
I32Array array = NULL;
u64 expected_count = 5;
array = wapp_array_copy_alloc(i32, &allocator, dst1, src, ARRAY_INIT_NONE);
result = wapp_array_count(array) == expected_count && array == dst1;
u64 index = 0;
b8 running = true;
while (running) {
result = result && *wapp_array_get(i32, src, index) == *wapp_array_get(i32, array, index);
++index;
running = index < expected_count;
}
expected_count = 5;
array = wapp_array_copy_alloc(i32, &allocator, dst2, src, ARRAY_INIT_NONE);
result = result && wapp_array_count(array) == expected_count && array != dst2;
index = 0;
running = true;
while (running) {
result = result && *wapp_array_get(i32, src, index) == *wapp_array_get(i32, array, index);
++index;
running = index < expected_count;
}
wapp_mem_arena_allocator_destroy(&allocator);
return wapp_tester_result(result);
}
TestFuncResult test_i32_array_pop(void) {
b8 result;
I32Array array1 = wapp_array(i32, 0, 1, 2, 3, 4, 5, 6, 7, 8);
I32Array array2 = wapp_array_with_capacity(i32, 32, ARRAY_INIT_NONE);
i32 item1 = wapp_array_pop(i32, array1);
i32 item2 = wapp_array_pop(i32, array2);
result = item1 == 8 && item2 == 0;
return wapp_tester_result(result);
}
TestFuncResult test_i32_array_clear(void) {
b8 result;
I32Array array = wapp_array(i32, 0, 1, 2, 3, 4, 5, 6, 7, 8);
result = wapp_array_count(array) == 9;
wapp_array_clear(i32, array);
result = result && wapp_array_count(array) == 0;
return wapp_tester_result(result);
}

View File

@@ -1,276 +0,0 @@
#include "test_i32_array.h"
#include "wapp.h"
TestFuncResult test_i32_array(void) {
b8 result;
I32Array array = wapp_array(i32, 1, 2, 3, 4, 5, 6, 7);
result = wapp_array_count(array) == 7 && wapp_array_capacity(array) == 16;
i32 *item;
u64 count = wapp_array_count(array);
u64 index = 0;
b8 running = true;
while (running) {
item = wapp_array_get(i32, array, index);
result = result && item && (*item == (i32)(index + 1));
++index;
running = index < count;
}
return wapp_tester_result(result);
}
TestFuncResult test_i32_array_with_capacity(void) {
b8 result;
I32Array array1 = wapp_array_with_capacity(i32, 64, ARRAY_INIT_NONE);
result = wapp_array_count(array1) == 0 && wapp_array_capacity(array1) == 64;
I32Array array2 = wapp_array_with_capacity(i32, 64, ARRAY_INIT_FILLED);
result = wapp_array_count(array2) == 64 && wapp_array_capacity(array2) == 64;
return wapp_tester_result(result);
}
TestFuncResult test_i32_array_get(void) {
b8 result = true;
I32Array array = wapp_array(i32, 0, 1, 2, 3, 4, 5, 6, 7, 8);
i32 *item;
u64 count = wapp_array_count(array);
u64 index = 0;
b8 running = true;
while (running) {
item = wapp_array_get(i32, array, index);
result = result && item && (*item == (i32)index);
++index;
running = index < count;
}
return wapp_tester_result(result);
}
TestFuncResult test_i32_array_set(void) {
b8 result = true;
I32Array array = wapp_array(i32, 0, 1, 2, 3, 4, 5, 6, 7, 8);
i32 *item;
u64 count = wapp_array_count(array);
u64 index = 0;
b8 running = true;
while (running) {
i32 num = (i32)(index * 2);
wapp_array_set(i32, array, index, &num);
item = wapp_array_get(i32, array, index);
result = result && item && (*item == (i32)(index * 2));
++index;
running = index < count;
}
return wapp_tester_result(result);
}
TestFuncResult test_i32_array_append_capped(void) {
b8 result;
I32Array array = wapp_array_with_capacity(i32, 64, ARRAY_INIT_NONE);
i32 item1 = 10;
wapp_array_append_capped(i32, array, &item1);
result = wapp_array_count(array) == 1;
i32 *item = wapp_array_get(i32, array, 0);
result = result && item && *item == 10;
array = wapp_array(i32, 1);
i32 item2 = 10;
wapp_array_append_capped(i32, array, &item2);
result = result && wapp_array_count(array) == 2;
return wapp_tester_result(result);
}
TestFuncResult test_i32_array_extend_capped(void) {
b8 result;
I32Array array1 = wapp_array(i32, 1, 2, 3, 4);
I32Array array2 = wapp_array(i32, 10, 20);
result = wapp_array_count(array1) == 4 && wapp_array_count(array2) == 2;
wapp_array_extend_capped(i32, array1, array2);
result = result && wapp_array_count(array1) == 6;
return wapp_tester_result(result);
}
TestFuncResult test_i32_array_copy_capped(void) {
b8 result;
I32Array src = wapp_array(i32, 1, 2, 3, 4, 5);
I32Array dst1 = wapp_array(i32, 1, 2, 3, 4, 5, 6);
I32Array dst2 = wapp_array(i32, 1, 2);
u64 expected_count = 5;
wapp_array_copy_capped(i32, dst1, src);
result = wapp_array_count(dst1) == expected_count;
u64 index = 0;
b8 running = true;
while (running) {
result = result && (*wapp_array_get(i32, src, index) == *wapp_array_get(i32, dst1, index));
++index;
running = index < expected_count;
}
expected_count = 4;
wapp_array_copy_capped(i32, dst2, src);
result = result && wapp_array_count(dst2) == expected_count;
index = 0;
running = true;
while (running) {
result = result && (*wapp_array_get(i32, src, index) == *wapp_array_get(i32, dst2, index));
++index;
running = index < expected_count;
}
return wapp_tester_result(result);
}
TestFuncResult test_i32_array_alloc_capacity(void) {
b8 result;
Allocator allocator = wapp_mem_arena_allocator_init(MiB(4));
u64 capacity = 32;
I32Array array = wapp_array_alloc_capacity(i32, &allocator, capacity, ARRAY_INIT_NONE);
result = array && wapp_array_capacity(array) == capacity;
wapp_mem_arena_allocator_destroy(&allocator);
return wapp_tester_result(result);
}
TestFuncResult test_i32_array_append_alloc(void) {
b8 result;
Allocator allocator = wapp_mem_arena_allocator_init(MiB(4));
I32Array array1 = wapp_array(i32, 1, 2, 3, 4, 5, 6, 7, 8);
I32Array array2 = wapp_array(i32, 1, 2);
i32 num = 10;
I32Array arr_ptr = wapp_array_append_alloc(i32, &allocator, array1, &num, ARRAY_INIT_NONE);
result = arr_ptr == array1;
u64 count = 4;
u64 index = 0;
b8 running = true;
while (running) {
num = (i32)index;
arr_ptr = wapp_array_append_alloc(i32, &allocator, array2, &num, ARRAY_INIT_NONE);
++index;
running = index < count;
}
result = result && arr_ptr != array2;
wapp_mem_arena_allocator_destroy(&allocator);
return wapp_tester_result(result);
}
TestFuncResult test_i32_array_extend_alloc(void) {
b8 result;
Allocator allocator = wapp_mem_arena_allocator_init(MiB(4));
I32Array array1 = wapp_array(i32, 1, 2, 3, 4, 5, 6, 7, 8);
I32Array array2 = wapp_array(i32, 1, 2);
I32Array array3 = wapp_array(i32, 1, 2, 3, 4);
I32Array array = wapp_array_extend_alloc(i32, &allocator, array1, array3, ARRAY_INIT_NONE);
result = array == array1;
array = wapp_array_extend_alloc(i32, &allocator, array2, array3, ARRAY_INIT_NONE);
result = result && array != array2;
wapp_mem_arena_allocator_destroy(&allocator);
return wapp_tester_result(result);
}
TestFuncResult test_i32_array_copy_alloc(void) {
b8 result;
Allocator allocator = wapp_mem_arena_allocator_init(MiB(4));
I32Array src = wapp_array(i32, 1, 2, 3, 4, 5);
I32Array dst1 = wapp_array(i32, 1, 2, 3, 4, 5, 6);
I32Array dst2 = wapp_array(i32, 1, 2);
I32Array array = nullptr;
u64 expected_count = 5;
array = wapp_array_copy_alloc(i32, &allocator, dst1, src, ARRAY_INIT_NONE);
result = wapp_array_count(array) == expected_count && array == dst1;
u64 index = 0;
b8 running = true;
while (running) {
result = result && (*wapp_array_get(i32, src, index) == *wapp_array_get(i32, array, index));
++index;
running = index < expected_count;
}
expected_count = 5;
array = wapp_array_copy_alloc(i32, &allocator, dst2, src, ARRAY_INIT_NONE);
result = result && wapp_array_count(array) == expected_count && array != dst2;
index = 0;
running = true;
while (running) {
result = result && (*wapp_array_get(i32, src, index) == *wapp_array_get(i32, array, index));
++index;
running = index < expected_count;
}
wapp_mem_arena_allocator_destroy(&allocator);
return wapp_tester_result(result);
}
TestFuncResult test_i32_array_clear(void) {
b8 result;
I32Array array = wapp_array(i32, 0, 1, 2, 3, 4, 5, 6, 7, 8);
result = wapp_array_count(array) == 9;
wapp_array_clear(i32, array);
result = result && wapp_array_count(array) == 0;
return wapp_tester_result(result);
}
TestFuncResult test_i32_array_pop(void) {
b8 result;
I32Array array1 = wapp_array(i32, 0, 1, 2, 3, 4, 5, 6, 7, 8);
I32Array array2 = wapp_array_with_capacity(i32, 32, ARRAY_INIT_NONE);
i32 item1 = wapp_array_pop(i32, array1);
i32 item2 = wapp_array_pop(i32, array2);
result = item1 == 8 && item2 == 0;
return wapp_tester_result(result);
}

View File

@@ -1,20 +0,0 @@
#ifndef TEST_INT_ARRAY_H
#define TEST_INT_ARRAY_H
#include "wapp.h"
TestFuncResult test_i32_array(void);
TestFuncResult test_i32_array_with_capacity(void);
TestFuncResult test_i32_array_get(void);
TestFuncResult test_i32_array_set(void);
TestFuncResult test_i32_array_append_capped(void);
TestFuncResult test_i32_array_extend_capped(void);
TestFuncResult test_i32_array_copy_capped(void);
TestFuncResult test_i32_array_alloc_capacity(void);
TestFuncResult test_i32_array_append_alloc(void);
TestFuncResult test_i32_array_extend_alloc(void);
TestFuncResult test_i32_array_copy_alloc(void);
TestFuncResult test_i32_array_pop(void);
TestFuncResult test_i32_array_clear(void);
#endif // !TEST_INT_ARRAY_H

View File

@@ -1,25 +0,0 @@
// vim:fileencoding=utf-8:foldmethod=marker
#include "test_str8_array.h"
TestFuncResult test_str8_array(void) {
b8 result;
Str8 expected[] = {wapp_str8_lit("Hello"), wapp_str8_lit("Hi"), wapp_str8_lit("Bye")};
Str8Array array = wapp_array(Str8, wapp_str8_lit("Hello"), wapp_str8_lit("Hi"), wapp_str8_lit("Bye"));
result = wapp_array_count(array) == 3 && wapp_array_capacity(array) == 8;
Str8 *item;
u64 count = wapp_array_count(array);
u64 index = 0;
b8 running = true;
while (running) {
item = wapp_array_get(Str8, array, index);
result = result && item && (wapp_str8_equal(item, &expected[index]));
++index;
running = index < count;
}
return wapp_tester_result(result);
}

Some files were not shown because too many files have changed in this diff Show More