Compare commits
80 Commits
d79e7615a1
...
v1.0.0
| Author | SHA1 | Date | |
|---|---|---|---|
| 95deda1f59 | |||
| 3f3d1e1e5d | |||
| 877b8e9a04 | |||
| 4ce59f537c | |||
| 7d13bde13b | |||
| 3aa792a620 | |||
| c0b667847c | |||
| ce2956f072 | |||
| a1182016af | |||
| 59423e294a | |||
| ef5c9376a9 | |||
| eeed101228 | |||
| 6b88d7e3fe | |||
| 58dab46902 | |||
| 269ee5d9ab | |||
| 610df6869f | |||
| 1cdb08a81a | |||
| 8d9ef89329 | |||
|
|
3d3452f523 | ||
|
|
8e41b627bc | ||
|
|
7a54c28c0f | ||
|
|
bd659e64fc | ||
|
|
21ac756fad | ||
|
|
243f04c0ca | ||
| 4cc8cb3d25 | |||
| a9f5b9c3c6 | |||
| 9af9cedd51 | |||
| 1e536cc3ba | |||
| e6f31e4f7b | |||
| 6cd3c6f596 | |||
| 5a504c6791 | |||
| a4492cf8e8 | |||
| ce76ac1e7c | |||
| cff418b9e9 | |||
| b88cb71aa8 | |||
| 8efcf14462 | |||
| f383fbb43e | |||
| 24069529c3 | |||
| d2b4ec2052 | |||
| 0a761eef05 | |||
| 821406315e | |||
| 8adbc1f841 | |||
| 1f3df20b7d | |||
| 458046a5d0 | |||
| 6d4a72aff9 | |||
| 326265722e | |||
| 83b879a180 | |||
| b372447a46 | |||
| fac9cb57eb | |||
| abad2fa02a | |||
| 576699996f | |||
| c2ca99cac4 | |||
| a07f05d1a3 | |||
| ebf16c6ba3 | |||
| 91138f9239 | |||
| ae8cb2e473 | |||
| f5c2ed89a4 | |||
| 989a5f60c4 | |||
| 659a3e457c | |||
| c2a156e256 | |||
| f3ee1ee468 | |||
| 7be1b42107 | |||
| 41cac2ef7f | |||
| 24716505be | |||
| 7e21961943 | |||
| 6f27d5ea91 | |||
| 54691a8ede | |||
| ab91bb2c9e | |||
| 52303c81ae | |||
| 2372ae6675 | |||
| ad2de98093 | |||
| aa6ef1ec2c | |||
| 5e939a7158 | |||
| 1cbb148a1f | |||
| a065dfb573 | |||
| 3904b3a1ee | |||
| d15022603f | |||
| debf6ed8eb | |||
| 6c5352e9de | |||
| 4ea30f0762 |
81
.gitea/workflows/release.yml
Normal file
81
.gitea/workflows/release.yml
Normal file
@@ -0,0 +1,81 @@
|
|||||||
|
name: Release
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- main # or your default branch
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
release:
|
||||||
|
runs-on: self-hosted
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Checkout repository
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
fetch-depth: 0 # fetch full history
|
||||||
|
tags: true # fetch all tags
|
||||||
|
|
||||||
|
- name: Check/Create Tag
|
||||||
|
id: tag
|
||||||
|
run: |
|
||||||
|
VERSION=$(cat VERSION | tr -d '[:space:]') # read version and trim whitespace
|
||||||
|
echo "Version: $VERSION"
|
||||||
|
|
||||||
|
if git rev-parse "v$VERSION" >/dev/null 2>&1; then
|
||||||
|
echo "Tag v$VERSION already exists. Skipping release."
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Tag does not exist → create it
|
||||||
|
echo "Creating tag v$VERSION"
|
||||||
|
git tag "v$VERSION"
|
||||||
|
git push origin "v$VERSION"
|
||||||
|
|
||||||
|
echo "version=$VERSION" >> $GITHUB_OUTPUT
|
||||||
|
|
||||||
|
- name: Build Artifacts
|
||||||
|
if: steps.tag.outputs.version
|
||||||
|
run: |
|
||||||
|
chmod +x ./package
|
||||||
|
./package
|
||||||
|
ls -l dist/
|
||||||
|
|
||||||
|
- name: Create Release
|
||||||
|
if: steps.tag.outputs.version
|
||||||
|
id: create_release
|
||||||
|
run: |
|
||||||
|
VERSION="${{ steps.tag.outputs.version }}"
|
||||||
|
RESPONSE=$(curl -s -X POST \
|
||||||
|
-H "Authorization: token ${{ secrets.GITEA_TOKEN }}" \
|
||||||
|
-H "Content-Type: application/json" \
|
||||||
|
"https://git.thewizardapprentice.com/api/v1/repos/${{ gitea.repository }}/releases" \
|
||||||
|
-d '{
|
||||||
|
"tag_name": "v'"$VERSION"'",
|
||||||
|
"name": "wapp-v'"$VERSION"'",
|
||||||
|
"body": "Automated release for wapp-v'"$VERSION"'",
|
||||||
|
"draft": false,
|
||||||
|
"prerelease": false
|
||||||
|
}')
|
||||||
|
|
||||||
|
echo "$RESPONSE"
|
||||||
|
RELEASE_ID=$(echo $RESPONSE | jq -r '.id')
|
||||||
|
echo "release_id=$RELEASE_ID" >> $GITHUB_OUTPUT
|
||||||
|
|
||||||
|
- name: Upload Artifacts
|
||||||
|
if: steps.tag.outputs.version
|
||||||
|
run: |
|
||||||
|
RELEASE_ID="${{ steps.create_release.outputs.release_id }}"
|
||||||
|
for FILE in dist/*; do
|
||||||
|
FILENAME=$(basename "$FILE")
|
||||||
|
echo "Uploading $FILENAME"
|
||||||
|
curl -X POST \
|
||||||
|
-H "Authorization: token ${{ secrets.GITEA_TOKEN }}" \
|
||||||
|
-H "Content-Type: application/octet-stream" \
|
||||||
|
--data-binary @"$FILE" \
|
||||||
|
"https://git.thewizardapprentice.com/api/v1/repos/${{ gitea.repository }}/releases/$RELEASE_ID/assets?name=$FILENAME"
|
||||||
|
done
|
||||||
|
|
||||||
|
- name: Cleanup
|
||||||
|
if: steps.tag.outputs.version
|
||||||
|
run: rm -rf dist/*
|
||||||
27
Makefile
27
Makefile
@@ -1,4 +1,4 @@
|
|||||||
.PHONY: help full base os prng testing uuid all clean builddir build-test run-test codegen install build-lib ccodegen
|
.PHONY: help full base os prng testing uuid all clean builddir build-test run-test install build-lib
|
||||||
|
|
||||||
# External variables
|
# External variables
|
||||||
CC = clang
|
CC = clang
|
||||||
@@ -7,7 +7,6 @@ AR = ar
|
|||||||
BUILD_TYPE = Debug
|
BUILD_TYPE = Debug
|
||||||
BUILD_DIR = libwapp-build/$(PLATFORM)-$(BUILD_TYPE)
|
BUILD_DIR = libwapp-build/$(PLATFORM)-$(BUILD_TYPE)
|
||||||
INSTALL_PREFIX = dist
|
INSTALL_PREFIX = dist
|
||||||
CODEGEN_INPUT = ""
|
|
||||||
RUNTIME_ASSERT = true
|
RUNTIME_ASSERT = true
|
||||||
|
|
||||||
# Internal variables
|
# Internal variables
|
||||||
@@ -22,13 +21,14 @@ override TEST_INCLUDE := -Isrc $(shell find tests -type d | xargs -I{} ech
|
|||||||
override TEST_SRC := $(shell find tests -type f -name "*.c" | xargs -I{} echo -n "{} ")
|
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_C_SRC := src/wapp.c $(TEST_SRC)
|
||||||
override TEST_CXX_SRC := $(shell find tests -type f -name "*.cc" | xargs -I{} echo -n "{} ")
|
override TEST_CXX_SRC := $(shell find tests -type f -name "*.cc" | xargs -I{} echo -n "{} ")
|
||||||
override LIB_NAME := wapp
|
override LIB_BASENAME := wapp
|
||||||
override OBJ_OUT := $(BUILD_DIR)/$(LIB_NAME).o
|
override OBJ_OUT := $(BUILD_DIR)/$(LIB_BASENAME).o
|
||||||
override LIB_OUT := $(BUILD_DIR)/lib$(LIB_NAME).a
|
override LIB_STATIC_NAME := lib$(LIB_BASENAME).a
|
||||||
|
override LIB_OUT := $(BUILD_DIR)/$(LIB_STATIC_NAME)
|
||||||
override TEST_C_OUT := $(BUILD_DIR)/wapptest
|
override TEST_C_OUT := $(BUILD_DIR)/wapptest
|
||||||
override TEST_CXX_OUT := $(BUILD_DIR)/wapptestcc
|
override TEST_CXX_OUT := $(BUILD_DIR)/wapptestcc
|
||||||
override ABS_INSTALL_PREFIX := $(shell mkdir -p $(INSTALL_PREFIX) && realpath $(INSTALL_PREFIX))
|
override ABS_INSTALL_PREFIX := $(shell mkdir -p $(INSTALL_PREFIX) && realpath $(INSTALL_PREFIX))
|
||||||
override INCLUDE_INSTALL := $(ABS_INSTALL_PREFIX)/include/$(LIB_NAME)
|
override INCLUDE_INSTALL := $(ABS_INSTALL_PREFIX)/include/$(LIB_BASENAME)
|
||||||
override LIB_INSTALL := $(ABS_INSTALL_PREFIX)/lib
|
override LIB_INSTALL := $(ABS_INSTALL_PREFIX)/lib
|
||||||
override HEADER_INSTALL_CMD := scripts/header_install.sh
|
override HEADER_INSTALL_CMD := scripts/header_install.sh
|
||||||
|
|
||||||
@@ -46,7 +46,7 @@ endif
|
|||||||
|
|
||||||
# Disable runtime asserts
|
# Disable runtime asserts
|
||||||
ifeq ($(RUNTIME_ASSERT), false)
|
ifeq ($(RUNTIME_ASSERT), false)
|
||||||
override BUILD_FLAGS += WAPP_NO_RUNTIME_ASSERT
|
override BUILD_FLAGS += -DWAPP_NO_RUNTIME_ASSERT
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifeq ($(CC),gcc)
|
ifeq ($(CC),gcc)
|
||||||
@@ -95,7 +95,7 @@ ifeq ($(KERNEL), Darwin)
|
|||||||
ECHO_E = echo
|
ECHO_E = echo
|
||||||
endif
|
endif
|
||||||
|
|
||||||
all: clean builddir codegen run-c-test full run-cc-test
|
all: clean builddir run-c-test full run-cc-test
|
||||||
|
|
||||||
help:
|
help:
|
||||||
@$(ECHO_E) "$(BOLD)$(BLUE)Available build variables:$(RESET)"
|
@$(ECHO_E) "$(BOLD)$(BLUE)Available build variables:$(RESET)"
|
||||||
@@ -105,7 +105,6 @@ help:
|
|||||||
@$(ECHO_E) " $(GREEN)BUILD_TYPE$(RESET) Build type $(MAGENTA)[Debug | RelWithDebInfo | Release] $(YELLOW)(Default: Debug)$(RESET)."
|
@$(ECHO_E) " $(GREEN)BUILD_TYPE$(RESET) Build type $(MAGENTA)[Debug | RelWithDebInfo | Release] $(YELLOW)(Default: Debug)$(RESET)."
|
||||||
@$(ECHO_E) " $(GREEN)BUILD_DIR$(RESET) Directory where build files will be written."
|
@$(ECHO_E) " $(GREEN)BUILD_DIR$(RESET) Directory where build files will be written."
|
||||||
@$(ECHO_E) " $(GREEN)INSTALL_PREFIX$(RESET) Prefix where library and include files will be installed."
|
@$(ECHO_E) " $(GREEN)INSTALL_PREFIX$(RESET) Prefix where library and include files will be installed."
|
||||||
@$(ECHO_E) " $(GREEN)CODEGEN_INPUT$(RESET) Input file for code generation (See $(CYAN)codegen_custom_data_example.json$(RESET) for an example)."
|
|
||||||
@$(ECHO_E) " $(GREEN)RUNTIME_ASSERT$(RESET) Whether runtime asserts are enabled $(MAGENTA)[true | false] $(YELLOW)(Default: true)$(RESET)."
|
@$(ECHO_E) " $(GREEN)RUNTIME_ASSERT$(RESET) Whether runtime asserts are enabled $(MAGENTA)[true | false] $(YELLOW)(Default: true)$(RESET)."
|
||||||
@$(ECHO_E) " $(GREEN)$(RESET) $(BOLD)$(BG_RED)DISCLAIMER:$(RESET) Using this flag is not recommended as it disables safety checks"
|
@$(ECHO_E) " $(GREEN)$(RESET) $(BOLD)$(BG_RED)DISCLAIMER:$(RESET) Using this flag is not recommended as it disables safety checks"
|
||||||
@$(ECHO_E) " $(GREEN)$(RESET) potentially leading to Undefined Behaviour."
|
@$(ECHO_E) " $(GREEN)$(RESET) potentially leading to Undefined Behaviour."
|
||||||
@@ -147,6 +146,8 @@ uuid: install
|
|||||||
|
|
||||||
clean:
|
clean:
|
||||||
@rm -rf "$(BUILD_DIR)"
|
@rm -rf "$(BUILD_DIR)"
|
||||||
|
@rm -rf "$(INCLUDE_INSTALL)"
|
||||||
|
@rm -f "$(LIB_INSTALL)/$(LIB_STATIC_NAME)"
|
||||||
|
|
||||||
builddir:
|
builddir:
|
||||||
@mkdir -p "$(BUILD_DIR)"
|
@mkdir -p "$(BUILD_DIR)"
|
||||||
@@ -167,10 +168,7 @@ run-cc-test: build-cc-test
|
|||||||
@export LD_LIBRARY_PATH=$$LD_LIBRARY_PATH:"$(BUILD_DIR)" && "$(TEST_CXX_OUT)"
|
@export LD_LIBRARY_PATH=$$LD_LIBRARY_PATH:"$(BUILD_DIR)" && "$(TEST_CXX_OUT)"
|
||||||
@rm "$(TEST_CXX_OUT)"
|
@rm "$(TEST_CXX_OUT)"
|
||||||
|
|
||||||
codegen:
|
install: build-lib
|
||||||
python3 -m codegen -f $(CODEGEN_INPUT)
|
|
||||||
|
|
||||||
install: codegen build-lib
|
|
||||||
@mkdir -p "$(LIB_INSTALL)"
|
@mkdir -p "$(LIB_INSTALL)"
|
||||||
@cp -v "$(LIB_OUT)" "$(LIB_INSTALL)"
|
@cp -v "$(LIB_OUT)" "$(LIB_INSTALL)"
|
||||||
@mkdir -p "$(INCLUDE_INSTALL)"
|
@mkdir -p "$(INCLUDE_INSTALL)"
|
||||||
@@ -180,6 +178,3 @@ build-lib: builddir
|
|||||||
$(CC) -c $(CSTD) $(CFLAGS) $(BUILD_FLAGS) $(LIBFLAGS) $(LIB_SRC) -o "$(OBJ_OUT)"
|
$(CC) -c $(CSTD) $(CFLAGS) $(BUILD_FLAGS) $(LIBFLAGS) $(LIB_SRC) -o "$(OBJ_OUT)"
|
||||||
$(AR) r "$(LIB_OUT)" "$(OBJ_OUT)"
|
$(AR) r "$(LIB_OUT)" "$(OBJ_OUT)"
|
||||||
@rm "$(OBJ_OUT)"
|
@rm "$(OBJ_OUT)"
|
||||||
|
|
||||||
ccodegen:
|
|
||||||
$(CC) $(CSTD) $(CFLAGS) $(BUILD_FLAGS) $(LIBFLAGS) -Isrc/os src/os/wapp_os.c ccodegen/*.c -o ccgen
|
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
# Wizard Apprentice Standard Library
|
# Wizard Apprentice Standard Library
|
||||||
|
|
||||||
A base layer for C/C++ projects
|
A group of utilities for C/C++ projects
|
||||||
|
|||||||
@@ -52,9 +52,6 @@ mkdir -p $ObjDir > $null
|
|||||||
mkdir -p $OutDir > $null
|
mkdir -p $OutDir > $null
|
||||||
mkdir -p $TestsDir > $null
|
mkdir -p $TestsDir > $null
|
||||||
|
|
||||||
# Run code generation
|
|
||||||
Invoke-Expression "python -m codegen"
|
|
||||||
|
|
||||||
# Build and run C tests
|
# Build and run C tests
|
||||||
Invoke-Expression "$Compiler $GeneralFlags $CStd $IncludeDirs $TestIncludeDirs $SrcFiles $TestCSrcFiles $TestCOutputFlags" -ErrorAction Stop
|
Invoke-Expression "$Compiler $GeneralFlags $CStd $IncludeDirs $TestIncludeDirs $SrcFiles $TestCSrcFiles $TestCOutputFlags" -ErrorAction Stop
|
||||||
Invoke-Expression "$TestsDir/$TestCOutputBasename.exe"
|
Invoke-Expression "$TestsDir/$TestCOutputBasename.exe"
|
||||||
|
|||||||
@@ -1,522 +0,0 @@
|
|||||||
// 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 _wapp_intern = wapp_str8_lit_ro("wapp_intern ");
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
b8 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;
|
|
||||||
}
|
|
||||||
@@ -1,280 +0,0 @@
|
|||||||
// 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;
|
|
||||||
b8 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;
|
|
||||||
b8 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;
|
|
||||||
b8 is_local;
|
|
||||||
b8 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);
|
|
||||||
b8 cheaderinclude_to_string(Str8 *dst, const CHeaderInclude *cheaderinclude);
|
|
||||||
|
|
||||||
#endif // !DATATYPES_H
|
|
||||||
1526
ccodegen/dbl_list.c
1526
ccodegen/dbl_list.c
File diff suppressed because it is too large
Load Diff
@@ -1,222 +0,0 @@
|
|||||||
// 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
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
// 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;
|
|
||||||
}
|
|
||||||
@@ -1,84 +0,0 @@
|
|||||||
// vim:fileencoding=utf-8:foldmethod=marker
|
|
||||||
|
|
||||||
#ifndef TYPE_ENUMS_H
|
|
||||||
#define TYPE_ENUMS_H
|
|
||||||
|
|
||||||
#include "wapp_core.h"
|
|
||||||
|
|
||||||
typedef enum {
|
|
||||||
CTYPE_VOID,
|
|
||||||
CTYPE_B8,
|
|
||||||
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;
|
|
||||||
wapp_intern Str8RO ctypes[COUNT_CTYPE] = {
|
|
||||||
[CTYPE_VOID] = wapp_str8_lit_ro("void"),
|
|
||||||
[CTYPE_B8] = wapp_str8_lit_ro("b8"),
|
|
||||||
[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;
|
|
||||||
wapp_intern Str8RO cqualifiers[COUNT_CQUALIFIER] = {
|
|
||||||
[CQUALIFIER_NONE] = wapp_str8_lit_ro(""),
|
|
||||||
[CQUALIFIER_CONST] = wapp_str8_lit_ro("const "),
|
|
||||||
[CQUALIFIER_EXTERNAL] = wapp_str8_lit_ro("wapp_extern "),
|
|
||||||
[CQUALIFIER_INTERNAL] = wapp_str8_lit_ro("wapp_intern "),
|
|
||||||
[CQUALIFIER_PERSISTENT] = wapp_str8_lit_ro("wapp_persist "),
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
typedef enum {
|
|
||||||
CPOINTERTYPE_NONE,
|
|
||||||
CPOINTERTYPE_SINGLE,
|
|
||||||
CPOINTERTYPE_DOUBLE,
|
|
||||||
|
|
||||||
COUNT_CPOINTERTYPE,
|
|
||||||
} CPointerType;
|
|
||||||
wapp_intern 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
|
|
||||||
@@ -1,47 +0,0 @@
|
|||||||
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
|
|
||||||
from codegen.dbl_list.make_dbl_list import DblListData, make_dbl_list
|
|
||||||
|
|
||||||
|
|
||||||
def main(types_file: Path | None):
|
|
||||||
dbl_list_datatypes: Dict[CDataType, DblListData] = {}
|
|
||||||
|
|
||||||
if types_file is not None and types_file.is_file() and "json" in types_file.suffix.lower():
|
|
||||||
with types_file.open("r") as infile:
|
|
||||||
datatypes = json.load(infile)
|
|
||||||
dbl_list_data = datatypes.get(DBL_LIST_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()}
|
|
||||||
|
|
||||||
make_dbl_list(dbl_list_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()
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
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)
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
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"
|
|
||||||
@@ -1,503 +0,0 @@
|
|||||||
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 = "b8"
|
|
||||||
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 = "wapp_extern "
|
|
||||||
INTERNAL = "wapp_intern "
|
|
||||||
PERSISTENT = "wapp_persist "
|
|
||||||
|
|
||||||
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
|
|
||||||
@@ -1,339 +0,0 @@
|
|||||||
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 / "base" / "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)
|
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
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);
|
|
||||||
}}
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
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;
|
|
||||||
@@ -1,26 +0,0 @@
|
|||||||
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 +0,0 @@
|
|||||||
(({NodeType}){{.item = ITEM_PTR}})
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
{NodeType}{{ITEM_PTR, nullptr, nullptr}}
|
|
||||||
@@ -1,22 +0,0 @@
|
|||||||
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;
|
|
||||||
@@ -1,22 +0,0 @@
|
|||||||
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;
|
|
||||||
@@ -1,18 +0,0 @@
|
|||||||
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;
|
|
||||||
@@ -1,18 +0,0 @@
|
|||||||
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;
|
|
||||||
@@ -1,26 +0,0 @@
|
|||||||
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;
|
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
{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;
|
|
||||||
@@ -1,18 +0,0 @@
|
|||||||
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)))
|
|
||||||
@@ -1,16 +0,0 @@
|
|||||||
{
|
|
||||||
"dbl_list_data": {
|
|
||||||
"CustomType": {
|
|
||||||
"node_typename": "CustomTypeNode",
|
|
||||||
"list_typename": "CustomTypeList",
|
|
||||||
"hdr_decl_types": [
|
|
||||||
{
|
|
||||||
"name": "custom_type",
|
|
||||||
"cargs": [],
|
|
||||||
"typedef_name": "CustomType"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"src_decl_types": []
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
11
package
Executable file
11
package
Executable file
@@ -0,0 +1,11 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
cp -r src wapp
|
||||||
|
|
||||||
|
mkdir -p dist
|
||||||
|
|
||||||
|
ARCHIVE_NAME="wapp-v$(cat VERSION)"
|
||||||
|
tar -czvf dist/$ARCHIVE_NAME.tar.gz wapp
|
||||||
|
zip -r dist/$ARCHIVE_NAME.zip wapp
|
||||||
|
|
||||||
|
rm -rf wapp
|
||||||
@@ -7,169 +7,260 @@
|
|||||||
#include "../../common/aliases/aliases.h"
|
#include "../../common/aliases/aliases.h"
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
|
|
||||||
#define _offset_pointer(PTR, OFFSET) ((void *)((uptr)(PTR) + (OFFSET)))
|
#define _array_header(ARRAY) (ArrayHeader *)(wapp_pointer_offset(ARRAY, (i64)sizeof(ArrayHeader) * -1))
|
||||||
|
|
||||||
void *_array_get(Array *array, u64 index, u64 item_size) {
|
wapp_persist inline void _array_validate(const GenericArray array, u64 item_size);
|
||||||
wapp_runtime_assert(array != NULL, "`array` should not be NULL");
|
|
||||||
wapp_runtime_assert(WAPP_ARRAY_MAGIC == array->magic, "`array` is not a valid wapp array");
|
|
||||||
wapp_runtime_assert(item_size == array->item_size, "Invalid item type provided");
|
|
||||||
wapp_runtime_assert(index < array->count, "`index` is out of bounds");
|
|
||||||
|
|
||||||
return _offset_pointer(array->items, array->item_size * index);
|
u64 _array_count(GenericArray array) {
|
||||||
|
wapp_debug_assert(array != NULL, "`array` should not be NULL");
|
||||||
|
|
||||||
|
ArrayHeader *header = _array_header(array);
|
||||||
|
wapp_runtime_assert(WAPP_ARRAY_MAGIC == header->magic, "`array` is not a valid wapp array");
|
||||||
|
|
||||||
|
return header->count;
|
||||||
}
|
}
|
||||||
|
|
||||||
void _array_set(Array *array, u64 index, void *value, u64 item_size) {
|
u64 _array_capacity(GenericArray array) {
|
||||||
void *item = _array_get(array, index, item_size);
|
wapp_debug_assert(array != NULL, "`array` should not be NULL");
|
||||||
memcpy(item, value, array->item_size);
|
|
||||||
|
ArrayHeader *header = _array_header(array);
|
||||||
|
wapp_runtime_assert(WAPP_ARRAY_MAGIC == header->magic, "`array` is not a valid wapp array");
|
||||||
|
|
||||||
|
return header->capacity;
|
||||||
}
|
}
|
||||||
|
|
||||||
void _array_append_capped(Array *array, void *value, u64 item_size) {
|
u64 _array_item_size(GenericArray array) {
|
||||||
wapp_runtime_assert(array != NULL, "`array` should not be NULL");
|
wapp_debug_assert(array != NULL, "`array` should not be NULL");
|
||||||
wapp_runtime_assert(WAPP_ARRAY_MAGIC == array->magic, "`array` is not a valid wapp array");
|
|
||||||
wapp_runtime_assert(item_size == array->item_size, "Invalid item type provided");
|
|
||||||
|
|
||||||
if (array->count >= array->capacity) { return; }
|
ArrayHeader *header = _array_header(array);
|
||||||
|
wapp_runtime_assert(WAPP_ARRAY_MAGIC == header->magic, "`array` is not a valid wapp array");
|
||||||
|
|
||||||
u64 index = (array->count)++;
|
return header->item_size;
|
||||||
_array_set(array, index, value, item_size);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void _array_extend_capped(Array *dst, const Array *src, u64 item_size) {
|
void _array_set_count(GenericArray array, u64 count) {
|
||||||
wapp_runtime_assert(dst != NULL && src != NULL, "`dst` and `src` should not be NULL");
|
wapp_debug_assert(array != NULL, "`array` should not be NULL");
|
||||||
wapp_runtime_assert(WAPP_ARRAY_MAGIC == dst->magic, "`dst` is not a valid wapp array");
|
|
||||||
wapp_runtime_assert(WAPP_ARRAY_MAGIC == src->magic, "`src` is not a valid wapp array");
|
|
||||||
wapp_runtime_assert(item_size == dst->item_size && item_size == src->item_size, "Invalid item type provided");
|
|
||||||
|
|
||||||
u64 remaining_capacity = dst->capacity - dst->count;
|
ArrayHeader *header = _array_header(array);
|
||||||
|
wapp_runtime_assert(WAPP_ARRAY_MAGIC == header->magic, "`array` is not a valid wapp array");
|
||||||
|
|
||||||
u64 copy_count = src->count < remaining_capacity ? src->count : remaining_capacity;
|
header->count = count;
|
||||||
void *dst_ptr = _offset_pointer(dst->items, dst->count * dst->item_size);
|
|
||||||
memcpy(dst_ptr, src->items, copy_count * src->item_size);
|
|
||||||
dst->count += copy_count;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void _array_copy_capped(Array *dst, const Array *src, u64 item_size) {
|
void *_array_get(GenericArray array, u64 index, u64 item_size) {
|
||||||
wapp_runtime_assert(dst != NULL && src != NULL, "`dst` and `src` should not be NULL");
|
wapp_runtime_assert(array != NULL, "`array` should not be NULL");
|
||||||
wapp_runtime_assert(WAPP_ARRAY_MAGIC == dst->magic, "`dst` is not a valid wapp array");
|
_array_validate(array, item_size);
|
||||||
wapp_runtime_assert(WAPP_ARRAY_MAGIC == src->magic, "`src` is not a valid wapp array");
|
|
||||||
wapp_runtime_assert(item_size == dst->item_size && item_size == src->item_size, "Invalid item type provided");
|
|
||||||
|
|
||||||
_array_clear(dst, item_size);
|
ArrayHeader *header = _array_header(array);
|
||||||
u64 copy_count = src->count < dst->capacity ? src->count : dst->capacity;
|
wapp_runtime_assert(index < header->count, "`index` is out of bounds");
|
||||||
memcpy(dst->items, src->items, copy_count * src->item_size);
|
|
||||||
dst->count = copy_count;
|
return wapp_pointer_offset(array, header->item_size * index);
|
||||||
}
|
}
|
||||||
|
|
||||||
Array *_array_append_alloc(const Allocator *allocator, Array *array, void *value, u64 item_size) {
|
void _array_set(GenericArray array, u64 index, void *value, u64 item_size) {
|
||||||
wapp_runtime_assert(allocator != NULL && array != NULL, "`allocator` and `array` should not be NULL");
|
void *item = _array_get(array, index, item_size);
|
||||||
wapp_runtime_assert(WAPP_ARRAY_MAGIC == array->magic, "`array` is not a valid wapp array");
|
|
||||||
wapp_runtime_assert(item_size == array->item_size, "Invalid item type provided");
|
|
||||||
|
|
||||||
Array *output = array;
|
ArrayHeader *header = _array_header(array);
|
||||||
|
memcpy(item, value, header->item_size);
|
||||||
|
}
|
||||||
|
|
||||||
if (array->count >= array->capacity) {
|
void _array_append_capped(GenericArray array, void *value, u64 item_size) {
|
||||||
u64 new_capacity = wapp_misc_utils_u64_round_up_pow2(array->capacity * 2);
|
wapp_runtime_assert(array != NULL, "`array` should not be NULL");
|
||||||
output = (Array *)_array_alloc_capacity(allocator, new_capacity, array->item_size);
|
_array_validate(array, item_size);
|
||||||
if (!output) {
|
|
||||||
output = array;
|
|
||||||
goto RETURN_ARRAY_APPEND_ALLOC;
|
|
||||||
}
|
|
||||||
_array_copy_capped(output, array, item_size);
|
|
||||||
}
|
|
||||||
|
|
||||||
_array_append_capped(output, value, item_size);
|
ArrayHeader *header = _array_header(array);
|
||||||
|
if (header->count >= header->capacity) { return; }
|
||||||
|
|
||||||
|
u64 index = (header->count)++;
|
||||||
|
_array_set(array, index, value, item_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
void _array_extend_capped(GenericArray dst, const GenericArray src, u64 item_size) {
|
||||||
|
wapp_runtime_assert(dst != NULL && src != NULL, "`dst` and `src` should not be NULL");
|
||||||
|
_array_validate(dst, item_size);
|
||||||
|
_array_validate(src, item_size);
|
||||||
|
|
||||||
|
ArrayHeader *src_header = _array_header(src);
|
||||||
|
ArrayHeader *dst_header = _array_header(dst);
|
||||||
|
u64 remaining_capacity = dst_header->capacity - dst_header->count;
|
||||||
|
|
||||||
|
u64 copy_count = src_header->count < remaining_capacity ? src_header->count : remaining_capacity;
|
||||||
|
void *dst_ptr = wapp_pointer_offset(dst, dst_header->count * dst_header->item_size);
|
||||||
|
memcpy(dst_ptr, src, copy_count * src_header->item_size);
|
||||||
|
dst_header->count += copy_count;
|
||||||
|
}
|
||||||
|
|
||||||
|
void _array_copy_capped(GenericArray dst, const GenericArray src, u64 item_size) {
|
||||||
|
wapp_runtime_assert(dst != NULL && src != NULL, "`dst` and `src` should not be NULL");
|
||||||
|
_array_validate(dst, item_size);
|
||||||
|
_array_validate(src, item_size);
|
||||||
|
|
||||||
|
_array_clear(dst, item_size);
|
||||||
|
|
||||||
|
ArrayHeader *src_header = _array_header(src);
|
||||||
|
ArrayHeader *dst_header = _array_header(dst);
|
||||||
|
u64 copy_count = src_header->count < dst_header->capacity ? src_header->count : dst_header->capacity;
|
||||||
|
memcpy((void *)dst, (void *)src, copy_count * src_header->item_size);
|
||||||
|
dst_header->count = copy_count;
|
||||||
|
}
|
||||||
|
|
||||||
|
GenericArray _array_append_alloc(const Allocator *allocator, GenericArray array, void *value,
|
||||||
|
ArrayInitFlags flags, u64 item_size) {
|
||||||
|
wapp_runtime_assert(allocator != NULL && array != NULL, "`allocator` and `array` should not be NULL");
|
||||||
|
_array_validate(array, item_size);
|
||||||
|
|
||||||
|
GenericArray output = array;
|
||||||
|
|
||||||
|
ArrayHeader *header = _array_header(array);
|
||||||
|
if (header->count >= header->capacity) {
|
||||||
|
u64 new_capacity = wapp_misc_utils_u64_round_up_pow2(header->capacity * 2);
|
||||||
|
output = (GenericArray )_array_alloc_capacity(allocator, new_capacity, flags,
|
||||||
|
header->item_size);
|
||||||
|
if (!output) {
|
||||||
|
output = array;
|
||||||
|
goto RETURN_ARRAY_APPEND_ALLOC;
|
||||||
|
}
|
||||||
|
_array_copy_capped(output, array, item_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
_array_append_capped(output, value, item_size);
|
||||||
|
|
||||||
|
if ((flags & ARRAY_INIT_FILLED) == ARRAY_INIT_FILLED) {
|
||||||
|
_array_set_count(output, _array_capacity(output));
|
||||||
|
}
|
||||||
|
|
||||||
RETURN_ARRAY_APPEND_ALLOC:
|
RETURN_ARRAY_APPEND_ALLOC:
|
||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
|
|
||||||
Array *_array_extend_alloc(const Allocator *allocator, Array *dst, const Array *src, u64 item_size) {
|
GenericArray _array_extend_alloc(const Allocator *allocator, GenericArray dst, const GenericArray src,
|
||||||
wapp_runtime_assert(allocator != NULL && dst != NULL && src != NULL, "`allocator`, `dst` and `src` should not be NULL");
|
ArrayInitFlags flags, u64 item_size) {
|
||||||
wapp_runtime_assert(WAPP_ARRAY_MAGIC == dst->magic, "`dst` is not a valid wapp array");
|
wapp_runtime_assert(allocator != NULL && dst != NULL && src != NULL, "`allocator`, `dst` and `src` should not be NULL");
|
||||||
wapp_runtime_assert(WAPP_ARRAY_MAGIC == src->magic, "`src` is not a valid wapp array");
|
_array_validate(dst, item_size);
|
||||||
wapp_runtime_assert(item_size == dst->item_size && item_size == src->item_size, "Invalid item type provided");
|
_array_validate(src, item_size);
|
||||||
|
|
||||||
Array *output = dst;
|
GenericArray output = dst;
|
||||||
|
|
||||||
u64 remaining_capacity = dst->capacity - dst->count;
|
ArrayHeader *src_header = _array_header(src);
|
||||||
if (src->count >= remaining_capacity) {
|
ArrayHeader *dst_header = _array_header(dst);
|
||||||
u64 new_capacity = wapp_misc_utils_u64_round_up_pow2(dst->capacity * 2);
|
u64 remaining_capacity = dst_header->capacity - dst_header->count;
|
||||||
output = (Array *)_array_alloc_capacity(allocator, new_capacity, dst->item_size);
|
if (src_header->count >= remaining_capacity) {
|
||||||
if (!output) {
|
u64 new_capacity = wapp_misc_utils_u64_round_up_pow2(dst_header->capacity * 2);
|
||||||
output = dst;
|
output = (GenericArray )_array_alloc_capacity(allocator, new_capacity,
|
||||||
goto RETURN_ARRAY_EXTEND_ALLOC;
|
flags, dst_header->item_size);
|
||||||
}
|
if (!output) {
|
||||||
_array_copy_capped(output, dst, item_size);
|
output = dst;
|
||||||
}
|
goto RETURN_ARRAY_EXTEND_ALLOC;
|
||||||
|
}
|
||||||
|
_array_copy_capped(output, dst, item_size);
|
||||||
|
}
|
||||||
|
|
||||||
_array_extend_capped(output, src, item_size);
|
_array_extend_capped(output, src, item_size);
|
||||||
|
|
||||||
|
if ((flags & ARRAY_INIT_FILLED) == ARRAY_INIT_FILLED) {
|
||||||
|
_array_set_count(output, _array_capacity(output));
|
||||||
|
}
|
||||||
|
|
||||||
RETURN_ARRAY_EXTEND_ALLOC:
|
RETURN_ARRAY_EXTEND_ALLOC:
|
||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
|
|
||||||
Array *_array_copy_alloc(const Allocator *allocator, Array *dst, const Array *src, u64 item_size) {
|
GenericArray _array_copy_alloc(const Allocator *allocator, GenericArray dst, const GenericArray src,
|
||||||
wapp_runtime_assert(allocator != NULL && dst != NULL && src != NULL, "`allocator`, `dst` and `src` should not be NULL");
|
ArrayInitFlags flags, u64 item_size) {
|
||||||
wapp_runtime_assert(WAPP_ARRAY_MAGIC == dst->magic, "`dst` is not a valid wapp array");
|
wapp_runtime_assert(allocator != NULL && dst != NULL && src != NULL, "`allocator`, `dst` and `src` should not be NULL");
|
||||||
wapp_runtime_assert(WAPP_ARRAY_MAGIC == src->magic, "`src` is not a valid wapp array");
|
_array_validate(dst, item_size);
|
||||||
wapp_runtime_assert(item_size == dst->item_size && item_size == src->item_size, "Invalid item type provided");
|
_array_validate(src, item_size);
|
||||||
|
|
||||||
Array *output = dst;
|
GenericArray output = dst;
|
||||||
|
|
||||||
if (src->count >= dst->capacity) {
|
ArrayHeader *src_header = _array_header(src);
|
||||||
u64 new_capacity = wapp_misc_utils_u64_round_up_pow2(dst->capacity * 2);
|
ArrayHeader *dst_header = _array_header(dst);
|
||||||
output = (Array *)_array_alloc_capacity(allocator, new_capacity, src->item_size);
|
if (src_header->count >= dst_header->capacity) {
|
||||||
if (!output) {
|
u64 new_capacity = wapp_misc_utils_u64_round_up_pow2(dst_header->capacity * 2);
|
||||||
output = dst;
|
output = (GenericArray )_array_alloc_capacity(allocator, new_capacity,
|
||||||
goto RETURN_ARRAY_COPY_ALLOC;
|
flags, src_header->item_size);
|
||||||
}
|
if (!output) {
|
||||||
}
|
output = dst;
|
||||||
|
goto RETURN_ARRAY_COPY_ALLOC;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
_array_copy_capped(output, src, item_size);
|
_array_copy_capped(output, src, item_size);
|
||||||
|
|
||||||
|
if ((flags & ARRAY_INIT_FILLED) == ARRAY_INIT_FILLED) {
|
||||||
|
_array_set_count(output, _array_capacity(output));
|
||||||
|
}
|
||||||
|
|
||||||
RETURN_ARRAY_COPY_ALLOC:
|
RETURN_ARRAY_COPY_ALLOC:
|
||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
|
|
||||||
void *_array_pop(Array *array, u64 item_size) {
|
void *_array_pop(GenericArray array, u64 item_size) {
|
||||||
wapp_runtime_assert(array != NULL, "`array` should not be NULL");
|
wapp_runtime_assert(array != NULL, "`array` should not be NULL");
|
||||||
wapp_runtime_assert(WAPP_ARRAY_MAGIC == array->magic, "`array` is not a valid wapp array");
|
_array_validate(array, item_size);
|
||||||
wapp_runtime_assert(item_size == array->item_size, "Invalid item type provided");
|
|
||||||
|
|
||||||
if (array->count == 0) { return NULL; }
|
ArrayHeader *header = _array_header(array);
|
||||||
|
if (header->count == 0) { return NULL; }
|
||||||
|
|
||||||
u64 index = array->count - 1;
|
u64 index = header->count - 1;
|
||||||
void *out = _array_get(array, index, item_size);
|
void *out = _array_get(array, index, item_size);
|
||||||
--(array->count);
|
--(header->count);
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
void _array_clear(Array *array, u64 item_size) {
|
void _array_clear(GenericArray array, u64 item_size) {
|
||||||
wapp_runtime_assert(array != NULL, "`array` should not be NULL");
|
wapp_runtime_assert(array != NULL, "`array` should not be NULL");
|
||||||
wapp_runtime_assert(WAPP_ARRAY_MAGIC == array->magic, "`array` is not a valid wapp array");
|
_array_validate(array, item_size);
|
||||||
wapp_runtime_assert(item_size == array->item_size, "Invalid item type provided");
|
|
||||||
|
|
||||||
array->count = 0;
|
ArrayHeader *header = _array_header(array);
|
||||||
|
header->count = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
Array *_array_alloc_capacity(const Allocator *allocator, u64 capacity, u64 item_size) {
|
u64 _array_calc_alloc_size(u64 capacity, u64 item_size) {
|
||||||
wapp_runtime_assert(allocator != NULL, "`allocator` should not be NULL");
|
return sizeof(ArrayHeader) + item_size * capacity;
|
||||||
|
}
|
||||||
|
|
||||||
Array *output = NULL;
|
GenericArray _array_alloc_capacity(const Allocator *allocator, u64 capacity, ArrayInitFlags flags,
|
||||||
|
u64 item_size) {
|
||||||
|
wapp_runtime_assert(allocator != NULL, "`allocator` should not be NULL");
|
||||||
|
|
||||||
u64 allocation_size = sizeof(Array) + item_size * capacity;
|
GenericArray output = NULL;
|
||||||
|
|
||||||
output = wapp_mem_allocator_alloc(allocator, allocation_size);
|
u64 allocation_size = _array_calc_alloc_size(capacity, item_size);
|
||||||
if (!output) {
|
void *buffer = wapp_mem_allocator_alloc(allocator, allocation_size);
|
||||||
goto RETURN_ARRAY_ALLOC;
|
if (!buffer) {
|
||||||
}
|
goto RETURN_ARRAY_ALLOC;
|
||||||
|
}
|
||||||
|
|
||||||
output->magic = WAPP_ARRAY_MAGIC;
|
output = _array_from_preallocated_buffer(buffer, allocation_size, flags, item_size);
|
||||||
output->count = 0;
|
|
||||||
output->capacity = capacity;
|
|
||||||
output->item_size = item_size;
|
|
||||||
output->items = (void *)(output + 1);
|
|
||||||
|
|
||||||
RETURN_ARRAY_ALLOC:
|
RETURN_ARRAY_ALLOC:
|
||||||
return output;
|
return output;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
GenericArray _array_from_preallocated_buffer(void *buffer, u64 buffer_size, ArrayInitFlags flags,
|
||||||
|
u64 item_size) {
|
||||||
|
wapp_runtime_assert(buffer != NULL, "`buffer` should not be NULL");
|
||||||
|
|
||||||
|
i64 data_buffer_size = (i64)buffer_size - (i64)(sizeof(ArrayHeader));
|
||||||
|
if (data_buffer_size <= 0) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
u64 item_capacity = (u64)data_buffer_size / item_size;
|
||||||
|
ArrayHeader *header = (ArrayHeader *)buffer;
|
||||||
|
GenericArray output = (u8 *)(header + 1);
|
||||||
|
header->magic = WAPP_ARRAY_MAGIC;
|
||||||
|
header->count = flags & ARRAY_INIT_FILLED ? item_capacity : 0;
|
||||||
|
header->capacity = item_capacity;
|
||||||
|
header->item_size = item_size;
|
||||||
|
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
||||||
|
wapp_persist inline void _array_validate(const GenericArray array, u64 item_size) {
|
||||||
|
ArrayHeader *header = _array_header(array);
|
||||||
|
wapp_runtime_assert(WAPP_ARRAY_MAGIC == header->magic, "`array` is not a valid wapp array");
|
||||||
|
wapp_runtime_assert(item_size == header->item_size, "Invalid item type provided");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,139 +12,202 @@
|
|||||||
BEGIN_C_LINKAGE
|
BEGIN_C_LINKAGE
|
||||||
#endif // !WAPP_PLATFORM_CPP
|
#endif // !WAPP_PLATFORM_CPP
|
||||||
|
|
||||||
#define WAPP_ARRAY_MAGIC (u64)0x57415F415252
|
#define WAPP_ARRAY_MAGIC (u64)0x57415f415252
|
||||||
|
|
||||||
#define _calc_array_count(TYPE, ...) wapp_misc_utils_va_args_count(TYPE, __VA_ARGS__)
|
#define _calc_array_count(TYPE, ...) wapp_misc_utils_va_args_count(TYPE, __VA_ARGS__)
|
||||||
#define _calc_array_capacity(TYPE, ...) wapp_misc_utils_u64_round_up_pow2(_calc_array_count(TYPE, __VA_ARGS__) * 2)
|
#define _calc_array_capacity(TYPE, ...) wapp_misc_utils_u64_round_up_pow2(_calc_array_count(TYPE, __VA_ARGS__) * 2)
|
||||||
|
|
||||||
#define wapp_array_alloc_capacity(ELEM_TYPE, ARRAY_TYPE, ALLOCATOR_PTR, CAPACITY) \
|
typedef struct Str8 Str8;
|
||||||
((ARRAY_TYPE *)_array_alloc_capacity(ALLOCATOR_PTR, CAPACITY, sizeof(ELEM_TYPE)))
|
|
||||||
|
|
||||||
#define WAPP_DEF_ARRAY_TYPE(T, NAME) \
|
// NOTE (Abdelrahman): Typedefs to distinguish arrays from regular pointers
|
||||||
typedef struct { \
|
typedef void *GenericArray;
|
||||||
u64 magic; \
|
typedef void **VoidPtrArray;
|
||||||
u64 count; \
|
typedef c8 *C8Array;
|
||||||
u64 capacity; \
|
typedef c16 *C16Array;
|
||||||
u64 item_size; \
|
typedef c32 *C32Array;
|
||||||
T *items; \
|
typedef u8 *U8Array;
|
||||||
} NAME
|
typedef u16 *U16Array;
|
||||||
|
typedef u32 *U32Array;
|
||||||
|
typedef u64 *U64Array;
|
||||||
|
typedef b8 *B8Array;
|
||||||
|
typedef i8 *I8Array;
|
||||||
|
typedef i16 *I16Array;
|
||||||
|
typedef i32 *I32Array;
|
||||||
|
typedef i64 *I64Array;
|
||||||
|
typedef f32 *F32Array;
|
||||||
|
typedef f64 *F64Array;
|
||||||
|
typedef f128 *F128Array;
|
||||||
|
typedef uptr *UptrArray;
|
||||||
|
typedef iptr *IptrArray;
|
||||||
|
typedef Str8 *Str8Array;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
ARRAY_INIT_NONE = 0,
|
||||||
|
ARRAY_INIT_FILLED = 1 << 1,
|
||||||
|
} ArrayInitFlags;
|
||||||
|
|
||||||
#ifdef WAPP_PLATFORM_CPP
|
#ifdef WAPP_PLATFORM_CPP
|
||||||
#define wapp_array(ELEM_TYPE, ARRAY_TYPE, ...) ([&]() { \
|
#define wapp_array(TYPE, ...) ([&]() { \
|
||||||
wapp_persist ELEM_TYPE items[sizeof(ELEM_TYPE) == sizeof(*((ARRAY_TYPE{}).items)) ? \
|
u64 capacity = _calc_array_capacity(TYPE, __VA_ARGS__); \
|
||||||
_calc_array_capacity(ELEM_TYPE, __VA_ARGS__) : -1 \
|
\
|
||||||
] = {__VA_ARGS__}; \
|
TYPE items[_calc_array_capacity(TYPE, __VA_ARGS__)] = {__VA_ARGS__}; \
|
||||||
\
|
\
|
||||||
return ARRAY_TYPE{ \
|
wapp_persist u8 array[ \
|
||||||
WAPP_ARRAY_MAGIC, \
|
sizeof(ArrayHeader) + _calc_array_capacity(TYPE, __VA_ARGS__) * sizeof(TYPE) \
|
||||||
_calc_array_count(ELEM_TYPE, __VA_ARGS__), \
|
] = {0}; \
|
||||||
_calc_array_capacity(ELEM_TYPE, __VA_ARGS__), \
|
ArrayHeader *header = (ArrayHeader *)array; \
|
||||||
sizeof(ELEM_TYPE), \
|
header->magic = WAPP_ARRAY_MAGIC; \
|
||||||
items, \
|
header->count = _calc_array_count(TYPE, __VA_ARGS__); \
|
||||||
}; \
|
header->capacity = _calc_array_capacity(TYPE, __VA_ARGS__); \
|
||||||
|
header->item_size = sizeof(TYPE); \
|
||||||
|
\
|
||||||
|
u8 *buf = (u8 *)(header + 1); \
|
||||||
|
memcpy(buf, items, capacity * sizeof(TYPE)); \
|
||||||
|
return (TYPE *)buf; \
|
||||||
}())
|
}())
|
||||||
#define wapp_array_with_capacity(ELEM_TYPE, ARRAY_TYPE, CAPACITY) ([&]() { \
|
#define wapp_array_with_capacity(TYPE, CAPACITY, FLAGS) ([&]() { \
|
||||||
wapp_persist ELEM_TYPE items[sizeof(ELEM_TYPE) == sizeof(*((ARRAY_TYPE{}).items)) ? \
|
wapp_persist u8 array[ \
|
||||||
CAPACITY : -1] = {}; \
|
sizeof(ArrayHeader) + CAPACITY * sizeof(TYPE) \
|
||||||
\
|
] = {0}; \
|
||||||
return ARRAY_TYPE{ \
|
ArrayHeader *header = (ArrayHeader *)array; \
|
||||||
WAPP_ARRAY_MAGIC, \
|
header->magic = WAPP_ARRAY_MAGIC; \
|
||||||
0, \
|
header->count = (FLAGS & ARRAY_INIT_FILLED) ? CAPACITY : 0; \
|
||||||
CAPACITY, \
|
header->capacity = CAPACITY; \
|
||||||
sizeof(ELEM_TYPE), \
|
header->item_size = sizeof(TYPE); \
|
||||||
items, \
|
\
|
||||||
}; \
|
return (TYPE *)(header + 1); \
|
||||||
}())
|
}())
|
||||||
#define wapp_array_pop(ELEM_TYPE, ARRAY_PTR) ([&]() { \
|
#define wapp_array_pop(TYPE, ARRAY) ([&]() { \
|
||||||
if (ARRAY_PTR == NULL || (ARRAY_PTR)->count == 0) { \
|
if (ARRAY == NULL || _array_count((GenericArray)ARRAY) == 0) { \
|
||||||
ELEM_TYPE result{}; \
|
TYPE result{}; \
|
||||||
return result; \
|
return result; \
|
||||||
} \
|
} \
|
||||||
\
|
\
|
||||||
return *((ELEM_TYPE *)_array_pop((Array *)ARRAY_PTR, sizeof(ELEM_TYPE))); \
|
return *((TYPE *)_array_pop((GenericArray)ARRAY, sizeof(TYPE))); \
|
||||||
}())
|
}())
|
||||||
#else
|
#else
|
||||||
#define wapp_array(ELEM_TYPE, ARRAY_TYPE, ...) \
|
#define _stack_array(TYPE, SIZE) struct {ArrayHeader header; \
|
||||||
((ARRAY_TYPE){ \
|
TYPE items[SIZE]; \
|
||||||
.magic = WAPP_ARRAY_MAGIC, \
|
wapp_misc_utils_reserve_padding(sizeof(ArrayHeader) + \
|
||||||
.count = _calc_array_count(ELEM_TYPE, __VA_ARGS__), \
|
sizeof(TYPE) * SIZE);}
|
||||||
.capacity = _calc_array_capacity(ELEM_TYPE, __VA_ARGS__), \
|
#define wapp_array(TYPE, ...) \
|
||||||
.item_size = sizeof(ELEM_TYPE), \
|
((TYPE *)( \
|
||||||
.items = (ELEM_TYPE[sizeof(ELEM_TYPE) == sizeof(*((ARRAY_TYPE){0}.items)) ? \
|
(_stack_array(TYPE, _calc_array_capacity(TYPE, __VA_ARGS__))){ \
|
||||||
_calc_array_capacity(ELEM_TYPE, __VA_ARGS__) : \
|
.header = { \
|
||||||
-1]){__VA_ARGS__} \
|
.magic = WAPP_ARRAY_MAGIC, \
|
||||||
})
|
.count = _calc_array_count(TYPE, __VA_ARGS__), \
|
||||||
#define wapp_array_with_capacity(ELEM_TYPE, ARRAY_TYPE, CAPACITY) \
|
.capacity = _calc_array_capacity(TYPE, __VA_ARGS__), \
|
||||||
((ARRAY_TYPE){ \
|
.item_size = sizeof(TYPE), \
|
||||||
.magic = WAPP_ARRAY_MAGIC, \
|
}, \
|
||||||
.count = 0, \
|
.items = {__VA_ARGS__}, \
|
||||||
.capacity = CAPACITY, \
|
}.items \
|
||||||
.item_size = sizeof(ELEM_TYPE), \
|
))
|
||||||
.items = (ELEM_TYPE[sizeof(ELEM_TYPE) == sizeof(*((ARRAY_TYPE){0}.items)) ? \
|
#define wapp_array_with_capacity(TYPE, CAPACITY, FLAGS) \
|
||||||
CAPACITY : -1]){0} \
|
((TYPE *)( \
|
||||||
})
|
(_stack_array(TYPE, CAPACITY)){ \
|
||||||
#define wapp_array_pop(ELEM_TYPE, ARRAY_PTR) \
|
.header = { \
|
||||||
(ARRAY_PTR != NULL && (ARRAY_PTR)->count > 0 ? \
|
.magic = WAPP_ARRAY_MAGIC, \
|
||||||
*((ELEM_TYPE *)_array_pop((Array *)ARRAY_PTR, sizeof(ELEM_TYPE))) : \
|
.count = (FLAGS & ARRAY_INIT_FILLED) ? CAPACITY : 0, \
|
||||||
(ELEM_TYPE){0} \
|
.capacity = CAPACITY, \
|
||||||
)
|
.item_size = sizeof(TYPE), \
|
||||||
|
}, \
|
||||||
|
.items = {0}, \
|
||||||
|
}.items \
|
||||||
|
))
|
||||||
|
#define wapp_array_pop(TYPE, ARRAY) \
|
||||||
|
(ARRAY == NULL || _array_count((GenericArray)ARRAY) == 0 ? \
|
||||||
|
(TYPE){0} : \
|
||||||
|
*((TYPE *)_array_pop((GenericArray)ARRAY, sizeof(TYPE))) \
|
||||||
|
)
|
||||||
#endif // !WAPP_PLATFORM_CPP
|
#endif // !WAPP_PLATFORM_CPP
|
||||||
|
|
||||||
#define wapp_array_get(ELEM_TYPE, ARRAY_PTR, INDEX) \
|
#define wapp_array_count(ARRAY) \
|
||||||
((ELEM_TYPE *)_array_get((Array *)ARRAY_PTR, INDEX, sizeof(ELEM_TYPE)))
|
(_array_count((GenericArray)ARRAY))
|
||||||
#define wapp_array_set(ELEM_TYPE, ARRAY_PTR, INDEX, VALUE_PTR) \
|
#define wapp_array_capacity(ARRAY) \
|
||||||
_array_set((Array *)ARRAY_PTR, INDEX, (void *)VALUE_PTR, sizeof(ELEM_TYPE))
|
(_array_capacity((GenericArray)ARRAY))
|
||||||
#define wapp_array_append_capped(ELEM_TYPE, ARRAY_PTR, VALUE_PTR) \
|
#define wapp_array_item_size(ARRAY) \
|
||||||
_array_append_capped((Array *)ARRAY_PTR, (void *)VALUE_PTR, sizeof(ELEM_TYPE))
|
(_array_item_size((GenericArray)ARRAY))
|
||||||
#define wapp_array_extend_capped(ELEM_TYPE, DST_ARRAY_PTR, SRC_ARRAY_PTR) \
|
#define wapp_array_set_count(ARRAY, COUNT) \
|
||||||
_array_extend_capped((Array *)DST_ARRAY_PTR, (Array *)SRC_ARRAY_PTR, sizeof(ELEM_TYPE))
|
(_array_set_count((GenericArray)ARRAY, COUNT))
|
||||||
#define wapp_array_copy_capped(ELEM_TYPE, DST_ARRAY_PTR, SRC_ARRAY_PTR) \
|
#define wapp_array_get(TYPE, ARRAY, INDEX) \
|
||||||
_array_copy_capped((Array *)DST_ARRAY_PTR, (Array *)SRC_ARRAY_PTR, sizeof(ELEM_TYPE))
|
((TYPE *)_array_get((GenericArray)ARRAY, \
|
||||||
#define wapp_array_append_alloc(ELEM_TYPE, ARRAY_TYPE, ALLOCATOR_PTR, ARRAY_PTR, VALUE_PTR) \
|
INDEX, \
|
||||||
(ARRAY_TYPE *)_array_append_alloc(ALLOCATOR_PTR, (Array *)ARRAY_PTR, (void *)VALUE_PTR, sizeof(ELEM_TYPE))
|
sizeof(TYPE)))
|
||||||
#define wapp_array_extend_alloc(ELEM_TYPE, ARRAY_TYPE, ALLOCATOR_PTR, DST_ARRAY_PTR, SRC_ARRAY_PTR) \
|
#define wapp_array_set(TYPE, ARRAY, INDEX, VALUE_PTR) \
|
||||||
(ARRAY_TYPE *)_array_extend_alloc(ALLOCATOR_PTR, (Array *)DST_ARRAY_PTR, (Array *)SRC_ARRAY_PTR, sizeof(ELEM_TYPE))
|
(_array_set((GenericArray)ARRAY, \
|
||||||
#define wapp_array_copy_alloc(ELEM_TYPE, ARRAY_TYPE, ALLOCATOR_PTR, DST_ARRAY_PTR, SRC_ARRAY_PTR) \
|
INDEX, \
|
||||||
(ARRAY_TYPE *)_array_copy_alloc(ALLOCATOR_PTR, (Array *)DST_ARRAY_PTR, (Array *)SRC_ARRAY_PTR, sizeof(ELEM_TYPE))
|
(u8 *)VALUE_PTR, \
|
||||||
#define wapp_array_clear(ELEM_TYPE, ARRAY_PTR) \
|
sizeof(TYPE)))
|
||||||
_array_clear((Array *)ARRAY_PTR, sizeof(ELEM_TYPE))
|
#define wapp_array_append_capped(TYPE, ARRAY, VALUE_PTR) \
|
||||||
|
(_array_append_capped((GenericArray)ARRAY, \
|
||||||
|
(u8 *)VALUE_PTR, \
|
||||||
|
sizeof(TYPE)))
|
||||||
|
#define wapp_array_extend_capped(TYPE, DST_ARRAY, SRC_ARRAY) \
|
||||||
|
(_array_extend_capped((GenericArray)DST_ARRAY, \
|
||||||
|
(GenericArray)SRC_ARRAY, \
|
||||||
|
sizeof(TYPE)))
|
||||||
|
#define wapp_array_copy_capped(TYPE, DST_ARRAY, SRC_ARRAY) \
|
||||||
|
(_array_copy_capped((GenericArray)DST_ARRAY, \
|
||||||
|
(GenericArray)SRC_ARRAY, \
|
||||||
|
sizeof(TYPE)))
|
||||||
|
#define wapp_array_append_alloc(TYPE, ALLOCATOR_PTR, ARRAY, VALUE_PTR, FLAGS) \
|
||||||
|
((TYPE *)_array_append_alloc(ALLOCATOR_PTR, \
|
||||||
|
(GenericArray)ARRAY, \
|
||||||
|
(u8 *)VALUE_PTR, \
|
||||||
|
FLAGS, \
|
||||||
|
sizeof(TYPE)))
|
||||||
|
#define wapp_array_extend_alloc(TYPE, ALLOCATOR_PTR, DST_ARRAY, SRC_ARRAY, FLAGS) \
|
||||||
|
((TYPE *)_array_extend_alloc(ALLOCATOR_PTR, \
|
||||||
|
(GenericArray)DST_ARRAY, \
|
||||||
|
(GenericArray)SRC_ARRAY, \
|
||||||
|
FLAGS, \
|
||||||
|
sizeof(TYPE)))
|
||||||
|
#define wapp_array_copy_alloc(TYPE, ALLOCATOR_PTR, DST_ARRAY, SRC_ARRAY, FLAGS) \
|
||||||
|
((TYPE *)_array_copy_alloc(ALLOCATOR_PTR, \
|
||||||
|
(GenericArray)DST_ARRAY, \
|
||||||
|
(GenericArray)SRC_ARRAY, \
|
||||||
|
FLAGS, \
|
||||||
|
sizeof(TYPE)))
|
||||||
|
#define wapp_array_clear(TYPE, ARRAY) \
|
||||||
|
(_array_clear((GenericArray)ARRAY, \
|
||||||
|
sizeof(TYPE)))
|
||||||
|
#define wapp_array_calc_alloc_size(TYPE, CAPACITY) _array_calc_alloc_size(CAPACITY, sizeof(TYPE))
|
||||||
|
#define wapp_array_alloc_capacity(TYPE, ALLOCATOR_PTR, CAPACITY, FLAGS) \
|
||||||
|
((TYPE *)_array_alloc_capacity(ALLOCATOR_PTR, CAPACITY, FLAGS, sizeof(TYPE)))
|
||||||
|
#define wapp_array_from_preallcated_buffer(TYPE, BUFFER, BUFFER_SIZE) \
|
||||||
|
((TYPE *)_array_from_preallcated_buffer(BUFFER, BUFFER_SIZE, sizeof(TYPE)))
|
||||||
|
|
||||||
WAPP_DEF_ARRAY_TYPE(void, Array);
|
|
||||||
|
|
||||||
void *_array_get(Array *array, u64 index, u64 item_size);
|
typedef struct header ArrayHeader;
|
||||||
void _array_set(Array *array, u64 index, void *value, u64 item_size);
|
struct header {
|
||||||
void _array_append_capped(Array *array, void *value, u64 item_size);
|
u64 magic;
|
||||||
void _array_extend_capped(Array *dst, const Array *src, u64 item_size);
|
u64 count;
|
||||||
void _array_copy_capped(Array *dst, const Array *src, u64 item_size);
|
u64 capacity;
|
||||||
Array *_array_append_alloc(const Allocator *allocator, Array *array, void *value, u64 item_size);
|
u64 item_size;
|
||||||
Array *_array_extend_alloc(const Allocator *allocator, Array *dst, const Array *src, u64 item_size);
|
};
|
||||||
Array *_array_copy_alloc(const Allocator *allocator, Array *dst, const Array *src, u64 item_size);
|
|
||||||
void *_array_pop(Array *array, u64 item_size);
|
|
||||||
void _array_clear(Array *array, u64 item_size);
|
|
||||||
Array *_array_alloc_capacity(const Allocator *allocator, u64 capacity, u64 item_size);
|
|
||||||
|
|
||||||
// Base array types
|
u64 _array_count(GenericArray array);
|
||||||
typedef struct str8 Str8;
|
u64 _array_capacity(GenericArray array);
|
||||||
|
u64 _array_item_size(GenericArray array);
|
||||||
WAPP_DEF_ARRAY_TYPE(void *, VoidPtrArray);
|
void _array_set_count(GenericArray array, u64 count);
|
||||||
WAPP_DEF_ARRAY_TYPE(c8 , C8Array);
|
void *_array_get(GenericArray array, u64 index, u64 item_size);
|
||||||
WAPP_DEF_ARRAY_TYPE(c16 , C16Array);
|
void _array_set(GenericArray array, u64 index, void *value, u64 item_size);
|
||||||
WAPP_DEF_ARRAY_TYPE(c32 , C32Array);
|
void _array_append_capped(GenericArray array, void *value, u64 item_size);
|
||||||
WAPP_DEF_ARRAY_TYPE(u8 , U8Array);
|
void _array_extend_capped(GenericArray dst, const GenericArray src, u64 item_size);
|
||||||
WAPP_DEF_ARRAY_TYPE(u16 , U16Array);
|
void _array_copy_capped(GenericArray dst, const GenericArray src, u64 item_size);
|
||||||
WAPP_DEF_ARRAY_TYPE(u32 , U32Array);
|
GenericArray _array_append_alloc(const Allocator *allocator, GenericArray array, void *value,
|
||||||
WAPP_DEF_ARRAY_TYPE(u64 , U64Array);
|
ArrayInitFlags flags, u64 item_size);
|
||||||
WAPP_DEF_ARRAY_TYPE(b8 , B8Array);
|
GenericArray _array_extend_alloc(const Allocator *allocator, GenericArray dst, const GenericArray src,
|
||||||
WAPP_DEF_ARRAY_TYPE(i8 , I8Array);
|
ArrayInitFlags flags, u64 item_size);
|
||||||
WAPP_DEF_ARRAY_TYPE(i16 , I16Array);
|
GenericArray _array_copy_alloc(const Allocator *allocator, GenericArray dst, const GenericArray src,
|
||||||
WAPP_DEF_ARRAY_TYPE(i32 , I32Array);
|
ArrayInitFlags flags, u64 item_size);
|
||||||
WAPP_DEF_ARRAY_TYPE(i64 , I64Array);
|
void *_array_pop(GenericArray array, u64 item_size);
|
||||||
WAPP_DEF_ARRAY_TYPE(f32 , F32Array);
|
void _array_clear(GenericArray array, u64 item_size);
|
||||||
WAPP_DEF_ARRAY_TYPE(f64 , F64Array);
|
u64 _array_calc_alloc_size(u64 capacity, u64 item_size);
|
||||||
WAPP_DEF_ARRAY_TYPE(f128 , F128Array);
|
GenericArray _array_alloc_capacity(const Allocator *allocator, u64 capacity, ArrayInitFlags flags,
|
||||||
WAPP_DEF_ARRAY_TYPE(uptr , UptrArray);
|
u64 item_size);
|
||||||
WAPP_DEF_ARRAY_TYPE(iptr , IptrArray);
|
GenericArray _array_from_preallocated_buffer(void *buffer, u64 buffer_size, ArrayInitFlags flags,
|
||||||
WAPP_DEF_ARRAY_TYPE(Str8 , Str8Array);
|
u64 item_size);
|
||||||
|
|
||||||
#ifdef WAPP_PLATFORM_CPP
|
#ifdef WAPP_PLATFORM_CPP
|
||||||
END_C_LINKAGE
|
END_C_LINKAGE
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -1,10 +1,9 @@
|
|||||||
/**
|
// vim:fileencoding=utf-8:foldmethod=marker
|
||||||
* THIS FILE IS AUTOMATICALLY GENERATED. ANY MODIFICATIONS TO IT WILL BE OVERWRITTEN.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef DBL_LIST_H
|
#ifndef DBL_LIST_H
|
||||||
#define DBL_LIST_H
|
#define DBL_LIST_H
|
||||||
|
|
||||||
|
#include "../mem/allocator/mem_allocator.h"
|
||||||
#include "../../common/aliases/aliases.h"
|
#include "../../common/aliases/aliases.h"
|
||||||
#include "../../common/platform/platform.h"
|
#include "../../common/platform/platform.h"
|
||||||
|
|
||||||
@@ -12,506 +11,171 @@
|
|||||||
BEGIN_C_LINKAGE
|
BEGIN_C_LINKAGE
|
||||||
#endif // !WAPP_PLATFORM_CPP
|
#endif // !WAPP_PLATFORM_CPP
|
||||||
|
|
||||||
#ifdef WAPP_PLATFORM_CPP
|
#define WAPP_DBL_LIST_MAGIC (u64)0x57415f444c5354
|
||||||
#define wapp_void_ptr_list_node(ITEM_PTR) VoidPNode{ITEM_PTR, nullptr, nullptr}
|
#define WAPP_DBL_NODE_MAGIC (u64)0x57415f444e44
|
||||||
#define wapp_str8_list_node(ITEM_PTR) Str8Node{ITEM_PTR, nullptr, nullptr}
|
|
||||||
#define wapp_b8_list_node(ITEM_PTR) B8Node{ITEM_PTR, nullptr, nullptr}
|
|
||||||
#define wapp_char_list_node(ITEM_PTR) CharNode{ITEM_PTR, nullptr, nullptr}
|
|
||||||
#define wapp_c8_list_node(ITEM_PTR) C8Node{ITEM_PTR, nullptr, nullptr}
|
|
||||||
#define wapp_c16_list_node(ITEM_PTR) C16Node{ITEM_PTR, nullptr, nullptr}
|
|
||||||
#define wapp_c32_list_node(ITEM_PTR) C32Node{ITEM_PTR, nullptr, nullptr}
|
|
||||||
#define wapp_i8_list_node(ITEM_PTR) I8Node{ITEM_PTR, nullptr, nullptr}
|
|
||||||
#define wapp_i16_list_node(ITEM_PTR) I16Node{ITEM_PTR, nullptr, nullptr}
|
|
||||||
#define wapp_i32_list_node(ITEM_PTR) I32Node{ITEM_PTR, nullptr, nullptr}
|
|
||||||
#define wapp_i64_list_node(ITEM_PTR) I64Node{ITEM_PTR, nullptr, nullptr}
|
|
||||||
#define wapp_u8_list_node(ITEM_PTR) U8Node{ITEM_PTR, nullptr, nullptr}
|
|
||||||
#define wapp_u16_list_node(ITEM_PTR) U16Node{ITEM_PTR, nullptr, nullptr}
|
|
||||||
#define wapp_u32_list_node(ITEM_PTR) U32Node{ITEM_PTR, nullptr, nullptr}
|
|
||||||
#define wapp_u64_list_node(ITEM_PTR) U64Node{ITEM_PTR, nullptr, nullptr}
|
|
||||||
#define wapp_f32_list_node(ITEM_PTR) F32Node{ITEM_PTR, nullptr, nullptr}
|
|
||||||
#define wapp_f64_list_node(ITEM_PTR) F64Node{ITEM_PTR, nullptr, nullptr}
|
|
||||||
#define wapp_f128_list_node(ITEM_PTR) F128Node{ITEM_PTR, nullptr, nullptr}
|
|
||||||
#define wapp_iptr_list_node(ITEM_PTR) IptrNode{ITEM_PTR, nullptr, nullptr}
|
|
||||||
#define wapp_uptr_list_node(ITEM_PTR) UptrNode{ITEM_PTR, nullptr, nullptr}
|
|
||||||
#else
|
|
||||||
#define wapp_void_ptr_list_node(ITEM_PTR) ((VoidPNode){.item = ITEM_PTR})
|
|
||||||
#define wapp_str8_list_node(ITEM_PTR) ((Str8Node){.item = ITEM_PTR})
|
|
||||||
#define wapp_b8_list_node(ITEM_PTR) ((B8Node){.item = ITEM_PTR})
|
|
||||||
#define wapp_char_list_node(ITEM_PTR) ((CharNode){.item = ITEM_PTR})
|
|
||||||
#define wapp_c8_list_node(ITEM_PTR) ((C8Node){.item = ITEM_PTR})
|
|
||||||
#define wapp_c16_list_node(ITEM_PTR) ((C16Node){.item = ITEM_PTR})
|
|
||||||
#define wapp_c32_list_node(ITEM_PTR) ((C32Node){.item = ITEM_PTR})
|
|
||||||
#define wapp_i8_list_node(ITEM_PTR) ((I8Node){.item = ITEM_PTR})
|
|
||||||
#define wapp_i16_list_node(ITEM_PTR) ((I16Node){.item = ITEM_PTR})
|
|
||||||
#define wapp_i32_list_node(ITEM_PTR) ((I32Node){.item = ITEM_PTR})
|
|
||||||
#define wapp_i64_list_node(ITEM_PTR) ((I64Node){.item = ITEM_PTR})
|
|
||||||
#define wapp_u8_list_node(ITEM_PTR) ((U8Node){.item = ITEM_PTR})
|
|
||||||
#define wapp_u16_list_node(ITEM_PTR) ((U16Node){.item = ITEM_PTR})
|
|
||||||
#define wapp_u32_list_node(ITEM_PTR) ((U32Node){.item = ITEM_PTR})
|
|
||||||
#define wapp_u64_list_node(ITEM_PTR) ((U64Node){.item = ITEM_PTR})
|
|
||||||
#define wapp_f32_list_node(ITEM_PTR) ((F32Node){.item = ITEM_PTR})
|
|
||||||
#define wapp_f64_list_node(ITEM_PTR) ((F64Node){.item = ITEM_PTR})
|
|
||||||
#define wapp_f128_list_node(ITEM_PTR) ((F128Node){.item = ITEM_PTR})
|
|
||||||
#define wapp_iptr_list_node(ITEM_PTR) ((IptrNode){.item = ITEM_PTR})
|
|
||||||
#define wapp_uptr_list_node(ITEM_PTR) ((UptrNode){.item = ITEM_PTR})
|
|
||||||
#endif // !WAPP_PLATFORM_CPP
|
|
||||||
|
|
||||||
typedef struct str8 Str8;
|
|
||||||
|
|
||||||
typedef struct GenericNode GenericNode;
|
typedef struct GenericNode GenericNode;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
u64 magic;
|
||||||
|
u64 item_size;
|
||||||
|
GenericNode *prev;
|
||||||
|
GenericNode *next;
|
||||||
|
} NodeHeader;
|
||||||
|
|
||||||
struct GenericNode {
|
struct GenericNode {
|
||||||
void *item;
|
NodeHeader header;
|
||||||
GenericNode *prev;
|
void *item;
|
||||||
GenericNode *next;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct GenericList GenericList;
|
typedef struct {
|
||||||
struct GenericList {
|
u64 magic;
|
||||||
GenericNode *first;
|
u64 node_count;
|
||||||
GenericNode *last;
|
u64 item_size;
|
||||||
u64 node_count;
|
GenericNode *first;
|
||||||
};
|
GenericNode *last;
|
||||||
|
} GenericList;
|
||||||
|
|
||||||
typedef struct VoidPNode VoidPNode;
|
// NOTE (Abdelrahman): GenericList typedefs for readability
|
||||||
struct VoidPNode {
|
typedef GenericList VoidPtrList;
|
||||||
void * *item;
|
typedef GenericList C8List;
|
||||||
VoidPNode *prev;
|
typedef GenericList C16List;
|
||||||
VoidPNode *next;
|
typedef GenericList C32List;
|
||||||
};
|
typedef GenericList U8List;
|
||||||
|
typedef GenericList U16List;
|
||||||
|
typedef GenericList U32List;
|
||||||
|
typedef GenericList U64List;
|
||||||
|
typedef GenericList B8List;
|
||||||
|
typedef GenericList I8List;
|
||||||
|
typedef GenericList I16List;
|
||||||
|
typedef GenericList I32List;
|
||||||
|
typedef GenericList I64List;
|
||||||
|
typedef GenericList F32List;
|
||||||
|
typedef GenericList F64List;
|
||||||
|
typedef GenericList F128List;
|
||||||
|
typedef GenericList UptrList;
|
||||||
|
typedef GenericList IptrList;
|
||||||
|
typedef GenericList Str8List;
|
||||||
|
|
||||||
typedef struct VoidPList VoidPList;
|
// NOTE (Abdelrahman): GenericNode typedefs for readability
|
||||||
struct VoidPList {
|
typedef GenericNode VoidPtrNode;
|
||||||
VoidPNode *first;
|
typedef GenericNode C8Node;
|
||||||
VoidPNode *last;
|
typedef GenericNode C16Node;
|
||||||
u64 node_count;
|
typedef GenericNode C32Node;
|
||||||
};
|
typedef GenericNode U8Node;
|
||||||
|
typedef GenericNode U16Node;
|
||||||
|
typedef GenericNode U32Node;
|
||||||
|
typedef GenericNode U64Node;
|
||||||
|
typedef GenericNode B8Node;
|
||||||
|
typedef GenericNode I8Node;
|
||||||
|
typedef GenericNode I16Node;
|
||||||
|
typedef GenericNode I32Node;
|
||||||
|
typedef GenericNode I64Node;
|
||||||
|
typedef GenericNode F32Node;
|
||||||
|
typedef GenericNode F64Node;
|
||||||
|
typedef GenericNode F128Node;
|
||||||
|
typedef GenericNode UptrNode;
|
||||||
|
typedef GenericNode IptrNode;
|
||||||
|
typedef GenericNode Str8Node;
|
||||||
|
|
||||||
typedef struct Str8Node Str8Node;
|
#ifdef WAPP_PLATFORM_CPP
|
||||||
struct Str8Node {
|
#define wapp_dbl_list(TYPE) \
|
||||||
Str8 *item;
|
GenericList{WAPP_DBL_LIST_MAGIC, 0, sizeof(TYPE), nullptr, nullptr}
|
||||||
Str8Node *prev;
|
#define _dbl_list_node(TYPE, ITEM_PTR) ([&]() { \
|
||||||
Str8Node *next;
|
wapp_persist GenericNode node = { \
|
||||||
};
|
NodeHeader{WAPP_DBL_NODE_MAGIC, sizeof(TYPE), nullptr, nullptr}, \
|
||||||
|
ITEM_PTR, \
|
||||||
|
}; \
|
||||||
|
\
|
||||||
|
return &node; \
|
||||||
|
}())
|
||||||
|
#else
|
||||||
|
#define wapp_dbl_list(TYPE) ( \
|
||||||
|
(GenericList){.magic = WAPP_DBL_LIST_MAGIC, .item_size = sizeof(TYPE)} \
|
||||||
|
)
|
||||||
|
#define _dbl_list_node(TYPE, ITEM_PTR) ( \
|
||||||
|
&((GenericNode){.header = {.magic = WAPP_DBL_NODE_MAGIC, .item_size = sizeof(TYPE)}, \
|
||||||
|
.item = ITEM_PTR}) \
|
||||||
|
)
|
||||||
|
#endif // !WAPP_PLATFORM_CPP
|
||||||
|
|
||||||
typedef struct Str8List Str8List;
|
#define wapp_dbl_list_alloc(TYPE, ALLOCATOR) \
|
||||||
struct Str8List {
|
(_dbl_list_alloc(ALLOCATOR, sizeof(TYPE)))
|
||||||
Str8Node *first;
|
#define wapp_dbl_list_get(TYPE, LIST_PTR, ITEM_INDEX) \
|
||||||
Str8Node *last;
|
((TYPE *)(_dbl_list_get(LIST_PTR, ITEM_INDEX, sizeof(TYPE))->item))
|
||||||
u64 node_count;
|
#define wapp_dbl_list_get_node(TYPE, LIST_PTR, ITEM_INDEX) \
|
||||||
};
|
(_dbl_list_get(LIST_PTR, ITEM_INDEX, sizeof(TYPE)))
|
||||||
|
#define wapp_dbl_list_get_node_item(TYPE, NODE_PTR) \
|
||||||
|
((TYPE *)( \
|
||||||
|
(NODE_PTR == NULL) ? \
|
||||||
|
NULL : \
|
||||||
|
(NODE_PTR)->item \
|
||||||
|
))
|
||||||
|
#define wapp_dbl_list_push_front(TYPE, LIST_PTR, ITEM_PTR) \
|
||||||
|
(_dbl_list_push_front(LIST_PTR, _dbl_list_node(TYPE, ITEM_PTR), sizeof(TYPE)))
|
||||||
|
#define wapp_dbl_list_push_back(TYPE, LIST_PTR, ITEM_PTR) \
|
||||||
|
(_dbl_list_push_back(LIST_PTR, _dbl_list_node(TYPE, ITEM_PTR), sizeof(TYPE)))
|
||||||
|
#define wapp_dbl_list_insert(TYPE, LIST_PTR, ITEM_PTR, ITEM_INDEX) \
|
||||||
|
(_dbl_list_insert(LIST_PTR, _dbl_list_node(TYPE, ITEM_PTR), \
|
||||||
|
ITEM_INDEX, sizeof(TYPE)))
|
||||||
|
#define wapp_dbl_list_push_front_alloc(TYPE, ALLOCATOR, LIST_PTR, ITEM_PTR) \
|
||||||
|
(_dbl_list_push_front(LIST_PTR, _dbl_list_node_alloc(ALLOCATOR, ITEM_PTR, sizeof(TYPE)), \
|
||||||
|
sizeof(TYPE)))
|
||||||
|
#define wapp_dbl_list_push_back_alloc(TYPE, ALLOCATOR, LIST_PTR, ITEM_PTR) \
|
||||||
|
(_dbl_list_push_back(LIST_PTR, _dbl_list_node_alloc(ALLOCATOR, ITEM_PTR, sizeof(TYPE)), \
|
||||||
|
sizeof(TYPE)))
|
||||||
|
#define wapp_dbl_list_insert_alloc(TYPE, ALLOCATOR, LIST_PTR, ITEM_PTR, ITEM_INDEX) \
|
||||||
|
(_dbl_list_insert(LIST_PTR, _dbl_list_node_alloc(ALLOCATOR, ITEM_PTR, sizeof(TYPE)), \
|
||||||
|
ITEM_INDEX, sizeof(TYPE)))
|
||||||
|
#define wapp_dbl_list_pop_front(TYPE, LIST_PTR) \
|
||||||
|
((TYPE *)( \
|
||||||
|
(LIST_PTR == NULL || (LIST_PTR)->node_count == 0) ? \
|
||||||
|
NULL : \
|
||||||
|
_dbl_list_pop_front(LIST_PTR, sizeof(TYPE))->item \
|
||||||
|
))
|
||||||
|
#define wapp_dbl_list_pop_back(TYPE, LIST_PTR) \
|
||||||
|
((TYPE *)( \
|
||||||
|
(LIST_PTR == NULL || (LIST_PTR)->node_count == 0) ? \
|
||||||
|
NULL : \
|
||||||
|
_dbl_list_pop_back(LIST_PTR, sizeof(TYPE))->item \
|
||||||
|
))
|
||||||
|
#define wapp_dbl_list_remove(TYPE, LIST_PTR, ITEM_INDEX) \
|
||||||
|
((TYPE *)( \
|
||||||
|
(LIST_PTR == NULL || (LIST_PTR)->node_count == 0 || ITEM_INDEX >= (LIST_PTR)->node_count) ? \
|
||||||
|
NULL : \
|
||||||
|
_dbl_list_remove(LIST_PTR, ITEM_INDEX, sizeof(TYPE))->item \
|
||||||
|
))
|
||||||
|
#define wapp_dbl_list_pop_front_node(TYPE, LIST_PTR) \
|
||||||
|
( \
|
||||||
|
(LIST_PTR == NULL || (LIST_PTR)->node_count == 0) ? \
|
||||||
|
NULL : \
|
||||||
|
_dbl_list_pop_front(LIST_PTR, sizeof(TYPE)) \
|
||||||
|
)
|
||||||
|
#define wapp_dbl_list_pop_back_node(TYPE, LIST_PTR) \
|
||||||
|
( \
|
||||||
|
(LIST_PTR == NULL || (LIST_PTR)->node_count == 0) ? \
|
||||||
|
NULL : \
|
||||||
|
_dbl_list_pop_back(LIST_PTR, sizeof(TYPE)) \
|
||||||
|
)
|
||||||
|
#define wapp_dbl_list_remove_node(TYPE, LIST_PTR, ITEM_INDEX) \
|
||||||
|
( \
|
||||||
|
(LIST_PTR == NULL || (LIST_PTR)->node_count == 0 || ITEM_INDEX >= (LIST_PTR)->node_count) ? \
|
||||||
|
NULL : \
|
||||||
|
_dbl_list_remove(LIST_PTR, ITEM_INDEX, sizeof(TYPE)) \
|
||||||
|
)
|
||||||
|
#define wapp_dbl_list_empty(TYPE, LIST_PTR) \
|
||||||
|
(_dbl_list_empty(LIST_PTR, sizeof(TYPE)))
|
||||||
|
|
||||||
typedef struct B8Node B8Node;
|
GenericList *_dbl_list_alloc(const Allocator *allocator, u64 item_size);
|
||||||
struct B8Node {
|
GenericNode *_dbl_list_node_alloc(const Allocator *allocator, void *item, u64 item_size);
|
||||||
b8 *item;
|
GenericNode *_dbl_list_get(const GenericList *list, u64 index, u64 item_size);
|
||||||
B8Node *prev;
|
void _dbl_list_push_front(GenericList *list, GenericNode *node, u64 item_size);
|
||||||
B8Node *next;
|
void _dbl_list_push_back(GenericList *list, GenericNode *node, u64 item_size);
|
||||||
};
|
void _dbl_list_insert(GenericList *list, GenericNode *node, u64 index, u64 item_size);
|
||||||
|
GenericNode *_dbl_list_pop_front(GenericList *list, u64 item_size);
|
||||||
typedef struct B8List B8List;
|
GenericNode *_dbl_list_pop_back(GenericList *list, u64 item_size);
|
||||||
struct B8List {
|
GenericNode *_dbl_list_remove(GenericList *list, u64 index, u64 item_size);
|
||||||
B8Node *first;
|
void _dbl_list_empty(GenericList *list, u64 item_size);
|
||||||
B8Node *last;
|
|
||||||
u64 node_count;
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef struct CharNode CharNode;
|
|
||||||
struct CharNode {
|
|
||||||
char *item;
|
|
||||||
CharNode *prev;
|
|
||||||
CharNode *next;
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef struct CharList CharList;
|
|
||||||
struct CharList {
|
|
||||||
CharNode *first;
|
|
||||||
CharNode *last;
|
|
||||||
u64 node_count;
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef struct C8Node C8Node;
|
|
||||||
struct C8Node {
|
|
||||||
c8 *item;
|
|
||||||
C8Node *prev;
|
|
||||||
C8Node *next;
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef struct C8List C8List;
|
|
||||||
struct C8List {
|
|
||||||
C8Node *first;
|
|
||||||
C8Node *last;
|
|
||||||
u64 node_count;
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef struct C16Node C16Node;
|
|
||||||
struct C16Node {
|
|
||||||
c16 *item;
|
|
||||||
C16Node *prev;
|
|
||||||
C16Node *next;
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef struct C16List C16List;
|
|
||||||
struct C16List {
|
|
||||||
C16Node *first;
|
|
||||||
C16Node *last;
|
|
||||||
u64 node_count;
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef struct C32Node C32Node;
|
|
||||||
struct C32Node {
|
|
||||||
c32 *item;
|
|
||||||
C32Node *prev;
|
|
||||||
C32Node *next;
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef struct C32List C32List;
|
|
||||||
struct C32List {
|
|
||||||
C32Node *first;
|
|
||||||
C32Node *last;
|
|
||||||
u64 node_count;
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef struct I8Node I8Node;
|
|
||||||
struct I8Node {
|
|
||||||
i8 *item;
|
|
||||||
I8Node *prev;
|
|
||||||
I8Node *next;
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef struct I8List I8List;
|
|
||||||
struct I8List {
|
|
||||||
I8Node *first;
|
|
||||||
I8Node *last;
|
|
||||||
u64 node_count;
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef struct I16Node I16Node;
|
|
||||||
struct I16Node {
|
|
||||||
i16 *item;
|
|
||||||
I16Node *prev;
|
|
||||||
I16Node *next;
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef struct I16List I16List;
|
|
||||||
struct I16List {
|
|
||||||
I16Node *first;
|
|
||||||
I16Node *last;
|
|
||||||
u64 node_count;
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef struct I32Node I32Node;
|
|
||||||
struct I32Node {
|
|
||||||
i32 *item;
|
|
||||||
I32Node *prev;
|
|
||||||
I32Node *next;
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef struct I32List I32List;
|
|
||||||
struct I32List {
|
|
||||||
I32Node *first;
|
|
||||||
I32Node *last;
|
|
||||||
u64 node_count;
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef struct I64Node I64Node;
|
|
||||||
struct I64Node {
|
|
||||||
i64 *item;
|
|
||||||
I64Node *prev;
|
|
||||||
I64Node *next;
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef struct I64List I64List;
|
|
||||||
struct I64List {
|
|
||||||
I64Node *first;
|
|
||||||
I64Node *last;
|
|
||||||
u64 node_count;
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef struct U8Node U8Node;
|
|
||||||
struct U8Node {
|
|
||||||
u8 *item;
|
|
||||||
U8Node *prev;
|
|
||||||
U8Node *next;
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef struct U8List U8List;
|
|
||||||
struct U8List {
|
|
||||||
U8Node *first;
|
|
||||||
U8Node *last;
|
|
||||||
u64 node_count;
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef struct U16Node U16Node;
|
|
||||||
struct U16Node {
|
|
||||||
u16 *item;
|
|
||||||
U16Node *prev;
|
|
||||||
U16Node *next;
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef struct U16List U16List;
|
|
||||||
struct U16List {
|
|
||||||
U16Node *first;
|
|
||||||
U16Node *last;
|
|
||||||
u64 node_count;
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef struct U32Node U32Node;
|
|
||||||
struct U32Node {
|
|
||||||
u32 *item;
|
|
||||||
U32Node *prev;
|
|
||||||
U32Node *next;
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef struct U32List U32List;
|
|
||||||
struct U32List {
|
|
||||||
U32Node *first;
|
|
||||||
U32Node *last;
|
|
||||||
u64 node_count;
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef struct U64Node U64Node;
|
|
||||||
struct U64Node {
|
|
||||||
u64 *item;
|
|
||||||
U64Node *prev;
|
|
||||||
U64Node *next;
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef struct U64List U64List;
|
|
||||||
struct U64List {
|
|
||||||
U64Node *first;
|
|
||||||
U64Node *last;
|
|
||||||
u64 node_count;
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef struct F32Node F32Node;
|
|
||||||
struct F32Node {
|
|
||||||
f32 *item;
|
|
||||||
F32Node *prev;
|
|
||||||
F32Node *next;
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef struct F32List F32List;
|
|
||||||
struct F32List {
|
|
||||||
F32Node *first;
|
|
||||||
F32Node *last;
|
|
||||||
u64 node_count;
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef struct F64Node F64Node;
|
|
||||||
struct F64Node {
|
|
||||||
f64 *item;
|
|
||||||
F64Node *prev;
|
|
||||||
F64Node *next;
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef struct F64List F64List;
|
|
||||||
struct F64List {
|
|
||||||
F64Node *first;
|
|
||||||
F64Node *last;
|
|
||||||
u64 node_count;
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef struct F128Node F128Node;
|
|
||||||
struct F128Node {
|
|
||||||
f128 *item;
|
|
||||||
F128Node *prev;
|
|
||||||
F128Node *next;
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef struct F128List F128List;
|
|
||||||
struct F128List {
|
|
||||||
F128Node *first;
|
|
||||||
F128Node *last;
|
|
||||||
u64 node_count;
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef struct IptrNode IptrNode;
|
|
||||||
struct IptrNode {
|
|
||||||
iptr *item;
|
|
||||||
IptrNode *prev;
|
|
||||||
IptrNode *next;
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef struct IptrList IptrList;
|
|
||||||
struct IptrList {
|
|
||||||
IptrNode *first;
|
|
||||||
IptrNode *last;
|
|
||||||
u64 node_count;
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef struct UptrNode UptrNode;
|
|
||||||
struct UptrNode {
|
|
||||||
uptr *item;
|
|
||||||
UptrNode *prev;
|
|
||||||
UptrNode *next;
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef struct UptrList UptrList;
|
|
||||||
struct UptrList {
|
|
||||||
UptrNode *first;
|
|
||||||
UptrNode *last;
|
|
||||||
u64 node_count;
|
|
||||||
};
|
|
||||||
|
|
||||||
VoidPNode *wapp_void_ptr_list_get(const VoidPList *list, u64 index);
|
|
||||||
void wapp_void_ptr_list_push_front(VoidPList *list, VoidPNode *node);
|
|
||||||
void wapp_void_ptr_list_push_back(VoidPList *list, VoidPNode *node);
|
|
||||||
void wapp_void_ptr_list_insert(VoidPList *list, VoidPNode *node, u64 index);
|
|
||||||
VoidPNode *wapp_void_ptr_list_pop_front(VoidPList *list);
|
|
||||||
VoidPNode *wapp_void_ptr_list_pop_back(VoidPList *list);
|
|
||||||
VoidPNode *wapp_void_ptr_list_remove(VoidPList *list, u64 index);
|
|
||||||
void wapp_void_ptr_list_empty(VoidPList *list);
|
|
||||||
Str8Node *wapp_str8_list_get(const Str8List *list, u64 index);
|
|
||||||
void wapp_str8_list_push_front(Str8List *list, Str8Node *node);
|
|
||||||
void wapp_str8_list_push_back(Str8List *list, Str8Node *node);
|
|
||||||
void wapp_str8_list_insert(Str8List *list, Str8Node *node, u64 index);
|
|
||||||
Str8Node *wapp_str8_list_pop_front(Str8List *list);
|
|
||||||
Str8Node *wapp_str8_list_pop_back(Str8List *list);
|
|
||||||
Str8Node *wapp_str8_list_remove(Str8List *list, u64 index);
|
|
||||||
void wapp_str8_list_empty(Str8List *list);
|
|
||||||
B8Node *wapp_b8_list_get(const B8List *list, u64 index);
|
|
||||||
void wapp_b8_list_push_front(B8List *list, B8Node *node);
|
|
||||||
void wapp_b8_list_push_back(B8List *list, B8Node *node);
|
|
||||||
void wapp_b8_list_insert(B8List *list, B8Node *node, u64 index);
|
|
||||||
B8Node *wapp_b8_list_pop_front(B8List *list);
|
|
||||||
B8Node *wapp_b8_list_pop_back(B8List *list);
|
|
||||||
B8Node *wapp_b8_list_remove(B8List *list, u64 index);
|
|
||||||
void wapp_b8_list_empty(B8List *list);
|
|
||||||
CharNode *wapp_char_list_get(const CharList *list, u64 index);
|
|
||||||
void wapp_char_list_push_front(CharList *list, CharNode *node);
|
|
||||||
void wapp_char_list_push_back(CharList *list, CharNode *node);
|
|
||||||
void wapp_char_list_insert(CharList *list, CharNode *node, u64 index);
|
|
||||||
CharNode *wapp_char_list_pop_front(CharList *list);
|
|
||||||
CharNode *wapp_char_list_pop_back(CharList *list);
|
|
||||||
CharNode *wapp_char_list_remove(CharList *list, u64 index);
|
|
||||||
void wapp_char_list_empty(CharList *list);
|
|
||||||
C8Node *wapp_c8_list_get(const C8List *list, u64 index);
|
|
||||||
void wapp_c8_list_push_front(C8List *list, C8Node *node);
|
|
||||||
void wapp_c8_list_push_back(C8List *list, C8Node *node);
|
|
||||||
void wapp_c8_list_insert(C8List *list, C8Node *node, u64 index);
|
|
||||||
C8Node *wapp_c8_list_pop_front(C8List *list);
|
|
||||||
C8Node *wapp_c8_list_pop_back(C8List *list);
|
|
||||||
C8Node *wapp_c8_list_remove(C8List *list, u64 index);
|
|
||||||
void wapp_c8_list_empty(C8List *list);
|
|
||||||
C16Node *wapp_c16_list_get(const C16List *list, u64 index);
|
|
||||||
void wapp_c16_list_push_front(C16List *list, C16Node *node);
|
|
||||||
void wapp_c16_list_push_back(C16List *list, C16Node *node);
|
|
||||||
void wapp_c16_list_insert(C16List *list, C16Node *node, u64 index);
|
|
||||||
C16Node *wapp_c16_list_pop_front(C16List *list);
|
|
||||||
C16Node *wapp_c16_list_pop_back(C16List *list);
|
|
||||||
C16Node *wapp_c16_list_remove(C16List *list, u64 index);
|
|
||||||
void wapp_c16_list_empty(C16List *list);
|
|
||||||
C32Node *wapp_c32_list_get(const C32List *list, u64 index);
|
|
||||||
void wapp_c32_list_push_front(C32List *list, C32Node *node);
|
|
||||||
void wapp_c32_list_push_back(C32List *list, C32Node *node);
|
|
||||||
void wapp_c32_list_insert(C32List *list, C32Node *node, u64 index);
|
|
||||||
C32Node *wapp_c32_list_pop_front(C32List *list);
|
|
||||||
C32Node *wapp_c32_list_pop_back(C32List *list);
|
|
||||||
C32Node *wapp_c32_list_remove(C32List *list, u64 index);
|
|
||||||
void wapp_c32_list_empty(C32List *list);
|
|
||||||
I8Node *wapp_i8_list_get(const I8List *list, u64 index);
|
|
||||||
void wapp_i8_list_push_front(I8List *list, I8Node *node);
|
|
||||||
void wapp_i8_list_push_back(I8List *list, I8Node *node);
|
|
||||||
void wapp_i8_list_insert(I8List *list, I8Node *node, u64 index);
|
|
||||||
I8Node *wapp_i8_list_pop_front(I8List *list);
|
|
||||||
I8Node *wapp_i8_list_pop_back(I8List *list);
|
|
||||||
I8Node *wapp_i8_list_remove(I8List *list, u64 index);
|
|
||||||
void wapp_i8_list_empty(I8List *list);
|
|
||||||
I16Node *wapp_i16_list_get(const I16List *list, u64 index);
|
|
||||||
void wapp_i16_list_push_front(I16List *list, I16Node *node);
|
|
||||||
void wapp_i16_list_push_back(I16List *list, I16Node *node);
|
|
||||||
void wapp_i16_list_insert(I16List *list, I16Node *node, u64 index);
|
|
||||||
I16Node *wapp_i16_list_pop_front(I16List *list);
|
|
||||||
I16Node *wapp_i16_list_pop_back(I16List *list);
|
|
||||||
I16Node *wapp_i16_list_remove(I16List *list, u64 index);
|
|
||||||
void wapp_i16_list_empty(I16List *list);
|
|
||||||
I32Node *wapp_i32_list_get(const I32List *list, u64 index);
|
|
||||||
void wapp_i32_list_push_front(I32List *list, I32Node *node);
|
|
||||||
void wapp_i32_list_push_back(I32List *list, I32Node *node);
|
|
||||||
void wapp_i32_list_insert(I32List *list, I32Node *node, u64 index);
|
|
||||||
I32Node *wapp_i32_list_pop_front(I32List *list);
|
|
||||||
I32Node *wapp_i32_list_pop_back(I32List *list);
|
|
||||||
I32Node *wapp_i32_list_remove(I32List *list, u64 index);
|
|
||||||
void wapp_i32_list_empty(I32List *list);
|
|
||||||
I64Node *wapp_i64_list_get(const I64List *list, u64 index);
|
|
||||||
void wapp_i64_list_push_front(I64List *list, I64Node *node);
|
|
||||||
void wapp_i64_list_push_back(I64List *list, I64Node *node);
|
|
||||||
void wapp_i64_list_insert(I64List *list, I64Node *node, u64 index);
|
|
||||||
I64Node *wapp_i64_list_pop_front(I64List *list);
|
|
||||||
I64Node *wapp_i64_list_pop_back(I64List *list);
|
|
||||||
I64Node *wapp_i64_list_remove(I64List *list, u64 index);
|
|
||||||
void wapp_i64_list_empty(I64List *list);
|
|
||||||
U8Node *wapp_u8_list_get(const U8List *list, u64 index);
|
|
||||||
void wapp_u8_list_push_front(U8List *list, U8Node *node);
|
|
||||||
void wapp_u8_list_push_back(U8List *list, U8Node *node);
|
|
||||||
void wapp_u8_list_insert(U8List *list, U8Node *node, u64 index);
|
|
||||||
U8Node *wapp_u8_list_pop_front(U8List *list);
|
|
||||||
U8Node *wapp_u8_list_pop_back(U8List *list);
|
|
||||||
U8Node *wapp_u8_list_remove(U8List *list, u64 index);
|
|
||||||
void wapp_u8_list_empty(U8List *list);
|
|
||||||
U16Node *wapp_u16_list_get(const U16List *list, u64 index);
|
|
||||||
void wapp_u16_list_push_front(U16List *list, U16Node *node);
|
|
||||||
void wapp_u16_list_push_back(U16List *list, U16Node *node);
|
|
||||||
void wapp_u16_list_insert(U16List *list, U16Node *node, u64 index);
|
|
||||||
U16Node *wapp_u16_list_pop_front(U16List *list);
|
|
||||||
U16Node *wapp_u16_list_pop_back(U16List *list);
|
|
||||||
U16Node *wapp_u16_list_remove(U16List *list, u64 index);
|
|
||||||
void wapp_u16_list_empty(U16List *list);
|
|
||||||
U32Node *wapp_u32_list_get(const U32List *list, u64 index);
|
|
||||||
void wapp_u32_list_push_front(U32List *list, U32Node *node);
|
|
||||||
void wapp_u32_list_push_back(U32List *list, U32Node *node);
|
|
||||||
void wapp_u32_list_insert(U32List *list, U32Node *node, u64 index);
|
|
||||||
U32Node *wapp_u32_list_pop_front(U32List *list);
|
|
||||||
U32Node *wapp_u32_list_pop_back(U32List *list);
|
|
||||||
U32Node *wapp_u32_list_remove(U32List *list, u64 index);
|
|
||||||
void wapp_u32_list_empty(U32List *list);
|
|
||||||
U64Node *wapp_u64_list_get(const U64List *list, u64 index);
|
|
||||||
void wapp_u64_list_push_front(U64List *list, U64Node *node);
|
|
||||||
void wapp_u64_list_push_back(U64List *list, U64Node *node);
|
|
||||||
void wapp_u64_list_insert(U64List *list, U64Node *node, u64 index);
|
|
||||||
U64Node *wapp_u64_list_pop_front(U64List *list);
|
|
||||||
U64Node *wapp_u64_list_pop_back(U64List *list);
|
|
||||||
U64Node *wapp_u64_list_remove(U64List *list, u64 index);
|
|
||||||
void wapp_u64_list_empty(U64List *list);
|
|
||||||
F32Node *wapp_f32_list_get(const F32List *list, u64 index);
|
|
||||||
void wapp_f32_list_push_front(F32List *list, F32Node *node);
|
|
||||||
void wapp_f32_list_push_back(F32List *list, F32Node *node);
|
|
||||||
void wapp_f32_list_insert(F32List *list, F32Node *node, u64 index);
|
|
||||||
F32Node *wapp_f32_list_pop_front(F32List *list);
|
|
||||||
F32Node *wapp_f32_list_pop_back(F32List *list);
|
|
||||||
F32Node *wapp_f32_list_remove(F32List *list, u64 index);
|
|
||||||
void wapp_f32_list_empty(F32List *list);
|
|
||||||
F64Node *wapp_f64_list_get(const F64List *list, u64 index);
|
|
||||||
void wapp_f64_list_push_front(F64List *list, F64Node *node);
|
|
||||||
void wapp_f64_list_push_back(F64List *list, F64Node *node);
|
|
||||||
void wapp_f64_list_insert(F64List *list, F64Node *node, u64 index);
|
|
||||||
F64Node *wapp_f64_list_pop_front(F64List *list);
|
|
||||||
F64Node *wapp_f64_list_pop_back(F64List *list);
|
|
||||||
F64Node *wapp_f64_list_remove(F64List *list, u64 index);
|
|
||||||
void wapp_f64_list_empty(F64List *list);
|
|
||||||
F128Node *wapp_f128_list_get(const F128List *list, u64 index);
|
|
||||||
void wapp_f128_list_push_front(F128List *list, F128Node *node);
|
|
||||||
void wapp_f128_list_push_back(F128List *list, F128Node *node);
|
|
||||||
void wapp_f128_list_insert(F128List *list, F128Node *node, u64 index);
|
|
||||||
F128Node *wapp_f128_list_pop_front(F128List *list);
|
|
||||||
F128Node *wapp_f128_list_pop_back(F128List *list);
|
|
||||||
F128Node *wapp_f128_list_remove(F128List *list, u64 index);
|
|
||||||
void wapp_f128_list_empty(F128List *list);
|
|
||||||
IptrNode *wapp_iptr_list_get(const IptrList *list, u64 index);
|
|
||||||
void wapp_iptr_list_push_front(IptrList *list, IptrNode *node);
|
|
||||||
void wapp_iptr_list_push_back(IptrList *list, IptrNode *node);
|
|
||||||
void wapp_iptr_list_insert(IptrList *list, IptrNode *node, u64 index);
|
|
||||||
IptrNode *wapp_iptr_list_pop_front(IptrList *list);
|
|
||||||
IptrNode *wapp_iptr_list_pop_back(IptrList *list);
|
|
||||||
IptrNode *wapp_iptr_list_remove(IptrList *list, u64 index);
|
|
||||||
void wapp_iptr_list_empty(IptrList *list);
|
|
||||||
UptrNode *wapp_uptr_list_get(const UptrList *list, u64 index);
|
|
||||||
void wapp_uptr_list_push_front(UptrList *list, UptrNode *node);
|
|
||||||
void wapp_uptr_list_push_back(UptrList *list, UptrNode *node);
|
|
||||||
void wapp_uptr_list_insert(UptrList *list, UptrNode *node, u64 index);
|
|
||||||
UptrNode *wapp_uptr_list_pop_front(UptrList *list);
|
|
||||||
UptrNode *wapp_uptr_list_pop_back(UptrList *list);
|
|
||||||
UptrNode *wapp_uptr_list_remove(UptrList *list, u64 index);
|
|
||||||
void wapp_uptr_list_empty(UptrList *list);
|
|
||||||
|
|
||||||
#ifdef WAPP_PLATFORM_CPP
|
#ifdef WAPP_PLATFORM_CPP
|
||||||
END_C_LINKAGE
|
END_C_LINKAGE
|
||||||
|
|||||||
@@ -6,30 +6,30 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
void *wapp_mem_allocator_alloc(const Allocator *allocator, u64 size) {
|
void *wapp_mem_allocator_alloc(const Allocator *allocator, u64 size) {
|
||||||
wapp_debug_assert(allocator != NULL && (allocator->alloc) != NULL, "`allocator` and `allocator->alloc` should not be NULL");
|
wapp_debug_assert(allocator != NULL && (allocator->alloc) != NULL, "`allocator` and `allocator->alloc` should not be NULL");
|
||||||
return allocator->alloc(size, allocator->obj);
|
return allocator->alloc(size, allocator->obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
void *wapp_mem_allocator_alloc_aligned(const Allocator *allocator, u64 size, u64 alignment) {
|
void *wapp_mem_allocator_alloc_aligned(const Allocator *allocator, u64 size, u64 alignment) {
|
||||||
wapp_debug_assert(allocator != NULL && (allocator->alloc_aligned) != NULL, "`allocator` and `allocator->alloc_aligned` should not be NULL");
|
wapp_debug_assert(allocator != NULL && (allocator->alloc_aligned) != NULL, "`allocator` and `allocator->alloc_aligned` should not be NULL");
|
||||||
return allocator->alloc_aligned(size, alignment, allocator->obj);
|
return allocator->alloc_aligned(size, alignment, allocator->obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
void *wapp_mem_allocator_realloc(const Allocator *allocator, void *ptr, u64 old_size, u64 new_size) {
|
void *wapp_mem_allocator_realloc(const Allocator *allocator, void *ptr, u64 old_size, u64 new_size) {
|
||||||
wapp_debug_assert(allocator != NULL && (allocator->realloc) != NULL, "`allocator` and `allocator->realloc` should not be NULL");
|
wapp_debug_assert(allocator != NULL && (allocator->realloc) != NULL, "`allocator` and `allocator->realloc` should not be NULL");
|
||||||
return allocator->realloc(ptr, old_size, new_size, allocator->obj);
|
return allocator->realloc(ptr, old_size, new_size, allocator->obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
void *wapp_mem_allocator_realloc_aligned(const Allocator *allocator, void *ptr, u64 old_size,
|
void *wapp_mem_allocator_realloc_aligned(const Allocator *allocator, void *ptr, u64 old_size,
|
||||||
u64 new_size, u64 alignment) {
|
u64 new_size, u64 alignment) {
|
||||||
wapp_debug_assert(allocator != NULL && (allocator->realloc_aligned) != NULL, "`allocator` and `allocator->realloc_aligned` should not be NULL");
|
wapp_debug_assert(allocator != NULL && (allocator->realloc_aligned) != NULL, "`allocator` and `allocator->realloc_aligned` should not be NULL");
|
||||||
return allocator->realloc_aligned(ptr, old_size, new_size, alignment, allocator->obj);
|
return allocator->realloc_aligned(ptr, old_size, new_size, alignment, allocator->obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
void wapp_mem_allocator_free(const Allocator *allocator, void **ptr, u64 size) {
|
void wapp_mem_allocator_free(const Allocator *allocator, void **ptr, u64 size) {
|
||||||
if (!allocator || !(allocator->free)) {
|
if (!allocator || !(allocator->free)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
allocator->free(ptr, size, allocator->obj);
|
allocator->free(ptr, size, allocator->obj);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,26 +11,26 @@
|
|||||||
BEGIN_C_LINKAGE
|
BEGIN_C_LINKAGE
|
||||||
#endif // !WAPP_PLATFORM_CPP
|
#endif // !WAPP_PLATFORM_CPP
|
||||||
|
|
||||||
typedef void *(MemAllocFunc)(u64 size, void *alloc_obj);
|
typedef void *(MemAllocFunc)(u64 size, void *alloc_obj);
|
||||||
typedef void *(MemAllocAlignedFunc)(u64 size, u64 alignment, void *alloc_obj);
|
typedef void *(MemAllocAlignedFunc)(u64 size, u64 alignment, void *alloc_obj);
|
||||||
typedef void *(MemReallocFunc)(void *ptr, u64 old_size, u64 new_size, void *alloc_obj);
|
typedef void *(MemReallocFunc)(void *ptr, u64 old_size, u64 new_size, void *alloc_obj);
|
||||||
typedef void *(MemReallocAlignedFunc)(void *ptr, u64 old_size, u64 new_size, u64 alignment, void *alloc_obj);
|
typedef void *(MemReallocAlignedFunc)(void *ptr, u64 old_size, u64 new_size, u64 alignment, void *alloc_obj);
|
||||||
typedef void (MemFreeFunc)(void **ptr, u64 size, void *alloc_obj);
|
typedef void (MemFreeFunc)(void **ptr, u64 size, void *alloc_obj);
|
||||||
|
|
||||||
typedef struct allocator Allocator;
|
typedef struct Allocator Allocator;
|
||||||
struct allocator {
|
struct Allocator {
|
||||||
void *obj;
|
void *obj;
|
||||||
MemAllocFunc *alloc;
|
MemAllocFunc *alloc;
|
||||||
MemAllocAlignedFunc *alloc_aligned;
|
MemAllocAlignedFunc *alloc_aligned;
|
||||||
MemReallocFunc *realloc;
|
MemReallocFunc *realloc;
|
||||||
MemReallocAlignedFunc *realloc_aligned;
|
MemReallocAlignedFunc *realloc_aligned;
|
||||||
MemFreeFunc *free;
|
MemFreeFunc *free;
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifdef WAPP_PLATFORM_CPP
|
#ifdef WAPP_PLATFORM_CPP
|
||||||
#define wapp_mem_allocator_invalid(ALLOCATOR) ([&]() { \
|
#define wapp_mem_allocator_invalid(ALLOCATOR) ([&]() { \
|
||||||
Allocator alloc{}; \
|
Allocator alloc{}; \
|
||||||
return memcmp(ALLOCATOR, &alloc, sizeof(Allocator)) == 0; \
|
return memcmp(ALLOCATOR, &alloc, sizeof(Allocator)) == 0; \
|
||||||
}())
|
}())
|
||||||
#else
|
#else
|
||||||
#define wapp_mem_allocator_invalid(ALLOCATOR) (memcmp(ALLOCATOR, &((Allocator){0}), sizeof(Allocator)) == 0)
|
#define wapp_mem_allocator_invalid(ALLOCATOR) (memcmp(ALLOCATOR, &((Allocator){0}), sizeof(Allocator)) == 0)
|
||||||
|
|||||||
@@ -3,24 +3,23 @@
|
|||||||
#include "mem_utils.h"
|
#include "mem_utils.h"
|
||||||
#include "../../../common/aliases/aliases.h"
|
#include "../../../common/aliases/aliases.h"
|
||||||
#include "../../../common/assert/assert.h"
|
#include "../../../common/assert/assert.h"
|
||||||
|
#include "../../../common/misc/misc_utils.h"
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
|
|
||||||
wapp_intern b8 is_power_of_two(u64 num) { return (num & (num - 1)) == 0; }
|
|
||||||
|
|
||||||
void *wapp_mem_util_align_forward(void *ptr, u64 alignment) {
|
void *wapp_mem_util_align_forward(void *ptr, u64 alignment) {
|
||||||
wapp_debug_assert(ptr != NULL, "`ptr` should not be NULL");
|
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");
|
wapp_runtime_assert(wapp_is_power_of_two(alignment), "`alignment` value is not a power of two");
|
||||||
|
|
||||||
uptr p = (uptr)ptr;
|
uptr p = (uptr)ptr;
|
||||||
uptr align = (uptr)alignment;
|
uptr align = (uptr)alignment;
|
||||||
|
|
||||||
// Similar to p % align, but it's a faster implementation that works fine
|
// Similar to p % align, but it's a faster implementation that works fine
|
||||||
// because align is guaranteed to be a power of 2
|
// because align is guaranteed to be a power of 2
|
||||||
uptr modulo = p & (align - 1);
|
uptr modulo = p & (align - 1);
|
||||||
|
|
||||||
if (modulo != 0) {
|
if (modulo != 0) {
|
||||||
p += align - modulo;
|
p += align - modulo;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (void *)p;
|
return (void *)p;
|
||||||
}
|
}
|
||||||
|
|||||||
85
src/base/queue/queue.c
Normal file
85
src/base/queue/queue.c
Normal file
@@ -0,0 +1,85 @@
|
|||||||
|
// vim:fileencoding=utf-8:foldmethod=marker
|
||||||
|
|
||||||
|
#include "queue.h"
|
||||||
|
#include "../array/array.h"
|
||||||
|
#include "../../common/assert/assert.h"
|
||||||
|
#include "../../common/misc/misc_utils.h"
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
void _queue_push(GenericQueue *queue, void *item, u64 item_size) {
|
||||||
|
wapp_debug_assert(queue != NULL, "`queue` should not be NULL");
|
||||||
|
wapp_runtime_assert(item_size == wapp_array_item_size(queue->items), "Invalid type");
|
||||||
|
|
||||||
|
u64 capacity = wapp_array_capacity(queue->items);
|
||||||
|
if (queue->count >= capacity) { return; }
|
||||||
|
|
||||||
|
u64 index = (queue->back)++;
|
||||||
|
_array_set(queue->items, index, item, item_size);
|
||||||
|
++(queue->count);
|
||||||
|
|
||||||
|
if (queue->back >= capacity) {
|
||||||
|
queue->back = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
GenericQueue *_queue_push_alloc(const Allocator *allocator, GenericQueue *queue, void *item, u64 item_size) {
|
||||||
|
wapp_debug_assert(allocator != NULL && queue != NULL && item != NULL,
|
||||||
|
"`allocator`, `queue` and `item` should not be NULL");
|
||||||
|
wapp_runtime_assert(item_size == wapp_array_item_size(queue->items), "Invalid type");
|
||||||
|
|
||||||
|
GenericQueue *output = queue;
|
||||||
|
|
||||||
|
u64 capacity = wapp_array_capacity(queue->items);
|
||||||
|
if (queue->count >= capacity) {
|
||||||
|
u64 new_capacity = wapp_misc_utils_u64_round_up_pow2(capacity * 2);
|
||||||
|
u64 array_size = _array_calc_alloc_size(new_capacity, item_size);
|
||||||
|
u64 alloc_size = sizeof(GenericQueue) + array_size;
|
||||||
|
void *buffer = wapp_mem_allocator_alloc(allocator, alloc_size);
|
||||||
|
if (!buffer) {
|
||||||
|
goto RETURN_QUEUE_PUSH_ALLOC;
|
||||||
|
}
|
||||||
|
|
||||||
|
memset((void *)buffer, 0, alloc_size);
|
||||||
|
|
||||||
|
output = (GenericQueue *)buffer;
|
||||||
|
output->items = _array_from_preallocated_buffer((void *)(output + 1), array_size, ARRAY_INIT_FILLED, item_size);
|
||||||
|
|
||||||
|
// NOTE (Abdelrahman): When the queue is full, the front and back indices should
|
||||||
|
// always be the same
|
||||||
|
u64 front_count = capacity - queue->front;
|
||||||
|
u64 back_count = queue->back;
|
||||||
|
void *copy_boundary = (void *)((uptr)(queue->items) + (queue->front * item_size));
|
||||||
|
|
||||||
|
memcpy(output->items, copy_boundary, front_count * item_size);
|
||||||
|
if (back_count > 0) {
|
||||||
|
void *back_copy_dst = (void *)((uptr)(output->items) + (front_count * item_size));
|
||||||
|
memcpy(back_copy_dst, queue->items, back_count * item_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
output->front = 0;
|
||||||
|
output->back = front_count + back_count;
|
||||||
|
output->count = queue->count;
|
||||||
|
}
|
||||||
|
|
||||||
|
_queue_push(output, item, item_size);
|
||||||
|
|
||||||
|
RETURN_QUEUE_PUSH_ALLOC:
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
||||||
|
void *_queue_pop(GenericQueue *queue, u64 item_size) {
|
||||||
|
wapp_debug_assert(queue != NULL, "`queue` should not be NULL");
|
||||||
|
wapp_runtime_assert(item_size == wapp_array_item_size(queue->items), "Invalid type");
|
||||||
|
|
||||||
|
if (queue->count == 0) { return NULL; }
|
||||||
|
|
||||||
|
u64 index = (queue->front)++;
|
||||||
|
--(queue->count);
|
||||||
|
|
||||||
|
u64 capacity = wapp_array_capacity(queue->items);
|
||||||
|
if (queue->front >= capacity) {
|
||||||
|
queue->front = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return _array_get(queue->items, index, item_size);
|
||||||
|
}
|
||||||
100
src/base/queue/queue.h
Normal file
100
src/base/queue/queue.h
Normal file
@@ -0,0 +1,100 @@
|
|||||||
|
// vim:fileencoding=utf-8:foldmethod=marker
|
||||||
|
|
||||||
|
#ifndef QUEUE_H
|
||||||
|
#define QUEUE_H
|
||||||
|
|
||||||
|
#include "../array/array.h"
|
||||||
|
#include "../mem/allocator/mem_allocator.h"
|
||||||
|
#include "../../common/aliases/aliases.h"
|
||||||
|
#include "../../common/platform/platform.h"
|
||||||
|
|
||||||
|
#ifdef WAPP_PLATFORM_CPP
|
||||||
|
BEGIN_C_LINKAGE
|
||||||
|
#endif // !WAPP_PLATFORM_CPP
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
GenericArray items;
|
||||||
|
u64 front;
|
||||||
|
u64 back;
|
||||||
|
u64 count;
|
||||||
|
} GenericQueue;
|
||||||
|
|
||||||
|
// NOTE (Abdelrahman): GenericQueue typedefs for readability
|
||||||
|
typedef GenericQueue VoidPtrQueue;
|
||||||
|
typedef GenericQueue C8Queue;
|
||||||
|
typedef GenericQueue C16Queue;
|
||||||
|
typedef GenericQueue C32Queue;
|
||||||
|
typedef GenericQueue U8Queue;
|
||||||
|
typedef GenericQueue U16Queue;
|
||||||
|
typedef GenericQueue U32Queue;
|
||||||
|
typedef GenericQueue U64Queue;
|
||||||
|
typedef GenericQueue B8Queue;
|
||||||
|
typedef GenericQueue I8Queue;
|
||||||
|
typedef GenericQueue I16Queue;
|
||||||
|
typedef GenericQueue I32Queue;
|
||||||
|
typedef GenericQueue I64Queue;
|
||||||
|
typedef GenericQueue F32Queue;
|
||||||
|
typedef GenericQueue F64Queue;
|
||||||
|
typedef GenericQueue F128Queue;
|
||||||
|
typedef GenericQueue UptrQueue;
|
||||||
|
typedef GenericQueue IptrQueue;
|
||||||
|
typedef GenericQueue Str8Queue;
|
||||||
|
|
||||||
|
#ifdef WAPP_PLATFORM_CPP
|
||||||
|
#define wapp_queue(TYPE, CAPACITY) ([&]() { \
|
||||||
|
wapp_persist GenericArray arr = wapp_array_with_capacity(TYPE, CAPACITY, ARRAY_INIT_FILLED); \
|
||||||
|
wapp_persist GenericQueue queue = { \
|
||||||
|
arr, \
|
||||||
|
0, \
|
||||||
|
0, \
|
||||||
|
0, \
|
||||||
|
}; \
|
||||||
|
\
|
||||||
|
return queue; \
|
||||||
|
}())
|
||||||
|
#define wapp_queue_alloc(TYPE, ALLOCATOR_PTR, CAPACITY) ([&]() { \
|
||||||
|
wapp_persist GenericQueue queue = { \
|
||||||
|
wapp_array_alloc_capacity(TYPE, ALLOCATOR_PTR, CAPACITY, ARRAY_INIT_FILLED), \
|
||||||
|
0, \
|
||||||
|
0, \
|
||||||
|
0, \
|
||||||
|
}; \
|
||||||
|
\
|
||||||
|
return queue; \
|
||||||
|
}())
|
||||||
|
#else
|
||||||
|
#define wapp_queue(TYPE, CAPACITY) ((GenericQueue){ \
|
||||||
|
.items = wapp_array_with_capacity(TYPE, CAPACITY, ARRAY_INIT_FILLED), \
|
||||||
|
.front = 0, \
|
||||||
|
.back = 0, \
|
||||||
|
.count = 0, \
|
||||||
|
})
|
||||||
|
#define wapp_queue_alloc(TYPE, ALLOCATOR_PTR, CAPACITY) ((GenericQueue){ \
|
||||||
|
.items = wapp_array_alloc_capacity(TYPE, ALLOCATOR_PTR, CAPACITY, ARRAY_INIT_FILLED), \
|
||||||
|
.front = 0, \
|
||||||
|
.back = 0, \
|
||||||
|
.count = 0, \
|
||||||
|
})
|
||||||
|
#endif // !WAPP_PLATFORM_CPP
|
||||||
|
|
||||||
|
#define wapp_queue_capacity(QUEUE_PTR) (wapp_array_capacity((QUEUE_PTR)->items))
|
||||||
|
#define wapp_queue_item_size(QUEUE_PTR) (wapp_array_item_size((QUEUE_PTR)->items))
|
||||||
|
#define wapp_queue_push(TYPE, QUEUE_PTR, VALUE_PTR) ( \
|
||||||
|
_queue_push(QUEUE_PTR, VALUE_PTR, sizeof(TYPE)) \
|
||||||
|
)
|
||||||
|
#define wapp_queue_push_alloc(TYPE, ALLOCATOR_PTR, QUEUE_PTR, VALUE_PTR) ( \
|
||||||
|
_queue_push_alloc(ALLOCATOR_PTR, QUEUE_PTR, VALUE_PTR, sizeof(TYPE)) \
|
||||||
|
)
|
||||||
|
#define wapp_queue_pop(TYPE, QUEUE_PTR) ( \
|
||||||
|
(TYPE *)_queue_pop(QUEUE_PTR, sizeof(TYPE)) \
|
||||||
|
)
|
||||||
|
|
||||||
|
void _queue_push(GenericQueue *queue, void *item, u64 item_size);
|
||||||
|
GenericQueue *_queue_push_alloc(const Allocator *allocator, GenericQueue *queue, void *item, u64 item_size);
|
||||||
|
void *_queue_pop(GenericQueue *queue, u64 item_size);
|
||||||
|
|
||||||
|
#ifdef WAPP_PLATFORM_CPP
|
||||||
|
END_C_LINKAGE
|
||||||
|
#endif // !WAPP_PLATFORM_CPP
|
||||||
|
|
||||||
|
#endif // !QUEUE_H
|
||||||
@@ -14,479 +14,467 @@
|
|||||||
#define STR8_BUF_ALLOC_SIZE(CAPACITY) (sizeof(Str8) + sizeof(c8) * CAPACITY)
|
#define STR8_BUF_ALLOC_SIZE(CAPACITY) (sizeof(Str8) + sizeof(c8) * CAPACITY)
|
||||||
|
|
||||||
Str8 *wapp_str8_alloc_buf(const Allocator *allocator, u64 capacity) {
|
Str8 *wapp_str8_alloc_buf(const Allocator *allocator, u64 capacity) {
|
||||||
wapp_debug_assert(allocator != NULL, "`allocator` should not be NULL");
|
wapp_debug_assert(allocator != NULL, "`allocator` should not be NULL");
|
||||||
|
|
||||||
Str8 *str = wapp_mem_allocator_alloc(allocator, STR8_BUF_ALLOC_SIZE(capacity));
|
Str8 *str = wapp_mem_allocator_alloc(allocator, STR8_BUF_ALLOC_SIZE(capacity));
|
||||||
if (!str) {
|
if (!str) {
|
||||||
goto RETURN_STR8;
|
goto RETURN_STR8;
|
||||||
}
|
}
|
||||||
|
|
||||||
str->buf = (u8 *)str + sizeof(Str8);
|
str->buf = (u8 *)str + sizeof(Str8);
|
||||||
str->size = 0;
|
str->size = 0;
|
||||||
str->capacity = capacity;
|
str->capacity = capacity;
|
||||||
|
|
||||||
RETURN_STR8:
|
RETURN_STR8:
|
||||||
return str;
|
return str;
|
||||||
}
|
}
|
||||||
|
|
||||||
Str8 *wapp_str8_alloc_and_fill_buf(const Allocator *allocator, u64 capacity) {
|
Str8 *wapp_str8_alloc_and_fill_buf(const Allocator *allocator, u64 capacity) {
|
||||||
Str8 *out = wapp_str8_alloc_buf(allocator, capacity);
|
Str8 *out = wapp_str8_alloc_buf(allocator, capacity);
|
||||||
if (out) {
|
if (out) {
|
||||||
memset(out->buf, 0, capacity);
|
memset(out->buf, 0, capacity);
|
||||||
out->size = capacity;
|
out->size = capacity;
|
||||||
}
|
}
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
Str8 *wapp_str8_alloc_cstr(const Allocator *allocator, const char *str) {
|
Str8 *wapp_str8_alloc_cstr(const Allocator *allocator, const char *str) {
|
||||||
wapp_debug_assert(allocator != NULL && str != NULL, "`allocator` and `str` should not be NULL");
|
wapp_debug_assert(allocator != NULL && str != NULL, "`allocator` and `str` should not be NULL");
|
||||||
|
|
||||||
u64 length = strlen(str);
|
u64 length = strlen(str);
|
||||||
Str8 *output = wapp_str8_alloc_buf(allocator, length * 2);
|
Str8 *output = wapp_str8_alloc_buf(allocator, length * 2);
|
||||||
if (!output) {
|
if (!output) {
|
||||||
goto RETURN_ALLOC_CSTR;
|
goto RETURN_ALLOC_CSTR;
|
||||||
}
|
}
|
||||||
|
|
||||||
output->size = length;
|
output->size = length;
|
||||||
memcpy(output->buf, str, length);
|
memcpy(output->buf, str, length);
|
||||||
|
|
||||||
RETURN_ALLOC_CSTR:
|
RETURN_ALLOC_CSTR:
|
||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
|
|
||||||
Str8 *wapp_str8_alloc_str8(const Allocator *allocator, Str8RO *str) {
|
Str8 *wapp_str8_alloc_str8(const Allocator *allocator, Str8RO *str) {
|
||||||
wapp_debug_assert(allocator != NULL && str != NULL, "`allocator` and `str` should not be NULL");
|
wapp_debug_assert(allocator != NULL && str != NULL, "`allocator` and `str` should not be NULL");
|
||||||
|
|
||||||
Str8 *output = wapp_str8_alloc_buf(allocator, str->capacity);
|
Str8 *output = wapp_str8_alloc_buf(allocator, str->capacity);
|
||||||
if (!output) {
|
if (!output) {
|
||||||
goto RETURN_ALLOC_STR8;
|
goto RETURN_ALLOC_STR8;
|
||||||
}
|
}
|
||||||
|
|
||||||
output->size = str->size;
|
output->size = str->size;
|
||||||
memcpy(output->buf, str->buf, str->size);
|
memcpy(output->buf, str->buf, str->size);
|
||||||
|
|
||||||
RETURN_ALLOC_STR8:
|
RETURN_ALLOC_STR8:
|
||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
|
|
||||||
Str8 *wapp_str8_alloc_substr(const Allocator *allocator, Str8RO *str, u64 start, u64 end) {
|
Str8 *wapp_str8_alloc_substr(const Allocator *allocator, Str8RO *str, u64 start, u64 end) {
|
||||||
wapp_debug_assert(allocator != NULL && str != NULL, "`allocator` and `str` should not be NULL");
|
wapp_debug_assert(allocator != NULL && str != NULL, "`allocator` and `str` should not be NULL");
|
||||||
|
|
||||||
Str8 *output = NULL;
|
Str8 *output = NULL;
|
||||||
|
|
||||||
if (start >= str->size || start >= end) {
|
if (start >= str->size || start >= end) {
|
||||||
goto RETURN_ALLOC_SUBSTR;
|
goto RETURN_ALLOC_SUBSTR;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (end > str->size) {
|
if (end > str->size) {
|
||||||
end = str->size;
|
end = str->size;
|
||||||
}
|
}
|
||||||
|
|
||||||
output = wapp_str8_alloc_buf(allocator, str->capacity);
|
output = wapp_str8_alloc_buf(allocator, str->capacity);
|
||||||
if (!output) {
|
if (!output) {
|
||||||
goto RETURN_ALLOC_SUBSTR;
|
goto RETURN_ALLOC_SUBSTR;
|
||||||
}
|
}
|
||||||
|
|
||||||
output->size = end - start;
|
output->size = end - start;
|
||||||
memcpy(output->buf, str->buf + start, output->size);
|
memcpy(output->buf, str->buf + start, output->size);
|
||||||
|
|
||||||
RETURN_ALLOC_SUBSTR:
|
RETURN_ALLOC_SUBSTR:
|
||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
|
|
||||||
void wapp_str8_dealloc_buf(const Allocator *allocator, Str8 **str) {
|
void wapp_str8_dealloc_buf(const Allocator *allocator, Str8 **str) {
|
||||||
wapp_debug_assert(allocator != NULL && str != NULL && (*str) != NULL, "Either `allocator` is NULL or `str` is an invalid double pointer");
|
wapp_debug_assert(allocator != NULL && str != NULL && (*str) != NULL, "Either `allocator` is NULL or `str` is an invalid double pointer");
|
||||||
wapp_mem_allocator_free(allocator, (void **)str, STR8_BUF_ALLOC_SIZE((*str)->capacity));
|
wapp_mem_allocator_free(allocator, (void **)str, STR8_BUF_ALLOC_SIZE((*str)->capacity));
|
||||||
}
|
}
|
||||||
|
|
||||||
c8 wapp_str8_get(const Str8 *str, u64 index) {
|
c8 wapp_str8_get(const Str8 *str, u64 index) {
|
||||||
if (index >= str->size) {
|
if (index >= str->size) {
|
||||||
return '\0';
|
return '\0';
|
||||||
}
|
}
|
||||||
|
|
||||||
return str->buf[index];
|
return str->buf[index];
|
||||||
}
|
}
|
||||||
|
|
||||||
void wapp_str8_set(Str8 *str, u64 index, c8 c) {
|
void wapp_str8_set(Str8 *str, u64 index, c8 c) {
|
||||||
if (index >= str->size) {
|
if (index >= str->size) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
str->buf[index] = c;
|
str->buf[index] = c;
|
||||||
}
|
}
|
||||||
|
|
||||||
void wapp_str8_push_back(Str8 *str, c8 c) {
|
void wapp_str8_push_back(Str8 *str, c8 c) {
|
||||||
if (!(str->size < str->capacity)) {
|
if (!(str->size < str->capacity)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
u64 index = (str->size)++;
|
u64 index = (str->size)++;
|
||||||
wapp_str8_set(str, index, c);
|
wapp_str8_set(str, index, c);
|
||||||
}
|
}
|
||||||
|
|
||||||
b8 wapp_str8_equal(Str8RO *s1, Str8RO *s2) {
|
b8 wapp_str8_equal(Str8RO *s1, Str8RO *s2) {
|
||||||
if (s1->size != s2->size) {
|
if (s1->size != s2->size) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return wapp_str8_equal_to_count(s1, s2, s1->size);
|
return wapp_str8_equal_to_count(s1, s2, s1->size);
|
||||||
}
|
}
|
||||||
|
|
||||||
b8 wapp_str8_equal_to_count(Str8RO* s1, Str8RO* s2, u64 count) {
|
b8 wapp_str8_equal_to_count(Str8RO* s1, Str8RO* s2, u64 count) {
|
||||||
if (!s1 || !s2) {
|
if (!s1 || !s2) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return memcmp(s1->buf, s2->buf, count) == 0;
|
return memcmp(s1->buf, s2->buf, count) == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
Str8 wapp_str8_slice(Str8RO *str, u64 start, u64 end) {
|
Str8 wapp_str8_slice(Str8RO *str, u64 start, u64 end) {
|
||||||
if (start >= str->size || start >= end) {
|
if (start >= str->size || start >= end) {
|
||||||
start = str->size;
|
start = str->size;
|
||||||
end = str->size;
|
end = str->size;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (end > str->size) {
|
if (end > str->size) {
|
||||||
end = str->size;
|
end = str->size;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (Str8RO){
|
return (Str8RO){
|
||||||
.capacity = end - start,
|
.capacity = end - start,
|
||||||
.size = end - start,
|
.size = end - start,
|
||||||
.buf = str->buf + start,
|
.buf = str->buf + start,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
Str8 *wapp_str8_alloc_concat(const Allocator *allocator, Str8 *dst, Str8RO *src) {
|
Str8 *wapp_str8_alloc_concat(const Allocator *allocator, Str8 *dst, Str8RO *src) {
|
||||||
wapp_debug_assert(allocator != NULL && dst != NULL && src != NULL, "`allocator`, `dst` and `src` should not be NULL");
|
wapp_debug_assert(allocator != NULL && dst != NULL && src != NULL, "`allocator`, `dst` and `src` should not be NULL");
|
||||||
|
|
||||||
Str8 *output = NULL;
|
Str8 *output = NULL;
|
||||||
u64 remaining = dst->capacity - dst->size;
|
u64 remaining = dst->capacity - dst->size;
|
||||||
if (src->size <= remaining) {
|
if (src->size <= remaining) {
|
||||||
output = dst;
|
output = dst;
|
||||||
goto SOURCE_STRING_STR8_CONCAT;
|
goto SOURCE_STRING_STR8_CONCAT;
|
||||||
}
|
}
|
||||||
|
|
||||||
u64 capacity = dst->capacity + src->size;
|
u64 capacity = dst->capacity + src->size;
|
||||||
|
|
||||||
output = wapp_str8_alloc_buf(allocator, capacity);
|
output = wapp_str8_alloc_buf(allocator, capacity);
|
||||||
if (!output) {
|
if (!output) {
|
||||||
goto RETURN_STR8_CONCAT;
|
goto RETURN_STR8_CONCAT;
|
||||||
}
|
}
|
||||||
|
|
||||||
wapp_str8_concat_capped(output, dst);
|
wapp_str8_concat_capped(output, dst);
|
||||||
|
|
||||||
SOURCE_STRING_STR8_CONCAT:
|
SOURCE_STRING_STR8_CONCAT:
|
||||||
wapp_str8_concat_capped(output, src);
|
wapp_str8_concat_capped(output, src);
|
||||||
|
|
||||||
RETURN_STR8_CONCAT:
|
RETURN_STR8_CONCAT:
|
||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
|
|
||||||
void wapp_str8_concat_capped(Str8 *dst, Str8RO *src) {
|
void wapp_str8_concat_capped(Str8 *dst, Str8RO *src) {
|
||||||
wapp_debug_assert(dst != NULL && src != NULL, "`dst` and `src` should not be NULL");
|
wapp_debug_assert(dst != NULL && src != NULL, "`dst` and `src` should not be NULL");
|
||||||
|
|
||||||
u64 remaining = dst->capacity - dst->size;
|
u64 remaining = dst->capacity - dst->size;
|
||||||
u64 to_copy = remaining < src->size ? remaining : src->size;
|
u64 to_copy = remaining < src->size ? remaining : src->size;
|
||||||
|
|
||||||
memcpy(dst->buf + dst->size, src->buf, to_copy);
|
memcpy(dst->buf + dst->size, src->buf, to_copy);
|
||||||
dst->size += to_copy;
|
dst->size += to_copy;
|
||||||
}
|
}
|
||||||
|
|
||||||
void wapp_str8_copy_cstr_capped(Str8 *dst, const char *src) {
|
void wapp_str8_copy_cstr_capped(Str8 *dst, const char *src) {
|
||||||
wapp_debug_assert(dst != NULL && src != NULL, "`dst` and `src` should not be NULL");
|
wapp_debug_assert(dst != NULL && src != NULL, "`dst` and `src` should not be NULL");
|
||||||
|
|
||||||
u64 length = strlen(src);
|
u64 length = strlen(src);
|
||||||
u64 to_copy = length <= dst->capacity ? length : dst->capacity;
|
u64 to_copy = length <= dst->capacity ? length : dst->capacity;
|
||||||
|
|
||||||
memset(dst->buf, 0, dst->size);
|
memset(dst->buf, 0, dst->size);
|
||||||
memcpy(dst->buf, src, to_copy);
|
memcpy(dst->buf, src, to_copy);
|
||||||
dst->size = to_copy;
|
dst->size = to_copy;
|
||||||
}
|
}
|
||||||
|
|
||||||
void wapp_str8_copy_str8_capped(Str8 *dst, Str8RO *src) {
|
void wapp_str8_copy_str8_capped(Str8 *dst, Str8RO *src) {
|
||||||
wapp_debug_assert(dst != NULL && src != NULL, "`dst` and `src` should not be NULL");
|
wapp_debug_assert(dst != NULL && src != NULL, "`dst` and `src` should not be NULL");
|
||||||
|
|
||||||
u64 to_copy = src->size <= dst->capacity ? src->size : dst->capacity;
|
u64 to_copy = src->size <= dst->capacity ? src->size : dst->capacity;
|
||||||
|
|
||||||
memset(dst->buf, 0, dst->size);
|
memset(dst->buf, 0, dst->size);
|
||||||
memcpy(dst->buf, src->buf, to_copy);
|
memcpy(dst->buf, src->buf, to_copy);
|
||||||
dst->size = to_copy;
|
dst->size = to_copy;
|
||||||
}
|
}
|
||||||
|
|
||||||
void wapp_str8_copy_to_cstr(char *dst, Str8RO *src, u64 dst_capacity) {
|
void wapp_str8_copy_to_cstr(char *dst, Str8RO *src, u64 dst_capacity) {
|
||||||
wapp_debug_assert(dst != NULL && src != NULL, "`dst` and `src` should not be NULL");
|
wapp_debug_assert(dst != NULL && src != NULL, "`dst` and `src` should not be NULL");
|
||||||
|
|
||||||
u64 to_copy = src->size < dst_capacity ? src->size : dst_capacity - 1;
|
u64 to_copy = src->size < dst_capacity ? src->size : dst_capacity - 1;
|
||||||
|
|
||||||
memset(dst, 0, dst_capacity);
|
memset(dst, 0, dst_capacity);
|
||||||
memcpy(dst, src->buf, to_copy);
|
memcpy(dst, src->buf, to_copy);
|
||||||
}
|
}
|
||||||
|
|
||||||
void wapp_str8_format(Str8 *dst, const char *format, ...) {
|
void wapp_str8_format(Str8 *dst, const char *format, ...) {
|
||||||
wapp_debug_assert(dst != NULL && format != NULL, "`dst` and `format` should not be NULL");
|
wapp_debug_assert(dst != NULL && format != NULL, "`dst` and `format` should not be NULL");
|
||||||
|
|
||||||
va_list args1;
|
va_list args1;
|
||||||
va_list args2;
|
va_list args2;
|
||||||
|
|
||||||
va_start(args1, format);
|
va_start(args1, format);
|
||||||
va_copy(args2, args1);
|
va_copy(args2, args1);
|
||||||
|
|
||||||
u64 total_size = vsnprintf(NULL, 0, format, args1);
|
u64 total_size = vsnprintf(NULL, 0, format, args1);
|
||||||
dst->size = total_size <= dst->capacity ? total_size : dst->capacity;
|
dst->size = total_size <= dst->capacity ? total_size : dst->capacity;
|
||||||
|
|
||||||
vsnprintf((char *)(dst->buf), dst->capacity, format, args2);
|
vsnprintf((char *)(dst->buf), dst->capacity, format, args2);
|
||||||
|
|
||||||
va_end(args1);
|
va_end(args1);
|
||||||
va_end(args2);
|
va_end(args2);
|
||||||
}
|
}
|
||||||
|
|
||||||
void wapp_str8_to_lower(Str8 *dst, Str8RO *src) {
|
void wapp_str8_to_lower(Str8 *dst, Str8RO *src) {
|
||||||
wapp_debug_assert(src != NULL && dst != NULL, "`dst` and `src` should not be NULL");
|
wapp_debug_assert(src != NULL && dst != NULL, "`dst` and `src` should not be NULL");
|
||||||
wapp_debug_assert(dst->capacity >= src->capacity, "`dst` does not have enough capacity");
|
wapp_debug_assert(dst->capacity >= src->capacity, "`dst` does not have enough capacity");
|
||||||
|
|
||||||
dst->size = src->size;
|
dst->size = src->size;
|
||||||
|
|
||||||
// NOTE (Abdelrahman): Uses a while loop instead of a for loop to get rid of
|
// NOTE (Abdelrahman): Uses a while loop instead of a for loop to get rid of
|
||||||
// MSVC Spectre mitigation warnings
|
// MSVC Spectre mitigation warnings
|
||||||
u64 index = 0;
|
u64 index = 0;
|
||||||
b8 running = true;
|
b8 running = true;
|
||||||
while (running) {
|
while (running) {
|
||||||
wapp_str8_set(dst, index, (u8)tolower(wapp_str8_get(src, index)));
|
wapp_str8_set(dst, index, (u8)tolower(wapp_str8_get(src, index)));
|
||||||
++index;
|
++index;
|
||||||
running = index < src->size;
|
running = index < src->size;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void wapp_str8_to_upper(Str8 *dst, Str8RO *src) {
|
void wapp_str8_to_upper(Str8 *dst, Str8RO *src) {
|
||||||
wapp_debug_assert(src != NULL && dst != NULL, "`dst` and `src` should not be NULL");
|
wapp_debug_assert(src != NULL && dst != NULL, "`dst` and `src` should not be NULL");
|
||||||
wapp_debug_assert(dst->capacity >= src->capacity, "`dst` does not have enough capacity");
|
wapp_debug_assert(dst->capacity >= src->capacity, "`dst` does not have enough capacity");
|
||||||
|
|
||||||
dst->size = src->size;
|
dst->size = src->size;
|
||||||
|
|
||||||
// NOTE (Abdelrahman): Uses a while loop instead of a for loop to get rid of
|
// NOTE (Abdelrahman): Uses a while loop instead of a for loop to get rid of
|
||||||
// MSVC Spectre mitigation warnings
|
// MSVC Spectre mitigation warnings
|
||||||
u64 index = 0;
|
u64 index = 0;
|
||||||
b8 running = true;
|
b8 running = true;
|
||||||
while (running) {
|
while (running) {
|
||||||
wapp_str8_set(dst, index, (u8)toupper(wapp_str8_get(src, index)));
|
wapp_str8_set(dst, index, (u8)toupper(wapp_str8_get(src, index)));
|
||||||
++index;
|
++index;
|
||||||
running = index < src->size;
|
running = index < src->size;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void wapp_str8_from_bytes(Str8 *dst, const U8Array *src) {
|
void wapp_str8_from_bytes(Str8 *dst, const U8Array src) {
|
||||||
wapp_debug_assert(src != NULL && dst != NULL, "`dst` and `src` should not be NULL");
|
wapp_debug_assert(src != NULL && dst != NULL, "`dst` and `src` should not be NULL");
|
||||||
|
|
||||||
u64 size = src->count * src->item_size;
|
u64 size = wapp_array_count(src) * wapp_array_item_size(src);
|
||||||
|
|
||||||
wapp_debug_assert(dst->capacity >= size, "`dst` does not have enough capacity");
|
wapp_debug_assert(dst->capacity >= size, "`dst` does not have enough capacity");
|
||||||
|
|
||||||
dst->size = size;
|
dst->size = size;
|
||||||
memcpy(dst->buf, src->items, size);
|
memcpy(dst->buf, src, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
i64 wapp_str8_find(Str8RO *str, Str8RO substr) {
|
i64 wapp_str8_find(Str8RO *str, Str8RO substr) {
|
||||||
if (!str || substr.size > str->size) {
|
if (!str || substr.size > str->size) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// NOTE (Abdelrahman): Uses a while loop instead of a for loop to get rid of
|
// NOTE (Abdelrahman): Uses a while loop instead of a for loop to get rid of
|
||||||
// MSVC Spectre mitigation warnings
|
// MSVC Spectre mitigation warnings
|
||||||
u64 char_index = 0;
|
u64 char_index = 0;
|
||||||
b8 running = char_index < str->size;
|
b8 running = char_index < str->size;
|
||||||
while (running) {
|
while (running) {
|
||||||
const c8 *sub = str->buf + char_index;
|
const c8 *sub = str->buf + char_index;
|
||||||
if (memcmp(sub, substr.buf, substr.size) == 0) {
|
if (memcmp(sub, substr.buf, substr.size) == 0) {
|
||||||
return char_index;
|
return char_index;
|
||||||
}
|
}
|
||||||
|
|
||||||
++char_index;
|
++char_index;
|
||||||
running = char_index < str->size;
|
running = char_index < str->size;
|
||||||
}
|
}
|
||||||
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
i64 wapp_str8_rfind(Str8RO *str, Str8RO substr) {
|
i64 wapp_str8_rfind(Str8RO *str, Str8RO substr) {
|
||||||
if (!str || substr.size > str->size) {
|
if (!str || substr.size > str->size) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// NOTE (Abdelrahman): Uses a while loop instead of a for loop to get rid of
|
// NOTE (Abdelrahman): Uses a while loop instead of a for loop to get rid of
|
||||||
// MSVC Spectre mitigation warnings
|
// MSVC Spectre mitigation warnings
|
||||||
i64 char_index = str->size - substr.size;
|
i64 char_index = str->size - substr.size;
|
||||||
b8 running = char_index >= 0;
|
b8 running = char_index >= 0;
|
||||||
while (running) {
|
while (running) {
|
||||||
const c8 *sub = str->buf + char_index;
|
const c8 *sub = str->buf + char_index;
|
||||||
if (memcmp(sub, substr.buf, substr.size) == 0) {
|
if (memcmp(sub, substr.buf, substr.size) == 0) {
|
||||||
return char_index;
|
return char_index;
|
||||||
}
|
}
|
||||||
|
|
||||||
--char_index;
|
--char_index;
|
||||||
running = char_index >= 0;
|
running = char_index >= 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
Str8List *wapp_str8_split_with_max(const Allocator *allocator, Str8RO *str, Str8RO *delimiter, i64 max_splits) {
|
Str8List *wapp_str8_split_with_max(const Allocator *allocator, Str8RO *str, Str8RO *delimiter, i64 max_splits) {
|
||||||
wapp_debug_assert(allocator != NULL && str != NULL && delimiter != NULL, "`allocator`, `str` and `delimiter` should not be NULL");
|
wapp_debug_assert(allocator != NULL && str != NULL && delimiter != NULL, "`allocator`, `str` and `delimiter` should not be NULL");
|
||||||
|
|
||||||
Str8List *output = wapp_mem_allocator_alloc(allocator, sizeof(Str8List));
|
Str8List *output = wapp_dbl_list_alloc(Str8, allocator);
|
||||||
|
|
||||||
if (delimiter->size > str->size) {
|
if (delimiter->size > str->size) {
|
||||||
Str8 *full = wapp_str8_alloc_str8(allocator, str);
|
Str8 *full = wapp_str8_alloc_str8(allocator, str);
|
||||||
Str8Node *node = wapp_mem_allocator_alloc(allocator, sizeof(Str8Node));
|
if (full) {
|
||||||
if (node) {
|
wapp_dbl_list_push_back_alloc(Str8, allocator, output, full);
|
||||||
node->item = full;
|
}
|
||||||
wapp_str8_list_push_back(output, node);
|
|
||||||
}
|
|
||||||
|
|
||||||
goto RETURN_STR8_SPLIT;
|
goto RETURN_STR8_SPLIT;
|
||||||
}
|
}
|
||||||
|
|
||||||
i64 start = 0;
|
i64 start = 0;
|
||||||
i64 end = 0;
|
i64 end = 0;
|
||||||
i64 splits = 0;
|
i64 splits = 0;
|
||||||
Str8 *rest = wapp_str8_alloc_str8(allocator, str);
|
Str8 *rest = wapp_str8_alloc_str8(allocator, str);
|
||||||
Str8 *before_str;
|
Str8 *before_str;
|
||||||
|
|
||||||
while ((end = wapp_str8_find(rest, *delimiter)) != -1) {
|
while ((end = wapp_str8_find(rest, *delimiter)) != -1) {
|
||||||
if (max_splits > 0 && splits >= max_splits) {
|
if (max_splits > 0 && splits >= max_splits) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
before_str = wapp_str8_alloc_substr(allocator, str, start, start + end);
|
before_str = wapp_str8_alloc_substr(allocator, str, start, start + end);
|
||||||
Str8Node *node = wapp_mem_allocator_alloc(allocator, sizeof(Str8Node));
|
if (before_str) {
|
||||||
if (node && before_str) {
|
wapp_dbl_list_push_back_alloc(Str8, allocator, output, before_str);
|
||||||
node->item = before_str;
|
}
|
||||||
wapp_str8_list_push_back(output, node);
|
|
||||||
}
|
|
||||||
|
|
||||||
wapp_mem_allocator_free(allocator, (void **)&rest, sizeof(Str8));
|
wapp_mem_allocator_free(allocator, (void **)&rest, sizeof(Str8));
|
||||||
rest = wapp_str8_alloc_substr(allocator, str, start + end + delimiter->size, str->size);
|
rest = wapp_str8_alloc_substr(allocator, str, start + end + delimiter->size, str->size);
|
||||||
start += end + delimiter->size;
|
start += end + delimiter->size;
|
||||||
|
|
||||||
++splits;
|
++splits;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ensure the last part of the string after the delimiter is added to the list
|
// Ensure the last part of the string after the delimiter is added to the list
|
||||||
rest = wapp_str8_alloc_substr(allocator, str, start, str->size);
|
rest = wapp_str8_alloc_substr(allocator, str, start, str->size);
|
||||||
Str8Node *node = wapp_mem_allocator_alloc(allocator, sizeof(Str8Node));
|
if (rest) {
|
||||||
if (node && rest) {
|
wapp_dbl_list_push_back_alloc(Str8, allocator, output, rest);
|
||||||
node->item = rest;
|
}
|
||||||
wapp_str8_list_push_back(output, node);
|
|
||||||
}
|
|
||||||
|
|
||||||
RETURN_STR8_SPLIT:
|
RETURN_STR8_SPLIT:
|
||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
|
|
||||||
Str8List *wapp_str8_rsplit_with_max(const Allocator *allocator, Str8RO *str, Str8RO *delimiter, i64 max_splits) {
|
Str8List *wapp_str8_rsplit_with_max(const Allocator *allocator, Str8RO *str, Str8RO *delimiter, i64 max_splits) {
|
||||||
wapp_debug_assert(allocator != NULL && str != NULL && delimiter != NULL, "`allocator`, `str` and `delimiter` should not be NULL");
|
wapp_debug_assert(allocator != NULL && str != NULL && delimiter != NULL, "`allocator`, `str` and `delimiter` should not be NULL");
|
||||||
|
|
||||||
Str8List *output = wapp_mem_allocator_alloc(allocator, sizeof(Str8List));
|
Str8List *output = wapp_dbl_list_alloc(Str8, allocator);
|
||||||
|
|
||||||
if (delimiter->size > str->size) {
|
if (delimiter->size > str->size) {
|
||||||
Str8 *full = wapp_str8_alloc_str8(allocator, str);
|
Str8 *full = wapp_str8_alloc_str8(allocator, str);
|
||||||
Str8Node *node = wapp_mem_allocator_alloc(allocator, sizeof(Str8Node));
|
if (full) {
|
||||||
if (node && full) {
|
wapp_dbl_list_push_back_alloc(Str8, allocator, output, full);
|
||||||
node->item = full;
|
}
|
||||||
wapp_str8_list_push_back(output, node);
|
|
||||||
}
|
|
||||||
|
|
||||||
goto RETURN_STR8_SPLIT;
|
goto RETURN_STR8_SPLIT;
|
||||||
}
|
}
|
||||||
|
|
||||||
i64 end = 0;
|
i64 end = 0;
|
||||||
i64 splits = 0;
|
i64 splits = 0;
|
||||||
Str8 *rest = wapp_str8_alloc_str8(allocator, str);
|
Str8 *rest = wapp_str8_alloc_str8(allocator, str);
|
||||||
Str8 *after_str;
|
Str8 *after_str;
|
||||||
|
|
||||||
while ((end = wapp_str8_rfind(rest, *delimiter)) != -1) {
|
while ((end = wapp_str8_rfind(rest, *delimiter)) != -1) {
|
||||||
if (max_splits > 0 && splits >= max_splits) {
|
if (max_splits > 0 && splits >= max_splits) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
after_str = wapp_str8_alloc_substr(allocator, rest, end + delimiter->size, str->size);
|
after_str = wapp_str8_alloc_substr(allocator, rest, end + delimiter->size, str->size);
|
||||||
Str8Node *node = wapp_mem_allocator_alloc(allocator, sizeof(Str8Node));
|
if (after_str) {
|
||||||
if (node) {
|
wapp_dbl_list_push_front_alloc(Str8, allocator, output, after_str);
|
||||||
node->item = after_str;
|
}
|
||||||
wapp_str8_list_push_front(output, node);
|
|
||||||
}
|
|
||||||
|
|
||||||
wapp_mem_allocator_free(allocator, (void **)&rest, sizeof(Str8));
|
wapp_mem_allocator_free(allocator, (void **)&rest, sizeof(Str8));
|
||||||
rest = wapp_str8_alloc_substr(allocator, rest, 0, end);
|
rest = wapp_str8_alloc_substr(allocator, rest, 0, end);
|
||||||
|
|
||||||
++splits;
|
++splits;
|
||||||
}
|
}
|
||||||
|
|
||||||
rest = wapp_str8_alloc_substr(allocator, str, 0, rest->size);
|
rest = wapp_str8_alloc_substr(allocator, str, 0, rest->size);
|
||||||
Str8Node *node = wapp_mem_allocator_alloc(allocator, sizeof(Str8Node));
|
if (rest) {
|
||||||
if (node && rest) {
|
wapp_dbl_list_push_front_alloc(Str8, allocator, output, rest);
|
||||||
node->item = rest;
|
}
|
||||||
wapp_str8_list_push_front(output, node);
|
|
||||||
}
|
|
||||||
|
|
||||||
RETURN_STR8_SPLIT:
|
RETURN_STR8_SPLIT:
|
||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
|
|
||||||
Str8 *wapp_str8_join(const Allocator *allocator, const Str8List *list, Str8RO *delimiter) {
|
Str8 *wapp_str8_join(const Allocator *allocator, const Str8List *list, Str8RO *delimiter) {
|
||||||
wapp_debug_assert(allocator != NULL && list != NULL && delimiter != NULL, "`allocator`, `list` and `delimiter` should not be NULL");
|
wapp_debug_assert(allocator != NULL && list != NULL && delimiter != NULL, "`allocator`, `list` and `delimiter` should not be NULL");
|
||||||
|
|
||||||
u64 capacity = wapp_str8_list_total_size(list) + (delimiter->size * (list->node_count - 1));
|
u64 capacity = wapp_str8_list_total_size(list) + (delimiter->size * (list->node_count - 1));
|
||||||
Str8 *output = wapp_str8_alloc_buf(allocator, capacity * 2);
|
Str8 *output = wapp_str8_alloc_buf(allocator, capacity * 2);
|
||||||
|
|
||||||
// NOTE (Abdelrahman): Uses a while loop instead of a for loop to get rid of
|
// NOTE (Abdelrahman): Uses a while loop instead of a for loop to get rid of
|
||||||
// MSVC Spectre mitigation warnings
|
// MSVC Spectre mitigation warnings
|
||||||
Str8Node *node;
|
Str8 *node;
|
||||||
u64 node_index = 0;
|
u64 node_index = 0;
|
||||||
b8 running = node_index < list->node_count;
|
b8 running = node_index < list->node_count;
|
||||||
while (running) {
|
while (running) {
|
||||||
node = wapp_str8_list_get(list, node_index);
|
node = wapp_dbl_list_get(Str8, list, node_index);
|
||||||
if (!node) {
|
if (!node) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
wapp_str8_concat_capped(output, node->item);
|
wapp_str8_concat_capped(output, node);
|
||||||
|
|
||||||
// NOTE (Abdelrahman): Comparison extracted to variable to silence
|
// NOTE (Abdelrahman): Comparison extracted to variable to silence
|
||||||
// MSVC Spectre mitigation warnings
|
// MSVC Spectre mitigation warnings
|
||||||
b8 not_last = node_index + 1 < list->node_count;
|
b8 not_last = node_index + 1 < list->node_count;
|
||||||
if (not_last) {
|
if (not_last) {
|
||||||
wapp_str8_concat_capped(output, delimiter);
|
wapp_str8_concat_capped(output, delimiter);
|
||||||
}
|
}
|
||||||
|
|
||||||
++node_index;
|
++node_index;
|
||||||
running = node_index < list->node_count;
|
running = node_index < list->node_count;
|
||||||
}
|
}
|
||||||
|
|
||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
|
|
||||||
u64 wapp_str8_list_total_size(const Str8List *list) {
|
u64 wapp_str8_list_total_size(const Str8List *list) {
|
||||||
if (!list) {
|
if (!list) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// NOTE (Abdelrahman): Uses a while loop instead of a for loop to get rid of
|
// NOTE (Abdelrahman): Uses a while loop instead of a for loop to get rid of
|
||||||
// MSVC Spectre mitigation warnings
|
// MSVC Spectre mitigation warnings
|
||||||
Str8Node* node;
|
Str8 *node;
|
||||||
u64 node_index = 0;
|
u64 node_index = 0;
|
||||||
u64 output = 0;
|
u64 output = 0;
|
||||||
b8 running = node_index < list->node_count;
|
b8 running = node_index < list->node_count;
|
||||||
while (running) {
|
while (running) {
|
||||||
node = wapp_str8_list_get(list, node_index);
|
node = wapp_dbl_list_get(Str8, list, node_index);
|
||||||
if (!node) {
|
if (!node) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
output += node->item->size;
|
output += node->size;
|
||||||
++node_index;
|
++node_index;
|
||||||
running = node_index < list->node_count;
|
running = node_index < list->node_count;
|
||||||
}
|
}
|
||||||
|
|
||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,11 +15,11 @@
|
|||||||
BEGIN_C_LINKAGE
|
BEGIN_C_LINKAGE
|
||||||
#endif // !WAPP_PLATFORM_CPP
|
#endif // !WAPP_PLATFORM_CPP
|
||||||
|
|
||||||
typedef struct str8 Str8;
|
typedef struct Str8 Str8;
|
||||||
struct str8 {
|
struct Str8 {
|
||||||
u64 capacity;
|
u64 capacity;
|
||||||
u64 size;
|
u64 size;
|
||||||
c8 *buf;
|
c8 *buf;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef const Str8 Str8RO;
|
typedef const Str8 Str8RO;
|
||||||
@@ -37,16 +37,16 @@ typedef const Str8 Str8RO;
|
|||||||
#ifdef WAPP_PLATFORM_CPP
|
#ifdef WAPP_PLATFORM_CPP
|
||||||
// Uses a lambda to achieve the same behaviour achieved by the C macro
|
// Uses a lambda to achieve the same behaviour achieved by the C macro
|
||||||
#define wapp_str8_buf(CAPACITY) ([&](){ \
|
#define wapp_str8_buf(CAPACITY) ([&](){ \
|
||||||
wapp_persist c8 buf[CAPACITY] = {}; \
|
wapp_persist c8 buf[CAPACITY] = {}; \
|
||||||
memset(buf, 0, CAPACITY); \
|
memset(buf, 0, CAPACITY); \
|
||||||
return Str8{CAPACITY, 0, buf}; \
|
return Str8{CAPACITY, 0, buf}; \
|
||||||
}())
|
}())
|
||||||
|
|
||||||
// Uses a lambda to achieve the same behaviour achieved by the C macro
|
// Uses a lambda to achieve the same behaviour achieved by the C macro
|
||||||
#define wapp_str8_lit(STRING) ([&]() { \
|
#define wapp_str8_lit(STRING) ([&]() { \
|
||||||
wapp_persist c8 buf[sizeof(STRING) * 2] = {}; \
|
wapp_persist c8 buf[sizeof(STRING) * 2] = {}; \
|
||||||
memcpy(buf, STRING, sizeof(STRING)); \
|
memcpy(buf, STRING, sizeof(STRING)); \
|
||||||
return Str8{(sizeof(STRING) - 1) * 2, sizeof(STRING) - 1, buf}; \
|
return Str8{(sizeof(STRING) - 1) * 2, sizeof(STRING) - 1, buf}; \
|
||||||
}())
|
}())
|
||||||
|
|
||||||
#define wapp_str8_lit_ro(STRING) Str8RO{sizeof(STRING) - 1, sizeof(STRING) - 1, (c8 *)STRING}
|
#define wapp_str8_lit_ro(STRING) Str8RO{sizeof(STRING) - 1, sizeof(STRING) - 1, (c8 *)STRING}
|
||||||
@@ -56,18 +56,20 @@ typedef const Str8 Str8RO;
|
|||||||
|
|
||||||
// Utilises the fact that memcpy returns pointer to dest buffer and that getting
|
// Utilises the fact that memcpy returns pointer to dest buffer and that getting
|
||||||
// address of compound literals is valid in C to create a string on the stack
|
// address of compound literals is valid in C to create a string on the stack
|
||||||
#define wapp_str8_lit(STRING) ((Str8){.capacity = (sizeof(STRING) - 1) * 2, \
|
#define wapp_str8_lit(STRING) ((Str8){.capacity = (sizeof(STRING) - 1) * 2, \
|
||||||
.size = sizeof(STRING) - 1, \
|
.size = sizeof(STRING) - 1, \
|
||||||
.buf = memcpy(&((c8 [sizeof(STRING) * 2]){0}), STRING, sizeof(STRING))})
|
.buf = memcpy(&((c8 [sizeof(STRING) * 2]){0}), \
|
||||||
#define wapp_str8_lit_ro(STRING) ((Str8RO){.capacity = sizeof(STRING) - 1, \
|
STRING, \
|
||||||
.size = sizeof(STRING) - 1, \
|
sizeof(STRING))})
|
||||||
.buf = (c8 *)STRING})
|
#define wapp_str8_lit_ro(STRING) ((Str8RO){.capacity = sizeof(STRING) - 1, \
|
||||||
|
.size = sizeof(STRING) - 1, \
|
||||||
|
.buf = (c8 *)STRING})
|
||||||
// To be used only when initialising a static storage variable in compilers that don't support
|
// To be used only when initialising a static storage variable in compilers that don't support
|
||||||
// initialisers with the syntax of wapp_str8_lit_ro (e.g. gcc). Should only be used when necessary
|
// initialisers with the syntax of wapp_str8_lit_ro (e.g. gcc). Should only be used when necessary
|
||||||
// and only be assigned to a Str8RO variable to avoid any attempt at modifying the string
|
// and only be assigned to a Str8RO variable to avoid any attempt at modifying the string
|
||||||
#define wapp_str8_lit_ro_initialiser_list(STRING) {.capacity = sizeof(STRING) - 1, \
|
#define wapp_str8_lit_ro_initialiser_list(STRING) {.capacity = sizeof(STRING) - 1, \
|
||||||
.size = sizeof(STRING) - 1, \
|
.size = sizeof(STRING) - 1, \
|
||||||
.buf = (c8 *)STRING}
|
.buf = (c8 *)STRING}
|
||||||
#endif // !WAPP_PLATFORM_CPP
|
#endif // !WAPP_PLATFORM_CPP
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -89,8 +91,8 @@ void wapp_str8_dealloc_buf(const Allocator *allocator, Str8 **str);
|
|||||||
c8 wapp_str8_get(Str8RO *str, u64 index);
|
c8 wapp_str8_get(Str8RO *str, u64 index);
|
||||||
void wapp_str8_set(Str8 *str, u64 index, c8 c);
|
void wapp_str8_set(Str8 *str, u64 index, c8 c);
|
||||||
void wapp_str8_push_back(Str8 *str, c8 c);
|
void wapp_str8_push_back(Str8 *str, c8 c);
|
||||||
b8 wapp_str8_equal(Str8RO *s1, Str8RO *s2);
|
b8 wapp_str8_equal(Str8RO *s1, Str8RO *s2);
|
||||||
b8 wapp_str8_equal_to_count(Str8RO* s1, Str8RO* s2, u64 count);
|
b8 wapp_str8_equal_to_count(Str8RO* s1, Str8RO* s2, u64 count);
|
||||||
Str8 wapp_str8_slice(Str8RO *str, u64 start, u64 end);
|
Str8 wapp_str8_slice(Str8RO *str, u64 start, u64 end);
|
||||||
void wapp_str8_concat_capped(Str8 *dst, Str8RO *src);
|
void wapp_str8_concat_capped(Str8 *dst, Str8RO *src);
|
||||||
void wapp_str8_copy_cstr_capped(Str8 *dst, const char *src);
|
void wapp_str8_copy_cstr_capped(Str8 *dst, const char *src);
|
||||||
@@ -99,7 +101,7 @@ void wapp_str8_copy_to_cstr(char *dst, Str8RO *src, u64 dst_capacity);
|
|||||||
void wapp_str8_format(Str8 *dst, const char *format, ...);
|
void wapp_str8_format(Str8 *dst, const char *format, ...);
|
||||||
void wapp_str8_to_lower(Str8 *dst, Str8RO *src);
|
void wapp_str8_to_lower(Str8 *dst, Str8RO *src);
|
||||||
void wapp_str8_to_upper(Str8 *dst, Str8RO *src);
|
void wapp_str8_to_upper(Str8 *dst, Str8RO *src);
|
||||||
void wapp_str8_from_bytes(Str8 *dst, const U8Array *src);
|
void wapp_str8_from_bytes(Str8 *dst, const U8Array src);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Str8 find functions
|
* Str8 find functions
|
||||||
@@ -119,19 +121,6 @@ Str8 *wapp_str8_join(const Allocator *allocator, const Str8List *list, Str8R
|
|||||||
/**
|
/**
|
||||||
* Str8 list utilities
|
* Str8 list utilities
|
||||||
*/
|
*/
|
||||||
#ifdef WAPP_PLATFORM_CPP
|
|
||||||
#define wapp_str8_node_from_cstr(STRING) wapp_str8_list_node([&]() { \
|
|
||||||
wapp_persist Str8 str = wapp_str8_lit(STRING); \
|
|
||||||
return &str; \
|
|
||||||
}())
|
|
||||||
#define wapp_str8_node_from_str8(STRING) wapp_str8_list_node([&]() { \
|
|
||||||
wapp_persist Str8 str = STRING; \
|
|
||||||
return &str; \
|
|
||||||
}())
|
|
||||||
#else
|
|
||||||
#define wapp_str8_node_from_cstr(STRING) wapp_str8_list_node(&wapp_str8_lit(STRING))
|
|
||||||
#define wapp_str8_node_from_str8(STRING) wapp_str8_list_node(&(STRING))
|
|
||||||
#endif // !WAPP_PLATFORM_CPP
|
|
||||||
u64 wapp_str8_list_total_size(const Str8List *list);
|
u64 wapp_str8_list_total_size(const Str8List *list);
|
||||||
|
|
||||||
#ifdef WAPP_PLATFORM_CPP
|
#ifdef WAPP_PLATFORM_CPP
|
||||||
|
|||||||
@@ -6,6 +6,7 @@
|
|||||||
#include "wapp_base.h"
|
#include "wapp_base.h"
|
||||||
#include "array/array.c"
|
#include "array/array.c"
|
||||||
#include "dbl_list/dbl_list.c"
|
#include "dbl_list/dbl_list.c"
|
||||||
|
#include "queue/queue.c"
|
||||||
#include "mem/allocator/mem_allocator.c"
|
#include "mem/allocator/mem_allocator.c"
|
||||||
#include "mem/utils/mem_utils.c"
|
#include "mem/utils/mem_utils.c"
|
||||||
#include "strings/str8/str8.c"
|
#include "strings/str8/str8.c"
|
||||||
|
|||||||
@@ -3,8 +3,9 @@
|
|||||||
#ifndef WAPP_BASE_H
|
#ifndef WAPP_BASE_H
|
||||||
#define WAPP_BASE_H
|
#define WAPP_BASE_H
|
||||||
|
|
||||||
#include "dbl_list/dbl_list.h"
|
|
||||||
#include "array/array.h"
|
#include "array/array.h"
|
||||||
|
#include "dbl_list/dbl_list.h"
|
||||||
|
#include "queue/queue.h"
|
||||||
#include "mem/allocator/mem_allocator.h"
|
#include "mem/allocator/mem_allocator.h"
|
||||||
#include "mem/utils/mem_utils.h"
|
#include "mem/utils/mem_utils.h"
|
||||||
#include "strings/str8/str8.h"
|
#include "strings/str8/str8.h"
|
||||||
|
|||||||
@@ -7,28 +7,28 @@
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
#if defined(WAPP_PLATFORM_C) && WAPP_PLATFORM_C_VERSION >= WAPP_PLATFORM_C11_VERSION && !defined(WAPP_PLATFORM_APPLE)
|
#if defined(WAPP_PLATFORM_C) && WAPP_PLATFORM_C_VERSION >= WAPP_PLATFORM_C11_VERSION && !defined(WAPP_PLATFORM_APPLE)
|
||||||
#include <uchar.h>
|
#include <uchar.h>
|
||||||
|
|
||||||
#if WAPP_PLATFORM_C_VERSION >= WAPP_PLATFORM_C23_VERSION
|
#if WAPP_PLATFORM_C_VERSION >= WAPP_PLATFORM_C23_VERSION
|
||||||
#define c8 char8_t
|
typedef char8_t c8;
|
||||||
#else
|
#else
|
||||||
#define c8 uint8_t
|
typedef uint8_t c8;
|
||||||
#endif // !WAPP_PLATFORM_C23_VERSION
|
#endif // !WAPP_PLATFORM_C23_VERSION
|
||||||
|
|
||||||
#define c16 char16_t
|
typedef char16_t c16;
|
||||||
#define c32 char32_t
|
typedef char32_t c32;
|
||||||
#else
|
#else
|
||||||
#define c8 uint8_t
|
typedef uint8_t c8;
|
||||||
#define c16 uint16_t
|
typedef uint16_t c16;
|
||||||
#define c32 uint32_t
|
typedef uint32_t c32;
|
||||||
#endif // !WAPP_PLATFORM_C
|
#endif // !WAPP_PLATFORM_C
|
||||||
|
|
||||||
#define u8 uint8_t
|
typedef uint8_t u8;
|
||||||
#define u16 uint16_t
|
typedef uint16_t u16;
|
||||||
#define u32 uint32_t
|
typedef uint32_t u32;
|
||||||
#define u64 uint64_t
|
typedef uint64_t u64;
|
||||||
|
|
||||||
#define b8 uint8_t
|
typedef uint8_t b8;
|
||||||
|
|
||||||
#ifndef WAPP_PLATFORM_CPP
|
#ifndef WAPP_PLATFORM_CPP
|
||||||
|
|
||||||
@@ -42,17 +42,17 @@
|
|||||||
|
|
||||||
#endif // !WAPP_PLATFORM_CPP
|
#endif // !WAPP_PLATFORM_CPP
|
||||||
|
|
||||||
#define i8 int8_t
|
typedef int8_t i8;
|
||||||
#define i16 int16_t
|
typedef int16_t i16;
|
||||||
#define i32 int32_t
|
typedef int32_t i32;
|
||||||
#define i64 int64_t
|
typedef int64_t i64;
|
||||||
|
|
||||||
#define f32 float
|
typedef float f32;
|
||||||
#define f64 double
|
typedef double f64;
|
||||||
#define f128 long double
|
typedef long double f128;
|
||||||
|
|
||||||
#define uptr uintptr_t
|
typedef uintptr_t uptr;
|
||||||
#define iptr intptr_t
|
typedef intptr_t iptr;
|
||||||
|
|
||||||
#define wapp_extern extern
|
#define wapp_extern extern
|
||||||
#define wapp_intern static
|
#define wapp_intern static
|
||||||
|
|||||||
@@ -16,42 +16,42 @@ BEGIN_C_LINKAGE
|
|||||||
#define wapp_static_assert(EXPR, MSG) extern char ASSERTION_FAILED[EXPR ? 1 : -1]
|
#define wapp_static_assert(EXPR, MSG) extern char ASSERTION_FAILED[EXPR ? 1 : -1]
|
||||||
|
|
||||||
#ifndef WAPP_NO_RUNTIME_ASSERT
|
#ifndef WAPP_NO_RUNTIME_ASSERT
|
||||||
#define wapp_runtime_assert(EXPR, MSG) __wapp_runtime_assert(EXPR, MSG)
|
#define wapp_runtime_assert(EXPR, MSG) __wapp_runtime_assert(EXPR, MSG)
|
||||||
#else
|
#else
|
||||||
#define wapp_runtime_assert(EXPR, MSG)
|
#define wapp_runtime_assert(EXPR, MSG)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef WAPP_DEBUG_ASSERT
|
#ifdef WAPP_DEBUG_ASSERT
|
||||||
#define wapp_debug_assert(EXPR, MSG) wapp_runtime_assert(EXPR, MSG)
|
#define wapp_debug_assert(EXPR, MSG) wapp_runtime_assert(EXPR, MSG)
|
||||||
#else
|
#else
|
||||||
#define wapp_debug_assert(EXPR, MSG)
|
#define wapp_debug_assert(EXPR, MSG)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef WAPP_PLATFORM_WINDOWS
|
#ifdef WAPP_PLATFORM_WINDOWS
|
||||||
#define __wapp_runtime_assert(EXPR, MSG) do { \
|
#define __wapp_runtime_assert(EXPR, MSG) do { \
|
||||||
__pragma(warning(push)) \
|
__pragma(warning(push)) \
|
||||||
__pragma(warning(disable:4127)) \
|
__pragma(warning(disable:4127)) \
|
||||||
if (!(EXPR)) { \
|
if (!(EXPR)) { \
|
||||||
__pragma(warning(pop)) \
|
__pragma(warning(pop)) \
|
||||||
__runtime_assert_failed(EXPR, MSG); \
|
__runtime_assert_failed(EXPR, MSG); \
|
||||||
} \
|
} \
|
||||||
} while(false)
|
} while(false)
|
||||||
#else
|
#else
|
||||||
#define __wapp_runtime_assert(EXPR, MSG) do { \
|
#define __wapp_runtime_assert(EXPR, MSG) do { \
|
||||||
if (!(EXPR)) { \
|
if (!(EXPR)) { \
|
||||||
__runtime_assert_failed(EXPR, MSG); \
|
__runtime_assert_failed(EXPR, MSG); \
|
||||||
} \
|
} \
|
||||||
} while(false)
|
} while(false)
|
||||||
#endif // !WAPP_PLATFORM_WINDOWS
|
#endif // !WAPP_PLATFORM_WINDOWS
|
||||||
|
|
||||||
#define __runtime_assert_failed(EXPR, MSG) do { \
|
#define __runtime_assert_failed(EXPR, MSG) do { \
|
||||||
fprintf( \
|
fprintf( \
|
||||||
stderr, \
|
stderr, \
|
||||||
"%s:%d (In function `%s`): Assertion failed (%" PRIu32 ")\nDiagnostic: %s\n\n", \
|
"%s:%d (In function `%s`): Assertion failed (%" PRIu32 ")\nDiagnostic: %s\n\n", \
|
||||||
__FILE__, __LINE__, __func__, \
|
__FILE__, __LINE__, __func__, \
|
||||||
EXPR, MSG \
|
EXPR, MSG \
|
||||||
); \
|
); \
|
||||||
abort(); \
|
abort(); \
|
||||||
} while(false)
|
} while(false)
|
||||||
|
|
||||||
#ifdef WAPP_PLATFORM_CPP
|
#ifdef WAPP_PLATFORM_CPP
|
||||||
|
|||||||
@@ -9,35 +9,47 @@
|
|||||||
BEGIN_C_LINKAGE
|
BEGIN_C_LINKAGE
|
||||||
#endif // !WAPP_PLATFORM_CPP
|
#endif // !WAPP_PLATFORM_CPP
|
||||||
|
|
||||||
#define KB(SIZE) (SIZE * 1024ull)
|
#define KiB(SIZE) (((u64)SIZE) << 10)
|
||||||
#define MB(SIZE) (KB(SIZE) * 1024)
|
#define MiB(SIZE) (((u64)SIZE) << 20)
|
||||||
#define GB(SIZE) (MB(SIZE) * 1024)
|
#define GiB(SIZE) (((u64)SIZE) << 30)
|
||||||
#define TB(SIZE) (GB(SIZE) * 1024)
|
#define TiB(SIZE) (((u64)SIZE) << 40)
|
||||||
|
#define PiB(SIZE) (((u64)SIZE) << 50)
|
||||||
|
#define EiB(SIZE) (((u64)SIZE) << 60)
|
||||||
|
|
||||||
#define wapp_misc_utils_padding_size(SIZE) u8 reserved_padding[sizeof(void *) - ((SIZE) % sizeof(void *))]
|
#define KB(SIZE) (((u64)SIZE) * 1000llu)
|
||||||
|
#define MB(SIZE) (KB(SIZE) * 1000llu)
|
||||||
|
#define GB(SIZE) (MB(SIZE) * 1000llu)
|
||||||
|
#define TB(SIZE) (GB(SIZE) * 1000llu)
|
||||||
|
#define PB(SIZE) (TB(SIZE) * 1000llu)
|
||||||
|
#define EB(SIZE) (PB(SIZE) * 1000llu)
|
||||||
|
|
||||||
|
#define wapp_misc_utils_reserve_padding(SIZE) u8 reserved_padding[sizeof(void *) - ((SIZE) % sizeof(void *))]
|
||||||
|
|
||||||
#define U64_RSHIFT_OR_1(X) (((u64)X) | (((u64)X) >> 1))
|
#define U64_RSHIFT_OR_1(X) (((u64)X) | (((u64)X) >> 1))
|
||||||
#define U64_RSHIFT_OR_2(X) (((u64)X) | (((u64)X) >> 2))
|
#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_4(X) (((u64)X) | (((u64)X) >> 4))
|
||||||
#define U64_RSHIFT_OR_8(X) (((u64)X) | (((u64)X) >> 8))
|
#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_16(X) (((u64)X) | (((u64)X) >> 16))
|
||||||
#define U64_RSHIFT_OR_32(X) (((u64)X) | (((u64)X) >> 32))
|
#define U64_RSHIFT_OR_32(X) (((u64)X) | (((u64)X) >> 32))
|
||||||
#define wapp_misc_utils_u64_round_up_pow2(X) ( \
|
#define wapp_misc_utils_u64_round_up_pow2(X) ( \
|
||||||
( \
|
( \
|
||||||
U64_RSHIFT_OR_32( \
|
U64_RSHIFT_OR_32( \
|
||||||
U64_RSHIFT_OR_16( \
|
U64_RSHIFT_OR_16( \
|
||||||
U64_RSHIFT_OR_8( \
|
U64_RSHIFT_OR_8( \
|
||||||
U64_RSHIFT_OR_4( \
|
U64_RSHIFT_OR_4( \
|
||||||
U64_RSHIFT_OR_2( \
|
U64_RSHIFT_OR_2( \
|
||||||
U64_RSHIFT_OR_1(X - 1) \
|
U64_RSHIFT_OR_1(X - 1) \
|
||||||
) \
|
) \
|
||||||
) \
|
) \
|
||||||
) \
|
) \
|
||||||
) \
|
) \
|
||||||
) \
|
) \
|
||||||
) + 1 \
|
) + 1 \
|
||||||
)
|
)
|
||||||
|
|
||||||
|
#define wapp_is_power_of_two(NUM) ((NUM & (NUM - 1)) == 0)
|
||||||
|
#define wapp_pointer_offset(PTR, OFFSET) ((void *)((uptr)(PTR) + (OFFSET)))
|
||||||
|
|
||||||
#ifdef WAPP_PLATFORM_CPP
|
#ifdef WAPP_PLATFORM_CPP
|
||||||
END_C_LINKAGE
|
END_C_LINKAGE
|
||||||
|
|
||||||
|
|||||||
@@ -4,111 +4,111 @@
|
|||||||
#define PLATFORM_H
|
#define PLATFORM_H
|
||||||
|
|
||||||
#if defined(__ANDROID__)
|
#if defined(__ANDROID__)
|
||||||
#define WAPP_PLATFORM_ANDROID
|
#define WAPP_PLATFORM_ANDROID
|
||||||
#define WAPP_PLATFORM_POSIX
|
#define WAPP_PLATFORM_POSIX
|
||||||
#elif defined(__FreeBSD__)
|
#elif defined(__FreeBSD__)
|
||||||
#define WAPP_PLATFORM_FREE_BSD
|
#define WAPP_PLATFORM_FREE_BSD
|
||||||
#define WAPP_PLATFORM_BSD
|
#define WAPP_PLATFORM_BSD
|
||||||
#define WAPP_PLATFORM_POSIX
|
#define WAPP_PLATFORM_POSIX
|
||||||
#elif defined(__NetBSD__)
|
#elif defined(__NetBSD__)
|
||||||
#define WAPP_PLATFORM_NET_BSD
|
#define WAPP_PLATFORM_NET_BSD
|
||||||
#define WAPP_PLATFORM_BSD
|
#define WAPP_PLATFORM_BSD
|
||||||
#define WAPP_PLATFORM_POSIX
|
#define WAPP_PLATFORM_POSIX
|
||||||
#elif defined(__OpenBSD__)
|
#elif defined(__OpenBSD__)
|
||||||
#define WAPP_PLATFORM_OPEN_BSD
|
#define WAPP_PLATFORM_OPEN_BSD
|
||||||
#define WAPP_PLATFORM_BSD
|
#define WAPP_PLATFORM_BSD
|
||||||
#define WAPP_PLATFORM_POSIX
|
#define WAPP_PLATFORM_POSIX
|
||||||
#elif defined(__DragonFly__)
|
#elif defined(__DragonFly__)
|
||||||
#define WAPP_PLATFORM_DRAGON_FLY
|
#define WAPP_PLATFORM_DRAGON_FLY
|
||||||
#define WAPP_PLATFORM_BSD
|
#define WAPP_PLATFORM_BSD
|
||||||
#define WAPP_PLATFORM_POSIX
|
#define WAPP_PLATFORM_POSIX
|
||||||
#elif defined(__bsdi__)
|
#elif defined(__bsdi__)
|
||||||
#define WAPP_PLATFORM_BSD
|
#define WAPP_PLATFORM_BSD
|
||||||
#define WAPP_PLATFORM_POSIX
|
#define WAPP_PLATFORM_POSIX
|
||||||
#elif defined(__linux__) || defined(linux) || defined(__linux) || defined(__gnu_linux__)
|
#elif defined(__linux__) || defined(linux) || defined(__linux) || defined(__gnu_linux__)
|
||||||
#define WAPP_PLATFORM_LINUX
|
#define WAPP_PLATFORM_LINUX
|
||||||
#define WAPP_PLATFORM_POSIX
|
#define WAPP_PLATFORM_POSIX
|
||||||
#elif defined(__GNU__) || defined(__gnu_hurd__)
|
#elif defined(__GNU__) || defined(__gnu_hurd__)
|
||||||
#define WAPP_PLATFORM_GNU
|
#define WAPP_PLATFORM_GNU
|
||||||
#define WAPP_PLATFORM_POSIX
|
#define WAPP_PLATFORM_POSIX
|
||||||
#elif defined(__APPLE__) || defined(__MACH__)
|
#elif defined(__APPLE__) || defined(__MACH__)
|
||||||
#include <TargetConditionals.h>
|
#include <TargetConditionals.h>
|
||||||
#if TARGET_OS_IPHONE
|
#if TARGET_OS_IPHONE
|
||||||
#define WAPP_PLATFORM_IOS
|
#define WAPP_PLATFORM_IOS
|
||||||
#define WAPP_PLATFORM_APPLE
|
#define WAPP_PLATFORM_APPLE
|
||||||
#define WAPP_PLATFORM_POSIX
|
#define WAPP_PLATFORM_POSIX
|
||||||
#elif TARGET_OS_MAC
|
#elif TARGET_OS_MAC
|
||||||
#define WAPP_PLATFORM_MACOS
|
#define WAPP_PLATFORM_MACOS
|
||||||
#define WAPP_PLATFORM_APPLE
|
#define WAPP_PLATFORM_APPLE
|
||||||
#define WAPP_PLATFORM_POSIX
|
#define WAPP_PLATFORM_POSIX
|
||||||
#else
|
#else
|
||||||
#error "Unrecognised Apple platform"
|
#error "Unrecognised Apple platform"
|
||||||
#endif
|
#endif
|
||||||
#elif defined(_WIN64)
|
#elif defined(_WIN64)
|
||||||
#define WAPP_PLATFORM_WINDOWS64
|
#define WAPP_PLATFORM_WINDOWS64
|
||||||
#define WAPP_PLATFORM_WINDOWS
|
#define WAPP_PLATFORM_WINDOWS
|
||||||
#elif defined(_WIN32)
|
#elif defined(_WIN32)
|
||||||
#define WAPP_PLATFORM_WINDOWS32
|
#define WAPP_PLATFORM_WINDOWS32
|
||||||
#define WAPP_PLATFORM_WINDOWS
|
#define WAPP_PLATFORM_WINDOWS
|
||||||
#elif defined(__CYGWIN__)
|
#elif defined(__CYGWIN__)
|
||||||
#define WAPP_PLATFORM_CYGWIN
|
#define WAPP_PLATFORM_CYGWIN
|
||||||
#define WAPP_PLATFORM_WINDOWS
|
#define WAPP_PLATFORM_WINDOWS
|
||||||
#elif defined(__unix__) || defined(__unix)
|
#elif defined(__unix__) || defined(__unix)
|
||||||
#define WAPP_PLATFORM_UNIX
|
#define WAPP_PLATFORM_UNIX
|
||||||
#define WAPP_PLATFORM_POSIX
|
#define WAPP_PLATFORM_POSIX
|
||||||
#else
|
#else
|
||||||
#error "Unrecognised platform"
|
#error "Unrecognised platform"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
#define WAPP_PLATFORM_CPP
|
#define WAPP_PLATFORM_CPP
|
||||||
#define WAPP_PLATFORM_CPP_VERSION __cplusplus
|
#define WAPP_PLATFORM_CPP_VERSION __cplusplus
|
||||||
#define WAPP_PLATFORM_CPP98_VERSION 199711L
|
#define WAPP_PLATFORM_CPP98_VERSION 199711L
|
||||||
#define WAPP_PLATFORM_CPP11_VERSION 201103L
|
#define WAPP_PLATFORM_CPP11_VERSION 201103L
|
||||||
#define WAPP_PLATFORM_CPP14_VERSION 201402L
|
#define WAPP_PLATFORM_CPP14_VERSION 201402L
|
||||||
#define WAPP_PLATFORM_CPP17_VERSION 201703L
|
#define WAPP_PLATFORM_CPP17_VERSION 201703L
|
||||||
#define WAPP_PLATFORM_CPP20_VERSION 202002L
|
#define WAPP_PLATFORM_CPP20_VERSION 202002L
|
||||||
#define WAPP_PLATFORM_CPP23_VERSION 202302L
|
#define WAPP_PLATFORM_CPP23_VERSION 202302L
|
||||||
|
|
||||||
#if WAPP_PLATFORM_CPP_VERSION == WAPP_PLATFORM_CPP98_VERSION
|
#if WAPP_PLATFORM_CPP_VERSION == WAPP_PLATFORM_CPP98_VERSION
|
||||||
#define WAPP_PLATFORM_CPP98
|
#define WAPP_PLATFORM_CPP98
|
||||||
#elif WAPP_PLATFORM_CPP_VERSION == WAPP_PLATFORM_CPP11_VERSION
|
#elif WAPP_PLATFORM_CPP_VERSION == WAPP_PLATFORM_CPP11_VERSION
|
||||||
#define WAPP_PLATFORM_CPP11
|
#define WAPP_PLATFORM_CPP11
|
||||||
#elif WAPP_PLATFORM_CPP_VERSION == WAPP_PLATFORM_CPP14_VERSION
|
#elif WAPP_PLATFORM_CPP_VERSION == WAPP_PLATFORM_CPP14_VERSION
|
||||||
#define WAPP_PLATFORM_CPP14
|
#define WAPP_PLATFORM_CPP14
|
||||||
#elif WAPP_PLATFORM_CPP_VERSION == WAPP_PLATFORM_CPP17_VERSION
|
#elif WAPP_PLATFORM_CPP_VERSION == WAPP_PLATFORM_CPP17_VERSION
|
||||||
#define WAPP_PLATFORM_CPP17
|
#define WAPP_PLATFORM_CPP17
|
||||||
#elif WAPP_PLATFORM_CPP_VERSION == WAPP_PLATFORM_CPP20_VERSION
|
#elif WAPP_PLATFORM_CPP_VERSION == WAPP_PLATFORM_CPP20_VERSION
|
||||||
#define WAPP_PLATFORM_CPP20
|
#define WAPP_PLATFORM_CPP20
|
||||||
#elif WAPP_PLATFORM_CPP_VERSION == WAPP_PLATFORM_CPP23_VERSION
|
#elif WAPP_PLATFORM_CPP_VERSION == WAPP_PLATFORM_CPP23_VERSION
|
||||||
#define WAPP_PLATFORM_CPP23
|
#define WAPP_PLATFORM_CPP23
|
||||||
#else
|
#else
|
||||||
#error "Unrecognised C++ version"
|
#error "Unrecognised C++ version"
|
||||||
#endif
|
#endif
|
||||||
#else
|
#else
|
||||||
#define WAPP_PLATFORM_C
|
#define WAPP_PLATFORM_C
|
||||||
|
|
||||||
#if defined(__STDC_VERSION__)
|
#if defined(__STDC_VERSION__)
|
||||||
#define WAPP_PLATFORM_C_VERSION __STDC_VERSION__
|
#define WAPP_PLATFORM_C_VERSION __STDC_VERSION__
|
||||||
#define WAPP_PLATFORM_C99_VERSION 199901L
|
#define WAPP_PLATFORM_C99_VERSION 199901L
|
||||||
#define WAPP_PLATFORM_C11_VERSION 201112L
|
#define WAPP_PLATFORM_C11_VERSION 201112L
|
||||||
#define WAPP_PLATFORM_C17_VERSION 201710L
|
#define WAPP_PLATFORM_C17_VERSION 201710L
|
||||||
#define WAPP_PLATFORM_C23_VERSION 202311L
|
#define WAPP_PLATFORM_C23_VERSION 202311L
|
||||||
|
|
||||||
#if WAPP_PLATFORM_C_VERSION == WAPP_PLATFORM_C99_VERSION
|
#if WAPP_PLATFORM_C_VERSION == WAPP_PLATFORM_C99_VERSION
|
||||||
#define WAPP_PLATFORM_C99
|
#define WAPP_PLATFORM_C99
|
||||||
#elif WAPP_PLATFORM_C_VERSION == WAPP_PLATFORM_C11_VERSION
|
#elif WAPP_PLATFORM_C_VERSION == WAPP_PLATFORM_C11_VERSION
|
||||||
#define WAPP_PLATFORM_C11
|
#define WAPP_PLATFORM_C11
|
||||||
#elif WAPP_PLATFORM_C_VERSION == WAPP_PLATFORM_C17_VERSION
|
#elif WAPP_PLATFORM_C_VERSION == WAPP_PLATFORM_C17_VERSION
|
||||||
#define WAPP_PLATFORM_C17
|
#define WAPP_PLATFORM_C17
|
||||||
#elif WAPP_PLATFORM_C_VERSION == WAPP_PLATFORM_C23_VERSION
|
#elif WAPP_PLATFORM_C_VERSION == WAPP_PLATFORM_C23_VERSION
|
||||||
#define WAPP_PLATFORM_C23
|
#define WAPP_PLATFORM_C23
|
||||||
#else
|
#else
|
||||||
#error "Unrecognised C version"
|
#error "Unrecognised C version"
|
||||||
#endif
|
#endif
|
||||||
#else
|
#else
|
||||||
#define WAPP_PLATFORM_C89
|
#define WAPP_PLATFORM_C89
|
||||||
#endif
|
#endif
|
||||||
#endif // !__cplusplus
|
#endif // !__cplusplus
|
||||||
|
|
||||||
#endif // !PLATFORM_H
|
#endif // !PLATFORM_H
|
||||||
|
|||||||
@@ -6,7 +6,6 @@
|
|||||||
#include "../../../common/assert/assert.h"
|
#include "../../../common/assert/assert.h"
|
||||||
#include "../../../common/misc/misc_utils.h"
|
#include "../../../common/misc/misc_utils.h"
|
||||||
#include "../../../base/mem/utils/mem_utils.h"
|
#include "../../../base/mem/utils/mem_utils.h"
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#ifndef DEFAULT_ALIGNMENT
|
#ifndef DEFAULT_ALIGNMENT
|
||||||
@@ -15,132 +14,179 @@
|
|||||||
#define DEFAULT_ALIGNMENT (2 * sizeof(void *))
|
#define DEFAULT_ALIGNMENT (2 * sizeof(void *))
|
||||||
#endif /* ifndef DEFAULT_ALIGNMENT */
|
#endif /* ifndef DEFAULT_ALIGNMENT */
|
||||||
|
|
||||||
#define ARENA_MINIMUM_CAPACITY KB(16) // Allocate minimum of 4 pages
|
#define ARENA_MINIMUM_CAPACITY KiB(16) // Allocate minimum of 4 pages
|
||||||
|
|
||||||
struct arena {
|
typedef enum {
|
||||||
u8 *buf;
|
ARENA_STORAGE_TYPE_ALLOCATED,
|
||||||
u8 *offset;
|
ARENA_STORAGE_TYPE_BUFFER,
|
||||||
u64 capacity;
|
} ArenaStorageType;
|
||||||
b8 committed;
|
|
||||||
|
|
||||||
#ifdef WAPP_PLATFORM_WINDOWS
|
struct Arena {
|
||||||
wapp_misc_utils_padding_size(sizeof(u8 *) * 2 + sizeof(u64) + sizeof(b8));
|
u8 *buf;
|
||||||
#endif // ifdef WAPP_PLATFORM_WINDOWS
|
u8 *offset;
|
||||||
|
u8 *prev_offset;
|
||||||
|
u64 capacity;
|
||||||
|
ArenaStorageType type;
|
||||||
|
b8 committed;
|
||||||
|
|
||||||
|
wapp_misc_utils_reserve_padding(sizeof(u8 *) * 3 + sizeof(u64) + sizeof(ArenaStorageType) + sizeof(b8));
|
||||||
};
|
};
|
||||||
|
|
||||||
b8 wapp_mem_arena_init_custom(Arena **arena, u64 base_capacity, MemAllocFlags flags, b8 zero_buffer) {
|
b8 wapp_mem_arena_init_buffer(Arena **arena, u8 *buffer, u64 buffer_size) {
|
||||||
if (!arena || *arena || base_capacity == 0) {
|
if (!arena || *arena || buffer_size < sizeof(Arena)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
*arena = (Arena *)calloc(1, sizeof(Arena));
|
*arena = (Arena *)buffer;
|
||||||
Arena *arena_ptr = *arena;
|
Arena *arena_ptr = *arena;
|
||||||
if (!arena_ptr) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
u64 arena_capacity = wapp_misc_utils_u64_round_up_pow2(
|
arena_ptr->buf = (u8 *)(arena_ptr + 1);
|
||||||
base_capacity >= ARENA_MINIMUM_CAPACITY ?
|
arena_ptr->offset = arena_ptr->buf;
|
||||||
base_capacity :
|
arena_ptr->prev_offset = NULL;
|
||||||
ARENA_MINIMUM_CAPACITY
|
arena_ptr->capacity = buffer_size - sizeof(Arena);
|
||||||
);
|
arena_ptr->type = ARENA_STORAGE_TYPE_BUFFER;
|
||||||
|
arena_ptr->committed = true;
|
||||||
|
|
||||||
arena_ptr->buf = (u8 *)wapp_mem_util_alloc(NULL, arena_capacity, WAPP_MEM_ACCESS_READ_WRITE, flags,
|
return true;
|
||||||
zero_buffer ? WAPP_MEM_INIT_INITIALISED : WAPP_MEM_INIT_UNINITIALISED);
|
}
|
||||||
|
|
||||||
if (!(arena_ptr->buf)) {
|
b8 wapp_mem_arena_init_allocated_custom(Arena **arena, u64 base_capacity, MemAllocFlags flags, b8 zero_buffer) {
|
||||||
wapp_mem_arena_destroy(arena);
|
if (!arena || *arena || base_capacity == 0) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
arena_ptr->capacity = arena_capacity;
|
u64 size = sizeof(Arena) + (base_capacity >= ARENA_MINIMUM_CAPACITY ? base_capacity : ARENA_MINIMUM_CAPACITY);
|
||||||
arena_ptr->offset = arena_ptr->buf;
|
u64 alloc_size = wapp_misc_utils_u64_round_up_pow2(size);
|
||||||
arena_ptr->committed = (flags & WAPP_MEM_ALLOC_COMMIT) == WAPP_MEM_ALLOC_COMMIT;
|
u8 *allocated = (u8 *)wapp_os_mem_alloc(NULL, alloc_size, WAPP_MEM_ACCESS_READ_WRITE, flags,
|
||||||
|
zero_buffer ? WAPP_MEM_INIT_INITIALISED : WAPP_MEM_INIT_UNINITIALISED);
|
||||||
|
if (!allocated) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
b8 committed = (flags & WAPP_MEM_ALLOC_COMMIT) == WAPP_MEM_ALLOC_COMMIT;
|
||||||
|
|
||||||
|
#ifdef WAPP_PLATFORM_WINDOWS
|
||||||
|
if (!committed) {
|
||||||
|
wapp_os_mem_alloc(allocated, sizeof(Arena), WAPP_MEM_ACCESS_READ_WRITE, WAPP_MEM_ALLOC_COMMIT,
|
||||||
|
WAPP_MEM_INIT_INITIALISED);
|
||||||
|
}
|
||||||
|
#endif // ifdef WAPP_PLATFORM_WINDOWS
|
||||||
|
|
||||||
|
if (!wapp_mem_arena_init_buffer(arena, allocated, alloc_size)) {
|
||||||
|
wapp_mem_arena_destroy(arena);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
Arena *arena_ptr = *arena;
|
||||||
|
arena_ptr->type = ARENA_STORAGE_TYPE_ALLOCATED;
|
||||||
|
arena_ptr->committed = committed;
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void *wapp_mem_arena_alloc(Arena *arena, u64 size) {
|
void *wapp_mem_arena_alloc(Arena *arena, u64 size) {
|
||||||
return wapp_mem_arena_alloc_aligned(arena, size, DEFAULT_ALIGNMENT);
|
return wapp_mem_arena_alloc_aligned(arena, size, DEFAULT_ALIGNMENT);
|
||||||
}
|
}
|
||||||
|
|
||||||
void *wapp_mem_arena_alloc_aligned(Arena *arena, u64 size, u64 alignment) {
|
void *wapp_mem_arena_alloc_aligned(Arena *arena, u64 size, u64 alignment) {
|
||||||
wapp_debug_assert(arena != NULL, "`arena` should not be NULL");
|
wapp_debug_assert(arena != NULL, "`arena` should not be NULL");
|
||||||
|
|
||||||
u8 *alloc_start = arena->offset;
|
u8 *alloc_start = arena->offset;
|
||||||
|
|
||||||
u8 *output = wapp_mem_util_align_forward((void *)alloc_start, alignment);
|
u8 *output = wapp_mem_util_align_forward((void *)alloc_start, alignment);
|
||||||
if (output + size >= arena->buf + arena->capacity) {
|
if (output + size >= arena->buf + arena->capacity) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
arena->offset = output + size;
|
arena->offset = output + size;
|
||||||
|
|
||||||
#ifdef WAPP_PLATFORM_WINDOWS
|
#ifdef WAPP_PLATFORM_WINDOWS
|
||||||
if (!(arena->committed)) {
|
if (arena->type == ARENA_STORAGE_TYPE_ALLOCATED && !(arena->committed)) {
|
||||||
wapp_mem_util_alloc(alloc_start, (uptr)(arena->offset) - (uptr)(alloc_start),
|
wapp_os_mem_alloc(alloc_start, (uptr)(arena->offset) - (uptr)(alloc_start),
|
||||||
WAPP_MEM_ACCESS_READ_WRITE, WAPP_MEM_ALLOC_COMMIT,
|
WAPP_MEM_ACCESS_READ_WRITE, WAPP_MEM_ALLOC_COMMIT,
|
||||||
WAPP_MEM_INIT_UNINITIALISED);
|
WAPP_MEM_INIT_UNINITIALISED);
|
||||||
}
|
}
|
||||||
#endif // ifdef WAPP_PLATFORM_WINDOWS
|
#endif // ifdef WAPP_PLATFORM_WINDOWS
|
||||||
|
|
||||||
memset(output, 0, size);
|
memset(output, 0, size);
|
||||||
|
|
||||||
return (void *)output;
|
return (void *)output;
|
||||||
}
|
}
|
||||||
|
|
||||||
void *wapp_mem_arena_realloc(Arena *arena, void *ptr, u64 old_size, u64 new_size) {
|
void *wapp_mem_arena_realloc(Arena *arena, void *ptr, u64 old_size, u64 new_size) {
|
||||||
if ((u8*)ptr < arena->buf || (u8*)ptr > arena->offset ||
|
wapp_debug_assert(arena != NULL, "`arena` should not be NULL");
|
||||||
arena->offset + new_size >= arena->buf + arena->capacity) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
void *new_ptr = wapp_mem_arena_alloc(arena, new_size);
|
if ((u8*)ptr < arena->buf || (u8*)ptr > arena->offset ||
|
||||||
if (!new_ptr) {
|
arena->offset + new_size >= arena->buf + arena->capacity) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
u64 copy_size = new_size <= old_size ? new_size : old_size;
|
void *new_ptr = wapp_mem_arena_alloc(arena, new_size);
|
||||||
memcpy(new_ptr, ptr, copy_size);
|
if (!new_ptr) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
return new_ptr;
|
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) {
|
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 ||
|
wapp_debug_assert(arena != NULL, "`arena` should not be NULL");
|
||||||
arena->offset + new_size >= arena->buf + arena->capacity) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
void *new_ptr = wapp_mem_arena_alloc_aligned(arena, new_size, alignment);
|
if ((u8*)ptr < arena->buf || (u8*)ptr > arena->offset ||
|
||||||
if (!new_ptr) {
|
arena->offset + new_size >= arena->buf + arena->capacity) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
u64 copy_size = new_size <= old_size ? new_size : old_size;
|
void *new_ptr = wapp_mem_arena_alloc_aligned(arena, new_size, alignment);
|
||||||
memcpy(new_ptr, ptr, copy_size);
|
if (!new_ptr) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
return new_ptr;
|
u64 copy_size = new_size <= old_size ? new_size : old_size;
|
||||||
|
memcpy(new_ptr, ptr, copy_size);
|
||||||
|
|
||||||
|
return new_ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void wapp_mem_arena_temp_begin(Arena *arena) {
|
||||||
|
wapp_debug_assert(arena != NULL, "`arena` should not be NULL");
|
||||||
|
|
||||||
|
if (arena->prev_offset != NULL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
arena->prev_offset = arena->offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
void wapp_mem_arena_temp_end(Arena *arena) {
|
||||||
|
wapp_debug_assert(arena != NULL, "`arena` should not be NULL");
|
||||||
|
|
||||||
|
if (arena->prev_offset == NULL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
arena->offset = arena->prev_offset;
|
||||||
|
arena->prev_offset = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void wapp_mem_arena_clear(Arena *arena) {
|
void wapp_mem_arena_clear(Arena *arena) {
|
||||||
wapp_debug_assert(arena != NULL, "`arena` should not be NULL");
|
wapp_debug_assert(arena != NULL, "`arena` should not be NULL");
|
||||||
|
|
||||||
memset(arena->buf, 0, arena->offset - arena->buf);
|
memset(arena->buf, 0, arena->offset - arena->buf);
|
||||||
arena->offset = arena->buf;
|
arena->offset = arena->buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
void wapp_mem_arena_destroy(Arena **arena) {
|
void wapp_mem_arena_destroy(Arena **arena) {
|
||||||
wapp_debug_assert(arena != NULL && (*arena) != NULL, "`arena` double pointer is not valid");
|
wapp_debug_assert(arena != NULL && (*arena) != NULL, "`arena` double pointer is not valid");
|
||||||
|
|
||||||
Arena *arena_ptr = *arena;
|
Arena *arena_ptr = *arena;
|
||||||
if (arena_ptr->buf) {
|
|
||||||
wapp_mem_util_free(arena_ptr->buf, arena_ptr->capacity);
|
|
||||||
}
|
|
||||||
|
|
||||||
arena_ptr->buf = arena_ptr->offset = NULL;
|
if (arena_ptr->type == ARENA_STORAGE_TYPE_ALLOCATED) {
|
||||||
arena_ptr->capacity = 0;
|
wapp_os_mem_free(*arena, sizeof(Arena) + arena_ptr->capacity);
|
||||||
|
}
|
||||||
|
|
||||||
free(*arena);
|
*arena = NULL;
|
||||||
*arena = NULL;
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,29 +11,32 @@
|
|||||||
BEGIN_C_LINKAGE
|
BEGIN_C_LINKAGE
|
||||||
#endif // !WAPP_PLATFORM_CPP
|
#endif // !WAPP_PLATFORM_CPP
|
||||||
|
|
||||||
typedef struct arena Arena;
|
typedef struct Arena Arena;
|
||||||
|
|
||||||
#define wapp_mem_arena_init(arena_dptr, base_capacity) \
|
#define wapp_mem_arena_init_allocated(arena_dptr, base_capacity) \
|
||||||
(wapp_mem_arena_init_custom(arena_dptr, base_capacity, WAPP_MEM_ALLOC_RESERVE, false))
|
(wapp_mem_arena_init_allocated_custom(arena_dptr, base_capacity, WAPP_MEM_ALLOC_RESERVE, false))
|
||||||
#define wapp_mem_arena_init_commit(arena_dptr, base_capacity) \
|
#define wapp_mem_arena_init_allocated_commit(arena_dptr, base_capacity) \
|
||||||
(wapp_mem_arena_init_custom(arena_dptr, base_capacity, WAPP_MEM_ALLOC_RESERVE | WAPP_MEM_ALLOC_COMMIT, false))
|
(wapp_mem_arena_init_allocated_custom(arena_dptr, base_capacity, WAPP_MEM_ALLOC_RESERVE | WAPP_MEM_ALLOC_COMMIT, false))
|
||||||
#define wapp_mem_arena_init_zero(arena_dptr, base_capacity) \
|
#define wapp_mem_arena_init_allocated_zero(arena_dptr, base_capacity) \
|
||||||
(wapp_mem_arena_init_custom(arena_dptr, base_capacity, WAPP_MEM_ALLOC_RESERVE, true))
|
(wapp_mem_arena_init_allocated_custom(arena_dptr, base_capacity, WAPP_MEM_ALLOC_RESERVE, true))
|
||||||
#define wapp_mem_arena_init_commit_and_zero(arena_dptr, base_capacity) \
|
#define wapp_mem_arena_init_allocated_commit_and_zero(arena_dptr, base_capacity) \
|
||||||
(wapp_mem_arena_init_custom(arena_dptr, base_capacity, WAPP_MEM_ALLOC_RESERVE | WAPP_MEM_ALLOC_COMMIT, true))
|
(wapp_mem_arena_init_allocated_custom(arena_dptr, base_capacity, WAPP_MEM_ALLOC_RESERVE | WAPP_MEM_ALLOC_COMMIT, true))
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Arena initialisation function. `wapp_mem_arena_init_custom` provides the most
|
* Arena initialisation function. `wapp_mem_arena_init_allocated_custom` provides the most
|
||||||
* control over how the Arena is initialised. Wrapper macros are provided for
|
* control over how the Arena is initialised. Wrapper macros are provided for
|
||||||
* easier use.
|
* easier use.
|
||||||
*/
|
*/
|
||||||
b8 wapp_mem_arena_init_custom(Arena **arena, u64 base_capacity, MemAllocFlags flags, b8 zero_buffer);
|
b8 wapp_mem_arena_init_allocated_custom(Arena **arena, u64 base_capacity, MemAllocFlags flags, b8 zero_buffer);
|
||||||
|
b8 wapp_mem_arena_init_buffer(Arena **arena, u8 *buffer, u64 buffer_size);
|
||||||
void *wapp_mem_arena_alloc(Arena *arena, u64 size);
|
void *wapp_mem_arena_alloc(Arena *arena, u64 size);
|
||||||
void *wapp_mem_arena_alloc_aligned(Arena *arena, u64 size, u64 alignment);
|
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(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_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_temp_begin(Arena *arena);
|
||||||
void wapp_mem_arena_destroy(Arena **arena);
|
void wapp_mem_arena_temp_end(Arena *arena);
|
||||||
|
void wapp_mem_arena_clear(Arena *arena);
|
||||||
|
void wapp_mem_arena_destroy(Arena **arena);
|
||||||
|
|
||||||
#ifdef WAPP_PLATFORM_CPP
|
#ifdef WAPP_PLATFORM_CPP
|
||||||
END_C_LINKAGE
|
END_C_LINKAGE
|
||||||
|
|||||||
@@ -4,56 +4,84 @@
|
|||||||
#include "mem_arena.h"
|
#include "mem_arena.h"
|
||||||
#include "../../mem/mem_os.h"
|
#include "../../mem/mem_os.h"
|
||||||
#include "../../../common/aliases/aliases.h"
|
#include "../../../common/aliases/aliases.h"
|
||||||
|
#include "../../../common/assert/assert.h"
|
||||||
|
|
||||||
wapp_intern inline void *mem_arena_alloc(u64 size, void *alloc_obj);
|
wapp_intern void initialise_arena_allocator(Allocator *allocator);
|
||||||
wapp_intern inline void *mem_arena_alloc_aligned(u64 size, u64 alignment, void *alloc_obj);
|
wapp_intern void *mem_arena_alloc(u64 size, void *alloc_obj);
|
||||||
wapp_intern inline void *mem_arena_realloc(void *ptr, u64 old_size, u64 new_size, void *alloc_obj);
|
wapp_intern void *mem_arena_alloc_aligned(u64 size, u64 alignment, void *alloc_obj);
|
||||||
wapp_intern inline void *mem_arena_realloc_aligned(void *ptr, u64 old_size, u64 new_size, u64 alignment,
|
wapp_intern void *mem_arena_realloc(void *ptr, u64 old_size, u64 new_size, void *alloc_obj);
|
||||||
void *alloc_obj);
|
wapp_intern void *mem_arena_realloc_aligned(void *ptr, u64 old_size, u64 new_size, u64 alignment,
|
||||||
|
void *alloc_obj);
|
||||||
|
|
||||||
|
Allocator wapp_mem_arena_allocator_init_with_buffer(u8 *buffer, u64 buffer_size) {
|
||||||
|
Allocator allocator = {0};
|
||||||
|
b8 initialised = wapp_mem_arena_init_buffer((Arena **)(&allocator.obj), buffer, buffer_size);
|
||||||
|
if (!initialised) {
|
||||||
|
return allocator;
|
||||||
|
}
|
||||||
|
|
||||||
|
initialise_arena_allocator(&allocator);
|
||||||
|
|
||||||
|
return allocator;
|
||||||
|
}
|
||||||
|
|
||||||
Allocator wapp_mem_arena_allocator_init_custom(u64 base_capacity, MemAllocFlags flags, b8 zero_buffer) {
|
Allocator wapp_mem_arena_allocator_init_custom(u64 base_capacity, MemAllocFlags flags, b8 zero_buffer) {
|
||||||
Allocator allocator = {0};
|
Allocator allocator = {0};
|
||||||
b8 initialised = wapp_mem_arena_init_custom((Arena **)(&allocator.obj), base_capacity, flags, zero_buffer);
|
b8 initialised = wapp_mem_arena_init_allocated_custom((Arena **)(&allocator.obj), base_capacity, flags, zero_buffer);
|
||||||
if (!initialised) {
|
if (!initialised) {
|
||||||
return allocator;
|
return allocator;
|
||||||
}
|
}
|
||||||
|
|
||||||
allocator.alloc = mem_arena_alloc;
|
initialise_arena_allocator(&allocator);
|
||||||
allocator.alloc_aligned = mem_arena_alloc_aligned;
|
|
||||||
allocator.realloc = mem_arena_realloc;
|
|
||||||
allocator.realloc_aligned = mem_arena_realloc_aligned;
|
|
||||||
|
|
||||||
return allocator;
|
return allocator;
|
||||||
|
}
|
||||||
|
|
||||||
|
void wapp_mem_arena_allocator_temp_begin(const Allocator *allocator) {
|
||||||
|
wapp_debug_assert(allocator != NULL, "`allocator` should not be NULL");
|
||||||
|
wapp_mem_arena_temp_begin((Arena *)(allocator->obj));
|
||||||
|
}
|
||||||
|
|
||||||
|
void wapp_mem_arena_allocator_temp_end(const Allocator *allocator) {
|
||||||
|
wapp_debug_assert(allocator != NULL, "`allocator` should not be NULL");
|
||||||
|
wapp_mem_arena_temp_end((Arena *)(allocator->obj));
|
||||||
}
|
}
|
||||||
|
|
||||||
void wapp_mem_arena_allocator_clear(Allocator *allocator) {
|
void wapp_mem_arena_allocator_clear(Allocator *allocator) {
|
||||||
wapp_mem_arena_clear((Arena *)(allocator->obj));
|
wapp_debug_assert(allocator != NULL, "`allocator` should not be NULL");
|
||||||
|
wapp_mem_arena_clear((Arena *)(allocator->obj));
|
||||||
}
|
}
|
||||||
|
|
||||||
void wapp_mem_arena_allocator_destroy(Allocator *allocator) {
|
void wapp_mem_arena_allocator_destroy(Allocator *allocator) {
|
||||||
wapp_mem_arena_destroy((Arena **)(&(allocator->obj)));
|
wapp_debug_assert(allocator != NULL, "`allocator` should not be NULL");
|
||||||
*allocator = (Allocator){0};
|
wapp_mem_arena_destroy((Arena **)(&(allocator->obj)));
|
||||||
|
*allocator = (Allocator){0};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
wapp_intern void initialise_arena_allocator(Allocator *allocator) {
|
||||||
wapp_intern inline void *mem_arena_alloc(u64 size, void *alloc_obj) {
|
allocator->alloc = mem_arena_alloc;
|
||||||
Arena *arena = (Arena *)alloc_obj;
|
allocator->alloc_aligned = mem_arena_alloc_aligned;
|
||||||
return wapp_mem_arena_alloc(arena, size);
|
allocator->realloc = mem_arena_realloc;
|
||||||
|
allocator->realloc_aligned = mem_arena_realloc_aligned;
|
||||||
}
|
}
|
||||||
|
|
||||||
wapp_intern inline void *mem_arena_alloc_aligned(u64 size, u64 alignment, void *alloc_obj) {
|
wapp_intern void *mem_arena_alloc(u64 size, void *alloc_obj) {
|
||||||
Arena *arena = (Arena *)alloc_obj;
|
Arena *arena = (Arena *)alloc_obj;
|
||||||
return wapp_mem_arena_alloc_aligned(arena, size, alignment);
|
return wapp_mem_arena_alloc(arena, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
wapp_intern inline void *mem_arena_realloc(void *ptr, u64 old_size, u64 new_size, void *alloc_obj) {
|
wapp_intern void *mem_arena_alloc_aligned(u64 size, u64 alignment, void *alloc_obj) {
|
||||||
Arena *arena = (Arena *)alloc_obj;
|
Arena *arena = (Arena *)alloc_obj;
|
||||||
return wapp_mem_arena_realloc(arena, ptr, old_size, new_size);
|
return wapp_mem_arena_alloc_aligned(arena, size, alignment);
|
||||||
}
|
}
|
||||||
|
|
||||||
wapp_intern inline void *mem_arena_realloc_aligned(void *ptr, u64 old_size, u64 new_size, u64 alignment,
|
wapp_intern void *mem_arena_realloc(void *ptr, u64 old_size, u64 new_size, void *alloc_obj) {
|
||||||
void *alloc_obj) {
|
Arena *arena = (Arena *)alloc_obj;
|
||||||
Arena *arena = (Arena *)alloc_obj;
|
return wapp_mem_arena_realloc(arena, ptr, old_size, new_size);
|
||||||
return wapp_mem_arena_realloc_aligned(arena, ptr, old_size, new_size, alignment);
|
}
|
||||||
|
|
||||||
|
wapp_intern void *mem_arena_realloc_aligned(void *ptr, u64 old_size, u64 new_size, u64 alignment,
|
||||||
|
void *alloc_obj) {
|
||||||
|
Arena *arena = (Arena *)alloc_obj;
|
||||||
|
return wapp_mem_arena_realloc_aligned(arena, ptr, old_size, new_size, alignment);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,14 +12,14 @@
|
|||||||
BEGIN_C_LINKAGE
|
BEGIN_C_LINKAGE
|
||||||
#endif // !WAPP_PLATFORM_CPP
|
#endif // !WAPP_PLATFORM_CPP
|
||||||
|
|
||||||
#define wapp_mem_arena_allocator_init(base_capacity) \
|
#define wapp_mem_arena_allocator_init(base_capacity) \
|
||||||
(wapp_mem_arena_allocator_init_custom(base_capacity, WAPP_MEM_ALLOC_RESERVE, false))
|
(wapp_mem_arena_allocator_init_custom(base_capacity, WAPP_MEM_ALLOC_RESERVE, false))
|
||||||
#define wapp_mem_arena_allocator_init_commit(base_capacity) \
|
#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))
|
(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) \
|
#define wapp_mem_arena_allocator_init_zero(base_capacity) \
|
||||||
(wapp_mem_arena_allocator_init_custom(base_capacity, WAPP_MEM_ALLOC_RESERVE, true))
|
(wapp_mem_arena_allocator_init_custom(base_capacity, WAPP_MEM_ALLOC_RESERVE, true))
|
||||||
#define wapp_mem_arena_allocator_init_commit_and_zero(base_capacity) \
|
#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))
|
(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
|
* Wraps an Arena in an Allocator object. It attempts to initialise the Arena
|
||||||
@@ -33,8 +33,11 @@ BEGIN_C_LINKAGE
|
|||||||
* the Arena is initialised. Wrapper macros are provided for easier use.
|
* the Arena is initialised. Wrapper macros are provided for easier use.
|
||||||
*/
|
*/
|
||||||
Allocator wapp_mem_arena_allocator_init_custom(u64 base_capacity, MemAllocFlags flags, b8 zero_buffer);
|
Allocator wapp_mem_arena_allocator_init_custom(u64 base_capacity, MemAllocFlags flags, b8 zero_buffer);
|
||||||
void wapp_mem_arena_allocator_clear(Allocator *allocator);
|
Allocator wapp_mem_arena_allocator_init_with_buffer(u8 *buffer, u64 buffer_size);
|
||||||
void wapp_mem_arena_allocator_destroy(Allocator *allocator);
|
void wapp_mem_arena_allocator_temp_begin(const Allocator *allocator);
|
||||||
|
void wapp_mem_arena_allocator_temp_end(const Allocator *allocator);
|
||||||
|
void wapp_mem_arena_allocator_clear(Allocator *allocator);
|
||||||
|
void wapp_mem_arena_allocator_destroy(Allocator *allocator);
|
||||||
|
|
||||||
#ifdef WAPP_PLATFORM_CPP
|
#ifdef WAPP_PLATFORM_CPP
|
||||||
END_C_LINKAGE
|
END_C_LINKAGE
|
||||||
|
|||||||
@@ -12,124 +12,125 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
u32 wapp_cpath_join_path(Str8 *dst, const Str8List *parts) {
|
u32 wapp_cpath_join_path(Str8 *dst, const Str8List *parts) {
|
||||||
if (!dst || !parts) {
|
if (!dst || !parts) {
|
||||||
return CPATH_JOIN_INVALID_ARGS;
|
return CPATH_JOIN_INVALID_ARGS;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (parts->node_count == 0) {
|
if (parts->node_count == 0) {
|
||||||
return CPATH_JOIN_EMPTY_PARTS;
|
return CPATH_JOIN_EMPTY_PARTS;
|
||||||
}
|
}
|
||||||
|
|
||||||
Str8 separator = wapp_str8_buf(4);
|
Str8 separator = wapp_str8_buf(4);
|
||||||
wapp_str8_push_back(&separator, WAPP_PATH_SEP);
|
wapp_str8_push_back(&separator, WAPP_PATH_SEP);
|
||||||
|
|
||||||
u64 required_capacity = parts->node_count * separator.size + wapp_str8_list_total_size(parts);
|
u64 required_capacity = parts->node_count * separator.size + wapp_str8_list_total_size(parts);
|
||||||
if (dst->capacity < required_capacity) {
|
if (dst->capacity < required_capacity) {
|
||||||
return CPATH_JOIN_INSUFFICIENT_DST_CAPACITY;
|
return CPATH_JOIN_INSUFFICIENT_DST_CAPACITY;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handle first node
|
// Handle first node
|
||||||
const Str8Node *first_node = wapp_str8_list_get(parts, 0);
|
Str8 *first_node = wapp_dbl_list_get(Str8, parts, 0);
|
||||||
wapp_str8_copy_str8_capped(dst, first_node->item);
|
wapp_str8_copy_str8_capped(dst, first_node);
|
||||||
|
|
||||||
// NOTE (Abdelrahman): Uses a while loop instead of a for loop to get rid of
|
// NOTE (Abdelrahman): Uses a while loop instead of a for loop to get rid of
|
||||||
// MSVC Spectre mitigation warnings
|
// MSVC Spectre mitigation warnings
|
||||||
const Str8Node *node = first_node;
|
Str8 *node = first_node;
|
||||||
u64 node_index = 1;
|
u64 node_index = 1;
|
||||||
b8 running = node_index < parts->node_count;
|
b8 running = node_index < parts->node_count;
|
||||||
while (running && node->next) {
|
while (running) {
|
||||||
node = node->next;
|
node = wapp_dbl_list_get(Str8, parts, node_index);
|
||||||
if (node->item->size == 0) {
|
if (node->size == 0) {
|
||||||
continue;
|
goto CPATH_JOIN_LOOP_END;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dst->size > 0) {
|
if (dst->size > 0) {
|
||||||
char dst_last = wapp_str8_get(dst, dst->size - 1);
|
char dst_last = wapp_str8_get(dst, dst->size - 1);
|
||||||
char node_start = wapp_str8_get(node->item, 0);
|
char node_start = wapp_str8_get(node, 0);
|
||||||
b8 add_path_sep = dst_last != WAPP_PATH_SEP && node_start != WAPP_PATH_SEP;
|
b8 add_path_sep = dst_last != WAPP_PATH_SEP && node_start != WAPP_PATH_SEP;
|
||||||
|
|
||||||
if (add_path_sep) {
|
if (add_path_sep) {
|
||||||
wapp_str8_concat_capped(dst, &separator);
|
wapp_str8_concat_capped(dst, &separator);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
wapp_str8_concat_capped(dst, node->item);
|
wapp_str8_concat_capped(dst, node);
|
||||||
|
|
||||||
++node_index;
|
CPATH_JOIN_LOOP_END:
|
||||||
running = node_index < parts->node_count;
|
++node_index;
|
||||||
}
|
running = node_index < parts->node_count;
|
||||||
|
}
|
||||||
|
|
||||||
return CPATH_JOIN_SUCCESS;
|
return CPATH_JOIN_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
Str8 *dirup(const Allocator *allocator, Str8RO *path, u64 levels) {
|
Str8 *dirup(const Allocator *allocator, Str8RO *path, u64 levels) {
|
||||||
Str8 *output = NULL;
|
Str8 *output = NULL;
|
||||||
if (!allocator || !path) {
|
if (!allocator || !path) {
|
||||||
goto RETURN_DIRUP;
|
goto RETURN_DIRUP;
|
||||||
}
|
}
|
||||||
|
|
||||||
b8 absolute = wapp_str8_get(path, 0) == WAPP_PATH_SEP;
|
b8 absolute = wapp_str8_get(path, 0) == WAPP_PATH_SEP;
|
||||||
Str8 separator = wapp_str8_buf(4);
|
Str8 separator = wapp_str8_buf(4);
|
||||||
wapp_str8_push_back(&separator, WAPP_PATH_SEP);
|
wapp_str8_push_back(&separator, WAPP_PATH_SEP);
|
||||||
|
|
||||||
if (path->size == 0) {
|
if (path->size == 0) {
|
||||||
output = wapp_str8_alloc_buf(allocator, 16);
|
output = wapp_str8_alloc_buf(allocator, 16);
|
||||||
if (!output) {
|
if (!output) {
|
||||||
goto RETURN_DIRUP;
|
goto RETURN_DIRUP;
|
||||||
}
|
}
|
||||||
|
|
||||||
wapp_str8_push_back(output, absolute ? WAPP_PATH_SEP : '.');
|
wapp_str8_push_back(output, absolute ? WAPP_PATH_SEP : '.');
|
||||||
goto RETURN_DIRUP;
|
goto RETURN_DIRUP;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (levels < 1) {
|
if (levels < 1) {
|
||||||
output = wapp_str8_alloc_str8(allocator, path);
|
output = wapp_str8_alloc_str8(allocator, path);
|
||||||
goto RETURN_DIRUP;
|
goto RETURN_DIRUP;
|
||||||
}
|
}
|
||||||
|
|
||||||
Allocator tmp_arena = wapp_mem_arena_allocator_init(MB(8));
|
Allocator tmp_arena = wapp_mem_arena_allocator_init(MiB(8));
|
||||||
if (wapp_mem_allocator_invalid(&tmp_arena)) {
|
if (wapp_mem_allocator_invalid(&tmp_arena)) {
|
||||||
goto RETURN_DIRUP;
|
goto RETURN_DIRUP;
|
||||||
}
|
}
|
||||||
|
|
||||||
Str8List *parts = wapp_str8_split(&tmp_arena, path, &separator);
|
Str8List *parts = wapp_str8_split(&tmp_arena, path, &separator);
|
||||||
if (!parts) {
|
if (!parts) {
|
||||||
goto RETURN_DIRUP;
|
goto RETURN_DIRUP;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (levels >= parts->node_count) {
|
if (levels >= parts->node_count) {
|
||||||
output = wapp_str8_alloc_buf(allocator, 16);
|
output = wapp_str8_alloc_buf(allocator, 16);
|
||||||
if (!output) {
|
if (!output) {
|
||||||
goto LIST_CLEANUP_DIRUP;
|
goto LIST_CLEANUP_DIRUP;
|
||||||
}
|
}
|
||||||
|
|
||||||
wapp_str8_push_back(output, absolute ? WAPP_PATH_SEP : '.');
|
wapp_str8_push_back(output, absolute ? WAPP_PATH_SEP : '.');
|
||||||
} else {
|
} else {
|
||||||
for (u64 i = 0; i < levels; ++i) {
|
for (u64 i = 0; i < levels; ++i) {
|
||||||
wapp_str8_list_pop_back(parts);
|
wapp_dbl_list_pop_back(Str8, parts);
|
||||||
}
|
}
|
||||||
|
|
||||||
u64 alignment = sizeof(void *) * 2;
|
u64 alignment = sizeof(void *) * 2;
|
||||||
u64 alloc_size = wapp_str8_list_total_size(parts) + parts->node_count * separator.size;
|
u64 alloc_size = wapp_str8_list_total_size(parts) + parts->node_count * separator.size;
|
||||||
u64 modulo = alloc_size & (alignment - 1);
|
u64 modulo = alloc_size & (alignment - 1);
|
||||||
alloc_size += alignment - modulo;
|
alloc_size += alignment - modulo;
|
||||||
|
|
||||||
output = wapp_str8_alloc_buf(allocator, alloc_size);
|
output = wapp_str8_alloc_buf(allocator, alloc_size);
|
||||||
if (output) {
|
if (output) {
|
||||||
if (absolute) {
|
if (absolute) {
|
||||||
wapp_str8_push_back(output, WAPP_PATH_SEP);
|
wapp_str8_push_back(output, WAPP_PATH_SEP);
|
||||||
}
|
}
|
||||||
|
|
||||||
Str8 *joined = wapp_str8_join(&tmp_arena, parts, &separator);
|
Str8 *joined = wapp_str8_join(&tmp_arena, parts, &separator);
|
||||||
if (joined) {
|
if (joined) {
|
||||||
wapp_str8_concat_capped(output, joined);
|
wapp_str8_concat_capped(output, joined);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
LIST_CLEANUP_DIRUP:
|
LIST_CLEANUP_DIRUP:
|
||||||
wapp_mem_arena_allocator_destroy(&tmp_arena);
|
wapp_mem_arena_allocator_destroy(&tmp_arena);
|
||||||
|
|
||||||
RETURN_DIRUP:
|
RETURN_DIRUP:
|
||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ BEGIN_C_LINKAGE
|
|||||||
#define WAPP_PATH_MAX PATH_MAX
|
#define WAPP_PATH_MAX PATH_MAX
|
||||||
#elif defined(WAPP_PLATFORM_WINDOWS)
|
#elif defined(WAPP_PLATFORM_WINDOWS)
|
||||||
#define WIN32_LEAN_AND_MEAN
|
#define WIN32_LEAN_AND_MEAN
|
||||||
#include <windows.h>
|
#include <Windows.h>
|
||||||
#define WAPP_PATH_SEP '\\'
|
#define WAPP_PATH_SEP '\\'
|
||||||
#define WAPP_PATH_MAX MAX_PATH
|
#define WAPP_PATH_MAX MAX_PATH
|
||||||
#else
|
#else
|
||||||
@@ -29,13 +29,13 @@ BEGIN_C_LINKAGE
|
|||||||
#define wapp_cpath_dirup(ALLOCATOR, PATH, COUNT) dirup(ALLOCATOR, PATH, COUNT)
|
#define wapp_cpath_dirup(ALLOCATOR, PATH, COUNT) dirup(ALLOCATOR, PATH, COUNT)
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
CPATH_JOIN_SUCCESS = 0,
|
CPATH_JOIN_SUCCESS = 0,
|
||||||
CPATH_JOIN_INVALID_ARGS,
|
CPATH_JOIN_INVALID_ARGS,
|
||||||
CPATH_JOIN_EMPTY_PARTS,
|
CPATH_JOIN_EMPTY_PARTS,
|
||||||
CPATH_JOIN_INSUFFICIENT_DST_CAPACITY,
|
CPATH_JOIN_INSUFFICIENT_DST_CAPACITY,
|
||||||
};
|
};
|
||||||
|
|
||||||
u32 wapp_cpath_join_path(Str8 *dst, const Str8List *parts);
|
u32 wapp_cpath_join_path(Str8 *dst, const Str8List *parts);
|
||||||
Str8 *dirup(const Allocator *allocator, Str8RO *path, u64 levels);
|
Str8 *dirup(const Allocator *allocator, Str8RO *path, u64 levels);
|
||||||
|
|
||||||
#ifdef WAPP_PLATFORM_CPP
|
#ifdef WAPP_PLATFORM_CPP
|
||||||
|
|||||||
@@ -6,104 +6,124 @@
|
|||||||
#include "../../common/aliases/aliases.h"
|
#include "../../common/aliases/aliases.h"
|
||||||
#include "../../base/array/array.h"
|
#include "../../base/array/array.h"
|
||||||
#include "../../base/strings/str8/str8.h"
|
#include "../../base/strings/str8/str8.h"
|
||||||
#include <stdio.h>
|
|
||||||
|
|
||||||
File *wapp_file_open(Str8RO *filepath, FileAccessMode mode) {
|
WFile *wapp_file_open(const Allocator *allocator, Str8RO *filepath, FileAccessMode mode) {
|
||||||
wapp_persist const char *modes[FILE_ACCESS_MODE_COUNT] = {
|
wapp_debug_assert(allocator != NULL && filepath != NULL, "`allocator` and `filepath` should not be NULL");
|
||||||
[WAPP_FA_MODE_R] = "r",
|
wapp_debug_assert(filepath->size < WAPP_PATH_MAX, "`filepath` exceeds max path limit.");
|
||||||
[WAPP_FA_MODE_W] = "w",
|
return _file_open(allocator, filepath, mode);
|
||||||
[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+",
|
|
||||||
};
|
|
||||||
wapp_persist 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) {
|
i64 wapp_file_get_current_position(WFile *file) {
|
||||||
wapp_debug_assert(file != NULL, "`file` should not be NULL.");
|
wapp_debug_assert(file != NULL, "`file` should not be NULL.");
|
||||||
return (u64)ftell(file);
|
return _file_seek(file, 0, WAPP_SEEK_CURRENT);
|
||||||
}
|
}
|
||||||
|
|
||||||
i32 wapp_file_seek(File *file, u64 offset, FileSeekOrigin origin) {
|
i64 wapp_file_seek(WFile *file, i64 offset, FileSeekOrigin origin) {
|
||||||
wapp_debug_assert(file != NULL, "`file` should not be NULL.");
|
wapp_debug_assert(file != NULL, "`file` should not be NULL.");
|
||||||
// TODO (Abdelrahman): Revisit conversion to long
|
return _file_seek(file, offset, origin);
|
||||||
return fseek(file, (long)offset, origin);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
u64 wapp_file_get_length(File *file) {
|
i64 wapp_file_get_length(WFile *file) {
|
||||||
wapp_debug_assert(file != NULL, "`file` should not be NULL.");
|
wapp_debug_assert(file != NULL, "`file` should not be NULL.");
|
||||||
|
|
||||||
u64 current = wapp_file_get_current_position(file);
|
i64 current = wapp_file_get_current_position(file);
|
||||||
|
|
||||||
wapp_file_seek(file, 0, WAPP_SEEK_END);
|
_file_seek(file, 0, WAPP_SEEK_END);
|
||||||
|
|
||||||
u64 output = ftell(file);
|
i64 output = wapp_file_get_current_position(file);
|
||||||
|
|
||||||
// Restore position
|
// Restore position
|
||||||
wapp_file_seek(file, current, WAPP_SEEK_START);
|
_file_seek(file, current, WAPP_SEEK_START);
|
||||||
|
|
||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
|
|
||||||
u64 wapp_file_read(Array *dst_buf, File *file, u64 item_count) {
|
u64 wapp_file_read(void *dst_buf, WFile *file, u64 byte_count) {
|
||||||
wapp_debug_assert(dst_buf != NULL && file != NULL,
|
wapp_debug_assert(dst_buf != NULL && file != NULL,
|
||||||
"`dst_buf` and `file` should not be NULL.");
|
"`dst_buf` and `file` should not be NULL.");
|
||||||
|
|
||||||
u64 file_length = wapp_file_get_length(file);
|
i64 file_length = wapp_file_get_length(file);
|
||||||
u64 item_size = dst_buf->item_size;
|
if (file_length < 0) {
|
||||||
u64 dst_byte_capacity = dst_buf->capacity * item_size;
|
return 0;
|
||||||
u64 req_byte_count = item_count * item_size;
|
}
|
||||||
u64 copy_byte_count = 0;
|
|
||||||
|
|
||||||
if (req_byte_count <= file_length && req_byte_count <= dst_byte_capacity) {
|
return _file_read(dst_buf, byte_count, file, file_length);
|
||||||
copy_byte_count = req_byte_count;
|
|
||||||
} else {
|
|
||||||
copy_byte_count = file_length <= dst_byte_capacity ? file_length : dst_byte_capacity;
|
|
||||||
}
|
|
||||||
|
|
||||||
u64 count = fread(dst_buf->items, sizeof(u8), copy_byte_count, file);
|
|
||||||
if (ferror(file)) { return 0; }
|
|
||||||
|
|
||||||
dst_buf->count = count / item_size;
|
|
||||||
|
|
||||||
return dst_buf->count;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
u64 wapp_file_write(const Array *src_buf, File *file, u64 item_count) {
|
i64 wapp_file_write(const void *src_buf, WFile *file, u64 byte_count) {
|
||||||
wapp_debug_assert(src_buf != NULL && file != NULL,
|
wapp_debug_assert(src_buf != NULL && file != NULL,
|
||||||
"`src_buf` and `file` should not be NULL.");
|
"`src_buf` and `file` should not be NULL.");
|
||||||
|
return _file_write(src_buf, file, byte_count);
|
||||||
u64 item_size = src_buf->item_size;
|
|
||||||
u64 src_byte_count = src_buf->count * item_size;
|
|
||||||
u64 req_byte_count = item_count * item_size;
|
|
||||||
u64 to_copy = req_byte_count <= src_byte_count ? req_byte_count : src_byte_count;
|
|
||||||
|
|
||||||
return fwrite(src_buf->items, sizeof(u8), to_copy, file);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
i32 wapp_file_flush(File *file) {
|
u64 wapp_file_read_array(GenericArray dst_buf, WFile *file, u64 item_count) {
|
||||||
wapp_debug_assert(file != NULL, "`file` should not be NULL.");
|
wapp_debug_assert(dst_buf != NULL && file != NULL,
|
||||||
return fflush(file);
|
"`dst_buf` and `file` should not be NULL.");
|
||||||
|
|
||||||
|
i64 _file_length = wapp_file_get_length(file);
|
||||||
|
if (_file_length < 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
u64 file_length = (u64)_file_length;
|
||||||
|
u64 item_size = wapp_array_item_size(dst_buf);
|
||||||
|
u64 dst_byte_capacity = wapp_array_capacity(dst_buf) * item_size;
|
||||||
|
u64 req_byte_count = item_count * item_size;
|
||||||
|
u64 copy_byte_count = 0;
|
||||||
|
|
||||||
|
if (req_byte_count <= file_length && req_byte_count <= dst_byte_capacity) {
|
||||||
|
copy_byte_count = req_byte_count;
|
||||||
|
} else {
|
||||||
|
copy_byte_count = file_length <= dst_byte_capacity ? file_length : dst_byte_capacity;
|
||||||
|
}
|
||||||
|
|
||||||
|
u64 byte_count = _file_read(dst_buf, copy_byte_count, file, file_length);
|
||||||
|
if (byte_count == 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
wapp_array_set_count(dst_buf, byte_count / item_size);
|
||||||
|
|
||||||
|
return wapp_array_count(dst_buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
i32 wapp_file_close(File *file) {
|
i64 wapp_file_write_array(const GenericArray src_buf, WFile *file, u64 item_count) {
|
||||||
wapp_debug_assert(file != NULL, "`file` should not be NULL.");
|
wapp_debug_assert(src_buf != NULL && file != NULL,
|
||||||
return fclose(file);
|
"`src_buf` and `file` should not be NULL.");
|
||||||
|
|
||||||
|
u64 item_size = wapp_array_item_size(src_buf);
|
||||||
|
u64 src_byte_count = wapp_array_count(src_buf) * item_size;
|
||||||
|
u64 req_byte_count = item_count * item_size;
|
||||||
|
u64 to_copy = req_byte_count <= src_byte_count ? req_byte_count : src_byte_count;
|
||||||
|
|
||||||
|
i64 bytes_written = _file_write(src_buf, file, to_copy);
|
||||||
|
if (bytes_written < 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (u64)bytes_written / item_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
i32 wapp_file_flush(WFile *file) {
|
||||||
|
wapp_debug_assert(file != NULL, "`file` should not be NULL.");
|
||||||
|
return _file_flush(file);
|
||||||
|
}
|
||||||
|
|
||||||
|
i32 wapp_file_close(WFile *file) {
|
||||||
|
wapp_debug_assert(file != NULL, "`file` should not be NULL.");
|
||||||
|
return _file_close(file);
|
||||||
|
}
|
||||||
|
|
||||||
|
i32 wapp_file_rename(Str8RO *old_filepath, Str8RO *new_filepath) {
|
||||||
|
wapp_debug_assert(old_filepath != NULL && new_filepath != NULL,
|
||||||
|
"`old_filepath` and `new_filepath` should not be NULL");
|
||||||
|
wapp_debug_assert(old_filepath->size < WAPP_PATH_MAX, "`old_filepath` exceeds max path limit.");
|
||||||
|
wapp_debug_assert(new_filepath->size < WAPP_PATH_MAX, "`new_filepath` exceeds max path limit.");
|
||||||
|
return _file_rename(old_filepath, new_filepath);
|
||||||
|
}
|
||||||
|
|
||||||
|
i32 wapp_file_remove(Str8RO *filepath) {
|
||||||
|
wapp_debug_assert(filepath != NULL, "`filepath` should not be NULL");
|
||||||
|
wapp_debug_assert(filepath->size < WAPP_PATH_MAX, "`filepath` exceeds max path limit.");
|
||||||
|
return _file_remove(filepath);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,51 +3,58 @@
|
|||||||
#ifndef FILE_H
|
#ifndef FILE_H
|
||||||
#define FILE_H
|
#define FILE_H
|
||||||
|
|
||||||
|
#include "../../base/mem/allocator/mem_allocator.h"
|
||||||
#include "../../common/aliases/aliases.h"
|
#include "../../common/aliases/aliases.h"
|
||||||
#include "../../base/strings/str8/str8.h"
|
#include "../../base/strings/str8/str8.h"
|
||||||
#include <stdio.h>
|
|
||||||
|
|
||||||
#ifdef WAPP_PLATFORM_CPP
|
#ifdef WAPP_PLATFORM_CPP
|
||||||
BEGIN_C_LINKAGE
|
BEGIN_C_LINKAGE
|
||||||
#endif // !WAPP_PLATFORM_CPP
|
#endif // !WAPP_PLATFORM_CPP
|
||||||
|
|
||||||
typedef FILE File;
|
typedef struct WFile WFile;
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
WAPP_FA_MODE_R, // Equivalent to r
|
WAPP_ACCESS_READ, // Equivalent to r
|
||||||
WAPP_FA_MODE_W, // Equivalent to w
|
WAPP_ACCESS_WRITE, // Equivalent to w
|
||||||
WAPP_FA_MODE_A, // Equivalent to a
|
WAPP_ACCESS_APPEND, // Equivalent to a
|
||||||
WAPP_FA_MODE_R_EX, // Equivalent to r+
|
WAPP_ACCESS_READ_EX, // Equivalent to r+
|
||||||
WAPP_FA_MODE_W_EX, // Equivalent to w+
|
WAPP_ACCESS_WRITE_EX, // Equivalent to w+
|
||||||
WAPP_FA_MODE_A_EX, // Equivalent to a+
|
WAPP_ACCESS_APPEND_EX, // Equivalent to a+
|
||||||
WAPP_FA_MODE_RB, // Equivalent to rb
|
WAPP_ACCESS_WRITE_FAIL_ON_EXIST, // Equivalent to wx
|
||||||
WAPP_FA_MODE_WB, // Equivalent to wb
|
WAPP_ACCESS_WRITE_FAIL_ON_EXIST_EX, // Equivalent to wx+
|
||||||
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,
|
FILE_ACCESS_MODE_COUNT,
|
||||||
} FileAccessMode;
|
} FileAccessMode;
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
WAPP_SEEK_START = SEEK_SET,
|
WAPP_SEEK_START,
|
||||||
WAPP_SEEK_CURRENT = SEEK_CUR,
|
WAPP_SEEK_CURRENT,
|
||||||
WAPP_SEEK_END = SEEK_END,
|
WAPP_SEEK_END,
|
||||||
|
|
||||||
|
FILE_SEEK_ORIGIN_COUNT,
|
||||||
} FileSeekOrigin;
|
} FileSeekOrigin;
|
||||||
|
|
||||||
File *wapp_file_open(Str8RO *filename, FileAccessMode mode);
|
WFile *wapp_file_open(const Allocator *allocator, Str8RO *filepath, FileAccessMode mode);
|
||||||
u64 wapp_file_get_current_position(File *file);
|
i64 wapp_file_get_current_position(WFile *file);
|
||||||
i32 wapp_file_seek(File *file, u64 offset, FileSeekOrigin origin);
|
i64 wapp_file_seek(WFile *file, i64 offset, FileSeekOrigin origin);
|
||||||
u64 wapp_file_get_length(File *file);
|
i64 wapp_file_get_length(WFile *file);
|
||||||
u64 wapp_file_read(Array *dst_buf, File *file, u64 item_count);
|
u64 wapp_file_read(void *dst_buf, WFile *file, u64 byte_count);
|
||||||
u64 wapp_file_write(const Array *src_buf, File *file, u64 item_count);
|
i64 wapp_file_write(const void *src_buf, WFile *file, u64 byte_count);
|
||||||
i32 wapp_file_flush(File *file);
|
u64 wapp_file_read_array(GenericArray dst_buf, WFile *file, u64 item_count);
|
||||||
i32 wapp_file_close(File *file);
|
i64 wapp_file_write_array(const GenericArray src_buf, WFile *file, u64 item_count);
|
||||||
|
i32 wapp_file_flush(WFile *file);
|
||||||
|
i32 wapp_file_close(WFile *file);
|
||||||
|
i32 wapp_file_rename(Str8RO *old_filepath, Str8RO *new_filepath);
|
||||||
|
i32 wapp_file_remove(Str8RO *filepath);
|
||||||
|
|
||||||
|
extern WFile *_file_open(const Allocator *allocator, Str8RO *filepath, FileAccessMode mode);
|
||||||
|
extern i64 _file_seek(WFile *file, i64 offset, FileSeekOrigin origin);
|
||||||
|
extern u64 _file_read(void *dst_buf, u64 byte_count, WFile *file, u64 file_length);
|
||||||
|
extern i64 _file_write(const void *src_buf, WFile *file, u64 byte_count);
|
||||||
|
extern i32 _file_flush(WFile *file);
|
||||||
|
extern i32 _file_close(WFile *file);
|
||||||
|
extern i32 _file_rename(Str8RO *old_filepath, Str8RO *new_filepath);
|
||||||
|
extern i32 _file_remove(Str8RO *filepath);
|
||||||
|
|
||||||
#ifdef WAPP_PLATFORM_CPP
|
#ifdef WAPP_PLATFORM_CPP
|
||||||
END_C_LINKAGE
|
END_C_LINKAGE
|
||||||
|
|||||||
119
src/os/file/posix/file_posix.c
Normal file
119
src/os/file/posix/file_posix.c
Normal file
@@ -0,0 +1,119 @@
|
|||||||
|
// vim:fileencoding=utf-8:foldmethod=marker
|
||||||
|
|
||||||
|
#include "file_posix.h"
|
||||||
|
#include "../../../common/platform/platform.h"
|
||||||
|
|
||||||
|
#ifdef WAPP_PLATFORM_POSIX
|
||||||
|
|
||||||
|
#include "../file.h"
|
||||||
|
#include "../../cpath/cpath.h"
|
||||||
|
#include "../../../common/aliases/aliases.h"
|
||||||
|
#include "../../../base/array/array.h"
|
||||||
|
#include "../../../base/strings/str8/str8.h"
|
||||||
|
|
||||||
|
#ifdef WAPP_PLATFORM_APPLE
|
||||||
|
#define _FILE_OFFSET_BITS 64
|
||||||
|
#define lseek64 lseek
|
||||||
|
#endif // !WAPP_PLATFORM_APPLE
|
||||||
|
|
||||||
|
#define __USE_LARGEFILE64
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
|
||||||
|
wapp_intern i32 file_flags[FILE_ACCESS_MODE_COUNT] = {
|
||||||
|
[WAPP_ACCESS_READ] = O_RDONLY,
|
||||||
|
[WAPP_ACCESS_WRITE] = O_WRONLY | O_CREAT,
|
||||||
|
[WAPP_ACCESS_APPEND] = O_WRONLY | O_APPEND | O_CREAT,
|
||||||
|
[WAPP_ACCESS_READ_EX] = O_RDWR,
|
||||||
|
[WAPP_ACCESS_WRITE_EX] = O_RDWR | O_CREAT,
|
||||||
|
[WAPP_ACCESS_APPEND_EX] = O_RDWR | O_APPEND | O_CREAT,
|
||||||
|
[WAPP_ACCESS_WRITE_FAIL_ON_EXIST] = O_WRONLY | O_CREAT | O_EXCL,
|
||||||
|
[WAPP_ACCESS_WRITE_FAIL_ON_EXIST_EX] = O_RDWR | O_CREAT | O_EXCL,
|
||||||
|
};
|
||||||
|
|
||||||
|
wapp_intern mode_t file_modes[FILE_ACCESS_MODE_COUNT] = {
|
||||||
|
[WAPP_ACCESS_READ] = 0,
|
||||||
|
[WAPP_ACCESS_WRITE] = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP,
|
||||||
|
[WAPP_ACCESS_APPEND] = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP,
|
||||||
|
[WAPP_ACCESS_READ_EX] = 0,
|
||||||
|
[WAPP_ACCESS_WRITE_EX] = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP,
|
||||||
|
[WAPP_ACCESS_APPEND_EX] = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP,
|
||||||
|
[WAPP_ACCESS_WRITE_FAIL_ON_EXIST] = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP,
|
||||||
|
[WAPP_ACCESS_WRITE_FAIL_ON_EXIST_EX] = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP,
|
||||||
|
};
|
||||||
|
|
||||||
|
wapp_intern i32 file_seek_origins[FILE_SEEK_ORIGIN_COUNT] = {
|
||||||
|
[WAPP_SEEK_START] = SEEK_SET,
|
||||||
|
[WAPP_SEEK_CURRENT] = SEEK_CUR,
|
||||||
|
[WAPP_SEEK_END] = SEEK_END,
|
||||||
|
};
|
||||||
|
|
||||||
|
WFile *_file_open(const Allocator *allocator, Str8RO *filepath, FileAccessMode mode) {
|
||||||
|
wapp_persist c8 tmp[WAPP_PATH_MAX] = {0};
|
||||||
|
memset(tmp, 0, WAPP_PATH_MAX);
|
||||||
|
memcpy(tmp, filepath->buf, filepath->size);
|
||||||
|
|
||||||
|
i32 fd = open((const char *)tmp, file_flags[mode], file_modes[mode]);
|
||||||
|
if (fd < 0) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
WFile *output = wapp_mem_allocator_alloc(allocator, sizeof(WFile));
|
||||||
|
if (output) {
|
||||||
|
output->fd = fd;
|
||||||
|
}
|
||||||
|
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
||||||
|
i64 _file_seek(WFile *file, i64 offset, FileSeekOrigin origin) {
|
||||||
|
return lseek64(file->fd, offset, file_seek_origins[origin]);
|
||||||
|
}
|
||||||
|
|
||||||
|
u64 _file_read(void *dst_buf, u64 byte_count, WFile *file, u64 file_length) {
|
||||||
|
u64 copy_byte_count = file_length <= byte_count ? file_length : byte_count;
|
||||||
|
|
||||||
|
i64 count = read(file->fd, dst_buf, copy_byte_count);
|
||||||
|
if (count < 0) { return 0; }
|
||||||
|
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
i64 _file_write(const void *src_buf, WFile *file, u64 byte_count) {
|
||||||
|
return write(file->fd, src_buf, byte_count);
|
||||||
|
}
|
||||||
|
|
||||||
|
i32 _file_flush(WFile *file) {
|
||||||
|
return fsync(file->fd);
|
||||||
|
}
|
||||||
|
|
||||||
|
i32 _file_close(WFile *file) {
|
||||||
|
return close(file->fd);
|
||||||
|
}
|
||||||
|
|
||||||
|
i32 _file_rename(Str8RO *old_filepath, Str8RO *new_filepath) {
|
||||||
|
wapp_persist c8 old_tmp[WAPP_PATH_MAX] = {0};
|
||||||
|
wapp_persist c8 new_tmp[WAPP_PATH_MAX] = {0};
|
||||||
|
memset(old_tmp, 0, WAPP_PATH_MAX);
|
||||||
|
memcpy(old_tmp, old_filepath->buf, old_filepath->size);
|
||||||
|
memset(new_tmp, 0, WAPP_PATH_MAX);
|
||||||
|
memcpy(new_tmp, new_filepath->buf, new_filepath->size);
|
||||||
|
|
||||||
|
i32 link_result = link((const char *)old_tmp, (const char *)new_tmp);
|
||||||
|
if (link_result == 0) {
|
||||||
|
_file_remove(old_filepath);
|
||||||
|
}
|
||||||
|
|
||||||
|
return link_result;
|
||||||
|
}
|
||||||
|
|
||||||
|
i32 _file_remove(Str8RO *filepath) {
|
||||||
|
wapp_persist c8 tmp[WAPP_PATH_MAX] = {0};
|
||||||
|
memset(tmp, 0, WAPP_PATH_MAX);
|
||||||
|
memcpy(tmp, filepath->buf, filepath->size);
|
||||||
|
|
||||||
|
return unlink((const char *)tmp);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // !WAPP_PLATFORM_POSIX
|
||||||
27
src/os/file/posix/file_posix.h
Normal file
27
src/os/file/posix/file_posix.h
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
// vim:fileencoding=utf-8:foldmethod=marker
|
||||||
|
|
||||||
|
#ifndef FILE_POSIX_H
|
||||||
|
#define FILE_POSIX_H
|
||||||
|
|
||||||
|
#include "../../../common/aliases/aliases.h"
|
||||||
|
#include "../../../common/platform/platform.h"
|
||||||
|
|
||||||
|
#ifdef WAPP_PLATFORM_CPP
|
||||||
|
BEGIN_C_LINKAGE
|
||||||
|
#endif // !WAPP_PLATFORM_CPP
|
||||||
|
|
||||||
|
#ifdef WAPP_PLATFORM_POSIX
|
||||||
|
|
||||||
|
#define END_OF_LINE "\n"
|
||||||
|
|
||||||
|
struct WFile {
|
||||||
|
i32 fd;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // !WAPP_PLATFORM_POSIX
|
||||||
|
|
||||||
|
#ifdef WAPP_PLATFORM_CPP
|
||||||
|
END_C_LINKAGE
|
||||||
|
#endif // !WAPP_PLATFORM_CPP
|
||||||
|
|
||||||
|
#endif // !FILE_POSIX_H
|
||||||
159
src/os/file/win/file_win.c
Normal file
159
src/os/file/win/file_win.c
Normal file
@@ -0,0 +1,159 @@
|
|||||||
|
// vim:fileencoding=utf-8:foldmethod=marker
|
||||||
|
|
||||||
|
#include "file_win.h"
|
||||||
|
#include "../../../common/platform/platform.h"
|
||||||
|
|
||||||
|
#ifdef WAPP_PLATFORM_WINDOWS
|
||||||
|
|
||||||
|
#include "../file.h"
|
||||||
|
#include "../../cpath/cpath.h"
|
||||||
|
#include "../../../common/aliases/aliases.h"
|
||||||
|
#include "../../../base/array/array.h"
|
||||||
|
#include "../../../base/strings/str8/str8.h"
|
||||||
|
#define WIN32_LEAN_AND_MEAN
|
||||||
|
#include <Windows.h>
|
||||||
|
#include <fileapi.h>
|
||||||
|
#include <intsafe.h>
|
||||||
|
|
||||||
|
wapp_intern DWORD file_accesses[FILE_ACCESS_MODE_COUNT] = {
|
||||||
|
[WAPP_ACCESS_READ] = FILE_READ_DATA,
|
||||||
|
[WAPP_ACCESS_WRITE] = FILE_WRITE_DATA,
|
||||||
|
[WAPP_ACCESS_APPEND] = FILE_APPEND_DATA,
|
||||||
|
[WAPP_ACCESS_READ_EX] = FILE_READ_DATA | FILE_WRITE_DATA,
|
||||||
|
[WAPP_ACCESS_WRITE_EX] = FILE_READ_DATA | FILE_WRITE_DATA,
|
||||||
|
[WAPP_ACCESS_APPEND_EX] = FILE_READ_DATA | FILE_APPEND_DATA,
|
||||||
|
[WAPP_ACCESS_WRITE_FAIL_ON_EXIST] = FILE_WRITE_DATA,
|
||||||
|
[WAPP_ACCESS_WRITE_FAIL_ON_EXIST_EX] = FILE_READ_DATA | FILE_WRITE_DATA,
|
||||||
|
};
|
||||||
|
|
||||||
|
wapp_intern DWORD creation_dispositions[FILE_ACCESS_MODE_COUNT] = {
|
||||||
|
[WAPP_ACCESS_READ] = OPEN_EXISTING,
|
||||||
|
[WAPP_ACCESS_WRITE] = CREATE_ALWAYS,
|
||||||
|
[WAPP_ACCESS_APPEND] = OPEN_ALWAYS,
|
||||||
|
[WAPP_ACCESS_READ_EX] = OPEN_EXISTING,
|
||||||
|
[WAPP_ACCESS_WRITE_EX] = CREATE_ALWAYS,
|
||||||
|
[WAPP_ACCESS_APPEND_EX] = OPEN_ALWAYS,
|
||||||
|
[WAPP_ACCESS_WRITE_FAIL_ON_EXIST] = CREATE_NEW,
|
||||||
|
[WAPP_ACCESS_WRITE_FAIL_ON_EXIST_EX] = CREATE_NEW,
|
||||||
|
};
|
||||||
|
|
||||||
|
wapp_intern DWORD sharing_modes[FILE_ACCESS_MODE_COUNT] = {
|
||||||
|
[WAPP_ACCESS_READ] = FILE_SHARE_READ | FILE_SHARE_WRITE,
|
||||||
|
[WAPP_ACCESS_WRITE] = FILE_SHARE_READ,
|
||||||
|
[WAPP_ACCESS_APPEND] = FILE_SHARE_READ,
|
||||||
|
[WAPP_ACCESS_READ_EX] = FILE_SHARE_READ | FILE_SHARE_WRITE,
|
||||||
|
[WAPP_ACCESS_WRITE_EX] = FILE_SHARE_READ,
|
||||||
|
[WAPP_ACCESS_APPEND_EX] = FILE_SHARE_READ,
|
||||||
|
[WAPP_ACCESS_WRITE_FAIL_ON_EXIST] = FILE_SHARE_READ,
|
||||||
|
[WAPP_ACCESS_WRITE_FAIL_ON_EXIST_EX] = FILE_SHARE_READ,
|
||||||
|
};
|
||||||
|
|
||||||
|
wapp_intern DWORD file_seek_origins[FILE_SEEK_ORIGIN_COUNT] = {
|
||||||
|
[WAPP_SEEK_START] = FILE_BEGIN,
|
||||||
|
[WAPP_SEEK_CURRENT] = FILE_CURRENT,
|
||||||
|
[WAPP_SEEK_END] = FILE_END,
|
||||||
|
};
|
||||||
|
|
||||||
|
WFile *_file_open(const Allocator *allocator, Str8RO *filepath, FileAccessMode mode) {
|
||||||
|
wapp_persist c8 tmp[WAPP_PATH_MAX] = {0};
|
||||||
|
memset(tmp, 0, WAPP_PATH_MAX);
|
||||||
|
memcpy(tmp, filepath->buf, filepath->size);
|
||||||
|
|
||||||
|
HANDLE fh = CreateFileA((LPCSTR)tmp,
|
||||||
|
file_accesses[mode],
|
||||||
|
sharing_modes[mode],
|
||||||
|
NULL,
|
||||||
|
creation_dispositions[mode],
|
||||||
|
FILE_ATTRIBUTE_NORMAL,
|
||||||
|
NULL);
|
||||||
|
if (fh == INVALID_HANDLE_VALUE) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
WFile *output = wapp_mem_allocator_alloc(allocator, sizeof(WFile));
|
||||||
|
if (output) {
|
||||||
|
output->fh = fh;
|
||||||
|
}
|
||||||
|
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
||||||
|
i64 _file_seek(WFile *file, i64 offset, FileSeekOrigin origin) {
|
||||||
|
LARGE_INTEGER distance = {0};
|
||||||
|
LARGE_INTEGER output = {0};
|
||||||
|
|
||||||
|
distance.QuadPart = offset;
|
||||||
|
|
||||||
|
if (!SetFilePointerEx(file->fh, distance, &output, file_seek_origins[origin])) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return output.QuadPart;
|
||||||
|
}
|
||||||
|
|
||||||
|
u64 _file_read(void* dst_buf, u64 byte_count, WFile* file, u64 file_length) {
|
||||||
|
u64 copy_byte_count = file_length <= byte_count ? file_length : byte_count;
|
||||||
|
wapp_debug_assert(copy_byte_count <= DWORD_MAX, "Attempting to read large number of bytes at once");
|
||||||
|
|
||||||
|
DWORD read_count = 0;
|
||||||
|
if (!ReadFile(file->fh, dst_buf, (DWORD)copy_byte_count, &read_count, NULL)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (u64)read_count;
|
||||||
|
}
|
||||||
|
|
||||||
|
i64 _file_write(const void *src_buf, WFile *file, u64 byte_count) {
|
||||||
|
wapp_debug_assert(byte_count <= DWORD_MAX, "Attempting to write large number of bytes at once");
|
||||||
|
|
||||||
|
DWORD write_count = 0;
|
||||||
|
if (!WriteFile(file->fh, src_buf, (DWORD)byte_count, &write_count, NULL)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return (i64)write_count;
|
||||||
|
}
|
||||||
|
|
||||||
|
i32 _file_flush(WFile *file) {
|
||||||
|
if (!FlushFileBuffers(file->fh)) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
i32 _file_close(WFile *file) {
|
||||||
|
if (!CloseHandle(file->fh)) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
i32 _file_rename(Str8RO *old_filepath, Str8RO *new_filepath) {
|
||||||
|
wapp_persist c8 old_tmp[WAPP_PATH_MAX] = {0};
|
||||||
|
wapp_persist c8 new_tmp[WAPP_PATH_MAX] = {0};
|
||||||
|
memset(old_tmp, 0, WAPP_PATH_MAX);
|
||||||
|
memcpy(old_tmp, old_filepath->buf, old_filepath->size);
|
||||||
|
memset(new_tmp, 0, WAPP_PATH_MAX);
|
||||||
|
memcpy(new_tmp, new_filepath->buf, new_filepath->size);
|
||||||
|
|
||||||
|
if (!MoveFile((LPCSTR)old_tmp, (LPCSTR)new_tmp)) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
i32 _file_remove(Str8RO *filepath) {
|
||||||
|
wapp_persist c8 tmp[WAPP_PATH_MAX] = {0};
|
||||||
|
memset(tmp, 0, WAPP_PATH_MAX);
|
||||||
|
memcpy(tmp, filepath->buf, filepath->size);
|
||||||
|
|
||||||
|
if (!DeleteFile((LPCSTR)tmp)) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // !WAPP_PLATFORM_WINDOWS
|
||||||
31
src/os/file/win/file_win.h
Normal file
31
src/os/file/win/file_win.h
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
// vim:fileencoding=utf-8:foldmethod=marker
|
||||||
|
|
||||||
|
#ifndef FILE_WIN_H
|
||||||
|
#define FILE_WIN_H
|
||||||
|
|
||||||
|
#include "../../../common/aliases/aliases.h"
|
||||||
|
#include "../../../common/platform/platform.h"
|
||||||
|
|
||||||
|
#ifdef WAPP_PLATFORM_CPP
|
||||||
|
BEGIN_C_LINKAGE
|
||||||
|
#endif // !WAPP_PLATFORM_CPP
|
||||||
|
|
||||||
|
#ifdef WAPP_PLATFORM_WINDOWS
|
||||||
|
|
||||||
|
#define END_OF_LINE "\r\n"
|
||||||
|
|
||||||
|
#define WIN32_LEAN_AND_MEAN
|
||||||
|
#include <Windows.h>
|
||||||
|
#include <fileapi.h>
|
||||||
|
|
||||||
|
struct WFile {
|
||||||
|
HANDLE fh;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // !WAPP_PLATFORM_WINDOWS
|
||||||
|
|
||||||
|
#ifdef WAPP_PLATFORM_CPP
|
||||||
|
END_C_LINKAGE
|
||||||
|
#endif // !WAPP_PLATFORM_CPP
|
||||||
|
|
||||||
|
#endif // !FILE_WIN_H
|
||||||
@@ -15,16 +15,16 @@
|
|||||||
#error "Unrecognised platform"
|
#error "Unrecognised platform"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void *wapp_mem_util_alloc(void *addr, u64 size, MemAccess access, MemAllocFlags flags, MemInitType type) {
|
void *wapp_os_mem_alloc(void *addr, u64 size, MemAccess access, MemAllocFlags flags, MemInitType type) {
|
||||||
void *output = mem_util_allocate(addr, size, access, flags, type);
|
void *output = os_mem_allocate(addr, size, access, flags, type);
|
||||||
|
|
||||||
if (type == WAPP_MEM_INIT_INITIALISED) {
|
if (type == WAPP_MEM_INIT_INITIALISED) {
|
||||||
memset(output, 0, size);
|
memset(output, 0, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
|
|
||||||
void wapp_mem_util_free(void *ptr, u64 size) {
|
void wapp_os_mem_free(void *ptr, u64 size) {
|
||||||
mem_util_free(ptr, size);
|
os_mem_free(ptr, size);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,11 +20,11 @@ BEGIN_C_LINKAGE
|
|||||||
#error "Unrecognised platform"
|
#error "Unrecognised platform"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void *wapp_mem_util_alloc(void *addr, u64 size, MemAccess access, MemAllocFlags flags, MemInitType type);
|
void *wapp_os_mem_alloc(void *addr, u64 size, MemAccess access, MemAllocFlags flags, MemInitType type);
|
||||||
void wapp_mem_util_free(void *ptr, u64 size);
|
void wapp_os_mem_free(void *ptr, u64 size);
|
||||||
|
|
||||||
wapp_extern void *mem_util_allocate(void *addr, u64 size, MemAccess access, MemAllocFlags flags, MemInitType type);
|
wapp_extern void *os_mem_allocate(void *addr, u64 size, MemAccess access, MemAllocFlags flags, MemInitType type);
|
||||||
wapp_extern void mem_util_free(void *ptr, u64 size);
|
wapp_extern void os_mem_free(void *ptr, u64 size);
|
||||||
|
|
||||||
#ifdef WAPP_PLATFORM_CPP
|
#ifdef WAPP_PLATFORM_CPP
|
||||||
END_C_LINKAGE
|
END_C_LINKAGE
|
||||||
|
|||||||
@@ -10,17 +10,17 @@ BEGIN_C_LINKAGE
|
|||||||
#endif // !WAPP_PLATFORM_CPP
|
#endif // !WAPP_PLATFORM_CPP
|
||||||
|
|
||||||
typedef enum mem_access {
|
typedef enum mem_access {
|
||||||
WAPP_MEM_ACCESS_NONE,
|
WAPP_MEM_ACCESS_NONE,
|
||||||
WAPP_MEM_ACCESS_READ_ONLY,
|
WAPP_MEM_ACCESS_READ_ONLY,
|
||||||
WAPP_MEM_ACCESS_EXEC_ONLY,
|
WAPP_MEM_ACCESS_EXEC_ONLY,
|
||||||
WAPP_MEM_ACCESS_READ_WRITE,
|
WAPP_MEM_ACCESS_READ_WRITE,
|
||||||
WAPP_MEM_ACCESS_READ_EXEC,
|
WAPP_MEM_ACCESS_READ_EXEC,
|
||||||
WAPP_MEM_ACCESS_READ_WRITE_EXEC,
|
WAPP_MEM_ACCESS_READ_WRITE_EXEC,
|
||||||
} MemAccess;
|
} MemAccess;
|
||||||
|
|
||||||
typedef enum mem_init_type {
|
typedef enum mem_init_type {
|
||||||
WAPP_MEM_INIT_UNINITIALISED,
|
WAPP_MEM_INIT_UNINITIALISED,
|
||||||
WAPP_MEM_INIT_INITIALISED,
|
WAPP_MEM_INIT_INITIALISED,
|
||||||
} MemInitType;
|
} MemInitType;
|
||||||
|
|
||||||
#ifdef WAPP_PLATFORM_CPP
|
#ifdef WAPP_PLATFORM_CPP
|
||||||
|
|||||||
@@ -10,27 +10,27 @@
|
|||||||
#include <sys/mman.h>
|
#include <sys/mman.h>
|
||||||
|
|
||||||
wapp_intern const i32 access_types[] = {
|
wapp_intern const i32 access_types[] = {
|
||||||
[WAPP_MEM_ACCESS_NONE] = PROT_NONE,
|
[WAPP_MEM_ACCESS_NONE] = PROT_NONE,
|
||||||
[WAPP_MEM_ACCESS_READ_ONLY] = PROT_READ,
|
[WAPP_MEM_ACCESS_READ_ONLY] = PROT_READ,
|
||||||
[WAPP_MEM_ACCESS_EXEC_ONLY] = PROT_EXEC,
|
[WAPP_MEM_ACCESS_EXEC_ONLY] = PROT_EXEC,
|
||||||
[WAPP_MEM_ACCESS_READ_WRITE] = PROT_READ | PROT_WRITE,
|
[WAPP_MEM_ACCESS_READ_WRITE] = PROT_READ | PROT_WRITE,
|
||||||
[WAPP_MEM_ACCESS_READ_EXEC] = PROT_READ | PROT_EXEC,
|
[WAPP_MEM_ACCESS_READ_EXEC] = PROT_READ | PROT_EXEC,
|
||||||
[WAPP_MEM_ACCESS_READ_WRITE_EXEC] = PROT_READ | PROT_WRITE | 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 *os_mem_allocate(void *addr, u64 size, MemAccess access, MemAllocFlags flags, MemInitType type) {
|
||||||
(void)type;
|
(void)type;
|
||||||
i32 alloc_flags = flags | MAP_ANON | MAP_PRIVATE;
|
i32 alloc_flags = flags | MAP_ANON | MAP_PRIVATE;
|
||||||
|
|
||||||
#if defined(WAPP_PLATFORM_LINUX) || defined(WAPP_PLATFORM_GNU) || defined(WAPP_PLATFORM_NET_BSD)
|
#if defined(WAPP_PLATFORM_LINUX) || defined(WAPP_PLATFORM_GNU) || defined(WAPP_PLATFORM_NET_BSD)
|
||||||
alloc_flags |= MAP_NORESERVE;
|
alloc_flags |= MAP_NORESERVE;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return mmap(addr, size, access_types[access], alloc_flags, -1, 0);
|
return mmap(addr, size, access_types[access], alloc_flags, -1, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void mem_util_free(void *ptr, u64 size) {
|
void os_mem_free(void *ptr, u64 size) {
|
||||||
munmap(ptr, size);
|
munmap(ptr, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // !WAPP_PLATFORM_POSIX
|
#endif // !WAPP_PLATFORM_POSIX
|
||||||
|
|||||||
@@ -15,14 +15,14 @@ BEGIN_C_LINKAGE
|
|||||||
|
|
||||||
typedef enum mem_alloc_flags {
|
typedef enum mem_alloc_flags {
|
||||||
#if defined(WAPP_PLATFORM_LINUX) || defined(WAPP_PLATFORM_GNU)
|
#if defined(WAPP_PLATFORM_LINUX) || defined(WAPP_PLATFORM_GNU)
|
||||||
WAPP_MEM_ALLOC_RESERVE = 0,
|
WAPP_MEM_ALLOC_RESERVE = 0,
|
||||||
WAPP_MEM_ALLOC_COMMIT = MAP_POPULATE,
|
WAPP_MEM_ALLOC_COMMIT = MAP_POPULATE,
|
||||||
#elif defined(WAPP_PLATFORM_FREE_BSD)
|
#elif defined(WAPP_PLATFORM_FREE_BSD)
|
||||||
WAPP_MEM_ALLOC_RESERVE = 0,
|
WAPP_MEM_ALLOC_RESERVE = 0,
|
||||||
WAPP_MEM_ALLOC_COMMIT = MAP_PREFAULT_READ,
|
WAPP_MEM_ALLOC_COMMIT = MAP_PREFAULT_READ,
|
||||||
#elif defined(WAPP_PLATFORM_BSD) || defined(WAPP_PLATFORM_UNIX) || defined(WAPP_PLATFORM_APPLE)
|
#elif defined(WAPP_PLATFORM_BSD) || defined(WAPP_PLATFORM_UNIX) || defined(WAPP_PLATFORM_APPLE)
|
||||||
WAPP_MEM_ALLOC_RESERVE = 0,
|
WAPP_MEM_ALLOC_RESERVE = 0,
|
||||||
WAPP_MEM_ALLOC_COMMIT = 0,
|
WAPP_MEM_ALLOC_COMMIT = 0,
|
||||||
#endif
|
#endif
|
||||||
} MemAllocFlags;
|
} MemAllocFlags;
|
||||||
|
|
||||||
|
|||||||
@@ -13,25 +13,25 @@
|
|||||||
#include <memoryapi.h>
|
#include <memoryapi.h>
|
||||||
|
|
||||||
wapp_intern const i32 access_types[] = {
|
wapp_intern const i32 access_types[] = {
|
||||||
[WAPP_MEM_ACCESS_NONE] = PAGE_NOACCESS,
|
[WAPP_MEM_ACCESS_NONE] = PAGE_NOACCESS,
|
||||||
[WAPP_MEM_ACCESS_READ_ONLY] = PAGE_READONLY,
|
[WAPP_MEM_ACCESS_READ_ONLY] = PAGE_READONLY,
|
||||||
[WAPP_MEM_ACCESS_EXEC_ONLY] = PAGE_EXECUTE,
|
[WAPP_MEM_ACCESS_EXEC_ONLY] = PAGE_EXECUTE,
|
||||||
[WAPP_MEM_ACCESS_READ_WRITE] = PAGE_READWRITE,
|
[WAPP_MEM_ACCESS_READ_WRITE] = PAGE_READWRITE,
|
||||||
[WAPP_MEM_ACCESS_READ_EXEC] = PAGE_EXECUTE_READ,
|
[WAPP_MEM_ACCESS_READ_EXEC] = PAGE_EXECUTE_READ,
|
||||||
[WAPP_MEM_ACCESS_READ_WRITE_EXEC] = PAGE_EXECUTE_READWRITE,
|
[WAPP_MEM_ACCESS_READ_WRITE_EXEC] = PAGE_EXECUTE_READWRITE,
|
||||||
};
|
};
|
||||||
|
|
||||||
void *mem_util_allocate(void *addr, u64 size, MemAccess access, MemAllocFlags flags, MemInitType type) {
|
void *os_mem_allocate(void *addr, u64 size, MemAccess access, MemAllocFlags flags, MemInitType type) {
|
||||||
// Ensure memory is committed if it's meant to be initialised
|
// Ensure memory is committed if it's meant to be initialised
|
||||||
if (type == WAPP_MEM_INIT_INITIALISED) {
|
if (type == WAPP_MEM_INIT_INITIALISED) {
|
||||||
flags |= WAPP_MEM_ALLOC_COMMIT;
|
flags |= WAPP_MEM_ALLOC_COMMIT;
|
||||||
}
|
}
|
||||||
|
|
||||||
return VirtualAlloc(addr, (SIZE_T)size, flags, access_types[access]);
|
return VirtualAlloc(addr, (SIZE_T)size, flags, access_types[access]);
|
||||||
}
|
}
|
||||||
|
|
||||||
void mem_util_free(void *ptr, u64 size) {
|
void os_mem_free(void *ptr, u64 size) {
|
||||||
VirtualFree(ptr, size, MEM_RELEASE);
|
VirtualFree(ptr, size, MEM_RELEASE);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // !WAPP_PLATFORM_WINDOWS
|
#endif // !WAPP_PLATFORM_WINDOWS
|
||||||
|
|||||||
@@ -16,8 +16,8 @@ BEGIN_C_LINKAGE
|
|||||||
#include <memoryapi.h>
|
#include <memoryapi.h>
|
||||||
|
|
||||||
typedef enum mem_alloc_flags {
|
typedef enum mem_alloc_flags {
|
||||||
WAPP_MEM_ALLOC_RESERVE = MEM_RESERVE,
|
WAPP_MEM_ALLOC_RESERVE = MEM_RESERVE,
|
||||||
WAPP_MEM_ALLOC_COMMIT = MEM_COMMIT,
|
WAPP_MEM_ALLOC_COMMIT = MEM_COMMIT,
|
||||||
} MemAllocFlags;
|
} MemAllocFlags;
|
||||||
|
|
||||||
#endif // !WAPP_PLATFORM_WINDOWS
|
#endif // !WAPP_PLATFORM_WINDOWS
|
||||||
|
|||||||
@@ -17,85 +17,85 @@
|
|||||||
#define CMD_BUF_LEN 8192
|
#define CMD_BUF_LEN 8192
|
||||||
#define OUT_BUF_LEN 4096
|
#define OUT_BUF_LEN 4096
|
||||||
|
|
||||||
wapp_intern inline CMDResult execute_command(Str8RO *cmd, CMDOutHandling out_handling, Str8 *out_buf);
|
wapp_intern CMDResult execute_command(Str8RO *cmd, CMDOutHandling out_handling, Str8 *out_buf);
|
||||||
wapp_intern inline CMDError get_command_output(FILE *fp, CMDOutHandling out_handling, Str8 *out_buf);
|
wapp_intern 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) {
|
CMDResult wapp_shell_commander_execute(CMDOutHandling out_handling, Str8 *out_buf, const Str8List *cmd) {
|
||||||
if (!cmd) {
|
if (!cmd) {
|
||||||
return CMD_NO_EXIT(SHELL_ERR_INVALID_ARGS);
|
return CMD_NO_EXIT(SHELL_ERR_INVALID_ARGS);
|
||||||
}
|
}
|
||||||
|
|
||||||
Allocator arena = wapp_mem_arena_allocator_init(KB(500));
|
Allocator arena = wapp_mem_arena_allocator_init(KiB(500));
|
||||||
|
|
||||||
Str8 *cmd_str = wapp_str8_join(&arena, cmd, &wapp_str8_lit_ro(" "));
|
Str8 *cmd_str = wapp_str8_join(&arena, cmd, &wapp_str8_lit_ro(" "));
|
||||||
if (!cmd_str) {
|
if (!cmd_str) {
|
||||||
wapp_mem_arena_allocator_destroy(&arena);
|
wapp_mem_arena_allocator_destroy(&arena);
|
||||||
return CMD_NO_EXIT(SHELL_ERR_ALLOCATION_FAIL);
|
return CMD_NO_EXIT(SHELL_ERR_ALLOCATION_FAIL);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Redirect output
|
// Redirect output
|
||||||
cmd_str = wapp_str8_alloc_concat(&arena, cmd_str, &wapp_str8_lit_ro(" 2>&1"));
|
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);
|
CMDResult output = execute_command(cmd_str, out_handling, out_buf);
|
||||||
|
|
||||||
wapp_mem_arena_allocator_destroy(&arena);
|
wapp_mem_arena_allocator_destroy(&arena);
|
||||||
|
|
||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
|
|
||||||
wapp_intern inline CMDResult execute_command(Str8RO *cmd, CMDOutHandling out_handling, Str8 *out_buf) {
|
wapp_intern CMDResult execute_command(Str8RO *cmd, CMDOutHandling out_handling, Str8 *out_buf) {
|
||||||
char cmd_buf[CMD_BUF_LEN] = {0};
|
char cmd_buf[CMD_BUF_LEN] = {0};
|
||||||
wapp_str8_copy_to_cstr(cmd_buf, cmd, CMD_BUF_LEN);
|
wapp_str8_copy_to_cstr(cmd_buf, cmd, CMD_BUF_LEN);
|
||||||
|
|
||||||
FILE *fp = wapp_shell_utils_popen(cmd_buf, "r");
|
FILE *fp = wapp_shell_utils_popen(cmd_buf, "r");
|
||||||
if (!fp) {
|
if (!fp) {
|
||||||
return CMD_NO_EXIT(SHELL_ERR_PROC_START_FAIL);
|
return CMD_NO_EXIT(SHELL_ERR_PROC_START_FAIL);
|
||||||
}
|
}
|
||||||
|
|
||||||
CMDResult output;
|
CMDResult output;
|
||||||
|
|
||||||
CMDError err = get_command_output(fp, out_handling, out_buf);
|
CMDError err = get_command_output(fp, out_handling, out_buf);
|
||||||
if (err > SHELL_ERR_NO_ERROR) {
|
if (err > SHELL_ERR_NO_ERROR) {
|
||||||
output = CMD_NO_EXIT(err);
|
output = CMD_NO_EXIT(err);
|
||||||
goto EXECUTE_COMMAND_CLOSE;
|
goto EXECUTE_COMMAND_CLOSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
i32 st = EXIT_SUCCESS;
|
i32 st = EXIT_SUCCESS;
|
||||||
err = get_output_status(fp, &st);
|
err = get_output_status(fp, &st);
|
||||||
if (err > SHELL_ERR_NO_ERROR) {
|
if (err > SHELL_ERR_NO_ERROR) {
|
||||||
output = CMD_NO_EXIT(err);
|
output = CMD_NO_EXIT(err);
|
||||||
goto EXECUTE_COMMAND_CLOSE;
|
goto EXECUTE_COMMAND_CLOSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Process is already closed in get_output_status
|
// Process is already closed in get_output_status
|
||||||
fp = NULL;
|
fp = NULL;
|
||||||
|
|
||||||
output = (CMDResult){
|
output = (CMDResult){
|
||||||
.exited = true,
|
.exited = true,
|
||||||
.exit_code = st,
|
.exit_code = st,
|
||||||
.error = SHELL_ERR_NO_ERROR,
|
.error = SHELL_ERR_NO_ERROR,
|
||||||
};
|
};
|
||||||
|
|
||||||
EXECUTE_COMMAND_CLOSE:
|
EXECUTE_COMMAND_CLOSE:
|
||||||
if (fp) {
|
if (fp) {
|
||||||
wapp_shell_utils_pclose(fp);
|
wapp_shell_utils_pclose(fp);
|
||||||
}
|
}
|
||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
|
|
||||||
wapp_intern inline CMDError get_command_output(FILE *fp, CMDOutHandling out_handling, Str8 *out_buf) {
|
wapp_intern CMDError get_command_output(FILE *fp, CMDOutHandling out_handling, Str8 *out_buf) {
|
||||||
Str8 out = wapp_str8_buf(OUT_BUF_LEN);
|
Str8 out = wapp_str8_buf(OUT_BUF_LEN);
|
||||||
|
|
||||||
out.size = fread((void *)out.buf, sizeof(u8), out.capacity, fp);
|
out.size = fread((void *)out.buf, sizeof(u8), out.capacity, fp);
|
||||||
if (out_handling == SHELL_OUTPUT_CAPTURE && out_buf != NULL) {
|
if (out_handling == SHELL_OUTPUT_CAPTURE && out_buf != NULL) {
|
||||||
if (out.size >= out_buf->capacity) {
|
if (out.size >= out_buf->capacity) {
|
||||||
return SHELL_ERR_OUT_BUF_FULL;
|
return SHELL_ERR_OUT_BUF_FULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
wapp_str8_concat_capped(out_buf, &out);
|
wapp_str8_concat_capped(out_buf, &out);
|
||||||
} else if (out_handling == SHELL_OUTPUT_PRINT) {
|
} else if (out_handling == SHELL_OUTPUT_PRINT) {
|
||||||
printf(WAPP_STR8_SPEC, wapp_str8_varg(out));
|
printf(WAPP_STR8_SPEC, wapp_str8_varg(out));
|
||||||
}
|
}
|
||||||
|
|
||||||
return SHELL_ERR_NO_ERROR;
|
return SHELL_ERR_NO_ERROR;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,36 +5,34 @@
|
|||||||
|
|
||||||
#include "../../../common/aliases/aliases.h"
|
#include "../../../common/aliases/aliases.h"
|
||||||
#include "../../../common/platform/platform.h"
|
#include "../../../common/platform/platform.h"
|
||||||
|
#include "../../../common/misc/misc_utils.h"
|
||||||
|
|
||||||
#ifdef WAPP_PLATFORM_CPP
|
#ifdef WAPP_PLATFORM_CPP
|
||||||
BEGIN_C_LINKAGE
|
BEGIN_C_LINKAGE
|
||||||
#endif // !WAPP_PLATFORM_CPP
|
#endif // !WAPP_PLATFORM_CPP
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
SHELL_OUTPUT_DISCARD,
|
SHELL_OUTPUT_DISCARD,
|
||||||
SHELL_OUTPUT_PRINT,
|
SHELL_OUTPUT_PRINT,
|
||||||
SHELL_OUTPUT_CAPTURE,
|
SHELL_OUTPUT_CAPTURE,
|
||||||
} CMDOutHandling;
|
} CMDOutHandling;
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
SHELL_ERR_NO_ERROR,
|
SHELL_ERR_NO_ERROR,
|
||||||
SHELL_ERR_INVALID_ARGS,
|
SHELL_ERR_INVALID_ARGS,
|
||||||
SHELL_ERR_ALLOCATION_FAIL,
|
SHELL_ERR_ALLOCATION_FAIL,
|
||||||
SHELL_ERR_PROC_START_FAIL,
|
SHELL_ERR_PROC_START_FAIL,
|
||||||
SHELL_ERR_OUT_BUF_FULL,
|
SHELL_ERR_OUT_BUF_FULL,
|
||||||
SHELL_ERR_PROC_EXIT_FAIL,
|
SHELL_ERR_PROC_EXIT_FAIL,
|
||||||
} CMDError;
|
} CMDError;
|
||||||
|
|
||||||
typedef struct commander_result CMDResult;
|
typedef struct CMDResult CMDResult;
|
||||||
struct commander_result {
|
struct CMDResult {
|
||||||
i32 exit_code;
|
i32 exit_code;
|
||||||
CMDError error;
|
CMDError error;
|
||||||
b8 exited;
|
b8 exited;
|
||||||
|
|
||||||
#ifdef WAPP_PLATFORM_WINDOWS
|
wapp_misc_utils_reserve_padding(sizeof(b8) + sizeof(i32) + sizeof(CMDError));
|
||||||
#include "../../../../common/misc/misc_utils.h"
|
|
||||||
wapp_misc_utils_padding_size(sizeof(b8) + sizeof(i32) + sizeof(CMDError));
|
|
||||||
#endif // !WAPP_PLATFORM_WINDOWS
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifdef WAPP_PLATFORM_CPP
|
#ifdef WAPP_PLATFORM_CPP
|
||||||
|
|||||||
@@ -11,15 +11,15 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
CMDError get_output_status(FILE *fp, i32 *status_out) {
|
CMDError get_output_status(FILE *fp, i32 *status_out) {
|
||||||
*status_out = wapp_shell_utils_pclose(fp);
|
*status_out = wapp_shell_utils_pclose(fp);
|
||||||
|
|
||||||
if (!WIFEXITED(*status_out)) {
|
if (!WIFEXITED(*status_out)) {
|
||||||
return SHELL_ERR_PROC_EXIT_FAIL;
|
return SHELL_ERR_PROC_EXIT_FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
*status_out = WEXITSTATUS(*status_out);
|
*status_out = WEXITSTATUS(*status_out);
|
||||||
|
|
||||||
return SHELL_ERR_NO_ERROR;
|
return SHELL_ERR_NO_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // !WAPP_PLATFORM_POSIX
|
#endif // !WAPP_PLATFORM_POSIX
|
||||||
|
|||||||
@@ -10,15 +10,15 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
CMDError get_output_status(FILE *fp, i32 *status_out) {
|
CMDError get_output_status(FILE *fp, i32 *status_out) {
|
||||||
if (!feof(fp)) {
|
if (!feof(fp)) {
|
||||||
// Ensure process is closed on failure
|
// Ensure process is closed on failure
|
||||||
wapp_shell_utils_pclose(fp);
|
wapp_shell_utils_pclose(fp);
|
||||||
return SHELL_ERR_PROC_EXIT_FAIL;
|
return SHELL_ERR_PROC_EXIT_FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
*status_out = wapp_shell_utils_pclose(fp);
|
*status_out = wapp_shell_utils_pclose(fp);
|
||||||
|
|
||||||
return SHELL_ERR_NO_ERROR;
|
return SHELL_ERR_NO_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // !WAPP_PLATFORM_WINDOWS
|
#endif // !WAPP_PLATFORM_WINDOWS
|
||||||
|
|||||||
@@ -10,27 +10,27 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
wapp_intern Str8RO colours[COUNT_TERM_COLOUR] = {
|
wapp_intern Str8RO colours[COUNT_TERM_COLOUR] = {
|
||||||
[WAPP_TERM_COLOUR_FG_BLACK] = wapp_str8_lit_ro_initialiser_list("\033[30m"),
|
[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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_FG_BR_WHITE] = wapp_str8_lit_ro_initialiser_list("\033[97m"),
|
||||||
[WAPP_TERM_COLOUR_CLEAR] = wapp_str8_lit_ro_initialiser_list("\033[0m"),
|
[WAPP_TERM_COLOUR_CLEAR] = wapp_str8_lit_ro_initialiser_list("\033[0m"),
|
||||||
};
|
};
|
||||||
|
|
||||||
void print_coloured_text(Str8RO *text, TerminalColour colour) {
|
void print_coloured_text(Str8RO *text, TerminalColour colour) {
|
||||||
printf(WAPP_STR8_SPEC WAPP_STR8_SPEC, wapp_str8_varg(colours[colour]), wapp_str8_varg((*text)));
|
printf(WAPP_STR8_SPEC WAPP_STR8_SPEC, wapp_str8_varg(colours[colour]), wapp_str8_varg((*text)));
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // !WAPP_PLATFORM_POSIX
|
#endif // !WAPP_PLATFORM_POSIX
|
||||||
|
|||||||
@@ -5,14 +5,14 @@
|
|||||||
#include "../../../base/strings/str8/str8.h"
|
#include "../../../base/strings/str8/str8.h"
|
||||||
|
|
||||||
void wapp_shell_termcolour_print_text(Str8RO *text, TerminalColour colour) {
|
void wapp_shell_termcolour_print_text(Str8RO *text, TerminalColour colour) {
|
||||||
if (colour < WAPP_TERM_COLOUR_FG_BLACK || colour > WAPP_TERM_COLOUR_FG_BR_WHITE) {
|
if (colour < WAPP_TERM_COLOUR_FG_BLACK || colour > WAPP_TERM_COLOUR_FG_BR_WHITE) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
print_coloured_text(text, colour);
|
print_coloured_text(text, colour);
|
||||||
}
|
}
|
||||||
|
|
||||||
void wapp_shell_termcolour_clear_colour(void) {
|
void wapp_shell_termcolour_clear_colour(void) {
|
||||||
Str8RO empty = wapp_str8_lit_ro("");
|
Str8RO empty = wapp_str8_lit_ro("");
|
||||||
print_coloured_text(&empty, WAPP_TERM_COLOUR_CLEAR);
|
print_coloured_text(&empty, WAPP_TERM_COLOUR_CLEAR);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,25 +11,25 @@ BEGIN_C_LINKAGE
|
|||||||
#endif // !WAPP_PLATFORM_CPP
|
#endif // !WAPP_PLATFORM_CPP
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
WAPP_TERM_COLOUR_FG_BLACK,
|
WAPP_TERM_COLOUR_FG_BLACK,
|
||||||
WAPP_TERM_COLOUR_FG_RED,
|
WAPP_TERM_COLOUR_FG_RED,
|
||||||
WAPP_TERM_COLOUR_FG_GREEN,
|
WAPP_TERM_COLOUR_FG_GREEN,
|
||||||
WAPP_TERM_COLOUR_FG_BLUE,
|
WAPP_TERM_COLOUR_FG_BLUE,
|
||||||
WAPP_TERM_COLOUR_FG_CYAN,
|
WAPP_TERM_COLOUR_FG_CYAN,
|
||||||
WAPP_TERM_COLOUR_FG_MAGENTA,
|
WAPP_TERM_COLOUR_FG_MAGENTA,
|
||||||
WAPP_TERM_COLOUR_FG_YELLOW,
|
WAPP_TERM_COLOUR_FG_YELLOW,
|
||||||
WAPP_TERM_COLOUR_FG_WHITE,
|
WAPP_TERM_COLOUR_FG_WHITE,
|
||||||
WAPP_TERM_COLOUR_FG_BR_BLACK,
|
WAPP_TERM_COLOUR_FG_BR_BLACK,
|
||||||
WAPP_TERM_COLOUR_FG_BR_RED,
|
WAPP_TERM_COLOUR_FG_BR_RED,
|
||||||
WAPP_TERM_COLOUR_FG_BR_GREEN,
|
WAPP_TERM_COLOUR_FG_BR_GREEN,
|
||||||
WAPP_TERM_COLOUR_FG_BR_BLUE,
|
WAPP_TERM_COLOUR_FG_BR_BLUE,
|
||||||
WAPP_TERM_COLOUR_FG_BR_CYAN,
|
WAPP_TERM_COLOUR_FG_BR_CYAN,
|
||||||
WAPP_TERM_COLOUR_FG_BR_MAGENTA,
|
WAPP_TERM_COLOUR_FG_BR_MAGENTA,
|
||||||
WAPP_TERM_COLOUR_FG_BR_YELLOW,
|
WAPP_TERM_COLOUR_FG_BR_YELLOW,
|
||||||
WAPP_TERM_COLOUR_FG_BR_WHITE,
|
WAPP_TERM_COLOUR_FG_BR_WHITE,
|
||||||
WAPP_TERM_COLOUR_CLEAR,
|
WAPP_TERM_COLOUR_CLEAR,
|
||||||
|
|
||||||
COUNT_TERM_COLOUR,
|
COUNT_TERM_COLOUR,
|
||||||
} TerminalColour;
|
} TerminalColour;
|
||||||
|
|
||||||
#ifdef WAPP_PLATFORM_CPP
|
#ifdef WAPP_PLATFORM_CPP
|
||||||
|
|||||||
@@ -7,67 +7,67 @@
|
|||||||
#ifdef WAPP_PLATFORM_WINDOWS
|
#ifdef WAPP_PLATFORM_WINDOWS
|
||||||
|
|
||||||
#include "../terminal_colours.h"
|
#include "../terminal_colours.h"
|
||||||
#include "../../../../../common/misc/misc_utils.h"
|
#include "../../../../common/misc/misc_utils.h"
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
#define WIN32_LEAN_AND_MEAN
|
#define WIN32_LEAN_AND_MEAN
|
||||||
#include <Windows.h>
|
#include <Windows.h>
|
||||||
|
|
||||||
typedef struct termcolour_data TermcolourData;
|
typedef struct TermcolourData TermcolourData;
|
||||||
struct termcolour_data {
|
struct TermcolourData {
|
||||||
HANDLE handle;
|
HANDLE handle;
|
||||||
WORD default_colour;
|
WORD default_colour;
|
||||||
WORD current_colour;
|
WORD current_colour;
|
||||||
|
|
||||||
wapp_misc_utils_padding_size(sizeof(HANDLE) + sizeof(WORD) + sizeof(WORD));
|
wapp_misc_utils_reserve_padding(sizeof(HANDLE) + sizeof(WORD) + sizeof(WORD));
|
||||||
};
|
};
|
||||||
|
|
||||||
wapp_intern void init_data(TermcolourData *data);
|
wapp_intern void init_data(TermcolourData *data);
|
||||||
|
|
||||||
wapp_intern WORD colours[COUNT_TERM_COLOUR] = {
|
wapp_intern WORD colours[COUNT_TERM_COLOUR] = {
|
||||||
[WAPP_TERM_COLOUR_FG_BLACK] = 0,
|
[WAPP_TERM_COLOUR_FG_BLACK] = 0,
|
||||||
[WAPP_TERM_COLOUR_FG_RED] = FOREGROUND_RED,
|
[WAPP_TERM_COLOUR_FG_RED] = FOREGROUND_RED,
|
||||||
[WAPP_TERM_COLOUR_FG_GREEN] = FOREGROUND_GREEN,
|
[WAPP_TERM_COLOUR_FG_GREEN] = FOREGROUND_GREEN,
|
||||||
[WAPP_TERM_COLOUR_FG_BLUE] = FOREGROUND_BLUE,
|
[WAPP_TERM_COLOUR_FG_BLUE] = FOREGROUND_BLUE,
|
||||||
[WAPP_TERM_COLOUR_FG_CYAN] = FOREGROUND_GREEN | FOREGROUND_BLUE,
|
[WAPP_TERM_COLOUR_FG_CYAN] = FOREGROUND_GREEN | FOREGROUND_BLUE,
|
||||||
[WAPP_TERM_COLOUR_FG_MAGENTA] = FOREGROUND_RED | FOREGROUND_BLUE,
|
[WAPP_TERM_COLOUR_FG_MAGENTA] = FOREGROUND_RED | FOREGROUND_BLUE,
|
||||||
[WAPP_TERM_COLOUR_FG_YELLOW] = FOREGROUND_RED | FOREGROUND_GREEN,
|
[WAPP_TERM_COLOUR_FG_YELLOW] = FOREGROUND_RED | FOREGROUND_GREEN,
|
||||||
[WAPP_TERM_COLOUR_FG_WHITE] = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE,
|
[WAPP_TERM_COLOUR_FG_WHITE] = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE,
|
||||||
[WAPP_TERM_COLOUR_FG_BR_BLACK] = FOREGROUND_INTENSITY,
|
[WAPP_TERM_COLOUR_FG_BR_BLACK] = FOREGROUND_INTENSITY,
|
||||||
[WAPP_TERM_COLOUR_FG_BR_RED] = FOREGROUND_RED | 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_GREEN] = FOREGROUND_GREEN | FOREGROUND_INTENSITY,
|
||||||
[WAPP_TERM_COLOUR_FG_BR_BLUE] = FOREGROUND_BLUE | 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_CYAN] = FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY,
|
||||||
[WAPP_TERM_COLOUR_FG_BR_MAGENTA] = FOREGROUND_RED | 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_YELLOW] = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_INTENSITY,
|
||||||
[WAPP_TERM_COLOUR_FG_BR_WHITE] = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY,
|
[WAPP_TERM_COLOUR_FG_BR_WHITE] = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY,
|
||||||
};
|
};
|
||||||
|
|
||||||
void print_coloured_text(Str8RO *text, TerminalColour colour) {
|
void print_coloured_text(Str8RO *text, TerminalColour colour) {
|
||||||
wapp_persist TermcolourData data = {0};
|
wapp_persist TermcolourData data = {0};
|
||||||
if (data.handle == 0) {
|
if (data.handle == 0) {
|
||||||
init_data(&data);
|
init_data(&data);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (colour == WAPP_TERM_COLOUR_CLEAR) {
|
if (colour == WAPP_TERM_COLOUR_CLEAR) {
|
||||||
data.current_colour = data.default_colour;
|
data.current_colour = data.default_colour;
|
||||||
} else {
|
} else {
|
||||||
data.current_colour = colours[colour];
|
data.current_colour = colours[colour];
|
||||||
}
|
}
|
||||||
|
|
||||||
SetConsoleTextAttribute(data.handle, data.current_colour);
|
SetConsoleTextAttribute(data.handle, data.current_colour);
|
||||||
printf(WAPP_STR8_SPEC, wapp_str8_varg((*text)));
|
printf(WAPP_STR8_SPEC, wapp_str8_varg((*text)));
|
||||||
}
|
}
|
||||||
|
|
||||||
wapp_intern void init_data(TermcolourData *data) {
|
wapp_intern void init_data(TermcolourData *data) {
|
||||||
// create handle
|
// create handle
|
||||||
data->handle = GetStdHandle(STD_OUTPUT_HANDLE);
|
data->handle = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||||
|
|
||||||
// get console colour information
|
// get console colour information
|
||||||
CONSOLE_SCREEN_BUFFER_INFO csbi;
|
CONSOLE_SCREEN_BUFFER_INFO csbi;
|
||||||
GetConsoleScreenBufferInfo(data->handle, &csbi);
|
GetConsoleScreenBufferInfo(data->handle, &csbi);
|
||||||
data->default_colour = csbi.wAttributes;
|
data->default_colour = csbi.wAttributes;
|
||||||
data->current_colour = data->default_colour;
|
data->current_colour = data->default_colour;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // !WAPP_PLATFORM_WINDOWS
|
#endif // !WAPP_PLATFORM_WINDOWS
|
||||||
|
|||||||
@@ -12,11 +12,11 @@ BEGIN_C_LINKAGE
|
|||||||
#endif // !WAPP_PLATFORM_CPP
|
#endif // !WAPP_PLATFORM_CPP
|
||||||
|
|
||||||
#ifdef WAPP_PLATFORM_WINDOWS
|
#ifdef WAPP_PLATFORM_WINDOWS
|
||||||
#define wapp_shell_utils_popen _popen
|
#define wapp_shell_utils_popen _popen
|
||||||
#define wapp_shell_utils_pclose _pclose
|
#define wapp_shell_utils_pclose _pclose
|
||||||
#else
|
#else
|
||||||
#define wapp_shell_utils_popen popen
|
#define wapp_shell_utils_popen popen
|
||||||
#define wapp_shell_utils_pclose pclose
|
#define wapp_shell_utils_pclose pclose
|
||||||
#endif /* ifdef WAPP_PLATFORM_WINDOWS */
|
#endif /* ifdef WAPP_PLATFORM_WINDOWS */
|
||||||
|
|
||||||
#ifdef WAPP_PLATFORM_CPP
|
#ifdef WAPP_PLATFORM_CPP
|
||||||
|
|||||||
@@ -5,6 +5,8 @@
|
|||||||
|
|
||||||
#include "wapp_os.h"
|
#include "wapp_os.h"
|
||||||
#include "file/file.c"
|
#include "file/file.c"
|
||||||
|
#include "file/posix/file_posix.c"
|
||||||
|
#include "file/win/file_win.c"
|
||||||
#include "shell/termcolour/posix/termcolour_posix.c"
|
#include "shell/termcolour/posix/termcolour_posix.c"
|
||||||
#include "shell/termcolour/win/termcolour_win.c"
|
#include "shell/termcolour/win/termcolour_win.c"
|
||||||
#include "shell/termcolour/termcolour.c"
|
#include "shell/termcolour/termcolour.c"
|
||||||
|
|||||||
@@ -4,6 +4,8 @@
|
|||||||
#define WAPP_CORE_H
|
#define WAPP_CORE_H
|
||||||
|
|
||||||
#include "file/file.h"
|
#include "file/file.h"
|
||||||
|
#include "file/posix/file_posix.h"
|
||||||
|
#include "file/win/file_win.h"
|
||||||
#include "shell/termcolour/termcolour.h"
|
#include "shell/termcolour/termcolour.h"
|
||||||
#include "shell/termcolour/terminal_colours.h"
|
#include "shell/termcolour/terminal_colours.h"
|
||||||
#include "shell/commander/commander.h"
|
#include "shell/commander/commander.h"
|
||||||
|
|||||||
@@ -7,9 +7,9 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
|
|
||||||
typedef struct split_mix_64_state SplitMix64State;
|
typedef struct SplitMix64State SplitMix64State;
|
||||||
struct split_mix_64_state {
|
struct SplitMix64State {
|
||||||
u64 seed;
|
u64 seed;
|
||||||
};
|
};
|
||||||
|
|
||||||
wapp_intern u64 rol64(u64 x, u64 bits);
|
wapp_intern u64 rol64(u64 x, u64 bits);
|
||||||
@@ -18,118 +18,118 @@ wapp_intern void seed_os_generator(void);
|
|||||||
wapp_intern u64 generate_random_number(void);
|
wapp_intern u64 generate_random_number(void);
|
||||||
|
|
||||||
XOR256State wapp_prng_xorshift_init_state(void) {
|
XOR256State wapp_prng_xorshift_init_state(void) {
|
||||||
wapp_persist b8 seeded = false;
|
wapp_persist b8 seeded = false;
|
||||||
if (!seeded) {
|
if (!seeded) {
|
||||||
seeded = true;
|
seeded = true;
|
||||||
seed_os_generator();
|
seed_os_generator();
|
||||||
}
|
}
|
||||||
|
|
||||||
SplitMix64State sm64 = {.seed = generate_random_number()};
|
SplitMix64State sm64 = {.seed = generate_random_number()};
|
||||||
|
|
||||||
return (XOR256State){
|
return (XOR256State){
|
||||||
.x = split_mix_64(&sm64),
|
.x = split_mix_64(&sm64),
|
||||||
.y = split_mix_64(&sm64),
|
.y = split_mix_64(&sm64),
|
||||||
.z = split_mix_64(&sm64),
|
.z = split_mix_64(&sm64),
|
||||||
.w = split_mix_64(&sm64),
|
.w = split_mix_64(&sm64),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
u64 wapp_prng_xorshift_256(XOR256State *state) {
|
u64 wapp_prng_xorshift_256(XOR256State *state) {
|
||||||
u64 t = state->x ^ (state->x << 11);
|
u64 t = state->x ^ (state->x << 11);
|
||||||
|
|
||||||
state->x = state->y;
|
state->x = state->y;
|
||||||
state->y = state->z;
|
state->y = state->z;
|
||||||
state->z = state->w;
|
state->z = state->w;
|
||||||
state->w = (state->w ^ (state->w >> 19)) ^ (t ^ (t >> 8));
|
state->w = (state->w ^ (state->w >> 19)) ^ (t ^ (t >> 8));
|
||||||
|
|
||||||
return state->w;
|
return state->w;
|
||||||
}
|
}
|
||||||
|
|
||||||
u64 wapp_prng_xorshift_256ss(XOR256State *state) {
|
u64 wapp_prng_xorshift_256ss(XOR256State *state) {
|
||||||
const u64 result = rol64(state->z * 5, 7) * 9;
|
const u64 result = rol64(state->z * 5, 7) * 9;
|
||||||
const u64 t = state->z << 17;
|
const u64 t = state->z << 17;
|
||||||
|
|
||||||
state->y ^= state->w;
|
state->y ^= state->w;
|
||||||
state->x ^= state->z;
|
state->x ^= state->z;
|
||||||
state->z ^= state->y;
|
state->z ^= state->y;
|
||||||
state->w ^= state->x;
|
state->w ^= state->x;
|
||||||
|
|
||||||
state->y ^= t;
|
state->y ^= t;
|
||||||
state->x = rol64(state->x, 45);
|
state->x = rol64(state->x, 45);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
u64 wapp_prng_xorshift_256p(XOR256State *state) {
|
u64 wapp_prng_xorshift_256p(XOR256State *state) {
|
||||||
const u64 result = state->w + state->x;
|
const u64 result = state->w + state->x;
|
||||||
const u64 t = state->z << 17;
|
const u64 t = state->z << 17;
|
||||||
|
|
||||||
state->y ^= state->w;
|
state->y ^= state->w;
|
||||||
state->x ^= state->z;
|
state->x ^= state->z;
|
||||||
state->z ^= state->y;
|
state->z ^= state->y;
|
||||||
state->w ^= state->x;
|
state->w ^= state->x;
|
||||||
|
|
||||||
state->y ^= t;
|
state->y ^= t;
|
||||||
state->x = rol64(state->x, 45);
|
state->x = rol64(state->x, 45);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
wapp_intern u64 rol64(u64 x, u64 bits) {
|
wapp_intern u64 rol64(u64 x, u64 bits) {
|
||||||
return (x << bits) | (x >> (64 - bits));
|
return (x << bits) | (x >> (64 - bits));
|
||||||
}
|
}
|
||||||
|
|
||||||
wapp_intern u64 split_mix_64(SplitMix64State *state) {
|
wapp_intern u64 split_mix_64(SplitMix64State *state) {
|
||||||
state->seed += 0x9E3779B97f4A7C15;
|
state->seed += 0x9E3779B97f4A7C15;
|
||||||
|
|
||||||
u64 result = state->seed;
|
u64 result = state->seed;
|
||||||
result = (result ^ (result >> 30)) * 0xBF58476D1CE4E5B9;
|
result = (result ^ (result >> 30)) * 0xBF58476D1CE4E5B9;
|
||||||
result = (result ^ (result >> 27)) * 0x94D049BB133111EB;
|
result = (result ^ (result >> 27)) * 0x94D049BB133111EB;
|
||||||
|
|
||||||
return result ^ (result >> 31);
|
return result ^ (result >> 31);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(WAPP_PLATFORM_C) && WAPP_PLATFORM_C_VERSION >= WAPP_PLATFORM_C11_VERSION
|
#if defined(WAPP_PLATFORM_C) && WAPP_PLATFORM_C_VERSION >= WAPP_PLATFORM_C11_VERSION
|
||||||
#ifdef WAPP_PLATFORM_POSIX
|
#ifdef WAPP_PLATFORM_POSIX
|
||||||
wapp_intern void seed_os_generator(void) {
|
wapp_intern void seed_os_generator(void) {
|
||||||
struct timespec ts = {0};
|
struct timespec ts = {0};
|
||||||
int result = clock_gettime(CLOCK_MONOTONIC_RAW, &ts);
|
int result = clock_gettime(CLOCK_MONOTONIC_RAW, &ts);
|
||||||
wapp_runtime_assert(result == 0, "Invalid seed value");
|
wapp_runtime_assert(result == 0, "Invalid seed value");
|
||||||
|
|
||||||
srand48(ts.tv_nsec);
|
srand48(ts.tv_nsec);
|
||||||
}
|
}
|
||||||
|
|
||||||
wapp_intern u64 generate_random_number(void) {
|
wapp_intern u64 generate_random_number(void) {
|
||||||
return lrand48();
|
return lrand48();
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
wapp_intern void seed_os_generator(void) {
|
wapp_intern void seed_os_generator(void) {
|
||||||
struct timespec ts = {0};
|
struct timespec ts = {0};
|
||||||
int result = timespec_get(&ts, TIME_UTC);
|
int result = timespec_get(&ts, TIME_UTC);
|
||||||
wapp_runtime_assert(result != 0, "Invalid seed value");
|
wapp_runtime_assert(result != 0, "Invalid seed value");
|
||||||
|
|
||||||
srand(ts.tv_nsec);
|
srand(ts.tv_nsec);
|
||||||
}
|
}
|
||||||
|
|
||||||
wapp_intern u64 generate_random_number(void) {
|
wapp_intern u64 generate_random_number(void) {
|
||||||
i32 n1 = rand();
|
i32 n1 = rand();
|
||||||
i32 n2 = rand();
|
i32 n2 = rand();
|
||||||
|
|
||||||
return (((u64)n1) << 32 | (u64)n2);
|
return (((u64)n1) << 32 | (u64)n2);
|
||||||
}
|
}
|
||||||
#endif // !WAPP_PLATFORM_POSIX
|
#endif // !WAPP_PLATFORM_POSIX
|
||||||
#else
|
#else
|
||||||
wapp_intern void seed_os_generator(void) {
|
wapp_intern void seed_os_generator(void) {
|
||||||
time_t result = time(NULL);
|
time_t result = time(NULL);
|
||||||
wapp_runtime_assert(result != (time_t)(-1), "Invalid seed value");
|
wapp_runtime_assert(result != (time_t)(-1), "Invalid seed value");
|
||||||
|
|
||||||
srand(result);
|
srand(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
wapp_intern u64 generate_random_number(void) {
|
wapp_intern u64 generate_random_number(void) {
|
||||||
i32 n1 = rand();
|
i32 n1 = rand();
|
||||||
i32 n2 = rand();
|
i32 n2 = rand();
|
||||||
|
|
||||||
return (((u64)n1) << 32 | (u64)n2);
|
return (((u64)n1) << 32 | (u64)n2);
|
||||||
}
|
}
|
||||||
#endif // !WAPP_PLATFORM_C
|
#endif // !WAPP_PLATFORM_C
|
||||||
|
|||||||
@@ -10,12 +10,12 @@
|
|||||||
BEGIN_C_LINKAGE
|
BEGIN_C_LINKAGE
|
||||||
#endif // !WAPP_PLATFORM_CPP
|
#endif // !WAPP_PLATFORM_CPP
|
||||||
|
|
||||||
typedef struct xor_256_state XOR256State;
|
typedef struct XOR256State XOR256State;
|
||||||
struct xor_256_state {
|
struct XOR256State {
|
||||||
u64 x;
|
u64 x;
|
||||||
u64 y;
|
u64 y;
|
||||||
u64 z;
|
u64 z;
|
||||||
u64 w;
|
u64 w;
|
||||||
};
|
};
|
||||||
|
|
||||||
XOR256State wapp_prng_xorshift_init_state(void);
|
XOR256State wapp_prng_xorshift_init_state(void);
|
||||||
|
|||||||
@@ -11,45 +11,45 @@
|
|||||||
wapp_intern void handle_test_result(TestFuncResult result);
|
wapp_intern void handle_test_result(TestFuncResult result);
|
||||||
|
|
||||||
void run_tests(TestFunc *func1, ...) {
|
void run_tests(TestFunc *func1, ...) {
|
||||||
printf("\n");
|
printf("\n");
|
||||||
|
|
||||||
handle_test_result(func1());
|
handle_test_result(func1());
|
||||||
|
|
||||||
va_list args;
|
va_list args;
|
||||||
va_start(args, func1);
|
va_start(args, func1);
|
||||||
|
|
||||||
TestFunc *func = va_arg(args, TestFunc *);
|
TestFunc *func = va_arg(args, TestFunc *);
|
||||||
|
|
||||||
while (func) {
|
while (func) {
|
||||||
TestFuncResult result = func();
|
TestFuncResult result = func();
|
||||||
handle_test_result(result);
|
handle_test_result(result);
|
||||||
|
|
||||||
func = va_arg(args, TestFunc *);
|
func = va_arg(args, TestFunc *);
|
||||||
}
|
}
|
||||||
|
|
||||||
va_end(args);
|
va_end(args);
|
||||||
|
|
||||||
printf("\n");
|
printf("\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
wapp_intern void handle_test_result(TestFuncResult result) {
|
wapp_intern void handle_test_result(TestFuncResult result) {
|
||||||
TerminalColour colour;
|
TerminalColour colour;
|
||||||
Str8 result_text = wapp_str8_buf(64);
|
Str8 result_text = wapp_str8_buf(64);
|
||||||
|
|
||||||
if (result.passed) {
|
if (result.passed) {
|
||||||
colour = WAPP_TERM_COLOUR_FG_BR_GREEN;
|
colour = WAPP_TERM_COLOUR_FG_BR_GREEN;
|
||||||
wapp_str8_copy_cstr_capped(&result_text, "PASSED");
|
wapp_str8_copy_cstr_capped(&result_text, "PASSED");
|
||||||
} else {
|
} else {
|
||||||
colour = WAPP_TERM_COLOUR_FG_BR_RED;
|
colour = WAPP_TERM_COLOUR_FG_BR_RED;
|
||||||
wapp_str8_copy_cstr_capped(&result_text, "FAILED");
|
wapp_str8_copy_cstr_capped(&result_text, "FAILED");
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("[");
|
printf("[");
|
||||||
wapp_shell_termcolour_print_text(&result_text, colour);
|
wapp_shell_termcolour_print_text(&result_text, colour);
|
||||||
wapp_shell_termcolour_clear_colour();
|
wapp_shell_termcolour_clear_colour();
|
||||||
printf("] " WAPP_STR8_SPEC "\n", wapp_str8_varg(result.name));
|
printf("] " WAPP_STR8_SPEC "\n", wapp_str8_varg(result.name));
|
||||||
|
|
||||||
if (!result.passed) {
|
if (!result.passed) {
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,21 +10,19 @@
|
|||||||
#ifdef WAPP_PLATFORM_CPP
|
#ifdef WAPP_PLATFORM_CPP
|
||||||
BEGIN_C_LINKAGE
|
BEGIN_C_LINKAGE
|
||||||
|
|
||||||
#define wapp_tester_result(PASSED) (TestFuncResult{wapp_str8_lit_ro(__func__), PASSED})
|
#define wapp_tester_result(PASSED) (TestFuncResult{wapp_str8_lit_ro(__func__), PASSED, {}})
|
||||||
#else
|
#else
|
||||||
#define wapp_tester_result(PASSED) ((TestFuncResult){.name = wapp_str8_lit_ro(__func__), .passed = PASSED})
|
#define wapp_tester_result(PASSED) ((TestFuncResult){.name = wapp_str8_lit_ro(__func__), .passed = PASSED})
|
||||||
#endif // !WAPP_PLATFORM_CPP
|
#endif // !WAPP_PLATFORM_CPP
|
||||||
|
|
||||||
#define wapp_tester_run_tests(...) run_tests(__VA_ARGS__, NULL)
|
#define wapp_tester_run_tests(...) run_tests(__VA_ARGS__, NULL)
|
||||||
|
|
||||||
typedef struct test_func_result TestFuncResult;
|
typedef struct TestFuncResult TestFuncResult;
|
||||||
struct test_func_result {
|
struct TestFuncResult {
|
||||||
Str8 name;
|
Str8 name;
|
||||||
b8 passed;
|
b8 passed;
|
||||||
|
|
||||||
#ifdef WAPP_PLATFORM_WINDOWS
|
wapp_misc_utils_reserve_padding(sizeof(Str8) + sizeof(b8));
|
||||||
wapp_misc_utils_padding_size(sizeof(Str8RO) + sizeof(b8));
|
|
||||||
#endif // WAPP_PLATFORM_WINDOWS
|
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef TestFuncResult(TestFunc)(void);
|
typedef TestFuncResult(TestFunc)(void);
|
||||||
|
|||||||
@@ -9,50 +9,50 @@
|
|||||||
|
|
||||||
#define UUID_STR_FORMAT ("%.8" PRIx64 "-%.4" PRIx64 "-%.4" PRIx64 "-%.4" PRIx64 "-%.12" PRIx64)
|
#define UUID_STR_FORMAT ("%.8" PRIx64 "-%.4" PRIx64 "-%.4" PRIx64 "-%.4" PRIx64 "-%.12" PRIx64)
|
||||||
|
|
||||||
typedef struct uuid4 UUID4;
|
typedef struct UUID4 UUID4;
|
||||||
struct uuid4 {
|
struct UUID4 {
|
||||||
u64 high;
|
u64 high;
|
||||||
u64 low;
|
u64 low;
|
||||||
};
|
};
|
||||||
|
|
||||||
wapp_intern UUID4 generate_uuid4(void);
|
wapp_intern UUID4 generate_uuid4(void);
|
||||||
wapp_intern void uuid4_to_uuid(const UUID4* uuid4, WUUID *uuid);
|
wapp_intern void uuid4_to_uuid(const UUID4* uuid4, WUUID *uuid);
|
||||||
|
|
||||||
WUUID *wapp_uuid_init_uuid4(WUUID *uuid) {
|
WUUID *wapp_uuid_init_uuid4(WUUID *uuid) {
|
||||||
wapp_debug_assert(uuid != NULL, "`uuid` should not be NULL");
|
wapp_debug_assert(uuid != NULL, "`uuid` should not be NULL");
|
||||||
|
|
||||||
UUID4 uuid4 = generate_uuid4();
|
UUID4 uuid4 = generate_uuid4();
|
||||||
uuid4_to_uuid(&uuid4, uuid);
|
uuid4_to_uuid(&uuid4, uuid);
|
||||||
|
|
||||||
return uuid;
|
return uuid;
|
||||||
}
|
}
|
||||||
|
|
||||||
wapp_intern UUID4 generate_uuid4(void) {
|
wapp_intern UUID4 generate_uuid4(void) {
|
||||||
wapp_persist XOR256State state = {0};
|
wapp_persist XOR256State state = {0};
|
||||||
wapp_persist b8 initialised = false;
|
wapp_persist b8 initialised = false;
|
||||||
|
|
||||||
if (!initialised) {
|
if (!initialised) {
|
||||||
initialised = true;
|
initialised = true;
|
||||||
state = wapp_prng_xorshift_init_state();
|
state = wapp_prng_xorshift_init_state();
|
||||||
}
|
}
|
||||||
|
|
||||||
UUID4 uuid = (UUID4){
|
UUID4 uuid = (UUID4){
|
||||||
.high = wapp_prng_xorshift_256(&state),
|
.high = wapp_prng_xorshift_256(&state),
|
||||||
.low = wapp_prng_xorshift_256(&state),
|
.low = wapp_prng_xorshift_256(&state),
|
||||||
};
|
};
|
||||||
|
|
||||||
uuid.high = (uuid.high & 0xffffffffffff0fff) | 0x0000000000004000;
|
uuid.high = (uuid.high & 0xffffffffffff0fff) | 0x0000000000004000;
|
||||||
uuid.low = (uuid.low & 0x3fffffffffffffff) | 0x8000000000000000;
|
uuid.low = (uuid.low & 0x3fffffffffffffff) | 0x8000000000000000;
|
||||||
|
|
||||||
return uuid;
|
return uuid;
|
||||||
}
|
}
|
||||||
|
|
||||||
wapp_intern void uuid4_to_uuid(const UUID4* uuid4, WUUID *uuid) {
|
wapp_intern void uuid4_to_uuid(const UUID4* uuid4, WUUID *uuid) {
|
||||||
u64 group1 = uuid4->high >> 32;
|
u64 group1 = uuid4->high >> 32;
|
||||||
u64 group2 = (uuid4->high << 32) >> 48;
|
u64 group2 = (uuid4->high << 32) >> 48;
|
||||||
u64 group3 = (uuid4->high << 48) >> 48;
|
u64 group3 = (uuid4->high << 48) >> 48;
|
||||||
u64 group4 = uuid4->low >> 48;
|
u64 group4 = uuid4->low >> 48;
|
||||||
u64 group5 = (uuid4->low << 16) >> 16;
|
u64 group5 = (uuid4->low << 16) >> 16;
|
||||||
|
|
||||||
wapp_str8_format(&(uuid->uuid), UUID_STR_FORMAT, group1, group2, group3, group4, group5);
|
wapp_str8_format(&(uuid->uuid), UUID_STR_FORMAT, group1, group2, group3, group4, group5);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,11 +15,13 @@ BEGIN_C_LINKAGE
|
|||||||
#define WAPP_UUID_SPEC WAPP_STR8_SPEC
|
#define WAPP_UUID_SPEC WAPP_STR8_SPEC
|
||||||
#define wapp_uuid_varg(WUUID) wapp_str8_varg((WUUID).uuid)
|
#define wapp_uuid_varg(WUUID) wapp_str8_varg((WUUID).uuid)
|
||||||
|
|
||||||
typedef struct wapp_uuid WUUID;
|
typedef struct WUUID WUUID;
|
||||||
struct wapp_uuid {
|
struct WUUID {
|
||||||
Str8 uuid;
|
Str8 uuid;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// TODO (Abdelrahman): Update UUID implementation to work properly with C++ and tests for validation
|
||||||
|
|
||||||
#define wapp_uuid_gen_uuid4() *(wapp_uuid_init_uuid4(&wapp_uuid_create()))
|
#define wapp_uuid_gen_uuid4() *(wapp_uuid_init_uuid4(&wapp_uuid_create()))
|
||||||
|
|
||||||
/* Low level UUID API */
|
/* Low level UUID API */
|
||||||
|
|||||||
@@ -2,16 +2,66 @@
|
|||||||
#include "wapp.h"
|
#include "wapp.h"
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
// NOTE (Abdelrahman): Cannot query size of Arena here so it's hardcoded. Similarly, since arena
|
||||||
|
// allocation are aligned to power of 2 boundaries, the number of i32 values needed is hardcoded.
|
||||||
|
#define TEMP_BUF_SIZE (40 + sizeof(i32) * 8)
|
||||||
|
|
||||||
|
wapp_intern u8 temp_buf[TEMP_BUF_SIZE] = {0};
|
||||||
|
wapp_intern Allocator temp_allocator = {0};
|
||||||
|
|
||||||
TestFuncResult test_arena_allocator(void) {
|
TestFuncResult test_arena_allocator(void) {
|
||||||
Allocator allocator = wapp_mem_arena_allocator_init(4096);
|
Allocator allocator = wapp_mem_arena_allocator_init(4096);
|
||||||
b8 result = allocator.obj != NULL && allocator.alloc != NULL &&
|
b8 result = allocator.obj != NULL && allocator.alloc != NULL &&
|
||||||
allocator.alloc_aligned != NULL &&
|
allocator.alloc_aligned != NULL &&
|
||||||
allocator.realloc != NULL && allocator.realloc_aligned != NULL &&
|
allocator.realloc != NULL && allocator.realloc_aligned != NULL &&
|
||||||
allocator.free == NULL;
|
allocator.free == NULL;
|
||||||
void *ptr = wapp_mem_allocator_alloc(&allocator, 20);
|
void *ptr = wapp_mem_allocator_alloc(&allocator, 20);
|
||||||
result = result && (ptr != NULL);
|
result = result && (ptr != NULL);
|
||||||
|
|
||||||
wapp_mem_arena_allocator_destroy(&allocator);
|
wapp_mem_arena_allocator_destroy(&allocator);
|
||||||
|
|
||||||
return wapp_tester_result(result);
|
return wapp_tester_result(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
TestFuncResult test_arena_allocator_with_buffer(void) {
|
||||||
|
u8 buffer[KiB(4)] = {0};
|
||||||
|
|
||||||
|
Allocator allocator = wapp_mem_arena_allocator_init_with_buffer(buffer, KiB(4));
|
||||||
|
b8 result = allocator.obj != NULL && allocator.alloc != NULL &&
|
||||||
|
allocator.alloc_aligned != NULL &&
|
||||||
|
allocator.realloc != NULL && allocator.realloc_aligned != NULL &&
|
||||||
|
allocator.free == NULL;
|
||||||
|
void *ptr = wapp_mem_allocator_alloc(&allocator, 20);
|
||||||
|
result = result && (ptr != NULL);
|
||||||
|
|
||||||
|
wapp_mem_arena_allocator_destroy(&allocator);
|
||||||
|
|
||||||
|
return wapp_tester_result(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
TestFuncResult test_arena_allocator_temp_begin(void) {
|
||||||
|
temp_allocator = wapp_mem_arena_allocator_init_with_buffer(temp_buf, TEMP_BUF_SIZE);
|
||||||
|
|
||||||
|
i32 *num1 = (i32 *)wapp_mem_allocator_alloc(&temp_allocator, sizeof(i32));
|
||||||
|
b8 result = num1 != NULL;
|
||||||
|
|
||||||
|
wapp_mem_arena_allocator_temp_begin(&temp_allocator);
|
||||||
|
i32 *num2 = (i32 *)wapp_mem_allocator_alloc(&temp_allocator, sizeof(i32));
|
||||||
|
result = result && num2 != NULL;
|
||||||
|
i32 *num3 = (i32 *)wapp_mem_allocator_alloc(&temp_allocator, sizeof(i32));
|
||||||
|
result = result && num3 == NULL;
|
||||||
|
|
||||||
|
return wapp_tester_result(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
TestFuncResult test_arena_allocator_temp_end(void) {
|
||||||
|
wapp_mem_arena_allocator_temp_end(&temp_allocator);
|
||||||
|
i32 *num1 = (i32 *)wapp_mem_allocator_alloc(&temp_allocator, sizeof(i32));
|
||||||
|
b8 result = num1 != NULL;
|
||||||
|
i32 *num2 = (i32 *)wapp_mem_allocator_alloc(&temp_allocator, sizeof(i32));
|
||||||
|
result = result && num2 == NULL;
|
||||||
|
|
||||||
|
wapp_mem_arena_allocator_destroy(&temp_allocator);
|
||||||
|
|
||||||
|
return wapp_tester_result(result);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,16 +2,66 @@
|
|||||||
#include "wapp.h"
|
#include "wapp.h"
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
// NOTE (Abdelrahman): Cannot query size of Arena here so it's hardcoded. Similarly, since arena
|
||||||
|
// allocation are aligned to power of 2 boundaries, the number of i32 values needed is hardcoded.
|
||||||
|
#define TEMP_BUF_SIZE (40 + sizeof(i32) * 8)
|
||||||
|
|
||||||
|
wapp_intern u8 temp_buf[TEMP_BUF_SIZE] = {};
|
||||||
|
wapp_intern Allocator temp_allocator = {};
|
||||||
|
|
||||||
TestFuncResult test_arena_allocator(void) {
|
TestFuncResult test_arena_allocator(void) {
|
||||||
Allocator allocator = wapp_mem_arena_allocator_init(4096);
|
Allocator allocator = wapp_mem_arena_allocator_init(4096);
|
||||||
b8 result = allocator.obj != nullptr && allocator.alloc != nullptr &&
|
b8 result = allocator.obj != nullptr && allocator.alloc != nullptr &&
|
||||||
allocator.alloc_aligned != nullptr &&
|
allocator.alloc_aligned != nullptr &&
|
||||||
allocator.realloc != nullptr && allocator.realloc_aligned != nullptr &&
|
allocator.realloc != nullptr && allocator.realloc_aligned != nullptr &&
|
||||||
allocator.free == nullptr;
|
allocator.free == nullptr;
|
||||||
void *ptr = wapp_mem_allocator_alloc(&allocator, 20);
|
void *ptr = wapp_mem_allocator_alloc(&allocator, 20);
|
||||||
result = result && (ptr != nullptr);
|
result = result && (ptr != nullptr);
|
||||||
|
|
||||||
wapp_mem_arena_allocator_destroy(&allocator);
|
wapp_mem_arena_allocator_destroy(&allocator);
|
||||||
|
|
||||||
return wapp_tester_result(result);
|
return wapp_tester_result(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
TestFuncResult test_arena_allocator_with_buffer(void) {
|
||||||
|
u8 buffer[KiB(4)] = {0};
|
||||||
|
|
||||||
|
Allocator allocator = wapp_mem_arena_allocator_init_with_buffer(buffer, KiB(4));
|
||||||
|
b8 result = allocator.obj != NULL && allocator.alloc != NULL &&
|
||||||
|
allocator.alloc_aligned != NULL &&
|
||||||
|
allocator.realloc != NULL && allocator.realloc_aligned != NULL &&
|
||||||
|
allocator.free == NULL;
|
||||||
|
void *ptr = wapp_mem_allocator_alloc(&allocator, 20);
|
||||||
|
result = result && (ptr != NULL);
|
||||||
|
|
||||||
|
wapp_mem_arena_allocator_destroy(&allocator);
|
||||||
|
|
||||||
|
return wapp_tester_result(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
TestFuncResult test_arena_allocator_temp_begin(void) {
|
||||||
|
temp_allocator = wapp_mem_arena_allocator_init_with_buffer(temp_buf, TEMP_BUF_SIZE);
|
||||||
|
|
||||||
|
i32 *num1 = (i32 *)wapp_mem_allocator_alloc(&temp_allocator, sizeof(i32));
|
||||||
|
b8 result = num1 != NULL;
|
||||||
|
|
||||||
|
wapp_mem_arena_allocator_temp_begin(&temp_allocator);
|
||||||
|
i32 *num2 = (i32 *)wapp_mem_allocator_alloc(&temp_allocator, sizeof(i32));
|
||||||
|
result = result && num2 != NULL;
|
||||||
|
i32 *num3 = (i32 *)wapp_mem_allocator_alloc(&temp_allocator, sizeof(i32));
|
||||||
|
result = result && num3 == NULL;
|
||||||
|
|
||||||
|
return wapp_tester_result(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
TestFuncResult test_arena_allocator_temp_end(void) {
|
||||||
|
wapp_mem_arena_allocator_temp_end(&temp_allocator);
|
||||||
|
i32 *num1 = (i32 *)wapp_mem_allocator_alloc(&temp_allocator, sizeof(i32));
|
||||||
|
b8 result = num1 != NULL;
|
||||||
|
i32 *num2 = (i32 *)wapp_mem_allocator_alloc(&temp_allocator, sizeof(i32));
|
||||||
|
result = result && num2 == NULL;
|
||||||
|
|
||||||
|
wapp_mem_arena_allocator_destroy(&temp_allocator);
|
||||||
|
|
||||||
|
return wapp_tester_result(result);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,5 +4,8 @@
|
|||||||
#include "wapp.h"
|
#include "wapp.h"
|
||||||
|
|
||||||
TestFuncResult test_arena_allocator(void);
|
TestFuncResult test_arena_allocator(void);
|
||||||
|
TestFuncResult test_arena_allocator_with_buffer(void);
|
||||||
|
TestFuncResult test_arena_allocator_temp_begin(void);
|
||||||
|
TestFuncResult test_arena_allocator_temp_end(void);
|
||||||
|
|
||||||
#endif // !TEST_ALLOCATOR_H
|
#endif // !TEST_ALLOCATOR_H
|
||||||
|
|||||||
@@ -2,110 +2,167 @@
|
|||||||
#include "wapp.h"
|
#include "wapp.h"
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
#define ARENA_CAPACITY KB(16)
|
#define ARENA_CAPACITY KiB(16)
|
||||||
|
#define ARENA_BUF_SIZE KiB(4)
|
||||||
|
// NOTE (Abdelrahman): Cannot query size of Arena here so it's hardcoded. Similarly, since arena
|
||||||
|
// allocation are aligned to power of 2 boundaries, the number of i32 values needed is hardcoded.
|
||||||
|
#define TEMP_BUF_SIZE (40 + sizeof(i32) * 8)
|
||||||
|
|
||||||
wapp_intern Arena *arena = NULL;
|
wapp_intern Arena *arena = NULL;
|
||||||
wapp_intern i32 count = 20;
|
wapp_intern i32 count = 20;
|
||||||
wapp_intern i32 *array = NULL;
|
wapp_intern i32 *array = NULL;
|
||||||
|
wapp_intern Arena *buf_arena = NULL;
|
||||||
|
wapp_intern u8 buf[ARENA_BUF_SIZE] = {0};
|
||||||
|
wapp_intern Arena *temp_arena = NULL;
|
||||||
|
wapp_intern u8 temp_buf[TEMP_BUF_SIZE] = {0};
|
||||||
|
|
||||||
TestFuncResult test_arena_init(void) {
|
TestFuncResult test_arena_init_buffer(void) {
|
||||||
b8 result = wapp_mem_arena_init(&arena, ARENA_CAPACITY);
|
b8 result = wapp_mem_arena_init_buffer(&buf_arena, buf, ARENA_BUF_SIZE);
|
||||||
|
return wapp_tester_result(result);
|
||||||
|
}
|
||||||
|
|
||||||
return wapp_tester_result(result);
|
TestFuncResult test_arena_init_allocated(void) {
|
||||||
|
b8 result = wapp_mem_arena_init_allocated(&arena, ARENA_CAPACITY);
|
||||||
|
|
||||||
|
return wapp_tester_result(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
TestFuncResult test_arena_init_succeeds_when_reserving_very_large_size(void) {
|
TestFuncResult test_arena_init_succeeds_when_reserving_very_large_size(void) {
|
||||||
Arena *large_arena = NULL;
|
Arena *large_arena = NULL;
|
||||||
u64 capacity = GB(512);
|
u64 capacity = GiB(512);
|
||||||
b8 result = wapp_mem_arena_init(&large_arena, capacity);
|
b8 result = wapp_mem_arena_init_allocated(&large_arena, capacity);
|
||||||
if (result) {
|
if (result) {
|
||||||
wapp_mem_arena_destroy(&large_arena);
|
wapp_mem_arena_destroy(&large_arena);
|
||||||
}
|
}
|
||||||
|
|
||||||
return wapp_tester_result(result);
|
return wapp_tester_result(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
TestFuncResult test_arena_alloc_with_buffer(void) {
|
||||||
|
i32 *arr = (i32 *)wapp_mem_arena_alloc(arena, count * sizeof(i32));
|
||||||
|
b8 result = arr != NULL;
|
||||||
|
|
||||||
|
for (i32 i = 0; i < count; ++i) {
|
||||||
|
arr[i] = i * 10;
|
||||||
|
}
|
||||||
|
|
||||||
|
return wapp_tester_result(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
TestFuncResult test_arena_alloc_succeeds_when_within_capacity(void) {
|
TestFuncResult test_arena_alloc_succeeds_when_within_capacity(void) {
|
||||||
array = wapp_mem_arena_alloc(arena, count * sizeof(i32));
|
array = wapp_mem_arena_alloc(arena, count * sizeof(i32));
|
||||||
b8 result = array != NULL;
|
b8 result = array != NULL;
|
||||||
|
|
||||||
for (i32 i = 0; i < count; ++i) {
|
for (i32 i = 0; i < count; ++i) {
|
||||||
array[i] = i * 10;
|
array[i] = i * 10;
|
||||||
}
|
}
|
||||||
|
|
||||||
return wapp_tester_result(result);
|
return wapp_tester_result(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
TestFuncResult test_arena_alloc_fails_when_over_capacity(void) {
|
TestFuncResult test_arena_alloc_fails_when_over_capacity(void) {
|
||||||
u8 *bytes = wapp_mem_arena_alloc(arena, ARENA_CAPACITY * 2);
|
u8 *bytes = wapp_mem_arena_alloc(arena, ARENA_CAPACITY * 2);
|
||||||
b8 result = bytes == NULL;
|
b8 result = bytes == NULL;
|
||||||
|
|
||||||
return wapp_tester_result(result);
|
return wapp_tester_result(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
TestFuncResult test_arena_realloc_bigger_size(void) {
|
TestFuncResult test_arena_realloc_bigger_size(void) {
|
||||||
u64 old_count = 10;
|
u64 old_count = 10;
|
||||||
u64 new_count = 20;
|
u64 new_count = 20;
|
||||||
i32 *bytes = wapp_mem_arena_alloc(arena, old_count * sizeof(i32));
|
i32 *bytes = wapp_mem_arena_alloc(arena, old_count * sizeof(i32));
|
||||||
|
|
||||||
for (u64 i = 0; i < old_count; ++i) {
|
for (u64 i = 0; i < old_count; ++i) {
|
||||||
bytes[i] = (i32)i;
|
bytes[i] = (i32)i;
|
||||||
}
|
}
|
||||||
|
|
||||||
i32 *new_bytes = wapp_mem_arena_realloc(arena, bytes, old_count * sizeof(i32), new_count * sizeof(i32));
|
i32 *new_bytes = wapp_mem_arena_realloc(arena, bytes, old_count * sizeof(i32), new_count * sizeof(i32));
|
||||||
if (!new_bytes) {
|
if (!new_bytes) {
|
||||||
return wapp_tester_result(false);
|
return wapp_tester_result(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (u64 i = 0; i < new_count; ++i) {
|
for (u64 i = 0; i < new_count; ++i) {
|
||||||
if (i < old_count && new_bytes[i] != bytes[i]) {
|
if (i < old_count && new_bytes[i] != bytes[i]) {
|
||||||
return wapp_tester_result(false);
|
return wapp_tester_result(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return wapp_tester_result(true);
|
return wapp_tester_result(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
TestFuncResult test_arena_realloc_smaller_size(void) {
|
TestFuncResult test_arena_realloc_smaller_size(void) {
|
||||||
u64 old_count = 10;
|
u64 old_count = 10;
|
||||||
u64 new_count = 5;
|
u64 new_count = 5;
|
||||||
i32 *bytes = wapp_mem_arena_alloc(arena, old_count * sizeof(i32));
|
i32 *bytes = wapp_mem_arena_alloc(arena, old_count * sizeof(i32));
|
||||||
|
|
||||||
for (u64 i = 0; i < old_count; ++i) {
|
for (u64 i = 0; i < old_count; ++i) {
|
||||||
bytes[i] = (i32)i;
|
bytes[i] = (i32)i;
|
||||||
}
|
}
|
||||||
|
|
||||||
i32 *new_bytes = wapp_mem_arena_realloc(arena, bytes, old_count * sizeof(i32), new_count * sizeof(i32));
|
i32 *new_bytes = wapp_mem_arena_realloc(arena, bytes, old_count * sizeof(i32), new_count * sizeof(i32));
|
||||||
if (!new_bytes) {
|
if (!new_bytes) {
|
||||||
return wapp_tester_result(false);
|
return wapp_tester_result(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (u64 i = 0; i < new_count; ++i) {
|
for (u64 i = 0; i < new_count; ++i) {
|
||||||
if (i < new_count && new_bytes[i] != bytes[i]) {
|
if (i < new_count && new_bytes[i] != bytes[i]) {
|
||||||
return wapp_tester_result(false);
|
return wapp_tester_result(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return wapp_tester_result(true);
|
return wapp_tester_result(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
TestFuncResult test_arena_temp_begin(void) {
|
||||||
|
b8 result = wapp_mem_arena_init_buffer(&temp_arena, temp_buf, TEMP_BUF_SIZE);
|
||||||
|
i32 *num1 = (i32 *)wapp_mem_arena_alloc(temp_arena, sizeof(i32));
|
||||||
|
result = result && num1 != NULL;
|
||||||
|
|
||||||
|
wapp_mem_arena_temp_begin(temp_arena);
|
||||||
|
i32 *num2 = (i32 *)wapp_mem_arena_alloc(temp_arena, sizeof(i32));
|
||||||
|
result = result && num2 != NULL;
|
||||||
|
i32 *num3 = (i32 *)wapp_mem_arena_alloc(temp_arena, sizeof(i32));
|
||||||
|
result = result && num3 == NULL;
|
||||||
|
|
||||||
|
return wapp_tester_result(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
TestFuncResult test_arena_temp_end(void) {
|
||||||
|
wapp_mem_arena_temp_end(temp_arena);
|
||||||
|
i32 *num1 = (i32 *)wapp_mem_arena_alloc(temp_arena, sizeof(i32));
|
||||||
|
b8 result = num1 != NULL;
|
||||||
|
i32 *num2 = (i32 *)wapp_mem_arena_alloc(temp_arena, sizeof(i32));
|
||||||
|
result = result && num2 == NULL;
|
||||||
|
|
||||||
|
wapp_mem_arena_destroy(&temp_arena);
|
||||||
|
|
||||||
|
return wapp_tester_result(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
TestFuncResult test_arena_clear(void) {
|
TestFuncResult test_arena_clear(void) {
|
||||||
wapp_mem_arena_clear(arena);
|
wapp_mem_arena_clear(arena);
|
||||||
b8 result = true;
|
b8 result = true;
|
||||||
|
|
||||||
for (i32 i = 0; i < count; ++i) {
|
for (i32 i = 0; i < count; ++i) {
|
||||||
if (array[i] != 0) {
|
if (array[i] != 0) {
|
||||||
result = false;
|
result = false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return wapp_tester_result(result);
|
return wapp_tester_result(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
TestFuncResult test_arena_destroy(void) {
|
TestFuncResult test_arena_destroy_buffer(void) {
|
||||||
wapp_mem_arena_destroy(&arena);
|
wapp_mem_arena_destroy(&buf_arena);
|
||||||
b8 result = arena == NULL;
|
b8 result = buf_arena == NULL;
|
||||||
|
|
||||||
return wapp_tester_result(result);
|
return wapp_tester_result(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
TestFuncResult test_arena_destroy_allocated(void) {
|
||||||
|
wapp_mem_arena_destroy(&arena);
|
||||||
|
b8 result = arena == NULL;
|
||||||
|
|
||||||
|
return wapp_tester_result(result);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,110 +2,167 @@
|
|||||||
#include "wapp.h"
|
#include "wapp.h"
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
#define ARENA_CAPACITY KB(16)
|
#define ARENA_CAPACITY KiB(16)
|
||||||
|
#define ARENA_BUF_SIZE KiB(4)
|
||||||
|
// NOTE (Abdelrahman): Cannot query size of Arena here so it's hardcoded. Similarly, since arena
|
||||||
|
// allocation are aligned to power of 2 boundaries, the number of i32 values needed is hardcoded.
|
||||||
|
#define TEMP_BUF_SIZE (40 + sizeof(i32) * 8)
|
||||||
|
|
||||||
wapp_intern Arena *arena = nullptr;
|
wapp_intern Arena *arena = NULL;
|
||||||
wapp_intern i32 count = 20;
|
wapp_intern i32 count = 20;
|
||||||
wapp_intern i32 *array = nullptr;
|
wapp_intern i32 *array = NULL;
|
||||||
|
wapp_intern Arena *buf_arena = NULL;
|
||||||
|
wapp_intern u8 buf[ARENA_BUF_SIZE] = {};
|
||||||
|
wapp_intern Arena *temp_arena = NULL;
|
||||||
|
wapp_intern u8 temp_buf[TEMP_BUF_SIZE] = {};
|
||||||
|
|
||||||
TestFuncResult test_arena_init(void) {
|
TestFuncResult test_arena_init_buffer(void) {
|
||||||
b8 result = wapp_mem_arena_init(&arena, ARENA_CAPACITY);
|
b8 result = wapp_mem_arena_init_buffer(&buf_arena, buf, ARENA_BUF_SIZE);
|
||||||
|
return wapp_tester_result(result);
|
||||||
|
}
|
||||||
|
|
||||||
return wapp_tester_result(result);
|
TestFuncResult test_arena_init_allocated(void) {
|
||||||
|
b8 result = wapp_mem_arena_init_allocated(&arena, ARENA_CAPACITY);
|
||||||
|
|
||||||
|
return wapp_tester_result(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
TestFuncResult test_arena_init_succeeds_when_reserving_very_large_size(void) {
|
TestFuncResult test_arena_init_succeeds_when_reserving_very_large_size(void) {
|
||||||
Arena *large_arena = nullptr;
|
Arena *large_arena = nullptr;
|
||||||
u64 capacity = GB(512);
|
u64 capacity = GiB(512);
|
||||||
b8 result = wapp_mem_arena_init(&large_arena, capacity);
|
b8 result = wapp_mem_arena_init_allocated(&large_arena, capacity);
|
||||||
if (result) {
|
if (result) {
|
||||||
wapp_mem_arena_destroy(&large_arena);
|
wapp_mem_arena_destroy(&large_arena);
|
||||||
}
|
}
|
||||||
|
|
||||||
return wapp_tester_result(result);
|
return wapp_tester_result(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
TestFuncResult test_arena_alloc_with_buffer(void) {
|
||||||
|
i32 *arr = (i32 *)wapp_mem_arena_alloc(arena, count * sizeof(i32));
|
||||||
|
b8 result = arr != NULL;
|
||||||
|
|
||||||
|
for (i32 i = 0; i < count; ++i) {
|
||||||
|
arr[i] = i * 10;
|
||||||
|
}
|
||||||
|
|
||||||
|
return wapp_tester_result(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
TestFuncResult test_arena_alloc_succeeds_when_within_capacity(void) {
|
TestFuncResult test_arena_alloc_succeeds_when_within_capacity(void) {
|
||||||
array = (i32 *)wapp_mem_arena_alloc(arena, count * sizeof(i32));
|
array = (i32 *)wapp_mem_arena_alloc(arena, count * sizeof(i32));
|
||||||
b8 result = array != nullptr;
|
b8 result = array != nullptr;
|
||||||
|
|
||||||
for (i32 i = 0; i < count; ++i) {
|
for (i32 i = 0; i < count; ++i) {
|
||||||
array[i] = i * 10;
|
array[i] = i * 10;
|
||||||
}
|
}
|
||||||
|
|
||||||
return wapp_tester_result(result);
|
return wapp_tester_result(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
TestFuncResult test_arena_alloc_fails_when_over_capacity(void) {
|
TestFuncResult test_arena_alloc_fails_when_over_capacity(void) {
|
||||||
u8 *bytes = (u8 *)wapp_mem_arena_alloc(arena, ARENA_CAPACITY * 2);
|
u8 *bytes = (u8 *)wapp_mem_arena_alloc(arena, ARENA_CAPACITY * 2);
|
||||||
b8 result = bytes == nullptr;
|
b8 result = bytes == nullptr;
|
||||||
|
|
||||||
return wapp_tester_result(result);
|
return wapp_tester_result(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
TestFuncResult test_arena_realloc_bigger_size(void) {
|
TestFuncResult test_arena_realloc_bigger_size(void) {
|
||||||
u64 old_count = 10;
|
u64 old_count = 10;
|
||||||
u64 new_count = 20;
|
u64 new_count = 20;
|
||||||
i32 *bytes = (i32 *)wapp_mem_arena_alloc(arena, old_count * sizeof(i32));
|
i32 *bytes = (i32 *)wapp_mem_arena_alloc(arena, old_count * sizeof(i32));
|
||||||
|
|
||||||
for (u64 i = 0; i < old_count; ++i) {
|
for (u64 i = 0; i < old_count; ++i) {
|
||||||
bytes[i] = (i32)i;
|
bytes[i] = (i32)i;
|
||||||
}
|
}
|
||||||
|
|
||||||
i32 *new_bytes = (i32 *)wapp_mem_arena_realloc(arena, bytes, old_count * sizeof(i32), new_count * sizeof(i32));
|
i32 *new_bytes = (i32 *)wapp_mem_arena_realloc(arena, bytes, old_count * sizeof(i32), new_count * sizeof(i32));
|
||||||
if (!new_bytes) {
|
if (!new_bytes) {
|
||||||
return wapp_tester_result(false);
|
return wapp_tester_result(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (u64 i = 0; i < new_count; ++i) {
|
for (u64 i = 0; i < new_count; ++i) {
|
||||||
if (i < old_count && new_bytes[i] != bytes[i]) {
|
if (i < old_count && new_bytes[i] != bytes[i]) {
|
||||||
return wapp_tester_result(false);
|
return wapp_tester_result(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return wapp_tester_result(true);
|
return wapp_tester_result(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
TestFuncResult test_arena_realloc_smaller_size(void) {
|
TestFuncResult test_arena_realloc_smaller_size(void) {
|
||||||
u64 old_count = 10;
|
u64 old_count = 10;
|
||||||
u64 new_count = 5;
|
u64 new_count = 5;
|
||||||
i32 *bytes = (i32 *)wapp_mem_arena_alloc(arena, old_count * sizeof(i32));
|
i32 *bytes = (i32 *)wapp_mem_arena_alloc(arena, old_count * sizeof(i32));
|
||||||
|
|
||||||
for (u64 i = 0; i < old_count; ++i) {
|
for (u64 i = 0; i < old_count; ++i) {
|
||||||
bytes[i] = (i32)i;
|
bytes[i] = (i32)i;
|
||||||
}
|
}
|
||||||
|
|
||||||
i32 *new_bytes = (i32 *)wapp_mem_arena_realloc(arena, bytes, old_count * sizeof(i32), new_count * sizeof(i32));
|
i32 *new_bytes = (i32 *)wapp_mem_arena_realloc(arena, bytes, old_count * sizeof(i32), new_count * sizeof(i32));
|
||||||
if (!new_bytes) {
|
if (!new_bytes) {
|
||||||
return wapp_tester_result(false);
|
return wapp_tester_result(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (u64 i = 0; i < new_count; ++i) {
|
for (u64 i = 0; i < new_count; ++i) {
|
||||||
if (i < new_count && new_bytes[i] != bytes[i]) {
|
if (i < new_count && new_bytes[i] != bytes[i]) {
|
||||||
return wapp_tester_result(false);
|
return wapp_tester_result(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return wapp_tester_result(true);
|
return wapp_tester_result(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
TestFuncResult test_arena_temp_begin(void) {
|
||||||
|
b8 result = wapp_mem_arena_init_buffer(&temp_arena, temp_buf, TEMP_BUF_SIZE);
|
||||||
|
i32 *num1 = (i32 *)wapp_mem_arena_alloc(temp_arena, sizeof(i32));
|
||||||
|
result = result && num1 != NULL;
|
||||||
|
|
||||||
|
wapp_mem_arena_temp_begin(temp_arena);
|
||||||
|
i32 *num2 = (i32 *)wapp_mem_arena_alloc(temp_arena, sizeof(i32));
|
||||||
|
result = result && num2 != NULL;
|
||||||
|
i32 *num3 = (i32 *)wapp_mem_arena_alloc(temp_arena, sizeof(i32));
|
||||||
|
result = result && num3 == NULL;
|
||||||
|
|
||||||
|
return wapp_tester_result(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
TestFuncResult test_arena_temp_end(void) {
|
||||||
|
wapp_mem_arena_temp_end(temp_arena);
|
||||||
|
i32 *num1 = (i32 *)wapp_mem_arena_alloc(temp_arena, sizeof(i32));
|
||||||
|
b8 result = num1 != NULL;
|
||||||
|
i32 *num2 = (i32 *)wapp_mem_arena_alloc(temp_arena, sizeof(i32));
|
||||||
|
result = result && num2 == NULL;
|
||||||
|
|
||||||
|
wapp_mem_arena_destroy(&temp_arena);
|
||||||
|
|
||||||
|
return wapp_tester_result(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
TestFuncResult test_arena_clear(void) {
|
TestFuncResult test_arena_clear(void) {
|
||||||
wapp_mem_arena_clear(arena);
|
wapp_mem_arena_clear(arena);
|
||||||
b8 result = true;
|
b8 result = true;
|
||||||
|
|
||||||
for (i32 i = 0; i < count; ++i) {
|
for (i32 i = 0; i < count; ++i) {
|
||||||
if (array[i] != 0) {
|
if (array[i] != 0) {
|
||||||
result = false;
|
result = false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return wapp_tester_result(result);
|
return wapp_tester_result(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
TestFuncResult test_arena_destroy(void) {
|
TestFuncResult test_arena_destroy_buffer(void) {
|
||||||
wapp_mem_arena_destroy(&arena);
|
wapp_mem_arena_destroy(&buf_arena);
|
||||||
b8 result = arena == nullptr;
|
b8 result = buf_arena == NULL;
|
||||||
|
|
||||||
return wapp_tester_result(result);
|
return wapp_tester_result(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
TestFuncResult test_arena_destroy_allocated(void) {
|
||||||
|
wapp_mem_arena_destroy(&arena);
|
||||||
|
b8 result = arena == nullptr;
|
||||||
|
|
||||||
|
return wapp_tester_result(result);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,13 +3,18 @@
|
|||||||
|
|
||||||
#include "wapp.h"
|
#include "wapp.h"
|
||||||
|
|
||||||
TestFuncResult test_arena_init(void);
|
TestFuncResult test_arena_init_buffer(void);
|
||||||
|
TestFuncResult test_arena_init_allocated(void);
|
||||||
TestFuncResult test_arena_init_succeeds_when_reserving_very_large_size(void);
|
TestFuncResult test_arena_init_succeeds_when_reserving_very_large_size(void);
|
||||||
|
TestFuncResult test_arena_alloc_with_buffer(void);
|
||||||
TestFuncResult test_arena_alloc_succeeds_when_within_capacity(void);
|
TestFuncResult test_arena_alloc_succeeds_when_within_capacity(void);
|
||||||
TestFuncResult test_arena_alloc_fails_when_over_capacity(void);
|
TestFuncResult test_arena_alloc_fails_when_over_capacity(void);
|
||||||
TestFuncResult test_arena_realloc_bigger_size(void);
|
TestFuncResult test_arena_realloc_bigger_size(void);
|
||||||
TestFuncResult test_arena_realloc_smaller_size(void);
|
TestFuncResult test_arena_realloc_smaller_size(void);
|
||||||
TestFuncResult test_arena_clear(void);
|
TestFuncResult test_arena_clear(void);
|
||||||
TestFuncResult test_arena_destroy(void);
|
TestFuncResult test_arena_temp_begin(void);
|
||||||
|
TestFuncResult test_arena_temp_end(void);
|
||||||
|
TestFuncResult test_arena_destroy_buffer(void);
|
||||||
|
TestFuncResult test_arena_destroy_allocated(void);
|
||||||
|
|
||||||
#endif // !TEST_ARENA_H
|
#endif // !TEST_ARENA_H
|
||||||
|
|||||||
@@ -2,269 +2,272 @@
|
|||||||
#include "wapp.h"
|
#include "wapp.h"
|
||||||
|
|
||||||
TestFuncResult test_i32_array(void) {
|
TestFuncResult test_i32_array(void) {
|
||||||
b8 result;
|
b8 result;
|
||||||
|
|
||||||
I32Array array = wapp_array(i32, I32Array, 1, 2, 3, 4, 5, 6, 7);
|
I32Array array = wapp_array(i32, 1, 2, 3, 4, 5, 6, 7);
|
||||||
result = array.count == 7 && array.capacity == 16;
|
result = wapp_array_count(array) == 7 && wapp_array_capacity(array) == 16;
|
||||||
|
|
||||||
i32 *item;
|
i32 *item;
|
||||||
u64 count = array.count;
|
u64 count = wapp_array_count(array);
|
||||||
u64 index = 0;
|
u64 index = 0;
|
||||||
b8 running = true;
|
b8 running = true;
|
||||||
while (running) {
|
while (running) {
|
||||||
item = wapp_array_get(i32, &array, index);
|
item = wapp_array_get(i32, array, index);
|
||||||
result = result && item && *item == (i32)(index + 1);
|
result = result && item && *item == (i32)(index + 1);
|
||||||
|
|
||||||
++index;
|
++index;
|
||||||
running = index < count;
|
running = index < count;
|
||||||
}
|
}
|
||||||
|
|
||||||
return wapp_tester_result(result);
|
return wapp_tester_result(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
TestFuncResult test_i32_array_with_capacity(void) {
|
TestFuncResult test_i32_array_with_capacity(void) {
|
||||||
b8 result;
|
b8 result;
|
||||||
|
|
||||||
I32Array array = wapp_array_with_capacity(i32, I32Array, 64);
|
I32Array array1 = wapp_array_with_capacity(i32, 64, ARRAY_INIT_NONE);
|
||||||
result = array.count == 0 && array.capacity == 64;
|
result = wapp_array_count(array1) == 0 && wapp_array_capacity(array1) == 64;
|
||||||
|
|
||||||
return wapp_tester_result(result);
|
I32Array array2 = wapp_array_with_capacity(i32, 64, ARRAY_INIT_FILLED);
|
||||||
|
result = wapp_array_count(array2) == 64 && wapp_array_capacity(array2) == 64;
|
||||||
|
|
||||||
|
return wapp_tester_result(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
TestFuncResult test_i32_array_get(void) {
|
TestFuncResult test_i32_array_get(void) {
|
||||||
b8 result = true;
|
b8 result = true;
|
||||||
|
|
||||||
I32Array array = wapp_array(i32, I32Array, 0, 1, 2, 3, 4, 5, 6, 7, 8);
|
I32Array array = wapp_array(i32, 0, 1, 2, 3, 4, 5, 6, 7, 8);
|
||||||
|
|
||||||
i32 *item;
|
i32 *item;
|
||||||
u64 count = array.count;
|
u64 count = wapp_array_count(array);
|
||||||
u64 index = 0;
|
u64 index = 0;
|
||||||
b8 running = true;
|
b8 running = true;
|
||||||
while (running) {
|
while (running) {
|
||||||
item = wapp_array_get(i32, &array, index);
|
item = wapp_array_get(i32, array, index);
|
||||||
result = result && item && *item == (i32)index;
|
result = result && item && *item == (i32)index;
|
||||||
|
|
||||||
++index;
|
++index;
|
||||||
running = index < count;
|
running = index < count;
|
||||||
}
|
}
|
||||||
|
|
||||||
return wapp_tester_result(result);
|
return wapp_tester_result(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
TestFuncResult test_i32_array_set(void) {
|
TestFuncResult test_i32_array_set(void) {
|
||||||
b8 result = true;
|
b8 result = true;
|
||||||
|
|
||||||
I32Array array = wapp_array(i32, I32Array, 0, 1, 2, 3, 4, 5, 6, 7, 8);
|
I32Array array = wapp_array(i32, 0, 1, 2, 3, 4, 5, 6, 7, 8);
|
||||||
|
|
||||||
i32 *item;
|
i32 *item;
|
||||||
u64 count = array.count;
|
u64 count = wapp_array_count(array);
|
||||||
u64 index = 0;
|
u64 index = 0;
|
||||||
b8 running = true;
|
b8 running = true;
|
||||||
while (running) {
|
while (running) {
|
||||||
i32 num = (i32)(index * 2);
|
i32 num = (i32)(index * 2);
|
||||||
wapp_array_set(i32, &array, index, &num);
|
wapp_array_set(i32, array, index, &num);
|
||||||
item = wapp_array_get(i32, &array, index);
|
item = wapp_array_get(i32, array, index);
|
||||||
result = result && item && *item == (i32)(index * 2);
|
result = result && item && *item == (i32)(index * 2);
|
||||||
|
|
||||||
++index;
|
++index;
|
||||||
running = index < count;
|
running = index < count;
|
||||||
}
|
}
|
||||||
|
|
||||||
return wapp_tester_result(result);
|
return wapp_tester_result(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
TestFuncResult test_i32_array_append_capped(void) {
|
TestFuncResult test_i32_array_append_capped(void) {
|
||||||
b8 result;
|
b8 result;
|
||||||
|
|
||||||
I32Array array = wapp_array_with_capacity(i32, I32Array, 64);
|
I32Array array = wapp_array_with_capacity(i32, 64, ARRAY_INIT_NONE);
|
||||||
wapp_array_append_capped(i32, &array, &((i32){10}));
|
wapp_array_append_capped(i32, array, &((i32){10}));
|
||||||
|
|
||||||
result = array.count == 1;
|
result = wapp_array_count(array) == 1;
|
||||||
i32 *item = wapp_array_get(i32, &array, 0);
|
i32 *item = wapp_array_get(i32, array, 0);
|
||||||
result = result && item && *item == 10;
|
result = result && item && *item == 10;
|
||||||
|
|
||||||
array = wapp_array(i32, I32Array, 1);
|
array = wapp_array(i32, 1);
|
||||||
wapp_array_append_capped(i32, &array, &((i32){10}));
|
wapp_array_append_capped(i32, array, &((i32){10}));
|
||||||
|
|
||||||
result = result && array.count == 2;
|
result = result && wapp_array_count(array) == 2;
|
||||||
|
|
||||||
return wapp_tester_result(result);
|
return wapp_tester_result(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
TestFuncResult test_i32_array_extend_capped(void) {
|
TestFuncResult test_i32_array_extend_capped(void) {
|
||||||
b8 result;
|
b8 result;
|
||||||
|
|
||||||
I32Array array1 = wapp_array(i32, I32Array, 1, 2, 3, 4);
|
I32Array array1 = wapp_array(i32, 1, 2, 3, 4);
|
||||||
I32Array array2 = wapp_array(i32, I32Array, 10, 20);
|
I32Array array2 = wapp_array(i32, 10, 20);
|
||||||
|
|
||||||
result = array1.count == 4 && array2.count == 2;
|
result = wapp_array_count(array1) == 4 && wapp_array_count(array2) == 2;
|
||||||
|
|
||||||
wapp_array_extend_capped(i32, &array1, &array2);
|
wapp_array_extend_capped(i32, array1, array2);
|
||||||
|
|
||||||
result = result && array1.count == 6;
|
result = result && wapp_array_count(array1) == 6;
|
||||||
|
|
||||||
return wapp_tester_result(result);
|
return wapp_tester_result(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
TestFuncResult test_i32_array_copy_capped(void) {
|
TestFuncResult test_i32_array_copy_capped(void) {
|
||||||
b8 result;
|
b8 result;
|
||||||
|
|
||||||
I32Array src = wapp_array(i32, I32Array, 1, 2, 3, 4, 5);
|
I32Array src = wapp_array(i32, 1, 2, 3, 4, 5);
|
||||||
I32Array dst1 = wapp_array(i32, I32Array, 1, 2, 3, 4, 5, 6);
|
I32Array dst1 = wapp_array(i32, 1, 2, 3, 4, 5, 6);
|
||||||
I32Array dst2 = wapp_array(i32, I32Array, 1, 2);
|
I32Array dst2 = wapp_array(i32, 1, 2);
|
||||||
|
|
||||||
u64 expected_count = 5;
|
u64 expected_count = 5;
|
||||||
wapp_array_copy_capped(i32, &dst1, &src);
|
wapp_array_copy_capped(i32, dst1, src);
|
||||||
result = dst1.count == expected_count;
|
result = wapp_array_count(dst1) == expected_count;
|
||||||
|
|
||||||
u64 index = 0;
|
u64 index = 0;
|
||||||
b8 running = true;
|
b8 running = true;
|
||||||
while (running) {
|
while (running) {
|
||||||
result = result && *wapp_array_get(i32, &src, index) == *wapp_array_get(i32, &dst1, index);
|
result = result && *wapp_array_get(i32, src, index) == *wapp_array_get(i32, dst1, index);
|
||||||
|
|
||||||
++index;
|
++index;
|
||||||
running = index < expected_count;
|
running = index < expected_count;
|
||||||
}
|
}
|
||||||
|
|
||||||
expected_count = 4;
|
expected_count = 4;
|
||||||
wapp_array_copy_capped(i32, &dst2, &src);
|
wapp_array_copy_capped(i32, dst2, src);
|
||||||
result = result && dst2.count == expected_count;
|
result = result && wapp_array_count(dst2) == expected_count;
|
||||||
|
|
||||||
index = 0;
|
index = 0;
|
||||||
running = true;
|
running = true;
|
||||||
while (running) {
|
while (running) {
|
||||||
result = result && *wapp_array_get(i32, &src, index) == *wapp_array_get(i32, &dst2, index);
|
result = result && *wapp_array_get(i32, src, index) == *wapp_array_get(i32, dst2, index);
|
||||||
|
|
||||||
++index;
|
++index;
|
||||||
running = index < expected_count;
|
running = index < expected_count;
|
||||||
}
|
}
|
||||||
|
|
||||||
return wapp_tester_result(result);
|
return wapp_tester_result(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
TestFuncResult test_i32_array_alloc_capacity(void) {
|
TestFuncResult test_i32_array_alloc_capacity(void) {
|
||||||
b8 result;
|
b8 result;
|
||||||
|
|
||||||
Allocator allocator = wapp_mem_arena_allocator_init(MB(4));
|
Allocator allocator = wapp_mem_arena_allocator_init(MiB(4));
|
||||||
u64 capacity = 32;
|
u64 capacity = 32;
|
||||||
I32Array *array = wapp_array_alloc_capacity(i32, I32Array, &allocator, capacity);
|
I32Array array = wapp_array_alloc_capacity(i32, &allocator, capacity, ARRAY_INIT_NONE);
|
||||||
|
|
||||||
result = array && array->capacity == capacity;
|
result = array && wapp_array_capacity(array) == capacity;
|
||||||
|
|
||||||
wapp_mem_arena_allocator_destroy(&allocator);
|
wapp_mem_arena_allocator_destroy(&allocator);
|
||||||
|
|
||||||
return wapp_tester_result(result);
|
return wapp_tester_result(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
TestFuncResult test_i32_array_append_alloc(void) {
|
TestFuncResult test_i32_array_append_alloc(void) {
|
||||||
b8 result;
|
b8 result;
|
||||||
|
|
||||||
Allocator allocator = wapp_mem_arena_allocator_init(MB(4));
|
Allocator allocator = wapp_mem_arena_allocator_init(MiB(4));
|
||||||
I32Array array1 = wapp_array(i32, I32Array, 1, 2, 3, 4, 5, 6, 7, 8);
|
I32Array array1 = wapp_array(i32, 1, 2, 3, 4, 5, 6, 7, 8);
|
||||||
I32Array array2 = wapp_array(i32, I32Array, 1, 2);
|
I32Array array2 = wapp_array(i32, 1, 2);
|
||||||
|
|
||||||
I32Array *arr_ptr = wapp_array_append_alloc(i32, I32Array, &allocator, &array1, &((i32){10}));
|
I32Array arr_ptr = wapp_array_append_alloc(i32, &allocator, array1, &((i32){10}), ARRAY_INIT_NONE);
|
||||||
result = arr_ptr == &array1;
|
result = arr_ptr == array1;
|
||||||
|
|
||||||
u64 count = 4;
|
u64 count = 4;
|
||||||
u64 index = 0;
|
u64 index = 0;
|
||||||
b8 running = true;
|
b8 running = true;
|
||||||
while (running) {
|
while (running) {
|
||||||
i32 num = (i32)index;
|
i32 num = (i32)index;
|
||||||
arr_ptr = wapp_array_append_alloc(i32, I32Array, &allocator, &array2, &num);
|
arr_ptr = wapp_array_append_alloc(i32, &allocator, array2, &num, ARRAY_INIT_NONE);
|
||||||
|
|
||||||
++index;
|
++index;
|
||||||
running = index < count;
|
running = index < count;
|
||||||
}
|
}
|
||||||
result = result && arr_ptr != &array2;
|
result = result && arr_ptr != array2;
|
||||||
|
|
||||||
wapp_mem_arena_allocator_destroy(&allocator);
|
wapp_mem_arena_allocator_destroy(&allocator);
|
||||||
|
|
||||||
return wapp_tester_result(result);
|
return wapp_tester_result(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
TestFuncResult test_i32_array_extend_alloc(void) {
|
TestFuncResult test_i32_array_extend_alloc(void) {
|
||||||
b8 result;
|
b8 result;
|
||||||
|
|
||||||
Allocator allocator = wapp_mem_arena_allocator_init(MB(4));
|
Allocator allocator = wapp_mem_arena_allocator_init(MiB(4));
|
||||||
I32Array array1 = wapp_array(i32, I32Array, 1, 2, 3, 4, 5, 6, 7, 8);
|
I32Array array1 = wapp_array(i32, 1, 2, 3, 4, 5, 6, 7, 8);
|
||||||
I32Array array2 = wapp_array(i32, I32Array, 1, 2);
|
I32Array array2 = wapp_array(i32, 1, 2);
|
||||||
I32Array array3 = wapp_array(i32, I32Array, 1, 2, 3, 4);
|
I32Array array3 = wapp_array(i32, 1, 2, 3, 4);
|
||||||
|
|
||||||
I32Array *arr_ptr = wapp_array_extend_alloc(i32, I32Array, &allocator, &array1, &array3);
|
I32Array arr_ptr = wapp_array_extend_alloc(i32, &allocator, array1, array3, ARRAY_INIT_NONE);
|
||||||
result = arr_ptr == &array1;
|
result = arr_ptr == array1;
|
||||||
|
|
||||||
arr_ptr = wapp_array_extend_alloc(i32, I32Array, &allocator, &array2, &array3);
|
arr_ptr = wapp_array_extend_alloc(i32, &allocator, array2, array3, ARRAY_INIT_NONE);
|
||||||
result = result && arr_ptr != &array2;
|
result = result && arr_ptr != array2;
|
||||||
|
|
||||||
wapp_mem_arena_allocator_destroy(&allocator);
|
wapp_mem_arena_allocator_destroy(&allocator);
|
||||||
|
|
||||||
return wapp_tester_result(result);
|
return wapp_tester_result(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
TestFuncResult test_i32_array_copy_alloc(void) {
|
TestFuncResult test_i32_array_copy_alloc(void) {
|
||||||
b8 result;
|
b8 result;
|
||||||
|
|
||||||
Allocator allocator = wapp_mem_arena_allocator_init(MB(4));
|
Allocator allocator = wapp_mem_arena_allocator_init(MiB(4));
|
||||||
I32Array src = wapp_array(i32, I32Array, 1, 2, 3, 4, 5);
|
I32Array src = wapp_array(i32, 1, 2, 3, 4, 5);
|
||||||
I32Array dst1 = wapp_array(i32, I32Array, 1, 2, 3, 4, 5, 6);
|
I32Array dst1 = wapp_array(i32, 1, 2, 3, 4, 5, 6);
|
||||||
I32Array dst2 = wapp_array(i32, I32Array, 1, 2);
|
I32Array dst2 = wapp_array(i32, 1, 2);
|
||||||
I32Array *array_ptr = NULL;
|
I32Array array = NULL;
|
||||||
|
|
||||||
u64 expected_count = 5;
|
u64 expected_count = 5;
|
||||||
array_ptr = wapp_array_copy_alloc(i32, I32Array, &allocator, &dst1, &src);
|
array = wapp_array_copy_alloc(i32, &allocator, dst1, src, ARRAY_INIT_NONE);
|
||||||
result = array_ptr->count == expected_count && array_ptr == &dst1;
|
result = wapp_array_count(array) == expected_count && array == dst1;
|
||||||
|
|
||||||
u64 index = 0;
|
u64 index = 0;
|
||||||
b8 running = true;
|
b8 running = true;
|
||||||
while (running) {
|
while (running) {
|
||||||
result = result && *wapp_array_get(i32, &src, index) == *wapp_array_get(i32, array_ptr, index);
|
result = result && *wapp_array_get(i32, src, index) == *wapp_array_get(i32, array, index);
|
||||||
|
|
||||||
++index;
|
++index;
|
||||||
running = index < expected_count;
|
running = index < expected_count;
|
||||||
}
|
}
|
||||||
|
|
||||||
expected_count = 5;
|
expected_count = 5;
|
||||||
array_ptr = wapp_array_copy_alloc(i32, I32Array, &allocator, &dst2, &src);
|
array = wapp_array_copy_alloc(i32, &allocator, dst2, src, ARRAY_INIT_NONE);
|
||||||
result = result && array_ptr->count == expected_count && array_ptr != &dst2;
|
result = result && wapp_array_count(array) == expected_count && array != dst2;
|
||||||
|
|
||||||
index = 0;
|
index = 0;
|
||||||
running = true;
|
running = true;
|
||||||
while (running) {
|
while (running) {
|
||||||
result = result && *wapp_array_get(i32, &src, index) == *wapp_array_get(i32, array_ptr, index);
|
result = result && *wapp_array_get(i32, src, index) == *wapp_array_get(i32, array, index);
|
||||||
|
|
||||||
++index;
|
++index;
|
||||||
running = index < expected_count;
|
running = index < expected_count;
|
||||||
}
|
}
|
||||||
|
|
||||||
wapp_mem_arena_allocator_destroy(&allocator);
|
wapp_mem_arena_allocator_destroy(&allocator);
|
||||||
|
|
||||||
return wapp_tester_result(result);
|
return wapp_tester_result(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
TestFuncResult test_i32_array_pop(void) {
|
TestFuncResult test_i32_array_pop(void) {
|
||||||
b8 result;
|
b8 result;
|
||||||
|
|
||||||
I32Array array1 = wapp_array(i32, I32Array, 0, 1, 2, 3, 4, 5, 6, 7, 8);
|
I32Array array1 = wapp_array(i32, 0, 1, 2, 3, 4, 5, 6, 7, 8);
|
||||||
I32Array array2 = wapp_array_with_capacity(i32, I32Array, 32);
|
I32Array array2 = wapp_array_with_capacity(i32, 32, ARRAY_INIT_NONE);
|
||||||
|
|
||||||
i32 item1 = wapp_array_pop(i32, &array1);
|
i32 item1 = wapp_array_pop(i32, array1);
|
||||||
i32 item2 = wapp_array_pop(i32, &array2);
|
i32 item2 = wapp_array_pop(i32, array2);
|
||||||
|
|
||||||
result = item1 == 8 && item2 == 0;
|
result = item1 == 8 && item2 == 0;
|
||||||
|
|
||||||
return wapp_tester_result(result);
|
return wapp_tester_result(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
TestFuncResult test_i32_array_clear(void) {
|
TestFuncResult test_i32_array_clear(void) {
|
||||||
b8 result;
|
b8 result;
|
||||||
|
|
||||||
I32Array array = wapp_array(i32, I32Array, 0, 1, 2, 3, 4, 5, 6, 7, 8);
|
I32Array array = wapp_array(i32, 0, 1, 2, 3, 4, 5, 6, 7, 8);
|
||||||
result = array.count == 9;
|
result = wapp_array_count(array) == 9;
|
||||||
|
|
||||||
wapp_array_clear(i32, &array);
|
wapp_array_clear(i32, array);
|
||||||
|
|
||||||
result = result && array.count == 0;
|
result = result && wapp_array_count(array) == 0;
|
||||||
|
|
||||||
return wapp_tester_result(result);
|
return wapp_tester_result(result);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,272 +2,275 @@
|
|||||||
#include "wapp.h"
|
#include "wapp.h"
|
||||||
|
|
||||||
TestFuncResult test_i32_array(void) {
|
TestFuncResult test_i32_array(void) {
|
||||||
b8 result;
|
b8 result;
|
||||||
|
|
||||||
I32Array array = wapp_array(i32, I32Array, 1, 2, 3, 4, 5, 6, 7);
|
I32Array array = wapp_array(i32, 1, 2, 3, 4, 5, 6, 7);
|
||||||
result = array.count == 7 && array.capacity == 16;
|
result = wapp_array_count(array) == 7 && wapp_array_capacity(array) == 16;
|
||||||
|
|
||||||
i32 *item;
|
i32 *item;
|
||||||
u64 count = array.count;
|
u64 count = wapp_array_count(array);
|
||||||
u64 index = 0;
|
u64 index = 0;
|
||||||
b8 running = true;
|
b8 running = true;
|
||||||
while (running) {
|
while (running) {
|
||||||
item = wapp_array_get(i32, &array, index);
|
item = wapp_array_get(i32, array, index);
|
||||||
result = result && item && (*item == (i32)(index + 1));
|
result = result && item && (*item == (i32)(index + 1));
|
||||||
|
|
||||||
++index;
|
++index;
|
||||||
running = index < count;
|
running = index < count;
|
||||||
}
|
}
|
||||||
|
|
||||||
return wapp_tester_result(result);
|
return wapp_tester_result(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
TestFuncResult test_i32_array_with_capacity(void) {
|
TestFuncResult test_i32_array_with_capacity(void) {
|
||||||
b8 result;
|
b8 result;
|
||||||
|
|
||||||
I32Array array = wapp_array_with_capacity(i32, I32Array, 64);
|
I32Array array1 = wapp_array_with_capacity(i32, 64, ARRAY_INIT_NONE);
|
||||||
result = array.count == 0 && array.capacity == 64;
|
result = wapp_array_count(array1) == 0 && wapp_array_capacity(array1) == 64;
|
||||||
|
|
||||||
return wapp_tester_result(result);
|
I32Array array2 = wapp_array_with_capacity(i32, 64, ARRAY_INIT_FILLED);
|
||||||
|
result = wapp_array_count(array2) == 64 && wapp_array_capacity(array2) == 64;
|
||||||
|
|
||||||
|
return wapp_tester_result(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
TestFuncResult test_i32_array_get(void) {
|
TestFuncResult test_i32_array_get(void) {
|
||||||
b8 result = true;
|
b8 result = true;
|
||||||
|
|
||||||
I32Array array = wapp_array(i32, I32Array, 0, 1, 2, 3, 4, 5, 6, 7, 8);
|
I32Array array = wapp_array(i32, 0, 1, 2, 3, 4, 5, 6, 7, 8);
|
||||||
|
|
||||||
i32 *item;
|
i32 *item;
|
||||||
u64 count = array.count;
|
u64 count = wapp_array_count(array);
|
||||||
u64 index = 0;
|
u64 index = 0;
|
||||||
b8 running = true;
|
b8 running = true;
|
||||||
while (running) {
|
while (running) {
|
||||||
item = wapp_array_get(i32, &array, index);
|
item = wapp_array_get(i32, array, index);
|
||||||
result = result && item && (*item == (i32)index);
|
result = result && item && (*item == (i32)index);
|
||||||
|
|
||||||
++index;
|
++index;
|
||||||
running = index < count;
|
running = index < count;
|
||||||
}
|
}
|
||||||
|
|
||||||
return wapp_tester_result(result);
|
return wapp_tester_result(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
TestFuncResult test_i32_array_set(void) {
|
TestFuncResult test_i32_array_set(void) {
|
||||||
b8 result = true;
|
b8 result = true;
|
||||||
|
|
||||||
I32Array array = wapp_array(i32, I32Array, 0, 1, 2, 3, 4, 5, 6, 7, 8);
|
I32Array array = wapp_array(i32, 0, 1, 2, 3, 4, 5, 6, 7, 8);
|
||||||
|
|
||||||
i32 *item;
|
i32 *item;
|
||||||
u64 count = array.count;
|
u64 count = wapp_array_count(array);
|
||||||
u64 index = 0;
|
u64 index = 0;
|
||||||
b8 running = true;
|
b8 running = true;
|
||||||
while (running) {
|
while (running) {
|
||||||
i32 num = (i32)(index * 2);
|
i32 num = (i32)(index * 2);
|
||||||
wapp_array_set(i32, &array, index, &num);
|
wapp_array_set(i32, array, index, &num);
|
||||||
item = wapp_array_get(i32, &array, index);
|
item = wapp_array_get(i32, array, index);
|
||||||
result = result && item && (*item == (i32)(index * 2));
|
result = result && item && (*item == (i32)(index * 2));
|
||||||
|
|
||||||
++index;
|
++index;
|
||||||
running = index < count;
|
running = index < count;
|
||||||
}
|
}
|
||||||
|
|
||||||
return wapp_tester_result(result);
|
return wapp_tester_result(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
TestFuncResult test_i32_array_append_capped(void) {
|
TestFuncResult test_i32_array_append_capped(void) {
|
||||||
b8 result;
|
b8 result;
|
||||||
|
|
||||||
I32Array array = wapp_array_with_capacity(i32, I32Array, 64);
|
I32Array array = wapp_array_with_capacity(i32, 64, ARRAY_INIT_NONE);
|
||||||
i32 item1 = 10;
|
i32 item1 = 10;
|
||||||
wapp_array_append_capped(i32, &array, &item1);
|
wapp_array_append_capped(i32, array, &item1);
|
||||||
|
|
||||||
result = array.count == 1;
|
result = wapp_array_count(array) == 1;
|
||||||
i32 *item = wapp_array_get(i32, &array, 0);
|
i32 *item = wapp_array_get(i32, array, 0);
|
||||||
result = result && item && *item == 10;
|
result = result && item && *item == 10;
|
||||||
|
|
||||||
array = wapp_array(i32, I32Array, 1);
|
array = wapp_array(i32, 1);
|
||||||
i32 item2 = 10;
|
i32 item2 = 10;
|
||||||
wapp_array_append_capped(i32, &array, &item2);
|
wapp_array_append_capped(i32, array, &item2);
|
||||||
|
|
||||||
result = result && array.count == 2;
|
result = result && wapp_array_count(array) == 2;
|
||||||
|
|
||||||
return wapp_tester_result(result);
|
return wapp_tester_result(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
TestFuncResult test_i32_array_extend_capped(void) {
|
TestFuncResult test_i32_array_extend_capped(void) {
|
||||||
b8 result;
|
b8 result;
|
||||||
|
|
||||||
I32Array array1 = wapp_array(i32, I32Array, 1, 2, 3, 4);
|
I32Array array1 = wapp_array(i32, 1, 2, 3, 4);
|
||||||
I32Array array2 = wapp_array(i32, I32Array, 10, 20);
|
I32Array array2 = wapp_array(i32, 10, 20);
|
||||||
|
|
||||||
result = array1.count == 4 && array2.count == 2;
|
result = wapp_array_count(array1) == 4 && wapp_array_count(array2) == 2;
|
||||||
|
|
||||||
wapp_array_extend_capped(i32, &array1, &array2);
|
wapp_array_extend_capped(i32, array1, array2);
|
||||||
|
|
||||||
result = result && array1.count == 6;
|
result = result && wapp_array_count(array1) == 6;
|
||||||
|
|
||||||
return wapp_tester_result(result);
|
return wapp_tester_result(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
TestFuncResult test_i32_array_copy_capped(void) {
|
TestFuncResult test_i32_array_copy_capped(void) {
|
||||||
b8 result;
|
b8 result;
|
||||||
|
|
||||||
I32Array src = wapp_array(i32, I32Array, 1, 2, 3, 4, 5);
|
I32Array src = wapp_array(i32, 1, 2, 3, 4, 5);
|
||||||
I32Array dst1 = wapp_array(i32, I32Array, 1, 2, 3, 4, 5, 6);
|
I32Array dst1 = wapp_array(i32, 1, 2, 3, 4, 5, 6);
|
||||||
I32Array dst2 = wapp_array(i32, I32Array, 1, 2);
|
I32Array dst2 = wapp_array(i32, 1, 2);
|
||||||
|
|
||||||
u64 expected_count = 5;
|
u64 expected_count = 5;
|
||||||
wapp_array_copy_capped(i32, &dst1, &src);
|
wapp_array_copy_capped(i32, dst1, src);
|
||||||
result = dst1.count == expected_count;
|
result = wapp_array_count(dst1) == expected_count;
|
||||||
|
|
||||||
u64 index = 0;
|
u64 index = 0;
|
||||||
b8 running = true;
|
b8 running = true;
|
||||||
while (running) {
|
while (running) {
|
||||||
result = result && (*wapp_array_get(i32, &src, index) == *wapp_array_get(i32, &dst1, index));
|
result = result && (*wapp_array_get(i32, src, index) == *wapp_array_get(i32, dst1, index));
|
||||||
|
|
||||||
++index;
|
++index;
|
||||||
running = index < expected_count;
|
running = index < expected_count;
|
||||||
}
|
}
|
||||||
|
|
||||||
expected_count = 4;
|
expected_count = 4;
|
||||||
wapp_array_copy_capped(i32, &dst2, &src);
|
wapp_array_copy_capped(i32, dst2, src);
|
||||||
result = result && dst2.count == expected_count;
|
result = result && wapp_array_count(dst2) == expected_count;
|
||||||
|
|
||||||
index = 0;
|
index = 0;
|
||||||
running = true;
|
running = true;
|
||||||
while (running) {
|
while (running) {
|
||||||
result = result && (*wapp_array_get(i32, &src, index) == *wapp_array_get(i32, &dst2, index));
|
result = result && (*wapp_array_get(i32, src, index) == *wapp_array_get(i32, dst2, index));
|
||||||
|
|
||||||
++index;
|
++index;
|
||||||
running = index < expected_count;
|
running = index < expected_count;
|
||||||
}
|
}
|
||||||
|
|
||||||
return wapp_tester_result(result);
|
return wapp_tester_result(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
TestFuncResult test_i32_array_alloc_capacity(void) {
|
TestFuncResult test_i32_array_alloc_capacity(void) {
|
||||||
b8 result;
|
b8 result;
|
||||||
|
|
||||||
Allocator allocator = wapp_mem_arena_allocator_init(MB(4));
|
Allocator allocator = wapp_mem_arena_allocator_init(MiB(4));
|
||||||
u64 capacity = 32;
|
u64 capacity = 32;
|
||||||
I32Array *array = wapp_array_alloc_capacity(i32, I32Array, &allocator, capacity);
|
I32Array array = wapp_array_alloc_capacity(i32, &allocator, capacity, ARRAY_INIT_NONE);
|
||||||
|
|
||||||
result = array && array->capacity == capacity;
|
result = array && wapp_array_capacity(array) == capacity;
|
||||||
|
|
||||||
wapp_mem_arena_allocator_destroy(&allocator);
|
wapp_mem_arena_allocator_destroy(&allocator);
|
||||||
|
|
||||||
return wapp_tester_result(result);
|
return wapp_tester_result(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
TestFuncResult test_i32_array_append_alloc(void) {
|
TestFuncResult test_i32_array_append_alloc(void) {
|
||||||
b8 result;
|
b8 result;
|
||||||
|
|
||||||
Allocator allocator = wapp_mem_arena_allocator_init(MB(4));
|
Allocator allocator = wapp_mem_arena_allocator_init(MiB(4));
|
||||||
I32Array array1 = wapp_array(i32, I32Array, 1, 2, 3, 4, 5, 6, 7, 8);
|
I32Array array1 = wapp_array(i32, 1, 2, 3, 4, 5, 6, 7, 8);
|
||||||
I32Array array2 = wapp_array(i32, I32Array, 1, 2);
|
I32Array array2 = wapp_array(i32, 1, 2);
|
||||||
|
|
||||||
i32 num = 10;
|
i32 num = 10;
|
||||||
I32Array *arr_ptr = wapp_array_append_alloc(i32, I32Array, &allocator, &array1, &num);
|
I32Array arr_ptr = wapp_array_append_alloc(i32, &allocator, array1, &num, ARRAY_INIT_NONE);
|
||||||
result = arr_ptr == &array1;
|
result = arr_ptr == array1;
|
||||||
|
|
||||||
u64 count = 4;
|
u64 count = 4;
|
||||||
u64 index = 0;
|
u64 index = 0;
|
||||||
b8 running = true;
|
b8 running = true;
|
||||||
while (running) {
|
while (running) {
|
||||||
num = (i32)index;
|
num = (i32)index;
|
||||||
arr_ptr = wapp_array_append_alloc(i32, I32Array, &allocator, &array2, &num);
|
arr_ptr = wapp_array_append_alloc(i32, &allocator, array2, &num, ARRAY_INIT_NONE);
|
||||||
|
|
||||||
++index;
|
++index;
|
||||||
running = index < count;
|
running = index < count;
|
||||||
}
|
}
|
||||||
result = result && arr_ptr != &array2;
|
result = result && arr_ptr != array2;
|
||||||
|
|
||||||
wapp_mem_arena_allocator_destroy(&allocator);
|
wapp_mem_arena_allocator_destroy(&allocator);
|
||||||
|
|
||||||
return wapp_tester_result(result);
|
return wapp_tester_result(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
TestFuncResult test_i32_array_extend_alloc(void) {
|
TestFuncResult test_i32_array_extend_alloc(void) {
|
||||||
b8 result;
|
b8 result;
|
||||||
|
|
||||||
Allocator allocator = wapp_mem_arena_allocator_init(MB(4));
|
Allocator allocator = wapp_mem_arena_allocator_init(MiB(4));
|
||||||
I32Array array1 = wapp_array(i32, I32Array, 1, 2, 3, 4, 5, 6, 7, 8);
|
I32Array array1 = wapp_array(i32, 1, 2, 3, 4, 5, 6, 7, 8);
|
||||||
I32Array array2 = wapp_array(i32, I32Array, 1, 2);
|
I32Array array2 = wapp_array(i32, 1, 2);
|
||||||
I32Array array3 = wapp_array(i32, I32Array, 1, 2, 3, 4);
|
I32Array array3 = wapp_array(i32, 1, 2, 3, 4);
|
||||||
|
|
||||||
I32Array *arr_ptr = wapp_array_extend_alloc(i32, I32Array, &allocator, &array1, &array3);
|
I32Array array = wapp_array_extend_alloc(i32, &allocator, array1, array3, ARRAY_INIT_NONE);
|
||||||
result = arr_ptr == &array1;
|
result = array == array1;
|
||||||
|
|
||||||
arr_ptr = wapp_array_extend_alloc(i32, I32Array, &allocator, &array2, &array3);
|
array = wapp_array_extend_alloc(i32, &allocator, array2, array3, ARRAY_INIT_NONE);
|
||||||
result = result && arr_ptr != &array2;
|
result = result && array != array2;
|
||||||
|
|
||||||
wapp_mem_arena_allocator_destroy(&allocator);
|
wapp_mem_arena_allocator_destroy(&allocator);
|
||||||
|
|
||||||
return wapp_tester_result(result);
|
return wapp_tester_result(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
TestFuncResult test_i32_array_copy_alloc(void) {
|
TestFuncResult test_i32_array_copy_alloc(void) {
|
||||||
b8 result;
|
b8 result;
|
||||||
|
|
||||||
Allocator allocator = wapp_mem_arena_allocator_init(MB(4));
|
Allocator allocator = wapp_mem_arena_allocator_init(MiB(4));
|
||||||
I32Array src = wapp_array(i32, I32Array, 1, 2, 3, 4, 5);
|
I32Array src = wapp_array(i32, 1, 2, 3, 4, 5);
|
||||||
I32Array dst1 = wapp_array(i32, I32Array, 1, 2, 3, 4, 5, 6);
|
I32Array dst1 = wapp_array(i32, 1, 2, 3, 4, 5, 6);
|
||||||
I32Array dst2 = wapp_array(i32, I32Array, 1, 2);
|
I32Array dst2 = wapp_array(i32, 1, 2);
|
||||||
I32Array *array_ptr = nullptr;
|
I32Array array = nullptr;
|
||||||
|
|
||||||
u64 expected_count = 5;
|
u64 expected_count = 5;
|
||||||
array_ptr = wapp_array_copy_alloc(i32, I32Array, &allocator, &dst1, &src);
|
array = wapp_array_copy_alloc(i32, &allocator, dst1, src, ARRAY_INIT_NONE);
|
||||||
result = array_ptr->count == expected_count && array_ptr == &dst1;
|
result = wapp_array_count(array) == expected_count && array == dst1;
|
||||||
|
|
||||||
u64 index = 0;
|
u64 index = 0;
|
||||||
b8 running = true;
|
b8 running = true;
|
||||||
while (running) {
|
while (running) {
|
||||||
result = result && (*wapp_array_get(i32, &src, index) == *wapp_array_get(i32, array_ptr, index));
|
result = result && (*wapp_array_get(i32, src, index) == *wapp_array_get(i32, array, index));
|
||||||
|
|
||||||
++index;
|
++index;
|
||||||
running = index < expected_count;
|
running = index < expected_count;
|
||||||
}
|
}
|
||||||
|
|
||||||
expected_count = 5;
|
expected_count = 5;
|
||||||
array_ptr = wapp_array_copy_alloc(i32, I32Array, &allocator, &dst2, &src);
|
array = wapp_array_copy_alloc(i32, &allocator, dst2, src, ARRAY_INIT_NONE);
|
||||||
result = result && array_ptr->count == expected_count && array_ptr != &dst2;
|
result = result && wapp_array_count(array) == expected_count && array != dst2;
|
||||||
|
|
||||||
index = 0;
|
index = 0;
|
||||||
running = true;
|
running = true;
|
||||||
while (running) {
|
while (running) {
|
||||||
result = result && (*wapp_array_get(i32, &src, index) == *wapp_array_get(i32, array_ptr, index));
|
result = result && (*wapp_array_get(i32, src, index) == *wapp_array_get(i32, array, index));
|
||||||
|
|
||||||
++index;
|
++index;
|
||||||
running = index < expected_count;
|
running = index < expected_count;
|
||||||
}
|
}
|
||||||
|
|
||||||
wapp_mem_arena_allocator_destroy(&allocator);
|
wapp_mem_arena_allocator_destroy(&allocator);
|
||||||
|
|
||||||
return wapp_tester_result(result);
|
return wapp_tester_result(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
TestFuncResult test_i32_array_clear(void) {
|
TestFuncResult test_i32_array_clear(void) {
|
||||||
b8 result;
|
b8 result;
|
||||||
|
|
||||||
I32Array array = wapp_array(i32, I32Array, 0, 1, 2, 3, 4, 5, 6, 7, 8);
|
I32Array array = wapp_array(i32, 0, 1, 2, 3, 4, 5, 6, 7, 8);
|
||||||
result = array.count == 9;
|
result = wapp_array_count(array) == 9;
|
||||||
|
|
||||||
wapp_array_clear(i32, &array);
|
wapp_array_clear(i32, array);
|
||||||
|
|
||||||
result = result && array.count == 0;
|
result = result && wapp_array_count(array) == 0;
|
||||||
|
|
||||||
return wapp_tester_result(result);
|
return wapp_tester_result(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
TestFuncResult test_i32_array_pop(void) {
|
TestFuncResult test_i32_array_pop(void) {
|
||||||
b8 result;
|
b8 result;
|
||||||
|
|
||||||
I32Array array1 = wapp_array(i32, I32Array, 0, 1, 2, 3, 4, 5, 6, 7, 8);
|
I32Array array1 = wapp_array(i32, 0, 1, 2, 3, 4, 5, 6, 7, 8);
|
||||||
I32Array array2 = wapp_array_with_capacity(i32, I32Array, 32);
|
I32Array array2 = wapp_array_with_capacity(i32, 32, ARRAY_INIT_NONE);
|
||||||
|
|
||||||
i32 item1 = wapp_array_pop(i32, &array1);
|
i32 item1 = wapp_array_pop(i32, array1);
|
||||||
i32 item2 = wapp_array_pop(i32, &array2);
|
i32 item2 = wapp_array_pop(i32, array2);
|
||||||
|
|
||||||
result = item1 == 8 && item2 == 0;
|
result = item1 == 8 && item2 == 0;
|
||||||
|
|
||||||
return wapp_tester_result(result);
|
return wapp_tester_result(result);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,23 +3,23 @@
|
|||||||
#include "test_str8_array.h"
|
#include "test_str8_array.h"
|
||||||
|
|
||||||
TestFuncResult test_str8_array(void) {
|
TestFuncResult test_str8_array(void) {
|
||||||
b8 result;
|
b8 result;
|
||||||
|
|
||||||
Str8 expected[] = {wapp_str8_lit("Hello"), wapp_str8_lit("Hi"), wapp_str8_lit("Bye")};
|
Str8 expected[] = {wapp_str8_lit("Hello"), wapp_str8_lit("Hi"), wapp_str8_lit("Bye")};
|
||||||
Str8Array array = wapp_array(Str8, Str8Array, wapp_str8_lit("Hello"), wapp_str8_lit("Hi"), wapp_str8_lit("Bye"));
|
Str8Array array = wapp_array(Str8, wapp_str8_lit("Hello"), wapp_str8_lit("Hi"), wapp_str8_lit("Bye"));
|
||||||
result = array.count == 3 && array.capacity == 8;
|
result = wapp_array_count(array) == 3 && wapp_array_capacity(array) == 8;
|
||||||
|
|
||||||
Str8 *item;
|
Str8 *item;
|
||||||
u64 count = array.count;
|
u64 count = wapp_array_count(array);
|
||||||
u64 index = 0;
|
u64 index = 0;
|
||||||
b8 running = true;
|
b8 running = true;
|
||||||
while (running) {
|
while (running) {
|
||||||
item = wapp_array_get(Str8, &array, index);
|
item = wapp_array_get(Str8, array, index);
|
||||||
result = result && item && (wapp_str8_equal(item, &expected[index]));
|
result = result && item && (wapp_str8_equal(item, &expected[index]));
|
||||||
|
|
||||||
++index;
|
++index;
|
||||||
running = index < count;
|
running = index < count;
|
||||||
}
|
}
|
||||||
|
|
||||||
return wapp_tester_result(result);
|
return wapp_tester_result(result);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,28 +3,28 @@
|
|||||||
#include "test_str8_array.h"
|
#include "test_str8_array.h"
|
||||||
|
|
||||||
TestFuncResult test_str8_array(void) {
|
TestFuncResult test_str8_array(void) {
|
||||||
b8 result;
|
b8 result;
|
||||||
|
|
||||||
Str8 expected[] = {wapp_str8_lit("Hello"), wapp_str8_lit("Hi"), wapp_str8_lit("Bye")};
|
Str8 expected[] = {wapp_str8_lit("Hello"), wapp_str8_lit("Hi"), wapp_str8_lit("Bye")};
|
||||||
|
|
||||||
Str8 str1 = wapp_str8_lit("Hello");
|
Str8 str1 = wapp_str8_lit("Hello");
|
||||||
Str8 str2 = wapp_str8_lit("Hi");
|
Str8 str2 = wapp_str8_lit("Hi");
|
||||||
Str8 str3 = wapp_str8_lit("Bye");
|
Str8 str3 = wapp_str8_lit("Bye");
|
||||||
Str8Array array = wapp_array(Str8, Str8Array, str1, str2, str3);
|
Str8Array array = wapp_array(Str8, str1, str2, str3);
|
||||||
|
|
||||||
result = array.count == 3 && array.capacity == 8;
|
result = wapp_array_count(array) == 3 && wapp_array_capacity(array) == 8;
|
||||||
|
|
||||||
Str8 *item;
|
Str8 *item;
|
||||||
u64 count = array.count;
|
u64 count = wapp_array_count(array);
|
||||||
u64 index = 0;
|
u64 index = 0;
|
||||||
b8 running = true;
|
b8 running = true;
|
||||||
while (running) {
|
while (running) {
|
||||||
item = wapp_array_get(Str8, &array, index);
|
item = wapp_array_get(Str8, array, index);
|
||||||
result = result && item && (wapp_str8_equal(item, &expected[index]));
|
result = result && item && (wapp_str8_equal(item, &expected[index]));
|
||||||
|
|
||||||
++index;
|
++index;
|
||||||
running = index < count;
|
running = index < count;
|
||||||
}
|
}
|
||||||
|
|
||||||
return wapp_tester_result(result);
|
return wapp_tester_result(result);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,175 +7,175 @@
|
|||||||
#define TMP_BUF_SIZE 1024
|
#define TMP_BUF_SIZE 1024
|
||||||
|
|
||||||
TestFuncResult test_cpath_join_path(void) {
|
TestFuncResult test_cpath_join_path(void) {
|
||||||
b8 result;
|
b8 result;
|
||||||
|
|
||||||
Str8 expected = wapp_str8_buf(MAIN_BUF_SIZE);
|
Str8 expected = wapp_str8_buf(MAIN_BUF_SIZE);
|
||||||
Str8 out = wapp_str8_buf(MAIN_BUF_SIZE);
|
Str8 out = wapp_str8_buf(MAIN_BUF_SIZE);
|
||||||
Str8 tmp = wapp_str8_buf(TMP_BUF_SIZE);
|
Str8 tmp = wapp_str8_buf(TMP_BUF_SIZE);
|
||||||
|
|
||||||
wapp_str8_format(&expected, "%chome%cabdelrahman%cDocuments", WAPP_PATH_SEP, WAPP_PATH_SEP, WAPP_PATH_SEP);
|
wapp_str8_format(&expected, "%chome%cabdelrahman%cDocuments", WAPP_PATH_SEP, WAPP_PATH_SEP, WAPP_PATH_SEP);
|
||||||
wapp_str8_format(&tmp, "%c", WAPP_PATH_SEP);
|
wapp_str8_format(&tmp, "%c", WAPP_PATH_SEP);
|
||||||
|
|
||||||
Str8List parts = {0};
|
Str8List parts = wapp_dbl_list(Str8);
|
||||||
wapp_str8_list_push_back(&parts, &wapp_str8_node_from_str8(tmp));
|
wapp_dbl_list_push_back(Str8, &parts, &tmp);
|
||||||
wapp_str8_list_push_back(&parts, &wapp_str8_node_from_cstr("home"));
|
wapp_dbl_list_push_back(Str8, &parts, &wapp_str8_lit("home"));
|
||||||
wapp_str8_list_push_back(&parts, &wapp_str8_node_from_cstr("abdelrahman"));
|
wapp_dbl_list_push_back(Str8, &parts, &wapp_str8_lit("abdelrahman"));
|
||||||
wapp_str8_list_push_back(&parts, &wapp_str8_node_from_cstr("Documents"));
|
wapp_dbl_list_push_back(Str8, &parts, &wapp_str8_lit("Documents"));
|
||||||
|
|
||||||
wapp_cpath_join_path(&out, &parts);
|
wapp_cpath_join_path(&out, &parts);
|
||||||
result = wapp_str8_equal(&out, &expected);
|
result = wapp_str8_equal(&out, &expected);
|
||||||
|
|
||||||
wapp_str8_list_pop_front(&parts);
|
wapp_dbl_list_pop_front(Str8, &parts);
|
||||||
|
|
||||||
wapp_str8_format(&expected, "home%cabdelrahman%cDocuments", WAPP_PATH_SEP, WAPP_PATH_SEP);
|
wapp_str8_format(&expected, "home%cabdelrahman%cDocuments", WAPP_PATH_SEP, WAPP_PATH_SEP);
|
||||||
|
|
||||||
wapp_cpath_join_path(&out, &parts);
|
wapp_cpath_join_path(&out, &parts);
|
||||||
result = result && wapp_str8_equal(&out, &expected);
|
result = result && wapp_str8_equal(&out, &expected);
|
||||||
|
|
||||||
wapp_str8_concat_capped(&tmp, &wapp_str8_lit_ro("home"));
|
wapp_str8_concat_capped(&tmp, &wapp_str8_lit_ro("home"));
|
||||||
wapp_str8_list_pop_front(&parts);
|
wapp_dbl_list_pop_front(Str8, &parts);
|
||||||
wapp_str8_list_push_front(&parts, &wapp_str8_node_from_str8(tmp));
|
wapp_dbl_list_push_front(Str8, &parts, &tmp);
|
||||||
|
|
||||||
wapp_str8_format(&expected, "%chome%cabdelrahman%cDocuments", WAPP_PATH_SEP, WAPP_PATH_SEP, WAPP_PATH_SEP);
|
wapp_str8_format(&expected, "%chome%cabdelrahman%cDocuments", WAPP_PATH_SEP, WAPP_PATH_SEP, WAPP_PATH_SEP);
|
||||||
|
|
||||||
wapp_cpath_join_path(&out, &parts);
|
wapp_cpath_join_path(&out, &parts);
|
||||||
result = result && wapp_str8_equal(&out, &expected);
|
result = result && wapp_str8_equal(&out, &expected);
|
||||||
|
|
||||||
wapp_str8_format(&tmp, "home%c", WAPP_PATH_SEP);
|
wapp_str8_format(&tmp, "home%c", WAPP_PATH_SEP);
|
||||||
wapp_str8_list_pop_front(&parts);
|
wapp_dbl_list_pop_front(Str8, &parts);
|
||||||
wapp_str8_list_push_front(&parts, &wapp_str8_node_from_cstr("home"));
|
wapp_dbl_list_push_front(Str8, &parts, &wapp_str8_lit("home"));
|
||||||
|
|
||||||
wapp_str8_format(&expected, "home%cabdelrahman%cDocuments", WAPP_PATH_SEP, WAPP_PATH_SEP);
|
wapp_str8_format(&expected, "home%cabdelrahman%cDocuments", WAPP_PATH_SEP, WAPP_PATH_SEP);
|
||||||
|
|
||||||
wapp_cpath_join_path(&out, &parts);
|
wapp_cpath_join_path(&out, &parts);
|
||||||
result = result && wapp_str8_equal(&out, &expected);
|
result = result && wapp_str8_equal(&out, &expected);
|
||||||
|
|
||||||
wapp_str8_list_empty(&parts);
|
wapp_dbl_list_empty(Str8, &parts);
|
||||||
|
|
||||||
wapp_str8_format(&tmp, "%chome", WAPP_PATH_SEP);
|
wapp_str8_format(&tmp, "%chome", WAPP_PATH_SEP);
|
||||||
wapp_str8_list_push_back(&parts, &wapp_str8_node_from_str8(tmp));
|
wapp_dbl_list_push_back(Str8, &parts, &tmp);
|
||||||
wapp_str8_list_push_back(&parts, &wapp_str8_node_from_cstr(""));
|
wapp_dbl_list_push_back(Str8, &parts, &wapp_str8_lit(""));
|
||||||
|
|
||||||
wapp_str8_format(&expected, "%chome", WAPP_PATH_SEP);
|
wapp_str8_format(&expected, "%chome", WAPP_PATH_SEP);
|
||||||
|
|
||||||
wapp_cpath_join_path(&out, &parts);
|
wapp_cpath_join_path(&out, &parts);
|
||||||
result = result && wapp_str8_equal(&out, &expected);
|
result = result && wapp_str8_equal(&out, &expected);
|
||||||
|
|
||||||
wapp_str8_list_pop_front(&parts);
|
wapp_dbl_list_pop_front(Str8, &parts);
|
||||||
wapp_str8_list_push_back(&parts, &wapp_str8_node_from_cstr(""));
|
wapp_dbl_list_push_back(Str8, &parts, &wapp_str8_lit(""));
|
||||||
|
|
||||||
wapp_str8_format(&expected, "%s", "");
|
wapp_str8_format(&expected, "%s", "");
|
||||||
|
|
||||||
wapp_cpath_join_path(&out, &parts);
|
wapp_cpath_join_path(&out, &parts);
|
||||||
result = result && wapp_str8_equal(&out, &expected);
|
result = result && wapp_str8_equal(&out, &expected);
|
||||||
|
|
||||||
wapp_str8_list_pop_back(&parts);
|
wapp_dbl_list_pop_back(Str8, &parts);
|
||||||
wapp_str8_list_push_back(&parts, &wapp_str8_node_from_cstr("home"));
|
wapp_dbl_list_push_back(Str8, &parts, &wapp_str8_lit("home"));
|
||||||
|
|
||||||
wapp_str8_copy_cstr_capped(&expected, "home");
|
wapp_str8_copy_cstr_capped(&expected, "home");
|
||||||
|
|
||||||
wapp_cpath_join_path(&out, &parts);
|
wapp_cpath_join_path(&out, &parts);
|
||||||
result = result && wapp_str8_equal(&out, &expected);
|
result = result && wapp_str8_equal(&out, &expected);
|
||||||
|
|
||||||
return wapp_tester_result(result);
|
return wapp_tester_result(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
TestFuncResult test_cpath_dirname(void) {
|
TestFuncResult test_cpath_dirname(void) {
|
||||||
Allocator arena = wapp_mem_arena_allocator_init(MB(8));
|
Allocator arena = wapp_mem_arena_allocator_init(MiB(8));
|
||||||
if (wapp_mem_allocator_invalid(&arena)) {
|
if (wapp_mem_allocator_invalid(&arena)) {
|
||||||
return wapp_tester_result(false);
|
return wapp_tester_result(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
b8 result;
|
b8 result;
|
||||||
Str8 *output = NULL;
|
Str8 *output = NULL;
|
||||||
|
|
||||||
Str8 expected = wapp_str8_buf(MAIN_BUF_SIZE);
|
Str8 expected = wapp_str8_buf(MAIN_BUF_SIZE);
|
||||||
Str8 tmp = wapp_str8_buf(TMP_BUF_SIZE);
|
Str8 tmp = wapp_str8_buf(TMP_BUF_SIZE);
|
||||||
|
|
||||||
// CASE 1
|
// CASE 1
|
||||||
wapp_str8_format(&tmp, "%c", WAPP_PATH_SEP);
|
wapp_str8_format(&tmp, "%c", WAPP_PATH_SEP);
|
||||||
wapp_str8_format(&expected, "%c", WAPP_PATH_SEP);
|
wapp_str8_format(&expected, "%c", WAPP_PATH_SEP);
|
||||||
|
|
||||||
output = wapp_cpath_dirname(&arena, &tmp);
|
output = wapp_cpath_dirname(&arena, &tmp);
|
||||||
result = output != NULL && wapp_str8_equal(output, &expected);
|
result = output != NULL && wapp_str8_equal(output, &expected);
|
||||||
|
|
||||||
// CASE 2
|
// CASE 2
|
||||||
wapp_str8_format(&expected, "%s", ".");
|
wapp_str8_format(&expected, "%s", ".");
|
||||||
|
|
||||||
output = wapp_cpath_dirname(&arena, &wapp_str8_lit("home"));
|
output = wapp_cpath_dirname(&arena, &wapp_str8_lit("home"));
|
||||||
result = result && output != NULL && wapp_str8_equal(output, &expected);
|
result = result && output != NULL && wapp_str8_equal(output, &expected);
|
||||||
|
|
||||||
// CASE 3
|
// CASE 3
|
||||||
output = wapp_cpath_dirname(&arena, &wapp_str8_lit(""));
|
output = wapp_cpath_dirname(&arena, &wapp_str8_lit(""));
|
||||||
result = result && output != NULL && wapp_str8_equal(output, &expected);
|
result = result && output != NULL && wapp_str8_equal(output, &expected);
|
||||||
|
|
||||||
// CASE 4
|
// CASE 4
|
||||||
wapp_str8_format(&tmp, "%chome%ctest", WAPP_PATH_SEP, WAPP_PATH_SEP);
|
wapp_str8_format(&tmp, "%chome%ctest", WAPP_PATH_SEP, WAPP_PATH_SEP);
|
||||||
wapp_str8_format(&expected, "%chome", WAPP_PATH_SEP);
|
wapp_str8_format(&expected, "%chome", WAPP_PATH_SEP);
|
||||||
|
|
||||||
output = wapp_cpath_dirname(&arena, &tmp);
|
output = wapp_cpath_dirname(&arena, &tmp);
|
||||||
result = result && output != NULL && wapp_str8_equal(output, &expected);
|
result = result && output != NULL && wapp_str8_equal(output, &expected);
|
||||||
|
|
||||||
// CASE 5
|
// CASE 5
|
||||||
wapp_str8_format(&tmp, "%chome%ctest%c", WAPP_PATH_SEP, WAPP_PATH_SEP, WAPP_PATH_SEP);
|
wapp_str8_format(&tmp, "%chome%ctest%c", WAPP_PATH_SEP, WAPP_PATH_SEP, WAPP_PATH_SEP);
|
||||||
wapp_str8_format(&expected, "%chome", WAPP_PATH_SEP);
|
wapp_str8_format(&expected, "%chome", WAPP_PATH_SEP);
|
||||||
|
|
||||||
output = wapp_cpath_dirname(&arena, &tmp);
|
output = wapp_cpath_dirname(&arena, &tmp);
|
||||||
result = result && output != NULL && wapp_str8_equal(output, &expected);
|
result = result && output != NULL && wapp_str8_equal(output, &expected);
|
||||||
|
|
||||||
wapp_mem_arena_allocator_destroy(&arena);
|
wapp_mem_arena_allocator_destroy(&arena);
|
||||||
|
|
||||||
return wapp_tester_result(result);
|
return wapp_tester_result(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
TestFuncResult test_cpath_dirup(void) {
|
TestFuncResult test_cpath_dirup(void) {
|
||||||
Allocator arena = wapp_mem_arena_allocator_init(MB(8));
|
Allocator arena = wapp_mem_arena_allocator_init(MiB(8));
|
||||||
if (wapp_mem_allocator_invalid(&arena)) {
|
if (wapp_mem_allocator_invalid(&arena)) {
|
||||||
return wapp_tester_result(false);
|
return wapp_tester_result(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
b8 result;
|
b8 result;
|
||||||
Str8 *output = NULL;
|
Str8 *output = NULL;
|
||||||
|
|
||||||
Str8 expected = wapp_str8_buf(MAIN_BUF_SIZE);
|
Str8 expected = wapp_str8_buf(MAIN_BUF_SIZE);
|
||||||
Str8 tmp = wapp_str8_buf(TMP_BUF_SIZE);
|
Str8 tmp = wapp_str8_buf(TMP_BUF_SIZE);
|
||||||
|
|
||||||
// CASE 1
|
// CASE 1
|
||||||
wapp_str8_format(&tmp, "%c", WAPP_PATH_SEP);
|
wapp_str8_format(&tmp, "%c", WAPP_PATH_SEP);
|
||||||
wapp_str8_format(&expected, "%c", WAPP_PATH_SEP);
|
wapp_str8_format(&expected, "%c", WAPP_PATH_SEP);
|
||||||
|
|
||||||
output = wapp_cpath_dirup(&arena, &tmp, 3);
|
output = wapp_cpath_dirup(&arena, &tmp, 3);
|
||||||
result = output != NULL && wapp_str8_equal(output, &expected);
|
result = output != NULL && wapp_str8_equal(output, &expected);
|
||||||
|
|
||||||
// CASE 2
|
// CASE 2
|
||||||
wapp_str8_format(&tmp, "%chome%cabdelrahman%cDocuments", WAPP_PATH_SEP, WAPP_PATH_SEP, WAPP_PATH_SEP);
|
wapp_str8_format(&tmp, "%chome%cabdelrahman%cDocuments", WAPP_PATH_SEP, WAPP_PATH_SEP, WAPP_PATH_SEP);
|
||||||
wapp_str8_format(&expected, "%c", WAPP_PATH_SEP);
|
wapp_str8_format(&expected, "%c", WAPP_PATH_SEP);
|
||||||
|
|
||||||
output = wapp_cpath_dirup(&arena, &tmp, 3);
|
output = wapp_cpath_dirup(&arena, &tmp, 3);
|
||||||
result = result && output != NULL && wapp_str8_equal(output, &expected);
|
result = result && output != NULL && wapp_str8_equal(output, &expected);
|
||||||
|
|
||||||
// CASE 3
|
// CASE 3
|
||||||
wapp_str8_format(&tmp, "home%cabdelrahman%cDocuments", WAPP_PATH_SEP, WAPP_PATH_SEP);
|
wapp_str8_format(&tmp, "home%cabdelrahman%cDocuments", WAPP_PATH_SEP, WAPP_PATH_SEP);
|
||||||
wapp_str8_copy_cstr_capped(&expected, ".");
|
wapp_str8_copy_cstr_capped(&expected, ".");
|
||||||
|
|
||||||
output = wapp_cpath_dirup(&arena, &tmp, 3);
|
output = wapp_cpath_dirup(&arena, &tmp, 3);
|
||||||
result = result && output != NULL && wapp_str8_equal(output, &expected);
|
result = result && output != NULL && wapp_str8_equal(output, &expected);
|
||||||
|
|
||||||
// CASE 4
|
// CASE 4
|
||||||
wapp_str8_format(&tmp, "%chome%cabdelrahman%cDocuments", WAPP_PATH_SEP, WAPP_PATH_SEP, WAPP_PATH_SEP);
|
wapp_str8_format(&tmp, "%chome%cabdelrahman%cDocuments", WAPP_PATH_SEP, WAPP_PATH_SEP, WAPP_PATH_SEP);
|
||||||
wapp_str8_format(&expected, "%chome", WAPP_PATH_SEP);
|
wapp_str8_format(&expected, "%chome", WAPP_PATH_SEP);
|
||||||
|
|
||||||
output = wapp_cpath_dirup(&arena, &tmp, 2);
|
output = wapp_cpath_dirup(&arena, &tmp, 2);
|
||||||
result = result && output != NULL && wapp_str8_equal(output, &expected);
|
result = result && output != NULL && wapp_str8_equal(output, &expected);
|
||||||
|
|
||||||
// CASE 5
|
// CASE 5
|
||||||
wapp_str8_format(&tmp, "home%cabdelrahman%cDocuments", WAPP_PATH_SEP, WAPP_PATH_SEP);
|
wapp_str8_format(&tmp, "home%cabdelrahman%cDocuments", WAPP_PATH_SEP, WAPP_PATH_SEP);
|
||||||
wapp_str8_copy_cstr_capped(&expected, "home");
|
wapp_str8_copy_cstr_capped(&expected, "home");
|
||||||
|
|
||||||
output = wapp_cpath_dirup(&arena, &tmp, 2);
|
output = wapp_cpath_dirup(&arena, &tmp, 2);
|
||||||
result = result && output != NULL && wapp_str8_equal(output, &expected);
|
result = result && output != NULL && wapp_str8_equal(output, &expected);
|
||||||
|
|
||||||
wapp_mem_arena_allocator_destroy(&arena);
|
wapp_mem_arena_allocator_destroy(&arena);
|
||||||
|
|
||||||
return wapp_tester_result(result);
|
return wapp_tester_result(result);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,198 +7,195 @@
|
|||||||
#define TMP_BUF_SIZE 1024
|
#define TMP_BUF_SIZE 1024
|
||||||
|
|
||||||
TestFuncResult test_cpath_join_path(void) {
|
TestFuncResult test_cpath_join_path(void) {
|
||||||
b8 result;
|
b8 result;
|
||||||
|
|
||||||
Str8 expected = wapp_str8_buf(MAIN_BUF_SIZE);
|
Str8 expected = wapp_str8_buf(MAIN_BUF_SIZE);
|
||||||
Str8 out = wapp_str8_buf(MAIN_BUF_SIZE);
|
Str8 out = wapp_str8_buf(MAIN_BUF_SIZE);
|
||||||
Str8 tmp = wapp_str8_buf(TMP_BUF_SIZE);
|
Str8 tmp = wapp_str8_buf(TMP_BUF_SIZE);
|
||||||
|
|
||||||
wapp_str8_format(&expected, "%chome%cabdelrahman%cDocuments", WAPP_PATH_SEP, WAPP_PATH_SEP, WAPP_PATH_SEP);
|
wapp_str8_format(&expected, "%chome%cabdelrahman%cDocuments", WAPP_PATH_SEP, WAPP_PATH_SEP, WAPP_PATH_SEP);
|
||||||
wapp_str8_format(&tmp, "%c", WAPP_PATH_SEP);
|
wapp_str8_format(&tmp, "%c", WAPP_PATH_SEP);
|
||||||
|
|
||||||
Str8List parts = {};
|
Str8List parts = wapp_dbl_list(Str8);
|
||||||
|
|
||||||
Str8Node tmp_node = wapp_str8_node_from_str8(tmp);
|
wapp_dbl_list_push_back(Str8, &parts, &tmp);
|
||||||
wapp_str8_list_push_back(&parts, &tmp_node);
|
|
||||||
|
|
||||||
Str8Node home_node = wapp_str8_node_from_cstr("home");
|
Str8 home = wapp_str8_lit("home");
|
||||||
wapp_str8_list_push_back(&parts, &home_node);
|
wapp_dbl_list_push_back(Str8, &parts, &home);
|
||||||
|
|
||||||
Str8Node user_node = wapp_str8_node_from_cstr("abdelrahman");
|
Str8 user = wapp_str8_lit("abdelrahman");
|
||||||
wapp_str8_list_push_back(&parts, &user_node);
|
wapp_dbl_list_push_back(Str8, &parts, &user);
|
||||||
|
|
||||||
Str8Node docs_node = wapp_str8_node_from_cstr("Documents");
|
Str8 docs = wapp_str8_lit("Documents");
|
||||||
wapp_str8_list_push_back(&parts, &docs_node);
|
wapp_dbl_list_push_back(Str8, &parts, &docs);
|
||||||
|
|
||||||
wapp_cpath_join_path(&out, &parts);
|
wapp_cpath_join_path(&out, &parts);
|
||||||
result = wapp_str8_equal(&out, &expected);
|
result = wapp_str8_equal(&out, &expected);
|
||||||
|
|
||||||
wapp_str8_list_pop_front(&parts);
|
wapp_dbl_list_pop_front(Str8, &parts);
|
||||||
|
|
||||||
wapp_str8_format(&expected, "home%cabdelrahman%cDocuments", WAPP_PATH_SEP, WAPP_PATH_SEP);
|
wapp_str8_format(&expected, "home%cabdelrahman%cDocuments", WAPP_PATH_SEP, WAPP_PATH_SEP);
|
||||||
|
|
||||||
wapp_cpath_join_path(&out, &parts);
|
wapp_cpath_join_path(&out, &parts);
|
||||||
result = result && wapp_str8_equal(&out, &expected);
|
result = result && wapp_str8_equal(&out, &expected);
|
||||||
|
|
||||||
Str8RO str = wapp_str8_lit_ro("home");
|
Str8RO str = wapp_str8_lit_ro("home");
|
||||||
wapp_str8_concat_capped(&tmp, &str);
|
wapp_str8_concat_capped(&tmp, &str);
|
||||||
wapp_str8_list_pop_front(&parts);
|
wapp_dbl_list_pop_front(Str8, &parts);
|
||||||
|
|
||||||
Str8Node tmp_node_2 = wapp_str8_node_from_str8(tmp);
|
wapp_dbl_list_push_front(Str8, &parts, &tmp);
|
||||||
wapp_str8_list_push_front(&parts, &tmp_node_2);
|
|
||||||
|
|
||||||
wapp_str8_format(&expected, "%chome%cabdelrahman%cDocuments", WAPP_PATH_SEP, WAPP_PATH_SEP, WAPP_PATH_SEP);
|
wapp_str8_format(&expected, "%chome%cabdelrahman%cDocuments", WAPP_PATH_SEP, WAPP_PATH_SEP, WAPP_PATH_SEP);
|
||||||
|
|
||||||
wapp_cpath_join_path(&out, &parts);
|
wapp_cpath_join_path(&out, &parts);
|
||||||
result = result && wapp_str8_equal(&out, &expected);
|
result = result && wapp_str8_equal(&out, &expected);
|
||||||
|
|
||||||
wapp_str8_format(&tmp, "home%c", WAPP_PATH_SEP);
|
wapp_str8_format(&tmp, "home%c", WAPP_PATH_SEP);
|
||||||
wapp_str8_list_pop_front(&parts);
|
wapp_dbl_list_pop_front(Str8, &parts);
|
||||||
|
|
||||||
Str8Node home_node_2 = wapp_str8_node_from_cstr("home");
|
Str8 home_2 = wapp_str8_lit("home");
|
||||||
wapp_str8_list_push_front(&parts, &home_node_2);
|
wapp_dbl_list_push_front(Str8, &parts, &home_2);
|
||||||
|
|
||||||
wapp_str8_format(&expected, "home%cabdelrahman%cDocuments", WAPP_PATH_SEP, WAPP_PATH_SEP);
|
wapp_str8_format(&expected, "home%cabdelrahman%cDocuments", WAPP_PATH_SEP, WAPP_PATH_SEP);
|
||||||
|
|
||||||
wapp_cpath_join_path(&out, &parts);
|
wapp_cpath_join_path(&out, &parts);
|
||||||
result = result && wapp_str8_equal(&out, &expected);
|
result = result && wapp_str8_equal(&out, &expected);
|
||||||
|
|
||||||
wapp_str8_list_empty(&parts);
|
wapp_dbl_list_empty(Str8, &parts);
|
||||||
|
|
||||||
wapp_str8_format(&tmp, "%chome", WAPP_PATH_SEP);
|
wapp_str8_format(&tmp, "%chome", WAPP_PATH_SEP);
|
||||||
|
|
||||||
Str8Node tmp_node_3 = wapp_str8_node_from_str8(tmp);
|
wapp_dbl_list_push_back(Str8, &parts, &tmp);
|
||||||
wapp_str8_list_push_back(&parts, &tmp_node_3);
|
|
||||||
|
|
||||||
Str8Node empty_node = wapp_str8_node_from_cstr("");
|
Str8 empty = wapp_str8_lit("");
|
||||||
wapp_str8_list_push_back(&parts, &empty_node);
|
wapp_dbl_list_push_back(Str8, &parts, &empty);
|
||||||
|
|
||||||
wapp_str8_format(&expected, "%chome", WAPP_PATH_SEP);
|
wapp_str8_format(&expected, "%chome", WAPP_PATH_SEP);
|
||||||
|
|
||||||
wapp_cpath_join_path(&out, &parts);
|
wapp_cpath_join_path(&out, &parts);
|
||||||
result = result && wapp_str8_equal(&out, &expected);
|
result = result && wapp_str8_equal(&out, &expected);
|
||||||
|
|
||||||
wapp_str8_list_pop_front(&parts);
|
wapp_dbl_list_pop_front(Str8, &parts);
|
||||||
|
|
||||||
Str8Node empty_node_2 = wapp_str8_node_from_cstr("");
|
Str8 empty_2 = wapp_str8_lit("");
|
||||||
wapp_str8_list_push_back(&parts, &empty_node_2);
|
wapp_dbl_list_push_back(Str8, &parts, &empty_2);
|
||||||
|
|
||||||
wapp_str8_format(&expected, "%s", "");
|
wapp_str8_format(&expected, "%s", "");
|
||||||
|
|
||||||
wapp_cpath_join_path(&out, &parts);
|
wapp_cpath_join_path(&out, &parts);
|
||||||
result = result && wapp_str8_equal(&out, &expected);
|
result = result && wapp_str8_equal(&out, &expected);
|
||||||
|
|
||||||
wapp_str8_list_pop_back(&parts);
|
wapp_dbl_list_pop_back(Str8, &parts);
|
||||||
|
|
||||||
Str8Node home_node_3 = wapp_str8_node_from_cstr("home");
|
Str8 home_3 = wapp_str8_lit("home");
|
||||||
wapp_str8_list_push_back(&parts, &home_node_3);
|
wapp_dbl_list_push_back(Str8, &parts, &home_3);
|
||||||
|
|
||||||
wapp_str8_copy_cstr_capped(&expected, "home");
|
wapp_str8_copy_cstr_capped(&expected, "home");
|
||||||
|
|
||||||
wapp_cpath_join_path(&out, &parts);
|
wapp_cpath_join_path(&out, &parts);
|
||||||
result = result && wapp_str8_equal(&out, &expected);
|
result = result && wapp_str8_equal(&out, &expected);
|
||||||
|
|
||||||
return wapp_tester_result(result);
|
return wapp_tester_result(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
TestFuncResult test_cpath_dirname(void) {
|
TestFuncResult test_cpath_dirname(void) {
|
||||||
Allocator arena = wapp_mem_arena_allocator_init(MB(8));
|
Allocator arena = wapp_mem_arena_allocator_init(MiB(8));
|
||||||
if (wapp_mem_allocator_invalid(&arena)) {
|
if (wapp_mem_allocator_invalid(&arena)) {
|
||||||
return wapp_tester_result(false);
|
return wapp_tester_result(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
b8 result;
|
b8 result;
|
||||||
Str8 *output = nullptr;
|
Str8 *output = nullptr;
|
||||||
|
|
||||||
Str8 expected = wapp_str8_buf(MAIN_BUF_SIZE);
|
Str8 expected = wapp_str8_buf(MAIN_BUF_SIZE);
|
||||||
Str8 tmp = wapp_str8_buf(TMP_BUF_SIZE);
|
Str8 tmp = wapp_str8_buf(TMP_BUF_SIZE);
|
||||||
|
|
||||||
// CASE 1
|
// CASE 1
|
||||||
wapp_str8_format(&tmp, "%c", WAPP_PATH_SEP);
|
wapp_str8_format(&tmp, "%c", WAPP_PATH_SEP);
|
||||||
wapp_str8_format(&expected, "%c", WAPP_PATH_SEP);
|
wapp_str8_format(&expected, "%c", WAPP_PATH_SEP);
|
||||||
|
|
||||||
output = wapp_cpath_dirname(&arena, &tmp);
|
output = wapp_cpath_dirname(&arena, &tmp);
|
||||||
result = output != nullptr && wapp_str8_equal(output, &expected);
|
result = output != nullptr && wapp_str8_equal(output, &expected);
|
||||||
|
|
||||||
// CASE 2
|
// CASE 2
|
||||||
wapp_str8_format(&expected, "%s", ".");
|
wapp_str8_format(&expected, "%s", ".");
|
||||||
|
|
||||||
Str8 path = wapp_str8_lit("home");
|
Str8 path = wapp_str8_lit("home");
|
||||||
output = wapp_cpath_dirname(&arena, &path);
|
output = wapp_cpath_dirname(&arena, &path);
|
||||||
result = result && output != nullptr && wapp_str8_equal(output, &expected);
|
result = result && output != nullptr && wapp_str8_equal(output, &expected);
|
||||||
|
|
||||||
// CASE 3
|
// CASE 3
|
||||||
path = wapp_str8_lit("");
|
path = wapp_str8_lit("");
|
||||||
output = wapp_cpath_dirname(&arena, &path);
|
output = wapp_cpath_dirname(&arena, &path);
|
||||||
result = result && output != nullptr && wapp_str8_equal(output, &expected);
|
result = result && output != nullptr && wapp_str8_equal(output, &expected);
|
||||||
|
|
||||||
// CASE 4
|
// CASE 4
|
||||||
wapp_str8_format(&tmp, "%chome%ctest", WAPP_PATH_SEP, WAPP_PATH_SEP);
|
wapp_str8_format(&tmp, "%chome%ctest", WAPP_PATH_SEP, WAPP_PATH_SEP);
|
||||||
wapp_str8_format(&expected, "%chome", WAPP_PATH_SEP);
|
wapp_str8_format(&expected, "%chome", WAPP_PATH_SEP);
|
||||||
|
|
||||||
output = wapp_cpath_dirname(&arena, &tmp);
|
output = wapp_cpath_dirname(&arena, &tmp);
|
||||||
result = result && output != nullptr && wapp_str8_equal(output, &expected);
|
result = result && output != nullptr && wapp_str8_equal(output, &expected);
|
||||||
|
|
||||||
// CASE 5
|
// CASE 5
|
||||||
wapp_str8_format(&tmp, "%chome%ctest%c", WAPP_PATH_SEP, WAPP_PATH_SEP, WAPP_PATH_SEP);
|
wapp_str8_format(&tmp, "%chome%ctest%c", WAPP_PATH_SEP, WAPP_PATH_SEP, WAPP_PATH_SEP);
|
||||||
wapp_str8_format(&expected, "%chome", WAPP_PATH_SEP);
|
wapp_str8_format(&expected, "%chome", WAPP_PATH_SEP);
|
||||||
|
|
||||||
output = wapp_cpath_dirname(&arena, &tmp);
|
output = wapp_cpath_dirname(&arena, &tmp);
|
||||||
result = result && output != nullptr && wapp_str8_equal(output, &expected);
|
result = result && output != nullptr && wapp_str8_equal(output, &expected);
|
||||||
|
|
||||||
wapp_mem_arena_allocator_destroy(&arena);
|
wapp_mem_arena_allocator_destroy(&arena);
|
||||||
|
|
||||||
return wapp_tester_result(result);
|
return wapp_tester_result(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
TestFuncResult test_cpath_dirup(void) {
|
TestFuncResult test_cpath_dirup(void) {
|
||||||
Allocator arena = wapp_mem_arena_allocator_init(MB(8));
|
Allocator arena = wapp_mem_arena_allocator_init(MiB(8));
|
||||||
if (wapp_mem_allocator_invalid(&arena)) {
|
if (wapp_mem_allocator_invalid(&arena)) {
|
||||||
return wapp_tester_result(false);
|
return wapp_tester_result(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
b8 result;
|
b8 result;
|
||||||
Str8 *output = nullptr;
|
Str8 *output = nullptr;
|
||||||
|
|
||||||
Str8 expected = wapp_str8_buf(MAIN_BUF_SIZE);
|
Str8 expected = wapp_str8_buf(MAIN_BUF_SIZE);
|
||||||
Str8 tmp = wapp_str8_buf(TMP_BUF_SIZE);
|
Str8 tmp = wapp_str8_buf(TMP_BUF_SIZE);
|
||||||
|
|
||||||
// CASE 1
|
// CASE 1
|
||||||
wapp_str8_format(&tmp, "%c", WAPP_PATH_SEP);
|
wapp_str8_format(&tmp, "%c", WAPP_PATH_SEP);
|
||||||
wapp_str8_format(&expected, "%c", WAPP_PATH_SEP);
|
wapp_str8_format(&expected, "%c", WAPP_PATH_SEP);
|
||||||
|
|
||||||
output = wapp_cpath_dirup(&arena, &tmp, 3);
|
output = wapp_cpath_dirup(&arena, &tmp, 3);
|
||||||
result = output != nullptr && wapp_str8_equal(output, &expected);
|
result = output != nullptr && wapp_str8_equal(output, &expected);
|
||||||
|
|
||||||
// CASE 2
|
// CASE 2
|
||||||
wapp_str8_format(&tmp, "%chome%cabdelrahman%cDocuments", WAPP_PATH_SEP, WAPP_PATH_SEP, WAPP_PATH_SEP);
|
wapp_str8_format(&tmp, "%chome%cabdelrahman%cDocuments", WAPP_PATH_SEP, WAPP_PATH_SEP, WAPP_PATH_SEP);
|
||||||
wapp_str8_format(&expected, "%c", WAPP_PATH_SEP);
|
wapp_str8_format(&expected, "%c", WAPP_PATH_SEP);
|
||||||
|
|
||||||
output = wapp_cpath_dirup(&arena, &tmp, 3);
|
output = wapp_cpath_dirup(&arena, &tmp, 3);
|
||||||
result = result && output != nullptr && wapp_str8_equal(output, &expected);
|
result = result && output != nullptr && wapp_str8_equal(output, &expected);
|
||||||
|
|
||||||
// CASE 3
|
// CASE 3
|
||||||
wapp_str8_format(&tmp, "home%cabdelrahman%cDocuments", WAPP_PATH_SEP, WAPP_PATH_SEP);
|
wapp_str8_format(&tmp, "home%cabdelrahman%cDocuments", WAPP_PATH_SEP, WAPP_PATH_SEP);
|
||||||
wapp_str8_copy_cstr_capped(&expected, ".");
|
wapp_str8_copy_cstr_capped(&expected, ".");
|
||||||
|
|
||||||
output = wapp_cpath_dirup(&arena, &tmp, 3);
|
output = wapp_cpath_dirup(&arena, &tmp, 3);
|
||||||
result = result && output != nullptr && wapp_str8_equal(output, &expected);
|
result = result && output != nullptr && wapp_str8_equal(output, &expected);
|
||||||
|
|
||||||
// CASE 4
|
// CASE 4
|
||||||
wapp_str8_format(&tmp, "%chome%cabdelrahman%cDocuments", WAPP_PATH_SEP, WAPP_PATH_SEP, WAPP_PATH_SEP);
|
wapp_str8_format(&tmp, "%chome%cabdelrahman%cDocuments", WAPP_PATH_SEP, WAPP_PATH_SEP, WAPP_PATH_SEP);
|
||||||
wapp_str8_format(&expected, "%chome", WAPP_PATH_SEP);
|
wapp_str8_format(&expected, "%chome", WAPP_PATH_SEP);
|
||||||
|
|
||||||
output = wapp_cpath_dirup(&arena, &tmp, 2);
|
output = wapp_cpath_dirup(&arena, &tmp, 2);
|
||||||
result = result && output != nullptr && wapp_str8_equal(output, &expected);
|
result = result && output != nullptr && wapp_str8_equal(output, &expected);
|
||||||
|
|
||||||
// CASE 5
|
// CASE 5
|
||||||
wapp_str8_format(&tmp, "home%cabdelrahman%cDocuments", WAPP_PATH_SEP, WAPP_PATH_SEP);
|
wapp_str8_format(&tmp, "home%cabdelrahman%cDocuments", WAPP_PATH_SEP, WAPP_PATH_SEP);
|
||||||
wapp_str8_copy_cstr_capped(&expected, "home");
|
wapp_str8_copy_cstr_capped(&expected, "home");
|
||||||
|
|
||||||
output = wapp_cpath_dirup(&arena, &tmp, 2);
|
output = wapp_cpath_dirup(&arena, &tmp, 2);
|
||||||
result = result && output != nullptr && wapp_str8_equal(output, &expected);
|
result = result && output != nullptr && wapp_str8_equal(output, &expected);
|
||||||
|
|
||||||
wapp_mem_arena_allocator_destroy(&arena);
|
wapp_mem_arena_allocator_destroy(&arena);
|
||||||
|
|
||||||
return wapp_tester_result(result);
|
return wapp_tester_result(result);
|
||||||
}
|
}
|
||||||
|
|||||||
118
tests/file/test_file.c
Normal file
118
tests/file/test_file.c
Normal file
@@ -0,0 +1,118 @@
|
|||||||
|
// vim:fileencoding=utf-8:foldmethod=marker
|
||||||
|
|
||||||
|
#include "test_file.h"
|
||||||
|
|
||||||
|
#define DST_CAPACITY 5
|
||||||
|
wapp_intern Allocator arena = {0};
|
||||||
|
wapp_intern Str8RO test_filename = wapp_str8_lit_ro_initialiser_list("wapptest.bin");
|
||||||
|
wapp_intern Str8RO new_filename = wapp_str8_lit_ro_initialiser_list("wapptest2.bin");
|
||||||
|
wapp_intern WFile *test_fp = NULL;
|
||||||
|
wapp_intern I32Array src_array1 = wapp_array(i32, 0, 1, 2, 3, 4);
|
||||||
|
wapp_intern I32Array src_array2 = wapp_array(i32, 5, 6, 7, 8, 9);
|
||||||
|
wapp_intern I32Array src_array3 = wapp_array(i32, 10, 11, 12, 13, 14);
|
||||||
|
wapp_intern I32Array dst_array = wapp_array_with_capacity(i32, DST_CAPACITY, false);
|
||||||
|
wapp_intern i32 dst_buf[DST_CAPACITY] = {0};
|
||||||
|
|
||||||
|
TestFuncResult test_wapp_file_open(void) {
|
||||||
|
arena = wapp_mem_arena_allocator_init(KiB(16));
|
||||||
|
test_fp = wapp_file_open(&arena, &test_filename, WAPP_ACCESS_WRITE_EX);
|
||||||
|
return wapp_tester_result(test_fp != NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
TestFuncResult test_wapp_file_get_current_position(void) {
|
||||||
|
i64 pos = wapp_file_get_current_position(test_fp);
|
||||||
|
return wapp_tester_result(pos == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
TestFuncResult test_wapp_file_seek(void) {
|
||||||
|
wapp_file_write_array((GenericArray)src_array1, test_fp, wapp_array_count(src_array1));
|
||||||
|
|
||||||
|
i64 seek_result = wapp_file_seek(test_fp, 0, WAPP_SEEK_END);
|
||||||
|
b8 result = seek_result == (i64)(wapp_array_count(src_array1) * wapp_array_item_size(src_array1));
|
||||||
|
|
||||||
|
wapp_file_seek(test_fp, 0, WAPP_SEEK_START);
|
||||||
|
|
||||||
|
return wapp_tester_result(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
TestFuncResult test_wapp_file_get_length(void) {
|
||||||
|
i64 length = wapp_file_get_length(test_fp);
|
||||||
|
return wapp_tester_result(length == (i64)(wapp_array_count(src_array1) * wapp_array_item_size(src_array1)));
|
||||||
|
}
|
||||||
|
|
||||||
|
TestFuncResult test_wapp_file_read(void) {
|
||||||
|
wapp_file_seek(test_fp, 0, WAPP_SEEK_START);
|
||||||
|
|
||||||
|
u64 byte_count = DST_CAPACITY * sizeof(i32);
|
||||||
|
u64 count = wapp_file_read((void *)dst_buf, test_fp, byte_count);
|
||||||
|
b8 result = count == byte_count;
|
||||||
|
|
||||||
|
// NOTE (Abdelrahman): Uses a while loop instead of a for loop to get rid of
|
||||||
|
// MSVC Spectre mitigation warnings
|
||||||
|
u64 index = 0;
|
||||||
|
b8 running = true;
|
||||||
|
while (running) {
|
||||||
|
result = result && (dst_buf[index] == *wapp_array_get(i32, src_array1, index));
|
||||||
|
++index;
|
||||||
|
running = index < DST_CAPACITY;
|
||||||
|
}
|
||||||
|
|
||||||
|
return wapp_tester_result(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
TestFuncResult test_wapp_file_write(void) {
|
||||||
|
wapp_file_seek(test_fp, 0, WAPP_SEEK_END);
|
||||||
|
|
||||||
|
u64 expected_count = wapp_array_count(src_array2) * wapp_array_item_size(src_array2);
|
||||||
|
i64 count = wapp_file_write((void *)src_array2, test_fp, expected_count);
|
||||||
|
|
||||||
|
return wapp_tester_result(count >= 0 && (u64)count == expected_count);
|
||||||
|
}
|
||||||
|
|
||||||
|
TestFuncResult test_wapp_file_read_array(void) {
|
||||||
|
wapp_file_seek(test_fp, 0, WAPP_SEEK_START);
|
||||||
|
|
||||||
|
u64 count = wapp_file_read_array((GenericArray)dst_array, test_fp, wapp_array_count(src_array1));
|
||||||
|
b8 result = count == wapp_array_count(src_array1) &&
|
||||||
|
wapp_array_count(dst_array) == wapp_array_count(src_array1);
|
||||||
|
|
||||||
|
// NOTE (Abdelrahman): Uses a while loop instead of a for loop to get rid of
|
||||||
|
// MSVC Spectre mitigation warnings
|
||||||
|
u64 index = 0;
|
||||||
|
b8 running = true;
|
||||||
|
while (running) {
|
||||||
|
result = result && (*wapp_array_get(i32, dst_array, index) == *wapp_array_get(i32, src_array1, index));
|
||||||
|
++index;
|
||||||
|
running = index < wapp_array_count(dst_array);
|
||||||
|
}
|
||||||
|
|
||||||
|
return wapp_tester_result(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
TestFuncResult test_wapp_file_write_array(void) {
|
||||||
|
wapp_file_seek(test_fp, 0, WAPP_SEEK_END);
|
||||||
|
|
||||||
|
i64 count = wapp_file_write_array((GenericArray)src_array3, test_fp, wapp_array_count(src_array3));
|
||||||
|
|
||||||
|
return wapp_tester_result(count >= 0 && (u64)count == wapp_array_count(src_array3));
|
||||||
|
}
|
||||||
|
|
||||||
|
TestFuncResult test_wapp_file_flush(void) {
|
||||||
|
i32 flush_result = wapp_file_flush(test_fp);
|
||||||
|
return wapp_tester_result(flush_result == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
TestFuncResult test_wapp_file_close(void) {
|
||||||
|
i32 close_result = wapp_file_close(test_fp);
|
||||||
|
return wapp_tester_result(close_result == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
TestFuncResult test_wapp_file_rename(void) {
|
||||||
|
i32 rename_result = wapp_file_rename(&test_filename, &new_filename);
|
||||||
|
return wapp_tester_result(rename_result == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
TestFuncResult test_wapp_file_remove(void) {
|
||||||
|
i32 remove_result = wapp_file_remove(&new_filename);
|
||||||
|
return wapp_tester_result(remove_result == 0);
|
||||||
|
}
|
||||||
122
tests/file/test_file.cc
Normal file
122
tests/file/test_file.cc
Normal file
@@ -0,0 +1,122 @@
|
|||||||
|
// vim:fileencoding=utf-8:foldmethod=marker
|
||||||
|
|
||||||
|
#include "test_file.h"
|
||||||
|
|
||||||
|
#define DST_CAPACITY 5
|
||||||
|
wapp_intern Allocator arena = {};
|
||||||
|
wapp_intern Str8RO test_filename = wapp_str8_lit_ro_initialiser_list("wapptest.bin");
|
||||||
|
wapp_intern Str8RO new_filename = wapp_str8_lit_ro_initialiser_list("wapptest2.bin");
|
||||||
|
wapp_intern WFile *test_fp = NULL;
|
||||||
|
wapp_intern i32 dst_buf[DST_CAPACITY] = {0};
|
||||||
|
wapp_intern I32Array src_array1;
|
||||||
|
wapp_intern I32Array src_array2;
|
||||||
|
wapp_intern I32Array src_array3;
|
||||||
|
wapp_intern I32Array dst_array ;
|
||||||
|
|
||||||
|
TestFuncResult test_wapp_file_open(void) {
|
||||||
|
arena = wapp_mem_arena_allocator_init(KiB(16));
|
||||||
|
src_array1 = wapp_array(i32, 0, 1, 2, 3, 4);
|
||||||
|
src_array2 = wapp_array(i32, 5, 6, 7, 8, 9);
|
||||||
|
src_array3 = wapp_array(i32, 10, 11, 12, 13, 14);
|
||||||
|
dst_array = wapp_array_with_capacity(i32, DST_CAPACITY, false);
|
||||||
|
test_fp = wapp_file_open(&arena, &test_filename, WAPP_ACCESS_WRITE_EX);
|
||||||
|
return wapp_tester_result(test_fp != NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
TestFuncResult test_wapp_file_get_current_position(void) {
|
||||||
|
i64 pos = wapp_file_get_current_position(test_fp);
|
||||||
|
return wapp_tester_result(pos == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
TestFuncResult test_wapp_file_seek(void) {
|
||||||
|
wapp_file_write_array((GenericArray)src_array1, test_fp, wapp_array_count(src_array1));
|
||||||
|
|
||||||
|
i64 seek_result = wapp_file_seek(test_fp, 0, WAPP_SEEK_END);
|
||||||
|
b8 result = seek_result == (i64)(wapp_array_count(src_array1) * wapp_array_item_size(src_array1));
|
||||||
|
|
||||||
|
wapp_file_seek(test_fp, 0, WAPP_SEEK_START);
|
||||||
|
|
||||||
|
return wapp_tester_result(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
TestFuncResult test_wapp_file_get_length(void) {
|
||||||
|
i64 length = wapp_file_get_length(test_fp);
|
||||||
|
return wapp_tester_result(length == (i64)(wapp_array_count(src_array1) * wapp_array_item_size(src_array1)));
|
||||||
|
}
|
||||||
|
|
||||||
|
TestFuncResult test_wapp_file_read(void) {
|
||||||
|
wapp_file_seek(test_fp, 0, WAPP_SEEK_START);
|
||||||
|
|
||||||
|
u64 byte_count = DST_CAPACITY * sizeof(i32);
|
||||||
|
u64 count = wapp_file_read((void *)dst_buf, test_fp, byte_count);
|
||||||
|
b8 result = count == byte_count;
|
||||||
|
|
||||||
|
// NOTE (Abdelrahman): Uses a while loop instead of a for loop to get rid of
|
||||||
|
// MSVC Spectre mitigation warnings
|
||||||
|
u64 index = 0;
|
||||||
|
b8 running = true;
|
||||||
|
while (running) {
|
||||||
|
result = result && (dst_buf[index] == *wapp_array_get(i32, src_array1, index));
|
||||||
|
++index;
|
||||||
|
running = index < DST_CAPACITY;
|
||||||
|
}
|
||||||
|
|
||||||
|
return wapp_tester_result(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
TestFuncResult test_wapp_file_write(void) {
|
||||||
|
wapp_file_seek(test_fp, 0, WAPP_SEEK_END);
|
||||||
|
|
||||||
|
u64 expected_count = wapp_array_count(src_array2) * wapp_array_item_size(src_array2);
|
||||||
|
i64 count = wapp_file_write((void *)src_array2, test_fp, expected_count);
|
||||||
|
|
||||||
|
return wapp_tester_result(count >= 0 && (u64)count == expected_count);
|
||||||
|
}
|
||||||
|
|
||||||
|
TestFuncResult test_wapp_file_read_array(void) {
|
||||||
|
wapp_file_seek(test_fp, 0, WAPP_SEEK_START);
|
||||||
|
|
||||||
|
u64 count = wapp_file_read_array((GenericArray)dst_array, test_fp, wapp_array_count(src_array1));
|
||||||
|
b8 result = count == wapp_array_count(src_array1) &&
|
||||||
|
wapp_array_count(dst_array) == wapp_array_count(src_array1);
|
||||||
|
|
||||||
|
// NOTE (Abdelrahman): Uses a while loop instead of a for loop to get rid of
|
||||||
|
// MSVC Spectre mitigation warnings
|
||||||
|
u64 index = 0;
|
||||||
|
b8 running = true;
|
||||||
|
while (running) {
|
||||||
|
result = result && (*wapp_array_get(i32, dst_array, index) == *wapp_array_get(i32, src_array1, index));
|
||||||
|
++index;
|
||||||
|
running = index < wapp_array_count(dst_array);
|
||||||
|
}
|
||||||
|
|
||||||
|
return wapp_tester_result(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
TestFuncResult test_wapp_file_write_array(void) {
|
||||||
|
wapp_file_seek(test_fp, 0, WAPP_SEEK_END);
|
||||||
|
|
||||||
|
i64 count = wapp_file_write_array((GenericArray)src_array3, test_fp, wapp_array_count(src_array3));
|
||||||
|
|
||||||
|
return wapp_tester_result(count >= 0 && (u64)count == wapp_array_count(src_array3));
|
||||||
|
}
|
||||||
|
|
||||||
|
TestFuncResult test_wapp_file_flush(void) {
|
||||||
|
i32 flush_result = wapp_file_flush(test_fp);
|
||||||
|
return wapp_tester_result(flush_result == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
TestFuncResult test_wapp_file_close(void) {
|
||||||
|
i32 close_result = wapp_file_close(test_fp);
|
||||||
|
return wapp_tester_result(close_result == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
TestFuncResult test_wapp_file_rename(void) {
|
||||||
|
i32 rename_result = wapp_file_rename(&test_filename, &new_filename);
|
||||||
|
return wapp_tester_result(rename_result == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
TestFuncResult test_wapp_file_remove(void) {
|
||||||
|
i32 remove_result = wapp_file_remove(&new_filename);
|
||||||
|
return wapp_tester_result(remove_result == 0);
|
||||||
|
}
|
||||||
21
tests/file/test_file.h
Normal file
21
tests/file/test_file.h
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
// vim:fileencoding=utf-8:foldmethod=marker
|
||||||
|
|
||||||
|
#ifndef TEST_FILE_H
|
||||||
|
#define TEST_FILE_H
|
||||||
|
|
||||||
|
#include "wapp.h"
|
||||||
|
|
||||||
|
TestFuncResult test_wapp_file_open(void);
|
||||||
|
TestFuncResult test_wapp_file_get_current_position(void);
|
||||||
|
TestFuncResult test_wapp_file_seek(void);
|
||||||
|
TestFuncResult test_wapp_file_get_length(void);
|
||||||
|
TestFuncResult test_wapp_file_read(void);
|
||||||
|
TestFuncResult test_wapp_file_write(void);
|
||||||
|
TestFuncResult test_wapp_file_read_array(void);
|
||||||
|
TestFuncResult test_wapp_file_write_array(void);
|
||||||
|
TestFuncResult test_wapp_file_flush(void);
|
||||||
|
TestFuncResult test_wapp_file_close(void);
|
||||||
|
TestFuncResult test_wapp_file_rename(void);
|
||||||
|
TestFuncResult test_wapp_file_remove(void);
|
||||||
|
|
||||||
|
#endif // !TEST_FILE_H
|
||||||
98
tests/queue/test_queue.c
Normal file
98
tests/queue/test_queue.c
Normal file
@@ -0,0 +1,98 @@
|
|||||||
|
// vim:fileencoding=utf-8:foldmethod=marker
|
||||||
|
|
||||||
|
#include "wapp.h"
|
||||||
|
#include "test_queue.h"
|
||||||
|
|
||||||
|
#define CAPACITY 8
|
||||||
|
|
||||||
|
TestFuncResult test_queue_push(void) {
|
||||||
|
I32Queue queue = wapp_queue(i32, CAPACITY);
|
||||||
|
|
||||||
|
for (u64 i = 0; i < CAPACITY; ++i) {
|
||||||
|
i32 item = (i32)i;
|
||||||
|
wapp_queue_push(i32, &queue, &item);
|
||||||
|
}
|
||||||
|
|
||||||
|
b8 result = true;
|
||||||
|
for (u64 i = 0; i < CAPACITY; ++i) {
|
||||||
|
i32 *value = ((i32 *)(queue.items)) + i;
|
||||||
|
result = result && value != NULL && *value == (i32)i;
|
||||||
|
}
|
||||||
|
|
||||||
|
return wapp_tester_result(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
TestFuncResult test_queue_push_alloc(void) {
|
||||||
|
Allocator arena = wapp_mem_arena_allocator_init(MiB(64));
|
||||||
|
I32Queue queue = wapp_queue(i32, CAPACITY);
|
||||||
|
|
||||||
|
for (u64 i = 0; i < CAPACITY; ++i) {
|
||||||
|
i32 item = (i32)i;
|
||||||
|
wapp_queue_push(i32, &queue, &item);
|
||||||
|
}
|
||||||
|
|
||||||
|
b8 result = true;
|
||||||
|
i32 item = 8;
|
||||||
|
u64 new_capacity = CAPACITY * 2;
|
||||||
|
I32Queue *new_queue = wapp_queue_push_alloc(i32, &arena, &queue, &item);
|
||||||
|
if (new_queue && new_queue != &queue) {
|
||||||
|
queue = *new_queue;
|
||||||
|
}
|
||||||
|
u64 capacity = wapp_queue_capacity(&queue);
|
||||||
|
result = result && capacity == new_capacity;
|
||||||
|
|
||||||
|
for (u64 i = 0; i < 2; ++i) {
|
||||||
|
wapp_queue_pop(i32, &queue);
|
||||||
|
}
|
||||||
|
|
||||||
|
u64 remaining = wapp_queue_capacity(&queue) - queue.count;
|
||||||
|
for (u64 i = 0; i < remaining; ++i) {
|
||||||
|
item = remaining + i;
|
||||||
|
wapp_queue_push(i32, &queue, &item);
|
||||||
|
}
|
||||||
|
|
||||||
|
++item;
|
||||||
|
new_queue = wapp_queue_push_alloc(i32, &arena, &queue, &item);
|
||||||
|
if (new_queue && new_queue != &queue) {
|
||||||
|
queue = *new_queue;
|
||||||
|
}
|
||||||
|
|
||||||
|
result = result && wapp_queue_capacity(&queue) == new_capacity * 2;
|
||||||
|
|
||||||
|
i32 *arr = (i32 *)queue.items;
|
||||||
|
for (u64 i = 0; i < queue.count; ++i) {
|
||||||
|
// NOTE (Abdelrahman): First queue value is currently 2
|
||||||
|
result = result && arr[i] == (i32)(2 + i);
|
||||||
|
}
|
||||||
|
|
||||||
|
wapp_mem_arena_allocator_destroy(&arena);
|
||||||
|
|
||||||
|
return wapp_tester_result(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
TestFuncResult test_queue_pop(void) {
|
||||||
|
I32Queue queue = wapp_queue(i32, CAPACITY);
|
||||||
|
for (u64 i = 0; i < CAPACITY; ++i) {
|
||||||
|
i32 item = (i32)i;
|
||||||
|
wapp_queue_push(i32, &queue, &item);
|
||||||
|
}
|
||||||
|
|
||||||
|
b8 result = true;
|
||||||
|
u64 half_count = queue.count / 2;
|
||||||
|
for (u64 i = 0; i < half_count; ++i) {
|
||||||
|
i32 *value = wapp_queue_pop(i32, &queue);
|
||||||
|
result = result && value != NULL && *value == (i32)i;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (u64 i = 0; i < half_count; ++i) {
|
||||||
|
i32 item = (i32)i + CAPACITY;
|
||||||
|
wapp_queue_push(i32, &queue, &item);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (u64 i = 0; i < CAPACITY; ++i) {
|
||||||
|
i32 *value = wapp_queue_pop(i32, &queue);
|
||||||
|
result = result && value != NULL && *value == (i32)half_count + (i32)i;
|
||||||
|
}
|
||||||
|
|
||||||
|
return wapp_tester_result(result);
|
||||||
|
}
|
||||||
96
tests/queue/test_queue.cc
Normal file
96
tests/queue/test_queue.cc
Normal file
@@ -0,0 +1,96 @@
|
|||||||
|
#include "wapp.h"
|
||||||
|
#include "test_queue.h"
|
||||||
|
|
||||||
|
#define CAPACITY 8
|
||||||
|
|
||||||
|
TestFuncResult test_queue_push(void) {
|
||||||
|
I32Queue queue = wapp_queue(i32, CAPACITY);
|
||||||
|
|
||||||
|
for (u64 i = 0; i < CAPACITY; ++i) {
|
||||||
|
i32 item = (i32)i;
|
||||||
|
wapp_queue_push(i32, &queue, &item);
|
||||||
|
}
|
||||||
|
|
||||||
|
b8 result = true;
|
||||||
|
for (u64 i = 0; i < CAPACITY; ++i) {
|
||||||
|
i32 *value = ((i32 *)(queue.items)) + i;
|
||||||
|
result = result && value != NULL && *value == (i32)i;
|
||||||
|
}
|
||||||
|
|
||||||
|
return wapp_tester_result(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
TestFuncResult test_queue_push_alloc(void) {
|
||||||
|
Allocator arena = wapp_mem_arena_allocator_init(MiB(64));
|
||||||
|
I32Queue queue = wapp_queue(i32, CAPACITY);
|
||||||
|
|
||||||
|
for (u64 i = 0; i < CAPACITY; ++i) {
|
||||||
|
i32 item = (i32)i;
|
||||||
|
wapp_queue_push(i32, &queue, &item);
|
||||||
|
}
|
||||||
|
|
||||||
|
b8 result = true;
|
||||||
|
i32 item = 8;
|
||||||
|
u64 new_capacity = CAPACITY * 2;
|
||||||
|
I32Queue *new_queue = wapp_queue_push_alloc(i32, &arena, &queue, &item);
|
||||||
|
if (new_queue && new_queue != &queue) {
|
||||||
|
queue = *new_queue;
|
||||||
|
}
|
||||||
|
u64 capacity = wapp_queue_capacity(&queue);
|
||||||
|
result = result && capacity == new_capacity;
|
||||||
|
|
||||||
|
for (u64 i = 0; i < 2; ++i) {
|
||||||
|
wapp_queue_pop(i32, &queue);
|
||||||
|
}
|
||||||
|
|
||||||
|
u64 remaining = wapp_queue_capacity(&queue) - queue.count;
|
||||||
|
for (u64 i = 0; i < remaining; ++i) {
|
||||||
|
item = remaining + i;
|
||||||
|
wapp_queue_push(i32, &queue, &item);
|
||||||
|
}
|
||||||
|
|
||||||
|
++item;
|
||||||
|
new_queue = wapp_queue_push_alloc(i32, &arena, &queue, &item);
|
||||||
|
if (new_queue && new_queue != &queue) {
|
||||||
|
queue = *new_queue;
|
||||||
|
}
|
||||||
|
|
||||||
|
result = result && wapp_queue_capacity(&queue) == new_capacity * 2;
|
||||||
|
|
||||||
|
i32 *arr = (i32 *)queue.items;
|
||||||
|
for (u64 i = 0; i < queue.count; ++i) {
|
||||||
|
// NOTE (Abdelrahman): First queue value is currently 2
|
||||||
|
result = result && arr[i] == (i32)(2 + i);
|
||||||
|
}
|
||||||
|
|
||||||
|
wapp_mem_arena_allocator_destroy(&arena);
|
||||||
|
|
||||||
|
return wapp_tester_result(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
TestFuncResult test_queue_pop(void) {
|
||||||
|
I32Queue queue = wapp_queue(i32, CAPACITY);
|
||||||
|
for (u64 i = 0; i < CAPACITY; ++i) {
|
||||||
|
i32 item = (i32)i;
|
||||||
|
wapp_queue_push(i32, &queue, &item);
|
||||||
|
}
|
||||||
|
|
||||||
|
b8 result = true;
|
||||||
|
u64 half_count = queue.count / 2;
|
||||||
|
for (u64 i = 0; i < half_count; ++i) {
|
||||||
|
i32 *value = wapp_queue_pop(i32, &queue);
|
||||||
|
result = result && value != NULL && *value == (i32)i;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (u64 i = 0; i < half_count; ++i) {
|
||||||
|
i32 item = (i32)i + CAPACITY;
|
||||||
|
wapp_queue_push(i32, &queue, &item);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (u64 i = 0; i < CAPACITY; ++i) {
|
||||||
|
i32 *value = wapp_queue_pop(i32, &queue);
|
||||||
|
result = result && value != NULL && *value == (i32)half_count + (i32)i;
|
||||||
|
}
|
||||||
|
|
||||||
|
return wapp_tester_result(result);
|
||||||
|
}
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user