Compare commits
201 Commits
8a91a0ec6b
...
main
Author | SHA1 | Date | |
---|---|---|---|
9f32891bbc | |||
b3ebff3635 | |||
14bd6ce5fd | |||
09e96f8112 | |||
|
9cbd0b29ef | ||
26fd329caa | |||
1e224702a3 | |||
74cca183e0 | |||
e26bf613a5 | |||
|
81e3ab2c67 | ||
|
8ec0757b34 | ||
|
eb98de7c2b | ||
d3fccd61b5 | |||
011083ab83 | |||
b8c548ee4b | |||
75be2316e0 | |||
|
d452225d02 | ||
74164717d0 | |||
6c8434a530 | |||
cac66b9dbb | |||
175f627f93 | |||
be30189d15 | |||
3689c17d09 | |||
8e952d9bc8 | |||
def7576101 | |||
3fed536a74 | |||
aae39fe656 | |||
4e3945d1d0 | |||
98a802e3eb | |||
0d4aa7a9c2 | |||
a229f9be8c | |||
2156d2ff3a | |||
12f083edb0 | |||
f444911452 | |||
163283f77f | |||
6064ed346c | |||
77f3c40ebd | |||
d3f1686d58 | |||
a359331df7 | |||
14115f7e7e | |||
12bd3eb489 | |||
266d43e262 | |||
a568b30163 | |||
b1773746d8 | |||
a479a43f4c | |||
b476ceaeef | |||
4d69b97149 | |||
181c4b8614 | |||
0d541f6ee8 | |||
9e34b37d8d | |||
b884d0e6a6 | |||
494bbeb398 | |||
7605eb4e57 | |||
037b0fe698 | |||
b13274cd81 | |||
4f9f632362 | |||
6b039aeac0 | |||
2ab3bfc2e1 | |||
bf99bef291 | |||
50e23d8a13 | |||
3a49dba366 | |||
1cfc52b35e | |||
25395553d7 | |||
9a651665ba | |||
8dbdfa2094 | |||
add2ba541d | |||
63ed2633ea | |||
|
3c32b247c0 | ||
|
aa04fab6ea | ||
|
2017f6de79 | ||
|
63acdd1336 | ||
|
cfa8094260 | ||
|
31373eba03 | ||
|
778a4da092 | ||
|
6fb078a868 | ||
0942643b4e | |||
|
0e5942af34 | ||
|
c83c652b37 | ||
|
74428f1caf | ||
|
d661312cfa | ||
70e075d2f6 | |||
96db885344 | |||
fb512e4a15 | |||
9361f0fe37 | |||
e7d2553400 | |||
509724cc31 | |||
|
82c23eed5e | ||
|
9403193f09 | ||
|
fa1d9eec0d | ||
|
4c14588d92 | ||
|
9e66bd60bd | ||
|
ce4957d0a0 | ||
b9ea290322 | |||
1479c13417 | |||
4520f2269d | |||
6119cf5c5f | |||
358f61e556 | |||
7ac6100a5a | |||
19efb08a3a | |||
491c742189 | |||
4f5dd3900f | |||
dbedcb3100 | |||
d9314fb41e | |||
fe2bb65b06 | |||
ed4ec54c7a | |||
ba5e902a1d | |||
01f066d20c | |||
80bd68f313 | |||
cda7e413e2 | |||
54da75f89f | |||
7df64a3168 | |||
f9f8f092b5 | |||
f89a4bf343 | |||
0d795cc0d9 | |||
28ac9ed8c8 | |||
99f7dcd794 | |||
c5ca39939d | |||
a308359942 | |||
a3d9bcf1a1 | |||
|
a534d44db5 | ||
11949e69be | |||
2c9e4c91a0 | |||
76b078fbc0 | |||
0569fca193 | |||
6078e54087 | |||
180425707b | |||
62dcfdaa93 | |||
19134d0e15 | |||
ca2b1cbf23 | |||
f60442bfcf | |||
a4a1e82c40 | |||
d50b41acac | |||
71b6242f16 | |||
241edfc7e4 | |||
d635e03cd8 | |||
68fe421ab0 | |||
622a4391a0 | |||
ff4d3c9e99 | |||
023c74d8d9 | |||
86fe867011 | |||
98829b8400 | |||
a7e98211f9 | |||
4642361969 | |||
093d0daf6f | |||
f8e0804dd2 | |||
fdb0650634 | |||
d1d6a8e64b | |||
bbf38499ca | |||
7657ad1b58 | |||
70399cb797 | |||
76c3b02e45 | |||
abf9b09495 | |||
6d09059911 | |||
894ae028b7 | |||
84a4ec223c | |||
8f10ac2916 | |||
bfb4e87a1e | |||
685682e1c8 | |||
40d301fd95 | |||
7d8df816a5 | |||
17f0f0eaf3 | |||
ce656a6275 | |||
8d8fcf9dc5 | |||
77e634ec2d | |||
22ece7215a | |||
4af4b39d6f | |||
a48002996e | |||
e9451f10f8 | |||
1de3608b1f | |||
3a25571105 | |||
139b4ca589 | |||
e431cf729e | |||
1d1c3ca928 | |||
f2f155744a | |||
d3a86ec6cb | |||
e053aa44ab | |||
a546a09565 | |||
12f182f0cf | |||
ffb99a3644 | |||
1ddc5610f9 | |||
d8c7b3162f | |||
9e1e4688e4 | |||
cd38672581 | |||
7fea236618 | |||
16a1b8fa35 | |||
a0dfe8acd0 | |||
95c47ec940 | |||
46f32f2ba9 | |||
8f794dee15 | |||
034b105ea1 | |||
c90874ad10 | |||
8468bb8e28 | |||
d30eee0cf8 | |||
59e56a75d3 | |||
5d6ce1d2c3 | |||
ce537b7494 | |||
b8f6e5f187 | |||
775f0864a8 | |||
8b6fb23bac | |||
1fb340561f | |||
8ed372d938 |
6
.gitignore
vendored
6
.gitignore
vendored
@@ -1,10 +1,14 @@
|
||||
.cache
|
||||
.vscode
|
||||
.venv
|
||||
test
|
||||
test.*
|
||||
*.dSYM
|
||||
.DS_Store
|
||||
*.pdb
|
||||
*.obj
|
||||
compile_commands.json
|
||||
libwapp-build
|
||||
libwapp.so
|
||||
dist
|
||||
*.vs
|
||||
__pycache__
|
||||
|
130
Makefile
Normal file
130
Makefile
Normal file
@@ -0,0 +1,130 @@
|
||||
.PHONY: help full prng testing uuid core primitives all clean builddir build-test run-test codegen install build-lib ccodegen
|
||||
|
||||
# External variables
|
||||
CC = clang
|
||||
CXX = clang++
|
||||
AR = ar
|
||||
BUILD_TYPE = Debug
|
||||
BUILD_DIR = libwapp-build/$(PLATFORM)-$(BUILD_TYPE)
|
||||
INSTALL_PREFIX = dist
|
||||
|
||||
# Internal variables
|
||||
override CFLAGS = -Wall -Wextra -Werror -pedantic -Isrc
|
||||
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_NAME := wapp
|
||||
override OBJ_OUT := $(BUILD_DIR)/$(LIB_NAME).o
|
||||
override LIB_OUT := $(BUILD_DIR)/lib$(LIB_NAME).a
|
||||
override TEST_C_OUT := $(BUILD_DIR)/wapptest
|
||||
override TEST_CXX_OUT := $(BUILD_DIR)/wapptestcc
|
||||
override INCLUDE_INSTALL := $(INSTALL_PREFIX)/include/$(LIB_NAME)
|
||||
override LIB_INSTALL := $(INSTALL_PREFIX)/lib
|
||||
override HEADER_INSTALL_CMD := scripts/header_install.sh
|
||||
|
||||
ifeq ($(BUILD_TYPE),Debug)
|
||||
override CFLAGS += -g -fsanitize=address,undefined -DWAPP_DEBUG_ASSERT
|
||||
else ifeq ($(BUILD_TYPE),RelWithDebInfo)
|
||||
override CFLAGS += -g -O2 -fsanitize=address,undefined -DWAPP_DEBUG_ASSERT
|
||||
else ifeq ($(BUILD_TYPE),Release)
|
||||
override CFLAGS += -O3
|
||||
else
|
||||
$(error Invalid BUILD type '$(BUILD_TYPE)'. Use 'Debug', 'RelWithDebInfo' or 'Release')
|
||||
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
|
||||
|
||||
all: clean builddir codegen run-c-test full run-cc-test
|
||||
|
||||
help:
|
||||
@echo "Available build variables:"
|
||||
@echo " CC C compiler to use (Default: clang)."
|
||||
@echo " CXX C++ compiler to use (Default: clang++)."
|
||||
@echo " AR Archiving utility to use for building static libraries (Default: ar)."
|
||||
@echo " BUILD_TYPE Build type. Choose from \`Debug\`, \`RelWithDebInfo\` or \`Release\` (Default: Debug)."
|
||||
@echo " BUILD_DIR Directory where build files will be written."
|
||||
@echo " INSTALL_PREFIX Prefix where library and include files will be installed."
|
||||
@echo
|
||||
@echo "Available targets:"
|
||||
@echo " make Build, install and test the full wapp library."
|
||||
@echo " make full Build and install the full wapp library."
|
||||
@echo " make core Build and install only the \`core\` component of the wapp library with all its dependencies."
|
||||
@echo " make prng Build and install only the \`prng\` component of the wapp library with all its dependencies."
|
||||
@echo " make uuid Build and install only the \`uuid\` component of the wapp library with all its dependencies."
|
||||
@echo " make testing Build and install only the \`testing\` component of the wapp library with all its dependencies."
|
||||
@echo " make primitives Build and install only the \`primitives\` component of the wapp library with all its dependencies."
|
||||
@echo " make clean Clean build directory."
|
||||
@echo " make help Print this help message and exit."
|
||||
|
||||
full: LIB_SRC = src/wapp.c
|
||||
full: INCLUDES = common core primitives prng testing uuid
|
||||
full: 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 core testing
|
||||
testing: install
|
||||
|
||||
uuid: LIB_SRC = src/uuid/wapp_uuid.c
|
||||
uuid: INCLUDES = common primitives prng
|
||||
uuid: install
|
||||
|
||||
core: LIB_SRC = src/core/wapp_core.c
|
||||
core: INCLUDES = common core primitives
|
||||
core: install
|
||||
|
||||
primitives: LIB_SRC = src/primitives/wapp_primitives.c
|
||||
primitives: INCLUDES = common primitives
|
||||
primitives: install
|
||||
|
||||
clean:
|
||||
@rm -rf $(BUILD_DIR)
|
||||
|
||||
builddir:
|
||||
@mkdir -p $(BUILD_DIR)
|
||||
|
||||
build-c-test:
|
||||
$(CC) $(CSTD) $(CFLAGS) $(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) $(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)
|
||||
|
||||
codegen:
|
||||
python3 -m codegen
|
||||
|
||||
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) $(LIBFLAGS) $(LIB_SRC) -o $(OBJ_OUT)
|
||||
$(AR) r $(LIB_OUT) $(OBJ_OUT)
|
||||
@rm $(OBJ_OUT)
|
||||
|
||||
ccodegen:
|
||||
$(CC) $(CSTD) $(CFLAGS) $(LIBFLAGS) -Isrc/core src/core/wapp_core.c ccodegen/*.c -o ccgen
|
@@ -1,3 +1,3 @@
|
||||
# Wizard Apprentice Standard Library
|
||||
|
||||
A collection of useful C/C++ utilities for my projects
|
||||
A collection of useful C utilities for my projects
|
||||
|
68
build
68
build
@@ -1,3 +1,69 @@
|
||||
#!/bin/bash
|
||||
|
||||
bear -- ./compile $@
|
||||
# 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
|
||||
|
||||
if [[ $KERNEL == "Darwin" ]]; then
|
||||
if [[ ! -d .venv ]]; then
|
||||
python3 -m venv .venv
|
||||
fi
|
||||
|
||||
source .venv/bin/activate
|
||||
pip install scan-build
|
||||
intercept-build make CC=intercept-cc CXX=intercept-c++ BUILD_TYPE=$BUILD_TYPE $ARGS
|
||||
deactivate
|
||||
else
|
||||
bear -- make BUILD_TYPE=$BUILD_TYPE $ARGS
|
||||
fi
|
||||
|
33
build.ps1
33
build.ps1
@@ -1,27 +1,31 @@
|
||||
Param(
|
||||
[switch]$Release
|
||||
[switch]$Release
|
||||
)
|
||||
|
||||
$Compiler = "cl.exe"
|
||||
|
||||
$GeneralFlags = "/Wall /WX /wd4996"
|
||||
$GeneralFlags = "/Wall /WX /wd4996 /wd4464 /wd5105 /std:c11"
|
||||
$LibraryFlags = "/LD"
|
||||
|
||||
$IncludeDirs = Get-ChildItem -Path src -Recurse -Directory -ErrorAction SilentlyContinue -Force | %{$("/I " + '"' + $_.FullName + '"')}
|
||||
$SrcFiles = Get-ChildItem -Path src -Recurse -Filter *.c -ErrorAction SilentlyContinue -Force | %{$('"' + $_.FullName + '"')}
|
||||
$Kernel = (Get-ChildItem Env:OS).Value
|
||||
$Machine = (Get-ChildItem Env:PROCESSOR_ARCHITECTURE).Value
|
||||
$Platform = "${Kernel}_${Machine}"
|
||||
|
||||
$IncludeDirs = "/I src"
|
||||
$SrcFiles = "src/wapp.c"
|
||||
|
||||
$TestIncludeDirs = Get-ChildItem -Path tests -Recurse -Directory -ErrorAction SilentlyContinue -Force | %{$("/I " + '"' + $_.FullName + '"')}
|
||||
$TestSrcFiles = Get-ChildItem -Path tests -Recurse -Filter *.c -ErrorAction SilentlyContinue -Force | %{$('"' + $_.FullName + '"')}
|
||||
|
||||
If ($Release -eq $True) {
|
||||
$GeneralFlags += " /O2 /Og"
|
||||
$BuildType = "release"
|
||||
$GeneralFlags += " /O2 /Og"
|
||||
$BuildType = "release"
|
||||
} Else {
|
||||
$GeneralFlags += " /Zi /Od /fsanitize=address"
|
||||
$BuildType = "debug"
|
||||
$GeneralFlags += " /Zi /Od /fsanitize=address"
|
||||
$BuildType = "debug"
|
||||
}
|
||||
|
||||
$BuildDir = "./libwapp-build/windows-$BuildType"
|
||||
$BuildDir = "./libwapp-build/${Platform}-${BuildType}"
|
||||
$ObjDir = "$BuildDir/objects"
|
||||
$OutDir = "$BuildDir/output"
|
||||
$TestsDir = "$BuildDir/tests"
|
||||
@@ -34,13 +38,16 @@ $TestOutBasename = "wapptest"
|
||||
$TestOutputs = "/Fo:$TestsDir/ /Fe:$TestsDir/$TestOutBasename"
|
||||
|
||||
If (Test-Path $BuildDir) {
|
||||
Remove-Item $BuildDir -Recurse -Force
|
||||
Remove-Item $BuildDir -Recurse -Force
|
||||
}
|
||||
|
||||
mkdir -p $ObjDir > $null
|
||||
mkdir -p $OutDir > $null
|
||||
mkdir -p $TestsDir > $null
|
||||
|
||||
# Run code generation
|
||||
Invoke-Expression "python -m codegen"
|
||||
|
||||
# Build and run tests
|
||||
Invoke-Expression "$Compiler $GeneralFlags $IncludeDirs $TestIncludeDirs $SrcFiles $TestSrcFiles $TestOutputs" -ErrorAction Stop
|
||||
|
||||
@@ -50,9 +57,9 @@ $Status = $LASTEXITCODE
|
||||
Remove-Item $TestsDir -Recurse -Force
|
||||
|
||||
If ($Status -ne 0) {
|
||||
Write-Error "Tests failed"
|
||||
Exit 1
|
||||
Write-Error "Tests failed"
|
||||
Exit 1
|
||||
}
|
||||
|
||||
# Build library
|
||||
Invoke-Expression "$Compiler $GeneralFlags $LibraryFlags $IncludeDirs $SrcFiles $Objects $Outputs"
|
||||
Invoke-Expression "$Compiler $GeneralFlags $LibraryFlags $SrcFiles $Objects $Outputs"
|
||||
|
522
ccodegen/datatypes.c
Normal file
522
ccodegen/datatypes.c
Normal file
@@ -0,0 +1,522 @@
|
||||
// vim:fileencoding=utf-8:foldmethod=marker
|
||||
|
||||
#include "datatypes.h"
|
||||
#include "dbl_list.h"
|
||||
#include "type_enums.h"
|
||||
#include "wapp_core.h"
|
||||
|
||||
#define ERR_MSG "Not enough capacity in dst buffer"
|
||||
#define CFILE_DISCLAIMER "/**\n" \
|
||||
" * THIS FILE IS AUTOMATICALLY GENERATED. ANY MODIFICATIONS TO IT WILL BE OVERWRITTEN.\n" \
|
||||
" */\n\n"
|
||||
|
||||
void cobject_to_string(Str8 *dst, const CObject *object) {
|
||||
wapp_debug_assert(dst != NULL && object != NULL, "`allocator`, `dst` and `object` should not be NULL");
|
||||
|
||||
switch (object->kind) {
|
||||
case COBJECT_CTYPE:
|
||||
ctype_to_string(dst, object->object.c_type);
|
||||
break;
|
||||
case COBJECT_CQUALIFIER:
|
||||
cqualifier_to_string(dst, object->object.c_qualifier);
|
||||
break;
|
||||
case COBJECT_CPOINTERTYPE:
|
||||
cpointertype_to_string(dst, object->object.c_pointertype);
|
||||
break;
|
||||
case COBJECT_CPOINTER:
|
||||
cpointer_to_string(dst, &(object->object.c_pointer));
|
||||
break;
|
||||
case COBJECT_CENUMVAL:
|
||||
cenumval_to_string(dst, &(object->object.c_enumval));
|
||||
break;
|
||||
case COBJECT_CENUM:
|
||||
cenum_to_string(dst, &(object->object.c_enum));
|
||||
break;
|
||||
case COBJECT_CMACRO:
|
||||
cmacro_to_string(dst, &(object->object.c_macro));
|
||||
break;
|
||||
case COBJECT_CSTRUCT:
|
||||
cstruct_to_string(dst, &(object->object.c_struct));
|
||||
break;
|
||||
case COBJECT_CUSERTYPE:
|
||||
cusertype_to_string(dst, &(object->object.c_usertype));
|
||||
break;
|
||||
case COBJECT_CDATATYPE:
|
||||
cdatatype_to_string(dst, &(object->object.c_datatype));
|
||||
break;
|
||||
case COBJECT_CARG:
|
||||
carg_to_string(dst, &(object->object.c_arg));
|
||||
break;
|
||||
case COBJECT_CFUNC:
|
||||
cfunc_to_string(dst, &(object->object.c_func));
|
||||
break;
|
||||
case COBJECT_CINCULDE:
|
||||
cinclude_to_string(dst, &(object->object.c_include));
|
||||
break;
|
||||
case COBJECT_CHEADER:
|
||||
cheader_to_string(dst, &(object->object.c_header));
|
||||
break;
|
||||
case COBJECT_CSOURCE:
|
||||
csource_to_string(dst, &(object->object.c_source));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void ctype_to_string(Str8 *dst, CType ctype) {
|
||||
wapp_runtime_assert(ctypes[ctype].size <= dst->capacity, ERR_MSG);
|
||||
wapp_str8_copy_str8_capped(dst, &ctypes[ctype]);
|
||||
}
|
||||
|
||||
void cqualifier_to_string(Str8 *dst, CQualifier cqualifier) {
|
||||
wapp_runtime_assert(cqualifiers[cqualifier].size <= dst->capacity, ERR_MSG);
|
||||
wapp_str8_copy_str8_capped(dst, &cqualifiers[cqualifier]);
|
||||
}
|
||||
|
||||
void cpointertype_to_string(Str8 *dst, CPointerType cpointertype) {
|
||||
wapp_runtime_assert(cpointertypes[cpointertype].size <= dst->capacity, ERR_MSG);
|
||||
wapp_str8_copy_str8_capped(dst, &cpointertypes[cpointertype]);
|
||||
}
|
||||
|
||||
void cpointer_to_string(Str8 *dst, const CPointer *cpointer) {
|
||||
wapp_debug_assert(dst != NULL && cpointer != NULL, "`dst` and `cpointer` should not be NULL");
|
||||
|
||||
u64 total_size = cpointertypes[cpointer->type].size + cqualifiers[cpointer->qualifier].size;
|
||||
wapp_runtime_assert(total_size <= dst->capacity, ERR_MSG);
|
||||
wapp_str8_format(dst,
|
||||
WAPP_STR8_SPEC WAPP_STR8_SPEC,
|
||||
wapp_str8_varg(cpointertypes[cpointer->type]),
|
||||
wapp_str8_varg(cqualifiers[cpointer->qualifier]));
|
||||
}
|
||||
|
||||
void cenumval_to_string(Str8 *dst, const CEnumVal *cenumval) {
|
||||
wapp_debug_assert(dst != NULL && cenumval != NULL, "`dst` and `cenumval` should not be NULL");
|
||||
|
||||
Str8 tmp = wapp_str8_buf(CCGEN_BUF_TINY);
|
||||
u64 tmp_size = 0;
|
||||
if (cenumval->value != NULL) {
|
||||
wapp_str8_format(&tmp, " = %d", *(cenumval->value));
|
||||
tmp_size = tmp.size;
|
||||
}
|
||||
|
||||
u64 total_size = cenumval->name.size + tmp_size;
|
||||
wapp_runtime_assert(total_size <= dst->capacity, ERR_MSG);
|
||||
wapp_str8_format(dst,
|
||||
WAPP_STR8_SPEC WAPP_STR8_SPEC,
|
||||
wapp_str8_varg(cenumval->name),
|
||||
wapp_str8_varg(tmp));
|
||||
}
|
||||
|
||||
void cenum_to_string(Str8 *dst, const CEnum *cenum) {
|
||||
wapp_debug_assert(dst != NULL && cenum != NULL, "`dst` and `cenum` should not be NULL");
|
||||
|
||||
Str8 header = wapp_str8_buf(CCGEN_BUF_LARGE);
|
||||
Str8 values = wapp_str8_buf(CCGEN_BUF_MAX);
|
||||
Str8 footer = wapp_str8_buf(CCGEN_BUF_LARGE);
|
||||
Str8 tmp = wapp_str8_buf(CCGEN_BUF_LARGE);
|
||||
|
||||
if (cenum->add_typedef) {
|
||||
wapp_str8_copy_cstr_capped(&header, "typedef enum {\n");
|
||||
wapp_str8_format(&footer, "} " WAPP_STR8_SPEC ";\n", wapp_str8_varg(cenum->name));
|
||||
} else {
|
||||
wapp_str8_format(&header, "enum " WAPP_STR8_SPEC " {\n", wapp_str8_varg(cenum->name));
|
||||
wapp_str8_copy_cstr_capped(&footer, "};\n");
|
||||
}
|
||||
|
||||
for (u64 i = 0; i < cenum->values.node_count; ++i) {
|
||||
cenumval_to_string(&tmp, wapp_cenumval_list_get(&(cenum->values), i)->item);
|
||||
// Add 4 for extra characters
|
||||
wapp_runtime_assert(tmp.size + 4 <= values.capacity - values.size, ERR_MSG);
|
||||
wapp_str8_concat_capped(&values, &wapp_str8_lit_ro(" "));
|
||||
wapp_str8_concat_capped(&values, &tmp);
|
||||
wapp_str8_concat_capped(&values, &wapp_str8_lit_ro(",\n"));
|
||||
}
|
||||
|
||||
u64 total_size = header.size + values.size + footer.size;
|
||||
wapp_runtime_assert(total_size <= dst->capacity, ERR_MSG);
|
||||
wapp_str8_format(dst,
|
||||
WAPP_STR8_SPEC WAPP_STR8_SPEC WAPP_STR8_SPEC,
|
||||
wapp_str8_varg(header),
|
||||
wapp_str8_varg(values),
|
||||
wapp_str8_varg(footer));
|
||||
}
|
||||
|
||||
void cmacro_to_string(Str8 *dst, const CMacro *cmacro) {
|
||||
wapp_debug_assert(dst != NULL && cmacro != NULL, "`dst` and `cmacro` should not be NULL");
|
||||
|
||||
Str8 def = wapp_str8_lit("#define ");
|
||||
u64 total_size = def.size + cmacro->name.size + cmacro->value.size + 1; // Add 1 for newline
|
||||
wapp_runtime_assert(total_size <= dst->capacity, ERR_MSG);
|
||||
wapp_str8_format(dst,
|
||||
WAPP_STR8_SPEC WAPP_STR8_SPEC " " WAPP_STR8_SPEC "\n",
|
||||
wapp_str8_varg(def),
|
||||
wapp_str8_varg(cmacro->name),
|
||||
wapp_str8_varg(cmacro->value));
|
||||
}
|
||||
|
||||
void cstruct_to_string(Str8 *dst, const CStruct *cstruct) {
|
||||
wapp_debug_assert(dst != NULL && cstruct != NULL, "`dst` and `cstruct` should not be NULL");
|
||||
|
||||
Str8 declaration = wapp_str8_buf(CCGEN_BUF_LARGE);
|
||||
Str8 definition = wapp_str8_buf(CCGEN_BUF_MAX);
|
||||
|
||||
declare_cstruct(&declaration, cstruct);
|
||||
define_cstruct(&definition, cstruct);
|
||||
|
||||
u64 total_size = declaration.size + definition.size;
|
||||
wapp_runtime_assert(total_size <= dst->capacity, ERR_MSG);
|
||||
wapp_str8_format(dst, WAPP_STR8_SPEC WAPP_STR8_SPEC,
|
||||
wapp_str8_varg(declaration), wapp_str8_varg(definition));
|
||||
}
|
||||
|
||||
void declare_cstruct(Str8 *dst, const CStruct *cstruct) {
|
||||
wapp_debug_assert(dst != NULL && cstruct != NULL, "`dst` and `cstruct` should not be NULL");
|
||||
|
||||
Str8 tmp = wapp_str8_buf(CCGEN_BUF_MAX);
|
||||
wapp_str8_format(&tmp,
|
||||
"typedef struct " WAPP_STR8_SPEC " " WAPP_STR8_SPEC ";\n",
|
||||
wapp_str8_varg(cstruct->name),
|
||||
wapp_str8_varg(cstruct->typedef_name.size > 0 ? cstruct->typedef_name : cstruct->name));
|
||||
|
||||
wapp_runtime_assert(tmp.size <= dst->capacity, ERR_MSG);
|
||||
wapp_str8_copy_str8_capped(dst, &tmp);
|
||||
}
|
||||
|
||||
void define_cstruct(Str8 *dst, const CStruct *cstruct) {
|
||||
wapp_debug_assert(dst != NULL && cstruct != NULL, "`dst` and `cstruct` should not be NULL");
|
||||
|
||||
Str8 definition = wapp_str8_buf(CCGEN_BUF_LARGE);
|
||||
Str8 args = wapp_str8_buf(CCGEN_BUF_MAX);
|
||||
Str8 footer = wapp_str8_lit_ro("};\n");
|
||||
Str8 tmp = wapp_str8_buf(CCGEN_BUF_MEDIUM);
|
||||
|
||||
wapp_str8_format(&definition, "struct " WAPP_STR8_SPEC " {\n", wapp_str8_varg(cstruct->name));
|
||||
|
||||
for (u64 i = 0; i < cstruct->args.node_count; ++i) {
|
||||
carg_to_string(&tmp, wapp_carg_list_get(&(cstruct->args), i)->item);
|
||||
// Add 4 for extra characters
|
||||
wapp_runtime_assert(tmp.size + 4 <= args.capacity - args.size, ERR_MSG);
|
||||
wapp_str8_concat_capped(&args, &wapp_str8_lit_ro(" "));
|
||||
wapp_str8_concat_capped(&args, &tmp);
|
||||
wapp_str8_concat_capped(&args, &wapp_str8_lit_ro(";\n"));
|
||||
}
|
||||
|
||||
u64 total_size = definition.size + args.size + footer.size;
|
||||
wapp_runtime_assert(total_size <= dst->capacity, ERR_MSG);
|
||||
wapp_str8_format(dst,
|
||||
WAPP_STR8_SPEC WAPP_STR8_SPEC WAPP_STR8_SPEC,
|
||||
wapp_str8_varg(definition),
|
||||
wapp_str8_varg(args),
|
||||
wapp_str8_varg(footer));
|
||||
}
|
||||
|
||||
void cusertype_to_string(Str8 *dst, const CUserType *cusertype) {
|
||||
wapp_debug_assert(dst != NULL && cusertype != NULL, "`dst` and `cusertype` should not be NULL");
|
||||
|
||||
switch (cusertype->kind) {
|
||||
case CUSERTYPE_CENUM:
|
||||
cenum_to_string(dst, &(cusertype->type.c_enum));
|
||||
break;
|
||||
case CUSERTYPE_CSTRUCT:
|
||||
cstruct_to_string(dst, &(cusertype->type.c_struct));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void cdatatype_to_string(Str8 *dst, const CDataType *cdatatype) {
|
||||
wapp_debug_assert(dst != NULL && cdatatype != NULL, "`dst` and `cdatatype` should not be NULL");
|
||||
|
||||
switch (cdatatype->kind) {
|
||||
case CDATATYPE_CTYPE:
|
||||
ctype_to_string(dst, cdatatype->type.c_type);
|
||||
break;
|
||||
case CDATATYPE_CUSERTYPE:
|
||||
cusertype_to_string(dst, &(cdatatype->type.c_usertype));
|
||||
break;
|
||||
case CDATATYPE_STR:
|
||||
wapp_runtime_assert(cdatatype->type.str.size <= dst->capacity, ERR_MSG);
|
||||
wapp_str8_copy_str8_capped(dst, &(cdatatype->type.str));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void carg_to_string(Str8 *dst, const CArg *carg) {
|
||||
wapp_debug_assert(dst != NULL && carg != NULL, "`dst` and `carg` should not be NULL");
|
||||
|
||||
Str8 qualifier = wapp_str8_buf(CCGEN_BUF_MEDIUM);
|
||||
Str8 type = wapp_str8_buf(CCGEN_BUF_LARGE);
|
||||
Str8 pointer = wapp_str8_buf(CCGEN_BUF_MEDIUM);
|
||||
Str8 array = wapp_str8_buf(CCGEN_BUF_MEDIUM);
|
||||
|
||||
cqualifier_to_string(&qualifier, carg->qualifier);
|
||||
cdatatype_to_string(&type, &(carg->type));
|
||||
wapp_str8_concat_capped(&type, &wapp_str8_lit_ro(" "));
|
||||
cpointer_to_string(&pointer, &(carg->pointer));
|
||||
if (carg->is_array) { wapp_str8_copy_cstr_capped(&array, "[]"); }
|
||||
|
||||
u64 total_size = qualifier.size + type.size + pointer.size + array.size + carg->name.size;
|
||||
wapp_runtime_assert(total_size <= dst->capacity, ERR_MSG);
|
||||
wapp_str8_format(dst, WAPP_STR8_SPEC WAPP_STR8_SPEC WAPP_STR8_SPEC WAPP_STR8_SPEC WAPP_STR8_SPEC,
|
||||
wapp_str8_varg(qualifier), wapp_str8_varg(type), wapp_str8_varg(pointer),
|
||||
wapp_str8_varg(carg->name), wapp_str8_varg(array));
|
||||
}
|
||||
|
||||
void cfunc_to_string(Str8 *dst, const CFunc *cfunc) {
|
||||
wapp_debug_assert(dst != NULL && cfunc != NULL, "`dst` and `cfunc` should not be NULL");
|
||||
|
||||
Str8 qualifiers = wapp_str8_buf(CCGEN_BUF_LARGE);
|
||||
Str8 args = wapp_str8_buf(CCGEN_BUF_LARGE);
|
||||
Str8 ret_type = wapp_str8_buf(CCGEN_BUF_SMALL);
|
||||
Str8 pointer = wapp_str8_buf(CCGEN_BUF_SMALL);
|
||||
Str8 tmp = wapp_str8_buf(CCGEN_BUF_MEDIUM);
|
||||
CQualifier *qf = NULL;
|
||||
CArg *arg = NULL;
|
||||
|
||||
for (u64 i = 0; i < cfunc->qualifiers.node_count; ++i) {
|
||||
qf = wapp_cqualifier_list_get(&(cfunc->qualifiers), i)->item;
|
||||
if (*qf == CQUALIFIER_NONE) { continue; }
|
||||
|
||||
cqualifier_to_string(&tmp, *qf);
|
||||
|
||||
wapp_runtime_assert(tmp.size + 1 <= qualifiers.capacity - qualifiers.size, ERR_MSG);
|
||||
if (qualifiers.size > 0) { wapp_str8_concat_capped(&qualifiers, &wapp_str8_lit_ro(" ")); }
|
||||
|
||||
wapp_str8_concat_capped(&qualifiers, &tmp);
|
||||
}
|
||||
|
||||
for (u64 i = 0; i < cfunc->args.node_count; ++i) {
|
||||
arg = wapp_carg_list_get(&(cfunc->args), i)->item;
|
||||
carg_to_string(&tmp, arg);
|
||||
|
||||
wapp_runtime_assert(tmp.size + 2 <= args.capacity - args.size, ERR_MSG);
|
||||
wapp_str8_concat_capped(&args, &tmp);
|
||||
if (i + 1 < cfunc->args.node_count) { wapp_str8_concat_capped(&args, &wapp_str8_lit_ro(", ")); }
|
||||
}
|
||||
|
||||
cdatatype_to_string(&ret_type, &(cfunc->ret_type));
|
||||
cpointer_to_string(&pointer, &(cfunc->pointer));
|
||||
|
||||
u64 total_size = cfunc->name.size + qualifiers.size + args.size + ret_type.size + pointer.size + 4;
|
||||
wapp_runtime_assert(total_size <= dst->capacity, ERR_MSG);
|
||||
wapp_str8_format(dst,
|
||||
WAPP_STR8_SPEC WAPP_STR8_SPEC " " WAPP_STR8_SPEC WAPP_STR8_SPEC "(" WAPP_STR8_SPEC ")",
|
||||
wapp_str8_varg(qualifiers),
|
||||
wapp_str8_varg(ret_type),
|
||||
wapp_str8_varg(pointer),
|
||||
wapp_str8_varg(cfunc->name),
|
||||
wapp_str8_varg(args));
|
||||
}
|
||||
|
||||
void declare_cfunc(Str8 *dst, const CFunc *cfunc) {
|
||||
wapp_debug_assert(dst != NULL && cfunc != NULL, "`dst` and `cfunc` should not be NULL");
|
||||
|
||||
Str8 tmp = wapp_str8_buf(CCGEN_BUF_MAX);
|
||||
cfunc_to_string(&tmp, cfunc);
|
||||
|
||||
wapp_runtime_assert(tmp.size + 2 <= dst->capacity, ERR_MSG);
|
||||
wapp_str8_format(dst, WAPP_STR8_SPEC ";\n", wapp_str8_varg(tmp));
|
||||
}
|
||||
|
||||
void define_cfunc(Str8 *dst, const CFunc *cfunc) {
|
||||
wapp_debug_assert(dst != NULL && cfunc != NULL, "`dst` and `cfunc` should not be NULL");
|
||||
|
||||
Str8 tmp = wapp_str8_buf(CCGEN_BUF_MAX);
|
||||
cfunc_to_string(&tmp, cfunc);
|
||||
|
||||
wapp_runtime_assert(tmp.size + cfunc->body.size + 8 <= dst->capacity, ERR_MSG);
|
||||
wapp_str8_format(dst, WAPP_STR8_SPEC " {\n" WAPP_STR8_SPEC "\n}\n\n",
|
||||
wapp_str8_varg(tmp), wapp_str8_varg(cfunc->body));
|
||||
}
|
||||
|
||||
void cinclude_to_string(Str8 *dst, const CInclude *cinclude) {
|
||||
wapp_debug_assert(dst != NULL && cinclude != NULL, "`dst` and `cinclude` should not be NULL");
|
||||
|
||||
Str8 header_str = wapp_str8_buf(CCGEN_BUF_LARGE);
|
||||
if (!cheaderinclude_to_string(&header_str, &(cinclude->header))) { return; }
|
||||
|
||||
Str8 inc = wapp_str8_lit("#include ");
|
||||
Str8 open_symbol = wapp_str8_buf(CCGEN_BUF_MIN);
|
||||
Str8 close_symbol = wapp_str8_buf(CCGEN_BUF_MIN);
|
||||
|
||||
if (cinclude->is_local) {
|
||||
wapp_str8_concat_capped(&open_symbol, &wapp_str8_lit_ro("\""));
|
||||
wapp_str8_concat_capped(&close_symbol, &wapp_str8_lit_ro("\""));
|
||||
if (cinclude->same_dir) { wapp_str8_concat_capped(&open_symbol, &wapp_str8_lit_ro("./")); }
|
||||
} else {
|
||||
wapp_str8_concat_capped(&open_symbol, &wapp_str8_lit_ro("<"));
|
||||
wapp_str8_concat_capped(&close_symbol, &wapp_str8_lit_ro(">"));
|
||||
}
|
||||
|
||||
u64 total_size = header_str.size + inc.size + open_symbol.size + close_symbol.size;
|
||||
wapp_runtime_assert(total_size <= dst->capacity, ERR_MSG);
|
||||
wapp_str8_format(dst,
|
||||
WAPP_STR8_SPEC WAPP_STR8_SPEC WAPP_STR8_SPEC WAPP_STR8_SPEC "\n",
|
||||
wapp_str8_varg(inc),
|
||||
wapp_str8_varg(open_symbol),
|
||||
wapp_str8_varg(header_str),
|
||||
wapp_str8_varg(close_symbol));
|
||||
}
|
||||
|
||||
void cheader_to_string(Str8 *dst, const CHeader *cheader) {
|
||||
wapp_debug_assert(dst != NULL && cheader != NULL, "`dst` and `cheader` should not be NULL");
|
||||
|
||||
Allocator arena = wapp_mem_arena_allocator_init(MB(64));
|
||||
Str8 *output = wapp_str8_alloc_buf(&arena, KB(32));
|
||||
wapp_runtime_assert(output != NULL, "Failed to allocate buffer");
|
||||
|
||||
Str8 header_guard_name = wapp_str8_buf(CCGEN_BUF_SMALL);
|
||||
Str8 tmp = wapp_str8_buf(CCGEN_BUF_MAX);
|
||||
|
||||
// ADD HEADER GUARD AND START C LINKAGE
|
||||
wapp_str8_to_upper(&header_guard_name, &(cheader->name));
|
||||
wapp_str8_concat_capped(&header_guard_name, &wapp_str8_lit_ro("_H"));
|
||||
wapp_str8_format(&tmp, "#ifndef " WAPP_STR8_SPEC "\n#define " WAPP_STR8_SPEC "\n\n"
|
||||
"#ifdef WAPP_PLATFORM_CPP\nBEGIN_C_LINKAGE\n#endif // !WAPP_PLATFORM_CPP\n\n",
|
||||
wapp_str8_varg(header_guard_name), wapp_str8_varg(header_guard_name));
|
||||
wapp_str8_alloc_concat(&arena, output, &tmp);
|
||||
|
||||
for (u64 i = 0; i < cheader->includes.node_count; ++i) {
|
||||
cinclude_to_string(&tmp, wapp_cinclude_list_get(&(cheader->includes), i)->item);
|
||||
wapp_str8_alloc_concat(&arena, output, &tmp);
|
||||
}
|
||||
if (cheader->includes.node_count > 0) { wapp_str8_alloc_concat(&arena, output, &wapp_str8_lit_ro("\n")); }
|
||||
|
||||
for (u64 i = 0; i < cheader->macros.node_count; ++i) {
|
||||
cmacro_to_string(&tmp, wapp_cmacro_list_get(&(cheader->macros), i)->item);
|
||||
wapp_str8_alloc_concat(&arena, output, &tmp);
|
||||
}
|
||||
if (cheader->macros.node_count > 0) { wapp_str8_alloc_concat(&arena, output, &wapp_str8_lit_ro("\n")); }
|
||||
|
||||
if (cheader->cpp_macros.node_count > 0) {
|
||||
wapp_str8_alloc_concat(&arena, output, &wapp_str8_lit_ro("#ifdef WAPP_PLATFORM_CPP\n"));
|
||||
|
||||
for (u64 i = 0; i < cheader->cpp_macros.node_count; ++i) {
|
||||
cmacro_to_string(&tmp, wapp_cmacro_list_get(&(cheader->cpp_macros), i)->item);
|
||||
wapp_str8_alloc_concat(&arena, output, &tmp);
|
||||
}
|
||||
|
||||
wapp_str8_alloc_concat(&arena, output, &wapp_str8_lit_ro("#else\n"));
|
||||
|
||||
for (u64 i = 0; i < cheader->c_macros.node_count; ++i) {
|
||||
cmacro_to_string(&tmp, wapp_cmacro_list_get(&(cheader->c_macros), i)->item);
|
||||
wapp_str8_alloc_concat(&arena, output, &tmp);
|
||||
}
|
||||
|
||||
wapp_str8_alloc_concat(&arena, output, &wapp_str8_lit_ro("#endif // !WAPP_PLATFORM_CPP\n\n"));
|
||||
}
|
||||
|
||||
for (u64 i = 0; i < cheader->decl_types.node_count; ++i) {
|
||||
declare_cstruct(&tmp, wapp_cstruct_list_get(&(cheader->decl_types), i)->item);
|
||||
wapp_str8_alloc_concat(&arena, output, &tmp);
|
||||
}
|
||||
if (cheader->decl_types.node_count > 0) { wapp_str8_alloc_concat(&arena, output, &wapp_str8_lit_ro("\n")); }
|
||||
|
||||
for (u64 i = 0; i < cheader->types.node_count; ++i) {
|
||||
cusertype_to_string(&tmp, wapp_cusertype_list_get(&(cheader->types), i)->item);
|
||||
wapp_str8_concat_capped(&tmp, &wapp_str8_lit_ro("\n"));
|
||||
wapp_str8_alloc_concat(&arena, output, &tmp);
|
||||
}
|
||||
|
||||
for (u64 i = 0; i < cheader->funcs.node_count; ++i) {
|
||||
declare_cfunc(&tmp, wapp_cfunc_list_get(&(cheader->funcs), i)->item);
|
||||
wapp_str8_alloc_concat(&arena, output, &tmp);
|
||||
}
|
||||
|
||||
// END C LINKAGE AND CLOSE HEADER GUARD
|
||||
wapp_str8_format(&tmp, "\n#ifdef WAPP_PLATFORM_CPP\nEND_C_LINKAGE\n#endif // !WAPP_PLATFORM_CPP\n\n"
|
||||
"#endif // !" WAPP_STR8_SPEC "\n", wapp_str8_varg(header_guard_name));
|
||||
wapp_str8_alloc_concat(&arena, output, &tmp);
|
||||
|
||||
wapp_runtime_assert(output->size <= dst->capacity, ERR_MSG);
|
||||
wapp_str8_copy_str8_capped(dst, output);
|
||||
|
||||
wapp_mem_arena_allocator_destroy(&arena);
|
||||
}
|
||||
|
||||
void csource_to_string(Str8 *dst, const CSource *csource) {
|
||||
wapp_debug_assert(dst != NULL && csource != NULL, "`dst` and `csource` should not be NULL");
|
||||
|
||||
Allocator arena = wapp_mem_arena_allocator_init(MB(64));
|
||||
Str8 *output = wapp_str8_alloc_buf(&arena, KB(32));
|
||||
Str8 *internal_funcs_def = wapp_str8_alloc_buf(&arena, KB(16));
|
||||
wapp_runtime_assert(output != NULL && internal_funcs_def != NULL, "Failed to allocate buffer");
|
||||
|
||||
Str8 tmp = wapp_str8_buf(CCGEN_BUF_MAX);
|
||||
|
||||
for (u64 i = 0; i < csource->includes.node_count; ++i) {
|
||||
cinclude_to_string(&tmp, wapp_cinclude_list_get(&(csource->includes), i)->item);
|
||||
wapp_str8_alloc_concat(&arena, output, &tmp);
|
||||
}
|
||||
if (csource->includes.node_count > 0) { wapp_str8_alloc_concat(&arena, output, &wapp_str8_lit_ro("\n")); }
|
||||
|
||||
for (u64 i = 0; i < csource->macros.node_count; ++i) {
|
||||
cmacro_to_string(&tmp, wapp_cmacro_list_get(&(csource->macros), i)->item);
|
||||
wapp_str8_alloc_concat(&arena, output, &tmp);
|
||||
}
|
||||
if (csource->macros.node_count > 0) { wapp_str8_alloc_concat(&arena, output, &wapp_str8_lit_ro("\n")); }
|
||||
|
||||
for (u64 i = 0; i < csource->decl_types.node_count; ++i) {
|
||||
declare_cstruct(&tmp, wapp_cstruct_list_get(&(csource->decl_types), i)->item);
|
||||
wapp_str8_alloc_concat(&arena, output, &tmp);
|
||||
}
|
||||
if (csource->decl_types.node_count > 0) { wapp_str8_alloc_concat(&arena, output, &wapp_str8_lit_ro("\n")); }
|
||||
|
||||
for (u64 i = 0; i < csource->types.node_count; ++i) {
|
||||
cusertype_to_string(&tmp, wapp_cusertype_list_get(&(csource->types), i)->item);
|
||||
wapp_str8_concat_capped(&tmp, &wapp_str8_lit_ro("\n"));
|
||||
wapp_str8_alloc_concat(&arena, output, &tmp);
|
||||
}
|
||||
|
||||
Str8RO _internal = wapp_str8_lit_ro("internal ");
|
||||
for (u64 i = 0; i < csource->internal_funcs.node_count; ++i) {
|
||||
declare_cfunc(&tmp, wapp_cfunc_list_get(&(csource->internal_funcs), i)->item);
|
||||
wapp_str8_alloc_concat(&arena, output, &_internal);
|
||||
wapp_str8_alloc_concat(&arena, output, &tmp);
|
||||
|
||||
define_cfunc(&tmp, wapp_cfunc_list_get(&(csource->internal_funcs), i)->item);
|
||||
wapp_str8_alloc_concat(&arena, internal_funcs_def, &_internal);
|
||||
wapp_str8_alloc_concat(&arena, internal_funcs_def, &tmp);
|
||||
}
|
||||
if (csource->internal_funcs.node_count > 0) { wapp_str8_alloc_concat(&arena, output, &wapp_str8_lit_ro("\n")); }
|
||||
|
||||
for (u64 i = 0; i < csource->funcs.node_count; ++i) {
|
||||
define_cfunc(&tmp, wapp_cfunc_list_get(&(csource->funcs), i)->item);
|
||||
wapp_str8_alloc_concat(&arena, output, &tmp);
|
||||
}
|
||||
|
||||
wapp_runtime_assert(output->size + internal_funcs_def->size <= dst->capacity, ERR_MSG);
|
||||
wapp_str8_copy_str8_capped(dst, output);
|
||||
wapp_str8_concat_capped(dst, internal_funcs_def);
|
||||
|
||||
wapp_mem_arena_allocator_destroy(&arena);
|
||||
}
|
||||
|
||||
b32 cheaderinclude_to_string(Str8 *dst, const CHeaderInclude *cheaderinclude) {
|
||||
wapp_debug_assert(dst != NULL && cheaderinclude != NULL, "`dst` and `cheaderinclude` should not be NULL");
|
||||
|
||||
switch (cheaderinclude->kind) {
|
||||
case C_HEADER_INCLUDE_STR:
|
||||
wapp_runtime_assert(cheaderinclude->header.name.size <= dst->capacity, ERR_MSG);
|
||||
wapp_str8_format(dst, WAPP_STR8_SPEC, wapp_str8_varg(cheaderinclude->header.name));
|
||||
return true;
|
||||
case C_HEADER_INCLUDE_HEADER:
|
||||
// Take extension into account
|
||||
wapp_runtime_assert(cheaderinclude->header.header.name.size + 2 <= dst->capacity, ERR_MSG);
|
||||
wapp_str8_format(
|
||||
dst,
|
||||
WAPP_STR8_SPEC ".%s",
|
||||
wapp_str8_varg(cheaderinclude->header.header.name),
|
||||
cheaderinclude->header.header.extension == CFILE_EXT_H ? "h" : "c"
|
||||
);
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
280
ccodegen/datatypes.h
Normal file
280
ccodegen/datatypes.h
Normal file
@@ -0,0 +1,280 @@
|
||||
// vim:fileencoding=utf-8:foldmethod=marker
|
||||
|
||||
#ifndef DATATYPES_H
|
||||
#define DATATYPES_H
|
||||
|
||||
#include "wapp_core.h"
|
||||
#include "dbl_list.h"
|
||||
#include "type_enums.h"
|
||||
|
||||
#ifndef CCGEN_BUF_MIN
|
||||
#define CCGEN_BUF_MIN 16
|
||||
#endif // !CCGEN_BUF_MIN
|
||||
|
||||
#ifndef CCGEN_BUF_TINY
|
||||
#define CCGEN_BUF_TINY 32
|
||||
#endif // !CCGEN_BUF_TINY
|
||||
|
||||
#ifndef CCGEN_BUF_SMALL
|
||||
#define CCGEN_BUF_SMALL 512
|
||||
#endif // !CCGEN_BUF_SMALL
|
||||
|
||||
#ifndef CCGEN_BUF_MEDIUM
|
||||
#define CCGEN_BUF_MEDIUM 1024
|
||||
#endif // !CCGEN_BUF_MEDIUM
|
||||
|
||||
#ifndef CCGEN_BUF_LARGE
|
||||
#define CCGEN_BUF_LARGE 4096
|
||||
#endif // !CCGEN_BUF_LARGE
|
||||
|
||||
#ifndef CCGEN_BUF_MAX
|
||||
#define CCGEN_BUF_MAX 8192
|
||||
#endif // !CCGEN_BUF_MAX
|
||||
|
||||
#define CENUM(NAME, VALUES, TYPEDEF) ((CEnum){ .name = (NAME), .values = (VALUES), .add_typedef = (TYPEDEF) })
|
||||
#define CSTRUCT(NAME, ARGS, TYPEDEF_NAME_PTR) ((CStruct){ .name = (NAME), .args = (ARGS), .typedef_name = (TYPEDEF_NAME_PTR) })
|
||||
|
||||
#define CUSERTYPE_ENUM(ENUM) ((CUserType){ .kind = CUSERTYPE_CENUM, .type.c_enum = ENUM })
|
||||
#define CUSERTYPE_STRUCT(STRUCT) ((CUserType){ .kind = CUSERTYPE_CSTRUCT, .type.c_struct = STRUCT })
|
||||
|
||||
#define CDATATYPE_CTYPE(VALUE) ((CDataType){ .kind = CDATATYPE_CTYPE, .type.c_type = (VALUE) })
|
||||
#define CDATATYPE_USERTYPE(USERTYPE) ((CDataType){ .kind = CDATATYPE_CUSERTYPE, .type.c_usertype = (USERTYPE) })
|
||||
#define CDATATYPE_STR(STR) ((CDataType){ .kind = CDATATYPE_STR, .type.str = (STR) })
|
||||
|
||||
#define CHEADERINCLUDE_STR(NAME) ((CHeaderInclude){ .kind = C_HEADER_INCLUDE_STR, .header.name = (NAME) })
|
||||
#define CHEADERINCLUDE_CHEADER(CHEADER) ((CHeaderInclude){ .kind = C_HEADER_INCLUDE_HEADER, .header.header = (CHEADER) })
|
||||
|
||||
#define COBJECT_TYPE(VALUE) \
|
||||
((CObject){ .kind = COBJECT_CTYPE, .object.c_type = (VALUE) })
|
||||
#define COBJECT_QUALIFIER(VALUE) \
|
||||
((CObject){ .kind = COBJECT_CQUALIFIER, .object.c_qualifier = (VALUE) })
|
||||
#define COBJECT_POINTERTYPE(VALUE) \
|
||||
((CObject){ .kind = COBJECT_CPOINTERTYPE, .object.c_pointertype = (VALUE) })
|
||||
#define COBJECT_POINTER(CPOINTER) \
|
||||
((CObject){ .kind = COBJECT_CPOINTER, .object.c_pointer = (CPOINTER) })
|
||||
#define COBJECT_ENUMVAL(CENUMVAL) \
|
||||
((CObject){ .kind = COBJECT_CENUMVAL, .object.c_enumval = (CENUMVAL) })
|
||||
#define COBJECT_ENUM(ENUM) \
|
||||
((CObject){ .kind = COBJECT_CENUM, .object.c_enum = (ENUM) })
|
||||
#define COBJECT_MACRO(CMACRO) \
|
||||
((CObject){ .kind = COBJECT_CMACRO, .object.c_macro = (CMACRO) })
|
||||
#define COBJECT_STRUCT(STRUCT) \
|
||||
((CObject){ .kind = COBJECT_CSTRUCT, .object.c_struct = STRUCT })
|
||||
#define COBJECT_USERTYPE(USERTYPE) \
|
||||
((CObject){ .kind = COBJECT_CUSERTYPE, .object.c_usertype = (USERTYPE) })
|
||||
#define COBJECT_DATATYPE(DATATYPE) \
|
||||
((CObject){ .kind = COBJECT_CDATATYPE, .object.c_datatype = (DATATYPE) })
|
||||
#define COBJECT_ARG(CARG) \
|
||||
((CObject){ .kind = COBJECT_CARG, .object.c_arg = (CARG) })
|
||||
#define COBJECT_FUNC(CFUNC) \
|
||||
((CObject){ .kind = COBJECT_CFUNC, .object.c_func = (CFUNC) })
|
||||
#define COBJECT_INCULDE(CINCLUDE) \
|
||||
((CObject){ .kind = COBJECT_CINCULDE, .object.c_include = (CINCLUDE) })
|
||||
#define COBJECT_HEADER(CHEADER) \
|
||||
((CObject){ .kind = COBJECT_CHEADER, .object.c_header = (CHEADER) })
|
||||
#define COBJECT_SOURCE(CSOURCE) \
|
||||
((CObject){ .kind = COBJECT_CSOURCE, .object.c_source = (CSOURCE) })
|
||||
|
||||
typedef enum {
|
||||
CUSERTYPE_CENUM,
|
||||
CUSERTYPE_CSTRUCT,
|
||||
|
||||
COUNT_CUSERTYPEKIND,
|
||||
} CUserTypeKind;
|
||||
|
||||
typedef enum {
|
||||
CDATATYPE_CTYPE,
|
||||
CDATATYPE_CUSERTYPE,
|
||||
CDATATYPE_STR,
|
||||
|
||||
COUNT_CDATATYPEKIND,
|
||||
} CDataTypeKind;
|
||||
|
||||
typedef enum {
|
||||
CFILE_EXT_H,
|
||||
CFILE_EXT_C,
|
||||
|
||||
COUNT_CFILE_EXT,
|
||||
} CFileExtension;
|
||||
|
||||
typedef enum {
|
||||
C_HEADER_INCLUDE_STR,
|
||||
C_HEADER_INCLUDE_HEADER,
|
||||
|
||||
COUNT_CHEADERINCLUDEKIND,
|
||||
} CHeaderIncludeKind;
|
||||
|
||||
typedef enum {
|
||||
COBJECT_CTYPE,
|
||||
COBJECT_CQUALIFIER,
|
||||
COBJECT_CPOINTERTYPE,
|
||||
COBJECT_CPOINTER,
|
||||
COBJECT_CENUMVAL,
|
||||
COBJECT_CENUM,
|
||||
COBJECT_CMACRO,
|
||||
COBJECT_CSTRUCT,
|
||||
COBJECT_CUSERTYPE,
|
||||
COBJECT_CDATATYPE,
|
||||
COBJECT_CARG,
|
||||
COBJECT_CFUNC,
|
||||
COBJECT_CINCULDE,
|
||||
COBJECT_CHEADER,
|
||||
COBJECT_CSOURCE,
|
||||
|
||||
COUNT_COBJECTKIND,
|
||||
} CObjectKind;
|
||||
|
||||
typedef struct cpointer CPointer;
|
||||
typedef struct cenumval CEnumVal;
|
||||
typedef struct cenum CEnum;
|
||||
typedef struct cmacro CMacro;
|
||||
typedef struct cstruct CStruct;
|
||||
typedef struct cusertype CUserType;
|
||||
typedef struct cdatatype CDataType;
|
||||
typedef struct carg CArg;
|
||||
typedef struct cfunc CFunc;
|
||||
typedef struct cheader_include CHeaderInclude;
|
||||
typedef struct cinclude CInclude;
|
||||
typedef struct cheader CHeader;
|
||||
typedef struct csource CSource;
|
||||
typedef struct cobject CObject;
|
||||
|
||||
struct cpointer {
|
||||
CPointerType type;
|
||||
CQualifier qualifier;
|
||||
};
|
||||
|
||||
struct cenumval {
|
||||
Str8 name;
|
||||
i32 *value;
|
||||
};
|
||||
|
||||
struct cenum {
|
||||
Str8 name;
|
||||
CEnumValList values;
|
||||
b32 add_typedef;
|
||||
};
|
||||
|
||||
struct cmacro {
|
||||
Str8 name;
|
||||
Str8 value;
|
||||
};
|
||||
|
||||
struct cstruct {
|
||||
Str8 name;
|
||||
CArgList args;
|
||||
Str8 typedef_name;
|
||||
};
|
||||
|
||||
struct cusertype {
|
||||
CUserTypeKind kind;
|
||||
union {
|
||||
CEnum c_enum;
|
||||
CStruct c_struct;
|
||||
} type;
|
||||
};
|
||||
|
||||
struct cdatatype {
|
||||
CDataTypeKind kind;
|
||||
union {
|
||||
CType c_type;
|
||||
CUserType c_usertype;
|
||||
Str8 str;
|
||||
} type;
|
||||
};
|
||||
|
||||
struct carg {
|
||||
Str8 name;
|
||||
CDataType type;
|
||||
CPointer pointer;
|
||||
CQualifier qualifier;
|
||||
b32 is_array;
|
||||
};
|
||||
|
||||
struct cfunc {
|
||||
Str8 name;
|
||||
CDataType ret_type;
|
||||
CArgList args;
|
||||
Str8 body;
|
||||
CPointer pointer;
|
||||
CQualifierList qualifiers;
|
||||
};
|
||||
|
||||
#define CFILE_ARGS \
|
||||
Str8 name; \
|
||||
CFileExtension extension; \
|
||||
CIncludeList includes; \
|
||||
CUserTypeList types; \
|
||||
CFuncList funcs; \
|
||||
CStructList decl_types; \
|
||||
CMacroList macros; \
|
||||
CMacroList c_macros; \
|
||||
CMacroList cpp_macros \
|
||||
|
||||
struct cheader {
|
||||
CFILE_ARGS;
|
||||
};
|
||||
|
||||
struct csource {
|
||||
CFILE_ARGS;
|
||||
CFuncList internal_funcs;
|
||||
};
|
||||
|
||||
struct cheader_include {
|
||||
CHeaderIncludeKind kind;
|
||||
union {
|
||||
Str8 name;
|
||||
CHeader header;
|
||||
} header;
|
||||
};
|
||||
|
||||
struct cinclude {
|
||||
CHeaderInclude header;
|
||||
b32 is_local;
|
||||
b32 same_dir;
|
||||
};
|
||||
|
||||
struct cobject {
|
||||
CObjectKind kind;
|
||||
union {
|
||||
CType c_type;
|
||||
CQualifier c_qualifier;
|
||||
CPointerType c_pointertype;
|
||||
CPointer c_pointer;
|
||||
CEnumVal c_enumval;
|
||||
CEnum c_enum;
|
||||
CMacro c_macro;
|
||||
CStruct c_struct;
|
||||
CUserType c_usertype;
|
||||
CDataType c_datatype;
|
||||
CArg c_arg;
|
||||
CFunc c_func;
|
||||
CInclude c_include;
|
||||
CHeader c_header;
|
||||
CSource c_source;
|
||||
} object;
|
||||
};
|
||||
|
||||
void cobject_to_string(Str8 *dst, const CObject *object);
|
||||
void ctype_to_string(Str8 *dst, CType ctype);
|
||||
void cqualifier_to_string(Str8 *dst, CQualifier cqualifier);
|
||||
void cpointertype_to_string(Str8 *dst, CPointerType cpointertype);
|
||||
void cpointer_to_string(Str8 *dst, const CPointer *cpointer);
|
||||
void cenumval_to_string(Str8 *dst, const CEnumVal *cenumval);
|
||||
void cenum_to_string(Str8 *dst, const CEnum *cenum);
|
||||
void cmacro_to_string(Str8 *dst, const CMacro *cmacro);
|
||||
void cstruct_to_string(Str8 *dst, const CStruct *cstruct);
|
||||
void declare_cstruct(Str8 *dst, const CStruct *cstruct);
|
||||
void define_cstruct(Str8 *dst, const CStruct *cstruct);
|
||||
void cusertype_to_string(Str8 *dst, const CUserType *cusertype);
|
||||
void cdatatype_to_string(Str8 *dst, const CDataType *cdatatype);
|
||||
void carg_to_string(Str8 *dst, const CArg *carg);
|
||||
void cfunc_to_string(Str8 *dst, const CFunc *cfunc);
|
||||
void declare_cfunc(Str8 *dst, const CFunc *cfunc);
|
||||
void define_cfunc(Str8 *dst, const CFunc *cfunc);
|
||||
void cinclude_to_string(Str8 *dst, const CInclude *cinclude);
|
||||
void cheader_to_string(Str8 *dst, const CHeader *cheader);
|
||||
void csource_to_string(Str8 *dst, const CSource *csource);
|
||||
b32 cheaderinclude_to_string(Str8 *dst, const CHeaderInclude *cheaderinclude);
|
||||
|
||||
#endif // !DATATYPES_H
|
1526
ccodegen/dbl_list.c
Normal file
1526
ccodegen/dbl_list.c
Normal file
File diff suppressed because it is too large
Load Diff
222
ccodegen/dbl_list.h
Normal file
222
ccodegen/dbl_list.h
Normal file
@@ -0,0 +1,222 @@
|
||||
// vim:fileencoding=utf-8:foldmethod=marker
|
||||
|
||||
#ifndef CCGEN_DBL_LIST_H
|
||||
#define CCGEN_DBL_LIST_H
|
||||
|
||||
#include "wapp_core.h"
|
||||
#include "type_enums.h"
|
||||
|
||||
#ifdef WAPP_PLATFORM_CPP
|
||||
BEGIN_C_LINKAGE
|
||||
#endif // !WAPP_PLATFORM_CPP
|
||||
|
||||
#ifdef WAPP_PLATFORM_CPP
|
||||
#define wapp_cenumval_list_node(ITEM_PTR) CEnumValNode{ITEM_PTR, nullptr, nullptr}
|
||||
#define wapp_carg_list_node(ITEM_PTR) CArgNode{ITEM_PTR, nullptr, nullptr}
|
||||
#define wapp_cqualifier_list_node(ITEM_PTR) CQualifierNode{ITEM_PTR, nullptr, nullptr}
|
||||
#define wapp_cinclude_list_node(ITEM_PTR) CIncludeNode{ITEM_PTR, nullptr, nullptr}
|
||||
#define wapp_cusertype_list_node(ITEM_PTR) CUserTypeNode{ITEM_PTR, nullptr, nullptr}
|
||||
#define wapp_cfunc_list_node(ITEM_PTR) CFuncNode{ITEM_PTR, nullptr, nullptr}
|
||||
#define wapp_cstruct_list_node(ITEM_PTR) CStructNode{ITEM_PTR, nullptr, nullptr}
|
||||
#define wapp_cmacro_list_node(ITEM_PTR) CMacroNode{ITEM_PTR, nullptr, nullptr}
|
||||
#else
|
||||
#define wapp_cenumval_list_node(ITEM_PTR) ((CEnumValNode){.item = ITEM_PTR})
|
||||
#define wapp_carg_list_node(ITEM_PTR) ((CArgNode){.item = ITEM_PTR})
|
||||
#define wapp_cqualifier_list_node(ITEM_PTR) ((CQualifierNode){.item = ITEM_PTR})
|
||||
#define wapp_cinclude_list_node(ITEM_PTR) ((CIncludeNode){.item = ITEM_PTR})
|
||||
#define wapp_cusertype_list_node(ITEM_PTR) ((CUserTypeNode){.item = ITEM_PTR})
|
||||
#define wapp_cfunc_list_node(ITEM_PTR) ((CFuncNode){.item = ITEM_PTR})
|
||||
#define wapp_cstruct_list_node(ITEM_PTR) ((CStructNode){.item = ITEM_PTR})
|
||||
#define wapp_cmacro_list_node(ITEM_PTR) ((CMacroNode){.item = ITEM_PTR})
|
||||
#endif // !WAPP_PLATFORM_CPP
|
||||
|
||||
typedef struct cenumval CEnumVal;
|
||||
typedef struct carg CArg;
|
||||
typedef struct cinclude CInclude;
|
||||
typedef struct cusertype CUserType;
|
||||
typedef struct cfunc CFunc;
|
||||
typedef struct cstruct CStruct;
|
||||
typedef struct cmacro CMacro;
|
||||
|
||||
typedef struct CEnumValNode CEnumValNode;
|
||||
struct CEnumValNode {
|
||||
CEnumVal *item;
|
||||
CEnumValNode *prev;
|
||||
CEnumValNode *next;
|
||||
};
|
||||
|
||||
typedef struct CEnumValList CEnumValList;
|
||||
struct CEnumValList {
|
||||
CEnumValNode *first;
|
||||
CEnumValNode *last;
|
||||
u64 node_count;
|
||||
};
|
||||
|
||||
typedef struct CArgNode CArgNode;
|
||||
struct CArgNode {
|
||||
CArg *item;
|
||||
CArgNode *prev;
|
||||
CArgNode *next;
|
||||
};
|
||||
|
||||
typedef struct CArgList CArgList;
|
||||
struct CArgList {
|
||||
CArgNode *first;
|
||||
CArgNode *last;
|
||||
u64 node_count;
|
||||
};
|
||||
|
||||
typedef struct CQualifierNode CQualifierNode;
|
||||
struct CQualifierNode {
|
||||
CQualifier *item;
|
||||
CQualifierNode *prev;
|
||||
CQualifierNode *next;
|
||||
};
|
||||
|
||||
typedef struct CQualifierList CQualifierList;
|
||||
struct CQualifierList {
|
||||
CQualifierNode *first;
|
||||
CQualifierNode *last;
|
||||
u64 node_count;
|
||||
};
|
||||
|
||||
typedef struct CIncludeNode CIncludeNode;
|
||||
struct CIncludeNode {
|
||||
CInclude *item;
|
||||
CIncludeNode *prev;
|
||||
CIncludeNode *next;
|
||||
};
|
||||
|
||||
typedef struct CIncludeList CIncludeList;
|
||||
struct CIncludeList {
|
||||
CIncludeNode *first;
|
||||
CIncludeNode *last;
|
||||
u64 node_count;
|
||||
};
|
||||
|
||||
typedef struct CUserTypeNode CUserTypeNode;
|
||||
struct CUserTypeNode {
|
||||
CUserType *item;
|
||||
CUserTypeNode *prev;
|
||||
CUserTypeNode *next;
|
||||
};
|
||||
|
||||
typedef struct CUserTypeList CUserTypeList;
|
||||
struct CUserTypeList {
|
||||
CUserTypeNode *first;
|
||||
CUserTypeNode *last;
|
||||
u64 node_count;
|
||||
};
|
||||
|
||||
typedef struct CFuncNode CFuncNode;
|
||||
struct CFuncNode {
|
||||
CFunc *item;
|
||||
CFuncNode *prev;
|
||||
CFuncNode *next;
|
||||
};
|
||||
|
||||
typedef struct CFuncList CFuncList;
|
||||
struct CFuncList {
|
||||
CFuncNode *first;
|
||||
CFuncNode *last;
|
||||
u64 node_count;
|
||||
};
|
||||
|
||||
typedef struct CStructNode CStructNode;
|
||||
struct CStructNode {
|
||||
CStruct *item;
|
||||
CStructNode *prev;
|
||||
CStructNode *next;
|
||||
};
|
||||
|
||||
typedef struct CStructList CStructList;
|
||||
struct CStructList {
|
||||
CStructNode *first;
|
||||
CStructNode *last;
|
||||
u64 node_count;
|
||||
};
|
||||
|
||||
typedef struct CMacroNode CMacroNode;
|
||||
struct CMacroNode {
|
||||
CMacro *item;
|
||||
CMacroNode *prev;
|
||||
CMacroNode *next;
|
||||
};
|
||||
|
||||
typedef struct CMacroList CMacroList;
|
||||
struct CMacroList {
|
||||
CMacroNode *first;
|
||||
CMacroNode *last;
|
||||
u64 node_count;
|
||||
};
|
||||
|
||||
CEnumValNode *wapp_cenumval_list_get(const CEnumValList *list, u64 index);
|
||||
void wapp_cenumval_list_push_front(CEnumValList *list, CEnumValNode *node);
|
||||
void wapp_cenumval_list_push_back(CEnumValList *list, CEnumValNode *node);
|
||||
void wapp_cenumval_list_insert(CEnumValList *list, CEnumValNode *node, u64 index);
|
||||
CEnumValNode *wapp_cenumval_list_pop_front(CEnumValList *list);
|
||||
CEnumValNode *wapp_cenumval_list_pop_back(CEnumValList *list);
|
||||
CEnumValNode *wapp_cenumval_list_remove(CEnumValList *list, u64 index);
|
||||
void wapp_cenumval_list_empty(CEnumValList *list);
|
||||
CArgNode *wapp_carg_list_get(const CArgList *list, u64 index);
|
||||
void wapp_carg_list_push_front(CArgList *list, CArgNode *node);
|
||||
void wapp_carg_list_push_back(CArgList *list, CArgNode *node);
|
||||
void wapp_carg_list_insert(CArgList *list, CArgNode *node, u64 index);
|
||||
CArgNode *wapp_carg_list_pop_front(CArgList *list);
|
||||
CArgNode *wapp_carg_list_pop_back(CArgList *list);
|
||||
CArgNode *wapp_carg_list_remove(CArgList *list, u64 index);
|
||||
void wapp_carg_list_empty(CArgList *list);
|
||||
CQualifierNode *wapp_cqualifier_list_get(const CQualifierList *list, u64 index);
|
||||
void wapp_cqualifier_list_push_front(CQualifierList *list, CQualifierNode *node);
|
||||
void wapp_cqualifier_list_push_back(CQualifierList *list, CQualifierNode *node);
|
||||
void wapp_cqualifier_list_insert(CQualifierList *list, CQualifierNode *node, u64 index);
|
||||
CQualifierNode *wapp_cqualifier_list_pop_front(CQualifierList *list);
|
||||
CQualifierNode *wapp_cqualifier_list_pop_back(CQualifierList *list);
|
||||
CQualifierNode *wapp_cqualifier_list_remove(CQualifierList *list, u64 index);
|
||||
void wapp_cqualifier_list_empty(CQualifierList *list);
|
||||
CIncludeNode *wapp_cinclude_list_get(const CIncludeList *list, u64 index);
|
||||
void wapp_cinclude_list_push_front(CIncludeList *list, CIncludeNode *node);
|
||||
void wapp_cinclude_list_push_back(CIncludeList *list, CIncludeNode *node);
|
||||
void wapp_cinclude_list_insert(CIncludeList *list, CIncludeNode *node, u64 index);
|
||||
CIncludeNode *wapp_cinclude_list_pop_front(CIncludeList *list);
|
||||
CIncludeNode *wapp_cinclude_list_pop_back(CIncludeList *list);
|
||||
CIncludeNode *wapp_cinclude_list_remove(CIncludeList *list, u64 index);
|
||||
void wapp_cinclude_list_empty(CIncludeList *list);
|
||||
CUserTypeNode *wapp_cusertype_list_get(const CUserTypeList *list, u64 index);
|
||||
void wapp_cusertype_list_push_front(CUserTypeList *list, CUserTypeNode *node);
|
||||
void wapp_cusertype_list_push_back(CUserTypeList *list, CUserTypeNode *node);
|
||||
void wapp_cusertype_list_insert(CUserTypeList *list, CUserTypeNode *node, u64 index);
|
||||
CUserTypeNode *wapp_cusertype_list_pop_front(CUserTypeList *list);
|
||||
CUserTypeNode *wapp_cusertype_list_pop_back(CUserTypeList *list);
|
||||
CUserTypeNode *wapp_cusertype_list_remove(CUserTypeList *list, u64 index);
|
||||
void wapp_cusertype_list_empty(CUserTypeList *list);
|
||||
CFuncNode *wapp_cfunc_list_get(const CFuncList *list, u64 index);
|
||||
void wapp_cfunc_list_push_front(CFuncList *list, CFuncNode *node);
|
||||
void wapp_cfunc_list_push_back(CFuncList *list, CFuncNode *node);
|
||||
void wapp_cfunc_list_insert(CFuncList *list, CFuncNode *node, u64 index);
|
||||
CFuncNode *wapp_cfunc_list_pop_front(CFuncList *list);
|
||||
CFuncNode *wapp_cfunc_list_pop_back(CFuncList *list);
|
||||
CFuncNode *wapp_cfunc_list_remove(CFuncList *list, u64 index);
|
||||
void wapp_cfunc_list_empty(CFuncList *list);
|
||||
CStructNode *wapp_cstruct_list_get(const CStructList *list, u64 index);
|
||||
void wapp_cstruct_list_push_front(CStructList *list, CStructNode *node);
|
||||
void wapp_cstruct_list_push_back(CStructList *list, CStructNode *node);
|
||||
void wapp_cstruct_list_insert(CStructList *list, CStructNode *node, u64 index);
|
||||
CStructNode *wapp_cstruct_list_pop_front(CStructList *list);
|
||||
CStructNode *wapp_cstruct_list_pop_back(CStructList *list);
|
||||
CStructNode *wapp_cstruct_list_remove(CStructList *list, u64 index);
|
||||
void wapp_cstruct_list_empty(CStructList *list);
|
||||
CMacroNode *wapp_cmacro_list_get(const CMacroList *list, u64 index);
|
||||
void wapp_cmacro_list_push_front(CMacroList *list, CMacroNode *node);
|
||||
void wapp_cmacro_list_push_back(CMacroList *list, CMacroNode *node);
|
||||
void wapp_cmacro_list_insert(CMacroList *list, CMacroNode *node, u64 index);
|
||||
CMacroNode *wapp_cmacro_list_pop_front(CMacroList *list);
|
||||
CMacroNode *wapp_cmacro_list_pop_back(CMacroList *list);
|
||||
CMacroNode *wapp_cmacro_list_remove(CMacroList *list, u64 index);
|
||||
void wapp_cmacro_list_empty(CMacroList *list);
|
||||
|
||||
#ifdef WAPP_PLATFORM_CPP
|
||||
END_C_LINKAGE
|
||||
#endif // !WAPP_PLATFORM_CPP
|
||||
|
||||
#endif // !DBL_LIST_H
|
10
ccodegen/main.c
Normal file
10
ccodegen/main.c
Normal file
@@ -0,0 +1,10 @@
|
||||
// vim:fileencoding=utf-8:foldmethod=marker
|
||||
|
||||
#include "datatypes.h"
|
||||
#include "type_enums.h"
|
||||
#include "wapp_core.h"
|
||||
#include <stdio.h>
|
||||
|
||||
int main(void) {
|
||||
return 0;
|
||||
}
|
84
ccodegen/type_enums.h
Normal file
84
ccodegen/type_enums.h
Normal file
@@ -0,0 +1,84 @@
|
||||
// vim:fileencoding=utf-8:foldmethod=marker
|
||||
|
||||
#ifndef TYPE_ENUMS_H
|
||||
#define TYPE_ENUMS_H
|
||||
|
||||
#include "wapp_core.h"
|
||||
|
||||
typedef enum {
|
||||
CTYPE_VOID,
|
||||
CTYPE_B32,
|
||||
CTYPE_CHAR,
|
||||
CTYPE_C8,
|
||||
CTYPE_C16,
|
||||
CTYPE_C32,
|
||||
CTYPE_I8,
|
||||
CTYPE_I16,
|
||||
CTYPE_I32,
|
||||
CTYPE_I64,
|
||||
CTYPE_U8,
|
||||
CTYPE_U16,
|
||||
CTYPE_U32,
|
||||
CTYPE_U64,
|
||||
CTYPE_F32,
|
||||
CTYPE_F64,
|
||||
CTYPE_F128,
|
||||
CTYPE_IPTR,
|
||||
CTYPE_UPTR,
|
||||
|
||||
COUNT_CTYPE,
|
||||
} CType;
|
||||
internal Str8RO ctypes[COUNT_CTYPE] = {
|
||||
[CTYPE_VOID] = wapp_str8_lit_ro("void"),
|
||||
[CTYPE_B32] = wapp_str8_lit_ro("b32"),
|
||||
[CTYPE_CHAR] = wapp_str8_lit_ro("char"),
|
||||
[CTYPE_C8] = wapp_str8_lit_ro("c8"),
|
||||
[CTYPE_C16] = wapp_str8_lit_ro("c16"),
|
||||
[CTYPE_C32] = wapp_str8_lit_ro("c32"),
|
||||
[CTYPE_I8] = wapp_str8_lit_ro("i8"),
|
||||
[CTYPE_I16] = wapp_str8_lit_ro("i16"),
|
||||
[CTYPE_I32] = wapp_str8_lit_ro("i32"),
|
||||
[CTYPE_I64] = wapp_str8_lit_ro("i64"),
|
||||
[CTYPE_U8] = wapp_str8_lit_ro("u8"),
|
||||
[CTYPE_U16] = wapp_str8_lit_ro("u16"),
|
||||
[CTYPE_U32] = wapp_str8_lit_ro("u32"),
|
||||
[CTYPE_U64] = wapp_str8_lit_ro("u64"),
|
||||
[CTYPE_F32] = wapp_str8_lit_ro("f32"),
|
||||
[CTYPE_F64] = wapp_str8_lit_ro("f64"),
|
||||
[CTYPE_F128] = wapp_str8_lit_ro("f128"),
|
||||
[CTYPE_IPTR] = wapp_str8_lit_ro("iptr"),
|
||||
[CTYPE_UPTR] = wapp_str8_lit_ro("uptr"),
|
||||
};
|
||||
|
||||
typedef enum {
|
||||
CQUALIFIER_NONE,
|
||||
CQUALIFIER_CONST,
|
||||
CQUALIFIER_EXTERNAL,
|
||||
CQUALIFIER_INTERNAL,
|
||||
CQUALIFIER_PERSISTENT,
|
||||
|
||||
COUNT_CQUALIFIER,
|
||||
} CQualifier;
|
||||
internal Str8RO cqualifiers[COUNT_CQUALIFIER] = {
|
||||
[CQUALIFIER_NONE] = wapp_str8_lit_ro(""),
|
||||
[CQUALIFIER_CONST] = wapp_str8_lit_ro("const "),
|
||||
[CQUALIFIER_EXTERNAL] = wapp_str8_lit_ro("external "),
|
||||
[CQUALIFIER_INTERNAL] = wapp_str8_lit_ro("internal "),
|
||||
[CQUALIFIER_PERSISTENT] = wapp_str8_lit_ro("persistent "),
|
||||
};
|
||||
|
||||
|
||||
typedef enum {
|
||||
CPOINTERTYPE_NONE,
|
||||
CPOINTERTYPE_SINGLE,
|
||||
CPOINTERTYPE_DOUBLE,
|
||||
|
||||
COUNT_CPOINTERTYPE,
|
||||
} CPointerType;
|
||||
internal Str8RO cpointertypes[COUNT_CPOINTERTYPE] = {
|
||||
[CPOINTERTYPE_NONE] = wapp_str8_lit_ro(""),
|
||||
[CPOINTERTYPE_SINGLE] = wapp_str8_lit_ro("*"),
|
||||
[CPOINTERTYPE_DOUBLE] = wapp_str8_lit_ro("**"),
|
||||
};
|
||||
|
||||
#endif // !TYPE_ENUMS_H
|
60
codegen/__main__.py
Normal file
60
codegen/__main__.py
Normal file
@@ -0,0 +1,60 @@
|
||||
import json
|
||||
from typing import Dict
|
||||
from pathlib import Path
|
||||
from codegen.datatypes import CDataType, CStruct
|
||||
from codegen.constants import WAPP_REPO_ROOT, DBL_LIST_DATA, ARRAY_DATA
|
||||
from codegen.dbl_list.make_dbl_list import DblListData, make_dbl_list
|
||||
from codegen.array.make_array import ArrayData, make_array
|
||||
|
||||
|
||||
def main(types_file: Path | None):
|
||||
dbl_list_datatypes: Dict[CDataType, DblListData] = {}
|
||||
array_datatypes: Dict[CDataType, ArrayData] = {}
|
||||
|
||||
if types_file is not None:
|
||||
with types_file.open("r") as infile:
|
||||
datatypes = json.load(infile)
|
||||
dbl_list_data = datatypes.get(DBL_LIST_DATA)
|
||||
array_data = datatypes.get(ARRAY_DATA)
|
||||
|
||||
if dbl_list_data is not None and isinstance(dbl_list_data, dict):
|
||||
dbl_list_datatypes = {k: DblListData.from_dict(v) for k, v in dbl_list_data.items()}
|
||||
|
||||
if array_data is not None and isinstance(array_data, dict):
|
||||
array_datatypes = {k: ArrayData.from_dict(v) for k, v in array_data.items()}
|
||||
|
||||
make_dbl_list(dbl_list_datatypes)
|
||||
make_array(array_datatypes)
|
||||
|
||||
# Save example types file
|
||||
custom_struct = CStruct(name="custom_type", cargs=[], typedef_name="CustomType")
|
||||
example = {
|
||||
DBL_LIST_DATA: {
|
||||
"CustomType": DblListData(
|
||||
node_typename="CustomTypeNode",
|
||||
list_typename="CustomTypeList",
|
||||
hdr_decl_types=[custom_struct],
|
||||
).to_dict()
|
||||
},
|
||||
ARRAY_DATA: {
|
||||
"CustomType": ArrayData(
|
||||
array_typename="CustomTypeArray",
|
||||
hdr_decl_types=[custom_struct],
|
||||
).to_dict()
|
||||
},
|
||||
}
|
||||
|
||||
example_file = WAPP_REPO_ROOT / "codegen_custom_data_example.json"
|
||||
with example_file.open("w") as outfile:
|
||||
json.dump(example, outfile, indent=2)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
from argparse import ArgumentParser
|
||||
|
||||
parser = ArgumentParser()
|
||||
parser.add_argument("-f", "--types-file", type=Path, help="JSON file containing custom types for codegen")
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
main(args.types_file)
|
435
codegen/array/make_array.py
Normal file
435
codegen/array/make_array.py
Normal file
@@ -0,0 +1,435 @@
|
||||
from pathlib import Path
|
||||
from dataclasses import dataclass, field
|
||||
from typing import List, Dict, Any, Type
|
||||
from codegen.constants import WAPP_SRC_ROOT
|
||||
from codegen.utils import load_func_body_from_file, convert_to_relative
|
||||
from codegen.datatypes import (
|
||||
CDataType,
|
||||
CMacro,
|
||||
CStruct,
|
||||
CFunc,
|
||||
CHeader,
|
||||
CSource,
|
||||
CArg,
|
||||
CType,
|
||||
CPointer,
|
||||
CPointerType,
|
||||
CQualifier,
|
||||
CInclude,
|
||||
SerialisableDataclass,
|
||||
get_datatype_string,
|
||||
)
|
||||
|
||||
|
||||
@dataclass
|
||||
class ArrayData(SerialisableDataclass):
|
||||
array_typename: str
|
||||
hdr_decl_types: List[CStruct] = field(default_factory=list)
|
||||
src_decl_types: List[CStruct] = field(default_factory=list)
|
||||
|
||||
@classmethod
|
||||
def from_dict(cls: Type["ArrayData"], d: Dict[str, Any]) -> "ArrayData":
|
||||
data = ArrayData(**d)
|
||||
data.hdr_decl_types = [CStruct.from_dict(v) for v in data.hdr_decl_types if isinstance(v, dict)]
|
||||
data.src_decl_types = [CStruct.from_dict(v) for v in data.src_decl_types if isinstance(v, dict)]
|
||||
return data
|
||||
|
||||
|
||||
def make_array(user_datatypes: Dict[CDataType, ArrayData] = {}):
|
||||
def __format_func_body(
|
||||
filename: Path,
|
||||
type_string: str,
|
||||
type_string_upper: str,
|
||||
type_string_lower: str,
|
||||
array_typename: str
|
||||
):
|
||||
return load_func_body_from_file(filename).format(
|
||||
T=type_string,
|
||||
ArrayType=array_typename,
|
||||
Tupper=type_string_upper,
|
||||
Tlower=type_string_lower,
|
||||
)
|
||||
|
||||
out_dir = WAPP_SRC_ROOT / "primitives" / "array"
|
||||
out_dir.mkdir(parents=True, exist_ok=True)
|
||||
|
||||
common_includes: List[CInclude] = [
|
||||
CInclude(
|
||||
header=str(convert_to_relative(WAPP_SRC_ROOT / "primitives" / "mem_allocator" / "mem_allocator.h", out_dir)).replace("\\", "/"),
|
||||
local=True,
|
||||
),
|
||||
CInclude(
|
||||
header=str(convert_to_relative(WAPP_SRC_ROOT / "common" / "misc" / "misc_utils.h", out_dir)).replace("\\", "/"),
|
||||
local=True,
|
||||
),
|
||||
]
|
||||
|
||||
common_decl_types: List[CStruct] = []
|
||||
|
||||
datatypes: dict[CDataType, ArrayData] = {
|
||||
CType.VOID: ArrayData(array_typename="GenericArray"),
|
||||
"void *": ArrayData(array_typename="VoidPArray"),
|
||||
"Str8": ArrayData(
|
||||
array_typename="Str8Array",
|
||||
hdr_decl_types=[
|
||||
CStruct(name="str8", cargs=[], typedef_name="Str8"),
|
||||
],
|
||||
),
|
||||
}
|
||||
|
||||
for _type in CType:
|
||||
if _type == CType.VOID:
|
||||
continue
|
||||
|
||||
type_title = _type.value.title()
|
||||
datatypes[_type] = ArrayData(
|
||||
array_typename=f"{type_title}Array",
|
||||
)
|
||||
|
||||
datatypes.update(user_datatypes)
|
||||
|
||||
snippets_dir = Path(__file__).parent / "snippets"
|
||||
|
||||
header = CHeader(
|
||||
name="array",
|
||||
decl_types=[*common_decl_types],
|
||||
includes=[],
|
||||
types=[],
|
||||
funcs=[]
|
||||
)
|
||||
|
||||
source = CSource(
|
||||
name=header.name,
|
||||
decl_types=[*common_decl_types],
|
||||
includes=[
|
||||
CInclude(header, local=True, same_dir=True),
|
||||
CInclude(
|
||||
header=str(convert_to_relative(WAPP_SRC_ROOT / "common" / "assert" / "assert.h", out_dir)).replace("\\", "/"),
|
||||
local=True
|
||||
),
|
||||
CInclude(header="stddef.h"),
|
||||
],
|
||||
internal_funcs=[],
|
||||
funcs=header.funcs
|
||||
)
|
||||
|
||||
if len(common_includes) > 0:
|
||||
header.includes.extend(common_includes)
|
||||
source.includes.extend(common_includes)
|
||||
|
||||
|
||||
generic_funcs = []
|
||||
|
||||
for _type, array_data in datatypes.items():
|
||||
type_string = get_datatype_string(_type)
|
||||
clean_type_string = type_string.replace(" ", "").replace("*", "_ptr")
|
||||
type_string_upper = clean_type_string.upper()
|
||||
type_string_lower = clean_type_string.lower()
|
||||
|
||||
array = CStruct(
|
||||
name=array_data.array_typename,
|
||||
cargs=[
|
||||
CArg(name="items", _type=type_string, pointer=CPointer(_type=CPointerType.SINGLE)),
|
||||
CArg(name="count", _type=CType.U64),
|
||||
CArg(name="capacity", _type=CType.U64),
|
||||
CArg(name="item_size", _type=CType.U64),
|
||||
],
|
||||
)
|
||||
|
||||
if isinstance(_type, CType) and _type == CType.VOID:
|
||||
alloc_capacity_func = CFunc(
|
||||
name=f"_array_alloc_capacity",
|
||||
ret_type=array,
|
||||
args=[
|
||||
CArg(name="allocator", _type="Allocator", pointer=CPointer(CPointerType.SINGLE), qualifier=CQualifier.CONST),
|
||||
CArg(name="capacity", _type=CType.U64),
|
||||
CArg(name="item_size", _type=CType.U64),
|
||||
],
|
||||
body=__format_func_body(
|
||||
filename=snippets_dir / "alloc_capacity",
|
||||
type_string=type_string,
|
||||
type_string_upper=type_string_upper,
|
||||
type_string_lower=type_string_lower,
|
||||
array_typename=array_data.array_typename,
|
||||
),
|
||||
pointer=CPointer(CPointerType.SINGLE),
|
||||
)
|
||||
generic_funcs.append(alloc_capacity_func)
|
||||
else:
|
||||
stack_array_cmacro = CMacro(
|
||||
name=f"wapp_{type_string_lower}_array(...)",
|
||||
value=__format_func_body(
|
||||
filename=snippets_dir / "stack_array",
|
||||
type_string=type_string,
|
||||
type_string_upper=type_string_upper,
|
||||
type_string_lower=type_string_lower,
|
||||
array_typename=array_data.array_typename,
|
||||
),
|
||||
)
|
||||
stack_array_cppmacro = CMacro(
|
||||
name=f"wapp_{type_string_lower}_array(...)",
|
||||
value=__format_func_body(
|
||||
filename=snippets_dir / "stack_array_cpp",
|
||||
type_string=type_string,
|
||||
type_string_upper=type_string_upper,
|
||||
type_string_lower=type_string_lower,
|
||||
array_typename=array_data.array_typename,
|
||||
),
|
||||
)
|
||||
|
||||
stack_capacity_array_cmacro = CMacro(
|
||||
name=f"wapp_{type_string_lower}_array_with_capacity(CAPACITY)",
|
||||
value=__format_func_body(
|
||||
filename=snippets_dir / "stack_capacity_array",
|
||||
type_string=type_string,
|
||||
type_string_upper=type_string_upper,
|
||||
type_string_lower=type_string_lower,
|
||||
array_typename=array_data.array_typename,
|
||||
),
|
||||
)
|
||||
stack_capacity_array_cppmacro = CMacro(
|
||||
name=f"wapp_{type_string_lower}_array_with_capacity(CAPACITY)",
|
||||
value=__format_func_body(
|
||||
filename=snippets_dir / "stack_capacity_array_cpp",
|
||||
type_string=type_string,
|
||||
type_string_upper=type_string_upper,
|
||||
type_string_lower=type_string_lower,
|
||||
array_typename=array_data.array_typename,
|
||||
),
|
||||
)
|
||||
|
||||
alloc_capacity_array_macro = CMacro(
|
||||
name=f"wapp_{type_string_lower}_array_alloc_capacity(ALLOCATOR_PTR, CAPACITY)",
|
||||
value=__format_func_body(
|
||||
filename=snippets_dir / "alloc_capacity_macro",
|
||||
type_string=type_string,
|
||||
type_string_upper=type_string_upper,
|
||||
type_string_lower=type_string_lower,
|
||||
array_typename=array_data.array_typename,
|
||||
),
|
||||
)
|
||||
|
||||
array_pop_cmacro = CMacro(
|
||||
name=f"wapp_{type_string_lower}_array_pop(ARRAY_PTR)",
|
||||
value=__format_func_body(
|
||||
filename=snippets_dir / "array_pop_macro",
|
||||
type_string=type_string,
|
||||
type_string_upper=type_string_upper,
|
||||
type_string_lower=type_string_lower,
|
||||
array_typename=array_data.array_typename,
|
||||
),
|
||||
)
|
||||
array_pop_cppmacro = CMacro(
|
||||
name=f"wapp_{type_string_lower}_array_pop(ARRAY_PTR)",
|
||||
value=__format_func_body(
|
||||
filename=snippets_dir / "array_pop_macro_cpp",
|
||||
type_string=type_string,
|
||||
type_string_upper=type_string_upper,
|
||||
type_string_lower=type_string_lower,
|
||||
array_typename=array_data.array_typename,
|
||||
),
|
||||
)
|
||||
|
||||
get_func = CFunc(
|
||||
name=f"wapp_{type_string_lower}_array_get",
|
||||
ret_type=type_string,
|
||||
args=[
|
||||
CArg(name="array", _type=array, pointer=CPointer(CPointerType.SINGLE), qualifier=CQualifier.CONST),
|
||||
CArg(name="index", _type=CType.U64),
|
||||
],
|
||||
body=__format_func_body(
|
||||
filename=snippets_dir / "array_get",
|
||||
type_string=type_string,
|
||||
type_string_upper=type_string_upper,
|
||||
type_string_lower=type_string_lower,
|
||||
array_typename=array_data.array_typename,
|
||||
),
|
||||
pointer=CPointer(CPointerType.SINGLE),
|
||||
)
|
||||
|
||||
set_func = CFunc(
|
||||
name=f"wapp_{type_string_lower}_array_set",
|
||||
ret_type=CType.VOID,
|
||||
args=[
|
||||
CArg(name="array", _type=array, pointer=CPointer(CPointerType.SINGLE)),
|
||||
CArg(name="index", _type=CType.U64),
|
||||
CArg(name="item", _type=type_string, pointer=CPointer(CPointerType.SINGLE)),
|
||||
],
|
||||
body=__format_func_body(
|
||||
filename=snippets_dir / "array_set",
|
||||
type_string=type_string,
|
||||
type_string_upper=type_string_upper,
|
||||
type_string_lower=type_string_lower,
|
||||
array_typename=array_data.array_typename,
|
||||
),
|
||||
)
|
||||
|
||||
append_capped_func = CFunc(
|
||||
name=f"wapp_{type_string_lower}_array_append_capped",
|
||||
ret_type=CType.VOID,
|
||||
args=[
|
||||
CArg(name="array", _type=array, pointer=CPointer(CPointerType.SINGLE)),
|
||||
CArg(name="item", _type=type_string, pointer=CPointer(CPointerType.SINGLE)),
|
||||
],
|
||||
body=__format_func_body(
|
||||
filename=snippets_dir / "append_capped",
|
||||
type_string=type_string,
|
||||
type_string_upper=type_string_upper,
|
||||
type_string_lower=type_string_lower,
|
||||
array_typename=array_data.array_typename,
|
||||
),
|
||||
)
|
||||
|
||||
extend_capped_func = CFunc(
|
||||
name=f"wapp_{type_string_lower}_array_extend_capped",
|
||||
ret_type=CType.VOID,
|
||||
args=[
|
||||
CArg(name="array", _type=array, pointer=CPointer(CPointerType.SINGLE)),
|
||||
CArg(name="other", _type=array, pointer=CPointer(CPointerType.SINGLE), qualifier=CQualifier.CONST),
|
||||
],
|
||||
body=__format_func_body(
|
||||
filename=snippets_dir / "extend_capped",
|
||||
type_string=type_string,
|
||||
type_string_upper=type_string_upper,
|
||||
type_string_lower=type_string_lower,
|
||||
array_typename=array_data.array_typename,
|
||||
),
|
||||
)
|
||||
|
||||
clear_func = CFunc(
|
||||
name=f"wapp_{type_string_lower}_array_clear",
|
||||
ret_type=CType.VOID,
|
||||
args=[
|
||||
CArg(name="array", _type=array, pointer=CPointer(CPointerType.SINGLE)),
|
||||
],
|
||||
body=__format_func_body(
|
||||
filename=snippets_dir / "clear",
|
||||
type_string=type_string,
|
||||
type_string_upper=type_string_upper,
|
||||
type_string_lower=type_string_lower,
|
||||
array_typename=array_data.array_typename,
|
||||
),
|
||||
)
|
||||
|
||||
copy_capped_func = CFunc(
|
||||
name=f"wapp_{type_string_lower}_array_copy_capped",
|
||||
ret_type=CType.VOID,
|
||||
args=[
|
||||
CArg(name="src", _type=array, pointer=CPointer(CPointerType.SINGLE), qualifier=CQualifier.CONST),
|
||||
CArg(name="dst", _type=array, pointer=CPointer(CPointerType.SINGLE)),
|
||||
],
|
||||
body=__format_func_body(
|
||||
filename=snippets_dir / "copy_capped",
|
||||
type_string=type_string,
|
||||
type_string_upper=type_string_upper,
|
||||
type_string_lower=type_string_lower,
|
||||
array_typename=array_data.array_typename,
|
||||
),
|
||||
)
|
||||
|
||||
append_alloc_func = CFunc(
|
||||
name=f"wapp_{type_string_lower}_array_append_alloc",
|
||||
ret_type=array,
|
||||
args=[
|
||||
CArg(name="allocator", _type="Allocator", pointer=CPointer(CPointerType.SINGLE), qualifier=CQualifier.CONST),
|
||||
CArg(name="array", _type=array, pointer=CPointer(CPointerType.SINGLE)),
|
||||
CArg(name="item", _type=type_string, pointer=CPointer(CPointerType.SINGLE)),
|
||||
],
|
||||
body=__format_func_body(
|
||||
filename=snippets_dir / "append_alloc",
|
||||
type_string=type_string,
|
||||
type_string_upper=type_string_upper,
|
||||
type_string_lower=type_string_lower,
|
||||
array_typename=array_data.array_typename,
|
||||
),
|
||||
pointer=CPointer(CPointerType.SINGLE),
|
||||
)
|
||||
|
||||
extend_alloc_func = CFunc(
|
||||
name=f"wapp_{type_string_lower}_array_extend_alloc",
|
||||
ret_type=array,
|
||||
args=[
|
||||
CArg(name="allocator", _type="Allocator", pointer=CPointer(CPointerType.SINGLE), qualifier=CQualifier.CONST),
|
||||
CArg(name="array", _type=array, pointer=CPointer(CPointerType.SINGLE)),
|
||||
CArg(name="other", _type=array, pointer=CPointer(CPointerType.SINGLE), qualifier=CQualifier.CONST),
|
||||
],
|
||||
body=__format_func_body(
|
||||
filename=snippets_dir / "extend_alloc",
|
||||
type_string=type_string,
|
||||
type_string_upper=type_string_upper,
|
||||
type_string_lower=type_string_lower,
|
||||
array_typename=array_data.array_typename,
|
||||
),
|
||||
pointer=CPointer(CPointerType.SINGLE),
|
||||
)
|
||||
|
||||
copy_alloc_func = CFunc(
|
||||
name=f"wapp_{type_string_lower}_array_copy_alloc",
|
||||
ret_type=array,
|
||||
args=[
|
||||
CArg(name="allocator", _type="Allocator", pointer=CPointer(CPointerType.SINGLE), qualifier=CQualifier.CONST),
|
||||
CArg(name="src", _type=array, pointer=CPointer(CPointerType.SINGLE), qualifier=CQualifier.CONST),
|
||||
CArg(name="dst", _type=array, pointer=CPointer(CPointerType.SINGLE)),
|
||||
],
|
||||
body=__format_func_body(
|
||||
filename=snippets_dir / "copy_alloc",
|
||||
type_string=type_string,
|
||||
type_string_upper=type_string_upper,
|
||||
type_string_lower=type_string_lower,
|
||||
array_typename=array_data.array_typename,
|
||||
),
|
||||
pointer=CPointer(CPointerType.SINGLE),
|
||||
)
|
||||
|
||||
pop_func = CFunc(
|
||||
name=f"_{type_string_lower}_array_pop",
|
||||
ret_type=type_string,
|
||||
args=[
|
||||
CArg(name="array", _type=array, pointer=CPointer(CPointerType.SINGLE)),
|
||||
],
|
||||
body=__format_func_body(
|
||||
filename=snippets_dir / "array_pop",
|
||||
type_string=type_string,
|
||||
type_string_upper=type_string_upper,
|
||||
type_string_lower=type_string_lower,
|
||||
array_typename=array_data.array_typename,
|
||||
),
|
||||
pointer=CPointer(CPointerType.SINGLE),
|
||||
)
|
||||
|
||||
header.macros.extend([
|
||||
alloc_capacity_array_macro,
|
||||
])
|
||||
header.c_macros.extend([
|
||||
stack_array_cmacro,
|
||||
stack_capacity_array_cmacro,
|
||||
array_pop_cmacro,
|
||||
])
|
||||
header.cpp_macros.extend([
|
||||
stack_array_cppmacro,
|
||||
stack_capacity_array_cppmacro,
|
||||
array_pop_cppmacro,
|
||||
])
|
||||
header.funcs.extend([
|
||||
get_func,
|
||||
set_func,
|
||||
append_capped_func,
|
||||
extend_capped_func,
|
||||
clear_func,
|
||||
copy_capped_func,
|
||||
append_alloc_func,
|
||||
extend_alloc_func,
|
||||
copy_alloc_func,
|
||||
pop_func,
|
||||
])
|
||||
|
||||
header.decl_types.extend(array_data.hdr_decl_types)
|
||||
header.types.extend([array])
|
||||
|
||||
source.decl_types.extend(array_data.src_decl_types)
|
||||
source.funcs = header.funcs
|
||||
|
||||
|
||||
header.funcs.extend(generic_funcs)
|
||||
header.save(out_dir)
|
||||
source.save(out_dir)
|
15
codegen/array/snippets/alloc_capacity
Normal file
15
codegen/array/snippets/alloc_capacity
Normal file
@@ -0,0 +1,15 @@
|
||||
wapp_debug_assert(allocator != NULL, "`allocator` should not be NULL");
|
||||
|
||||
u64 allocation_size = sizeof({ArrayType}) + item_size * capacity;
|
||||
{ArrayType} *array = wapp_mem_allocator_alloc(allocator, allocation_size);
|
||||
if (!array) {{
|
||||
goto RETURN_GENERIC_ARRAY_ALLOC;
|
||||
}}
|
||||
|
||||
array->items = ({T} *)((u8 *)array + sizeof({ArrayType}));
|
||||
array->count = 0;
|
||||
array->capacity = capacity;
|
||||
array->item_size = item_size;
|
||||
|
||||
RETURN_GENERIC_ARRAY_ALLOC:
|
||||
return array;
|
1
codegen/array/snippets/alloc_capacity_macro
Normal file
1
codegen/array/snippets/alloc_capacity_macro
Normal file
@@ -0,0 +1 @@
|
||||
(({ArrayType} *)_array_alloc_capacity(ALLOCATOR_PTR, CAPACITY, sizeof({T})))
|
18
codegen/array/snippets/append_alloc
Normal file
18
codegen/array/snippets/append_alloc
Normal file
@@ -0,0 +1,18 @@
|
||||
wapp_debug_assert(allocator != NULL && array != NULL, "`allocator` and `array` should not be NULL");
|
||||
|
||||
{ArrayType} *output = array;
|
||||
|
||||
if (array->count >= array->capacity) {{
|
||||
u64 new_capacity = wapp_misc_utils_u64_round_up_pow2(array->capacity * 2);
|
||||
output = ({ArrayType} *)_array_alloc_capacity(allocator, new_capacity, array->item_size);
|
||||
if (!output) {{
|
||||
output = array;
|
||||
goto RETURN_{Tupper}_ARRAY_APPEND_ALLOC;
|
||||
}}
|
||||
wapp_{Tlower}_array_copy_capped(array, output);
|
||||
}}
|
||||
|
||||
wapp_{Tlower}_array_append_capped(output, item);
|
||||
|
||||
RETURN_{Tupper}_ARRAY_APPEND_ALLOC:
|
||||
return output;
|
5
codegen/array/snippets/append_capped
Normal file
5
codegen/array/snippets/append_capped
Normal file
@@ -0,0 +1,5 @@
|
||||
wapp_debug_assert(array != NULL, "`array` should not be NULL");
|
||||
wapp_runtime_assert(array->count < array->capacity, "`array` is full");
|
||||
|
||||
u64 index = (array->count)++;
|
||||
wapp_{Tlower}_array_set(array, index, item);
|
5
codegen/array/snippets/array_get
Normal file
5
codegen/array/snippets/array_get
Normal file
@@ -0,0 +1,5 @@
|
||||
wapp_debug_assert(array != NULL, "`array` should not be NULL");
|
||||
wapp_runtime_assert(index < array->count, "`index` is out of bounds");
|
||||
|
||||
u8 *ptr = (u8 *)(array->items) + (array->item_size * index);
|
||||
return ({T} *)ptr;
|
4
codegen/array/snippets/array_pop
Normal file
4
codegen/array/snippets/array_pop
Normal file
@@ -0,0 +1,4 @@
|
||||
u64 index = array->count - 1;
|
||||
{T} *out = wapp_{Tlower}_array_get(array, index);
|
||||
--(array->count);
|
||||
return out;
|
4
codegen/array/snippets/array_pop_macro
Normal file
4
codegen/array/snippets/array_pop_macro
Normal file
@@ -0,0 +1,4 @@
|
||||
(ARRAY_PTR != NULL && (ARRAY_PTR)->count > 0 ? \
|
||||
*_{Tlower}_array_pop(ARRAY_PTR) : \
|
||||
({T}){{0}} \
|
||||
)
|
4
codegen/array/snippets/array_pop_macro_cpp
Normal file
4
codegen/array/snippets/array_pop_macro_cpp
Normal file
@@ -0,0 +1,4 @@
|
||||
(ARRAY_PTR != NULL && (ARRAY_PTR)->count > 0 ? \
|
||||
*_{Tlower}_array_pop(ARRAY_PTR) : \
|
||||
{T}{{}} \
|
||||
)
|
3
codegen/array/snippets/array_set
Normal file
3
codegen/array/snippets/array_set
Normal file
@@ -0,0 +1,3 @@
|
||||
{T} *ptr = wapp_{Tlower}_array_get(array, index);
|
||||
|
||||
memcpy((void *)ptr, (void *)item, array->item_size);
|
2
codegen/array/snippets/clear
Normal file
2
codegen/array/snippets/clear
Normal file
@@ -0,0 +1,2 @@
|
||||
wapp_debug_assert(array != NULL, "`array` should not be NULL");
|
||||
array->count = 0;
|
18
codegen/array/snippets/copy_alloc
Normal file
18
codegen/array/snippets/copy_alloc
Normal file
@@ -0,0 +1,18 @@
|
||||
wapp_debug_assert(allocator != NULL && src != NULL && dst != NULL, "`allocator`, `src` and `dst` should not be NULL");
|
||||
|
||||
{ArrayType} *output = dst;
|
||||
|
||||
if (src->count >= dst->capacity) {{
|
||||
u64 new_capacity = wapp_misc_utils_u64_round_up_pow2(dst->capacity * 2);
|
||||
output = ({ArrayType} *)_array_alloc_capacity(allocator, new_capacity, src->item_size);
|
||||
if (!output) {{
|
||||
output = dst;
|
||||
goto RETURN_{Tupper}_ARRAY_COPY_ALLOC;
|
||||
}}
|
||||
}}
|
||||
|
||||
wapp_{Tlower}_array_clear(output);
|
||||
wapp_{Tlower}_array_copy_capped(src, output);
|
||||
|
||||
RETURN_{Tupper}_ARRAY_COPY_ALLOC:
|
||||
return output;
|
22
codegen/array/snippets/copy_capped
Normal file
22
codegen/array/snippets/copy_capped
Normal file
@@ -0,0 +1,22 @@
|
||||
wapp_debug_assert(src != NULL && dst != NULL, "`src` and `dst` should not be NULL");
|
||||
|
||||
wapp_{Tlower}_array_clear(dst);
|
||||
|
||||
{T} *item;
|
||||
|
||||
// NOTE (Abdelrahman): Uses a while loop instead of a for loop to get rid of
|
||||
// MSVC Spectre mitigation warnings
|
||||
u64 to_copy = src->count < dst->capacity ? src->count : dst->capacity;
|
||||
u64 item_index = 0;
|
||||
b32 running = true;
|
||||
while (running) {{
|
||||
item = wapp_{Tlower}_array_get(src, item_index);
|
||||
++item_index;
|
||||
running = item_index < to_copy;
|
||||
|
||||
if (!item) {{
|
||||
continue;
|
||||
}}
|
||||
|
||||
wapp_{Tlower}_array_append_capped(dst, item);
|
||||
}}
|
19
codegen/array/snippets/extend_alloc
Normal file
19
codegen/array/snippets/extend_alloc
Normal file
@@ -0,0 +1,19 @@
|
||||
wapp_debug_assert(allocator != NULL && array != NULL && other != NULL, "`allocator`, `array` and `other` should not be NULL");
|
||||
|
||||
{ArrayType} *output = array;
|
||||
|
||||
u64 remaining_capacity = array->capacity - array->count;
|
||||
if (other->count >= remaining_capacity) {{
|
||||
u64 new_capacity = wapp_misc_utils_u64_round_up_pow2(array->capacity * 2);
|
||||
output = ({ArrayType} *)_array_alloc_capacity(allocator, new_capacity, array->item_size);
|
||||
if (!output) {{
|
||||
output = array;
|
||||
goto RETURN_{Tupper}_ARRAY_EXTEND_ALLOC;
|
||||
}}
|
||||
wapp_{Tlower}_array_copy_capped(array, output);
|
||||
}}
|
||||
|
||||
wapp_{Tlower}_array_extend_capped(output, other);
|
||||
|
||||
RETURN_{Tupper}_ARRAY_EXTEND_ALLOC:
|
||||
return output;
|
23
codegen/array/snippets/extend_capped
Normal file
23
codegen/array/snippets/extend_capped
Normal file
@@ -0,0 +1,23 @@
|
||||
wapp_debug_assert(array != NULL && other != NULL, "`array` and `other` should not be NULL");
|
||||
|
||||
u64 remaining_capacity = array->capacity - array->count;
|
||||
wapp_runtime_assert(other->count < remaining_capacity, "`array` does not have enough capacity");
|
||||
|
||||
{T} *item;
|
||||
|
||||
// NOTE (Abdelrahman): Uses a while loop instead of a for loop to get rid of
|
||||
// MSVC Spectre mitigation warnings
|
||||
u64 items_to_add = other->count;
|
||||
u64 item_index = 0;
|
||||
b32 running = true;
|
||||
while (running) {{
|
||||
item = wapp_{Tlower}_array_get(other, item_index);
|
||||
++item_index;
|
||||
running = item_index < items_to_add;
|
||||
|
||||
if (!item) {{
|
||||
continue;
|
||||
}}
|
||||
|
||||
wapp_{Tlower}_array_append_capped(array, item);
|
||||
}}
|
6
codegen/array/snippets/stack_array
Normal file
6
codegen/array/snippets/stack_array
Normal file
@@ -0,0 +1,6 @@
|
||||
(({ArrayType}){{ \
|
||||
.items = ({T}[wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count({T}, __VA_ARGS__) * 2)]){{__VA_ARGS__}}, \
|
||||
.count = wapp_misc_utils_va_args_count({T}, __VA_ARGS__), \
|
||||
.capacity = wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count({T}, __VA_ARGS__) * 2), \
|
||||
.item_size = sizeof({T}) \
|
||||
}})
|
9
codegen/array/snippets/stack_array_cpp
Normal file
9
codegen/array/snippets/stack_array_cpp
Normal file
@@ -0,0 +1,9 @@
|
||||
([&]() {{ \
|
||||
persistent {T} buf[wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count({T}, __VA_ARGS__) * 2)] = {{__VA_ARGS__}}; \
|
||||
return {ArrayType}{{ \
|
||||
buf, \
|
||||
wapp_misc_utils_va_args_count({T}, __VA_ARGS__), \
|
||||
wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count({T}, __VA_ARGS__) * 2), \
|
||||
sizeof({T}) \
|
||||
}}; \
|
||||
}}())
|
1
codegen/array/snippets/stack_capacity_array
Normal file
1
codegen/array/snippets/stack_capacity_array
Normal file
@@ -0,0 +1 @@
|
||||
(({ArrayType}){{.items = ({T}[CAPACITY]){{0}}, .count = 0, .capacity = CAPACITY, .item_size = sizeof({T})}})
|
4
codegen/array/snippets/stack_capacity_array_cpp
Normal file
4
codegen/array/snippets/stack_capacity_array_cpp
Normal file
@@ -0,0 +1,4 @@
|
||||
([&]() {{ \
|
||||
persistent {T} buf[CAPACITY] = {{}}; \
|
||||
return {ArrayType}{{buf, 0, CAPACITY, sizeof({T})}}; \
|
||||
}}())
|
10
codegen/constants.py
Normal file
10
codegen/constants.py
Normal file
@@ -0,0 +1,10 @@
|
||||
from pathlib import Path
|
||||
|
||||
# Paths
|
||||
PACKAGE_DIR = Path(__file__).parent.resolve()
|
||||
WAPP_REPO_ROOT = PACKAGE_DIR.parent
|
||||
WAPP_SRC_ROOT = WAPP_REPO_ROOT / "src"
|
||||
|
||||
# Dictionary Keys
|
||||
DBL_LIST_DATA = "dbl_list_data"
|
||||
ARRAY_DATA = "array_data"
|
503
codegen/datatypes.py
Normal file
503
codegen/datatypes.py
Normal file
@@ -0,0 +1,503 @@
|
||||
from enum import Enum
|
||||
from pathlib import Path
|
||||
from typing import Optional, Union, List, Dict, Type, Any, TypeVar, cast
|
||||
from dataclasses import dataclass, asdict, field, fields
|
||||
|
||||
from codegen.constants import WAPP_SRC_ROOT
|
||||
from codegen.utils import convert_to_relative
|
||||
|
||||
E = TypeVar("E", bound="Enum")
|
||||
S = TypeVar("S", bound="SerialisableDataclass")
|
||||
F = TypeVar("F", bound="CFile")
|
||||
|
||||
@dataclass
|
||||
class SerialisableDataclass:
|
||||
def to_dict(self) -> Dict[str, Any]:
|
||||
d = asdict(self)
|
||||
for f in fields(self):
|
||||
member = getattr(self, f.name)
|
||||
|
||||
if isinstance(member, list):
|
||||
d[f.name] = [self.__serialise_member(i) for i in member]
|
||||
else:
|
||||
d[f.name] = self.__serialise_member(member)
|
||||
|
||||
return d
|
||||
|
||||
def __serialise_member(self, member: Any) -> Any:
|
||||
if isinstance(member, Enum):
|
||||
return member.value
|
||||
elif isinstance(member, SerialisableDataclass):
|
||||
return member.to_dict()
|
||||
|
||||
return member
|
||||
|
||||
@staticmethod
|
||||
def to_enum_value(value: Any, _type: Type[E]) -> "E":
|
||||
if isinstance(value, _type):
|
||||
return value
|
||||
|
||||
return _type(value)
|
||||
|
||||
@staticmethod
|
||||
def to_c_usertype(value: dict[str, Any]) -> "CUserType":
|
||||
try:
|
||||
output = CStruct.from_dict(value)
|
||||
except TypeError:
|
||||
output = CEnum.from_dict(value)
|
||||
|
||||
return output
|
||||
|
||||
@staticmethod
|
||||
def to_cdatatype(value: Any) -> "CDataType":
|
||||
if isinstance(value, dict):
|
||||
output = SerialisableDataclass.to_c_usertype(value)
|
||||
else:
|
||||
try:
|
||||
output = CType(value)
|
||||
except ValueError:
|
||||
output = value
|
||||
|
||||
return output
|
||||
|
||||
@classmethod
|
||||
def from_dict(cls: Type[S], d: Dict[str, Any]) -> "S":
|
||||
return cls(**d)
|
||||
|
||||
|
||||
class CType(Enum):
|
||||
VOID = "void"
|
||||
BOOL = "b32"
|
||||
CHAR = "char"
|
||||
C8 = "c8"
|
||||
C16 = "c16"
|
||||
C32 = "c32"
|
||||
I8 = "i8"
|
||||
I16 = "i16"
|
||||
I32 = "i32"
|
||||
I64 = "i64"
|
||||
U8 = "u8"
|
||||
U16 = "u16"
|
||||
U32 = "u32"
|
||||
U64 = "u64"
|
||||
F32 = "f32"
|
||||
F64 = "f64"
|
||||
F128 = "f128"
|
||||
IPTR = "iptr"
|
||||
UPTR = "uptr"
|
||||
|
||||
def __str__(self) -> str:
|
||||
return self.value
|
||||
|
||||
|
||||
class CQualifier(Enum):
|
||||
NONE = ""
|
||||
CONST = "const "
|
||||
EXTERNAL = "external "
|
||||
INTERNAL = "internal "
|
||||
PERSISTENT = "persistent "
|
||||
|
||||
def __str__(self) -> str:
|
||||
return self.value
|
||||
|
||||
|
||||
class CPointerType(Enum):
|
||||
NONE = ""
|
||||
SINGLE = "*"
|
||||
DOUBLE = "**"
|
||||
|
||||
def __str__(self) -> str:
|
||||
return self.value
|
||||
|
||||
|
||||
@dataclass
|
||||
class CPointer(SerialisableDataclass):
|
||||
_type: CPointerType = CPointerType.NONE
|
||||
qualifier: CQualifier = CQualifier.NONE
|
||||
|
||||
def __str__(self) -> str:
|
||||
return str(self._type) + str(self.qualifier)
|
||||
|
||||
@classmethod
|
||||
def from_dict(cls: Type["CPointer"], d: Dict[str, Any]) -> "CPointer":
|
||||
ptr = CPointer(**d)
|
||||
ptr._type = CPointer.to_enum_value(ptr._type, CPointerType)
|
||||
ptr.qualifier = CPointer.to_enum_value(ptr.qualifier, CQualifier)
|
||||
return ptr
|
||||
|
||||
|
||||
@dataclass
|
||||
class CEnumVal(SerialisableDataclass):
|
||||
name: str
|
||||
value: Optional[int] = None
|
||||
|
||||
def __str__(self) -> str:
|
||||
return self.name + "" if self.value is None else f" = {self.value}"
|
||||
|
||||
|
||||
@dataclass
|
||||
class CEnum(SerialisableDataclass):
|
||||
name: str
|
||||
values: List[CEnumVal]
|
||||
typedef: bool = False
|
||||
|
||||
def __str__(self) -> str:
|
||||
if self.typedef:
|
||||
header = "typedef enum {\n"
|
||||
footer = f"}} {self.name};\n"
|
||||
else:
|
||||
header = f"enum {self.name} {{\n"
|
||||
footer = "};\n"
|
||||
|
||||
values = ""
|
||||
for value in self.values:
|
||||
values += f" {str(value)},\n"
|
||||
|
||||
return header + values + footer
|
||||
|
||||
@classmethod
|
||||
def from_dict(cls: Type["CEnum"], d: Dict[str, Any]) -> "CEnum":
|
||||
e = CEnum(**d)
|
||||
e.values = [CEnumVal.from_dict(v) for v in e.values if isinstance(v, dict)]
|
||||
return e
|
||||
|
||||
|
||||
@dataclass
|
||||
class CMacro(SerialisableDataclass):
|
||||
name: str
|
||||
value: str
|
||||
|
||||
def __str__(self) -> str:
|
||||
return f"#define {self.name} {self.value}\n"
|
||||
|
||||
|
||||
@dataclass
|
||||
class CStruct(SerialisableDataclass):
|
||||
name: str
|
||||
cargs: List["CArg"]
|
||||
typedef_name: Optional[str] = None
|
||||
|
||||
def __str__(self) -> str:
|
||||
return self.declare() + self.define()
|
||||
|
||||
def declare(self) -> str:
|
||||
declaration = f"typedef struct {self.name} {self.typedef_name if self.typedef_name is not None else self.name};\n"
|
||||
return declaration
|
||||
|
||||
def define(self):
|
||||
definition = f"struct {self.name} {{\n"
|
||||
args = ""
|
||||
for arg in self.cargs:
|
||||
args += f" {str(arg)};\n"
|
||||
footer = "};\n"
|
||||
|
||||
return definition + args + footer;
|
||||
|
||||
@classmethod
|
||||
def from_dict(cls: Type["CStruct"], d: Dict[str, Any]) -> "CStruct":
|
||||
s = CStruct(**d)
|
||||
s.cargs = [CArg.from_dict(v) for v in s.cargs if isinstance(v, dict)]
|
||||
return s
|
||||
|
||||
|
||||
CUserType = Union[CStruct, CEnum]
|
||||
CDataType = Union[CType, CUserType, str]
|
||||
|
||||
|
||||
@dataclass
|
||||
class CArg(SerialisableDataclass):
|
||||
name: str
|
||||
_type: CDataType
|
||||
array: bool = False
|
||||
pointer: CPointer = field(default_factory=CPointer)
|
||||
qualifier: CQualifier = CQualifier.NONE
|
||||
|
||||
def __str__(self) -> str:
|
||||
qualifier = str(self.qualifier)
|
||||
_type = get_datatype_string(self._type) + " "
|
||||
pointer = str(self.pointer)
|
||||
array = "[]" if self.array else ""
|
||||
|
||||
return qualifier + _type + pointer + self.name + array
|
||||
|
||||
@classmethod
|
||||
def from_dict(cls: Type["CArg"], d: Dict[str, Any]) -> "CArg":
|
||||
arg = CArg(**d)
|
||||
arg._type = CArg.to_cdatatype(arg._type)
|
||||
|
||||
if isinstance(arg.pointer, dict):
|
||||
arg.pointer = CPointer.from_dict(arg.pointer)
|
||||
|
||||
arg.qualifier = CArg.to_enum_value(arg.qualifier, CQualifier)
|
||||
|
||||
return arg
|
||||
|
||||
|
||||
@dataclass
|
||||
class CFunc(SerialisableDataclass):
|
||||
name: str
|
||||
ret_type: CDataType
|
||||
args: List[CArg]
|
||||
body: str
|
||||
pointer: CPointer = field(default_factory=CPointer)
|
||||
qualifiers: List[CQualifier] = field(default_factory=list)
|
||||
|
||||
def __str__(self) -> str:
|
||||
qualifiers = ""
|
||||
for qualifier in self.qualifiers:
|
||||
if qualifier == CQualifier.NONE:
|
||||
continue
|
||||
if len(qualifiers) > 0:
|
||||
qualifiers += " "
|
||||
qualifiers += f"{str(qualifier)}"
|
||||
|
||||
args = ""
|
||||
for i, arg in enumerate(self.args):
|
||||
args += f"{str(arg)}"
|
||||
if i + 1 < len(self.args):
|
||||
args += ", "
|
||||
|
||||
return qualifiers + get_datatype_string(self.ret_type) + " " + str(self.pointer) + self.name + f"({args})"
|
||||
|
||||
def declare(self) -> str:
|
||||
return f"{str(self)};\n"
|
||||
|
||||
def define(self) -> str:
|
||||
return f"{str(self)} {{\n{self.body}\n}}\n\n"
|
||||
|
||||
@classmethod
|
||||
def from_dict(cls: Type["CFunc"], d: Dict[str, Any]) -> "CFunc":
|
||||
f = CFunc(**d)
|
||||
f.ret_type = CFunc.to_cdatatype(f.ret_type)
|
||||
f.args = [CArg.from_dict(v) for v in f.args if isinstance(v, dict)]
|
||||
f.qualifiers = [CFunc.to_enum_value(v, CQualifier) for v in f.qualifiers]
|
||||
|
||||
if isinstance(f.pointer, dict):
|
||||
f.pointer = CPointer.from_dict(f.pointer)
|
||||
|
||||
return f
|
||||
|
||||
|
||||
@dataclass
|
||||
class CInclude(SerialisableDataclass):
|
||||
header: Union[str, "CHeader"]
|
||||
local: bool = False
|
||||
same_dir: bool = False
|
||||
|
||||
def __str__(self) -> str:
|
||||
if isinstance(self.header, CHeader):
|
||||
name = f"{self.header.name}.{self.header.extension}"
|
||||
else:
|
||||
name = self.header
|
||||
|
||||
if self.local:
|
||||
open_symbol = '"'
|
||||
close_symbol = '"'
|
||||
|
||||
if self.same_dir:
|
||||
name = f"./{name}"
|
||||
else:
|
||||
open_symbol = '<'
|
||||
close_symbol = '>'
|
||||
|
||||
return f"#include {open_symbol}{name}{close_symbol}\n"
|
||||
|
||||
@classmethod
|
||||
def from_dict(cls: Type["CInclude"], d: Dict[str, Any]) -> "CInclude":
|
||||
inc = CInclude(**d)
|
||||
|
||||
if isinstance(inc.header, dict):
|
||||
inc.header = CHeader.from_dict(inc.header)
|
||||
|
||||
return inc
|
||||
|
||||
|
||||
@dataclass
|
||||
class CFile(SerialisableDataclass):
|
||||
name: str
|
||||
extension: str
|
||||
includes: List[CInclude] = field(default_factory=list)
|
||||
types: List[CUserType] = field(default_factory=list)
|
||||
funcs: List[CFunc] = field(default_factory=list)
|
||||
decl_types: List[CStruct] = field(default_factory=list)
|
||||
macros: List[CMacro] = field(default_factory=list)
|
||||
c_macros: List[CMacro] = field(default_factory=list)
|
||||
cpp_macros: List[CMacro] = field(default_factory=list)
|
||||
|
||||
def save(self, output_dir: Path):
|
||||
self.includes.extend(
|
||||
[
|
||||
CInclude(
|
||||
header=str(convert_to_relative(WAPP_SRC_ROOT / "common" / "aliases" / "aliases.h", output_dir)).replace("\\", "/"),
|
||||
local=True,
|
||||
),
|
||||
CInclude(
|
||||
header=str(convert_to_relative(WAPP_SRC_ROOT / "common" / "platform" / "platform.h", output_dir)).replace("\\", "/"),
|
||||
local=True,
|
||||
)
|
||||
]
|
||||
)
|
||||
output_file = output_dir / f"{self.name}.{self.extension}"
|
||||
with open(output_file, "w+") as outfile:
|
||||
outfile.write(str(self))
|
||||
|
||||
def __str__(self) -> str:
|
||||
return """\
|
||||
/**
|
||||
* THIS FILE IS AUTOMATICALLY GENERATED. ANY MODIFICATIONS TO IT WILL BE OVERWRITTEN.
|
||||
*/
|
||||
|
||||
"""
|
||||
|
||||
@classmethod
|
||||
def from_dict(cls: Type["CFile"], d: Dict[str, Any]) -> "CFile":
|
||||
f = CFile(**d)
|
||||
f.deserialise_c_file_data()
|
||||
|
||||
return f
|
||||
|
||||
def deserialise_c_file_data(self) -> None:
|
||||
self.includes = [CInclude.from_dict(v) for v in self.includes if isinstance(v, dict)]
|
||||
self.types = [CFile.to_c_usertype(v) for v in self.types if isinstance(v, dict)]
|
||||
self.funcs = [CFunc.from_dict(v) for v in self.funcs if isinstance(v, dict)]
|
||||
self.decl_types = [CStruct.from_dict(v) for v in self.decl_types if isinstance(v, dict)]
|
||||
self.macros = [CMacro.from_dict(v) for v in self.macros if isinstance(v, dict)]
|
||||
self.c_macros = [CMacro.from_dict(v) for v in self.c_macros if isinstance(v, dict)]
|
||||
self.cpp_macros = [CMacro.from_dict(v) for v in self.cpp_macros if isinstance(v, dict)]
|
||||
|
||||
|
||||
@dataclass
|
||||
class CHeader(CFile):
|
||||
extension: str = "h"
|
||||
|
||||
def __str__(self) -> str:
|
||||
name_upper = self.name.upper()
|
||||
header_guard_name = f"{name_upper}_H"
|
||||
header_guard_open = f"#ifndef {header_guard_name}\n#define {header_guard_name}\n\n"
|
||||
header_guard_close = f"#endif // !{header_guard_name}\n"
|
||||
|
||||
c_linkage_open = "#ifdef WAPP_PLATFORM_CPP\nBEGIN_C_LINKAGE\n#endif // !WAPP_PLATFORM_CPP\n\n"
|
||||
c_linkage_close = "\n#ifdef WAPP_PLATFORM_CPP\nEND_C_LINKAGE\n#endif // !WAPP_PLATFORM_CPP\n\n"
|
||||
|
||||
includes = _get_includes_string(self.includes)
|
||||
|
||||
macros = ""
|
||||
for macro in self.macros:
|
||||
macros += str(macro)
|
||||
if len(macros) > 0:
|
||||
macros += "\n"
|
||||
|
||||
if len(self.cpp_macros) > 0:
|
||||
macros += "#ifdef WAPP_PLATFORM_CPP\n"
|
||||
for macro in self.cpp_macros:
|
||||
macros += str(macro)
|
||||
macros += "#else\n"
|
||||
for macro in self.c_macros:
|
||||
macros += str(macro)
|
||||
macros += "#endif // !WAPP_PLATFORM_CPP\n\n"
|
||||
|
||||
forward_declarations = ""
|
||||
for _type in self.decl_types:
|
||||
forward_declarations += _type.declare()
|
||||
if len(forward_declarations) > 0:
|
||||
forward_declarations += "\n"
|
||||
|
||||
types = ""
|
||||
for _type in self.types:
|
||||
types += str(_type) + "\n"
|
||||
|
||||
funcs = ""
|
||||
for func in self.funcs:
|
||||
funcs += func.declare()
|
||||
|
||||
return (
|
||||
super().__str__() +
|
||||
header_guard_open +
|
||||
includes +
|
||||
c_linkage_open +
|
||||
macros +
|
||||
forward_declarations +
|
||||
types +
|
||||
funcs +
|
||||
c_linkage_close +
|
||||
header_guard_close
|
||||
)
|
||||
|
||||
@classmethod
|
||||
def from_dict(cls: Type["CHeader"], d: Dict[str, Any]) -> "CHeader":
|
||||
return cast("CHeader", super().from_dict(d))
|
||||
|
||||
|
||||
@dataclass
|
||||
class CSource(CFile):
|
||||
extension: str = "c"
|
||||
internal_funcs: List[CFunc] = field(default_factory=list)
|
||||
|
||||
def __str__(self) -> str:
|
||||
includes = _get_includes_string(self.includes)
|
||||
|
||||
macros = ""
|
||||
for macro in self.macros:
|
||||
macros += str(macro)
|
||||
if len(macros) > 0:
|
||||
macros += "\n"
|
||||
|
||||
forward_declarations = ""
|
||||
for _type in self.decl_types:
|
||||
forward_declarations += _type.declare()
|
||||
if len(forward_declarations) > 0:
|
||||
forward_declarations += "\n"
|
||||
|
||||
types = ""
|
||||
for _type in self.types:
|
||||
types += str(_type) + "\n"
|
||||
|
||||
internal_funcs_decl = ""
|
||||
internal_funcs_def = ""
|
||||
for func in self.internal_funcs:
|
||||
internal_funcs_decl += func.declare()
|
||||
internal_funcs_def += func.define()
|
||||
|
||||
if len(internal_funcs_decl) > 0:
|
||||
internal_funcs_decl += "\n"
|
||||
|
||||
funcs = ""
|
||||
for func in self.funcs:
|
||||
funcs += func.define()
|
||||
|
||||
return (
|
||||
super().__str__() +
|
||||
includes +
|
||||
macros +
|
||||
forward_declarations +
|
||||
types +
|
||||
internal_funcs_decl +
|
||||
funcs +
|
||||
internal_funcs_def
|
||||
)
|
||||
|
||||
@classmethod
|
||||
def from_dict(cls: Type["CSource"], d: Dict[str, Any]) -> "CSource":
|
||||
s = CSource(**d)
|
||||
s.deserialise_c_file_data()
|
||||
s.internal_funcs = [CFunc.from_dict(v) for v in s.funcs if isinstance(v, dict)]
|
||||
return s
|
||||
|
||||
|
||||
def get_datatype_string(_type: CDataType) -> str:
|
||||
if isinstance(_type, CType):
|
||||
return str(_type)
|
||||
elif isinstance(_type, CStruct) or isinstance(_type, CEnum):
|
||||
return _type.name
|
||||
elif isinstance(_type, str):
|
||||
return _type
|
||||
|
||||
|
||||
def _get_includes_string(includes: List[CInclude]) -> str:
|
||||
output = ""
|
||||
for include in sorted(includes, key=lambda inc: inc.local, reverse=True):
|
||||
output += str(include)
|
||||
if len(output) > 0:
|
||||
output += "\n"
|
||||
|
||||
return output
|
339
codegen/dbl_list/make_dbl_list.py
Normal file
339
codegen/dbl_list/make_dbl_list.py
Normal file
@@ -0,0 +1,339 @@
|
||||
from pathlib import Path
|
||||
from dataclasses import dataclass, field
|
||||
from typing import List, Dict, Any, Type
|
||||
from codegen.constants import WAPP_SRC_ROOT
|
||||
from codegen.utils import load_func_body_from_file, convert_to_relative
|
||||
from codegen.datatypes import (
|
||||
CDataType,
|
||||
CMacro,
|
||||
CStruct,
|
||||
CFunc,
|
||||
CHeader,
|
||||
CSource,
|
||||
CArg,
|
||||
CType,
|
||||
CPointer,
|
||||
CPointerType,
|
||||
CQualifier,
|
||||
CInclude,
|
||||
SerialisableDataclass,
|
||||
get_datatype_string,
|
||||
)
|
||||
|
||||
|
||||
@dataclass
|
||||
class DblListData(SerialisableDataclass):
|
||||
node_typename: str
|
||||
list_typename: str
|
||||
hdr_decl_types: List[CStruct] = field(default_factory=list)
|
||||
src_decl_types: List[CStruct] = field(default_factory=list)
|
||||
|
||||
@classmethod
|
||||
def from_dict(cls: Type["DblListData"], d: Dict[str, Any]) -> "DblListData":
|
||||
data = DblListData(**d)
|
||||
data.hdr_decl_types = [CStruct.from_dict(v) for v in data.hdr_decl_types if isinstance(v, dict)]
|
||||
data.src_decl_types = [CStruct.from_dict(v) for v in data.src_decl_types if isinstance(v, dict)]
|
||||
return data
|
||||
|
||||
|
||||
def make_dbl_list(user_datatypes: Dict[CDataType, DblListData] = {}):
|
||||
def __format_func_body(
|
||||
filename: Path,
|
||||
type_string: str,
|
||||
type_string_upper: str,
|
||||
type_string_lower: str,
|
||||
node_typename: str,
|
||||
list_typename: str
|
||||
):
|
||||
return load_func_body_from_file(filename).format(
|
||||
T=type_string,
|
||||
NodeType=node_typename,
|
||||
ListType=list_typename,
|
||||
Tupper=type_string_upper,
|
||||
Tlower=type_string_lower,
|
||||
)
|
||||
|
||||
out_dir = WAPP_SRC_ROOT / "primitives" / "dbl_list"
|
||||
out_dir.mkdir(parents=True, exist_ok=True)
|
||||
|
||||
common_decl_types: List[CStruct] = []
|
||||
|
||||
datatypes: dict[CDataType, DblListData] = {
|
||||
CType.VOID: DblListData(node_typename="GenericNode", list_typename="GenericList"),
|
||||
"void *": DblListData(node_typename="VoidPNode", list_typename="VoidPList"),
|
||||
"Str8": DblListData(
|
||||
node_typename="Str8Node",
|
||||
list_typename="Str8List",
|
||||
hdr_decl_types=[
|
||||
CStruct(name="str8", cargs=[], typedef_name="Str8"),
|
||||
],
|
||||
),
|
||||
}
|
||||
|
||||
for _type in CType:
|
||||
if _type == CType.VOID:
|
||||
continue
|
||||
|
||||
type_title = _type.value.title()
|
||||
datatypes[_type] = DblListData(
|
||||
node_typename=f"{type_title}Node",
|
||||
list_typename=f"{type_title}List",
|
||||
)
|
||||
|
||||
datatypes.update(user_datatypes)
|
||||
|
||||
snippets_dir = Path(__file__).parent / "snippets"
|
||||
|
||||
header = CHeader(
|
||||
name="dbl_list",
|
||||
decl_types=[*common_decl_types],
|
||||
includes=[],
|
||||
types=[],
|
||||
funcs=[]
|
||||
)
|
||||
|
||||
source = CSource(
|
||||
name=header.name,
|
||||
decl_types=[*common_decl_types],
|
||||
includes=[
|
||||
CInclude(header, local=True, same_dir=True),
|
||||
CInclude(
|
||||
header=str(convert_to_relative(WAPP_SRC_ROOT / "common" / "assert" / "assert.h", out_dir)).replace("\\", "/"),
|
||||
local=True
|
||||
),
|
||||
CInclude(header="stddef.h"),
|
||||
],
|
||||
internal_funcs=[],
|
||||
funcs=header.funcs
|
||||
)
|
||||
|
||||
for _type, dbl_list_data in datatypes.items():
|
||||
type_string = get_datatype_string(_type)
|
||||
clean_type_string = type_string.replace(" ", "").replace("*", "_ptr")
|
||||
type_string_upper = clean_type_string.upper()
|
||||
type_string_lower = clean_type_string.lower()
|
||||
|
||||
node = CStruct(
|
||||
name=dbl_list_data.node_typename,
|
||||
cargs=[
|
||||
CArg(name="item", _type=type_string, pointer=CPointer(_type=CPointerType.SINGLE)),
|
||||
],
|
||||
)
|
||||
node.cargs.extend([
|
||||
CArg(name="prev", _type=node, pointer=CPointer(_type=CPointerType.SINGLE)),
|
||||
CArg(name="next", _type=node, pointer=CPointer(_type=CPointerType.SINGLE)),
|
||||
])
|
||||
|
||||
dl_list = CStruct(
|
||||
name=dbl_list_data.list_typename,
|
||||
cargs=[
|
||||
CArg(name="first", _type=node, pointer=CPointer(_type=CPointerType.SINGLE)),
|
||||
CArg(name="last", _type=node, pointer=CPointer(_type=CPointerType.SINGLE)),
|
||||
CArg(name="node_count", _type=CType.U64),
|
||||
],
|
||||
)
|
||||
|
||||
header.types.extend([node, dl_list])
|
||||
header.decl_types.extend(dbl_list_data.hdr_decl_types)
|
||||
source.decl_types.extend(dbl_list_data.src_decl_types)
|
||||
if isinstance(_type, CType) and _type == CType.VOID:
|
||||
# Don't define any functions for the generic node and list
|
||||
continue
|
||||
|
||||
node_cmacro = CMacro(
|
||||
name=f"wapp_{type_string_lower}_list_node(ITEM_PTR)",
|
||||
value=__format_func_body(
|
||||
filename=snippets_dir / "list_node",
|
||||
type_string=type_string,
|
||||
type_string_upper=type_string_upper,
|
||||
type_string_lower=type_string_lower,
|
||||
node_typename=dbl_list_data.node_typename,
|
||||
list_typename=dbl_list_data.list_typename
|
||||
),
|
||||
)
|
||||
|
||||
node_cppmacro = CMacro(
|
||||
name=f"wapp_{type_string_lower}_list_node(ITEM_PTR)",
|
||||
value=__format_func_body(
|
||||
filename=snippets_dir / "list_node_cpp",
|
||||
type_string=type_string,
|
||||
type_string_upper=type_string_upper,
|
||||
type_string_lower=type_string_lower,
|
||||
node_typename=dbl_list_data.node_typename,
|
||||
list_typename=dbl_list_data.list_typename
|
||||
),
|
||||
)
|
||||
|
||||
get_func = CFunc(
|
||||
name=f"wapp_{type_string_lower}_list_get",
|
||||
ret_type=node,
|
||||
args=[
|
||||
CArg(name="list", _type=dl_list, pointer=CPointer(CPointerType.SINGLE), qualifier=CQualifier.CONST),
|
||||
CArg(name="index", _type=CType.U64),
|
||||
],
|
||||
body=__format_func_body(
|
||||
filename=snippets_dir / "list_get",
|
||||
type_string=type_string,
|
||||
type_string_upper=type_string_upper,
|
||||
type_string_lower=type_string_lower,
|
||||
node_typename=dbl_list_data.node_typename,
|
||||
list_typename=dbl_list_data.list_typename
|
||||
),
|
||||
pointer=CPointer(CPointerType.SINGLE),
|
||||
)
|
||||
|
||||
push_front_func = CFunc(
|
||||
name=f"wapp_{type_string_lower}_list_push_front",
|
||||
ret_type=CType.VOID,
|
||||
args=[
|
||||
CArg(name="list", _type=dl_list, pointer=CPointer(CPointerType.SINGLE)),
|
||||
CArg(name="node", _type=node, pointer=CPointer(CPointerType.SINGLE)),
|
||||
],
|
||||
body=__format_func_body(
|
||||
filename=snippets_dir / "list_push_front",
|
||||
type_string=type_string,
|
||||
type_string_upper=type_string_upper,
|
||||
type_string_lower=type_string_lower,
|
||||
node_typename=dbl_list_data.node_typename,
|
||||
list_typename=dbl_list_data.list_typename
|
||||
),
|
||||
)
|
||||
|
||||
push_back_func = CFunc(
|
||||
name=f"wapp_{type_string_lower}_list_push_back",
|
||||
ret_type=CType.VOID,
|
||||
args=[
|
||||
CArg(name="list", _type=dl_list, pointer=CPointer(CPointerType.SINGLE)),
|
||||
CArg(name="node", _type=node, pointer=CPointer(CPointerType.SINGLE)),
|
||||
],
|
||||
body=__format_func_body(
|
||||
filename=snippets_dir / "list_push_back",
|
||||
type_string=type_string,
|
||||
type_string_upper=type_string_upper,
|
||||
type_string_lower=type_string_lower,
|
||||
node_typename=dbl_list_data.node_typename,
|
||||
list_typename=dbl_list_data.list_typename
|
||||
),
|
||||
)
|
||||
|
||||
insert_func = CFunc(
|
||||
name=f"wapp_{type_string_lower}_list_insert",
|
||||
ret_type=CType.VOID,
|
||||
args=[
|
||||
CArg(name="list", _type=dl_list, pointer=CPointer(CPointerType.SINGLE)),
|
||||
CArg(name="node", _type=node, pointer=CPointer(CPointerType.SINGLE)),
|
||||
CArg(name="index", _type=CType.U64),
|
||||
],
|
||||
body=__format_func_body(
|
||||
filename=snippets_dir / "list_insert",
|
||||
type_string=type_string,
|
||||
type_string_upper=type_string_upper,
|
||||
type_string_lower=type_string_lower,
|
||||
node_typename=dbl_list_data.node_typename,
|
||||
list_typename=dbl_list_data.list_typename
|
||||
),
|
||||
)
|
||||
|
||||
pop_front_func = CFunc(
|
||||
name=f"wapp_{type_string_lower}_list_pop_front",
|
||||
ret_type=node,
|
||||
args=[
|
||||
CArg(name="list", _type=dl_list, pointer=CPointer(CPointerType.SINGLE)),
|
||||
],
|
||||
body=__format_func_body(
|
||||
filename=snippets_dir / "list_pop_front",
|
||||
type_string=type_string,
|
||||
type_string_upper=type_string_upper,
|
||||
type_string_lower=type_string_lower,
|
||||
node_typename=dbl_list_data.node_typename,
|
||||
list_typename=dbl_list_data.list_typename
|
||||
),
|
||||
pointer=CPointer(CPointerType.SINGLE),
|
||||
)
|
||||
|
||||
pop_back_func = CFunc(
|
||||
name=f"wapp_{type_string_lower}_list_pop_back",
|
||||
ret_type=node,
|
||||
args=[
|
||||
CArg(name="list", _type=dl_list, pointer=CPointer(CPointerType.SINGLE)),
|
||||
],
|
||||
body=__format_func_body(
|
||||
filename=snippets_dir / "list_pop_back",
|
||||
type_string=type_string,
|
||||
type_string_upper=type_string_upper,
|
||||
type_string_lower=type_string_lower,
|
||||
node_typename=dbl_list_data.node_typename,
|
||||
list_typename=dbl_list_data.list_typename
|
||||
),
|
||||
pointer=CPointer(CPointerType.SINGLE),
|
||||
)
|
||||
|
||||
remove_func = CFunc(
|
||||
name=f"wapp_{type_string_lower}_list_remove",
|
||||
ret_type=node,
|
||||
args=[
|
||||
CArg(name="list", _type=dl_list, pointer=CPointer(CPointerType.SINGLE)),
|
||||
CArg(name="index", _type=CType.U64),
|
||||
],
|
||||
body=__format_func_body(
|
||||
filename=snippets_dir / "list_remove",
|
||||
type_string=type_string,
|
||||
type_string_upper=type_string_upper,
|
||||
type_string_lower=type_string_lower,
|
||||
node_typename=dbl_list_data.node_typename,
|
||||
list_typename=dbl_list_data.list_typename
|
||||
),
|
||||
pointer=CPointer(CPointerType.SINGLE),
|
||||
)
|
||||
|
||||
empty_func = CFunc(
|
||||
name=f"wapp_{type_string_lower}_list_empty",
|
||||
ret_type=CType.VOID,
|
||||
args=[
|
||||
CArg(name="list", _type=dl_list, pointer=CPointer(CPointerType.SINGLE)),
|
||||
],
|
||||
body=__format_func_body(
|
||||
filename=snippets_dir / "list_empty",
|
||||
type_string=type_string,
|
||||
type_string_upper=type_string_upper,
|
||||
type_string_lower=type_string_lower,
|
||||
node_typename=dbl_list_data.node_typename,
|
||||
list_typename=dbl_list_data.list_typename
|
||||
),
|
||||
)
|
||||
|
||||
node_to_list_func = CFunc(
|
||||
name=f"{type_string_lower}_node_to_list",
|
||||
ret_type=dl_list,
|
||||
args=[
|
||||
CArg(name="node", _type=node, pointer=CPointer(CPointerType.SINGLE)),
|
||||
],
|
||||
body=__format_func_body(
|
||||
filename=snippets_dir / "node_to_list",
|
||||
type_string=type_string,
|
||||
type_string_upper=type_string_upper,
|
||||
type_string_lower=type_string_lower,
|
||||
node_typename=dbl_list_data.node_typename,
|
||||
list_typename=dbl_list_data.list_typename
|
||||
),
|
||||
qualifiers=[CQualifier.INTERNAL],
|
||||
)
|
||||
|
||||
header.c_macros.append(node_cmacro)
|
||||
header.cpp_macros.append(node_cppmacro)
|
||||
header.funcs.extend([
|
||||
get_func,
|
||||
push_front_func,
|
||||
push_back_func,
|
||||
insert_func,
|
||||
pop_front_func,
|
||||
pop_back_func,
|
||||
remove_func,
|
||||
empty_func,
|
||||
])
|
||||
|
||||
source.internal_funcs.append(node_to_list_func)
|
||||
source.funcs = header.funcs
|
||||
|
||||
header.save(out_dir)
|
||||
source.save(out_dir)
|
6
codegen/dbl_list/snippets/list_empty
Normal file
6
codegen/dbl_list/snippets/list_empty
Normal file
@@ -0,0 +1,6 @@
|
||||
wapp_debug_assert(list != NULL, "`list` should not be NULL");
|
||||
|
||||
u64 count = list->node_count;
|
||||
for (u64 i = 0; i < count; ++i) {{
|
||||
wapp_{Tlower}_list_pop_back(list);
|
||||
}}
|
11
codegen/dbl_list/snippets/list_get
Normal file
11
codegen/dbl_list/snippets/list_get
Normal file
@@ -0,0 +1,11 @@
|
||||
wapp_runtime_assert(index < list->node_count, "`index` is out of bounds");
|
||||
|
||||
{NodeType} *output = NULL;
|
||||
{NodeType} *current = list->first;
|
||||
for (u64 i = 1; i <= index; ++i) {{
|
||||
current = current->next;
|
||||
}}
|
||||
|
||||
output = current;
|
||||
|
||||
return output;
|
26
codegen/dbl_list/snippets/list_insert
Normal file
26
codegen/dbl_list/snippets/list_insert
Normal file
@@ -0,0 +1,26 @@
|
||||
wapp_debug_assert(list != NULL && node != NULL && (node->item) != NULL, "`list`, `node` and `node->item` should not be NULL");
|
||||
|
||||
if (index == 0) {{
|
||||
wapp_{Tlower}_list_push_front(list, node);
|
||||
return;
|
||||
}} else if (index == list->node_count) {{
|
||||
wapp_{Tlower}_list_push_back(list, node);
|
||||
return;
|
||||
}}
|
||||
|
||||
{NodeType} *dst_node = wapp_{Tlower}_list_get(list, index);
|
||||
if (!dst_node) {{
|
||||
return;
|
||||
}}
|
||||
|
||||
{ListType} node_list = {Tlower}_node_to_list(node);
|
||||
|
||||
list->node_count += node_list.node_count;
|
||||
|
||||
{NodeType} *prev = dst_node->prev;
|
||||
|
||||
dst_node->prev = node_list.last;
|
||||
prev->next = node_list.first;
|
||||
|
||||
node_list.first->prev = prev;
|
||||
node_list.last->next = dst_node;
|
1
codegen/dbl_list/snippets/list_node
Normal file
1
codegen/dbl_list/snippets/list_node
Normal file
@@ -0,0 +1 @@
|
||||
(({NodeType}){{.item = ITEM_PTR}})
|
1
codegen/dbl_list/snippets/list_node_cpp
Normal file
1
codegen/dbl_list/snippets/list_node_cpp
Normal file
@@ -0,0 +1 @@
|
||||
{NodeType}{{ITEM_PTR, nullptr, nullptr}}
|
22
codegen/dbl_list/snippets/list_pop_back
Normal file
22
codegen/dbl_list/snippets/list_pop_back
Normal file
@@ -0,0 +1,22 @@
|
||||
wapp_debug_assert(list != NULL, "`list` should not be NULL");
|
||||
|
||||
{NodeType} *output = NULL;
|
||||
|
||||
if (list->node_count == 0) {{
|
||||
goto RETURN_{Tupper}_LIST_POP_BACK;
|
||||
}}
|
||||
|
||||
output = list->last;
|
||||
|
||||
if (list->node_count == 1) {{
|
||||
*list = ({ListType}){{0}};
|
||||
goto RETURN_{Tupper}_LIST_POP_BACK;
|
||||
}}
|
||||
|
||||
--(list->node_count);
|
||||
list->last = output->prev;
|
||||
|
||||
output->prev = output->next = NULL;
|
||||
|
||||
RETURN_{Tupper}_LIST_POP_BACK:
|
||||
return output;
|
22
codegen/dbl_list/snippets/list_pop_front
Normal file
22
codegen/dbl_list/snippets/list_pop_front
Normal file
@@ -0,0 +1,22 @@
|
||||
wapp_debug_assert(list != NULL, "`list` should not be NULL");
|
||||
|
||||
{NodeType} *output = NULL;
|
||||
|
||||
if (list->node_count == 0) {{
|
||||
goto RETURN_{Tupper}_LIST_POP_FRONT;
|
||||
}}
|
||||
|
||||
output = list->first;
|
||||
|
||||
if (list->node_count == 1) {{
|
||||
*list = ({ListType}){{0}};
|
||||
goto RETURN_{Tupper}_LIST_POP_FRONT;
|
||||
}}
|
||||
|
||||
--(list->node_count);
|
||||
list->first = output->next;
|
||||
|
||||
output->prev = output->next = NULL;
|
||||
|
||||
RETURN_{Tupper}_LIST_POP_FRONT:
|
||||
return output;
|
18
codegen/dbl_list/snippets/list_push_back
Normal file
18
codegen/dbl_list/snippets/list_push_back
Normal file
@@ -0,0 +1,18 @@
|
||||
wapp_debug_assert(list != NULL && node != NULL && (node->item) != NULL, "`list`, `node` and `node->item` should not be NULL");
|
||||
|
||||
{ListType} node_list = {Tlower}_node_to_list(node);
|
||||
|
||||
if (list->node_count == 0) {{
|
||||
*list = node_list;
|
||||
return;
|
||||
}}
|
||||
|
||||
list->node_count += node_list.node_count;
|
||||
|
||||
{NodeType} *last = list->last;
|
||||
if (last) {{
|
||||
last->next = node_list.first;
|
||||
}}
|
||||
|
||||
list->last = node_list.last;
|
||||
node_list.first->prev = last;
|
18
codegen/dbl_list/snippets/list_push_front
Normal file
18
codegen/dbl_list/snippets/list_push_front
Normal file
@@ -0,0 +1,18 @@
|
||||
wapp_debug_assert(list != NULL && node != NULL && (node->item) != NULL, "`list`, `node` and `node->item` should not be NULL");
|
||||
|
||||
{ListType} node_list = {Tlower}_node_to_list(node);
|
||||
|
||||
if (list->node_count == 0) {{
|
||||
*list = node_list;
|
||||
return;
|
||||
}}
|
||||
|
||||
list->node_count += node_list.node_count;
|
||||
|
||||
{NodeType} *first = list->first;
|
||||
if (first) {{
|
||||
first->prev = node_list.last;
|
||||
}}
|
||||
|
||||
list->first = node_list.first;
|
||||
node_list.last->next = first;
|
26
codegen/dbl_list/snippets/list_remove
Normal file
26
codegen/dbl_list/snippets/list_remove
Normal file
@@ -0,0 +1,26 @@
|
||||
wapp_debug_assert(list != NULL, "`list` should not be NULL");
|
||||
|
||||
{NodeType} *output = NULL;
|
||||
|
||||
if (index == 0) {{
|
||||
output = wapp_{Tlower}_list_pop_front(list);
|
||||
goto RETURN_{Tupper}_LIST_REMOVE;
|
||||
}} else if (index == list->node_count) {{
|
||||
output = wapp_{Tlower}_list_pop_back(list);
|
||||
goto RETURN_{Tupper}_LIST_REMOVE;
|
||||
}}
|
||||
|
||||
output = wapp_{Tlower}_list_get(list, index);
|
||||
if (!output) {{
|
||||
goto RETURN_{Tupper}_LIST_REMOVE;
|
||||
}}
|
||||
|
||||
output->prev->next = output->next;
|
||||
output->next->prev = output->prev;
|
||||
|
||||
--(list->node_count);
|
||||
|
||||
output->prev = output->next = NULL;
|
||||
|
||||
RETURN_{Tupper}_LIST_REMOVE:
|
||||
return output;
|
13
codegen/dbl_list/snippets/node_to_list
Normal file
13
codegen/dbl_list/snippets/node_to_list
Normal file
@@ -0,0 +1,13 @@
|
||||
{ListType} output = {{.first = node, .last = node, .node_count = 1}};
|
||||
|
||||
while (output.first->prev != NULL) {{
|
||||
output.first = output.first->prev;
|
||||
++(output.node_count);
|
||||
}}
|
||||
|
||||
while (output.last->next != NULL) {{
|
||||
output.last = output.last->next;
|
||||
++(output.node_count);
|
||||
}}
|
||||
|
||||
return output;
|
18
codegen/utils.py
Normal file
18
codegen/utils.py
Normal file
@@ -0,0 +1,18 @@
|
||||
import os
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
def load_func_body_from_file(filename: Path) -> str:
|
||||
with open(filename, "r") as infile:
|
||||
return infile.read().rstrip()
|
||||
|
||||
|
||||
def convert_to_relative(path: Path, target: Path) -> Path:
|
||||
major = sys.version_info.major
|
||||
minor = sys.version_info.minor
|
||||
|
||||
if major >= 3 and minor >= 12:
|
||||
return path.relative_to(target, walk_up=True)
|
||||
else:
|
||||
return Path(os.path.relpath(str(path), start=str(target)))
|
29
codegen_custom_data_example.json
Normal file
29
codegen_custom_data_example.json
Normal file
@@ -0,0 +1,29 @@
|
||||
{
|
||||
"dbl_list_data": {
|
||||
"CustomType": {
|
||||
"node_typename": "CustomTypeNode",
|
||||
"list_typename": "CustomTypeList",
|
||||
"hdr_decl_types": [
|
||||
{
|
||||
"name": "custom_type",
|
||||
"cargs": [],
|
||||
"typedef_name": "CustomType"
|
||||
}
|
||||
],
|
||||
"src_decl_types": []
|
||||
}
|
||||
},
|
||||
"array_data": {
|
||||
"CustomType": {
|
||||
"array_typename": "CustomTypeArray",
|
||||
"hdr_decl_types": [
|
||||
{
|
||||
"name": "custom_type",
|
||||
"cargs": [],
|
||||
"typedef_name": "CustomType"
|
||||
}
|
||||
],
|
||||
"src_decl_types": []
|
||||
}
|
||||
}
|
||||
}
|
61
compile
61
compile
@@ -1,61 +0,0 @@
|
||||
#!/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)
|
21
scripts/header_install.sh
Normal file
21
scripts/header_install.sh
Normal file
@@ -0,0 +1,21 @@
|
||||
#!/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
|
@@ -1,13 +1,47 @@
|
||||
// vim:fileencoding=utf-8:foldmethod=marker
|
||||
|
||||
#ifndef ALIASES_H
|
||||
#define ALIASES_H
|
||||
|
||||
#include "../platform/platform.h"
|
||||
#include <stdint.h>
|
||||
|
||||
#if WAPP_PLATFORM_C_VERSION >= WAPP_PLATFORM_C11_VERSION && !defined(WAPP_PLATFORM_APPLE)
|
||||
#include <uchar.h>
|
||||
|
||||
#if WAPP_PLATFORM_C_VERSION >= WAPP_PLATFORM_C23_VERSION
|
||||
#define c8 char8_t
|
||||
#else
|
||||
#define c8 uint8_t
|
||||
#endif // !WAPP_PLATFORM_C23_VERSION
|
||||
|
||||
#define c16 char16_t
|
||||
#define c32 char32_t
|
||||
#else
|
||||
#define c8 uint8_t
|
||||
#define c16 uint16_t
|
||||
#define c32 uint32_t
|
||||
#endif // !WAPP_PLATFORM_C11_VERSION
|
||||
|
||||
#define u8 uint8_t
|
||||
#define u16 uint16_t
|
||||
#define u32 uint32_t
|
||||
#define u64 uint64_t
|
||||
|
||||
#define b32 uint32_t
|
||||
|
||||
#ifndef WAPP_PLATFORM_CPP
|
||||
|
||||
#ifndef false
|
||||
#define false (b32)0
|
||||
#endif // !false
|
||||
|
||||
#ifndef true
|
||||
#define true (b32)1
|
||||
#endif // !true
|
||||
|
||||
#endif // !WAPP_PLATFORM_CPP
|
||||
|
||||
#define i8 int8_t
|
||||
#define i16 int16_t
|
||||
#define i32 int32_t
|
||||
@@ -20,11 +54,14 @@
|
||||
#define uptr uintptr_t
|
||||
#define iptr intptr_t
|
||||
|
||||
#define external extern
|
||||
#define internal static
|
||||
#define persistent static
|
||||
|
||||
#ifdef __cplusplus
|
||||
#ifdef WAPP_PLATFORM_CPP
|
||||
#define class_mem static
|
||||
#endif // __cplusplus
|
||||
#define BEGIN_C_LINKAGE extern "C" {
|
||||
#define END_C_LINKAGE }
|
||||
#endif // WAPP_PLATFORM_CPP
|
||||
|
||||
#endif // !ALIASES_H
|
||||
|
41
src/common/assert/assert.h
Normal file
41
src/common/assert/assert.h
Normal file
@@ -0,0 +1,41 @@
|
||||
// vim:fileencoding=utf-8:foldmethod=marker
|
||||
|
||||
#ifndef WAPP_ASSERT_H
|
||||
#define WAPP_ASSERT_H
|
||||
|
||||
#include "../aliases/aliases.h"
|
||||
#include "../platform/platform.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <inttypes.h>
|
||||
|
||||
#ifdef WAPP_PLATFORM_CPP
|
||||
BEGIN_C_LINKAGE
|
||||
#endif // !WAPP_PLATFORM_CPP
|
||||
|
||||
#define wapp_static_assert(EXPR, MSG) extern char ASSERTION_FAILED[EXPR ? 1 : -1]
|
||||
#define wapp_runtime_assert(EXPR, MSG) __wapp_runtime_assert(EXPR, MSG)
|
||||
|
||||
#ifdef WAPP_DEBUG_ASSERT
|
||||
#define wapp_debug_assert(EXPR, MSG) wapp_runtime_assert(EXPR, MSG)
|
||||
#else
|
||||
#define wapp_debug_assert(EXPR, MSG)
|
||||
#endif
|
||||
|
||||
#define __wapp_runtime_assert(EXPR, MSG) do { \
|
||||
if (!(EXPR)) { \
|
||||
fprintf( \
|
||||
stderr, \
|
||||
"%s:%d (In function `%s`): Assertion failed (%" PRIu32 ")\nDiagnostic: %s\n\n", \
|
||||
__FILE__, __LINE__, __func__, \
|
||||
EXPR, MSG \
|
||||
); \
|
||||
abort(); \
|
||||
} \
|
||||
} while(false)
|
||||
|
||||
#ifdef WAPP_PLATFORM_CPP
|
||||
END_C_LINKAGE
|
||||
#endif // !WAPP_PLATFORM_CPP
|
||||
|
||||
#endif // !WAPP_ASSERT_H
|
@@ -1,115 +0,0 @@
|
||||
#include "mem_utils.h"
|
||||
#include "aliases.h"
|
||||
#include "platform.h"
|
||||
#include <assert.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#if defined(WAPP_PLATFORM_WINDOWS)
|
||||
#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,
|
||||
};
|
||||
|
||||
internal inline void *alloc_windows(void *addr, u64 size, MemAccess access,
|
||||
MemAllocFlags flags);
|
||||
#elif defined(WAPP_PLATFORM_POSIX)
|
||||
#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,
|
||||
};
|
||||
|
||||
internal inline void *alloc_posix(void *addr, u64 size, MemAccess access,
|
||||
MemAllocFlags flags);
|
||||
#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) {
|
||||
#if defined(WAPP_PLATFORM_WINDOWS)
|
||||
// Ensure memory is committed if it's meant to be initialised
|
||||
if (type == WAPP_MEM_INIT_INITIALISED) {
|
||||
flags |= WAPP_MEM_ALLOC_COMMIT;
|
||||
}
|
||||
|
||||
void *output = alloc_windows(addr, size, access, flags);
|
||||
#elif defined(WAPP_PLATFORM_POSIX)
|
||||
void *output = alloc_posix(addr, size, access, flags);
|
||||
#else
|
||||
return NULL;
|
||||
#endif
|
||||
|
||||
if (type == WAPP_MEM_INIT_INITIALISED) {
|
||||
memset(output, 0, size);
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
void wapp_mem_util_free(void *ptr, u64 size) {
|
||||
#if defined(WAPP_PLATFORM_WINDOWS)
|
||||
VirtualFree(ptr, size, MEM_RELEASE);
|
||||
#elif defined(WAPP_PLATFORM_POSIX)
|
||||
munmap(ptr, size);
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef WAPP_PLATFORM_WINDOWS
|
||||
internal inline void *alloc_windows(void *addr, u64 size, MemAccess access,
|
||||
MemAllocFlags flags) {
|
||||
return VirtualAlloc(addr, (SIZE_T)size, flags, access_types[access]);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(WAPP_PLATFORM_POSIX)
|
||||
internal inline void *alloc_posix(void *addr, u64 size, MemAccess access,
|
||||
MemAllocFlags flags) {
|
||||
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);
|
||||
}
|
||||
#endif
|
@@ -1,61 +0,0 @@
|
||||
#ifndef MEM_UTILS_H
|
||||
#define MEM_UTILS_H
|
||||
|
||||
#include "aliases.h"
|
||||
#include "platform.h"
|
||||
|
||||
#if defined(WAPP_PLATFORM_WINDOWS)
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <Windows.h>
|
||||
#include <memoryapi.h>
|
||||
#elif defined(WAPP_PLATFORM_POSIX)
|
||||
#include <sys/mman.h>
|
||||
#else
|
||||
#error "Unrecognised platform"
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#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_alloc_flags {
|
||||
#if defined(WAPP_PLATFORM_WINDOWS)
|
||||
WAPP_MEM_ALLOC_RESERVE = MEM_RESERVE,
|
||||
WAPP_MEM_ALLOC_COMMIT = MEM_COMMIT,
|
||||
#elif 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;
|
||||
|
||||
typedef enum mem_init_type {
|
||||
WAPP_MEM_INIT_UNINITIALISED,
|
||||
WAPP_MEM_INIT_INITIALISED,
|
||||
} MemInitType;
|
||||
|
||||
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);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif // __cplusplus
|
||||
|
||||
#endif // !MEM_UTILS_H
|
@@ -1,9 +1,56 @@
|
||||
// vim:fileencoding=utf-8:foldmethod=marker
|
||||
|
||||
#ifndef MISC_UTILS_H
|
||||
#define MISC_UTILS_H
|
||||
|
||||
#include "aliases.h"
|
||||
#include "../aliases/aliases.h"
|
||||
|
||||
#define wapp_misc_utils_padding_size(SIZE) \
|
||||
u8 reserved_padding[sizeof(void *) - ((SIZE) % sizeof(void *))]
|
||||
#ifdef WAPP_PLATFORM_CPP
|
||||
BEGIN_C_LINKAGE
|
||||
#endif // !WAPP_PLATFORM_CPP
|
||||
|
||||
#define KB(SIZE) (SIZE * 1024ull)
|
||||
#define MB(SIZE) (KB(SIZE) * 1024)
|
||||
#define GB(SIZE) (MB(SIZE) * 1024)
|
||||
#define TB(SIZE) (GB(SIZE) * 1024)
|
||||
|
||||
#define wapp_misc_utils_padding_size(SIZE) u8 reserved_padding[sizeof(void *) - ((SIZE) % sizeof(void *))]
|
||||
|
||||
#define U64_RSHIFT_OR_1(X) (((u64)X) | (((u64)X) >> 1))
|
||||
#define U64_RSHIFT_OR_2(X) (((u64)X) | (((u64)X) >> 2))
|
||||
#define U64_RSHIFT_OR_4(X) (((u64)X) | (((u64)X) >> 4))
|
||||
#define U64_RSHIFT_OR_8(X) (((u64)X) | (((u64)X) >> 8))
|
||||
#define U64_RSHIFT_OR_16(X) (((u64)X) | (((u64)X) >> 16))
|
||||
#define U64_RSHIFT_OR_32(X) (((u64)X) | (((u64)X) >> 32))
|
||||
#define wapp_misc_utils_u64_round_up_pow2(X) ( \
|
||||
( \
|
||||
U64_RSHIFT_OR_32( \
|
||||
U64_RSHIFT_OR_16( \
|
||||
U64_RSHIFT_OR_8( \
|
||||
U64_RSHIFT_OR_4( \
|
||||
U64_RSHIFT_OR_2( \
|
||||
U64_RSHIFT_OR_1(X - 1) \
|
||||
) \
|
||||
) \
|
||||
) \
|
||||
) \
|
||||
) \
|
||||
) + 1 \
|
||||
)
|
||||
|
||||
#ifdef WAPP_PLATFORM_CPP
|
||||
#define wapp_misc_utils_va_args_count(T, ...) va_args_count<T>(__VA_ARGS__)
|
||||
#else
|
||||
#define wapp_misc_utils_va_args_count(T, ...) (sizeof((T[]){__VA_ARGS__})/sizeof(T))
|
||||
#endif // !WAPP_PLATFORM_CPP
|
||||
|
||||
#ifdef WAPP_PLATFORM_CPP
|
||||
END_C_LINKAGE
|
||||
|
||||
template <typename T, typename... Args>
|
||||
constexpr u64 va_args_count(Args&&...) {
|
||||
return sizeof...(Args);
|
||||
}
|
||||
#endif // !WAPP_PLATFORM_CPP
|
||||
|
||||
#endif // !MISC_UTILS_H
|
||||
|
@@ -1,7 +1,8 @@
|
||||
// vim:fileencoding=utf-8:foldmethod=marker
|
||||
|
||||
#ifndef PLATFORM_H
|
||||
#define PLATFORM_H
|
||||
|
||||
// clang-format off
|
||||
#if defined(__ANDROID__)
|
||||
#define WAPP_PLATFORM_ANDROID
|
||||
#define WAPP_PLATFORM_POSIX
|
||||
@@ -58,6 +59,56 @@
|
||||
#else
|
||||
#error "Unrecognised platform"
|
||||
#endif
|
||||
// clang-format on
|
||||
|
||||
#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
|
||||
|
@@ -1,132 +0,0 @@
|
||||
#include "commander.h"
|
||||
#include "aliases.h"
|
||||
#include "shell_utils.h"
|
||||
#include <stdarg.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#define CMD_BUF_LEN 8192
|
||||
#define OUT_BUF_LEN 4096
|
||||
|
||||
internal inline 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);
|
||||
internal inline CMDError get_output_status(FILE *fp, i32 *status_out);
|
||||
|
||||
// clang-format off
|
||||
CMDResult run_command(CMDOutHandling out_handling, char *out_buf, u64 buf_size, ...) { // clang-format on
|
||||
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);
|
||||
}
|
||||
|
||||
va_end(args);
|
||||
|
||||
return execute_command(cmd, out_handling, out_buf, buf_size);
|
||||
}
|
||||
|
||||
internal inline CMDError build_command_from_args(char *cmd, u64 buf_len,
|
||||
va_list args) {
|
||||
u64 size = 0;
|
||||
u64 arg_len = 0;
|
||||
|
||||
const char *arg;
|
||||
while ((arg = va_arg(args, const char *))) {
|
||||
arg_len = strlen(arg);
|
||||
if (arg_len >= buf_len - size) {
|
||||
return SHELL_ERR_CMD_BUF_FULL;
|
||||
}
|
||||
|
||||
strcat(cmd, arg);
|
||||
cmd[size + arg_len] = ' ';
|
||||
|
||||
size += arg_len + 1;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
CMDError err = get_command_output(fp, out_handling, out_buf, buf_size);
|
||||
if (err > SHELL_ERR_NO_ERROR) {
|
||||
// Ensure process is closed on failure
|
||||
wapp_shell_utils_pclose(fp);
|
||||
return CMD_NO_EXIT(err);
|
||||
}
|
||||
|
||||
i32 st = EXIT_SUCCESS;
|
||||
err = get_output_status(fp, &st);
|
||||
if (err > SHELL_ERR_NO_ERROR) {
|
||||
return CMD_NO_EXIT(err);
|
||||
}
|
||||
|
||||
return (CMDResult){
|
||||
.exited = true,
|
||||
.exit_code = st,
|
||||
.error = SHELL_ERR_NO_ERROR,
|
||||
};
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
u64 buf_filled = 0;
|
||||
while (fgets(out, max_out_length, fp)) {
|
||||
if (out_handling == SHELL_OUTPUT_CAPTURE && out_buf != NULL) {
|
||||
buf_filled += strlen(out);
|
||||
if (buf_filled >= buf_size) {
|
||||
return SHELL_ERR_OUT_BUF_FULL;
|
||||
}
|
||||
|
||||
strcat(out_buf, out);
|
||||
} else if (out_handling == SHELL_OUTPUT_PRINT) {
|
||||
printf("%s", out);
|
||||
}
|
||||
}
|
||||
|
||||
return SHELL_ERR_NO_ERROR;
|
||||
}
|
||||
|
||||
internal inline CMDError get_output_status(FILE *fp, i32 *status_out) {
|
||||
#ifdef WAPP_PLATFORM_WINDOWS
|
||||
if (!feof(fp)) {
|
||||
// Ensure process is closed on failure
|
||||
wapp_shell_utils_pclose(fp);
|
||||
return SHELL_ERR_PROC_EXIT_FAIL;
|
||||
}
|
||||
#endif /* ifdef WAPP_PLATFORM_WINDOWS */
|
||||
|
||||
*status_out = wapp_shell_utils_pclose(fp);
|
||||
|
||||
#ifdef WAPP_PLATFORM_POSIX
|
||||
if (!WIFEXITED(*status_out)) {
|
||||
return SHELL_ERR_PROC_EXIT_FAIL;
|
||||
}
|
||||
|
||||
*status_out = WEXITSTATUS(*status_out);
|
||||
#endif /* ifdef WAPP_PLATFORM_WINDOWS */
|
||||
|
||||
return SHELL_ERR_NO_ERROR;
|
||||
}
|
@@ -1,46 +0,0 @@
|
||||
#ifndef COMMANDER_H
|
||||
#define COMMANDER_H
|
||||
|
||||
#include "aliases.h"
|
||||
#include <stdbool.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#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__, NULL)
|
||||
|
||||
typedef enum {
|
||||
SHELL_OUTPUT_DISCARD,
|
||||
SHELL_OUTPUT_PRINT,
|
||||
SHELL_OUTPUT_CAPTURE,
|
||||
} CMDOutHandling;
|
||||
|
||||
typedef enum {
|
||||
SHELL_ERR_NO_ERROR,
|
||||
SHELL_ERR_CMD_BUF_FULL,
|
||||
SHELL_ERR_PROC_START_FAIL,
|
||||
SHELL_ERR_OUT_BUF_FULL,
|
||||
SHELL_ERR_PROC_EXIT_FAIL,
|
||||
} CMDError;
|
||||
|
||||
typedef struct commander_result CMDResult;
|
||||
struct commander_result {
|
||||
bool exited;
|
||||
int exit_code;
|
||||
CMDError error;
|
||||
};
|
||||
|
||||
// clang-format off
|
||||
CMDResult run_command(CMDOutHandling out_handling, char *out_buf, u64 buf_size, ...);
|
||||
// clang-format on
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif // __cplusplus
|
||||
|
||||
#endif // !COMMANDER_H
|
@@ -1,101 +0,0 @@
|
||||
#include "termcolour.h"
|
||||
#include "aliases.h"
|
||||
#include "platform.h"
|
||||
#include <stdio.h>
|
||||
|
||||
internal void print_coloured_text(const TerminalColourist *colourist,
|
||||
const char *text);
|
||||
|
||||
#ifdef WAPP_PLATFORM_WINDOWS
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <Windows.h>
|
||||
|
||||
internal WORD colours[COUNT_TERM_COLOUR] = {
|
||||
[WAPP_TERM_COLOUR_FG_BLACK] = 0,
|
||||
[WAPP_TERM_COLOUR_FG_RED] = FOREGROUND_RED,
|
||||
[WAPP_TERM_COLOUR_FG_GREEN] = FOREGROUND_GREEN,
|
||||
[WAPP_TERM_COLOUR_FG_BLUE] = FOREGROUND_BLUE,
|
||||
[WAPP_TERM_COLOUR_FG_CYAN] = FOREGROUND_GREEN | FOREGROUND_BLUE,
|
||||
[WAPP_TERM_COLOUR_FG_MAGENTA] = FOREGROUND_RED | FOREGROUND_BLUE,
|
||||
[WAPP_TERM_COLOUR_FG_YELLOW] = FOREGROUND_RED | FOREGROUND_GREEN,
|
||||
[WAPP_TERM_COLOUR_FG_WHITE] =
|
||||
FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE,
|
||||
[WAPP_TERM_COLOUR_FG_BR_BLACK] = FOREGROUND_INTENSITY,
|
||||
[WAPP_TERM_COLOUR_FG_BR_RED] = FOREGROUND_RED | FOREGROUND_INTENSITY,
|
||||
[WAPP_TERM_COLOUR_FG_BR_GREEN] = FOREGROUND_GREEN | FOREGROUND_INTENSITY,
|
||||
[WAPP_TERM_COLOUR_FG_BR_BLUE] = FOREGROUND_BLUE | FOREGROUND_INTENSITY,
|
||||
[WAPP_TERM_COLOUR_FG_BR_CYAN] =
|
||||
FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY,
|
||||
[WAPP_TERM_COLOUR_FG_BR_MAGENTA] =
|
||||
FOREGROUND_RED | FOREGROUND_BLUE | FOREGROUND_INTENSITY,
|
||||
[WAPP_TERM_COLOUR_FG_BR_YELLOW] =
|
||||
FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_INTENSITY,
|
||||
[WAPP_TERM_COLOUR_FG_BR_WHITE] = FOREGROUND_RED | FOREGROUND_GREEN |
|
||||
FOREGROUND_BLUE | FOREGROUND_INTENSITY,
|
||||
};
|
||||
#else
|
||||
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",
|
||||
};
|
||||
#endif /* ifdef WAPP_PLATFORM_WINDOWS */
|
||||
|
||||
TerminalColourist wapp_shell_termcolour_get_colourist(void) {
|
||||
TerminalColourist colourist;
|
||||
|
||||
#ifdef WAPP_PLATFORM_WINDOWS
|
||||
// create handle
|
||||
colourist.handle = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||
|
||||
// get console colour information
|
||||
CONSOLE_SCREEN_BUFFER_INFO csbi;
|
||||
GetConsoleScreenBufferInfo(colourist.handle, &csbi);
|
||||
colourist.default_colour = csbi.wAttributes;
|
||||
#else
|
||||
colourist.default_colour = "\033[0m";
|
||||
#endif // ifdef WAPP_PLATFORM_WINDOWS
|
||||
|
||||
colourist.current_colour = colourist.default_colour;
|
||||
|
||||
return colourist;
|
||||
}
|
||||
|
||||
void wapp_shell_termcolour_print_text(TerminalColourist *colourist,
|
||||
const char *text, TerminalColour colour) {
|
||||
if (colour < WAPP_TERM_COLOUR_FG_BLACK ||
|
||||
colour > WAPP_TERM_COLOUR_FG_BR_WHITE) {
|
||||
return;
|
||||
}
|
||||
|
||||
colourist->current_colour = colours[colour];
|
||||
print_coloured_text(colourist, text);
|
||||
}
|
||||
|
||||
void wapp_shell_termcolour_clear_colour(TerminalColourist *colourist) {
|
||||
colourist->current_colour = colourist->default_colour;
|
||||
print_coloured_text(colourist, "");
|
||||
}
|
||||
|
||||
internal void print_coloured_text(const TerminalColourist *colourist,
|
||||
const char *text) {
|
||||
#ifdef WAPP_PLATFORM_WINDOWS
|
||||
SetConsoleTextAttribute(colourist->handle, colourist->current_colour);
|
||||
printf("%s", text);
|
||||
#else
|
||||
printf("%s%s", colourist->current_colour, text);
|
||||
#endif // ifdef WAPP_PLATFORM_WINDOWS
|
||||
}
|
@@ -1,64 +0,0 @@
|
||||
#ifndef TERM_COLOUR_H
|
||||
#define TERM_COLOUR_H
|
||||
|
||||
#include "aliases.h"
|
||||
#include "misc_utils.h"
|
||||
#include "platform.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif // __cplusplus
|
||||
|
||||
typedef enum {
|
||||
WAPP_TERM_COLOUR_FG_BLACK,
|
||||
WAPP_TERM_COLOUR_FG_RED,
|
||||
WAPP_TERM_COLOUR_FG_GREEN,
|
||||
WAPP_TERM_COLOUR_FG_BLUE,
|
||||
WAPP_TERM_COLOUR_FG_CYAN,
|
||||
WAPP_TERM_COLOUR_FG_MAGENTA,
|
||||
WAPP_TERM_COLOUR_FG_YELLOW,
|
||||
WAPP_TERM_COLOUR_FG_WHITE,
|
||||
WAPP_TERM_COLOUR_FG_BR_BLACK,
|
||||
WAPP_TERM_COLOUR_FG_BR_RED,
|
||||
WAPP_TERM_COLOUR_FG_BR_GREEN,
|
||||
WAPP_TERM_COLOUR_FG_BR_BLUE,
|
||||
WAPP_TERM_COLOUR_FG_BR_CYAN,
|
||||
WAPP_TERM_COLOUR_FG_BR_MAGENTA,
|
||||
WAPP_TERM_COLOUR_FG_BR_YELLOW,
|
||||
WAPP_TERM_COLOUR_FG_BR_WHITE,
|
||||
|
||||
COUNT_TERM_COLOUR,
|
||||
} TerminalColour;
|
||||
|
||||
typedef struct terminal_colourist TerminalColourist;
|
||||
|
||||
// clang-format off
|
||||
#ifdef WAPP_PLATFORM_WINDOWS
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <Windows.h>
|
||||
#include <WinCon.h>
|
||||
|
||||
struct terminal_colourist {
|
||||
HANDLE handle;
|
||||
WORD default_colour;
|
||||
WORD current_colour;
|
||||
wapp_misc_utils_padding_size(sizeof(HANDLE) + sizeof(WORD) + sizeof(WORD));
|
||||
};
|
||||
#else
|
||||
struct terminal_colourist {
|
||||
const char *default_colour;
|
||||
const char *current_colour;
|
||||
};
|
||||
#endif // WAPP_PLATFORM_WINDOWS
|
||||
// clang-format on
|
||||
|
||||
TerminalColourist wapp_shell_termcolour_get_colourist(void);
|
||||
void wapp_shell_termcolour_print_text(TerminalColourist *colourist,
|
||||
const char *text, TerminalColour colour);
|
||||
void wapp_shell_termcolour_clear_colour(TerminalColourist *colourist);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif // __cplusplus
|
||||
|
||||
#endif // !TERM_COLOUR_H
|
@@ -1,16 +0,0 @@
|
||||
#ifndef SHELL_UTILS_H
|
||||
#define SHELL_UTILS_H
|
||||
|
||||
#include "platform.h"
|
||||
|
||||
// clang-format off
|
||||
#ifdef WAPP_PLATFORM_WINDOWS
|
||||
#define wapp_shell_utils_popen _popen
|
||||
#define wapp_shell_utils_pclose _pclose
|
||||
#else
|
||||
#define wapp_shell_utils_popen popen
|
||||
#define wapp_shell_utils_pclose pclose
|
||||
#endif /* ifdef WAPP_PLATFORM_WINDOWS */
|
||||
// clang-format on
|
||||
|
||||
#endif // !SHELL_UTILS_H
|
11
src/common/wapp_common.h
Normal file
11
src/common/wapp_common.h
Normal file
@@ -0,0 +1,11 @@
|
||||
// vim:fileencoding=utf-8:foldmethod=marker
|
||||
|
||||
#ifndef WAPP_COMMON_H
|
||||
#define WAPP_COMMON_H
|
||||
|
||||
#include "aliases/aliases.h"
|
||||
#include "assert/assert.h"
|
||||
#include "misc/misc_utils.h"
|
||||
#include "platform/platform.h"
|
||||
|
||||
#endif // !WAPP_COMMON_H
|
@@ -1,87 +0,0 @@
|
||||
#include "cpath.h"
|
||||
#include "aliases.h"
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#if defined(__unix__) || defined(__APPLE__) || defined(__ANDROID__)
|
||||
internal char path_sep = '/';
|
||||
#elif defined(_WIN32) || defined(_WIN64)
|
||||
internal char path_sep = '\\';
|
||||
#endif
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
void dirup(char *dst, u64 levels, const char *path) {
|
||||
if (levels < 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
u64 end_index = 0;
|
||||
u64 sep_count = 0;
|
||||
|
||||
u64 full_length;
|
||||
u64 length;
|
||||
length = full_length = strlen(path);
|
||||
|
||||
if (path[length - 1] == path_sep) {
|
||||
--length;
|
||||
}
|
||||
|
||||
for (i64 i = length - 1; i >= 0; --i) {
|
||||
if (path[i] == path_sep) {
|
||||
++sep_count;
|
||||
end_index = i;
|
||||
|
||||
if (sep_count == levels) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (sep_count < levels) {
|
||||
end_index = 0;
|
||||
}
|
||||
|
||||
if (dst == path) {
|
||||
memset(&dst[end_index], 0, full_length - end_index);
|
||||
} else {
|
||||
u64 dst_length = strlen(dst);
|
||||
memset(dst, 0, dst_length);
|
||||
strncpy(dst, path, end_index);
|
||||
}
|
||||
}
|
||||
|
||||
void join_root_and_leaf(const char *root, const char *leaf, char *dst) {
|
||||
u64 root_length = strlen(root);
|
||||
u64 root_end = root_length - 1;
|
||||
|
||||
u64 leaf_length = strlen(leaf);
|
||||
u64 leaf_start = 0;
|
||||
|
||||
if (root[root_end] == path_sep) {
|
||||
--root_end;
|
||||
}
|
||||
|
||||
if (leaf[leaf_start] == path_sep) {
|
||||
++leaf_start;
|
||||
}
|
||||
|
||||
memcpy(dst, root, ++root_end);
|
||||
|
||||
dst[root_end] = path_sep;
|
||||
|
||||
memcpy(&(dst[++root_end]), &(leaf[leaf_start]), leaf_length - leaf_start);
|
||||
}
|
@@ -1,25 +0,0 @@
|
||||
#ifndef PATH_UTILS_H
|
||||
#define PATH_UTILS_H
|
||||
|
||||
#include "aliases.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif // __cplusplus
|
||||
|
||||
#define NUMPARTS(...) \
|
||||
(sizeof((const char *[]){"", __VA_ARGS__}) / sizeof(const char *) - 1)
|
||||
|
||||
#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)
|
||||
|
||||
void join_path(char *dst, u64 count, ...);
|
||||
void dirup(char *dst, u64 levels, const char *path);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif // __cplusplus
|
||||
|
||||
#endif // !PATH_UTILS_H
|
103
src/core/file/file.c
Normal file
103
src/core/file/file.c
Normal file
@@ -0,0 +1,103 @@
|
||||
// vim:fileencoding=utf-8:foldmethod=marker
|
||||
|
||||
#include "file.h"
|
||||
#include "../os/cpath/cpath.h"
|
||||
#include "../../common/assert/assert.h"
|
||||
#include "../../common/aliases/aliases.h"
|
||||
#include "../../primitives/array/array.h"
|
||||
#include "../../primitives/strings/str8/str8.h"
|
||||
#include <stdio.h>
|
||||
|
||||
File *wapp_file_open(Str8RO *filepath, FileAccessMode mode) {
|
||||
persistent const char *modes[FILE_ACCESS_MODE_COUNT] = {
|
||||
[WAPP_FA_MODE_R] = "r",
|
||||
[WAPP_FA_MODE_W] = "w",
|
||||
[WAPP_FA_MODE_A] = "a",
|
||||
[WAPP_FA_MODE_R_EX] = "r+",
|
||||
[WAPP_FA_MODE_W_EX] = "w+",
|
||||
[WAPP_FA_MODE_A_EX] = "a+",
|
||||
[WAPP_FA_MODE_RB] = "rb",
|
||||
[WAPP_FA_MODE_WB] = "wb",
|
||||
[WAPP_FA_MODE_AB] = "ab",
|
||||
[WAPP_FA_MODE_RB_EX] = "rb+",
|
||||
[WAPP_FA_MODE_WB_EX] = "wb+",
|
||||
[WAPP_FA_MODE_AB_EX] = "ab+",
|
||||
[WAPP_FA_MODE_WX] = "wx",
|
||||
[WAPP_FA_MODE_WX_EX] = "wx+",
|
||||
[WAPP_FA_MODE_WBX] = "wbx",
|
||||
[WAPP_FA_MODE_WBX_EX] = "wbx+",
|
||||
};
|
||||
persistent c8 tmp[WAPP_PATH_MAX] = {0};
|
||||
wapp_debug_assert(filepath->size < WAPP_PATH_MAX, "`filepath` exceeds max path limit.");
|
||||
|
||||
memset(tmp, 0, WAPP_PATH_MAX);
|
||||
memcpy(tmp, filepath->buf, filepath->size);
|
||||
|
||||
return fopen((const char *)tmp, modes[mode]);
|
||||
}
|
||||
|
||||
u64 wapp_file_get_current_position(File *file) {
|
||||
wapp_debug_assert(file != NULL, "`file` should not be NULL.");
|
||||
return (u64)ftell(file);
|
||||
}
|
||||
|
||||
i32 wapp_file_seek(File *file, u64 offset, FileSeekOrigin origin) {
|
||||
wapp_debug_assert(file != NULL, "`file` should not be NULL.");
|
||||
return fseek(file, offset, origin);
|
||||
}
|
||||
|
||||
u64 wapp_file_get_length(File *file) {
|
||||
wapp_debug_assert(file != NULL, "`file` should not be NULL.");
|
||||
|
||||
u64 current = wapp_file_get_current_position(file);
|
||||
|
||||
wapp_file_seek(file, 0, WAPP_SEEK_END);
|
||||
|
||||
u64 output = ftell(file);
|
||||
|
||||
// Restore position
|
||||
wapp_file_seek(file, current, WAPP_SEEK_START);
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
u64 wapp_file_read(GenericArray *dst, File *file, u64 item_count) {
|
||||
wapp_debug_assert(dst != NULL && dst->items != NULL && file != NULL,
|
||||
"`dst`, `dst->items` and `file` should not be NULL.");
|
||||
|
||||
u64 file_length = wapp_file_get_length(file);
|
||||
u64 dst_byte_capacity = dst->item_size * dst->capacity;
|
||||
u64 req_byte_count = item_count * dst->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;
|
||||
}
|
||||
|
||||
dst->count = fread(dst->items, sizeof(u8), copy_byte_count, file) / dst->item_size;
|
||||
|
||||
return dst->count;
|
||||
}
|
||||
|
||||
u64 wapp_file_write(const GenericArray *src, File *file, u64 item_count) {
|
||||
wapp_debug_assert(src != NULL && src->items != NULL && file != NULL,
|
||||
"`src`, `src->items` and `file` should not be NULL.");
|
||||
|
||||
u64 src_byte_count = src->count * src->item_size;
|
||||
u64 req_byte_count = item_count * src->item_size;
|
||||
u64 to_copy = req_byte_count <= src_byte_count ? req_byte_count : src_byte_count;
|
||||
|
||||
return fwrite(src->items, sizeof(u8), to_copy, file);
|
||||
}
|
||||
|
||||
i32 wapp_file_flush(File *file) {
|
||||
wapp_debug_assert(file != NULL, "`file` should not be NULL.");
|
||||
return fflush(file);
|
||||
}
|
||||
|
||||
i32 wapp_file_close(File *file) {
|
||||
wapp_debug_assert(file != NULL, "`file` should not be NULL.");
|
||||
return fclose(file);
|
||||
}
|
72
src/core/file/file.h
Normal file
72
src/core/file/file.h
Normal file
@@ -0,0 +1,72 @@
|
||||
// vim:fileencoding=utf-8:foldmethod=marker
|
||||
|
||||
#ifndef FILE_H
|
||||
#define FILE_H
|
||||
|
||||
#include "../../common/aliases/aliases.h"
|
||||
#include "../../primitives/array/array.h"
|
||||
#include "../../primitives/strings/str8/str8.h"
|
||||
#include <stdio.h>
|
||||
|
||||
#ifdef WAPP_PLATFORM_CPP
|
||||
BEGIN_C_LINKAGE
|
||||
#endif // !WAPP_PLATFORM_CPP
|
||||
|
||||
#ifdef WAPP_PLATFORM_CPP
|
||||
#define wapp_file_item_to_array(ITEM) (GenericArray{&(ITEM), 1, 1, sizeof(ITEM)})
|
||||
#define wapp_file_array_to_item(TYPE, ARRAY) (sizeof(TYPE) == (ARRAY).item_size && (ARRAY).count == 1 ? \
|
||||
*((TYPE *)((ARRAY).items)) : \
|
||||
TYPE{})
|
||||
#else
|
||||
#define wapp_file_item_to_array(ITEM) ((GenericArray){.items = &(ITEM), \
|
||||
.count = 1, \
|
||||
.capacity = 1, \
|
||||
.item_size = sizeof(ITEM)})
|
||||
#define wapp_file_array_to_item(TYPE, ARRAY) (sizeof(TYPE) == (ARRAY).item_size && (ARRAY).count == 1 ? \
|
||||
*((TYPE *)((ARRAY).items)) : \
|
||||
(TYPE){0})
|
||||
#endif // !WAPP_PLATFORM_CPP
|
||||
|
||||
typedef FILE File;
|
||||
|
||||
typedef enum {
|
||||
WAPP_FA_MODE_R, // Equivalent to r
|
||||
WAPP_FA_MODE_W, // Equivalent to w
|
||||
WAPP_FA_MODE_A, // Equivalent to a
|
||||
WAPP_FA_MODE_R_EX, // Equivalent to r+
|
||||
WAPP_FA_MODE_W_EX, // Equivalent to w+
|
||||
WAPP_FA_MODE_A_EX, // Equivalent to a+
|
||||
WAPP_FA_MODE_RB, // Equivalent to rb
|
||||
WAPP_FA_MODE_WB, // Equivalent to wb
|
||||
WAPP_FA_MODE_AB, // Equivalent to ab
|
||||
WAPP_FA_MODE_RB_EX, // Equivalent to rb+
|
||||
WAPP_FA_MODE_WB_EX, // Equivalent to wb+
|
||||
WAPP_FA_MODE_AB_EX, // Equivalent to ab+
|
||||
WAPP_FA_MODE_WX, // Equivalent to wx
|
||||
WAPP_FA_MODE_WX_EX, // Equivalent to wx+
|
||||
WAPP_FA_MODE_WBX, // Equivalent to wbx
|
||||
WAPP_FA_MODE_WBX_EX, // Equivalent to wbx+
|
||||
|
||||
FILE_ACCESS_MODE_COUNT,
|
||||
} FileAccessMode;
|
||||
|
||||
typedef enum {
|
||||
WAPP_SEEK_START = SEEK_SET,
|
||||
WAPP_SEEK_CURRENT = SEEK_CUR,
|
||||
WAPP_SEEK_END = SEEK_END,
|
||||
} FileSeekOrigin;
|
||||
|
||||
File *wapp_file_open(Str8RO *filename, FileAccessMode mode);
|
||||
u64 wapp_file_get_current_position(File *file);
|
||||
i32 wapp_file_seek(File *file, u64 offset, FileSeekOrigin origin);
|
||||
u64 wapp_file_get_length(File *file);
|
||||
u64 wapp_file_read(GenericArray *dst, File *file, u64 item_count);
|
||||
u64 wapp_file_write(const GenericArray *src, File *file, u64 item_count);
|
||||
i32 wapp_file_flush(File *file);
|
||||
i32 wapp_file_close(File *file);
|
||||
|
||||
#ifdef WAPP_PLATFORM_CPP
|
||||
END_C_LINKAGE
|
||||
#endif // !WAPP_PLATFORM_CPP
|
||||
|
||||
#endif // !FILE_H
|
@@ -1,8 +1,11 @@
|
||||
// vim:fileencoding=utf-8:foldmethod=marker
|
||||
|
||||
#include "mem_arena.h"
|
||||
#include "aliases.h"
|
||||
#include "mem_utils.h"
|
||||
#include "misc_utils.h"
|
||||
#include <stdbool.h>
|
||||
#include "../utils/mem_utils.h"
|
||||
#include "../../../common/aliases/aliases.h"
|
||||
#include "../../../common/assert/assert.h"
|
||||
#include "../../../common/misc/misc_utils.h"
|
||||
#include "../../os/mem/mem_os.h"
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
@@ -12,23 +15,20 @@
|
||||
#define DEFAULT_ALIGNMENT (2 * sizeof(void *))
|
||||
#endif /* ifndef DEFAULT_ALIGNMENT */
|
||||
|
||||
#define ARENA_MINIMUM_CAPACITY 1024
|
||||
#define ARENA_MINIMUM_CAPACITY KB(16) // Allocate minimum of 4 pages
|
||||
|
||||
struct arena {
|
||||
u8 *buf;
|
||||
u8 *offset;
|
||||
u64 capacity;
|
||||
bool committed;
|
||||
b32 committed;
|
||||
|
||||
#ifdef WAPP_PLATFORM_WINDOWS
|
||||
wapp_misc_utils_padding_size(sizeof(u8 *) * 2 + sizeof(u64) + sizeof(bool));
|
||||
wapp_misc_utils_padding_size(sizeof(u8 *) * 2 + sizeof(u64) + sizeof(b32));
|
||||
#endif // ifdef WAPP_PLATFORM_WINDOWS
|
||||
};
|
||||
|
||||
// PUBLIC API
|
||||
|
||||
bool wapp_mem_arena_init(Arena **arena, u64 base_capacity, MemAllocFlags flags,
|
||||
bool zero_buffer) {
|
||||
b32 wapp_mem_arena_init_custom(Arena **arena, u64 base_capacity, MemAllocFlags flags, b32 zero_buffer) {
|
||||
if (!arena || *arena || base_capacity == 0) {
|
||||
return false;
|
||||
}
|
||||
@@ -39,23 +39,23 @@ bool wapp_mem_arena_init(Arena **arena, u64 base_capacity, MemAllocFlags flags,
|
||||
return false;
|
||||
}
|
||||
|
||||
u64 arena_capacity = base_capacity >= ARENA_MINIMUM_CAPACITY
|
||||
? base_capacity
|
||||
: ARENA_MINIMUM_CAPACITY;
|
||||
u64 arena_capacity = wapp_misc_utils_u64_round_up_pow2(
|
||||
base_capacity >= ARENA_MINIMUM_CAPACITY ?
|
||||
base_capacity :
|
||||
ARENA_MINIMUM_CAPACITY
|
||||
);
|
||||
|
||||
arena_ptr->buf = (u8 *)wapp_mem_util_alloc(
|
||||
NULL, arena_capacity, WAPP_MEM_ACCESS_READ_WRITE, flags,
|
||||
zero_buffer ? WAPP_MEM_INIT_INITIALISED : WAPP_MEM_INIT_UNINITIALISED);
|
||||
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;
|
||||
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;
|
||||
}
|
||||
@@ -65,9 +65,7 @@ void *wapp_mem_arena_alloc(Arena *arena, u64 size) {
|
||||
}
|
||||
|
||||
void *wapp_mem_arena_alloc_aligned(Arena *arena, u64 size, u64 alignment) {
|
||||
if (!arena) {
|
||||
return NULL;
|
||||
}
|
||||
wapp_debug_assert(arena != NULL, "`arena` should not be NULL");
|
||||
|
||||
u8 *alloc_start = arena->offset;
|
||||
|
||||
@@ -80,31 +78,60 @@ void *wapp_mem_arena_alloc_aligned(Arena *arena, u64 size, u64 alignment) {
|
||||
|
||||
#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);
|
||||
wapp_mem_util_alloc(alloc_start, (uptr)(arena->offset) - (uptr)(alloc_start),
|
||||
WAPP_MEM_ACCESS_READ_WRITE, WAPP_MEM_ALLOC_COMMIT,
|
||||
WAPP_MEM_INIT_UNINITIALISED);
|
||||
}
|
||||
#else
|
||||
memset(output, 0, size);
|
||||
#endif // ifdef WAPP_PLATFORM_WINDOWS
|
||||
|
||||
memset(output, 0, size);
|
||||
|
||||
return (void *)output;
|
||||
}
|
||||
|
||||
void wapp_mem_arena_clear(Arena *arena) {
|
||||
if (!arena) {
|
||||
return;
|
||||
void *wapp_mem_arena_realloc(Arena *arena, void *ptr, u64 old_size, u64 new_size) {
|
||||
if ((u8*)ptr < arena->buf || (u8*)ptr > arena->offset ||
|
||||
arena->offset + new_size >= arena->buf + arena->capacity) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void *new_ptr = wapp_mem_arena_alloc(arena, new_size);
|
||||
if (!new_ptr) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
u64 copy_size = new_size <= old_size ? new_size : old_size;
|
||||
memcpy(new_ptr, ptr, copy_size);
|
||||
|
||||
return new_ptr;
|
||||
}
|
||||
|
||||
void *wapp_mem_arena_realloc_aligned(Arena *arena, void *ptr, u64 old_size, u64 new_size, u64 alignment) {
|
||||
if ((u8*)ptr < arena->buf || (u8*)ptr > arena->offset ||
|
||||
arena->offset + new_size >= arena->buf + arena->capacity) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void *new_ptr = wapp_mem_arena_alloc_aligned(arena, new_size, alignment);
|
||||
if (!new_ptr) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
u64 copy_size = new_size <= old_size ? new_size : old_size;
|
||||
memcpy(new_ptr, ptr, copy_size);
|
||||
|
||||
return new_ptr;
|
||||
}
|
||||
|
||||
void wapp_mem_arena_clear(Arena *arena) {
|
||||
wapp_debug_assert(arena != NULL, "`arena` should not be NULL");
|
||||
|
||||
memset(arena->buf, 0, arena->offset - arena->buf);
|
||||
arena->offset = arena->buf;
|
||||
}
|
||||
|
||||
void wapp_mem_arena_destroy(Arena **arena) {
|
||||
if (!arena) {
|
||||
return;
|
||||
}
|
||||
wapp_debug_assert(arena != NULL && (*arena) != NULL, "`arena` double pointer is not valid");
|
||||
|
||||
Arena *arena_ptr = *arena;
|
||||
if (arena_ptr->buf) {
|
||||
|
@@ -1,37 +1,42 @@
|
||||
// vim:fileencoding=utf-8:foldmethod=marker
|
||||
|
||||
#ifndef MEM_ARENA_H
|
||||
#define MEM_ARENA_H
|
||||
|
||||
#include "aliases.h"
|
||||
#include "mem_utils.h"
|
||||
#include <stdbool.h>
|
||||
#include "../../../common/aliases/aliases.h"
|
||||
#include "../../../common/platform/platform.h"
|
||||
#include "../../os/mem/mem_os.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif // __cplusplus
|
||||
#ifdef WAPP_PLATFORM_CPP
|
||||
BEGIN_C_LINKAGE
|
||||
#endif // !WAPP_PLATFORM_CPP
|
||||
|
||||
typedef struct arena Arena;
|
||||
|
||||
#define wapp_mem_arena_init_default(arena_dptr, base_capacity) \
|
||||
(wapp_mem_arena_init(arena_dptr, base_capacity, WAPP_MEM_ALLOC_RESERVE, \
|
||||
false))
|
||||
#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(arena_dptr, base_capacity, \
|
||||
WAPP_MEM_ALLOC_RESERVE | WAPP_MEM_ALLOC_COMMIT, false))
|
||||
(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(arena_dptr, base_capacity, WAPP_MEM_ALLOC_RESERVE, true))
|
||||
(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(arena_dptr, base_capacity, \
|
||||
WAPP_MEM_ALLOC_RESERVE | WAPP_MEM_ALLOC_COMMIT, true))
|
||||
(wapp_mem_arena_init_custom(arena_dptr, base_capacity, WAPP_MEM_ALLOC_RESERVE | WAPP_MEM_ALLOC_COMMIT, true))
|
||||
|
||||
bool wapp_mem_arena_init(Arena **arena, u64 base_capacity, MemAllocFlags flags,
|
||||
bool zero_buffer);
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
b32 wapp_mem_arena_init_custom(Arena **arena, u64 base_capacity, MemAllocFlags flags, b32 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
|
||||
}
|
||||
#endif // __cplusplus
|
||||
#ifdef WAPP_PLATFORM_CPP
|
||||
END_C_LINKAGE
|
||||
#endif // !WAPP_PLATFORM_CPP
|
||||
|
||||
#endif // !MEM_ARENA_H
|
||||
|
59
src/core/mem/arena/mem_arena_allocator.c
Normal file
59
src/core/mem/arena/mem_arena_allocator.c
Normal file
@@ -0,0 +1,59 @@
|
||||
// vim:fileencoding=utf-8:foldmethod=marker
|
||||
|
||||
#include "mem_arena_allocator.h"
|
||||
#include "mem_arena.h"
|
||||
#include "../../../common/aliases/aliases.h"
|
||||
#include "../../os/mem/mem_os.h"
|
||||
|
||||
internal inline void *mem_arena_alloc(u64 size, void *alloc_obj);
|
||||
internal inline void *mem_arena_alloc_aligned(u64 size, u64 alignment, void *alloc_obj);
|
||||
internal inline void *mem_arena_realloc(void *ptr, u64 old_size, u64 new_size, void *alloc_obj);
|
||||
internal inline void *mem_arena_realloc_aligned(void *ptr, u64 old_size, u64 new_size, u64 alignment,
|
||||
void *alloc_obj);
|
||||
|
||||
|
||||
Allocator wapp_mem_arena_allocator_init_custom(u64 base_capacity, MemAllocFlags flags, b32 zero_buffer) {
|
||||
Allocator allocator = {0};
|
||||
b32 initialised = wapp_mem_arena_init_custom((Arena **)(&allocator.obj), base_capacity, flags, zero_buffer);
|
||||
if (!initialised) {
|
||||
return allocator;
|
||||
}
|
||||
|
||||
allocator.alloc = mem_arena_alloc;
|
||||
allocator.alloc_aligned = mem_arena_alloc_aligned;
|
||||
allocator.realloc = mem_arena_realloc;
|
||||
allocator.realloc_aligned = mem_arena_realloc_aligned;
|
||||
|
||||
return allocator;
|
||||
}
|
||||
|
||||
void wapp_mem_arena_allocator_clear(Allocator *allocator) {
|
||||
wapp_mem_arena_clear((Arena *)(allocator->obj));
|
||||
}
|
||||
|
||||
void wapp_mem_arena_allocator_destroy(Allocator *allocator) {
|
||||
wapp_mem_arena_destroy((Arena **)(&(allocator->obj)));
|
||||
*allocator = (Allocator){0};
|
||||
}
|
||||
|
||||
|
||||
internal inline void *mem_arena_alloc(u64 size, void *alloc_obj) {
|
||||
Arena *arena = (Arena *)alloc_obj;
|
||||
return wapp_mem_arena_alloc(arena, size);
|
||||
}
|
||||
|
||||
internal inline void *mem_arena_alloc_aligned(u64 size, u64 alignment, void *alloc_obj) {
|
||||
Arena *arena = (Arena *)alloc_obj;
|
||||
return wapp_mem_arena_alloc_aligned(arena, size, alignment);
|
||||
}
|
||||
|
||||
internal inline void *mem_arena_realloc(void *ptr, u64 old_size, u64 new_size, void *alloc_obj) {
|
||||
Arena *arena = (Arena *)alloc_obj;
|
||||
return wapp_mem_arena_realloc(arena, ptr, old_size, new_size);
|
||||
}
|
||||
|
||||
internal inline void *mem_arena_realloc_aligned(void *ptr, u64 old_size, u64 new_size, u64 alignment,
|
||||
void *alloc_obj) {
|
||||
Arena *arena = (Arena *)alloc_obj;
|
||||
return wapp_mem_arena_realloc_aligned(arena, ptr, old_size, new_size, alignment);
|
||||
}
|
43
src/core/mem/arena/mem_arena_allocator.h
Normal file
43
src/core/mem/arena/mem_arena_allocator.h
Normal file
@@ -0,0 +1,43 @@
|
||||
// vim:fileencoding=utf-8:foldmethod=marker
|
||||
|
||||
#ifndef MEM_ARENA_ALLOCATOR_H
|
||||
#define MEM_ARENA_ALLOCATOR_H
|
||||
|
||||
#include "../../../common/aliases/aliases.h"
|
||||
#include "../../../common/platform/platform.h"
|
||||
#include "../../../primitives/mem_allocator/mem_allocator.h"
|
||||
#include "../../os/mem/mem_os.h"
|
||||
|
||||
#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, b32 zero_buffer);
|
||||
void wapp_mem_arena_allocator_clear(Allocator *allocator);
|
||||
void wapp_mem_arena_allocator_destroy(Allocator *allocator);
|
||||
|
||||
#ifdef WAPP_PLATFORM_CPP
|
||||
END_C_LINKAGE
|
||||
#endif // !WAPP_PLATFORM_CPP
|
||||
|
||||
#endif // !MEM_ARENA_ALLOCATOR_H
|
26
src/core/mem/utils/mem_utils.c
Normal file
26
src/core/mem/utils/mem_utils.c
Normal file
@@ -0,0 +1,26 @@
|
||||
// vim:fileencoding=utf-8:foldmethod=marker
|
||||
|
||||
#include "mem_utils.h"
|
||||
#include "../../../common/aliases/aliases.h"
|
||||
#include "../../../common/assert/assert.h"
|
||||
#include <stddef.h>
|
||||
|
||||
internal b32 is_power_of_two(u64 num) { return (num & (num - 1)) == 0; }
|
||||
|
||||
void *wapp_mem_util_align_forward(void *ptr, u64 alignment) {
|
||||
wapp_debug_assert(ptr != NULL, "`ptr` should not be NULL");
|
||||
wapp_runtime_assert(is_power_of_two(alignment), "`alignment` value is not a power of two");
|
||||
|
||||
uptr p = (uptr)ptr;
|
||||
uptr align = (uptr)alignment;
|
||||
|
||||
// Similar to p % align, but it's a faster implementation that works fine
|
||||
// because align is guaranteed to be a power of 2
|
||||
uptr modulo = p & (align - 1);
|
||||
|
||||
if (modulo != 0) {
|
||||
p += align - modulo;
|
||||
}
|
||||
|
||||
return (void *)p;
|
||||
}
|
19
src/core/mem/utils/mem_utils.h
Normal file
19
src/core/mem/utils/mem_utils.h
Normal file
@@ -0,0 +1,19 @@
|
||||
// vim:fileencoding=utf-8:foldmethod=marker
|
||||
|
||||
#ifndef MEM_UTILS_H
|
||||
#define MEM_UTILS_H
|
||||
|
||||
#include "../../../common/aliases/aliases.h"
|
||||
#include "../../../common/platform/platform.h"
|
||||
|
||||
#ifdef WAPP_PLATFORM_CPP
|
||||
BEGIN_C_LINKAGE
|
||||
#endif // !WAPP_PLATFORM_CPP
|
||||
|
||||
void *wapp_mem_util_align_forward(void *ptr, u64 alignment);
|
||||
|
||||
#ifdef WAPP_PLATFORM_CPP
|
||||
END_C_LINKAGE
|
||||
#endif // !WAPP_PLATFORM_CPP
|
||||
|
||||
#endif // !MEM_UTILS_H
|
135
src/core/os/cpath/cpath.c
Normal file
135
src/core/os/cpath/cpath.c
Normal file
@@ -0,0 +1,135 @@
|
||||
// vim:fileencoding=utf-8:foldmethod=marker
|
||||
|
||||
#include "cpath.h"
|
||||
#include "../../../common/aliases/aliases.h"
|
||||
#include "../../../common/misc/misc_utils.h"
|
||||
#include "../../mem/arena/mem_arena_allocator.h"
|
||||
#include "../../../primitives/dbl_list/dbl_list.h"
|
||||
#include "../../../primitives/mem_allocator/mem_allocator.h"
|
||||
#include "../../../primitives/strings/str8/str8.h"
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
u32 wapp_cpath_join_path(Str8 *dst, const Str8List *parts) {
|
||||
if (!dst || !parts) {
|
||||
return CPATH_JOIN_INVALID_ARGS;
|
||||
}
|
||||
|
||||
if (parts->node_count == 0) {
|
||||
return CPATH_JOIN_EMPTY_PARTS;
|
||||
}
|
||||
|
||||
Str8 separator = wapp_str8_buf(4);
|
||||
wapp_str8_push_back(&separator, 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
|
||||
const Str8Node *first_node = wapp_str8_list_get(parts, 0);
|
||||
wapp_str8_copy_str8_capped(dst, first_node->item);
|
||||
|
||||
// NOTE (Abdelrahman): Uses a while loop instead of a for loop to get rid of
|
||||
// MSVC Spectre mitigation warnings
|
||||
const Str8Node *node = first_node;
|
||||
u64 node_index = 1;
|
||||
b32 running = node_index < parts->node_count;
|
||||
while (running && node->next) {
|
||||
node = node->next;
|
||||
if (node->item->size == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (dst->size > 0) {
|
||||
char dst_last = wapp_str8_get(dst, dst->size - 1);
|
||||
char node_start = wapp_str8_get(node->item, 0);
|
||||
b32 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->item);
|
||||
|
||||
++node_index;
|
||||
running = node_index < parts->node_count;
|
||||
}
|
||||
|
||||
return CPATH_JOIN_SUCCESS;
|
||||
}
|
||||
|
||||
Str8 *dirup(const Allocator *allocator, Str8RO *path, u64 levels) {
|
||||
Str8 *output = NULL;
|
||||
if (!allocator || !path) {
|
||||
goto RETURN_DIRUP;
|
||||
}
|
||||
|
||||
b32 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;
|
||||
}
|
||||
|
||||
if (levels < 1) {
|
||||
output = wapp_str8_alloc_str8(allocator, path);
|
||||
goto RETURN_DIRUP;
|
||||
}
|
||||
|
||||
Allocator tmp_arena = wapp_mem_arena_allocator_init(MB(8));
|
||||
if (wapp_mem_allocator_invalid(&tmp_arena)) {
|
||||
goto RETURN_DIRUP;
|
||||
}
|
||||
|
||||
Str8List *parts = wapp_str8_split(&tmp_arena, path, &separator);
|
||||
if (!parts) {
|
||||
goto RETURN_DIRUP;
|
||||
}
|
||||
|
||||
if (levels >= parts->node_count) {
|
||||
output = wapp_str8_alloc_buf(allocator, 16);
|
||||
if (!output) {
|
||||
goto LIST_CLEANUP_DIRUP;
|
||||
}
|
||||
|
||||
wapp_str8_push_back(output, absolute ? WAPP_PATH_SEP : '.');
|
||||
} else {
|
||||
for (u64 i = 0; i < levels; ++i) {
|
||||
wapp_str8_list_pop_back(parts);
|
||||
}
|
||||
|
||||
u64 alignment = sizeof(void *) * 2;
|
||||
u64 alloc_size = wapp_str8_list_total_size(parts) + parts->node_count * separator.size;
|
||||
u64 modulo = alloc_size & (alignment - 1);
|
||||
alloc_size += alignment - modulo;
|
||||
|
||||
output = wapp_str8_alloc_buf(allocator, alloc_size);
|
||||
if (output) {
|
||||
if (absolute) {
|
||||
wapp_str8_push_back(output, WAPP_PATH_SEP);
|
||||
}
|
||||
|
||||
Str8 *joined = wapp_str8_join(&tmp_arena, parts, &separator);
|
||||
if (joined) {
|
||||
wapp_str8_concat_capped(output, joined);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
LIST_CLEANUP_DIRUP:
|
||||
wapp_mem_arena_allocator_destroy(&tmp_arena);
|
||||
|
||||
RETURN_DIRUP:
|
||||
return output;
|
||||
}
|
44
src/core/os/cpath/cpath.h
Normal file
44
src/core/os/cpath/cpath.h
Normal file
@@ -0,0 +1,44 @@
|
||||
// vim:fileencoding=utf-8:foldmethod=marker
|
||||
|
||||
#ifndef CPATH_H
|
||||
#define CPATH_H
|
||||
|
||||
#include "../../../common/aliases/aliases.h"
|
||||
#include "../../../common/platform/platform.h"
|
||||
#include "../../../primitives/mem_allocator/mem_allocator.h"
|
||||
#include "../../../primitives/strings/str8/str8.h"
|
||||
|
||||
#ifdef WAPP_PLATFORM_CPP
|
||||
BEGIN_C_LINKAGE
|
||||
#endif // !WAPP_PLATFORM_CPP
|
||||
|
||||
#ifdef WAPP_PLATFORM_POSIX
|
||||
#include <limits.h>
|
||||
#define WAPP_PATH_SEP '/'
|
||||
#define WAPP_PATH_MAX PATH_MAX
|
||||
#elif defined(WAPP_PLATFORM_WINDOWS)
|
||||
#include <windows.h>
|
||||
#define WAPP_PATH_SEP '\\'
|
||||
#define WAPP_PATH_MAX MAX_PATH
|
||||
#else
|
||||
#error "Unrecognised platform"
|
||||
#endif
|
||||
|
||||
#define wapp_cpath_dirname(ALLOCATOR, PATH) dirup(ALLOCATOR, PATH, 1)
|
||||
#define wapp_cpath_dirup(ALLOCATOR, PATH, COUNT) dirup(ALLOCATOR, PATH, COUNT)
|
||||
|
||||
enum {
|
||||
CPATH_JOIN_SUCCESS = 0,
|
||||
CPATH_JOIN_INVALID_ARGS,
|
||||
CPATH_JOIN_EMPTY_PARTS,
|
||||
CPATH_JOIN_INSUFFICIENT_DST_CAPACITY,
|
||||
};
|
||||
|
||||
u32 wapp_cpath_join_path(Str8 *dst, const Str8List *parts);
|
||||
Str8 *dirup(const Allocator *allocator, Str8RO *path, u64 levels);
|
||||
|
||||
#ifdef WAPP_PLATFORM_CPP
|
||||
END_C_LINKAGE
|
||||
#endif // !WAPP_PLATFORM_CPP
|
||||
|
||||
#endif // !CPATH_H
|
30
src/core/os/mem/mem_os.c
Normal file
30
src/core/os/mem/mem_os.c
Normal file
@@ -0,0 +1,30 @@
|
||||
// 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_mem_util_alloc(void *addr, u64 size, MemAccess access, MemAllocFlags flags, MemInitType type) {
|
||||
void *output = mem_util_allocate(addr, size, access, flags, type);
|
||||
|
||||
if (type == WAPP_MEM_INIT_INITIALISED) {
|
||||
memset(output, 0, size);
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
void wapp_mem_util_free(void *ptr, u64 size) {
|
||||
mem_util_free(ptr, size);
|
||||
}
|
33
src/core/os/mem/mem_os.h
Normal file
33
src/core/os/mem/mem_os.h
Normal file
@@ -0,0 +1,33 @@
|
||||
// vim:fileencoding=utf-8:foldmethod=marker
|
||||
|
||||
#ifndef MEM_OS_H
|
||||
#define MEM_OS_H
|
||||
|
||||
#include "../../../common/aliases/aliases.h"
|
||||
#include "../../../common/platform/platform.h"
|
||||
|
||||
#include "mem_os_ops.h"
|
||||
|
||||
#ifdef WAPP_PLATFORM_CPP
|
||||
BEGIN_C_LINKAGE
|
||||
#endif // !WAPP_PLATFORM_CPP
|
||||
|
||||
#if defined(WAPP_PLATFORM_WINDOWS)
|
||||
#include "win/mem_os_win.h"
|
||||
#elif defined(WAPP_PLATFORM_POSIX)
|
||||
#include "posix/mem_os_posix.h"
|
||||
#else
|
||||
#error "Unrecognised platform"
|
||||
#endif
|
||||
|
||||
void *wapp_mem_util_alloc(void *addr, u64 size, MemAccess access, MemAllocFlags flags, MemInitType type);
|
||||
void wapp_mem_util_free(void *ptr, u64 size);
|
||||
|
||||
external void *mem_util_allocate(void *addr, u64 size, MemAccess access, MemAllocFlags flags, MemInitType type);
|
||||
external void mem_util_free(void *ptr, u64 size);
|
||||
|
||||
#ifdef WAPP_PLATFORM_CPP
|
||||
END_C_LINKAGE
|
||||
#endif // !WAPP_PLATFORM_CPP
|
||||
|
||||
#endif // !MEM_OS_H
|
30
src/core/os/mem/mem_os_ops.h
Normal file
30
src/core/os/mem/mem_os_ops.h
Normal file
@@ -0,0 +1,30 @@
|
||||
// vim:fileencoding=utf-8:foldmethod=marker
|
||||
|
||||
#ifndef MEM_OS_OPS_H
|
||||
#define MEM_OS_OPS_H
|
||||
|
||||
#include "../../../common/platform/platform.h"
|
||||
|
||||
#ifdef WAPP_PLATFORM_CPP
|
||||
BEGIN_C_LINKAGE
|
||||
#endif // !WAPP_PLATFORM_CPP
|
||||
|
||||
typedef enum mem_access {
|
||||
WAPP_MEM_ACCESS_NONE,
|
||||
WAPP_MEM_ACCESS_READ_ONLY,
|
||||
WAPP_MEM_ACCESS_EXEC_ONLY,
|
||||
WAPP_MEM_ACCESS_READ_WRITE,
|
||||
WAPP_MEM_ACCESS_READ_EXEC,
|
||||
WAPP_MEM_ACCESS_READ_WRITE_EXEC,
|
||||
} MemAccess;
|
||||
|
||||
typedef enum mem_init_type {
|
||||
WAPP_MEM_INIT_UNINITIALISED,
|
||||
WAPP_MEM_INIT_INITIALISED,
|
||||
} MemInitType;
|
||||
|
||||
#ifdef WAPP_PLATFORM_CPP
|
||||
END_C_LINKAGE
|
||||
#endif // !WAPP_PLATFORM_CPP
|
||||
|
||||
#endif // !MEM_OS_OPS_H
|
36
src/core/os/mem/posix/mem_os_posix.c
Normal file
36
src/core/os/mem/posix/mem_os_posix.c
Normal file
@@ -0,0 +1,36 @@
|
||||
// vim:fileencoding=utf-8:foldmethod=marker
|
||||
|
||||
#include "../../../../common/aliases/aliases.h"
|
||||
#include "../../../../common/platform/platform.h"
|
||||
|
||||
#ifdef WAPP_PLATFORM_POSIX
|
||||
|
||||
#include "mem_os_posix.h"
|
||||
#include "../mem_os_ops.h"
|
||||
#include <sys/mman.h>
|
||||
|
||||
internal const i32 access_types[] = {
|
||||
[WAPP_MEM_ACCESS_NONE] = PROT_NONE,
|
||||
[WAPP_MEM_ACCESS_READ_ONLY] = PROT_READ,
|
||||
[WAPP_MEM_ACCESS_EXEC_ONLY] = PROT_EXEC,
|
||||
[WAPP_MEM_ACCESS_READ_WRITE] = PROT_READ | PROT_WRITE,
|
||||
[WAPP_MEM_ACCESS_READ_EXEC] = PROT_READ | PROT_EXEC,
|
||||
[WAPP_MEM_ACCESS_READ_WRITE_EXEC] = PROT_READ | PROT_WRITE | PROT_EXEC,
|
||||
};
|
||||
|
||||
void *mem_util_allocate(void *addr, u64 size, MemAccess access, MemAllocFlags flags, MemInitType type) {
|
||||
(void)type;
|
||||
i32 alloc_flags = flags | MAP_ANON | MAP_PRIVATE;
|
||||
|
||||
#if defined(WAPP_PLATFORM_LINUX) || defined(WAPP_PLATFORM_GNU) || defined(WAPP_PLATFORM_NET_BSD)
|
||||
alloc_flags |= MAP_NORESERVE;
|
||||
#endif
|
||||
|
||||
return mmap(addr, size, access_types[access], alloc_flags, -1, 0);
|
||||
}
|
||||
|
||||
void mem_util_free(void *ptr, u64 size) {
|
||||
munmap(ptr, size);
|
||||
}
|
||||
|
||||
#endif // !WAPP_PLATFORM_POSIX
|
35
src/core/os/mem/posix/mem_os_posix.h
Normal file
35
src/core/os/mem/posix/mem_os_posix.h
Normal file
@@ -0,0 +1,35 @@
|
||||
// vim:fileencoding=utf-8:foldmethod=marker
|
||||
|
||||
#ifndef MEM_OS_POSIX_H
|
||||
#define MEM_OS_POSIX_H
|
||||
|
||||
#include "../../../../common/platform/platform.h"
|
||||
|
||||
#ifdef WAPP_PLATFORM_CPP
|
||||
BEGIN_C_LINKAGE
|
||||
#endif // !WAPP_PLATFORM_CPP
|
||||
|
||||
#ifdef WAPP_PLATFORM_POSIX
|
||||
|
||||
#include <sys/mman.h>
|
||||
|
||||
typedef enum mem_alloc_flags {
|
||||
#if defined(WAPP_PLATFORM_LINUX) || defined(WAPP_PLATFORM_GNU)
|
||||
WAPP_MEM_ALLOC_RESERVE = 0,
|
||||
WAPP_MEM_ALLOC_COMMIT = MAP_POPULATE,
|
||||
#elif defined(WAPP_PLATFORM_FREE_BSD)
|
||||
WAPP_MEM_ALLOC_RESERVE = 0,
|
||||
WAPP_MEM_ALLOC_COMMIT = MAP_PREFAULT_READ,
|
||||
#elif defined(WAPP_PLATFORM_BSD) || defined(WAPP_PLATFORM_UNIX) || defined(WAPP_PLATFORM_APPLE)
|
||||
WAPP_MEM_ALLOC_RESERVE = 0,
|
||||
WAPP_MEM_ALLOC_COMMIT = 0,
|
||||
#endif
|
||||
} MemAllocFlags;
|
||||
|
||||
#endif // !WAPP_PLATFORM_POSIX
|
||||
|
||||
#ifdef WAPP_PLATFORM_CPP
|
||||
END_C_LINKAGE
|
||||
#endif // !WAPP_PLATFORM_CPP
|
||||
|
||||
#endif // !MEM_OS_POSIX_H
|
37
src/core/os/mem/win/mem_os_win.c
Normal file
37
src/core/os/mem/win/mem_os_win.c
Normal file
@@ -0,0 +1,37 @@
|
||||
// vim:fileencoding=utf-8:foldmethod=marker
|
||||
|
||||
#include "../../../../common/aliases/aliases.h"
|
||||
#include "../../../../common/platform/platform.h"
|
||||
|
||||
#ifdef WAPP_PLATFORM_WINDOWS
|
||||
|
||||
#include "mem_os_win.h"
|
||||
#include "../mem_os_ops.h"
|
||||
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <Windows.h>
|
||||
#include <memoryapi.h>
|
||||
|
||||
internal const i32 access_types[] = {
|
||||
[WAPP_MEM_ACCESS_NONE] = PAGE_NOACCESS,
|
||||
[WAPP_MEM_ACCESS_READ_ONLY] = PAGE_READONLY,
|
||||
[WAPP_MEM_ACCESS_EXEC_ONLY] = PAGE_EXECUTE,
|
||||
[WAPP_MEM_ACCESS_READ_WRITE] = PAGE_READWRITE,
|
||||
[WAPP_MEM_ACCESS_READ_EXEC] = PAGE_EXECUTE_READ,
|
||||
[WAPP_MEM_ACCESS_READ_WRITE_EXEC] = PAGE_EXECUTE_READWRITE,
|
||||
};
|
||||
|
||||
void *mem_util_allocate(void *addr, u64 size, MemAccess access, MemAllocFlags flags, MemInitType type) {
|
||||
// Ensure memory is committed if it's meant to be initialised
|
||||
if (type == WAPP_MEM_INIT_INITIALISED) {
|
||||
flags |= WAPP_MEM_ALLOC_COMMIT;
|
||||
}
|
||||
|
||||
return VirtualAlloc(addr, (SIZE_T)size, flags, access_types[access]);
|
||||
}
|
||||
|
||||
void mem_util_free(void *ptr, u64 size) {
|
||||
VirtualFree(ptr, size, MEM_RELEASE);
|
||||
}
|
||||
|
||||
#endif // !WAPP_PLATFORM_WINDOWS
|
29
src/core/os/mem/win/mem_os_win.h
Normal file
29
src/core/os/mem/win/mem_os_win.h
Normal file
@@ -0,0 +1,29 @@
|
||||
// vim:fileencoding=utf-8:foldmethod=marker
|
||||
|
||||
#ifndef MEM_OS_WIN_H
|
||||
#define MEM_OS_WIN_H
|
||||
|
||||
#include "../../../../common/platform/platform.h"
|
||||
|
||||
#ifdef WAPP_PLATFORM_CPP
|
||||
BEGIN_C_LINKAGE
|
||||
#endif // !WAPP_PLATFORM_CPP
|
||||
|
||||
#ifdef WAPP_PLATFORM_WINDOWS
|
||||
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <Windows.h>
|
||||
#include <memoryapi.h>
|
||||
|
||||
typedef enum mem_alloc_flags {
|
||||
WAPP_MEM_ALLOC_RESERVE = MEM_RESERVE,
|
||||
WAPP_MEM_ALLOC_COMMIT = MEM_COMMIT,
|
||||
} MemAllocFlags;
|
||||
|
||||
#endif // !WAPP_PLATFORM_WINDOWS
|
||||
|
||||
#ifdef WAPP_PLATFORM_CPP
|
||||
END_C_LINKAGE
|
||||
#endif // !WAPP_PLATFORM_CPP
|
||||
|
||||
#endif // !MEM_OS_WIN_H
|
101
src/core/os/shell/commander/commander.c
Normal file
101
src/core/os/shell/commander/commander.c
Normal file
@@ -0,0 +1,101 @@
|
||||
// vim:fileencoding=utf-8:foldmethod=marker
|
||||
|
||||
#include "commander.h"
|
||||
#include "commander_output.h"
|
||||
#include "../utils/shell_utils.h"
|
||||
#include "../../../mem/arena/mem_arena_allocator.h"
|
||||
#include "../../../../common/aliases/aliases.h"
|
||||
#include "../../../../common/misc/misc_utils.h"
|
||||
#include "../../../../primitives/dbl_list/dbl_list.h"
|
||||
#include "../../../../primitives/mem_allocator/mem_allocator.h"
|
||||
#include "../../../../primitives/strings/str8/str8.h"
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#define CMD_BUF_LEN 8192
|
||||
#define OUT_BUF_LEN 4096
|
||||
|
||||
internal inline CMDResult execute_command(Str8RO *cmd, CMDOutHandling out_handling, Str8 *out_buf);
|
||||
internal inline CMDError get_command_output(FILE *fp, CMDOutHandling out_handling, Str8 *out_buf);
|
||||
|
||||
CMDResult wapp_shell_commander_execute(CMDOutHandling out_handling, Str8 *out_buf, const Str8List *cmd) {
|
||||
if (!cmd) {
|
||||
return CMD_NO_EXIT(SHELL_ERR_INVALID_ARGS);
|
||||
}
|
||||
|
||||
Allocator arena = wapp_mem_arena_allocator_init(KB(500));
|
||||
|
||||
Str8 *cmd_str = wapp_str8_join(&arena, cmd, &wapp_str8_lit_ro(" "));
|
||||
if (!cmd_str) {
|
||||
wapp_mem_arena_allocator_destroy(&arena);
|
||||
return CMD_NO_EXIT(SHELL_ERR_ALLOCATION_FAIL);
|
||||
}
|
||||
|
||||
// Redirect output
|
||||
cmd_str = wapp_str8_alloc_concat(&arena, cmd_str, &wapp_str8_lit_ro(" 2>&1"));
|
||||
|
||||
CMDResult output = execute_command(cmd_str, out_handling, out_buf);
|
||||
|
||||
wapp_mem_arena_allocator_destroy(&arena);
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
internal inline CMDResult execute_command(Str8RO *cmd, CMDOutHandling out_handling, Str8 *out_buf) {
|
||||
char cmd_buf[CMD_BUF_LEN] = {0};
|
||||
wapp_str8_copy_to_cstr(cmd_buf, cmd, CMD_BUF_LEN);
|
||||
|
||||
FILE *fp = wapp_shell_utils_popen(cmd_buf, "r");
|
||||
if (!fp) {
|
||||
return CMD_NO_EXIT(SHELL_ERR_PROC_START_FAIL);
|
||||
}
|
||||
|
||||
CMDResult output;
|
||||
|
||||
CMDError err = get_command_output(fp, out_handling, out_buf);
|
||||
if (err > SHELL_ERR_NO_ERROR) {
|
||||
output = CMD_NO_EXIT(err);
|
||||
goto EXECUTE_COMMAND_CLOSE;
|
||||
}
|
||||
|
||||
i32 st = EXIT_SUCCESS;
|
||||
err = get_output_status(fp, &st);
|
||||
if (err > SHELL_ERR_NO_ERROR) {
|
||||
output = CMD_NO_EXIT(err);
|
||||
goto EXECUTE_COMMAND_CLOSE;
|
||||
}
|
||||
|
||||
// Process is already closed in get_output_status
|
||||
fp = NULL;
|
||||
|
||||
output = (CMDResult){
|
||||
.exited = true,
|
||||
.exit_code = st,
|
||||
.error = SHELL_ERR_NO_ERROR,
|
||||
};
|
||||
|
||||
EXECUTE_COMMAND_CLOSE:
|
||||
if (fp) {
|
||||
wapp_shell_utils_pclose(fp);
|
||||
}
|
||||
return output;
|
||||
}
|
||||
|
||||
internal inline CMDError get_command_output(FILE *fp, CMDOutHandling out_handling, Str8 *out_buf) {
|
||||
Str8 out = wapp_str8_buf(OUT_BUF_LEN);
|
||||
|
||||
out.size = fread((void *)out.buf, sizeof(u8), out.capacity, fp);
|
||||
if (out_handling == SHELL_OUTPUT_CAPTURE && out_buf != NULL) {
|
||||
if (out.size >= out_buf->capacity) {
|
||||
return SHELL_ERR_OUT_BUF_FULL;
|
||||
}
|
||||
|
||||
wapp_str8_concat_capped(out_buf, &out);
|
||||
} else if (out_handling == SHELL_OUTPUT_PRINT) {
|
||||
printf(WAPP_STR8_SPEC, wapp_str8_varg(out));
|
||||
}
|
||||
|
||||
return SHELL_ERR_NO_ERROR;
|
||||
}
|
27
src/core/os/shell/commander/commander.h
Normal file
27
src/core/os/shell/commander/commander.h
Normal file
@@ -0,0 +1,27 @@
|
||||
// vim:fileencoding=utf-8:foldmethod=marker
|
||||
|
||||
#ifndef COMMANDER_H
|
||||
#define COMMANDER_H
|
||||
|
||||
#include "commander_output.h"
|
||||
#include "../../../../common/aliases/aliases.h"
|
||||
#include "../../../../common/platform/platform.h"
|
||||
#include "../../../../primitives/strings/str8/str8.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#ifdef WAPP_PLATFORM_CPP
|
||||
BEGIN_C_LINKAGE
|
||||
#endif // !WAPP_PLATFORM_CPP
|
||||
|
||||
#define CMD_NO_EXIT(ERR) ((CMDResult){.exited = false, .exit_code = EXIT_FAILURE, .error = ERR})
|
||||
|
||||
CMDResult wapp_shell_commander_execute(CMDOutHandling out_handling, Str8 *out_buf, const Str8List *cmd);
|
||||
|
||||
external CMDError get_output_status(FILE *fp, i32 *status_out);
|
||||
|
||||
#ifdef WAPP_PLATFORM_CPP
|
||||
END_C_LINKAGE
|
||||
#endif // !WAPP_PLATFORM_CPP
|
||||
|
||||
#endif // !COMMANDER_H
|
44
src/core/os/shell/commander/commander_output.h
Normal file
44
src/core/os/shell/commander/commander_output.h
Normal file
@@ -0,0 +1,44 @@
|
||||
// vim:fileencoding=utf-8:foldmethod=marker
|
||||
|
||||
#ifndef COMMANDER_OUTPUT_H
|
||||
#define COMMANDER_OUTPUT_H
|
||||
|
||||
#include "../../../../common/aliases/aliases.h"
|
||||
#include "../../../../common/platform/platform.h"
|
||||
|
||||
#ifdef WAPP_PLATFORM_CPP
|
||||
BEGIN_C_LINKAGE
|
||||
#endif // !WAPP_PLATFORM_CPP
|
||||
|
||||
typedef enum {
|
||||
SHELL_OUTPUT_DISCARD,
|
||||
SHELL_OUTPUT_PRINT,
|
||||
SHELL_OUTPUT_CAPTURE,
|
||||
} CMDOutHandling;
|
||||
|
||||
typedef enum {
|
||||
SHELL_ERR_NO_ERROR,
|
||||
SHELL_ERR_INVALID_ARGS,
|
||||
SHELL_ERR_ALLOCATION_FAIL,
|
||||
SHELL_ERR_PROC_START_FAIL,
|
||||
SHELL_ERR_OUT_BUF_FULL,
|
||||
SHELL_ERR_PROC_EXIT_FAIL,
|
||||
} CMDError;
|
||||
|
||||
typedef struct commander_result CMDResult;
|
||||
struct commander_result {
|
||||
i32 exit_code;
|
||||
CMDError error;
|
||||
b32 exited;
|
||||
|
||||
#ifdef WAPP_PLATFORM_WINDOWS
|
||||
#include "../../../../common/misc/misc_utils.h"
|
||||
wapp_misc_utils_padding_size(sizeof(b32) + sizeof(i32) + sizeof(CMDError));
|
||||
#endif // !WAPP_PLATFORM_WINDOWS
|
||||
};
|
||||
|
||||
#ifdef WAPP_PLATFORM_CPP
|
||||
END_C_LINKAGE
|
||||
#endif // !WAPP_PLATFORM_CPP
|
||||
|
||||
#endif // !COMMANDER_OUTPUT_H
|
25
src/core/os/shell/commander/posix/commander_posix.c
Normal file
25
src/core/os/shell/commander/posix/commander_posix.c
Normal file
@@ -0,0 +1,25 @@
|
||||
// vim:fileencoding=utf-8:foldmethod=marker
|
||||
|
||||
#include "../../../../../common/aliases/aliases.h"
|
||||
#include "../../../../../common/platform/platform.h"
|
||||
|
||||
#ifdef WAPP_PLATFORM_POSIX
|
||||
|
||||
#include "../commander_output.h"
|
||||
#include "../../utils/shell_utils.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
CMDError get_output_status(FILE *fp, i32 *status_out) {
|
||||
*status_out = wapp_shell_utils_pclose(fp);
|
||||
|
||||
if (!WIFEXITED(*status_out)) {
|
||||
return SHELL_ERR_PROC_EXIT_FAIL;
|
||||
}
|
||||
|
||||
*status_out = WEXITSTATUS(*status_out);
|
||||
|
||||
return SHELL_ERR_NO_ERROR;
|
||||
}
|
||||
|
||||
#endif // !WAPP_PLATFORM_POSIX
|
24
src/core/os/shell/commander/win/commander_win.c
Normal file
24
src/core/os/shell/commander/win/commander_win.c
Normal file
@@ -0,0 +1,24 @@
|
||||
// vim:fileencoding=utf-8:foldmethod=marker
|
||||
|
||||
#include "../../../../../common/aliases/aliases.h"
|
||||
#include "../../../../../common/platform/platform.h"
|
||||
|
||||
#ifdef WAPP_PLATFORM_WINDOWS
|
||||
|
||||
#include "../commander_output.h"
|
||||
#include "../../utils/shell_utils.h"
|
||||
#include <stdio.h>
|
||||
|
||||
CMDError get_output_status(FILE *fp, i32 *status_out) {
|
||||
if (!feof(fp)) {
|
||||
// Ensure process is closed on failure
|
||||
wapp_shell_utils_pclose(fp);
|
||||
return SHELL_ERR_PROC_EXIT_FAIL;
|
||||
}
|
||||
|
||||
*status_out = wapp_shell_utils_pclose(fp);
|
||||
|
||||
return SHELL_ERR_NO_ERROR;
|
||||
}
|
||||
|
||||
#endif // !WAPP_PLATFORM_WINDOWS
|
36
src/core/os/shell/termcolour/posix/termcolour_posix.c
Normal file
36
src/core/os/shell/termcolour/posix/termcolour_posix.c
Normal file
@@ -0,0 +1,36 @@
|
||||
// vim:fileencoding=utf-8:foldmethod=marker
|
||||
|
||||
#include "../../../../../common/aliases/aliases.h"
|
||||
#include "../../../../../common/platform/platform.h"
|
||||
#include "../../../../../primitives/strings/str8/str8.h"
|
||||
|
||||
#ifdef WAPP_PLATFORM_POSIX
|
||||
|
||||
#include "../terminal_colours.h"
|
||||
#include <stdio.h>
|
||||
|
||||
internal Str8RO colours[COUNT_TERM_COLOUR] = {
|
||||
[WAPP_TERM_COLOUR_FG_BLACK] = wapp_str8_lit_ro_initialiser_list("\033[30m"),
|
||||
[WAPP_TERM_COLOUR_FG_RED] = wapp_str8_lit_ro_initialiser_list("\033[31m"),
|
||||
[WAPP_TERM_COLOUR_FG_GREEN] = wapp_str8_lit_ro_initialiser_list("\033[32m"),
|
||||
[WAPP_TERM_COLOUR_FG_BLUE] = wapp_str8_lit_ro_initialiser_list("\033[34m"),
|
||||
[WAPP_TERM_COLOUR_FG_CYAN] = wapp_str8_lit_ro_initialiser_list("\033[36m"),
|
||||
[WAPP_TERM_COLOUR_FG_MAGENTA] = wapp_str8_lit_ro_initialiser_list("\033[35m"),
|
||||
[WAPP_TERM_COLOUR_FG_YELLOW] = wapp_str8_lit_ro_initialiser_list("\033[33m"),
|
||||
[WAPP_TERM_COLOUR_FG_WHITE] = wapp_str8_lit_ro_initialiser_list("\033[37m"),
|
||||
[WAPP_TERM_COLOUR_FG_BR_BLACK] = wapp_str8_lit_ro_initialiser_list("\033[90m"),
|
||||
[WAPP_TERM_COLOUR_FG_BR_RED] = wapp_str8_lit_ro_initialiser_list("\033[91m"),
|
||||
[WAPP_TERM_COLOUR_FG_BR_GREEN] = wapp_str8_lit_ro_initialiser_list("\033[92m"),
|
||||
[WAPP_TERM_COLOUR_FG_BR_BLUE] = wapp_str8_lit_ro_initialiser_list("\033[94m"),
|
||||
[WAPP_TERM_COLOUR_FG_BR_CYAN] = wapp_str8_lit_ro_initialiser_list("\033[96m"),
|
||||
[WAPP_TERM_COLOUR_FG_BR_MAGENTA] = wapp_str8_lit_ro_initialiser_list("\033[95m"),
|
||||
[WAPP_TERM_COLOUR_FG_BR_YELLOW] = wapp_str8_lit_ro_initialiser_list("\033[93m"),
|
||||
[WAPP_TERM_COLOUR_FG_BR_WHITE] = wapp_str8_lit_ro_initialiser_list("\033[97m"),
|
||||
[WAPP_TERM_COLOUR_CLEAR] = wapp_str8_lit_ro_initialiser_list("\033[0m"),
|
||||
};
|
||||
|
||||
void print_coloured_text(Str8RO *text, TerminalColour colour) {
|
||||
printf(WAPP_STR8_SPEC WAPP_STR8_SPEC, wapp_str8_varg(colours[colour]), wapp_str8_varg((*text)));
|
||||
}
|
||||
|
||||
#endif // !WAPP_PLATFORM_POSIX
|
18
src/core/os/shell/termcolour/termcolour.c
Normal file
18
src/core/os/shell/termcolour/termcolour.c
Normal file
@@ -0,0 +1,18 @@
|
||||
// vim:fileencoding=utf-8:foldmethod=marker
|
||||
|
||||
#include "termcolour.h"
|
||||
#include "terminal_colours.h"
|
||||
#include "../../../../primitives/strings/str8/str8.h"
|
||||
|
||||
void wapp_shell_termcolour_print_text(Str8RO *text, TerminalColour colour) {
|
||||
if (colour < WAPP_TERM_COLOUR_FG_BLACK || colour > WAPP_TERM_COLOUR_FG_BR_WHITE) {
|
||||
return;
|
||||
}
|
||||
|
||||
print_coloured_text(text, colour);
|
||||
}
|
||||
|
||||
void wapp_shell_termcolour_clear_colour(void) {
|
||||
Str8RO empty = wapp_str8_lit_ro("");
|
||||
print_coloured_text(&empty, WAPP_TERM_COLOUR_CLEAR);
|
||||
}
|
24
src/core/os/shell/termcolour/termcolour.h
Normal file
24
src/core/os/shell/termcolour/termcolour.h
Normal file
@@ -0,0 +1,24 @@
|
||||
// vim:fileencoding=utf-8:foldmethod=marker
|
||||
|
||||
#ifndef TERM_COLOUR_H
|
||||
#define TERM_COLOUR_H
|
||||
|
||||
#include "terminal_colours.h"
|
||||
#include "../../../../common/aliases/aliases.h"
|
||||
#include "../../../../common/platform/platform.h"
|
||||
#include "../../../../primitives/strings/str8/str8.h"
|
||||
|
||||
#ifdef WAPP_PLATFORM_CPP
|
||||
BEGIN_C_LINKAGE
|
||||
#endif // !WAPP_PLATFORM_CPP
|
||||
|
||||
void wapp_shell_termcolour_print_text(Str8RO *text, TerminalColour colour);
|
||||
void wapp_shell_termcolour_clear_colour(void);
|
||||
|
||||
external void print_coloured_text(Str8RO *text, TerminalColour colour);
|
||||
|
||||
#ifdef WAPP_PLATFORM_CPP
|
||||
END_C_LINKAGE
|
||||
#endif // !WAPP_PLATFORM_CPP
|
||||
|
||||
#endif // !TERM_COLOUR_H
|
39
src/core/os/shell/termcolour/terminal_colours.h
Normal file
39
src/core/os/shell/termcolour/terminal_colours.h
Normal file
@@ -0,0 +1,39 @@
|
||||
// vim:fileencoding=utf-8:foldmethod=marker
|
||||
|
||||
#ifndef TERMINAL_COLOURS_H
|
||||
#define TERMINAL_COLOURS_H
|
||||
|
||||
#include "../../../../common/aliases/aliases.h"
|
||||
#include "../../../../common/platform/platform.h"
|
||||
|
||||
#ifdef WAPP_PLATFORM_CPP
|
||||
BEGIN_C_LINKAGE
|
||||
#endif // !WAPP_PLATFORM_CPP
|
||||
|
||||
typedef enum {
|
||||
WAPP_TERM_COLOUR_FG_BLACK,
|
||||
WAPP_TERM_COLOUR_FG_RED,
|
||||
WAPP_TERM_COLOUR_FG_GREEN,
|
||||
WAPP_TERM_COLOUR_FG_BLUE,
|
||||
WAPP_TERM_COLOUR_FG_CYAN,
|
||||
WAPP_TERM_COLOUR_FG_MAGENTA,
|
||||
WAPP_TERM_COLOUR_FG_YELLOW,
|
||||
WAPP_TERM_COLOUR_FG_WHITE,
|
||||
WAPP_TERM_COLOUR_FG_BR_BLACK,
|
||||
WAPP_TERM_COLOUR_FG_BR_RED,
|
||||
WAPP_TERM_COLOUR_FG_BR_GREEN,
|
||||
WAPP_TERM_COLOUR_FG_BR_BLUE,
|
||||
WAPP_TERM_COLOUR_FG_BR_CYAN,
|
||||
WAPP_TERM_COLOUR_FG_BR_MAGENTA,
|
||||
WAPP_TERM_COLOUR_FG_BR_YELLOW,
|
||||
WAPP_TERM_COLOUR_FG_BR_WHITE,
|
||||
WAPP_TERM_COLOUR_CLEAR,
|
||||
|
||||
COUNT_TERM_COLOUR,
|
||||
} TerminalColour;
|
||||
|
||||
#ifdef WAPP_PLATFORM_CPP
|
||||
END_C_LINKAGE
|
||||
#endif // !WAPP_PLATFORM_CPP
|
||||
|
||||
#endif // !TERMINAL_COLOURS_H
|
73
src/core/os/shell/termcolour/win/termcolour_win.c
Normal file
73
src/core/os/shell/termcolour/win/termcolour_win.c
Normal file
@@ -0,0 +1,73 @@
|
||||
// vim:fileencoding=utf-8:foldmethod=marker
|
||||
|
||||
#include "../../../../../common/aliases/aliases.h"
|
||||
#include "../../../../../common/platform/platform.h"
|
||||
#include "../../../../../primitives/strings/str8/str8.h"
|
||||
|
||||
#ifdef WAPP_PLATFORM_WINDOWS
|
||||
|
||||
#include "../terminal_colours.h"
|
||||
#include "../../../../../common/misc/misc_utils.h"
|
||||
#include <stdio.h>
|
||||
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <Windows.h>
|
||||
|
||||
typedef struct termcolour_data TermcolourData;
|
||||
struct termcolour_data {
|
||||
HANDLE handle;
|
||||
WORD default_colour;
|
||||
WORD current_colour;
|
||||
|
||||
wapp_misc_utils_padding_size(sizeof(HANDLE) + sizeof(WORD) + sizeof(WORD));
|
||||
};
|
||||
|
||||
internal void init_data(TermcolourData *data);
|
||||
|
||||
internal WORD colours[COUNT_TERM_COLOUR] = {
|
||||
[WAPP_TERM_COLOUR_FG_BLACK] = 0,
|
||||
[WAPP_TERM_COLOUR_FG_RED] = FOREGROUND_RED,
|
||||
[WAPP_TERM_COLOUR_FG_GREEN] = FOREGROUND_GREEN,
|
||||
[WAPP_TERM_COLOUR_FG_BLUE] = FOREGROUND_BLUE,
|
||||
[WAPP_TERM_COLOUR_FG_CYAN] = FOREGROUND_GREEN | FOREGROUND_BLUE,
|
||||
[WAPP_TERM_COLOUR_FG_MAGENTA] = FOREGROUND_RED | FOREGROUND_BLUE,
|
||||
[WAPP_TERM_COLOUR_FG_YELLOW] = FOREGROUND_RED | FOREGROUND_GREEN,
|
||||
[WAPP_TERM_COLOUR_FG_WHITE] = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE,
|
||||
[WAPP_TERM_COLOUR_FG_BR_BLACK] = FOREGROUND_INTENSITY,
|
||||
[WAPP_TERM_COLOUR_FG_BR_RED] = FOREGROUND_RED | FOREGROUND_INTENSITY,
|
||||
[WAPP_TERM_COLOUR_FG_BR_GREEN] = FOREGROUND_GREEN | FOREGROUND_INTENSITY,
|
||||
[WAPP_TERM_COLOUR_FG_BR_BLUE] = FOREGROUND_BLUE | FOREGROUND_INTENSITY,
|
||||
[WAPP_TERM_COLOUR_FG_BR_CYAN] = FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY,
|
||||
[WAPP_TERM_COLOUR_FG_BR_MAGENTA] = FOREGROUND_RED | FOREGROUND_BLUE | FOREGROUND_INTENSITY,
|
||||
[WAPP_TERM_COLOUR_FG_BR_YELLOW] = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_INTENSITY,
|
||||
[WAPP_TERM_COLOUR_FG_BR_WHITE] = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY,
|
||||
};
|
||||
|
||||
void print_coloured_text(Str8RO *text, TerminalColour colour) {
|
||||
persistent TermcolourData data = {0};
|
||||
if (data.handle == 0) {
|
||||
init_data(&data);
|
||||
}
|
||||
|
||||
if (colour == WAPP_TERM_COLOUR_CLEAR) {
|
||||
data.current_colour = data.default_colour;
|
||||
} else {
|
||||
data.current_colour = colours[colour];
|
||||
}
|
||||
|
||||
SetConsoleTextAttribute(data.handle, data.current_colour);
|
||||
printf(WAPP_STR8_SPEC, wapp_str8_varg((*text)));
|
||||
}
|
||||
|
||||
internal void init_data(TermcolourData *data) {
|
||||
// create handle
|
||||
data->handle = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||
|
||||
// get console colour information
|
||||
CONSOLE_SCREEN_BUFFER_INFO csbi;
|
||||
GetConsoleScreenBufferInfo(data->handle, &csbi);
|
||||
data->default_colour = csbi.wAttributes;
|
||||
data->current_colour = data->default_colour;
|
||||
}
|
||||
|
||||
#endif // !WAPP_PLATFORM_WINDOWS
|
26
src/core/os/shell/utils/shell_utils.h
Normal file
26
src/core/os/shell/utils/shell_utils.h
Normal file
@@ -0,0 +1,26 @@
|
||||
// vim:fileencoding=utf-8:foldmethod=marker
|
||||
|
||||
#ifndef SHELL_UTILS_H
|
||||
#define SHELL_UTILS_H
|
||||
|
||||
#include "../../../../common/aliases/aliases.h"
|
||||
#include "../../../../common/platform/platform.h"
|
||||
#include <stdio.h>
|
||||
|
||||
#ifdef WAPP_PLATFORM_CPP
|
||||
BEGIN_C_LINKAGE
|
||||
#endif // !WAPP_PLATFORM_CPP
|
||||
|
||||
#ifdef WAPP_PLATFORM_WINDOWS
|
||||
#define wapp_shell_utils_popen _popen
|
||||
#define wapp_shell_utils_pclose _pclose
|
||||
#else
|
||||
#define wapp_shell_utils_popen popen
|
||||
#define wapp_shell_utils_pclose pclose
|
||||
#endif /* ifdef WAPP_PLATFORM_WINDOWS */
|
||||
|
||||
#ifdef WAPP_PLATFORM_CPP
|
||||
END_C_LINKAGE
|
||||
#endif // !WAPP_PLATFORM_CPP
|
||||
|
||||
#endif // !SHELL_UTILS_H
|
@@ -1,34 +0,0 @@
|
||||
#ifndef BASIC_STRING_H
|
||||
#define BASIC_STRING_H
|
||||
|
||||
#include "aliases.h"
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif // __cplusplus
|
||||
|
||||
typedef struct bstr BasicString;
|
||||
struct bstr {
|
||||
u64 size;
|
||||
const char *buf;
|
||||
};
|
||||
|
||||
typedef struct strvw StringView;
|
||||
struct strvw {
|
||||
const u64 size;
|
||||
const char *buf;
|
||||
};
|
||||
|
||||
#define new_string(STR) \
|
||||
{ .size = strlen(STR), .buf = STR }
|
||||
#define wapp_bstr_new(STR) ((BasicString)new_string(STR))
|
||||
#define wapp_strvw_new(STR) ((StringView)new_string(STR))
|
||||
#define wapp_string_print(STR) (printf("%.*s\n", (i32)STR.size, STR.buf))
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif // __cplusplus
|
||||
|
||||
#endif // !BASIC_STRING_H
|
@@ -1,191 +0,0 @@
|
||||
#include "dstr.h"
|
||||
#include "aliases.h"
|
||||
#include "mem_arena.h"
|
||||
#include "platform.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
// Use this scalar to allocate extra memory in order to avoid having to
|
||||
// constantly reallocate
|
||||
#define CAPACITY_SCALAR 8
|
||||
#define MINIMUM_DSTR_CAPACITY 1024
|
||||
|
||||
struct dstr {
|
||||
u64 capacity;
|
||||
u64 size;
|
||||
|
||||
#ifdef WAPP_PLATFORM_WINDOWS
|
||||
char *buf;
|
||||
#else
|
||||
char buf[];
|
||||
#endif // WAPP_PLATFORM_WINDOWS
|
||||
};
|
||||
|
||||
String *wapp_dstr_with_capacity(u64 capacity, Arena *arena) {
|
||||
if (!arena) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
String *out =
|
||||
(String *)wapp_mem_arena_alloc(arena, sizeof(String) + capacity + 1);
|
||||
if (!out) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
out->capacity = capacity;
|
||||
out->size = 0;
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
String *wapp_dstr_from_string(const char *str, Arena *arena) {
|
||||
if (!str || !arena) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
u64 length = strlen(str);
|
||||
u64 capacity = length * CAPACITY_SCALAR;
|
||||
capacity =
|
||||
capacity >= MINIMUM_DSTR_CAPACITY ? capacity : MINIMUM_DSTR_CAPACITY;
|
||||
|
||||
String *out = wapp_dstr_with_capacity(capacity, arena);
|
||||
if (!out) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
out->size = length;
|
||||
strncpy(out->buf, str, length + 1);
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
StringUpdate wapp_dstr_update(String **dst, const char *src, Arena *arena) {
|
||||
if (!dst || !(*dst)) {
|
||||
return (StringUpdate){.updated = false, .str = *dst};
|
||||
}
|
||||
|
||||
u64 length = strlen(src);
|
||||
|
||||
String *str = *dst;
|
||||
|
||||
if (length >= str->capacity) {
|
||||
if (!arena) {
|
||||
return (StringUpdate){.updated = false, .str = *dst};
|
||||
}
|
||||
|
||||
String *new_str = wapp_dstr_from_string(src, arena);
|
||||
if (!new_str) {
|
||||
return (StringUpdate){.updated = false, .str = *dst};
|
||||
}
|
||||
|
||||
return (StringUpdate){.updated = true, .str = new_str};
|
||||
}
|
||||
|
||||
memset(str->buf, 0, str->capacity);
|
||||
|
||||
str->size = length;
|
||||
|
||||
strncpy(str->buf, src, length + 1);
|
||||
|
||||
return (StringUpdate){.updated = true, .str = *dst};
|
||||
}
|
||||
|
||||
StringUpdate wapp_dstr_concat(String **dst, const char *src, Arena *arena) {
|
||||
if (!dst || !(*dst)) {
|
||||
return (StringUpdate){.updated = false, .str = *dst};
|
||||
}
|
||||
|
||||
u64 src_length = strlen(src);
|
||||
if (src_length == 0) {
|
||||
return (StringUpdate){.updated = false, .str = *dst};
|
||||
}
|
||||
|
||||
u64 new_length = (*dst)->size + src_length;
|
||||
|
||||
#ifdef WAPP_PLATFORM_WINDOWS
|
||||
char *str =
|
||||
wapp_mem_util_alloc(NULL, new_length + 1, WAPP_MEM_ACCESS_READ_WRITE,
|
||||
WAPP_MEM_ALLOC_RESERVE | WAPP_MEM_ALLOC_COMMIT,
|
||||
WAPP_MEM_INIT_INITIALISED);
|
||||
|
||||
if (!str) {
|
||||
return (StringUpdate){.updated = false, .str = *dst};
|
||||
}
|
||||
#else
|
||||
char str[new_length + 1];
|
||||
memset(str, 0, new_length + 1);
|
||||
#endif /* ifdef WAPP_PLATFORM_WINDOWS */
|
||||
|
||||
strncpy(str, (*dst)->buf, (*dst)->size);
|
||||
strncat(str, src, new_length + 1 - (*dst)->size);
|
||||
|
||||
return wapp_dstr_update(dst, str, arena);
|
||||
}
|
||||
|
||||
void wapp_dstr_clear(String *str) {
|
||||
if (!str || str->size == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
memset(str->buf, 0, str->capacity);
|
||||
str->size = 0;
|
||||
}
|
||||
|
||||
void wapp_dstr_print(const String *str) {
|
||||
if (!str) {
|
||||
return;
|
||||
}
|
||||
|
||||
printf("%.*s\n", (i32)str->size, str->buf);
|
||||
}
|
||||
|
||||
i64 wapp_dstr_find(const String *str, const char *substr) {
|
||||
if (!str || !substr) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
u64 substr_length = strlen(substr);
|
||||
if (substr_length == 0 || substr_length > str->size) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
const char *s1;
|
||||
for (u64 i = 0; i < str->size; ++i) {
|
||||
if (i + substr_length > str->size) {
|
||||
break;
|
||||
}
|
||||
|
||||
s1 = &(str->buf[i]);
|
||||
|
||||
if (strncmp(s1, substr, substr_length) == 0) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
u64 wapp_dstr_length(const String *str) {
|
||||
if (!str) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return str->size;
|
||||
}
|
||||
|
||||
u64 wapp_dstr_capacity(const String *str) {
|
||||
if (!str) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return str->capacity;
|
||||
}
|
||||
|
||||
const char *wapp_dstr_to_cstr(const String *str) {
|
||||
if (!str) {
|
||||
return "";
|
||||
}
|
||||
|
||||
return str->buf;
|
||||
}
|
@@ -1,41 +0,0 @@
|
||||
#ifndef DSTR_H
|
||||
#define DSTR_H
|
||||
|
||||
#include "aliases.h"
|
||||
#include "mem_arena.h"
|
||||
#include "misc_utils.h"
|
||||
#include "platform.h"
|
||||
#include <stdbool.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif // __cplusplus
|
||||
|
||||
typedef struct dstr String;
|
||||
|
||||
typedef struct string_update StringUpdate;
|
||||
struct string_update {
|
||||
String *str;
|
||||
bool updated;
|
||||
|
||||
#ifdef WAPP_PLATFORM_WINDOWS
|
||||
wapp_misc_utils_padding_size(sizeof(bool) + sizeof(String *));
|
||||
#endif // WAPP_PLATFORM_WINDOWS
|
||||
};
|
||||
|
||||
String *wapp_dstr_with_capacity(u64 capacity, Arena *arena);
|
||||
String *wapp_dstr_from_string(const char *str, Arena *arena);
|
||||
StringUpdate wapp_dstr_update(String **dst, const char *src, Arena *arena);
|
||||
StringUpdate wapp_dstr_concat(String **dst, const char *src, Arena *arena);
|
||||
void wapp_dstr_clear(String *str);
|
||||
void wapp_dstr_print(const String *str);
|
||||
i64 wapp_dstr_find(const String *str, const char *substr);
|
||||
u64 wapp_dstr_length(const String *str);
|
||||
u64 wapp_dstr_capacity(const String *str);
|
||||
const char *wapp_dstr_to_cstr(const String *str);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif // __cplusplus
|
||||
|
||||
#endif // !DSTR_H
|
23
src/core/wapp_core.c
Normal file
23
src/core/wapp_core.c
Normal file
@@ -0,0 +1,23 @@
|
||||
// vim:fileencoding=utf-8:foldmethod=marker
|
||||
|
||||
#ifndef WAPP_CORE_C
|
||||
#define WAPP_CORE_C
|
||||
|
||||
#include "wapp_core.h"
|
||||
#include "file/file.c"
|
||||
#include "os/shell/termcolour/posix/termcolour_posix.c"
|
||||
#include "os/shell/termcolour/win/termcolour_win.c"
|
||||
#include "os/shell/termcolour/termcolour.c"
|
||||
#include "os/shell/commander/posix/commander_posix.c"
|
||||
#include "os/shell/commander/win/commander_win.c"
|
||||
#include "os/shell/commander/commander.c"
|
||||
#include "os/cpath/cpath.c"
|
||||
#include "os/mem/posix/mem_os_posix.c"
|
||||
#include "os/mem/win/mem_os_win.c"
|
||||
#include "os/mem/mem_os.c"
|
||||
#include "mem/utils/mem_utils.c"
|
||||
#include "mem/arena/mem_arena.c"
|
||||
#include "mem/arena/mem_arena_allocator.c"
|
||||
#include "../primitives/wapp_primitives.c"
|
||||
|
||||
#endif // !WAPP_CORE_C
|
23
src/core/wapp_core.h
Normal file
23
src/core/wapp_core.h
Normal file
@@ -0,0 +1,23 @@
|
||||
// vim:fileencoding=utf-8:foldmethod=marker
|
||||
|
||||
#ifndef WAPP_CORE_H
|
||||
#define WAPP_CORE_H
|
||||
|
||||
#include "file/file.h"
|
||||
#include "os/shell/termcolour/termcolour.h"
|
||||
#include "os/shell/termcolour/terminal_colours.h"
|
||||
#include "os/shell/commander/commander.h"
|
||||
#include "os/shell/commander/commander_output.h"
|
||||
#include "os/shell/utils/shell_utils.h"
|
||||
#include "os/cpath/cpath.h"
|
||||
#include "os/mem/posix/mem_os_posix.h"
|
||||
#include "os/mem/win/mem_os_win.h"
|
||||
#include "os/mem/mem_os_ops.h"
|
||||
#include "os/mem/mem_os.h"
|
||||
#include "mem/utils/mem_utils.h"
|
||||
#include "mem/arena/mem_arena_allocator.h"
|
||||
#include "mem/arena/mem_arena.h"
|
||||
#include "../common/wapp_common.h"
|
||||
#include "../primitives/wapp_primitives.h"
|
||||
|
||||
#endif // !WAPP_CORE_H
|
3010
src/primitives/array/array.c
Normal file
3010
src/primitives/array/array.c
Normal file
File diff suppressed because it is too large
Load Diff
978
src/primitives/array/array.h
Normal file
978
src/primitives/array/array.h
Normal file
@@ -0,0 +1,978 @@
|
||||
/**
|
||||
* THIS FILE IS AUTOMATICALLY GENERATED. ANY MODIFICATIONS TO IT WILL BE OVERWRITTEN.
|
||||
*/
|
||||
|
||||
#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_void_ptr_array_alloc_capacity(ALLOCATOR_PTR, CAPACITY) ((VoidPArray *)_array_alloc_capacity(ALLOCATOR_PTR, CAPACITY, sizeof(void *)))
|
||||
#define wapp_str8_array_alloc_capacity(ALLOCATOR_PTR, CAPACITY) ((Str8Array *)_array_alloc_capacity(ALLOCATOR_PTR, CAPACITY, sizeof(Str8)))
|
||||
#define wapp_b32_array_alloc_capacity(ALLOCATOR_PTR, CAPACITY) ((B32Array *)_array_alloc_capacity(ALLOCATOR_PTR, CAPACITY, sizeof(b32)))
|
||||
#define wapp_char_array_alloc_capacity(ALLOCATOR_PTR, CAPACITY) ((CharArray *)_array_alloc_capacity(ALLOCATOR_PTR, CAPACITY, sizeof(char)))
|
||||
#define wapp_c8_array_alloc_capacity(ALLOCATOR_PTR, CAPACITY) ((C8Array *)_array_alloc_capacity(ALLOCATOR_PTR, CAPACITY, sizeof(c8)))
|
||||
#define wapp_c16_array_alloc_capacity(ALLOCATOR_PTR, CAPACITY) ((C16Array *)_array_alloc_capacity(ALLOCATOR_PTR, CAPACITY, sizeof(c16)))
|
||||
#define wapp_c32_array_alloc_capacity(ALLOCATOR_PTR, CAPACITY) ((C32Array *)_array_alloc_capacity(ALLOCATOR_PTR, CAPACITY, sizeof(c32)))
|
||||
#define wapp_i8_array_alloc_capacity(ALLOCATOR_PTR, CAPACITY) ((I8Array *)_array_alloc_capacity(ALLOCATOR_PTR, CAPACITY, sizeof(i8)))
|
||||
#define wapp_i16_array_alloc_capacity(ALLOCATOR_PTR, CAPACITY) ((I16Array *)_array_alloc_capacity(ALLOCATOR_PTR, CAPACITY, sizeof(i16)))
|
||||
#define wapp_i32_array_alloc_capacity(ALLOCATOR_PTR, CAPACITY) ((I32Array *)_array_alloc_capacity(ALLOCATOR_PTR, CAPACITY, sizeof(i32)))
|
||||
#define wapp_i64_array_alloc_capacity(ALLOCATOR_PTR, CAPACITY) ((I64Array *)_array_alloc_capacity(ALLOCATOR_PTR, CAPACITY, sizeof(i64)))
|
||||
#define wapp_u8_array_alloc_capacity(ALLOCATOR_PTR, CAPACITY) ((U8Array *)_array_alloc_capacity(ALLOCATOR_PTR, CAPACITY, sizeof(u8)))
|
||||
#define wapp_u16_array_alloc_capacity(ALLOCATOR_PTR, CAPACITY) ((U16Array *)_array_alloc_capacity(ALLOCATOR_PTR, CAPACITY, sizeof(u16)))
|
||||
#define wapp_u32_array_alloc_capacity(ALLOCATOR_PTR, CAPACITY) ((U32Array *)_array_alloc_capacity(ALLOCATOR_PTR, CAPACITY, sizeof(u32)))
|
||||
#define wapp_u64_array_alloc_capacity(ALLOCATOR_PTR, CAPACITY) ((U64Array *)_array_alloc_capacity(ALLOCATOR_PTR, CAPACITY, sizeof(u64)))
|
||||
#define wapp_f32_array_alloc_capacity(ALLOCATOR_PTR, CAPACITY) ((F32Array *)_array_alloc_capacity(ALLOCATOR_PTR, CAPACITY, sizeof(f32)))
|
||||
#define wapp_f64_array_alloc_capacity(ALLOCATOR_PTR, CAPACITY) ((F64Array *)_array_alloc_capacity(ALLOCATOR_PTR, CAPACITY, sizeof(f64)))
|
||||
#define wapp_f128_array_alloc_capacity(ALLOCATOR_PTR, CAPACITY) ((F128Array *)_array_alloc_capacity(ALLOCATOR_PTR, CAPACITY, sizeof(f128)))
|
||||
#define wapp_iptr_array_alloc_capacity(ALLOCATOR_PTR, CAPACITY) ((IptrArray *)_array_alloc_capacity(ALLOCATOR_PTR, CAPACITY, sizeof(iptr)))
|
||||
#define wapp_uptr_array_alloc_capacity(ALLOCATOR_PTR, CAPACITY) ((UptrArray *)_array_alloc_capacity(ALLOCATOR_PTR, CAPACITY, sizeof(uptr)))
|
||||
|
||||
#ifdef WAPP_PLATFORM_CPP
|
||||
#define wapp_void_ptr_array(...) ([&]() { \
|
||||
persistent void * buf[wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count(void *, __VA_ARGS__) * 2)] = {__VA_ARGS__}; \
|
||||
return VoidPArray{ \
|
||||
buf, \
|
||||
wapp_misc_utils_va_args_count(void *, __VA_ARGS__), \
|
||||
wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count(void *, __VA_ARGS__) * 2), \
|
||||
sizeof(void *) \
|
||||
}; \
|
||||
}())
|
||||
#define wapp_void_ptr_array_with_capacity(CAPACITY) ([&]() { \
|
||||
persistent void * buf[CAPACITY] = {}; \
|
||||
return VoidPArray{buf, 0, CAPACITY, sizeof(void *)}; \
|
||||
}())
|
||||
#define wapp_void_ptr_array_pop(ARRAY_PTR) (ARRAY_PTR != NULL && (ARRAY_PTR)->count > 0 ? \
|
||||
*_void_ptr_array_pop(ARRAY_PTR) : \
|
||||
void *{} \
|
||||
)
|
||||
#define wapp_str8_array(...) ([&]() { \
|
||||
persistent Str8 buf[wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count(Str8, __VA_ARGS__) * 2)] = {__VA_ARGS__}; \
|
||||
return Str8Array{ \
|
||||
buf, \
|
||||
wapp_misc_utils_va_args_count(Str8, __VA_ARGS__), \
|
||||
wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count(Str8, __VA_ARGS__) * 2), \
|
||||
sizeof(Str8) \
|
||||
}; \
|
||||
}())
|
||||
#define wapp_str8_array_with_capacity(CAPACITY) ([&]() { \
|
||||
persistent Str8 buf[CAPACITY] = {}; \
|
||||
return Str8Array{buf, 0, CAPACITY, sizeof(Str8)}; \
|
||||
}())
|
||||
#define wapp_str8_array_pop(ARRAY_PTR) (ARRAY_PTR != NULL && (ARRAY_PTR)->count > 0 ? \
|
||||
*_str8_array_pop(ARRAY_PTR) : \
|
||||
Str8{} \
|
||||
)
|
||||
#define wapp_b32_array(...) ([&]() { \
|
||||
persistent b32 buf[wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count(b32, __VA_ARGS__) * 2)] = {__VA_ARGS__}; \
|
||||
return B32Array{ \
|
||||
buf, \
|
||||
wapp_misc_utils_va_args_count(b32, __VA_ARGS__), \
|
||||
wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count(b32, __VA_ARGS__) * 2), \
|
||||
sizeof(b32) \
|
||||
}; \
|
||||
}())
|
||||
#define wapp_b32_array_with_capacity(CAPACITY) ([&]() { \
|
||||
persistent b32 buf[CAPACITY] = {}; \
|
||||
return B32Array{buf, 0, CAPACITY, sizeof(b32)}; \
|
||||
}())
|
||||
#define wapp_b32_array_pop(ARRAY_PTR) (ARRAY_PTR != NULL && (ARRAY_PTR)->count > 0 ? \
|
||||
*_b32_array_pop(ARRAY_PTR) : \
|
||||
b32{} \
|
||||
)
|
||||
#define wapp_char_array(...) ([&]() { \
|
||||
persistent char buf[wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count(char, __VA_ARGS__) * 2)] = {__VA_ARGS__}; \
|
||||
return CharArray{ \
|
||||
buf, \
|
||||
wapp_misc_utils_va_args_count(char, __VA_ARGS__), \
|
||||
wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count(char, __VA_ARGS__) * 2), \
|
||||
sizeof(char) \
|
||||
}; \
|
||||
}())
|
||||
#define wapp_char_array_with_capacity(CAPACITY) ([&]() { \
|
||||
persistent char buf[CAPACITY] = {}; \
|
||||
return CharArray{buf, 0, CAPACITY, sizeof(char)}; \
|
||||
}())
|
||||
#define wapp_char_array_pop(ARRAY_PTR) (ARRAY_PTR != NULL && (ARRAY_PTR)->count > 0 ? \
|
||||
*_char_array_pop(ARRAY_PTR) : \
|
||||
char{} \
|
||||
)
|
||||
#define wapp_c8_array(...) ([&]() { \
|
||||
persistent c8 buf[wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count(c8, __VA_ARGS__) * 2)] = {__VA_ARGS__}; \
|
||||
return C8Array{ \
|
||||
buf, \
|
||||
wapp_misc_utils_va_args_count(c8, __VA_ARGS__), \
|
||||
wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count(c8, __VA_ARGS__) * 2), \
|
||||
sizeof(c8) \
|
||||
}; \
|
||||
}())
|
||||
#define wapp_c8_array_with_capacity(CAPACITY) ([&]() { \
|
||||
persistent c8 buf[CAPACITY] = {}; \
|
||||
return C8Array{buf, 0, CAPACITY, sizeof(c8)}; \
|
||||
}())
|
||||
#define wapp_c8_array_pop(ARRAY_PTR) (ARRAY_PTR != NULL && (ARRAY_PTR)->count > 0 ? \
|
||||
*_c8_array_pop(ARRAY_PTR) : \
|
||||
c8{} \
|
||||
)
|
||||
#define wapp_c16_array(...) ([&]() { \
|
||||
persistent c16 buf[wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count(c16, __VA_ARGS__) * 2)] = {__VA_ARGS__}; \
|
||||
return C16Array{ \
|
||||
buf, \
|
||||
wapp_misc_utils_va_args_count(c16, __VA_ARGS__), \
|
||||
wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count(c16, __VA_ARGS__) * 2), \
|
||||
sizeof(c16) \
|
||||
}; \
|
||||
}())
|
||||
#define wapp_c16_array_with_capacity(CAPACITY) ([&]() { \
|
||||
persistent c16 buf[CAPACITY] = {}; \
|
||||
return C16Array{buf, 0, CAPACITY, sizeof(c16)}; \
|
||||
}())
|
||||
#define wapp_c16_array_pop(ARRAY_PTR) (ARRAY_PTR != NULL && (ARRAY_PTR)->count > 0 ? \
|
||||
*_c16_array_pop(ARRAY_PTR) : \
|
||||
c16{} \
|
||||
)
|
||||
#define wapp_c32_array(...) ([&]() { \
|
||||
persistent c32 buf[wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count(c32, __VA_ARGS__) * 2)] = {__VA_ARGS__}; \
|
||||
return C32Array{ \
|
||||
buf, \
|
||||
wapp_misc_utils_va_args_count(c32, __VA_ARGS__), \
|
||||
wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count(c32, __VA_ARGS__) * 2), \
|
||||
sizeof(c32) \
|
||||
}; \
|
||||
}())
|
||||
#define wapp_c32_array_with_capacity(CAPACITY) ([&]() { \
|
||||
persistent c32 buf[CAPACITY] = {}; \
|
||||
return C32Array{buf, 0, CAPACITY, sizeof(c32)}; \
|
||||
}())
|
||||
#define wapp_c32_array_pop(ARRAY_PTR) (ARRAY_PTR != NULL && (ARRAY_PTR)->count > 0 ? \
|
||||
*_c32_array_pop(ARRAY_PTR) : \
|
||||
c32{} \
|
||||
)
|
||||
#define wapp_i8_array(...) ([&]() { \
|
||||
persistent i8 buf[wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count(i8, __VA_ARGS__) * 2)] = {__VA_ARGS__}; \
|
||||
return I8Array{ \
|
||||
buf, \
|
||||
wapp_misc_utils_va_args_count(i8, __VA_ARGS__), \
|
||||
wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count(i8, __VA_ARGS__) * 2), \
|
||||
sizeof(i8) \
|
||||
}; \
|
||||
}())
|
||||
#define wapp_i8_array_with_capacity(CAPACITY) ([&]() { \
|
||||
persistent i8 buf[CAPACITY] = {}; \
|
||||
return I8Array{buf, 0, CAPACITY, sizeof(i8)}; \
|
||||
}())
|
||||
#define wapp_i8_array_pop(ARRAY_PTR) (ARRAY_PTR != NULL && (ARRAY_PTR)->count > 0 ? \
|
||||
*_i8_array_pop(ARRAY_PTR) : \
|
||||
i8{} \
|
||||
)
|
||||
#define wapp_i16_array(...) ([&]() { \
|
||||
persistent i16 buf[wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count(i16, __VA_ARGS__) * 2)] = {__VA_ARGS__}; \
|
||||
return I16Array{ \
|
||||
buf, \
|
||||
wapp_misc_utils_va_args_count(i16, __VA_ARGS__), \
|
||||
wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count(i16, __VA_ARGS__) * 2), \
|
||||
sizeof(i16) \
|
||||
}; \
|
||||
}())
|
||||
#define wapp_i16_array_with_capacity(CAPACITY) ([&]() { \
|
||||
persistent i16 buf[CAPACITY] = {}; \
|
||||
return I16Array{buf, 0, CAPACITY, sizeof(i16)}; \
|
||||
}())
|
||||
#define wapp_i16_array_pop(ARRAY_PTR) (ARRAY_PTR != NULL && (ARRAY_PTR)->count > 0 ? \
|
||||
*_i16_array_pop(ARRAY_PTR) : \
|
||||
i16{} \
|
||||
)
|
||||
#define wapp_i32_array(...) ([&]() { \
|
||||
persistent i32 buf[wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count(i32, __VA_ARGS__) * 2)] = {__VA_ARGS__}; \
|
||||
return I32Array{ \
|
||||
buf, \
|
||||
wapp_misc_utils_va_args_count(i32, __VA_ARGS__), \
|
||||
wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count(i32, __VA_ARGS__) * 2), \
|
||||
sizeof(i32) \
|
||||
}; \
|
||||
}())
|
||||
#define wapp_i32_array_with_capacity(CAPACITY) ([&]() { \
|
||||
persistent i32 buf[CAPACITY] = {}; \
|
||||
return I32Array{buf, 0, CAPACITY, sizeof(i32)}; \
|
||||
}())
|
||||
#define wapp_i32_array_pop(ARRAY_PTR) (ARRAY_PTR != NULL && (ARRAY_PTR)->count > 0 ? \
|
||||
*_i32_array_pop(ARRAY_PTR) : \
|
||||
i32{} \
|
||||
)
|
||||
#define wapp_i64_array(...) ([&]() { \
|
||||
persistent i64 buf[wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count(i64, __VA_ARGS__) * 2)] = {__VA_ARGS__}; \
|
||||
return I64Array{ \
|
||||
buf, \
|
||||
wapp_misc_utils_va_args_count(i64, __VA_ARGS__), \
|
||||
wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count(i64, __VA_ARGS__) * 2), \
|
||||
sizeof(i64) \
|
||||
}; \
|
||||
}())
|
||||
#define wapp_i64_array_with_capacity(CAPACITY) ([&]() { \
|
||||
persistent i64 buf[CAPACITY] = {}; \
|
||||
return I64Array{buf, 0, CAPACITY, sizeof(i64)}; \
|
||||
}())
|
||||
#define wapp_i64_array_pop(ARRAY_PTR) (ARRAY_PTR != NULL && (ARRAY_PTR)->count > 0 ? \
|
||||
*_i64_array_pop(ARRAY_PTR) : \
|
||||
i64{} \
|
||||
)
|
||||
#define wapp_u8_array(...) ([&]() { \
|
||||
persistent u8 buf[wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count(u8, __VA_ARGS__) * 2)] = {__VA_ARGS__}; \
|
||||
return U8Array{ \
|
||||
buf, \
|
||||
wapp_misc_utils_va_args_count(u8, __VA_ARGS__), \
|
||||
wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count(u8, __VA_ARGS__) * 2), \
|
||||
sizeof(u8) \
|
||||
}; \
|
||||
}())
|
||||
#define wapp_u8_array_with_capacity(CAPACITY) ([&]() { \
|
||||
persistent u8 buf[CAPACITY] = {}; \
|
||||
return U8Array{buf, 0, CAPACITY, sizeof(u8)}; \
|
||||
}())
|
||||
#define wapp_u8_array_pop(ARRAY_PTR) (ARRAY_PTR != NULL && (ARRAY_PTR)->count > 0 ? \
|
||||
*_u8_array_pop(ARRAY_PTR) : \
|
||||
u8{} \
|
||||
)
|
||||
#define wapp_u16_array(...) ([&]() { \
|
||||
persistent u16 buf[wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count(u16, __VA_ARGS__) * 2)] = {__VA_ARGS__}; \
|
||||
return U16Array{ \
|
||||
buf, \
|
||||
wapp_misc_utils_va_args_count(u16, __VA_ARGS__), \
|
||||
wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count(u16, __VA_ARGS__) * 2), \
|
||||
sizeof(u16) \
|
||||
}; \
|
||||
}())
|
||||
#define wapp_u16_array_with_capacity(CAPACITY) ([&]() { \
|
||||
persistent u16 buf[CAPACITY] = {}; \
|
||||
return U16Array{buf, 0, CAPACITY, sizeof(u16)}; \
|
||||
}())
|
||||
#define wapp_u16_array_pop(ARRAY_PTR) (ARRAY_PTR != NULL && (ARRAY_PTR)->count > 0 ? \
|
||||
*_u16_array_pop(ARRAY_PTR) : \
|
||||
u16{} \
|
||||
)
|
||||
#define wapp_u32_array(...) ([&]() { \
|
||||
persistent u32 buf[wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count(u32, __VA_ARGS__) * 2)] = {__VA_ARGS__}; \
|
||||
return U32Array{ \
|
||||
buf, \
|
||||
wapp_misc_utils_va_args_count(u32, __VA_ARGS__), \
|
||||
wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count(u32, __VA_ARGS__) * 2), \
|
||||
sizeof(u32) \
|
||||
}; \
|
||||
}())
|
||||
#define wapp_u32_array_with_capacity(CAPACITY) ([&]() { \
|
||||
persistent u32 buf[CAPACITY] = {}; \
|
||||
return U32Array{buf, 0, CAPACITY, sizeof(u32)}; \
|
||||
}())
|
||||
#define wapp_u32_array_pop(ARRAY_PTR) (ARRAY_PTR != NULL && (ARRAY_PTR)->count > 0 ? \
|
||||
*_u32_array_pop(ARRAY_PTR) : \
|
||||
u32{} \
|
||||
)
|
||||
#define wapp_u64_array(...) ([&]() { \
|
||||
persistent u64 buf[wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count(u64, __VA_ARGS__) * 2)] = {__VA_ARGS__}; \
|
||||
return U64Array{ \
|
||||
buf, \
|
||||
wapp_misc_utils_va_args_count(u64, __VA_ARGS__), \
|
||||
wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count(u64, __VA_ARGS__) * 2), \
|
||||
sizeof(u64) \
|
||||
}; \
|
||||
}())
|
||||
#define wapp_u64_array_with_capacity(CAPACITY) ([&]() { \
|
||||
persistent u64 buf[CAPACITY] = {}; \
|
||||
return U64Array{buf, 0, CAPACITY, sizeof(u64)}; \
|
||||
}())
|
||||
#define wapp_u64_array_pop(ARRAY_PTR) (ARRAY_PTR != NULL && (ARRAY_PTR)->count > 0 ? \
|
||||
*_u64_array_pop(ARRAY_PTR) : \
|
||||
u64{} \
|
||||
)
|
||||
#define wapp_f32_array(...) ([&]() { \
|
||||
persistent f32 buf[wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count(f32, __VA_ARGS__) * 2)] = {__VA_ARGS__}; \
|
||||
return F32Array{ \
|
||||
buf, \
|
||||
wapp_misc_utils_va_args_count(f32, __VA_ARGS__), \
|
||||
wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count(f32, __VA_ARGS__) * 2), \
|
||||
sizeof(f32) \
|
||||
}; \
|
||||
}())
|
||||
#define wapp_f32_array_with_capacity(CAPACITY) ([&]() { \
|
||||
persistent f32 buf[CAPACITY] = {}; \
|
||||
return F32Array{buf, 0, CAPACITY, sizeof(f32)}; \
|
||||
}())
|
||||
#define wapp_f32_array_pop(ARRAY_PTR) (ARRAY_PTR != NULL && (ARRAY_PTR)->count > 0 ? \
|
||||
*_f32_array_pop(ARRAY_PTR) : \
|
||||
f32{} \
|
||||
)
|
||||
#define wapp_f64_array(...) ([&]() { \
|
||||
persistent f64 buf[wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count(f64, __VA_ARGS__) * 2)] = {__VA_ARGS__}; \
|
||||
return F64Array{ \
|
||||
buf, \
|
||||
wapp_misc_utils_va_args_count(f64, __VA_ARGS__), \
|
||||
wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count(f64, __VA_ARGS__) * 2), \
|
||||
sizeof(f64) \
|
||||
}; \
|
||||
}())
|
||||
#define wapp_f64_array_with_capacity(CAPACITY) ([&]() { \
|
||||
persistent f64 buf[CAPACITY] = {}; \
|
||||
return F64Array{buf, 0, CAPACITY, sizeof(f64)}; \
|
||||
}())
|
||||
#define wapp_f64_array_pop(ARRAY_PTR) (ARRAY_PTR != NULL && (ARRAY_PTR)->count > 0 ? \
|
||||
*_f64_array_pop(ARRAY_PTR) : \
|
||||
f64{} \
|
||||
)
|
||||
#define wapp_f128_array(...) ([&]() { \
|
||||
persistent f128 buf[wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count(f128, __VA_ARGS__) * 2)] = {__VA_ARGS__}; \
|
||||
return F128Array{ \
|
||||
buf, \
|
||||
wapp_misc_utils_va_args_count(f128, __VA_ARGS__), \
|
||||
wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count(f128, __VA_ARGS__) * 2), \
|
||||
sizeof(f128) \
|
||||
}; \
|
||||
}())
|
||||
#define wapp_f128_array_with_capacity(CAPACITY) ([&]() { \
|
||||
persistent f128 buf[CAPACITY] = {}; \
|
||||
return F128Array{buf, 0, CAPACITY, sizeof(f128)}; \
|
||||
}())
|
||||
#define wapp_f128_array_pop(ARRAY_PTR) (ARRAY_PTR != NULL && (ARRAY_PTR)->count > 0 ? \
|
||||
*_f128_array_pop(ARRAY_PTR) : \
|
||||
f128{} \
|
||||
)
|
||||
#define wapp_iptr_array(...) ([&]() { \
|
||||
persistent iptr buf[wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count(iptr, __VA_ARGS__) * 2)] = {__VA_ARGS__}; \
|
||||
return IptrArray{ \
|
||||
buf, \
|
||||
wapp_misc_utils_va_args_count(iptr, __VA_ARGS__), \
|
||||
wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count(iptr, __VA_ARGS__) * 2), \
|
||||
sizeof(iptr) \
|
||||
}; \
|
||||
}())
|
||||
#define wapp_iptr_array_with_capacity(CAPACITY) ([&]() { \
|
||||
persistent iptr buf[CAPACITY] = {}; \
|
||||
return IptrArray{buf, 0, CAPACITY, sizeof(iptr)}; \
|
||||
}())
|
||||
#define wapp_iptr_array_pop(ARRAY_PTR) (ARRAY_PTR != NULL && (ARRAY_PTR)->count > 0 ? \
|
||||
*_iptr_array_pop(ARRAY_PTR) : \
|
||||
iptr{} \
|
||||
)
|
||||
#define wapp_uptr_array(...) ([&]() { \
|
||||
persistent uptr buf[wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count(uptr, __VA_ARGS__) * 2)] = {__VA_ARGS__}; \
|
||||
return UptrArray{ \
|
||||
buf, \
|
||||
wapp_misc_utils_va_args_count(uptr, __VA_ARGS__), \
|
||||
wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count(uptr, __VA_ARGS__) * 2), \
|
||||
sizeof(uptr) \
|
||||
}; \
|
||||
}())
|
||||
#define wapp_uptr_array_with_capacity(CAPACITY) ([&]() { \
|
||||
persistent uptr buf[CAPACITY] = {}; \
|
||||
return UptrArray{buf, 0, CAPACITY, sizeof(uptr)}; \
|
||||
}())
|
||||
#define wapp_uptr_array_pop(ARRAY_PTR) (ARRAY_PTR != NULL && (ARRAY_PTR)->count > 0 ? \
|
||||
*_uptr_array_pop(ARRAY_PTR) : \
|
||||
uptr{} \
|
||||
)
|
||||
#else
|
||||
#define wapp_void_ptr_array(...) ((VoidPArray){ \
|
||||
.items = (void *[wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count(void *, __VA_ARGS__) * 2)]){__VA_ARGS__}, \
|
||||
.count = wapp_misc_utils_va_args_count(void *, __VA_ARGS__), \
|
||||
.capacity = wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count(void *, __VA_ARGS__) * 2), \
|
||||
.item_size = sizeof(void *) \
|
||||
})
|
||||
#define wapp_void_ptr_array_with_capacity(CAPACITY) ((VoidPArray){.items = (void *[CAPACITY]){0}, .count = 0, .capacity = CAPACITY, .item_size = sizeof(void *)})
|
||||
#define wapp_void_ptr_array_pop(ARRAY_PTR) (ARRAY_PTR != NULL && (ARRAY_PTR)->count > 0 ? \
|
||||
*_void_ptr_array_pop(ARRAY_PTR) : \
|
||||
(void *){0} \
|
||||
)
|
||||
#define wapp_str8_array(...) ((Str8Array){ \
|
||||
.items = (Str8[wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count(Str8, __VA_ARGS__) * 2)]){__VA_ARGS__}, \
|
||||
.count = wapp_misc_utils_va_args_count(Str8, __VA_ARGS__), \
|
||||
.capacity = wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count(Str8, __VA_ARGS__) * 2), \
|
||||
.item_size = sizeof(Str8) \
|
||||
})
|
||||
#define wapp_str8_array_with_capacity(CAPACITY) ((Str8Array){.items = (Str8[CAPACITY]){0}, .count = 0, .capacity = CAPACITY, .item_size = sizeof(Str8)})
|
||||
#define wapp_str8_array_pop(ARRAY_PTR) (ARRAY_PTR != NULL && (ARRAY_PTR)->count > 0 ? \
|
||||
*_str8_array_pop(ARRAY_PTR) : \
|
||||
(Str8){0} \
|
||||
)
|
||||
#define wapp_b32_array(...) ((B32Array){ \
|
||||
.items = (b32[wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count(b32, __VA_ARGS__) * 2)]){__VA_ARGS__}, \
|
||||
.count = wapp_misc_utils_va_args_count(b32, __VA_ARGS__), \
|
||||
.capacity = wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count(b32, __VA_ARGS__) * 2), \
|
||||
.item_size = sizeof(b32) \
|
||||
})
|
||||
#define wapp_b32_array_with_capacity(CAPACITY) ((B32Array){.items = (b32[CAPACITY]){0}, .count = 0, .capacity = CAPACITY, .item_size = sizeof(b32)})
|
||||
#define wapp_b32_array_pop(ARRAY_PTR) (ARRAY_PTR != NULL && (ARRAY_PTR)->count > 0 ? \
|
||||
*_b32_array_pop(ARRAY_PTR) : \
|
||||
(b32){0} \
|
||||
)
|
||||
#define wapp_char_array(...) ((CharArray){ \
|
||||
.items = (char[wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count(char, __VA_ARGS__) * 2)]){__VA_ARGS__}, \
|
||||
.count = wapp_misc_utils_va_args_count(char, __VA_ARGS__), \
|
||||
.capacity = wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count(char, __VA_ARGS__) * 2), \
|
||||
.item_size = sizeof(char) \
|
||||
})
|
||||
#define wapp_char_array_with_capacity(CAPACITY) ((CharArray){.items = (char[CAPACITY]){0}, .count = 0, .capacity = CAPACITY, .item_size = sizeof(char)})
|
||||
#define wapp_char_array_pop(ARRAY_PTR) (ARRAY_PTR != NULL && (ARRAY_PTR)->count > 0 ? \
|
||||
*_char_array_pop(ARRAY_PTR) : \
|
||||
(char){0} \
|
||||
)
|
||||
#define wapp_c8_array(...) ((C8Array){ \
|
||||
.items = (c8[wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count(c8, __VA_ARGS__) * 2)]){__VA_ARGS__}, \
|
||||
.count = wapp_misc_utils_va_args_count(c8, __VA_ARGS__), \
|
||||
.capacity = wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count(c8, __VA_ARGS__) * 2), \
|
||||
.item_size = sizeof(c8) \
|
||||
})
|
||||
#define wapp_c8_array_with_capacity(CAPACITY) ((C8Array){.items = (c8[CAPACITY]){0}, .count = 0, .capacity = CAPACITY, .item_size = sizeof(c8)})
|
||||
#define wapp_c8_array_pop(ARRAY_PTR) (ARRAY_PTR != NULL && (ARRAY_PTR)->count > 0 ? \
|
||||
*_c8_array_pop(ARRAY_PTR) : \
|
||||
(c8){0} \
|
||||
)
|
||||
#define wapp_c16_array(...) ((C16Array){ \
|
||||
.items = (c16[wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count(c16, __VA_ARGS__) * 2)]){__VA_ARGS__}, \
|
||||
.count = wapp_misc_utils_va_args_count(c16, __VA_ARGS__), \
|
||||
.capacity = wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count(c16, __VA_ARGS__) * 2), \
|
||||
.item_size = sizeof(c16) \
|
||||
})
|
||||
#define wapp_c16_array_with_capacity(CAPACITY) ((C16Array){.items = (c16[CAPACITY]){0}, .count = 0, .capacity = CAPACITY, .item_size = sizeof(c16)})
|
||||
#define wapp_c16_array_pop(ARRAY_PTR) (ARRAY_PTR != NULL && (ARRAY_PTR)->count > 0 ? \
|
||||
*_c16_array_pop(ARRAY_PTR) : \
|
||||
(c16){0} \
|
||||
)
|
||||
#define wapp_c32_array(...) ((C32Array){ \
|
||||
.items = (c32[wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count(c32, __VA_ARGS__) * 2)]){__VA_ARGS__}, \
|
||||
.count = wapp_misc_utils_va_args_count(c32, __VA_ARGS__), \
|
||||
.capacity = wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count(c32, __VA_ARGS__) * 2), \
|
||||
.item_size = sizeof(c32) \
|
||||
})
|
||||
#define wapp_c32_array_with_capacity(CAPACITY) ((C32Array){.items = (c32[CAPACITY]){0}, .count = 0, .capacity = CAPACITY, .item_size = sizeof(c32)})
|
||||
#define wapp_c32_array_pop(ARRAY_PTR) (ARRAY_PTR != NULL && (ARRAY_PTR)->count > 0 ? \
|
||||
*_c32_array_pop(ARRAY_PTR) : \
|
||||
(c32){0} \
|
||||
)
|
||||
#define wapp_i8_array(...) ((I8Array){ \
|
||||
.items = (i8[wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count(i8, __VA_ARGS__) * 2)]){__VA_ARGS__}, \
|
||||
.count = wapp_misc_utils_va_args_count(i8, __VA_ARGS__), \
|
||||
.capacity = wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count(i8, __VA_ARGS__) * 2), \
|
||||
.item_size = sizeof(i8) \
|
||||
})
|
||||
#define wapp_i8_array_with_capacity(CAPACITY) ((I8Array){.items = (i8[CAPACITY]){0}, .count = 0, .capacity = CAPACITY, .item_size = sizeof(i8)})
|
||||
#define wapp_i8_array_pop(ARRAY_PTR) (ARRAY_PTR != NULL && (ARRAY_PTR)->count > 0 ? \
|
||||
*_i8_array_pop(ARRAY_PTR) : \
|
||||
(i8){0} \
|
||||
)
|
||||
#define wapp_i16_array(...) ((I16Array){ \
|
||||
.items = (i16[wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count(i16, __VA_ARGS__) * 2)]){__VA_ARGS__}, \
|
||||
.count = wapp_misc_utils_va_args_count(i16, __VA_ARGS__), \
|
||||
.capacity = wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count(i16, __VA_ARGS__) * 2), \
|
||||
.item_size = sizeof(i16) \
|
||||
})
|
||||
#define wapp_i16_array_with_capacity(CAPACITY) ((I16Array){.items = (i16[CAPACITY]){0}, .count = 0, .capacity = CAPACITY, .item_size = sizeof(i16)})
|
||||
#define wapp_i16_array_pop(ARRAY_PTR) (ARRAY_PTR != NULL && (ARRAY_PTR)->count > 0 ? \
|
||||
*_i16_array_pop(ARRAY_PTR) : \
|
||||
(i16){0} \
|
||||
)
|
||||
#define wapp_i32_array(...) ((I32Array){ \
|
||||
.items = (i32[wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count(i32, __VA_ARGS__) * 2)]){__VA_ARGS__}, \
|
||||
.count = wapp_misc_utils_va_args_count(i32, __VA_ARGS__), \
|
||||
.capacity = wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count(i32, __VA_ARGS__) * 2), \
|
||||
.item_size = sizeof(i32) \
|
||||
})
|
||||
#define wapp_i32_array_with_capacity(CAPACITY) ((I32Array){.items = (i32[CAPACITY]){0}, .count = 0, .capacity = CAPACITY, .item_size = sizeof(i32)})
|
||||
#define wapp_i32_array_pop(ARRAY_PTR) (ARRAY_PTR != NULL && (ARRAY_PTR)->count > 0 ? \
|
||||
*_i32_array_pop(ARRAY_PTR) : \
|
||||
(i32){0} \
|
||||
)
|
||||
#define wapp_i64_array(...) ((I64Array){ \
|
||||
.items = (i64[wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count(i64, __VA_ARGS__) * 2)]){__VA_ARGS__}, \
|
||||
.count = wapp_misc_utils_va_args_count(i64, __VA_ARGS__), \
|
||||
.capacity = wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count(i64, __VA_ARGS__) * 2), \
|
||||
.item_size = sizeof(i64) \
|
||||
})
|
||||
#define wapp_i64_array_with_capacity(CAPACITY) ((I64Array){.items = (i64[CAPACITY]){0}, .count = 0, .capacity = CAPACITY, .item_size = sizeof(i64)})
|
||||
#define wapp_i64_array_pop(ARRAY_PTR) (ARRAY_PTR != NULL && (ARRAY_PTR)->count > 0 ? \
|
||||
*_i64_array_pop(ARRAY_PTR) : \
|
||||
(i64){0} \
|
||||
)
|
||||
#define wapp_u8_array(...) ((U8Array){ \
|
||||
.items = (u8[wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count(u8, __VA_ARGS__) * 2)]){__VA_ARGS__}, \
|
||||
.count = wapp_misc_utils_va_args_count(u8, __VA_ARGS__), \
|
||||
.capacity = wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count(u8, __VA_ARGS__) * 2), \
|
||||
.item_size = sizeof(u8) \
|
||||
})
|
||||
#define wapp_u8_array_with_capacity(CAPACITY) ((U8Array){.items = (u8[CAPACITY]){0}, .count = 0, .capacity = CAPACITY, .item_size = sizeof(u8)})
|
||||
#define wapp_u8_array_pop(ARRAY_PTR) (ARRAY_PTR != NULL && (ARRAY_PTR)->count > 0 ? \
|
||||
*_u8_array_pop(ARRAY_PTR) : \
|
||||
(u8){0} \
|
||||
)
|
||||
#define wapp_u16_array(...) ((U16Array){ \
|
||||
.items = (u16[wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count(u16, __VA_ARGS__) * 2)]){__VA_ARGS__}, \
|
||||
.count = wapp_misc_utils_va_args_count(u16, __VA_ARGS__), \
|
||||
.capacity = wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count(u16, __VA_ARGS__) * 2), \
|
||||
.item_size = sizeof(u16) \
|
||||
})
|
||||
#define wapp_u16_array_with_capacity(CAPACITY) ((U16Array){.items = (u16[CAPACITY]){0}, .count = 0, .capacity = CAPACITY, .item_size = sizeof(u16)})
|
||||
#define wapp_u16_array_pop(ARRAY_PTR) (ARRAY_PTR != NULL && (ARRAY_PTR)->count > 0 ? \
|
||||
*_u16_array_pop(ARRAY_PTR) : \
|
||||
(u16){0} \
|
||||
)
|
||||
#define wapp_u32_array(...) ((U32Array){ \
|
||||
.items = (u32[wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count(u32, __VA_ARGS__) * 2)]){__VA_ARGS__}, \
|
||||
.count = wapp_misc_utils_va_args_count(u32, __VA_ARGS__), \
|
||||
.capacity = wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count(u32, __VA_ARGS__) * 2), \
|
||||
.item_size = sizeof(u32) \
|
||||
})
|
||||
#define wapp_u32_array_with_capacity(CAPACITY) ((U32Array){.items = (u32[CAPACITY]){0}, .count = 0, .capacity = CAPACITY, .item_size = sizeof(u32)})
|
||||
#define wapp_u32_array_pop(ARRAY_PTR) (ARRAY_PTR != NULL && (ARRAY_PTR)->count > 0 ? \
|
||||
*_u32_array_pop(ARRAY_PTR) : \
|
||||
(u32){0} \
|
||||
)
|
||||
#define wapp_u64_array(...) ((U64Array){ \
|
||||
.items = (u64[wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count(u64, __VA_ARGS__) * 2)]){__VA_ARGS__}, \
|
||||
.count = wapp_misc_utils_va_args_count(u64, __VA_ARGS__), \
|
||||
.capacity = wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count(u64, __VA_ARGS__) * 2), \
|
||||
.item_size = sizeof(u64) \
|
||||
})
|
||||
#define wapp_u64_array_with_capacity(CAPACITY) ((U64Array){.items = (u64[CAPACITY]){0}, .count = 0, .capacity = CAPACITY, .item_size = sizeof(u64)})
|
||||
#define wapp_u64_array_pop(ARRAY_PTR) (ARRAY_PTR != NULL && (ARRAY_PTR)->count > 0 ? \
|
||||
*_u64_array_pop(ARRAY_PTR) : \
|
||||
(u64){0} \
|
||||
)
|
||||
#define wapp_f32_array(...) ((F32Array){ \
|
||||
.items = (f32[wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count(f32, __VA_ARGS__) * 2)]){__VA_ARGS__}, \
|
||||
.count = wapp_misc_utils_va_args_count(f32, __VA_ARGS__), \
|
||||
.capacity = wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count(f32, __VA_ARGS__) * 2), \
|
||||
.item_size = sizeof(f32) \
|
||||
})
|
||||
#define wapp_f32_array_with_capacity(CAPACITY) ((F32Array){.items = (f32[CAPACITY]){0}, .count = 0, .capacity = CAPACITY, .item_size = sizeof(f32)})
|
||||
#define wapp_f32_array_pop(ARRAY_PTR) (ARRAY_PTR != NULL && (ARRAY_PTR)->count > 0 ? \
|
||||
*_f32_array_pop(ARRAY_PTR) : \
|
||||
(f32){0} \
|
||||
)
|
||||
#define wapp_f64_array(...) ((F64Array){ \
|
||||
.items = (f64[wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count(f64, __VA_ARGS__) * 2)]){__VA_ARGS__}, \
|
||||
.count = wapp_misc_utils_va_args_count(f64, __VA_ARGS__), \
|
||||
.capacity = wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count(f64, __VA_ARGS__) * 2), \
|
||||
.item_size = sizeof(f64) \
|
||||
})
|
||||
#define wapp_f64_array_with_capacity(CAPACITY) ((F64Array){.items = (f64[CAPACITY]){0}, .count = 0, .capacity = CAPACITY, .item_size = sizeof(f64)})
|
||||
#define wapp_f64_array_pop(ARRAY_PTR) (ARRAY_PTR != NULL && (ARRAY_PTR)->count > 0 ? \
|
||||
*_f64_array_pop(ARRAY_PTR) : \
|
||||
(f64){0} \
|
||||
)
|
||||
#define wapp_f128_array(...) ((F128Array){ \
|
||||
.items = (f128[wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count(f128, __VA_ARGS__) * 2)]){__VA_ARGS__}, \
|
||||
.count = wapp_misc_utils_va_args_count(f128, __VA_ARGS__), \
|
||||
.capacity = wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count(f128, __VA_ARGS__) * 2), \
|
||||
.item_size = sizeof(f128) \
|
||||
})
|
||||
#define wapp_f128_array_with_capacity(CAPACITY) ((F128Array){.items = (f128[CAPACITY]){0}, .count = 0, .capacity = CAPACITY, .item_size = sizeof(f128)})
|
||||
#define wapp_f128_array_pop(ARRAY_PTR) (ARRAY_PTR != NULL && (ARRAY_PTR)->count > 0 ? \
|
||||
*_f128_array_pop(ARRAY_PTR) : \
|
||||
(f128){0} \
|
||||
)
|
||||
#define wapp_iptr_array(...) ((IptrArray){ \
|
||||
.items = (iptr[wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count(iptr, __VA_ARGS__) * 2)]){__VA_ARGS__}, \
|
||||
.count = wapp_misc_utils_va_args_count(iptr, __VA_ARGS__), \
|
||||
.capacity = wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count(iptr, __VA_ARGS__) * 2), \
|
||||
.item_size = sizeof(iptr) \
|
||||
})
|
||||
#define wapp_iptr_array_with_capacity(CAPACITY) ((IptrArray){.items = (iptr[CAPACITY]){0}, .count = 0, .capacity = CAPACITY, .item_size = sizeof(iptr)})
|
||||
#define wapp_iptr_array_pop(ARRAY_PTR) (ARRAY_PTR != NULL && (ARRAY_PTR)->count > 0 ? \
|
||||
*_iptr_array_pop(ARRAY_PTR) : \
|
||||
(iptr){0} \
|
||||
)
|
||||
#define wapp_uptr_array(...) ((UptrArray){ \
|
||||
.items = (uptr[wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count(uptr, __VA_ARGS__) * 2)]){__VA_ARGS__}, \
|
||||
.count = wapp_misc_utils_va_args_count(uptr, __VA_ARGS__), \
|
||||
.capacity = wapp_misc_utils_u64_round_up_pow2(wapp_misc_utils_va_args_count(uptr, __VA_ARGS__) * 2), \
|
||||
.item_size = sizeof(uptr) \
|
||||
})
|
||||
#define wapp_uptr_array_with_capacity(CAPACITY) ((UptrArray){.items = (uptr[CAPACITY]){0}, .count = 0, .capacity = CAPACITY, .item_size = sizeof(uptr)})
|
||||
#define wapp_uptr_array_pop(ARRAY_PTR) (ARRAY_PTR != NULL && (ARRAY_PTR)->count > 0 ? \
|
||||
*_uptr_array_pop(ARRAY_PTR) : \
|
||||
(uptr){0} \
|
||||
)
|
||||
#endif // !WAPP_PLATFORM_CPP
|
||||
|
||||
typedef struct str8 Str8;
|
||||
|
||||
typedef struct GenericArray GenericArray;
|
||||
struct GenericArray {
|
||||
void *items;
|
||||
u64 count;
|
||||
u64 capacity;
|
||||
u64 item_size;
|
||||
};
|
||||
|
||||
typedef struct VoidPArray VoidPArray;
|
||||
struct VoidPArray {
|
||||
void * *items;
|
||||
u64 count;
|
||||
u64 capacity;
|
||||
u64 item_size;
|
||||
};
|
||||
|
||||
typedef struct Str8Array Str8Array;
|
||||
struct Str8Array {
|
||||
Str8 *items;
|
||||
u64 count;
|
||||
u64 capacity;
|
||||
u64 item_size;
|
||||
};
|
||||
|
||||
typedef struct B32Array B32Array;
|
||||
struct B32Array {
|
||||
b32 *items;
|
||||
u64 count;
|
||||
u64 capacity;
|
||||
u64 item_size;
|
||||
};
|
||||
|
||||
typedef struct CharArray CharArray;
|
||||
struct CharArray {
|
||||
char *items;
|
||||
u64 count;
|
||||
u64 capacity;
|
||||
u64 item_size;
|
||||
};
|
||||
|
||||
typedef struct C8Array C8Array;
|
||||
struct C8Array {
|
||||
c8 *items;
|
||||
u64 count;
|
||||
u64 capacity;
|
||||
u64 item_size;
|
||||
};
|
||||
|
||||
typedef struct C16Array C16Array;
|
||||
struct C16Array {
|
||||
c16 *items;
|
||||
u64 count;
|
||||
u64 capacity;
|
||||
u64 item_size;
|
||||
};
|
||||
|
||||
typedef struct C32Array C32Array;
|
||||
struct C32Array {
|
||||
c32 *items;
|
||||
u64 count;
|
||||
u64 capacity;
|
||||
u64 item_size;
|
||||
};
|
||||
|
||||
typedef struct I8Array I8Array;
|
||||
struct I8Array {
|
||||
i8 *items;
|
||||
u64 count;
|
||||
u64 capacity;
|
||||
u64 item_size;
|
||||
};
|
||||
|
||||
typedef struct I16Array I16Array;
|
||||
struct I16Array {
|
||||
i16 *items;
|
||||
u64 count;
|
||||
u64 capacity;
|
||||
u64 item_size;
|
||||
};
|
||||
|
||||
typedef struct I32Array I32Array;
|
||||
struct I32Array {
|
||||
i32 *items;
|
||||
u64 count;
|
||||
u64 capacity;
|
||||
u64 item_size;
|
||||
};
|
||||
|
||||
typedef struct I64Array I64Array;
|
||||
struct I64Array {
|
||||
i64 *items;
|
||||
u64 count;
|
||||
u64 capacity;
|
||||
u64 item_size;
|
||||
};
|
||||
|
||||
typedef struct U8Array U8Array;
|
||||
struct U8Array {
|
||||
u8 *items;
|
||||
u64 count;
|
||||
u64 capacity;
|
||||
u64 item_size;
|
||||
};
|
||||
|
||||
typedef struct U16Array U16Array;
|
||||
struct U16Array {
|
||||
u16 *items;
|
||||
u64 count;
|
||||
u64 capacity;
|
||||
u64 item_size;
|
||||
};
|
||||
|
||||
typedef struct U32Array U32Array;
|
||||
struct U32Array {
|
||||
u32 *items;
|
||||
u64 count;
|
||||
u64 capacity;
|
||||
u64 item_size;
|
||||
};
|
||||
|
||||
typedef struct U64Array U64Array;
|
||||
struct U64Array {
|
||||
u64 *items;
|
||||
u64 count;
|
||||
u64 capacity;
|
||||
u64 item_size;
|
||||
};
|
||||
|
||||
typedef struct F32Array F32Array;
|
||||
struct F32Array {
|
||||
f32 *items;
|
||||
u64 count;
|
||||
u64 capacity;
|
||||
u64 item_size;
|
||||
};
|
||||
|
||||
typedef struct F64Array F64Array;
|
||||
struct F64Array {
|
||||
f64 *items;
|
||||
u64 count;
|
||||
u64 capacity;
|
||||
u64 item_size;
|
||||
};
|
||||
|
||||
typedef struct F128Array F128Array;
|
||||
struct F128Array {
|
||||
f128 *items;
|
||||
u64 count;
|
||||
u64 capacity;
|
||||
u64 item_size;
|
||||
};
|
||||
|
||||
typedef struct IptrArray IptrArray;
|
||||
struct IptrArray {
|
||||
iptr *items;
|
||||
u64 count;
|
||||
u64 capacity;
|
||||
u64 item_size;
|
||||
};
|
||||
|
||||
typedef struct UptrArray UptrArray;
|
||||
struct UptrArray {
|
||||
uptr *items;
|
||||
u64 count;
|
||||
u64 capacity;
|
||||
u64 item_size;
|
||||
};
|
||||
|
||||
void * *wapp_void_ptr_array_get(const VoidPArray *array, u64 index);
|
||||
void wapp_void_ptr_array_set(VoidPArray *array, u64 index, void * *item);
|
||||
void wapp_void_ptr_array_append_capped(VoidPArray *array, void * *item);
|
||||
void wapp_void_ptr_array_extend_capped(VoidPArray *array, const VoidPArray *other);
|
||||
void wapp_void_ptr_array_clear(VoidPArray *array);
|
||||
void wapp_void_ptr_array_copy_capped(const VoidPArray *src, VoidPArray *dst);
|
||||
VoidPArray *wapp_void_ptr_array_append_alloc(const Allocator *allocator, VoidPArray *array, void * *item);
|
||||
VoidPArray *wapp_void_ptr_array_extend_alloc(const Allocator *allocator, VoidPArray *array, const VoidPArray *other);
|
||||
VoidPArray *wapp_void_ptr_array_copy_alloc(const Allocator *allocator, const VoidPArray *src, VoidPArray *dst);
|
||||
void * *_void_ptr_array_pop(VoidPArray *array);
|
||||
Str8 *wapp_str8_array_get(const Str8Array *array, u64 index);
|
||||
void wapp_str8_array_set(Str8Array *array, u64 index, Str8 *item);
|
||||
void wapp_str8_array_append_capped(Str8Array *array, Str8 *item);
|
||||
void wapp_str8_array_extend_capped(Str8Array *array, const Str8Array *other);
|
||||
void wapp_str8_array_clear(Str8Array *array);
|
||||
void wapp_str8_array_copy_capped(const Str8Array *src, Str8Array *dst);
|
||||
Str8Array *wapp_str8_array_append_alloc(const Allocator *allocator, Str8Array *array, Str8 *item);
|
||||
Str8Array *wapp_str8_array_extend_alloc(const Allocator *allocator, Str8Array *array, const Str8Array *other);
|
||||
Str8Array *wapp_str8_array_copy_alloc(const Allocator *allocator, const Str8Array *src, Str8Array *dst);
|
||||
Str8 *_str8_array_pop(Str8Array *array);
|
||||
b32 *wapp_b32_array_get(const B32Array *array, u64 index);
|
||||
void wapp_b32_array_set(B32Array *array, u64 index, b32 *item);
|
||||
void wapp_b32_array_append_capped(B32Array *array, b32 *item);
|
||||
void wapp_b32_array_extend_capped(B32Array *array, const B32Array *other);
|
||||
void wapp_b32_array_clear(B32Array *array);
|
||||
void wapp_b32_array_copy_capped(const B32Array *src, B32Array *dst);
|
||||
B32Array *wapp_b32_array_append_alloc(const Allocator *allocator, B32Array *array, b32 *item);
|
||||
B32Array *wapp_b32_array_extend_alloc(const Allocator *allocator, B32Array *array, const B32Array *other);
|
||||
B32Array *wapp_b32_array_copy_alloc(const Allocator *allocator, const B32Array *src, B32Array *dst);
|
||||
b32 *_b32_array_pop(B32Array *array);
|
||||
char *wapp_char_array_get(const CharArray *array, u64 index);
|
||||
void wapp_char_array_set(CharArray *array, u64 index, char *item);
|
||||
void wapp_char_array_append_capped(CharArray *array, char *item);
|
||||
void wapp_char_array_extend_capped(CharArray *array, const CharArray *other);
|
||||
void wapp_char_array_clear(CharArray *array);
|
||||
void wapp_char_array_copy_capped(const CharArray *src, CharArray *dst);
|
||||
CharArray *wapp_char_array_append_alloc(const Allocator *allocator, CharArray *array, char *item);
|
||||
CharArray *wapp_char_array_extend_alloc(const Allocator *allocator, CharArray *array, const CharArray *other);
|
||||
CharArray *wapp_char_array_copy_alloc(const Allocator *allocator, const CharArray *src, CharArray *dst);
|
||||
char *_char_array_pop(CharArray *array);
|
||||
c8 *wapp_c8_array_get(const C8Array *array, u64 index);
|
||||
void wapp_c8_array_set(C8Array *array, u64 index, c8 *item);
|
||||
void wapp_c8_array_append_capped(C8Array *array, c8 *item);
|
||||
void wapp_c8_array_extend_capped(C8Array *array, const C8Array *other);
|
||||
void wapp_c8_array_clear(C8Array *array);
|
||||
void wapp_c8_array_copy_capped(const C8Array *src, C8Array *dst);
|
||||
C8Array *wapp_c8_array_append_alloc(const Allocator *allocator, C8Array *array, c8 *item);
|
||||
C8Array *wapp_c8_array_extend_alloc(const Allocator *allocator, C8Array *array, const C8Array *other);
|
||||
C8Array *wapp_c8_array_copy_alloc(const Allocator *allocator, const C8Array *src, C8Array *dst);
|
||||
c8 *_c8_array_pop(C8Array *array);
|
||||
c16 *wapp_c16_array_get(const C16Array *array, u64 index);
|
||||
void wapp_c16_array_set(C16Array *array, u64 index, c16 *item);
|
||||
void wapp_c16_array_append_capped(C16Array *array, c16 *item);
|
||||
void wapp_c16_array_extend_capped(C16Array *array, const C16Array *other);
|
||||
void wapp_c16_array_clear(C16Array *array);
|
||||
void wapp_c16_array_copy_capped(const C16Array *src, C16Array *dst);
|
||||
C16Array *wapp_c16_array_append_alloc(const Allocator *allocator, C16Array *array, c16 *item);
|
||||
C16Array *wapp_c16_array_extend_alloc(const Allocator *allocator, C16Array *array, const C16Array *other);
|
||||
C16Array *wapp_c16_array_copy_alloc(const Allocator *allocator, const C16Array *src, C16Array *dst);
|
||||
c16 *_c16_array_pop(C16Array *array);
|
||||
c32 *wapp_c32_array_get(const C32Array *array, u64 index);
|
||||
void wapp_c32_array_set(C32Array *array, u64 index, c32 *item);
|
||||
void wapp_c32_array_append_capped(C32Array *array, c32 *item);
|
||||
void wapp_c32_array_extend_capped(C32Array *array, const C32Array *other);
|
||||
void wapp_c32_array_clear(C32Array *array);
|
||||
void wapp_c32_array_copy_capped(const C32Array *src, C32Array *dst);
|
||||
C32Array *wapp_c32_array_append_alloc(const Allocator *allocator, C32Array *array, c32 *item);
|
||||
C32Array *wapp_c32_array_extend_alloc(const Allocator *allocator, C32Array *array, const C32Array *other);
|
||||
C32Array *wapp_c32_array_copy_alloc(const Allocator *allocator, const C32Array *src, C32Array *dst);
|
||||
c32 *_c32_array_pop(C32Array *array);
|
||||
i8 *wapp_i8_array_get(const I8Array *array, u64 index);
|
||||
void wapp_i8_array_set(I8Array *array, u64 index, i8 *item);
|
||||
void wapp_i8_array_append_capped(I8Array *array, i8 *item);
|
||||
void wapp_i8_array_extend_capped(I8Array *array, const I8Array *other);
|
||||
void wapp_i8_array_clear(I8Array *array);
|
||||
void wapp_i8_array_copy_capped(const I8Array *src, I8Array *dst);
|
||||
I8Array *wapp_i8_array_append_alloc(const Allocator *allocator, I8Array *array, i8 *item);
|
||||
I8Array *wapp_i8_array_extend_alloc(const Allocator *allocator, I8Array *array, const I8Array *other);
|
||||
I8Array *wapp_i8_array_copy_alloc(const Allocator *allocator, const I8Array *src, I8Array *dst);
|
||||
i8 *_i8_array_pop(I8Array *array);
|
||||
i16 *wapp_i16_array_get(const I16Array *array, u64 index);
|
||||
void wapp_i16_array_set(I16Array *array, u64 index, i16 *item);
|
||||
void wapp_i16_array_append_capped(I16Array *array, i16 *item);
|
||||
void wapp_i16_array_extend_capped(I16Array *array, const I16Array *other);
|
||||
void wapp_i16_array_clear(I16Array *array);
|
||||
void wapp_i16_array_copy_capped(const I16Array *src, I16Array *dst);
|
||||
I16Array *wapp_i16_array_append_alloc(const Allocator *allocator, I16Array *array, i16 *item);
|
||||
I16Array *wapp_i16_array_extend_alloc(const Allocator *allocator, I16Array *array, const I16Array *other);
|
||||
I16Array *wapp_i16_array_copy_alloc(const Allocator *allocator, const I16Array *src, I16Array *dst);
|
||||
i16 *_i16_array_pop(I16Array *array);
|
||||
i32 *wapp_i32_array_get(const I32Array *array, u64 index);
|
||||
void wapp_i32_array_set(I32Array *array, u64 index, i32 *item);
|
||||
void wapp_i32_array_append_capped(I32Array *array, i32 *item);
|
||||
void wapp_i32_array_extend_capped(I32Array *array, const I32Array *other);
|
||||
void wapp_i32_array_clear(I32Array *array);
|
||||
void wapp_i32_array_copy_capped(const I32Array *src, I32Array *dst);
|
||||
I32Array *wapp_i32_array_append_alloc(const Allocator *allocator, I32Array *array, i32 *item);
|
||||
I32Array *wapp_i32_array_extend_alloc(const Allocator *allocator, I32Array *array, const I32Array *other);
|
||||
I32Array *wapp_i32_array_copy_alloc(const Allocator *allocator, const I32Array *src, I32Array *dst);
|
||||
i32 *_i32_array_pop(I32Array *array);
|
||||
i64 *wapp_i64_array_get(const I64Array *array, u64 index);
|
||||
void wapp_i64_array_set(I64Array *array, u64 index, i64 *item);
|
||||
void wapp_i64_array_append_capped(I64Array *array, i64 *item);
|
||||
void wapp_i64_array_extend_capped(I64Array *array, const I64Array *other);
|
||||
void wapp_i64_array_clear(I64Array *array);
|
||||
void wapp_i64_array_copy_capped(const I64Array *src, I64Array *dst);
|
||||
I64Array *wapp_i64_array_append_alloc(const Allocator *allocator, I64Array *array, i64 *item);
|
||||
I64Array *wapp_i64_array_extend_alloc(const Allocator *allocator, I64Array *array, const I64Array *other);
|
||||
I64Array *wapp_i64_array_copy_alloc(const Allocator *allocator, const I64Array *src, I64Array *dst);
|
||||
i64 *_i64_array_pop(I64Array *array);
|
||||
u8 *wapp_u8_array_get(const U8Array *array, u64 index);
|
||||
void wapp_u8_array_set(U8Array *array, u64 index, u8 *item);
|
||||
void wapp_u8_array_append_capped(U8Array *array, u8 *item);
|
||||
void wapp_u8_array_extend_capped(U8Array *array, const U8Array *other);
|
||||
void wapp_u8_array_clear(U8Array *array);
|
||||
void wapp_u8_array_copy_capped(const U8Array *src, U8Array *dst);
|
||||
U8Array *wapp_u8_array_append_alloc(const Allocator *allocator, U8Array *array, u8 *item);
|
||||
U8Array *wapp_u8_array_extend_alloc(const Allocator *allocator, U8Array *array, const U8Array *other);
|
||||
U8Array *wapp_u8_array_copy_alloc(const Allocator *allocator, const U8Array *src, U8Array *dst);
|
||||
u8 *_u8_array_pop(U8Array *array);
|
||||
u16 *wapp_u16_array_get(const U16Array *array, u64 index);
|
||||
void wapp_u16_array_set(U16Array *array, u64 index, u16 *item);
|
||||
void wapp_u16_array_append_capped(U16Array *array, u16 *item);
|
||||
void wapp_u16_array_extend_capped(U16Array *array, const U16Array *other);
|
||||
void wapp_u16_array_clear(U16Array *array);
|
||||
void wapp_u16_array_copy_capped(const U16Array *src, U16Array *dst);
|
||||
U16Array *wapp_u16_array_append_alloc(const Allocator *allocator, U16Array *array, u16 *item);
|
||||
U16Array *wapp_u16_array_extend_alloc(const Allocator *allocator, U16Array *array, const U16Array *other);
|
||||
U16Array *wapp_u16_array_copy_alloc(const Allocator *allocator, const U16Array *src, U16Array *dst);
|
||||
u16 *_u16_array_pop(U16Array *array);
|
||||
u32 *wapp_u32_array_get(const U32Array *array, u64 index);
|
||||
void wapp_u32_array_set(U32Array *array, u64 index, u32 *item);
|
||||
void wapp_u32_array_append_capped(U32Array *array, u32 *item);
|
||||
void wapp_u32_array_extend_capped(U32Array *array, const U32Array *other);
|
||||
void wapp_u32_array_clear(U32Array *array);
|
||||
void wapp_u32_array_copy_capped(const U32Array *src, U32Array *dst);
|
||||
U32Array *wapp_u32_array_append_alloc(const Allocator *allocator, U32Array *array, u32 *item);
|
||||
U32Array *wapp_u32_array_extend_alloc(const Allocator *allocator, U32Array *array, const U32Array *other);
|
||||
U32Array *wapp_u32_array_copy_alloc(const Allocator *allocator, const U32Array *src, U32Array *dst);
|
||||
u32 *_u32_array_pop(U32Array *array);
|
||||
u64 *wapp_u64_array_get(const U64Array *array, u64 index);
|
||||
void wapp_u64_array_set(U64Array *array, u64 index, u64 *item);
|
||||
void wapp_u64_array_append_capped(U64Array *array, u64 *item);
|
||||
void wapp_u64_array_extend_capped(U64Array *array, const U64Array *other);
|
||||
void wapp_u64_array_clear(U64Array *array);
|
||||
void wapp_u64_array_copy_capped(const U64Array *src, U64Array *dst);
|
||||
U64Array *wapp_u64_array_append_alloc(const Allocator *allocator, U64Array *array, u64 *item);
|
||||
U64Array *wapp_u64_array_extend_alloc(const Allocator *allocator, U64Array *array, const U64Array *other);
|
||||
U64Array *wapp_u64_array_copy_alloc(const Allocator *allocator, const U64Array *src, U64Array *dst);
|
||||
u64 *_u64_array_pop(U64Array *array);
|
||||
f32 *wapp_f32_array_get(const F32Array *array, u64 index);
|
||||
void wapp_f32_array_set(F32Array *array, u64 index, f32 *item);
|
||||
void wapp_f32_array_append_capped(F32Array *array, f32 *item);
|
||||
void wapp_f32_array_extend_capped(F32Array *array, const F32Array *other);
|
||||
void wapp_f32_array_clear(F32Array *array);
|
||||
void wapp_f32_array_copy_capped(const F32Array *src, F32Array *dst);
|
||||
F32Array *wapp_f32_array_append_alloc(const Allocator *allocator, F32Array *array, f32 *item);
|
||||
F32Array *wapp_f32_array_extend_alloc(const Allocator *allocator, F32Array *array, const F32Array *other);
|
||||
F32Array *wapp_f32_array_copy_alloc(const Allocator *allocator, const F32Array *src, F32Array *dst);
|
||||
f32 *_f32_array_pop(F32Array *array);
|
||||
f64 *wapp_f64_array_get(const F64Array *array, u64 index);
|
||||
void wapp_f64_array_set(F64Array *array, u64 index, f64 *item);
|
||||
void wapp_f64_array_append_capped(F64Array *array, f64 *item);
|
||||
void wapp_f64_array_extend_capped(F64Array *array, const F64Array *other);
|
||||
void wapp_f64_array_clear(F64Array *array);
|
||||
void wapp_f64_array_copy_capped(const F64Array *src, F64Array *dst);
|
||||
F64Array *wapp_f64_array_append_alloc(const Allocator *allocator, F64Array *array, f64 *item);
|
||||
F64Array *wapp_f64_array_extend_alloc(const Allocator *allocator, F64Array *array, const F64Array *other);
|
||||
F64Array *wapp_f64_array_copy_alloc(const Allocator *allocator, const F64Array *src, F64Array *dst);
|
||||
f64 *_f64_array_pop(F64Array *array);
|
||||
f128 *wapp_f128_array_get(const F128Array *array, u64 index);
|
||||
void wapp_f128_array_set(F128Array *array, u64 index, f128 *item);
|
||||
void wapp_f128_array_append_capped(F128Array *array, f128 *item);
|
||||
void wapp_f128_array_extend_capped(F128Array *array, const F128Array *other);
|
||||
void wapp_f128_array_clear(F128Array *array);
|
||||
void wapp_f128_array_copy_capped(const F128Array *src, F128Array *dst);
|
||||
F128Array *wapp_f128_array_append_alloc(const Allocator *allocator, F128Array *array, f128 *item);
|
||||
F128Array *wapp_f128_array_extend_alloc(const Allocator *allocator, F128Array *array, const F128Array *other);
|
||||
F128Array *wapp_f128_array_copy_alloc(const Allocator *allocator, const F128Array *src, F128Array *dst);
|
||||
f128 *_f128_array_pop(F128Array *array);
|
||||
iptr *wapp_iptr_array_get(const IptrArray *array, u64 index);
|
||||
void wapp_iptr_array_set(IptrArray *array, u64 index, iptr *item);
|
||||
void wapp_iptr_array_append_capped(IptrArray *array, iptr *item);
|
||||
void wapp_iptr_array_extend_capped(IptrArray *array, const IptrArray *other);
|
||||
void wapp_iptr_array_clear(IptrArray *array);
|
||||
void wapp_iptr_array_copy_capped(const IptrArray *src, IptrArray *dst);
|
||||
IptrArray *wapp_iptr_array_append_alloc(const Allocator *allocator, IptrArray *array, iptr *item);
|
||||
IptrArray *wapp_iptr_array_extend_alloc(const Allocator *allocator, IptrArray *array, const IptrArray *other);
|
||||
IptrArray *wapp_iptr_array_copy_alloc(const Allocator *allocator, const IptrArray *src, IptrArray *dst);
|
||||
iptr *_iptr_array_pop(IptrArray *array);
|
||||
uptr *wapp_uptr_array_get(const UptrArray *array, u64 index);
|
||||
void wapp_uptr_array_set(UptrArray *array, u64 index, uptr *item);
|
||||
void wapp_uptr_array_append_capped(UptrArray *array, uptr *item);
|
||||
void wapp_uptr_array_extend_capped(UptrArray *array, const UptrArray *other);
|
||||
void wapp_uptr_array_clear(UptrArray *array);
|
||||
void wapp_uptr_array_copy_capped(const UptrArray *src, UptrArray *dst);
|
||||
UptrArray *wapp_uptr_array_append_alloc(const Allocator *allocator, UptrArray *array, uptr *item);
|
||||
UptrArray *wapp_uptr_array_extend_alloc(const Allocator *allocator, UptrArray *array, const UptrArray *other);
|
||||
UptrArray *wapp_uptr_array_copy_alloc(const Allocator *allocator, const UptrArray *src, UptrArray *dst);
|
||||
uptr *_uptr_array_pop(UptrArray *array);
|
||||
GenericArray *_array_alloc_capacity(const Allocator *allocator, u64 capacity, u64 item_size);
|
||||
|
||||
#ifdef WAPP_PLATFORM_CPP
|
||||
END_C_LINKAGE
|
||||
#endif // !WAPP_PLATFORM_CPP
|
||||
|
||||
#endif // !ARRAY_H
|
3811
src/primitives/dbl_list/dbl_list.c
Normal file
3811
src/primitives/dbl_list/dbl_list.c
Normal file
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user