Compare commits
13
Commits
8a52f22b8a
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
12b560fb37 | ||
|
|
0e7c2cafaa | ||
|
|
1654b86640 | ||
|
|
4d96592a1e | ||
|
|
813390b6ac | ||
|
|
b89579a5e7 | ||
|
|
fbd97f7112 | ||
|
|
6b7a560156 | ||
|
|
b39911f57e | ||
|
|
4bc6efd89e | ||
|
|
b218af2952 | ||
|
|
74873807dd | ||
|
|
924c45e223 |
@@ -17,3 +17,4 @@ AllowShortIfStatementsOnASingleLine: AllIfsAndElse
|
||||
AllowShortLoopsOnASingleLine: true
|
||||
IndentAccessModifiers: false # Indent access specifiers by one level
|
||||
AccessModifierOffset: -4 # Optional: adjust offset relative to the class indentation level
|
||||
IndentGotoLabels: InnerIndent
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
Checks: >
|
||||
-*,
|
||||
clang-analyzer-*,
|
||||
bugprone-*,
|
||||
-bugprone-easily-swappable-parameters,
|
||||
-bugprone-reserved-identifier,
|
||||
performance-*,
|
||||
security-*
|
||||
@@ -1,2 +1,8 @@
|
||||
build/
|
||||
.cache/
|
||||
tests/cache/
|
||||
tests/bin/
|
||||
coverage.html
|
||||
|
||||
tests
|
||||
Makefile
|
||||
|
||||
+34
-6
@@ -3,12 +3,40 @@ project(libvec LANGUAGES C)
|
||||
set(CMAKE_C_STANDARD 23)
|
||||
set(CMAKE_C_STANDARD_REQUIRED ON)
|
||||
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
|
||||
include_directories(include)
|
||||
|
||||
set(SOURCES
|
||||
src/main.c
|
||||
src/char.c
|
||||
src/utils.c
|
||||
add_library(libvec STATIC
|
||||
src/char.c
|
||||
src/int.c
|
||||
src/utils.c
|
||||
src/float.c
|
||||
src/string.c
|
||||
# Add your other types here as you implement them:
|
||||
)
|
||||
|
||||
add_executable(libvec ${SOURCES})
|
||||
include(FetchContent)
|
||||
FetchContent_Declare(libstr
|
||||
GIT_REPOSITORY https://git.moomancer.xyz/DarthMooMancer/libstr.git
|
||||
GIT_TAG main
|
||||
GIT_SHALLOW TRUE
|
||||
)
|
||||
FetchContent_MakeAvailable(libstr)
|
||||
|
||||
target_link_libraries(libvec PRIVATE libstr)
|
||||
|
||||
target_include_directories(libvec
|
||||
# PRIVATE: Internal headers under src/lib are only visible
|
||||
# to files being compiled into libvec (char.c, utils.c, libvec.c).
|
||||
# PRIVATE
|
||||
|
||||
# PUBLIC: Consumers (and test_runner) are granted access ONLY to include/
|
||||
PUBLIC
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/include
|
||||
# ${CMAKE_CURRENT_SOURCE_DIR}/src/lib # Turn back to private when ready
|
||||
)
|
||||
|
||||
add_executable(libvec_bin src/main.c)
|
||||
set_target_properties(libvec_bin PROPERTIES OUTPUT_NAME "libvec")
|
||||
|
||||
# Linking libvec privately gives test_runner access to include/libvec.h,
|
||||
# but strictly hides src/lib/char/char.h and src/lib/utils/utils.h.
|
||||
target_link_libraries(libvec_bin PRIVATE libvec)
|
||||
|
||||
@@ -0,0 +1,143 @@
|
||||
# ==============================================================================
|
||||
# Toolchain & Executables
|
||||
# ==============================================================================
|
||||
LLVM_DIR ?= /opt/homebrew/opt/llvm/bin
|
||||
CC := $(LLVM_DIR)/clang
|
||||
LLVM_PROFDATA := $(LLVM_DIR)/llvm-profdata
|
||||
LLVM_COV := $(LLVM_DIR)/llvm-cov
|
||||
CPPCHECK := cppcheck
|
||||
|
||||
# libstr is populated by CMake's FetchContent (run `cmake -B build` once)
|
||||
LIBSTR_DIR := build/_deps/libstr-src
|
||||
|
||||
# ==============================================================================
|
||||
# Flags & Directories
|
||||
# ==============================================================================
|
||||
CFLAGS := -std=c23 -Wall -Wextra -Wpedantic -Wshadow \
|
||||
-Wconversion -Wsign-conversion \
|
||||
-g -O1 -fno-omit-frame-pointer
|
||||
SAN_FLAGS := -fsanitize=address,undefined
|
||||
INCLUDES := -Iinclude -Isrc/lib -Isrc/lib/int -Isrc/lib/utils
|
||||
|
||||
ASAN_ENV := ASAN_OPTIONS="allocator_may_return_null=1:detect_stack_use_after_return=1" \
|
||||
UBSAN_OPTIONS="halt_on_error=1:print_stacktrace=1"
|
||||
|
||||
CPPCHECK_FLAGS := --enable=all \
|
||||
--inconclusive \
|
||||
--error-exitcode=1 \
|
||||
--check-level=exhaustive \
|
||||
--suppress=missingIncludeSystem \
|
||||
--suppress=unmatchedSuppression \
|
||||
--suppress=unusedFunction \
|
||||
--suppress=staticFunction \
|
||||
--inline-suppr \
|
||||
$(INCLUDES)
|
||||
|
||||
# Sources & Build Directories
|
||||
SRCS := src/lib/int/int.c src/lib/utils/utils.c
|
||||
TEST_SRC := tests/test_learn.c
|
||||
FUZZ_SRC := tests/fuzz_char.c
|
||||
|
||||
STRING_SRCS := src/string.c src/utils.c $(LIBSTR_DIR)/src/string.c
|
||||
TEST_STRING_SRC := tests/test_string.c
|
||||
|
||||
BIN_DIR := tests/bin
|
||||
CACHE_DIR := tests/cache
|
||||
|
||||
TEST_BIN := $(BIN_DIR)/test_learn_runner
|
||||
TSAN_BIN := $(BIN_DIR)/test_tsan_runner
|
||||
FUZZ_BIN := $(BIN_DIR)/fuzz_char_runner
|
||||
COV_BIN := $(BIN_DIR)/test_cov_runner
|
||||
TEST_STRING_BIN := $(BIN_DIR)/test_string_runner
|
||||
|
||||
# ==============================================================================
|
||||
# Targets & Workflow Rules
|
||||
# ==============================================================================
|
||||
.PHONY: all test test-string sanitize check check-sources analyze cppcheck fuzz cov-build cov clean
|
||||
|
||||
all: test
|
||||
|
||||
$(BIN_DIR) $(CACHE_DIR):
|
||||
@mkdir -p $@
|
||||
|
||||
# --- Compilation Targets ---
|
||||
|
||||
$(TEST_BIN): $(SRCS) $(TEST_SRC) | $(BIN_DIR)
|
||||
$(CC) $(CFLAGS) $(SAN_FLAGS) $(INCLUDES) $^ -o $@
|
||||
|
||||
$(TEST_STRING_BIN): $(STRING_SRCS) $(TEST_STRING_SRC) | $(BIN_DIR)
|
||||
$(CC) $(CFLAGS) $(SAN_FLAGS) $(INCLUDES) -I$(LIBSTR_DIR)/include $^ -o $@
|
||||
|
||||
$(TSAN_BIN): $(SRCS) $(TEST_SRC) | $(BIN_DIR)
|
||||
$(CC) $(CFLAGS) -fsanitize=thread $(INCLUDES) $^ -o $@
|
||||
|
||||
$(FUZZ_BIN): $(SRCS) $(FUZZ_SRC) | $(BIN_DIR)
|
||||
$(CC) $(CFLAGS) -fsanitize=fuzzer,address,undefined $(INCLUDES) $^ -o $@
|
||||
|
||||
# --- Testing & Sanitizer Suites ---
|
||||
|
||||
test: $(TEST_BIN)
|
||||
@echo "=== Running Unit Tests (ASan + UBSan) ==="
|
||||
@$(ASAN_ENV) ./$(TEST_BIN)
|
||||
|
||||
test-string: $(TEST_STRING_BIN)
|
||||
@echo "=== Running vec_string Unit Tests (ASan + UBSan) ==="
|
||||
@$(ASAN_ENV) ./$(TEST_STRING_BIN)
|
||||
|
||||
sanitize: $(TEST_BIN) $(TSAN_BIN)
|
||||
@echo "\n=== [1/2] Running Address + UndefinedBehavior Sanitizers ==="
|
||||
@$(ASAN_ENV) ./$(TEST_BIN)
|
||||
@echo "\n=== [2/2] Running ThreadSanitizer ==="
|
||||
@./$(TSAN_BIN)
|
||||
@echo "\n>>> Sanitizers passed with zero defects."
|
||||
|
||||
# Unified master check: runtime sanitizers, static analyzer, and cppcheck
|
||||
check: sanitize analyze cppcheck
|
||||
@echo "\n=============================================="
|
||||
@echo " ALL TESTS, SANITIZERS & STATIC CHECKS PASSED "
|
||||
@echo "=============================================="
|
||||
|
||||
fuzz: $(FUZZ_BIN)
|
||||
@echo "=== Starting Fuzzer (Press Ctrl+C to stop) ==="
|
||||
@$(ASAN_ENV) ./$(FUZZ_BIN) -max_total_time=60
|
||||
|
||||
# --- Coverage Profiling ---
|
||||
|
||||
cov-build: $(SRCS) $(TEST_SRC) | $(BIN_DIR)
|
||||
$(CC) $(CFLAGS) $(SAN_FLAGS) -fprofile-instr-generate -fcoverage-mapping $(INCLUDES) $^ -o $(COV_BIN)
|
||||
|
||||
cov: cov-build | $(CACHE_DIR)
|
||||
@echo "=== Recording Coverage Profile Data ==="
|
||||
@$(ASAN_ENV) LLVM_PROFILE_FILE="$(CACHE_DIR)/test_char.profdata_raw" ./$(COV_BIN)
|
||||
@$(LLVM_PROFDATA) merge -sparse $(CACHE_DIR)/test_char.profdata_raw -o $(CACHE_DIR)/test_char.profdata
|
||||
@echo "\n=== Line & Branch Coverage Report: src/lib/char/char.c ==="
|
||||
@$(LLVM_COV) report $(COV_BIN) -instr-profile=$(CACHE_DIR)/test_char.profdata src/lib/char/char.c
|
||||
@$(LLVM_COV) show $(COV_BIN) -instr-profile=$(CACHE_DIR)/test_char.profdata src/lib/char/char.c --format=html > coverage.html
|
||||
@echo "\nDetailed HTML report written to coverage.html."
|
||||
|
||||
# --- Static Analysis & Object Checking ---
|
||||
|
||||
check-sources: | $(BIN_DIR)
|
||||
@echo "=== Compiling Sources to Object Files (ASan + UBSan) ==="
|
||||
$(CC) $(CFLAGS) $(SAN_FLAGS) $(INCLUDES) -c src/lib/char/char.c -o $(BIN_DIR)/char.o
|
||||
$(CC) $(CFLAGS) $(SAN_FLAGS) $(INCLUDES) -c src/lib/utils/utils.c -o $(BIN_DIR)/utils.o
|
||||
@echo "Library sources compiled cleanly."
|
||||
|
||||
analyze:
|
||||
@echo "=== Running Clang Static Analyzer ==="
|
||||
@$(CC) $(CFLAGS) $(INCLUDES) \
|
||||
--analyze \
|
||||
-Xanalyzer -analyzer-output=text \
|
||||
-Xanalyzer -analyzer-checker=core,unix,deadcode,security \
|
||||
$(SRCS)
|
||||
@echo "Clang Static Analyzer complete: zero defects."
|
||||
|
||||
cppcheck:
|
||||
@echo "=== Running Cppcheck Static Analysis ==="
|
||||
@$(CPPCHECK) $(CPPCHECK_FLAGS) include/ src/
|
||||
@echo "Cppcheck passed with zero defects."
|
||||
|
||||
# --- Housekeeping ---
|
||||
|
||||
clean:
|
||||
rm -rf $(BIN_DIR)/* $(CACHE_DIR)/* coverage.html
|
||||
-112
@@ -1,112 +0,0 @@
|
||||
/*
|
||||
* Andrew Haynes
|
||||
* dmm.dev@icloud.com
|
||||
* No LICENSE
|
||||
* Vector Library For C
|
||||
*/
|
||||
|
||||
#ifndef CHAR_H
|
||||
#define CHAR_H
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <utils.h>
|
||||
|
||||
typedef struct
|
||||
{
|
||||
char* arr;
|
||||
size_t size;
|
||||
size_t capacity;
|
||||
size_t max_size;
|
||||
} Vec8_t;
|
||||
|
||||
int
|
||||
is_valid(const Vec8_t* vec);
|
||||
|
||||
Vec8_t
|
||||
create(const char* buf, const size_t len);
|
||||
|
||||
Vec8_t
|
||||
push_back(Vec8_t* vec, const char val);
|
||||
|
||||
Vec8_t
|
||||
pop_back(Vec8_t* ptr);
|
||||
|
||||
Vec8_t
|
||||
reserve(const Vec8_t* ptr, const size_t max_size);
|
||||
|
||||
Vec8_t
|
||||
shrink_to_fit(Vec8_t* ptr);
|
||||
|
||||
int
|
||||
swap(Vec8_t* ptr, Vec8_t* ptr_other);
|
||||
|
||||
char*
|
||||
data(const Vec8_t* ptr);
|
||||
|
||||
size_t
|
||||
capacity(const Vec8_t* ptr);
|
||||
|
||||
size_t
|
||||
max_size(const Vec8_t* ptr);
|
||||
|
||||
void delete (const Vec8_t* vec);
|
||||
|
||||
Vec8_t
|
||||
clear(const Vec8_t* vec);
|
||||
|
||||
char
|
||||
at(const Vec8_t* vec, const size_t idx);
|
||||
|
||||
void
|
||||
print_vec(const Vec8_t* vec);
|
||||
|
||||
int
|
||||
begin(const Vec8_t* vec);
|
||||
|
||||
int
|
||||
end(const Vec8_t* vec);
|
||||
|
||||
char
|
||||
front(const Vec8_t* vec);
|
||||
|
||||
char
|
||||
back(const Vec8_t* vec);
|
||||
|
||||
int
|
||||
empty(const Vec8_t* vec);
|
||||
|
||||
__attribute__((overloadable)) Vec8_t
|
||||
erase(const Vec8_t* vec, const size_t iter);
|
||||
|
||||
__attribute__((overloadable)) Vec8_t
|
||||
erase(const Vec8_t* vec, const size_t iter_start, const size_t iter_end);
|
||||
|
||||
__attribute__((overloadable)) Vec8_t
|
||||
resize(const Vec8_t* vec, const size_t size);
|
||||
|
||||
__attribute__((overloadable)) Vec8_t
|
||||
resize(Vec8_t* vec, const size_t size, const char val);
|
||||
|
||||
__attribute__((overloadable)) Vec8_t
|
||||
assign(const Vec8_t* vec, const Vec8_t* iterator, const size_t iter_start,
|
||||
const size_t iter_end);
|
||||
|
||||
__attribute__((overloadable)) Vec8_t
|
||||
assign(const Vec8_t* vec, const size_t amount, const char val);
|
||||
|
||||
__attribute__((overloadable)) Vec8_t
|
||||
insert(const Vec8_t* vec, const size_t iter, const char val);
|
||||
|
||||
__attribute__((overloadable)) Vec8_t
|
||||
insert(const Vec8_t* vec, const size_t iter, const size_t amount,
|
||||
const char val);
|
||||
|
||||
__attribute__((overloadable)) Vec8_t
|
||||
insert(const Vec8_t* dst_vec, const Vec8_t* src_vec, const size_t iter,
|
||||
const size_t iter_start, const size_t iter_end);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,113 @@
|
||||
#ifndef LIBVEC_CHAR_H
|
||||
#define LIBVEC_CHAR_H
|
||||
|
||||
#include <libvec/utils.h>
|
||||
|
||||
// Will add DOCS later
|
||||
|
||||
typedef struct
|
||||
{
|
||||
char* array;
|
||||
size_t size;
|
||||
size_t capacity;
|
||||
size_t max_size;
|
||||
} vec_char;
|
||||
|
||||
__attribute__((overloadable)) size_t
|
||||
__null_check(const vec_char* ptr, err_t* status);
|
||||
|
||||
__attribute__((overloadable)) size_t
|
||||
__null_check(const char* ptr, err_t* status);
|
||||
|
||||
size_t
|
||||
__origin_override(err_t* status, char* str);
|
||||
|
||||
void
|
||||
vec_char_print_vec(const vec_char* ptr, err_t* err);
|
||||
|
||||
vec_char
|
||||
vec_char_cpy(const char* src, const size_t src_size, err_t* err);
|
||||
|
||||
void
|
||||
vec_char_push_back(vec_char* ptr, const char val, err_t* err);
|
||||
|
||||
void
|
||||
vec_char_pop_back(vec_char* ptr, err_t* err);
|
||||
|
||||
void
|
||||
vec_char_reserve(vec_char* ptr, const size_t capacity, err_t* err);
|
||||
|
||||
void
|
||||
vec_char_shrink_to_fit(vec_char* ptr, err_t* err);
|
||||
|
||||
void
|
||||
vec_char_swap(vec_char* ptr_a, vec_char* ptr_b, err_t* err);
|
||||
|
||||
const char*
|
||||
vec_char_data(const vec_char* ptr, err_t* err);
|
||||
|
||||
size_t
|
||||
vec_char_size(const vec_char* ptr, err_t* err);
|
||||
|
||||
size_t
|
||||
vec_char_capacity(const vec_char* ptr, err_t* err);
|
||||
|
||||
size_t
|
||||
vec_char_max_size(const vec_char* ptr, err_t* err);
|
||||
|
||||
void
|
||||
vec_char_delete(vec_char* ptr, err_t* err);
|
||||
|
||||
void
|
||||
vec_char_clear(vec_char* ptr, err_t* err);
|
||||
|
||||
char*
|
||||
vec_char_at(const vec_char* ptr, const size_t idx, err_t* err);
|
||||
|
||||
size_t
|
||||
vec_char_begin(const vec_char* ptr, err_t* err);
|
||||
|
||||
size_t
|
||||
vec_char_end(const vec_char* ptr, err_t* err);
|
||||
|
||||
char
|
||||
vec_char_front(const vec_char* ptr, err_t* err);
|
||||
|
||||
char
|
||||
vec_char_back(const vec_char* ptr, err_t* err);
|
||||
|
||||
size_t
|
||||
vec_char_empty(const vec_char* ptr, err_t* err);
|
||||
|
||||
__attribute__((overloadable)) void
|
||||
vec_char_erase(vec_char* ptr, const size_t iter, err_t* err);
|
||||
|
||||
__attribute__((overloadable)) void
|
||||
vec_char_erase(vec_char* ptr, const size_t iter_start, const size_t iter_end,
|
||||
err_t* err);
|
||||
|
||||
__attribute__((overloadable)) void
|
||||
vec_char_resize(vec_char* ptr, const size_t size, err_t* err);
|
||||
|
||||
__attribute__((overloadable)) void
|
||||
vec_char_resize(vec_char* ptr, const size_t size, const char val, err_t* err);
|
||||
|
||||
__attribute__((overloadable)) void
|
||||
vec_char_assign(vec_char* ptr, const vec_char* iterator,
|
||||
const size_t iter_start, const size_t iter_end, err_t* err);
|
||||
|
||||
__attribute__((overloadable)) void
|
||||
vec_char_assign(vec_char* ptr, const size_t amount, const char val, err_t* err);
|
||||
|
||||
__attribute__((overloadable)) void
|
||||
vec_char_insert(vec_char* ptr, const size_t iter, const char val, err_t* err);
|
||||
|
||||
__attribute__((overloadable)) void
|
||||
vec_char_insert(vec_char* ptr, const size_t iter, const size_t amount,
|
||||
const char val, err_t* err);
|
||||
|
||||
__attribute__((overloadable)) void
|
||||
vec_char_insert(vec_char* ptr, const vec_char* iterator, const size_t iter,
|
||||
const size_t iter_start, const size_t iter_end, err_t* err);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,107 @@
|
||||
#ifndef LIBVEC_FLOAT_H
|
||||
#define LIBVEC_FLOAT_H
|
||||
|
||||
#include <libvec/utils.h>
|
||||
|
||||
// Will add DOCS later
|
||||
|
||||
typedef struct
|
||||
{
|
||||
float* array;
|
||||
size_t size;
|
||||
size_t capacity;
|
||||
size_t max_size;
|
||||
} vec_float;
|
||||
|
||||
void
|
||||
vec_float_print_vec(const vec_float* ptr, err_t* err);
|
||||
|
||||
vec_float
|
||||
vec_float_cpy(const float* src, const size_t src_size, err_t* err);
|
||||
|
||||
void
|
||||
vec_float_push_back(vec_float* ptr, const float val, err_t* err);
|
||||
|
||||
void
|
||||
vec_float_pop_back(vec_float* ptr, err_t* err);
|
||||
|
||||
void
|
||||
vec_float_reserve(vec_float* ptr, const size_t capacity, err_t* err);
|
||||
|
||||
void
|
||||
vec_float_shrink_to_fit(vec_float* ptr, err_t* err);
|
||||
|
||||
void
|
||||
vec_float_swap(vec_float* ptr_a, vec_float* ptr_b, err_t* err);
|
||||
|
||||
const float*
|
||||
vec_float_data(const vec_float* ptr, err_t* err);
|
||||
|
||||
size_t
|
||||
vec_float_size(const vec_float* ptr, err_t* err);
|
||||
|
||||
size_t
|
||||
vec_float_capacity(const vec_float* ptr, err_t* err);
|
||||
|
||||
size_t
|
||||
vec_float_max_size(const vec_float* ptr, err_t* err);
|
||||
|
||||
void
|
||||
vec_float_delete(vec_float* ptr, err_t* err);
|
||||
|
||||
void
|
||||
vec_float_clear(vec_float* ptr, err_t* err);
|
||||
|
||||
float*
|
||||
vec_float_at(const vec_float* ptr, const size_t idx, err_t* err);
|
||||
|
||||
size_t
|
||||
vec_float_begin(const vec_float* ptr, err_t* err);
|
||||
|
||||
size_t
|
||||
vec_float_end(const vec_float* ptr, err_t* err);
|
||||
|
||||
float
|
||||
vec_float_front(const vec_float* ptr, err_t* err);
|
||||
|
||||
float
|
||||
vec_float_back(const vec_float* ptr, err_t* err);
|
||||
|
||||
size_t
|
||||
vec_float_empty(const vec_float* ptr, err_t* err);
|
||||
|
||||
__attribute__((overloadable)) void
|
||||
vec_float_erase(vec_float* ptr, const size_t iter, err_t* err);
|
||||
|
||||
__attribute__((overloadable)) void
|
||||
vec_float_erase(vec_float* ptr, const size_t iter_start, const size_t iter_end,
|
||||
err_t* err);
|
||||
|
||||
__attribute__((overloadable)) void
|
||||
vec_float_resize(vec_float* ptr, const size_t size, err_t* err);
|
||||
|
||||
__attribute__((overloadable)) void
|
||||
vec_float_resize(vec_float* ptr, const size_t size, const float val,
|
||||
err_t* err);
|
||||
|
||||
__attribute__((overloadable)) void
|
||||
vec_float_assign(vec_float* ptr, const vec_float* iterator,
|
||||
const size_t iter_start, const size_t iter_end, err_t* err);
|
||||
|
||||
__attribute__((overloadable)) void
|
||||
vec_float_assign(vec_float* ptr, const size_t amount, const float val,
|
||||
err_t* err);
|
||||
|
||||
__attribute__((overloadable)) void
|
||||
vec_float_insert(vec_float* ptr, const size_t iter, const float val,
|
||||
err_t* err);
|
||||
|
||||
__attribute__((overloadable)) void
|
||||
vec_float_insert(vec_float* ptr, const size_t iter, const size_t amount,
|
||||
const float val, err_t* err);
|
||||
|
||||
__attribute__((overloadable)) void
|
||||
vec_float_insert(vec_float* ptr, const vec_float* iterator, const size_t iter,
|
||||
const size_t iter_start, const size_t iter_end, err_t* err);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,113 @@
|
||||
#ifndef LIBVEC_INT_H
|
||||
#define LIBVEC_INT_H
|
||||
|
||||
#include <libvec/utils.h>
|
||||
|
||||
// Will add DOCS later
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int* array;
|
||||
size_t size;
|
||||
size_t capacity;
|
||||
size_t max_size;
|
||||
} vec_int;
|
||||
|
||||
__attribute__((overloadable)) size_t
|
||||
__null_check(const vec_int* ptr, err_t* status);
|
||||
|
||||
__attribute__((overloadable)) size_t
|
||||
__null_check(const int* ptr, err_t* status);
|
||||
|
||||
size_t
|
||||
__origin_override(err_t* status, char* str);
|
||||
|
||||
void
|
||||
vec_int_print_vec(const vec_int* ptr, err_t* err);
|
||||
|
||||
vec_int
|
||||
vec_int_cpy(const int* src, const size_t src_size, err_t* err);
|
||||
|
||||
void
|
||||
vec_int_push_back(vec_int* ptr, const int val, err_t* err);
|
||||
|
||||
void
|
||||
vec_int_pop_back(vec_int* ptr, err_t* err);
|
||||
|
||||
void
|
||||
vec_int_reserve(vec_int* ptr, const size_t capacity, err_t* err);
|
||||
|
||||
void
|
||||
vec_int_shrink_to_fit(vec_int* ptr, err_t* err);
|
||||
|
||||
void
|
||||
vec_int_swap(vec_int* ptr_a, vec_int* ptr_b, err_t* err);
|
||||
|
||||
const int*
|
||||
vec_int_data(const vec_int* ptr, err_t* err);
|
||||
|
||||
size_t
|
||||
vec_int_size(const vec_int* ptr, err_t* err);
|
||||
|
||||
size_t
|
||||
vec_int_capacity(const vec_int* ptr, err_t* err);
|
||||
|
||||
size_t
|
||||
vec_int_max_size(const vec_int* ptr, err_t* err);
|
||||
|
||||
void
|
||||
vec_int_delete(vec_int* ptr, err_t* err);
|
||||
|
||||
void
|
||||
vec_int_clear(vec_int* ptr, err_t* err);
|
||||
|
||||
int*
|
||||
vec_int_at(const vec_int* ptr, const size_t idx, err_t* err);
|
||||
|
||||
size_t
|
||||
vec_int_begin(const vec_int* ptr, err_t* err);
|
||||
|
||||
size_t
|
||||
vec_int_end(const vec_int* ptr, err_t* err);
|
||||
|
||||
int
|
||||
vec_int_front(const vec_int* ptr, err_t* err);
|
||||
|
||||
int
|
||||
vec_int_back(const vec_int* ptr, err_t* err);
|
||||
|
||||
size_t
|
||||
vec_int_empty(const vec_int* ptr, err_t* err);
|
||||
|
||||
__attribute__((overloadable)) void
|
||||
vec_int_erase(vec_int* ptr, const size_t iter, err_t* err);
|
||||
|
||||
__attribute__((overloadable)) void
|
||||
vec_int_erase(vec_int* ptr, const size_t iter_start, const size_t iter_end,
|
||||
err_t* err);
|
||||
|
||||
__attribute__((overloadable)) void
|
||||
vec_int_resize(vec_int* ptr, const size_t size, err_t* err);
|
||||
|
||||
__attribute__((overloadable)) void
|
||||
vec_int_resize(vec_int* ptr, const size_t size, const int val, err_t* err);
|
||||
|
||||
__attribute__((overloadable)) void
|
||||
vec_int_assign(vec_int* ptr, const vec_int* iterator, const size_t iter_start,
|
||||
const size_t iter_end, err_t* err);
|
||||
|
||||
__attribute__((overloadable)) void
|
||||
vec_int_assign(vec_int* ptr, const size_t amount, const int val, err_t* err);
|
||||
|
||||
__attribute__((overloadable)) void
|
||||
vec_int_insert(vec_int* ptr, const size_t iter, const int val, err_t* err);
|
||||
|
||||
__attribute__((overloadable)) void
|
||||
vec_int_insert(vec_int* ptr, const size_t iter, const size_t amount,
|
||||
const int val, err_t* err);
|
||||
|
||||
__attribute__((overloadable)) void
|
||||
vec_int_insert(vec_int* ptr, const vec_int* iterator, const size_t iter,
|
||||
const size_t iter_start, const size_t iter_end, err_t* err);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,115 @@
|
||||
#ifndef LIBVEC_STRING_H
|
||||
#define LIBVEC_STRING_H
|
||||
|
||||
#include <libstr/string.h>
|
||||
#include <libvec/utils.h>
|
||||
|
||||
// Will add DOCS later
|
||||
|
||||
typedef struct
|
||||
{
|
||||
String* array;
|
||||
size_t size;
|
||||
size_t capacity;
|
||||
size_t max_size;
|
||||
} vec_string;
|
||||
|
||||
__attribute__((overloadable)) size_t
|
||||
__null_check(const vec_string* ptr, err_t* status);
|
||||
|
||||
__attribute__((overloadable)) size_t
|
||||
__null_check(const char* ptr, err_t* status);
|
||||
|
||||
void
|
||||
vec_string_print_vec(const vec_string* ptr, err_t* err);
|
||||
|
||||
vec_string
|
||||
vec_string_cpy(const String* src, const size_t src_size, err_t* err);
|
||||
|
||||
void
|
||||
vec_string_push_back(vec_string* ptr, const String val, err_t* err);
|
||||
|
||||
void
|
||||
vec_string_pop_back(vec_string* ptr, err_t* err);
|
||||
|
||||
void
|
||||
vec_string_reserve(vec_string* ptr, const size_t capacity, err_t* err);
|
||||
|
||||
void
|
||||
vec_string_shrink_to_fit(vec_string* ptr, err_t* err);
|
||||
|
||||
void
|
||||
vec_string_swap(vec_string* ptr_a, vec_string* ptr_b, err_t* err);
|
||||
|
||||
const String*
|
||||
vec_string_data(const vec_string* ptr, err_t* err);
|
||||
|
||||
size_t
|
||||
vec_string_size(const vec_string* ptr, err_t* err);
|
||||
|
||||
size_t
|
||||
vec_string_capacity(const vec_string* ptr, err_t* err);
|
||||
|
||||
size_t
|
||||
vec_string_max_size(const vec_string* ptr, err_t* err);
|
||||
|
||||
void
|
||||
vec_string_delete(vec_string* ptr, err_t* err);
|
||||
|
||||
void
|
||||
vec_string_clear(vec_string* ptr, err_t* err);
|
||||
|
||||
String*
|
||||
vec_string_at(const vec_string* ptr, const size_t idx, err_t* err);
|
||||
|
||||
size_t
|
||||
vec_string_begin(const vec_string* ptr, err_t* err);
|
||||
|
||||
size_t
|
||||
vec_string_end(const vec_string* ptr, err_t* err);
|
||||
|
||||
String
|
||||
vec_string_front(const vec_string* ptr, err_t* err);
|
||||
|
||||
String
|
||||
vec_string_back(const vec_string* ptr, err_t* err);
|
||||
|
||||
size_t
|
||||
vec_string_empty(const vec_string* ptr, err_t* err);
|
||||
|
||||
__attribute__((overloadable)) void
|
||||
vec_string_erase(vec_string* ptr, const size_t iter, err_t* err);
|
||||
|
||||
__attribute__((overloadable)) void
|
||||
vec_string_erase(vec_string* ptr, const size_t iter_start,
|
||||
const size_t iter_end, err_t* err);
|
||||
|
||||
__attribute__((overloadable)) void
|
||||
vec_string_resize(vec_string* ptr, const size_t size, err_t* err);
|
||||
|
||||
__attribute__((overloadable)) void
|
||||
vec_string_resize(vec_string* ptr, const size_t size, const String val,
|
||||
err_t* err);
|
||||
|
||||
__attribute__((overloadable)) void
|
||||
vec_string_assign(vec_string* ptr, const vec_string* iterator,
|
||||
const size_t iter_start, const size_t iter_end, err_t* err);
|
||||
|
||||
__attribute__((overloadable)) void
|
||||
vec_string_assign(vec_string* ptr, const size_t amount, const String val,
|
||||
err_t* err);
|
||||
|
||||
__attribute__((overloadable)) void
|
||||
vec_string_insert(vec_string* ptr, const size_t iter, const String val,
|
||||
err_t* err);
|
||||
|
||||
__attribute__((overloadable)) void
|
||||
vec_string_insert(vec_string* ptr, const size_t iter, const size_t amount,
|
||||
const String val, err_t* err);
|
||||
|
||||
__attribute__((overloadable)) void
|
||||
vec_string_insert(vec_string* ptr, const vec_string* iterator,
|
||||
const size_t iter, const size_t iter_start,
|
||||
const size_t iter_end, err_t* err);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,65 @@
|
||||
#ifndef UTILS_H
|
||||
#define UTILS_H
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
static const size_t VEC_MAX = SIZE_MAX / sizeof(int);
|
||||
|
||||
#define ERROR_LIST(X) \
|
||||
X(SUCCESS, 0, "No Errors Found") \
|
||||
X(ERR_ALLOC_FAIL, (1u << 0), "Alloc :- Failed to allocate") \
|
||||
X(ERR_VEC_NULL, (1u << 1), "Vector :- Given vector is null") \
|
||||
X(ERR_BUF_NULL, (1u << 2), "Buffer :- NULL") \
|
||||
X(ERR_SIZE_ZERO, (1u << 3), \
|
||||
"Size :- Size is or is less than 0 or invalid") \
|
||||
X(ERR_OUT_OF_BOUNDS, (1u << 4), "Bounds:- Value is out of bounds") \
|
||||
X(ERR_DOUBLE_BUF, (1u << 5), \
|
||||
"Buffer :- Both buffers are copies of each other") \
|
||||
X(ERR_SIZE_OVERFLOW, (1u << 6), \
|
||||
"Max :- Vector Max value is overloaded") \
|
||||
X(ERR_ORIGIN_UNALTERABLE, (1u << 7), \
|
||||
"Origin :- Origin is non-null and cannot be overridden") \
|
||||
X(ERR_STR_NULL, (1u << 8), "String :- String is null value") \
|
||||
X(ERR_ERR_T_NULL, (1u << 9), "ERR_T :- Passed error is null")
|
||||
|
||||
typedef enum
|
||||
{
|
||||
#define X(name, val, desc) name = (val),
|
||||
ERROR_LIST(X)
|
||||
#undef X
|
||||
} ERROR_CODES;
|
||||
|
||||
/* NOTE
|
||||
* Value is the return value for functions like _vec_char_capacity
|
||||
* Err is the unsigned bit range for all the errors tracked
|
||||
* origin is a string for where the bug started and IS CHANGED ONLY WHEN NULL
|
||||
* */
|
||||
|
||||
typedef struct
|
||||
{
|
||||
unsigned int flags;
|
||||
char* origin; // Where the main bug started
|
||||
} err_t;
|
||||
|
||||
#define ERR_T_INIT { .flags = 0, .origin = NULL }
|
||||
#define VEC_INIT \
|
||||
{ .array = NULL, .size = 0, .capacity = 0, .max_size = VEC_MAX }
|
||||
|
||||
void
|
||||
vec_print_errs(const err_t err);
|
||||
|
||||
void
|
||||
vec_print_bits(unsigned int num);
|
||||
|
||||
size_t
|
||||
__origin_override(err_t* status, char* str);
|
||||
|
||||
__attribute__((overloadable)) size_t
|
||||
__null_check(const float* ptr, err_t* status);
|
||||
|
||||
#define LOG(msg) printf("LOG: %s\n", msg) /**< Print log message*/
|
||||
#define DEBUG(msg) printf("DEBUG: %s\n", msg) /**< Print debug message*/
|
||||
#define find_len(arr) (sizeof(arr) / sizeof((arr)[0]))
|
||||
|
||||
#endif
|
||||
@@ -1,31 +0,0 @@
|
||||
#ifndef UTILS_H
|
||||
#define UTILS_H
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#define CAPACITY 1024
|
||||
#define SUCCESS 0
|
||||
|
||||
#define FAILURE 1
|
||||
#define ERR_ALLOC_FAIL 20
|
||||
#define ERR_BUF_NULL 21
|
||||
#define ERR_SIZE_ZERO 22
|
||||
#define ERR_VECTOR_NULL 23
|
||||
#define ERR_MAX_PASSED 24
|
||||
#define ERR_OUT_OF_BOUNDS 25
|
||||
#define ERR_NULL 26
|
||||
#define ERR_DOUBLE_BUF 27
|
||||
|
||||
extern const char* error_messages[];
|
||||
|
||||
#define LOG(msg) printf("LOG: %s\n", msg) /**< Print log message*/
|
||||
#define LOGERROR(error_code) \
|
||||
printf("ERROR: %s\n", \
|
||||
error_messages[error_code]) /**< Print log error message*/
|
||||
|
||||
#define find_len(arr) sizeof(arr) / sizeof(arr[0])
|
||||
|
||||
static const size_t VEC_MAX = SIZE_MAX / sizeof(int);
|
||||
|
||||
#endif
|
||||
Vendored
BIN
Binary file not shown.
+702
-416
File diff suppressed because it is too large
Load Diff
+891
@@ -0,0 +1,891 @@
|
||||
#include <libvec/float.h>
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
__attribute__((overloadable)) size_t
|
||||
__null_check(const vec_float* ptr, err_t* status)
|
||||
{
|
||||
if (status == nullptr)
|
||||
{
|
||||
return ERR_ERR_T_NULL;
|
||||
}
|
||||
if (ptr == nullptr)
|
||||
{
|
||||
status->flags |= ERR_VEC_NULL;
|
||||
return ERR_VEC_NULL;
|
||||
}
|
||||
if (ptr->array == nullptr)
|
||||
{
|
||||
status->flags |= ERR_BUF_NULL;
|
||||
}
|
||||
|
||||
return status->flags;
|
||||
}
|
||||
|
||||
void
|
||||
vec_float_print_vec(const vec_float* ptr, err_t* err)
|
||||
{
|
||||
if (__null_check(ptr, err) != 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
for (size_t i = 0; i < ptr->size; i++)
|
||||
{
|
||||
printf("%f ", ptr->array[i]);
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
vec_float
|
||||
vec_float_cpy(const float* src, const size_t src_size, err_t* err)
|
||||
{
|
||||
vec_float self = VEC_INIT;
|
||||
err_t status = ERR_T_INIT;
|
||||
|
||||
size_t null = __null_check(src, err);
|
||||
if (null != 0)
|
||||
{
|
||||
if (null & ERR_ERR_T_NULL)
|
||||
{
|
||||
return self;
|
||||
}
|
||||
__origin_override(err, "CPY");
|
||||
err->flags |= status.flags;
|
||||
return self;
|
||||
}
|
||||
if (src_size == 0)
|
||||
{
|
||||
__origin_override(err, "CPY");
|
||||
err->flags |= ERR_SIZE_ZERO;
|
||||
err->flags |= status.flags;
|
||||
return self;
|
||||
}
|
||||
if (src_size > self.max_size)
|
||||
{
|
||||
__origin_override(err, "CPY");
|
||||
err->flags |= ERR_SIZE_OVERFLOW;
|
||||
return self;
|
||||
}
|
||||
self.array = malloc(src_size * sizeof(float));
|
||||
if (self.array == nullptr)
|
||||
{
|
||||
__origin_override(err, "CPY");
|
||||
err->flags |= ERR_ALLOC_FAIL;
|
||||
return self;
|
||||
}
|
||||
memcpy(self.array, src, src_size * sizeof(float));
|
||||
self.size = src_size;
|
||||
self.capacity = src_size;
|
||||
return self;
|
||||
}
|
||||
|
||||
void
|
||||
vec_float_push_back(vec_float* ptr, const float val, err_t* err)
|
||||
{
|
||||
err_t status = ERR_T_INIT;
|
||||
float* res;
|
||||
__null_check(ptr, &status);
|
||||
if ((status.flags & ERR_VEC_NULL) != 0)
|
||||
{
|
||||
__origin_override(err, "PUSH_BACK");
|
||||
err->flags |= ERR_VEC_NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
if (ptr->size + 1 > ptr->max_size)
|
||||
{
|
||||
__origin_override(err, "PUSH_BACK");
|
||||
err->flags |= ERR_SIZE_OVERFLOW;
|
||||
return;
|
||||
}
|
||||
|
||||
if ((status.flags & ERR_BUF_NULL) != 0)
|
||||
{
|
||||
res = malloc(1 * sizeof(float));
|
||||
if (res == nullptr)
|
||||
{
|
||||
__origin_override(err, "PUSH_BACK");
|
||||
err->flags |= ERR_ALLOC_FAIL;
|
||||
return;
|
||||
}
|
||||
ptr->array = res;
|
||||
ptr->capacity = 1;
|
||||
ptr->size = 0;
|
||||
}
|
||||
|
||||
else if (ptr->size + 1 > ptr->capacity)
|
||||
{
|
||||
size_t dst_cap = (ptr->capacity / 2) + ptr->capacity;
|
||||
if (dst_cap == ptr->capacity)
|
||||
{
|
||||
dst_cap++;
|
||||
}
|
||||
if (dst_cap > ptr->max_size)
|
||||
{
|
||||
dst_cap = ptr->max_size;
|
||||
DEBUG(
|
||||
"Capacity cannot be grown any further due "
|
||||
"to hitting max size");
|
||||
}
|
||||
res = realloc(ptr->array, dst_cap * sizeof(float));
|
||||
if (res == nullptr)
|
||||
{
|
||||
__origin_override(err, "PUSH_BACK");
|
||||
err->flags |= ERR_SIZE_OVERFLOW;
|
||||
return;
|
||||
}
|
||||
ptr->array = res;
|
||||
ptr->capacity = dst_cap;
|
||||
}
|
||||
ptr->array[ptr->size] = val;
|
||||
ptr->size++;
|
||||
return;
|
||||
}
|
||||
|
||||
void
|
||||
vec_float_pop_back(vec_float* ptr, err_t* err)
|
||||
{
|
||||
if (__null_check(ptr, err) != 0)
|
||||
{
|
||||
__origin_override(err, "POP_BACK");
|
||||
return;
|
||||
}
|
||||
|
||||
if (ptr->size == 0)
|
||||
{
|
||||
__origin_override(err, "POP_BACK");
|
||||
err->flags |= ERR_SIZE_ZERO;
|
||||
return;
|
||||
}
|
||||
|
||||
ptr->array[ptr->size - 1] = 0;
|
||||
ptr->size--;
|
||||
}
|
||||
|
||||
void
|
||||
vec_float_reserve(vec_float* ptr, const size_t capacity, err_t* err)
|
||||
{
|
||||
err_t status = ERR_T_INIT;
|
||||
if (__null_check(ptr, &status) != 0)
|
||||
{
|
||||
if ((status.flags & ERR_VEC_NULL) != 0)
|
||||
{
|
||||
__origin_override(err, "RESERVE");
|
||||
err->flags |= ERR_VEC_NULL;
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (ptr->max_size < capacity)
|
||||
{
|
||||
__origin_override(err, "RESERVE");
|
||||
err->flags |= ERR_SIZE_OVERFLOW;
|
||||
return;
|
||||
}
|
||||
if (capacity == 0)
|
||||
{
|
||||
__origin_override(err, "RESERVE");
|
||||
err->flags |= ERR_SIZE_ZERO;
|
||||
return;
|
||||
}
|
||||
|
||||
float* res = realloc(ptr->array, capacity * sizeof(float));
|
||||
if (res == nullptr)
|
||||
{
|
||||
__origin_override(err, "RESERVE");
|
||||
err->flags |= ERR_ALLOC_FAIL;
|
||||
return;
|
||||
}
|
||||
ptr->array = res;
|
||||
ptr->capacity = capacity;
|
||||
if (ptr->size > capacity)
|
||||
{
|
||||
ptr->size = capacity;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
void
|
||||
vec_float_shrink_to_fit(vec_float* ptr, err_t* err)
|
||||
{
|
||||
err_t status = ERR_T_INIT;
|
||||
if (__null_check(ptr, &status) != 0)
|
||||
{
|
||||
__origin_override(err, "SHRINK_TO_FIT");
|
||||
err->flags |= status.flags;
|
||||
return;
|
||||
}
|
||||
if (ptr->size == 0)
|
||||
{
|
||||
__origin_override(err, "SHRINK_TO_FIT");
|
||||
err->flags |= ERR_SIZE_ZERO;
|
||||
return;
|
||||
}
|
||||
vec_float_reserve(ptr, ptr->size, err);
|
||||
}
|
||||
|
||||
void
|
||||
vec_float_swap(vec_float* ptr_a, vec_float* ptr_b, err_t* err)
|
||||
{
|
||||
err_t status_1 = ERR_T_INIT, status_2 = ERR_T_INIT;
|
||||
if ((__null_check(ptr_a, &status_1) & ERR_VEC_NULL) != 0 ||
|
||||
(__null_check(ptr_b, &status_2) & ERR_VEC_NULL) != 0)
|
||||
{
|
||||
__origin_override(err, "SWAP");
|
||||
err->flags |= ERR_VEC_NULL;
|
||||
return;
|
||||
}
|
||||
vec_float self = *ptr_a;
|
||||
*ptr_a = *ptr_b;
|
||||
*ptr_b = self;
|
||||
return;
|
||||
}
|
||||
|
||||
const float*
|
||||
vec_float_data(const vec_float* ptr, err_t* err)
|
||||
{
|
||||
err_t status = ERR_T_INIT;
|
||||
if (__null_check(ptr, &status) != 0)
|
||||
{
|
||||
__origin_override(err, "DATA");
|
||||
err->flags |= status.flags;
|
||||
return nullptr;
|
||||
}
|
||||
return &ptr->array[0];
|
||||
}
|
||||
|
||||
size_t
|
||||
vec_float_size(const vec_float* ptr, err_t* err)
|
||||
{
|
||||
err_t status = ERR_T_INIT;
|
||||
if (__null_check(ptr, &status) != 0)
|
||||
{
|
||||
__origin_override(err, "SIZE");
|
||||
err->flags |= status.flags;
|
||||
return 0;
|
||||
}
|
||||
return ptr->size;
|
||||
}
|
||||
|
||||
size_t
|
||||
vec_float_capacity(const vec_float* ptr, err_t* err)
|
||||
{
|
||||
err_t status = ERR_T_INIT;
|
||||
if (__null_check(ptr, &status) != 0)
|
||||
{
|
||||
__origin_override(err, "CAPACITY");
|
||||
err->flags |= status.flags;
|
||||
return 0;
|
||||
}
|
||||
return ptr->capacity;
|
||||
}
|
||||
|
||||
size_t
|
||||
vec_float_max_size(const vec_float* ptr, err_t* err)
|
||||
{
|
||||
err_t status = ERR_T_INIT;
|
||||
if (__null_check(ptr, &status) != 0)
|
||||
{
|
||||
__origin_override(err, "MAX_SIZE");
|
||||
err->flags |= status.flags;
|
||||
return 0;
|
||||
}
|
||||
return ptr->max_size;
|
||||
}
|
||||
|
||||
void
|
||||
vec_float_delete(vec_float* ptr, err_t* err)
|
||||
{
|
||||
err_t status = ERR_T_INIT;
|
||||
if (__null_check(ptr, &status) != 0)
|
||||
{
|
||||
__origin_override(err, "DELETE");
|
||||
err->flags |= status.flags;
|
||||
return;
|
||||
}
|
||||
if (ptr->array != nullptr)
|
||||
{
|
||||
free(ptr->array);
|
||||
ptr->array = nullptr;
|
||||
}
|
||||
ptr->size = 0;
|
||||
ptr->capacity = 0;
|
||||
}
|
||||
|
||||
void
|
||||
vec_float_clear(vec_float* ptr, err_t* err)
|
||||
{
|
||||
err_t status = ERR_T_INIT;
|
||||
if (__null_check(ptr, &status) != 0)
|
||||
{
|
||||
__origin_override(err, "CLEAR");
|
||||
err->flags |= status.flags;
|
||||
return;
|
||||
}
|
||||
if (ptr->size > 0)
|
||||
{
|
||||
memset(ptr->array, 0, ptr->size);
|
||||
ptr->size = 0;
|
||||
}
|
||||
}
|
||||
|
||||
float*
|
||||
vec_float_at(const vec_float* ptr, const size_t idx, err_t* err)
|
||||
{
|
||||
err_t status = ERR_T_INIT;
|
||||
if (__null_check(ptr, &status) != 0)
|
||||
{
|
||||
__origin_override(err, "AT");
|
||||
err->flags |= status.flags;
|
||||
return nullptr;
|
||||
}
|
||||
if (idx >= ptr->size)
|
||||
{
|
||||
__origin_override(err, "AT");
|
||||
err->flags |= ERR_OUT_OF_BOUNDS;
|
||||
return nullptr;
|
||||
}
|
||||
return &ptr->array[idx];
|
||||
}
|
||||
|
||||
size_t
|
||||
vec_float_begin(const vec_float* ptr, err_t* err)
|
||||
{
|
||||
err_t status = ERR_T_INIT;
|
||||
if (__null_check(ptr, &status) != 0)
|
||||
{
|
||||
__origin_override(err, "BEGIN");
|
||||
err->flags |= status.flags;
|
||||
return status.flags;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t
|
||||
vec_float_end(const vec_float* ptr, err_t* err)
|
||||
{
|
||||
err_t status = ERR_T_INIT;
|
||||
if (__null_check(ptr, &status) != 0)
|
||||
{
|
||||
__origin_override(err, "END");
|
||||
err->flags |= status.flags;
|
||||
return status.flags;
|
||||
}
|
||||
if (ptr->size == 0)
|
||||
{
|
||||
__origin_override(err, "END");
|
||||
err->flags |= ERR_SIZE_ZERO;
|
||||
return status.flags;
|
||||
}
|
||||
return (size_t)(ptr->size - 1);
|
||||
}
|
||||
|
||||
float
|
||||
vec_float_front(const vec_float* ptr, err_t* err)
|
||||
{
|
||||
err_t status = ERR_T_INIT;
|
||||
if (__null_check(ptr, &status) != 0)
|
||||
{
|
||||
__origin_override(err, "FRONT");
|
||||
err->flags |= status.flags;
|
||||
return -1;
|
||||
}
|
||||
if (vec_float_at(ptr, 0, err) == nullptr)
|
||||
{
|
||||
err->flags |= ERR_OUT_OF_BOUNDS;
|
||||
return 0;
|
||||
}
|
||||
return *vec_float_at(ptr, 0, err);
|
||||
}
|
||||
|
||||
float
|
||||
vec_float_back(const vec_float* ptr, err_t* err)
|
||||
{
|
||||
err_t status = ERR_T_INIT;
|
||||
if (__null_check(ptr, &status) != 0)
|
||||
{
|
||||
__origin_override(err, "BACK");
|
||||
err->flags |= status.flags;
|
||||
return -1;
|
||||
}
|
||||
if (vec_float_at(ptr, 0, err) == nullptr)
|
||||
{
|
||||
err->flags |= ERR_OUT_OF_BOUNDS;
|
||||
return 0;
|
||||
}
|
||||
return *vec_float_at(ptr, ptr->size - 1, err);
|
||||
}
|
||||
|
||||
size_t
|
||||
vec_float_empty(const vec_float* ptr, err_t* err)
|
||||
{
|
||||
err_t status = ERR_T_INIT;
|
||||
if (__null_check(ptr, &status) != 0)
|
||||
{
|
||||
__origin_override(err, "EMPTY");
|
||||
err->flags |= status.flags;
|
||||
return status.flags;
|
||||
}
|
||||
if (ptr->size == 0)
|
||||
{
|
||||
return ptr->size;
|
||||
}
|
||||
return status.flags;
|
||||
}
|
||||
|
||||
__attribute__((overloadable)) void
|
||||
vec_float_erase(vec_float* ptr, const size_t iter, err_t* err)
|
||||
{
|
||||
err_t status = ERR_T_INIT;
|
||||
if (__null_check(ptr, &status) != 0)
|
||||
{
|
||||
__origin_override(err, "ERASE");
|
||||
err->flags |= status.flags;
|
||||
return;
|
||||
}
|
||||
if (iter >= ptr->size)
|
||||
{
|
||||
return;
|
||||
}
|
||||
memmove(&ptr->array[iter], &ptr->array[iter + 1],
|
||||
(ptr->size - iter - 1) * sizeof(float));
|
||||
ptr->array[ptr->size - 1] = 0;
|
||||
ptr->size--;
|
||||
return;
|
||||
}
|
||||
|
||||
__attribute__((overloadable)) void
|
||||
vec_float_erase(vec_float* ptr, const size_t iter_start, const size_t iter_end,
|
||||
err_t* err)
|
||||
{
|
||||
err_t status = ERR_T_INIT;
|
||||
if (__null_check(ptr, &status) != 0)
|
||||
{
|
||||
__origin_override(err, "ERASE");
|
||||
err->flags |= status.flags;
|
||||
return;
|
||||
}
|
||||
|
||||
if (ptr->size < iter_end || iter_end <= iter_start)
|
||||
{
|
||||
__origin_override(err, "ERASE");
|
||||
err->flags |= ERR_OUT_OF_BOUNDS;
|
||||
return;
|
||||
}
|
||||
size_t diff = iter_end - iter_start;
|
||||
memmove(&ptr->array[iter_start], &ptr->array[iter_end],
|
||||
(ptr->size - iter_end) * sizeof(float));
|
||||
memset(&ptr->array[ptr->size - diff], 0, sizeof(float) * diff);
|
||||
ptr->size -= diff;
|
||||
return;
|
||||
}
|
||||
|
||||
__attribute__((overloadable)) void
|
||||
vec_float_resize(vec_float* ptr, const size_t size, err_t* err)
|
||||
{
|
||||
err_t status = ERR_T_INIT;
|
||||
__null_check(ptr, &status);
|
||||
if ((status.flags & ERR_VEC_NULL) != 0)
|
||||
{
|
||||
__origin_override(err, "RESIZE");
|
||||
err->flags |= ERR_VEC_NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
if (ptr->size == size)
|
||||
{
|
||||
__origin_override(err, "RESIZE");
|
||||
err->flags |= ERR_OUT_OF_BOUNDS;
|
||||
return;
|
||||
}
|
||||
|
||||
else if (size > ptr->max_size)
|
||||
{
|
||||
__origin_override(err, "RESIZE");
|
||||
err->flags |= ERR_SIZE_OVERFLOW;
|
||||
return;
|
||||
}
|
||||
|
||||
else if ((status.flags & ERR_BUF_NULL) != 0 || ptr->size == 0)
|
||||
{
|
||||
size_t max = ptr->max_size;
|
||||
err_t verr = ERR_T_INIT;
|
||||
vec_float_reserve(ptr, size, &verr);
|
||||
if (verr.flags != 0)
|
||||
{
|
||||
__origin_override(err, "RESIZE");
|
||||
err->flags |= verr.flags;
|
||||
return;
|
||||
}
|
||||
if (ptr->capacity != size)
|
||||
{
|
||||
__origin_override(err, "RESIZE");
|
||||
err->flags |= ERR_ALLOC_FAIL;
|
||||
return;
|
||||
}
|
||||
for (size_t i = 0; i < size; i++)
|
||||
{
|
||||
ptr->array[i] = 0;
|
||||
}
|
||||
ptr->max_size = max;
|
||||
ptr->size = size;
|
||||
return;
|
||||
}
|
||||
else if (size > ptr->capacity)
|
||||
{
|
||||
size_t tmpcp = ptr->capacity;
|
||||
size_t tmpmx = ptr->max_size;
|
||||
err_t verr = ERR_T_INIT;
|
||||
while (size > tmpcp)
|
||||
{
|
||||
tmpcp *= 2;
|
||||
}
|
||||
if (tmpcp > ptr->max_size)
|
||||
{
|
||||
tmpcp = size;
|
||||
}
|
||||
vec_float_reserve(ptr, tmpcp, &verr);
|
||||
if (verr.flags != 0)
|
||||
{
|
||||
__origin_override(err, "RESIZE");
|
||||
err->flags |= verr.flags;
|
||||
return;
|
||||
}
|
||||
if (ptr->capacity != tmpcp)
|
||||
{
|
||||
__origin_override(err, "RESIZE");
|
||||
err->flags |= ERR_ALLOC_FAIL;
|
||||
return;
|
||||
}
|
||||
ptr->max_size = tmpmx;
|
||||
}
|
||||
if (size < ptr->size)
|
||||
{
|
||||
memset(&ptr->array[size], 0, ptr->size - size);
|
||||
}
|
||||
if (ptr->size < size && size <= ptr->capacity)
|
||||
{
|
||||
memset(&ptr->array[ptr->size], 0, size - ptr->size);
|
||||
}
|
||||
ptr->size = size;
|
||||
return;
|
||||
}
|
||||
|
||||
__attribute__((overloadable)) void
|
||||
vec_float_resize(vec_float* ptr, const size_t size, const float val, err_t* err)
|
||||
{
|
||||
err_t status = ERR_T_INIT;
|
||||
__null_check(ptr, &status);
|
||||
if ((status.flags & ERR_VEC_NULL) != 0)
|
||||
{
|
||||
__origin_override(err, "RESIZE");
|
||||
err->flags |= ERR_VEC_NULL;
|
||||
return;
|
||||
}
|
||||
if (ptr->size == size)
|
||||
{
|
||||
__origin_override(err, "RESIZE");
|
||||
err->flags |= ERR_OUT_OF_BOUNDS;
|
||||
return;
|
||||
}
|
||||
|
||||
else if (size > ptr->max_size)
|
||||
{
|
||||
__origin_override(err, "RESIZE");
|
||||
err->flags |= ERR_SIZE_OVERFLOW;
|
||||
return;
|
||||
}
|
||||
|
||||
else if ((status.flags & ERR_BUF_NULL) != 0 || ptr->size == 0)
|
||||
{
|
||||
size_t max = ptr->max_size;
|
||||
err_t verr = ERR_T_INIT;
|
||||
vec_float_reserve(ptr, size, &verr);
|
||||
if (verr.flags != 0)
|
||||
{
|
||||
__origin_override(err, "RESIZE");
|
||||
err->flags |= verr.flags;
|
||||
return;
|
||||
}
|
||||
if (ptr->capacity != size)
|
||||
{
|
||||
__origin_override(err, "RESIZE");
|
||||
err->flags |= ERR_ALLOC_FAIL;
|
||||
return;
|
||||
}
|
||||
for (size_t i = 0; i < size; i++)
|
||||
{
|
||||
ptr->array[i] = val;
|
||||
}
|
||||
ptr->max_size = max;
|
||||
ptr->size = size;
|
||||
return;
|
||||
}
|
||||
else if (size > ptr->capacity)
|
||||
{
|
||||
size_t tmpcp = ptr->capacity;
|
||||
size_t tmpmx = ptr->max_size;
|
||||
err_t verr = ERR_T_INIT;
|
||||
while (size > tmpcp)
|
||||
{
|
||||
tmpcp *= 2;
|
||||
}
|
||||
if (tmpcp > ptr->max_size)
|
||||
{
|
||||
tmpcp = size;
|
||||
}
|
||||
vec_float_reserve(ptr, tmpcp, &verr);
|
||||
if (verr.flags != 0)
|
||||
{
|
||||
__origin_override(err, "RESIZE");
|
||||
err->flags |= verr.flags;
|
||||
return;
|
||||
}
|
||||
ptr->max_size = tmpmx;
|
||||
}
|
||||
if (size < ptr->size)
|
||||
{
|
||||
memset(&ptr->array[size], val, ptr->size - size);
|
||||
}
|
||||
if (ptr->size < size && size <= ptr->capacity)
|
||||
{
|
||||
memset(&ptr->array[ptr->size], val, size - ptr->size);
|
||||
}
|
||||
ptr->size = size;
|
||||
return;
|
||||
}
|
||||
|
||||
__attribute__((overloadable)) void
|
||||
vec_float_assign(vec_float* ptr, const vec_float* iterator,
|
||||
const size_t iter_start, const size_t iter_end, err_t* err)
|
||||
{
|
||||
err_t status = ERR_T_INIT;
|
||||
if (__null_check(ptr, &status) != 0 ||
|
||||
__null_check(iterator, &status) != 0)
|
||||
{
|
||||
__origin_override(err, "ASSIGN");
|
||||
err->flags |= status.flags;
|
||||
return;
|
||||
}
|
||||
if (ptr->array == iterator->array)
|
||||
{
|
||||
__origin_override(err, "ASSIGN");
|
||||
err->flags |= ERR_DOUBLE_BUF;
|
||||
return;
|
||||
}
|
||||
if (iterator->size < iter_end || iter_end <= iter_start)
|
||||
{
|
||||
__origin_override(err, "ASSIGN");
|
||||
err->flags |= ERR_OUT_OF_BOUNDS;
|
||||
return;
|
||||
}
|
||||
vec_float_erase(ptr, vec_float_begin(ptr, &status),
|
||||
vec_float_end(ptr, &status) + 1, &status);
|
||||
if (status.flags != 0)
|
||||
{
|
||||
__origin_override(err, "ASSIGN");
|
||||
err->flags |= status.flags;
|
||||
return;
|
||||
}
|
||||
vec_float_reserve(ptr, (iter_end - iter_start), &status);
|
||||
if (status.flags != 0)
|
||||
{
|
||||
__origin_override(err, "ASSIGN");
|
||||
err->flags |= status.flags;
|
||||
return;
|
||||
}
|
||||
for (size_t i = iter_start; i < iter_end; i++)
|
||||
{
|
||||
float* res = vec_float_at(iterator, i, &status);
|
||||
if (res == nullptr)
|
||||
{
|
||||
err->flags |= ERR_OUT_OF_BOUNDS;
|
||||
return;
|
||||
}
|
||||
vec_float_push_back(ptr, *res, &status);
|
||||
if (status.flags != 0)
|
||||
{
|
||||
__origin_override(err, "ASSIGN");
|
||||
err->flags |= status.flags;
|
||||
return;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
__attribute__((overloadable)) void
|
||||
vec_float_assign(vec_float* ptr, const size_t amount, const float val,
|
||||
err_t* err)
|
||||
{
|
||||
err_t status = ERR_T_INIT;
|
||||
if (__null_check(ptr, &status) != 0)
|
||||
{
|
||||
__origin_override(err, "ASSIGN");
|
||||
err->flags |= status.flags;
|
||||
return;
|
||||
}
|
||||
if (amount == 0)
|
||||
{
|
||||
__origin_override(err, "ASSIGN");
|
||||
err->flags |= ERR_SIZE_ZERO;
|
||||
return;
|
||||
}
|
||||
vec_float_erase(ptr, vec_float_begin(ptr, &status),
|
||||
vec_float_end(ptr, &status) + 1, &status);
|
||||
if (status.flags != 0)
|
||||
{
|
||||
__origin_override(err, "ASSIGN");
|
||||
err->flags |= status.flags;
|
||||
return;
|
||||
}
|
||||
vec_float_reserve(ptr, amount, &status);
|
||||
if (status.flags != 0)
|
||||
{
|
||||
__origin_override(err, "ASSIGN");
|
||||
err->flags |= status.flags;
|
||||
return;
|
||||
}
|
||||
for (size_t i = 0; i < amount; i++)
|
||||
{
|
||||
vec_float_push_back(ptr, val, &status);
|
||||
if (status.flags != 0)
|
||||
{
|
||||
__origin_override(err, "ASSIGN");
|
||||
err->flags |= status.flags;
|
||||
return;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
__attribute__((overloadable)) void
|
||||
vec_float_insert(vec_float* ptr, const size_t iter, const float val, err_t* err)
|
||||
{
|
||||
err_t status = ERR_T_INIT;
|
||||
__null_check(ptr, &status);
|
||||
if ((status.flags & ERR_VEC_NULL) != 0)
|
||||
{
|
||||
__origin_override(err, "INSERT");
|
||||
err->flags |= status.flags;
|
||||
return;
|
||||
}
|
||||
if ((status.flags & ERR_BUF_NULL) != 0)
|
||||
{
|
||||
float* res = malloc(1 * sizeof(float));
|
||||
if (res == nullptr)
|
||||
{
|
||||
__origin_override(err, "INSERT");
|
||||
err->flags |= ERR_BUF_NULL;
|
||||
return;
|
||||
}
|
||||
ptr->array = res;
|
||||
ptr->capacity = 1;
|
||||
ptr->array[0] = val;
|
||||
ptr->size = 1;
|
||||
return;
|
||||
}
|
||||
if (ptr->max_size < ptr->size + 1)
|
||||
{
|
||||
__origin_override(err, "INSERT");
|
||||
err->flags |= ERR_SIZE_OVERFLOW;
|
||||
return;
|
||||
}
|
||||
if (iter > ptr->size)
|
||||
{
|
||||
__origin_override(err, "INSERT");
|
||||
err->flags |= ERR_OUT_OF_BOUNDS;
|
||||
return;
|
||||
}
|
||||
vec_float_push_back(ptr, 0, &status);
|
||||
if (status.flags != 0)
|
||||
{
|
||||
__origin_override(err, "INSERT");
|
||||
err->flags |= status.flags;
|
||||
return;
|
||||
}
|
||||
for (size_t i = ptr->size - 1; i > iter; i--)
|
||||
{
|
||||
ptr->array[i] = ptr->array[i - 1];
|
||||
}
|
||||
ptr->array[iter] = val;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
__attribute__((overloadable)) void
|
||||
vec_float_insert(vec_float* ptr, const size_t iter, const size_t amount,
|
||||
const float val, err_t* err)
|
||||
{
|
||||
err_t status = ERR_T_INIT;
|
||||
__null_check(ptr, &status);
|
||||
if ((status.flags & (ERR_VEC_NULL | ERR_BUF_NULL)) != 0)
|
||||
{
|
||||
__origin_override(err, "INSERT");
|
||||
err->flags |= status.flags;
|
||||
return;
|
||||
}
|
||||
if (iter > ptr->size)
|
||||
{
|
||||
__origin_override(err, "INSERT");
|
||||
err->flags |= ERR_OUT_OF_BOUNDS;
|
||||
return;
|
||||
}
|
||||
if (amount == 0)
|
||||
{
|
||||
__origin_override(err, "INSERT");
|
||||
err->flags |= ERR_SIZE_ZERO;
|
||||
return;
|
||||
}
|
||||
for (size_t i = iter; i < iter + amount; i++)
|
||||
{
|
||||
vec_float_insert(ptr, i, val, &status);
|
||||
if (status.flags != 0)
|
||||
{
|
||||
__origin_override(err, "INSERT");
|
||||
err->flags |= status.flags;
|
||||
return;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
__attribute__((overloadable)) void
|
||||
vec_float_insert(vec_float* ptr, const vec_float* iterator, const size_t iter,
|
||||
const size_t iter_start, const size_t iter_end, err_t* err)
|
||||
{
|
||||
err_t status = ERR_T_INIT;
|
||||
__null_check(ptr, &status);
|
||||
__null_check(iterator, &status);
|
||||
if ((status.flags & (ERR_VEC_NULL | ERR_BUF_NULL)) != 0)
|
||||
{
|
||||
__origin_override(err, "INSERT");
|
||||
err->flags |= status.flags;
|
||||
return;
|
||||
}
|
||||
if (iter_end <= iter_start || iter_end > iterator->size ||
|
||||
iter > ptr->size)
|
||||
{
|
||||
__origin_override(err, "INSERT");
|
||||
err->flags |= ERR_OUT_OF_BOUNDS;
|
||||
return;
|
||||
}
|
||||
if (ptr->array == iterator->array)
|
||||
{
|
||||
__origin_override(err, "INSERT");
|
||||
err->flags |= ERR_DOUBLE_BUF;
|
||||
return;
|
||||
}
|
||||
for (size_t i = iter_start; i < iter_end; i++)
|
||||
{
|
||||
vec_float_insert(ptr, iter + (i - iter_start),
|
||||
iterator->array[i], &status);
|
||||
if (status.flags != 0)
|
||||
{
|
||||
__origin_override(err, "INSERT");
|
||||
err->flags |= status.flags;
|
||||
return;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
@@ -0,0 +1,894 @@
|
||||
#include <libvec/int.h>
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
__attribute__((overloadable)) size_t
|
||||
__null_check(const vec_int* ptr, err_t* status)
|
||||
{
|
||||
if (status == nullptr)
|
||||
{
|
||||
return ERR_ERR_T_NULL;
|
||||
}
|
||||
if (ptr == nullptr)
|
||||
{
|
||||
status->flags |= ERR_VEC_NULL;
|
||||
return ERR_VEC_NULL;
|
||||
}
|
||||
if (ptr->array == nullptr)
|
||||
{
|
||||
status->flags |= ERR_BUF_NULL;
|
||||
}
|
||||
|
||||
return status->flags;
|
||||
}
|
||||
|
||||
void
|
||||
vec_int_print_vec(const vec_int* ptr, err_t* err)
|
||||
{
|
||||
if (__null_check(ptr, err) != 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
for (size_t i = 0; i < ptr->size; i++)
|
||||
{
|
||||
printf("%d ", ptr->array[i]);
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
vec_int
|
||||
vec_int_cpy(const int* src, const size_t src_size, err_t* err)
|
||||
{
|
||||
vec_int self = VEC_INIT;
|
||||
err_t status = ERR_T_INIT;
|
||||
|
||||
size_t null = __null_check(src, err);
|
||||
if (null != 0)
|
||||
{
|
||||
if (null & ERR_ERR_T_NULL)
|
||||
{
|
||||
return self;
|
||||
}
|
||||
__origin_override(err, "CPY");
|
||||
err->flags |= status.flags;
|
||||
return self;
|
||||
}
|
||||
if (src_size == 0)
|
||||
{
|
||||
__origin_override(err, "CPY");
|
||||
err->flags |= ERR_SIZE_ZERO;
|
||||
err->flags |= status.flags;
|
||||
return self;
|
||||
}
|
||||
if (src_size > self.max_size)
|
||||
{
|
||||
__origin_override(err, "CPY");
|
||||
err->flags |= ERR_SIZE_OVERFLOW;
|
||||
return self;
|
||||
}
|
||||
self.array = malloc(src_size * sizeof(int));
|
||||
if (self.array == nullptr)
|
||||
{
|
||||
__origin_override(err, "CPY");
|
||||
err->flags |= ERR_ALLOC_FAIL;
|
||||
return self;
|
||||
}
|
||||
memcpy(self.array, src, src_size * sizeof(int));
|
||||
self.size = src_size;
|
||||
self.capacity = src_size;
|
||||
return self;
|
||||
}
|
||||
|
||||
void
|
||||
vec_int_push_back(vec_int* ptr, const int val, err_t* err)
|
||||
{
|
||||
err_t status = ERR_T_INIT;
|
||||
int* res;
|
||||
__null_check(ptr, &status);
|
||||
if ((status.flags & ERR_VEC_NULL) != 0)
|
||||
{
|
||||
__origin_override(err, "PUSH_BACK");
|
||||
err->flags |= ERR_VEC_NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
if (ptr->size + 1 > ptr->max_size)
|
||||
{
|
||||
__origin_override(err, "PUSH_BACK");
|
||||
err->flags |= ERR_SIZE_OVERFLOW;
|
||||
return;
|
||||
}
|
||||
|
||||
if ((status.flags & ERR_BUF_NULL) != 0)
|
||||
{
|
||||
res = malloc(1 * sizeof(int));
|
||||
if (res == nullptr)
|
||||
{
|
||||
__origin_override(err, "PUSH_BACK");
|
||||
err->flags |= ERR_ALLOC_FAIL;
|
||||
return;
|
||||
}
|
||||
ptr->array = res;
|
||||
ptr->capacity = 1;
|
||||
ptr->size = 0;
|
||||
}
|
||||
|
||||
else if (ptr->size + 1 > ptr->capacity)
|
||||
{
|
||||
size_t dst_cap = (ptr->capacity / 2) + ptr->capacity;
|
||||
if (dst_cap == ptr->capacity)
|
||||
{
|
||||
dst_cap++;
|
||||
}
|
||||
if (dst_cap > ptr->max_size)
|
||||
{
|
||||
dst_cap = ptr->max_size;
|
||||
DEBUG(
|
||||
"Capacity cannot be grown any further due "
|
||||
"to hitting max size");
|
||||
}
|
||||
res = realloc(ptr->array, dst_cap * sizeof(int));
|
||||
if (res == nullptr)
|
||||
{
|
||||
__origin_override(err, "PUSH_BACK");
|
||||
err->flags |= ERR_SIZE_OVERFLOW;
|
||||
return;
|
||||
}
|
||||
ptr->array = res;
|
||||
ptr->capacity = dst_cap;
|
||||
}
|
||||
ptr->array[ptr->size] = val;
|
||||
ptr->size++;
|
||||
return;
|
||||
}
|
||||
|
||||
void
|
||||
vec_int_pop_back(vec_int* ptr, err_t* err)
|
||||
{
|
||||
if (__null_check(ptr, err) != 0)
|
||||
{
|
||||
__origin_override(err, "POP_BACK");
|
||||
return;
|
||||
}
|
||||
|
||||
if (ptr->size == 0)
|
||||
{
|
||||
__origin_override(err, "POP_BACK");
|
||||
err->flags |= ERR_SIZE_ZERO;
|
||||
return;
|
||||
}
|
||||
|
||||
ptr->array[ptr->size - 1] = 0;
|
||||
ptr->size--;
|
||||
}
|
||||
|
||||
void
|
||||
vec_int_reserve(vec_int* ptr, const size_t capacity, err_t* err)
|
||||
{
|
||||
err_t status = ERR_T_INIT;
|
||||
if (__null_check(ptr, &status) != 0)
|
||||
{
|
||||
if ((status.flags & ERR_VEC_NULL) != 0)
|
||||
{
|
||||
__origin_override(err, "RESERVE");
|
||||
err->flags |= ERR_VEC_NULL;
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (ptr->max_size < capacity)
|
||||
{
|
||||
__origin_override(err, "RESERVE");
|
||||
err->flags |= ERR_SIZE_OVERFLOW;
|
||||
return;
|
||||
}
|
||||
if (capacity == 0)
|
||||
{
|
||||
__origin_override(err, "RESERVE");
|
||||
err->flags |= ERR_SIZE_ZERO;
|
||||
return;
|
||||
}
|
||||
|
||||
int* res = realloc(ptr->array, capacity * sizeof(int));
|
||||
if (res == nullptr)
|
||||
{
|
||||
__origin_override(err, "RESERVE");
|
||||
err->flags |= ERR_ALLOC_FAIL;
|
||||
return;
|
||||
}
|
||||
ptr->array = res;
|
||||
ptr->capacity = capacity;
|
||||
if (ptr->size > capacity)
|
||||
{
|
||||
ptr->size = capacity;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
void
|
||||
vec_int_shrink_to_fit(vec_int* ptr, err_t* err)
|
||||
{
|
||||
err_t status = ERR_T_INIT;
|
||||
if (__null_check(ptr, &status) != 0)
|
||||
{
|
||||
__origin_override(err, "SHRINK_TO_FIT");
|
||||
err->flags |= status.flags;
|
||||
return;
|
||||
}
|
||||
if (ptr->size == 0)
|
||||
{
|
||||
__origin_override(err, "SHRINK_TO_FIT");
|
||||
err->flags |= ERR_SIZE_ZERO;
|
||||
return;
|
||||
}
|
||||
vec_int_reserve(ptr, ptr->size, err);
|
||||
}
|
||||
|
||||
void
|
||||
vec_int_swap(vec_int* ptr_a, vec_int* ptr_b, err_t* err)
|
||||
{
|
||||
err_t status_1 = ERR_T_INIT, status_2 = ERR_T_INIT;
|
||||
if ((__null_check(ptr_a, &status_1) & ERR_VEC_NULL) != 0 ||
|
||||
(__null_check(ptr_b, &status_2) & ERR_VEC_NULL) != 0)
|
||||
{
|
||||
__origin_override(err, "SWAP");
|
||||
err->flags |= ERR_VEC_NULL;
|
||||
return;
|
||||
}
|
||||
vec_int self = *ptr_a;
|
||||
*ptr_a = *ptr_b;
|
||||
*ptr_b = self;
|
||||
return;
|
||||
}
|
||||
|
||||
const int*
|
||||
vec_int_data(const vec_int* ptr, err_t* err)
|
||||
{
|
||||
err_t status = ERR_T_INIT;
|
||||
if (__null_check(ptr, &status) != 0)
|
||||
{
|
||||
__origin_override(err, "DATA");
|
||||
err->flags |= status.flags;
|
||||
return nullptr;
|
||||
}
|
||||
return &ptr->array[0];
|
||||
}
|
||||
|
||||
size_t
|
||||
vec_int_size(const vec_int* ptr, err_t* err)
|
||||
{
|
||||
err_t status = ERR_T_INIT;
|
||||
if (__null_check(ptr, &status) != 0)
|
||||
{
|
||||
__origin_override(err, "SIZE");
|
||||
err->flags |= status.flags;
|
||||
return 0;
|
||||
}
|
||||
return ptr->size;
|
||||
}
|
||||
|
||||
size_t
|
||||
vec_int_capacity(const vec_int* ptr, err_t* err)
|
||||
{
|
||||
err_t status = ERR_T_INIT;
|
||||
if (__null_check(ptr, &status) != 0)
|
||||
{
|
||||
__origin_override(err, "CAPACITY");
|
||||
err->flags |= status.flags;
|
||||
return 0;
|
||||
}
|
||||
return ptr->capacity;
|
||||
}
|
||||
|
||||
size_t
|
||||
vec_int_max_size(const vec_int* ptr, err_t* err)
|
||||
{
|
||||
err_t status = ERR_T_INIT;
|
||||
if (__null_check(ptr, &status) != 0)
|
||||
{
|
||||
__origin_override(err, "MAX_SIZE");
|
||||
err->flags |= status.flags;
|
||||
return 0;
|
||||
}
|
||||
return ptr->max_size;
|
||||
}
|
||||
|
||||
void
|
||||
vec_int_delete(vec_int* ptr, err_t* err)
|
||||
{
|
||||
err_t status = ERR_T_INIT;
|
||||
if (__null_check(ptr, &status) != 0)
|
||||
{
|
||||
__origin_override(err, "DELETE");
|
||||
err->flags |= status.flags;
|
||||
return;
|
||||
}
|
||||
if (ptr->array != nullptr)
|
||||
{
|
||||
free(ptr->array);
|
||||
ptr->array = nullptr;
|
||||
}
|
||||
ptr->size = 0;
|
||||
ptr->capacity = 0;
|
||||
}
|
||||
|
||||
void
|
||||
vec_int_clear(vec_int* ptr, err_t* err)
|
||||
{
|
||||
err_t status = ERR_T_INIT;
|
||||
if (__null_check(ptr, &status) != 0)
|
||||
{
|
||||
__origin_override(err, "CLEAR");
|
||||
err->flags |= status.flags;
|
||||
return;
|
||||
}
|
||||
if (ptr->size > 0)
|
||||
{
|
||||
memset(ptr->array, 0, ptr->size * sizeof(int));
|
||||
ptr->size = 0;
|
||||
}
|
||||
}
|
||||
|
||||
int*
|
||||
vec_int_at(const vec_int* ptr, const size_t idx, err_t* err)
|
||||
{
|
||||
err_t status = ERR_T_INIT;
|
||||
if (__null_check(ptr, &status) != 0)
|
||||
{
|
||||
__origin_override(err, "AT");
|
||||
err->flags |= status.flags;
|
||||
return nullptr;
|
||||
}
|
||||
if (idx >= ptr->size)
|
||||
{
|
||||
__origin_override(err, "AT");
|
||||
err->flags |= ERR_OUT_OF_BOUNDS;
|
||||
return nullptr;
|
||||
}
|
||||
return &ptr->array[idx];
|
||||
}
|
||||
|
||||
size_t
|
||||
vec_int_begin(const vec_int* ptr, err_t* err)
|
||||
{
|
||||
err_t status = ERR_T_INIT;
|
||||
if (__null_check(ptr, &status) != 0)
|
||||
{
|
||||
__origin_override(err, "BEGIN");
|
||||
err->flags |= status.flags;
|
||||
return status.flags;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t
|
||||
vec_int_end(const vec_int* ptr, err_t* err)
|
||||
{
|
||||
err_t status = ERR_T_INIT;
|
||||
if (__null_check(ptr, &status) != 0)
|
||||
{
|
||||
__origin_override(err, "END");
|
||||
err->flags |= status.flags;
|
||||
return status.flags;
|
||||
}
|
||||
if (ptr->size == 0)
|
||||
{
|
||||
__origin_override(err, "END");
|
||||
err->flags |= ERR_SIZE_ZERO;
|
||||
return status.flags;
|
||||
}
|
||||
return (size_t)(ptr->size - 1);
|
||||
}
|
||||
|
||||
int
|
||||
vec_int_front(const vec_int* ptr, err_t* err)
|
||||
{
|
||||
err_t status = ERR_T_INIT;
|
||||
if (__null_check(ptr, &status) != 0)
|
||||
{
|
||||
__origin_override(err, "FRONT");
|
||||
err->flags |= status.flags;
|
||||
return -1;
|
||||
}
|
||||
if (vec_int_at(ptr, 0, err) == nullptr)
|
||||
{
|
||||
err->flags |= ERR_OUT_OF_BOUNDS;
|
||||
return 0;
|
||||
}
|
||||
return *vec_int_at(ptr, 0, err);
|
||||
}
|
||||
|
||||
int
|
||||
vec_int_back(const vec_int* ptr, err_t* err)
|
||||
{
|
||||
err_t status = ERR_T_INIT;
|
||||
if (__null_check(ptr, &status) != 0)
|
||||
{
|
||||
__origin_override(err, "BACK");
|
||||
err->flags |= status.flags;
|
||||
return -1;
|
||||
}
|
||||
if (vec_int_at(ptr, 0, err) == nullptr)
|
||||
{
|
||||
err->flags |= ERR_OUT_OF_BOUNDS;
|
||||
return 0;
|
||||
}
|
||||
return *vec_int_at(ptr, ptr->size - 1, err);
|
||||
}
|
||||
|
||||
size_t
|
||||
vec_int_empty(const vec_int* ptr, err_t* err)
|
||||
{
|
||||
err_t status = ERR_T_INIT;
|
||||
if (__null_check(ptr, &status) != 0)
|
||||
{
|
||||
__origin_override(err, "EMPTY");
|
||||
err->flags |= status.flags;
|
||||
return status.flags;
|
||||
}
|
||||
if (ptr->size == 0)
|
||||
{
|
||||
return ptr->size;
|
||||
}
|
||||
return status.flags;
|
||||
}
|
||||
|
||||
__attribute__((overloadable)) void
|
||||
vec_int_erase(vec_int* ptr, const size_t iter, err_t* err)
|
||||
{
|
||||
err_t status = ERR_T_INIT;
|
||||
if (__null_check(ptr, &status) != 0)
|
||||
{
|
||||
__origin_override(err, "ERASE");
|
||||
err->flags |= status.flags;
|
||||
return;
|
||||
}
|
||||
if (iter >= ptr->size)
|
||||
{
|
||||
return;
|
||||
}
|
||||
memmove(&ptr->array[iter], &ptr->array[iter + 1],
|
||||
(ptr->size - iter - 1) * sizeof(int));
|
||||
ptr->array[ptr->size - 1] = 0;
|
||||
ptr->size--;
|
||||
return;
|
||||
}
|
||||
|
||||
__attribute__((overloadable)) void
|
||||
vec_int_erase(vec_int* ptr, const size_t iter_start, const size_t iter_end,
|
||||
err_t* err)
|
||||
{
|
||||
err_t status = ERR_T_INIT;
|
||||
if (__null_check(ptr, &status) != 0)
|
||||
{
|
||||
__origin_override(err, "ERASE");
|
||||
err->flags |= status.flags;
|
||||
return;
|
||||
}
|
||||
|
||||
if (ptr->size < iter_end || iter_end <= iter_start)
|
||||
{
|
||||
__origin_override(err, "ERASE");
|
||||
err->flags |= ERR_OUT_OF_BOUNDS;
|
||||
return;
|
||||
}
|
||||
size_t diff = iter_end - iter_start;
|
||||
memmove(&ptr->array[iter_start], &ptr->array[iter_end],
|
||||
(ptr->size - iter_end) * sizeof(int));
|
||||
memset(&ptr->array[ptr->size - diff], 0, sizeof(int) * diff);
|
||||
ptr->size -= diff;
|
||||
return;
|
||||
}
|
||||
|
||||
__attribute__((overloadable)) void
|
||||
vec_int_resize(vec_int* ptr, const size_t size, err_t* err)
|
||||
{
|
||||
err_t status = ERR_T_INIT;
|
||||
__null_check(ptr, &status);
|
||||
if ((status.flags & ERR_VEC_NULL) != 0)
|
||||
{
|
||||
__origin_override(err, "RESIZE");
|
||||
err->flags |= ERR_VEC_NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
if (ptr->size == size)
|
||||
{
|
||||
__origin_override(err, "RESIZE");
|
||||
err->flags |= ERR_OUT_OF_BOUNDS;
|
||||
return;
|
||||
}
|
||||
|
||||
else if (size > ptr->max_size)
|
||||
{
|
||||
__origin_override(err, "RESIZE");
|
||||
err->flags |= ERR_SIZE_OVERFLOW;
|
||||
return;
|
||||
}
|
||||
|
||||
else if ((status.flags & ERR_BUF_NULL) != 0 || ptr->size == 0)
|
||||
{
|
||||
size_t max = ptr->max_size;
|
||||
err_t verr = ERR_T_INIT;
|
||||
vec_int_reserve(ptr, size, &verr);
|
||||
if (verr.flags != 0)
|
||||
{
|
||||
__origin_override(err, "RESIZE");
|
||||
err->flags |= verr.flags;
|
||||
return;
|
||||
}
|
||||
if (ptr->capacity != size)
|
||||
{
|
||||
__origin_override(err, "RESIZE");
|
||||
err->flags |= ERR_ALLOC_FAIL;
|
||||
return;
|
||||
}
|
||||
memset(ptr->array, 0, size * sizeof(int));
|
||||
ptr->max_size = max;
|
||||
ptr->size = size;
|
||||
return;
|
||||
}
|
||||
else if (size > ptr->capacity)
|
||||
{
|
||||
size_t tmpcp = ptr->capacity;
|
||||
size_t tmpmx = ptr->max_size;
|
||||
err_t verr = ERR_T_INIT;
|
||||
while (size > tmpcp)
|
||||
{
|
||||
tmpcp *= 2;
|
||||
}
|
||||
if (tmpcp > ptr->max_size)
|
||||
{
|
||||
tmpcp = size;
|
||||
}
|
||||
vec_int_reserve(ptr, tmpcp, &verr);
|
||||
if (verr.flags != 0)
|
||||
{
|
||||
__origin_override(err, "RESIZE");
|
||||
err->flags |= verr.flags;
|
||||
return;
|
||||
}
|
||||
if (ptr->capacity != tmpcp)
|
||||
{
|
||||
__origin_override(err, "RESIZE");
|
||||
err->flags |= ERR_ALLOC_FAIL;
|
||||
return;
|
||||
}
|
||||
ptr->max_size = tmpmx;
|
||||
}
|
||||
if (size < ptr->size)
|
||||
{
|
||||
memset(&ptr->array[size], 0, (ptr->size - size) * sizeof(int));
|
||||
}
|
||||
if (ptr->size < size && size <= ptr->capacity)
|
||||
{
|
||||
memset(&ptr->array[ptr->size], 0,
|
||||
(size - ptr->size) * sizeof(int));
|
||||
}
|
||||
ptr->size = size;
|
||||
return;
|
||||
}
|
||||
|
||||
__attribute__((overloadable)) void
|
||||
vec_int_resize(vec_int* ptr, const size_t size, const int val, err_t* err)
|
||||
{
|
||||
err_t status = ERR_T_INIT;
|
||||
__null_check(ptr, &status);
|
||||
if ((status.flags & ERR_VEC_NULL) != 0)
|
||||
{
|
||||
__origin_override(err, "RESIZE");
|
||||
err->flags |= ERR_VEC_NULL;
|
||||
return;
|
||||
}
|
||||
if (ptr->size == size)
|
||||
{
|
||||
__origin_override(err, "RESIZE");
|
||||
err->flags |= ERR_OUT_OF_BOUNDS;
|
||||
return;
|
||||
}
|
||||
|
||||
else if (size > ptr->max_size)
|
||||
{
|
||||
__origin_override(err, "RESIZE");
|
||||
err->flags |= ERR_SIZE_OVERFLOW;
|
||||
return;
|
||||
}
|
||||
|
||||
else if ((status.flags & ERR_BUF_NULL) != 0 || ptr->size == 0)
|
||||
{
|
||||
size_t max = ptr->max_size;
|
||||
err_t verr = ERR_T_INIT;
|
||||
vec_int_reserve(ptr, size, &verr);
|
||||
if (verr.flags != 0)
|
||||
{
|
||||
__origin_override(err, "RESIZE");
|
||||
err->flags |= verr.flags;
|
||||
return;
|
||||
}
|
||||
if (ptr->capacity != size)
|
||||
{
|
||||
__origin_override(err, "RESIZE");
|
||||
err->flags |= ERR_ALLOC_FAIL;
|
||||
return;
|
||||
}
|
||||
for (size_t i = 0; i < size; i++)
|
||||
{
|
||||
ptr->array[i] = val;
|
||||
}
|
||||
ptr->max_size = max;
|
||||
ptr->size = size;
|
||||
return;
|
||||
}
|
||||
else if (size > ptr->capacity)
|
||||
{
|
||||
size_t tmpcp = ptr->capacity;
|
||||
size_t tmpmx = ptr->max_size;
|
||||
err_t verr = ERR_T_INIT;
|
||||
while (size > tmpcp)
|
||||
{
|
||||
tmpcp *= 2;
|
||||
}
|
||||
if (tmpcp > ptr->max_size)
|
||||
{
|
||||
tmpcp = size;
|
||||
}
|
||||
vec_int_reserve(ptr, tmpcp, &verr);
|
||||
if (verr.flags != 0)
|
||||
{
|
||||
__origin_override(err, "RESIZE");
|
||||
err->flags |= verr.flags;
|
||||
return;
|
||||
}
|
||||
ptr->max_size = tmpmx;
|
||||
}
|
||||
if (size < ptr->size)
|
||||
{
|
||||
for (size_t i = size; i < ptr->size; i++)
|
||||
{
|
||||
ptr->array[i] = 0;
|
||||
}
|
||||
}
|
||||
if (ptr->size < size && size <= ptr->capacity)
|
||||
{
|
||||
for (size_t i = ptr->size; i < size; i++)
|
||||
{
|
||||
ptr->array[i] = val;
|
||||
}
|
||||
}
|
||||
ptr->size = size;
|
||||
return;
|
||||
}
|
||||
|
||||
__attribute__((overloadable)) void
|
||||
vec_int_assign(vec_int* ptr, const vec_int* iterator, const size_t iter_start,
|
||||
const size_t iter_end, err_t* err)
|
||||
{
|
||||
err_t status = ERR_T_INIT;
|
||||
if (__null_check(ptr, &status) != 0 ||
|
||||
__null_check(iterator, &status) != 0)
|
||||
{
|
||||
__origin_override(err, "ASSIGN");
|
||||
err->flags |= status.flags;
|
||||
return;
|
||||
}
|
||||
if (ptr->array == iterator->array)
|
||||
{
|
||||
__origin_override(err, "ASSIGN");
|
||||
err->flags |= ERR_DOUBLE_BUF;
|
||||
return;
|
||||
}
|
||||
if (iterator->size < iter_end || iter_end <= iter_start)
|
||||
{
|
||||
__origin_override(err, "ASSIGN");
|
||||
err->flags |= ERR_OUT_OF_BOUNDS;
|
||||
return;
|
||||
}
|
||||
vec_int_erase(ptr, vec_int_begin(ptr, &status),
|
||||
vec_int_end(ptr, &status) + 1, &status);
|
||||
if (status.flags != 0)
|
||||
{
|
||||
__origin_override(err, "ASSIGN");
|
||||
err->flags |= status.flags;
|
||||
return;
|
||||
}
|
||||
vec_int_reserve(ptr, (iter_end - iter_start), &status);
|
||||
if (status.flags != 0)
|
||||
{
|
||||
__origin_override(err, "ASSIGN");
|
||||
err->flags |= status.flags;
|
||||
return;
|
||||
}
|
||||
for (size_t i = iter_start; i < iter_end; i++)
|
||||
{
|
||||
int* res = vec_int_at(iterator, i, &status);
|
||||
if (res == nullptr)
|
||||
{
|
||||
err->flags |= ERR_OUT_OF_BOUNDS;
|
||||
return;
|
||||
}
|
||||
vec_int_push_back(ptr, *res, &status);
|
||||
if (status.flags != 0)
|
||||
{
|
||||
__origin_override(err, "ASSIGN");
|
||||
err->flags |= status.flags;
|
||||
return;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
__attribute__((overloadable)) void
|
||||
vec_int_assign(vec_int* ptr, const size_t amount, const int val, err_t* err)
|
||||
{
|
||||
err_t status = ERR_T_INIT;
|
||||
if (__null_check(ptr, &status) != 0)
|
||||
{
|
||||
__origin_override(err, "ASSIGN");
|
||||
err->flags |= status.flags;
|
||||
return;
|
||||
}
|
||||
if (amount == 0)
|
||||
{
|
||||
__origin_override(err, "ASSIGN");
|
||||
err->flags |= ERR_SIZE_ZERO;
|
||||
return;
|
||||
}
|
||||
vec_int_erase(ptr, vec_int_begin(ptr, &status),
|
||||
vec_int_end(ptr, &status) + 1, &status);
|
||||
if (status.flags != 0)
|
||||
{
|
||||
__origin_override(err, "ASSIGN");
|
||||
err->flags |= status.flags;
|
||||
return;
|
||||
}
|
||||
vec_int_reserve(ptr, amount, &status);
|
||||
if (status.flags != 0)
|
||||
{
|
||||
__origin_override(err, "ASSIGN");
|
||||
err->flags |= status.flags;
|
||||
return;
|
||||
}
|
||||
for (size_t i = 0; i < amount; i++)
|
||||
{
|
||||
vec_int_push_back(ptr, val, &status);
|
||||
if (status.flags != 0)
|
||||
{
|
||||
__origin_override(err, "ASSIGN");
|
||||
err->flags |= status.flags;
|
||||
return;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
__attribute__((overloadable)) void
|
||||
vec_int_insert(vec_int* ptr, const size_t iter, const int val, err_t* err)
|
||||
{
|
||||
err_t status = ERR_T_INIT;
|
||||
__null_check(ptr, &status);
|
||||
if ((status.flags & ERR_VEC_NULL) != 0)
|
||||
{
|
||||
__origin_override(err, "INSERT");
|
||||
err->flags |= status.flags;
|
||||
return;
|
||||
}
|
||||
if ((status.flags & ERR_BUF_NULL) != 0)
|
||||
{
|
||||
int* res = malloc(1 * sizeof(int));
|
||||
if (res == nullptr)
|
||||
{
|
||||
__origin_override(err, "INSERT");
|
||||
err->flags |= ERR_BUF_NULL;
|
||||
return;
|
||||
}
|
||||
ptr->array = res;
|
||||
ptr->capacity = 1;
|
||||
ptr->array[0] = val;
|
||||
ptr->size = 1;
|
||||
return;
|
||||
}
|
||||
if (ptr->max_size < ptr->size + 1)
|
||||
{
|
||||
__origin_override(err, "INSERT");
|
||||
err->flags |= ERR_SIZE_OVERFLOW;
|
||||
return;
|
||||
}
|
||||
if (iter > ptr->size)
|
||||
{
|
||||
__origin_override(err, "INSERT");
|
||||
err->flags |= ERR_OUT_OF_BOUNDS;
|
||||
return;
|
||||
}
|
||||
vec_int_push_back(ptr, 0, &status);
|
||||
if (status.flags != 0)
|
||||
{
|
||||
__origin_override(err, "INSERT");
|
||||
err->flags |= status.flags;
|
||||
return;
|
||||
}
|
||||
for (size_t i = ptr->size - 1; i > iter; i--)
|
||||
{
|
||||
ptr->array[i] = ptr->array[i - 1];
|
||||
}
|
||||
ptr->array[iter] = val;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
__attribute__((overloadable)) void
|
||||
vec_int_insert(vec_int* ptr, const size_t iter, const size_t amount,
|
||||
const int val, err_t* err)
|
||||
{
|
||||
err_t status = ERR_T_INIT;
|
||||
__null_check(ptr, &status);
|
||||
if ((status.flags & (ERR_VEC_NULL | ERR_BUF_NULL)) != 0)
|
||||
{
|
||||
__origin_override(err, "INSERT");
|
||||
err->flags |= status.flags;
|
||||
return;
|
||||
}
|
||||
if (iter > ptr->size)
|
||||
{
|
||||
__origin_override(err, "INSERT");
|
||||
err->flags |= ERR_OUT_OF_BOUNDS;
|
||||
return;
|
||||
}
|
||||
if (amount == 0)
|
||||
{
|
||||
__origin_override(err, "INSERT");
|
||||
err->flags |= ERR_SIZE_ZERO;
|
||||
return;
|
||||
}
|
||||
for (size_t i = iter; i < iter + amount; i++)
|
||||
{
|
||||
vec_int_insert(ptr, i, val, &status);
|
||||
if (status.flags != 0)
|
||||
{
|
||||
__origin_override(err, "INSERT");
|
||||
err->flags |= status.flags;
|
||||
return;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
__attribute__((overloadable)) void
|
||||
vec_int_insert(vec_int* ptr, const vec_int* iterator, const size_t iter,
|
||||
const size_t iter_start, const size_t iter_end, err_t* err)
|
||||
{
|
||||
err_t status = ERR_T_INIT;
|
||||
__null_check(ptr, &status);
|
||||
__null_check(iterator, &status);
|
||||
if ((status.flags & (ERR_VEC_NULL | ERR_BUF_NULL)) != 0)
|
||||
{
|
||||
__origin_override(err, "INSERT");
|
||||
err->flags |= status.flags;
|
||||
return;
|
||||
}
|
||||
if (iter_end <= iter_start || iter_end > iterator->size ||
|
||||
iter > ptr->size)
|
||||
{
|
||||
__origin_override(err, "INSERT");
|
||||
err->flags |= ERR_OUT_OF_BOUNDS;
|
||||
return;
|
||||
}
|
||||
if (ptr->array == iterator->array)
|
||||
{
|
||||
__origin_override(err, "INSERT");
|
||||
err->flags |= ERR_DOUBLE_BUF;
|
||||
return;
|
||||
}
|
||||
for (size_t i = iter_start; i < iter_end; i++)
|
||||
{
|
||||
vec_int_insert(ptr, iter + (i - iter_start), iterator->array[i],
|
||||
&status);
|
||||
if (status.flags != 0)
|
||||
{
|
||||
__origin_override(err, "INSERT");
|
||||
err->flags |= status.flags;
|
||||
return;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
Vendored
BIN
Binary file not shown.
+22
-41
@@ -6,59 +6,40 @@
|
||||
*/
|
||||
/*
|
||||
* Types Wanted:
|
||||
* Char 8 Bits
|
||||
* Float 32 Bits with suffix of 'f'
|
||||
* Int 32 bits
|
||||
* String 32 Bits with suffix of 's'
|
||||
*/
|
||||
|
||||
#include <libvec/utils.h>
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "char.h"
|
||||
#include "utils.h"
|
||||
void
|
||||
print_bits(unsigned int num);
|
||||
|
||||
int
|
||||
main()
|
||||
{
|
||||
char ar1[] = { '1', '2', '3', '4' };
|
||||
char ar2[] = { 'a', 'b', 'c', 'd' };
|
||||
// Vec8_t v1;
|
||||
Vec8_t v1 = create(ar2, find_len(ar2));
|
||||
// print_vec(&v1);
|
||||
// printf("Hello\n");
|
||||
// v1 = assign(&v1, &v2, 0, 1);
|
||||
v1 = reserve(&v1, 9);
|
||||
print_vec(&v1);
|
||||
v1 = insert(&v1, 1, 'x');
|
||||
v1 = resize(&v1, 12);
|
||||
// v1 = insert(&v1, 1, 5, 'a');
|
||||
// printf("%c", at(&v1, 1));
|
||||
// printf("RESERVED SIZE: %zu", v1.max_size);
|
||||
print_vec(&v1);
|
||||
// v2 = resize(&v2, 3);
|
||||
// TODO:
|
||||
//
|
||||
// Fix the error checking because you make a status to hold all local
|
||||
// errors but then in some cases you or them to the main err handler and
|
||||
// if the error doesnt need to be there like a good error but one that
|
||||
// exists (i.e push_back getting a blank array), then you will have a
|
||||
// bloated and broken error handler
|
||||
//
|
||||
// Your pop back is a great example of how to handle it and is a clean
|
||||
// if statement as a header to all functions.
|
||||
// char res[4] = { 'a', 'b', 'c', 'd' };
|
||||
err_t status = ERR_T_INIT;
|
||||
status.flags |= ERR_BUF_NULL | ERR_VEC_NULL | ERR_STR_NULL;
|
||||
|
||||
// print_vec(&v2);
|
||||
unsigned int mask = 0;
|
||||
mask = ERR_BUF_NULL ^ status.flags;
|
||||
|
||||
// if (swap(&v1, &v2))
|
||||
// {
|
||||
// print_vec(&v1);
|
||||
// print_vec(&v2);
|
||||
// }
|
||||
// Vec8_t v1 = create(nullptr, 0);
|
||||
// v1 = reserve(&v1, 10);
|
||||
// v1 = pop_back(&v1);
|
||||
// for (int i = 0; i < 10; i++)
|
||||
// {
|
||||
// v1 = push_back(&v1, 'a');
|
||||
// }
|
||||
// print_vec(&v1);
|
||||
// printf("SIZE: %zu\n", v1.size);
|
||||
// v1 = push_back(&v1, 'a');
|
||||
// print_vec(&v1);
|
||||
// printf("SIZE: %zu\n", v1.size);
|
||||
delete(&v1);
|
||||
// delete(&v2);
|
||||
vec_print_bits(mask);
|
||||
vec_print_bits(status.flags);
|
||||
vec_print_errs(status);
|
||||
return 0;
|
||||
}
|
||||
|
||||
+938
@@ -0,0 +1,938 @@
|
||||
#include "libstr/string.h"
|
||||
|
||||
#include <libvec/string.h>
|
||||
#include <libvec/utils.h>
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
__attribute__((overloadable)) size_t
|
||||
__null_check(const vec_string* ptr, err_t* status)
|
||||
{
|
||||
if (status == nullptr)
|
||||
{
|
||||
return ERR_ERR_T_NULL;
|
||||
}
|
||||
if (ptr == nullptr)
|
||||
{
|
||||
status->flags |= ERR_VEC_NULL;
|
||||
return ERR_VEC_NULL;
|
||||
}
|
||||
if (ptr->array == nullptr)
|
||||
{
|
||||
status->flags |= ERR_BUF_NULL;
|
||||
}
|
||||
|
||||
return status->flags;
|
||||
}
|
||||
|
||||
__attribute__((overloadable)) size_t
|
||||
__null_check(const String* ptr, err_t* status)
|
||||
{
|
||||
if (status == nullptr)
|
||||
{
|
||||
return ERR_ERR_T_NULL;
|
||||
}
|
||||
if (ptr == nullptr)
|
||||
{
|
||||
status->flags |= ERR_STR_NULL;
|
||||
return status->flags;
|
||||
}
|
||||
if (ptr->data == nullptr)
|
||||
{
|
||||
status->flags |= ERR_BUF_NULL;
|
||||
}
|
||||
return status->flags;
|
||||
}
|
||||
|
||||
void
|
||||
vec_string_print_vec(const vec_string* ptr, err_t* err)
|
||||
{
|
||||
if (__null_check(ptr, err) != 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
for (size_t i = 0; i < ptr->size; i++)
|
||||
{
|
||||
printf("%s ", ptr->array[i].data);
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
vec_string
|
||||
vec_string_cpy(const String* src, const size_t src_size, err_t* err)
|
||||
{
|
||||
vec_string self = VEC_INIT;
|
||||
err_t status = ERR_T_INIT;
|
||||
|
||||
size_t null = __null_check(src, err);
|
||||
if (null != 0)
|
||||
{
|
||||
if (null & ERR_ERR_T_NULL)
|
||||
{
|
||||
return self;
|
||||
}
|
||||
__origin_override(err, "CPY");
|
||||
err->flags |= status.flags;
|
||||
return self;
|
||||
}
|
||||
if (src_size == 0)
|
||||
{
|
||||
__origin_override(err, "CPY");
|
||||
err->flags |= ERR_SIZE_ZERO;
|
||||
err->flags |= status.flags;
|
||||
return self;
|
||||
}
|
||||
if (src_size > self.max_size)
|
||||
{
|
||||
__origin_override(err, "CPY");
|
||||
err->flags |= ERR_SIZE_OVERFLOW;
|
||||
return self;
|
||||
}
|
||||
self.array = malloc(src_size * sizeof(String));
|
||||
if (self.array == nullptr)
|
||||
{
|
||||
__origin_override(err, "CPY");
|
||||
err->flags |= ERR_ALLOC_FAIL;
|
||||
return self;
|
||||
}
|
||||
memcpy(self.array, src, src_size * sizeof(String));
|
||||
self.size = src_size;
|
||||
self.capacity = src_size;
|
||||
return self;
|
||||
}
|
||||
|
||||
void
|
||||
vec_string_push_back(vec_string* ptr, const String val, err_t* err)
|
||||
{
|
||||
err_t status = ERR_T_INIT;
|
||||
String* res;
|
||||
__null_check(ptr, &status);
|
||||
if ((status.flags & ERR_VEC_NULL) != 0)
|
||||
{
|
||||
__origin_override(err, "PUSH_BACK");
|
||||
err->flags |= ERR_VEC_NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
if (ptr->size + 1 > ptr->max_size)
|
||||
{
|
||||
__origin_override(err, "PUSH_BACK");
|
||||
err->flags |= ERR_SIZE_OVERFLOW;
|
||||
return;
|
||||
}
|
||||
|
||||
if ((status.flags & ERR_BUF_NULL) != 0)
|
||||
{
|
||||
res = malloc(1 * sizeof(String));
|
||||
if (res == nullptr)
|
||||
{
|
||||
__origin_override(err, "PUSH_BACK");
|
||||
err->flags |= ERR_ALLOC_FAIL;
|
||||
return;
|
||||
}
|
||||
ptr->array = res;
|
||||
ptr->capacity = 1;
|
||||
ptr->size = 0;
|
||||
}
|
||||
|
||||
else if (ptr->size + 1 > ptr->capacity)
|
||||
{
|
||||
size_t dst_cap = (ptr->capacity / 2) + ptr->capacity;
|
||||
if (dst_cap == ptr->capacity)
|
||||
{
|
||||
dst_cap++;
|
||||
}
|
||||
if (dst_cap > ptr->max_size)
|
||||
{
|
||||
dst_cap = ptr->max_size;
|
||||
DEBUG(
|
||||
"Capacity cannot be grown any further due "
|
||||
"to hitting max size");
|
||||
}
|
||||
res = realloc(ptr->array, dst_cap * sizeof(String));
|
||||
if (res == nullptr)
|
||||
{
|
||||
__origin_override(err, "PUSH_BACK");
|
||||
err->flags |= ERR_SIZE_OVERFLOW;
|
||||
return;
|
||||
}
|
||||
ptr->array = res;
|
||||
ptr->capacity = dst_cap;
|
||||
}
|
||||
ptr->array[ptr->size] = val;
|
||||
ptr->size++;
|
||||
return;
|
||||
}
|
||||
|
||||
void
|
||||
vec_string_pop_back(vec_string* ptr, err_t* err)
|
||||
{
|
||||
if (__null_check(ptr, err) != 0)
|
||||
{
|
||||
__origin_override(err, "POP_BACK");
|
||||
return;
|
||||
}
|
||||
|
||||
if (ptr->size == 0)
|
||||
{
|
||||
__origin_override(err, "POP_BACK");
|
||||
err->flags |= ERR_SIZE_ZERO;
|
||||
return;
|
||||
}
|
||||
|
||||
ptr->array[ptr->size - 1] = (String)STR_INIT;
|
||||
ptr->size--;
|
||||
}
|
||||
|
||||
void
|
||||
vec_string_reserve(vec_string* ptr, const size_t capacity, err_t* err)
|
||||
{
|
||||
err_t status = ERR_T_INIT;
|
||||
if (__null_check(ptr, &status) != 0)
|
||||
{
|
||||
if ((status.flags & ERR_VEC_NULL) != 0)
|
||||
{
|
||||
__origin_override(err, "RESERVE");
|
||||
err->flags |= ERR_VEC_NULL;
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (ptr->max_size < capacity)
|
||||
{
|
||||
__origin_override(err, "RESERVE");
|
||||
err->flags |= ERR_SIZE_OVERFLOW;
|
||||
return;
|
||||
}
|
||||
if (capacity == 0)
|
||||
{
|
||||
__origin_override(err, "RESERVE");
|
||||
err->flags |= ERR_SIZE_ZERO;
|
||||
return;
|
||||
}
|
||||
|
||||
String* res = realloc(ptr->array, capacity * sizeof(String));
|
||||
if (res == nullptr)
|
||||
{
|
||||
__origin_override(err, "RESERVE");
|
||||
err->flags |= ERR_ALLOC_FAIL;
|
||||
return;
|
||||
}
|
||||
ptr->array = res;
|
||||
ptr->capacity = capacity;
|
||||
if (ptr->size > capacity)
|
||||
{
|
||||
ptr->size = capacity;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
void
|
||||
vec_string_shrink_to_fit(vec_string* ptr, err_t* err)
|
||||
{
|
||||
err_t status = ERR_T_INIT;
|
||||
if (__null_check(ptr, &status) != 0)
|
||||
{
|
||||
__origin_override(err, "SHRINK_TO_FIT");
|
||||
err->flags |= status.flags;
|
||||
return;
|
||||
}
|
||||
if (ptr->size == 0)
|
||||
{
|
||||
__origin_override(err, "SHRINK_TO_FIT");
|
||||
err->flags |= ERR_SIZE_ZERO;
|
||||
return;
|
||||
}
|
||||
vec_string_reserve(ptr, ptr->size, err);
|
||||
}
|
||||
|
||||
void
|
||||
vec_string_swap(vec_string* ptr_a, vec_string* ptr_b, err_t* err)
|
||||
{
|
||||
err_t status_1 = ERR_T_INIT, status_2 = ERR_T_INIT;
|
||||
if ((__null_check(ptr_a, &status_1) & ERR_VEC_NULL) != 0 ||
|
||||
(__null_check(ptr_b, &status_2) & ERR_VEC_NULL) != 0)
|
||||
{
|
||||
__origin_override(err, "SWAP");
|
||||
err->flags |= ERR_VEC_NULL;
|
||||
return;
|
||||
}
|
||||
vec_string self = *ptr_a;
|
||||
*ptr_a = *ptr_b;
|
||||
*ptr_b = self;
|
||||
return;
|
||||
}
|
||||
|
||||
const String*
|
||||
vec_string_data(const vec_string* ptr, err_t* err)
|
||||
{
|
||||
err_t status = ERR_T_INIT;
|
||||
if (__null_check(ptr, &status) != 0)
|
||||
{
|
||||
__origin_override(err, "DATA");
|
||||
err->flags |= status.flags;
|
||||
return nullptr;
|
||||
}
|
||||
return &ptr->array[0];
|
||||
}
|
||||
|
||||
size_t
|
||||
vec_string_size(const vec_string* ptr, err_t* err)
|
||||
{
|
||||
err_t status = ERR_T_INIT;
|
||||
if (__null_check(ptr, &status) != 0)
|
||||
{
|
||||
__origin_override(err, "SIZE");
|
||||
err->flags |= status.flags;
|
||||
return 0;
|
||||
}
|
||||
return ptr->size;
|
||||
}
|
||||
|
||||
size_t
|
||||
vec_string_capacity(const vec_string* ptr, err_t* err)
|
||||
{
|
||||
err_t status = ERR_T_INIT;
|
||||
if (__null_check(ptr, &status) != 0)
|
||||
{
|
||||
__origin_override(err, "CAPACITY");
|
||||
err->flags |= status.flags;
|
||||
return 0;
|
||||
}
|
||||
return ptr->capacity;
|
||||
}
|
||||
|
||||
size_t
|
||||
vec_string_max_size(const vec_string* ptr, err_t* err)
|
||||
{
|
||||
err_t status = ERR_T_INIT;
|
||||
if (__null_check(ptr, &status) != 0)
|
||||
{
|
||||
__origin_override(err, "MAX_SIZE");
|
||||
err->flags |= status.flags;
|
||||
return 0;
|
||||
}
|
||||
return ptr->max_size;
|
||||
}
|
||||
|
||||
void
|
||||
vec_string_delete(vec_string* ptr, err_t* err)
|
||||
{
|
||||
err_t status = ERR_T_INIT;
|
||||
if (__null_check(ptr, &status) != 0)
|
||||
{
|
||||
__origin_override(err, "DELETE");
|
||||
err->flags |= status.flags;
|
||||
return;
|
||||
}
|
||||
if (ptr->array != nullptr)
|
||||
{
|
||||
free(ptr->array);
|
||||
ptr->array = nullptr;
|
||||
}
|
||||
ptr->size = 0;
|
||||
ptr->capacity = 0;
|
||||
}
|
||||
|
||||
void
|
||||
vec_string_clear(vec_string* ptr, err_t* err)
|
||||
{
|
||||
err_t status = ERR_T_INIT;
|
||||
if (__null_check(ptr, &status) != 0)
|
||||
{
|
||||
__origin_override(err, "CLEAR");
|
||||
err->flags |= status.flags;
|
||||
return;
|
||||
}
|
||||
if (ptr->size > 0)
|
||||
{
|
||||
memset(ptr->array, 0, ptr->size * (sizeof(String)));
|
||||
ptr->size = 0;
|
||||
}
|
||||
}
|
||||
|
||||
String*
|
||||
vec_string_at(const vec_string* ptr, const size_t idx, err_t* err)
|
||||
{
|
||||
err_t status = ERR_T_INIT;
|
||||
if (__null_check(ptr, &status) != 0)
|
||||
{
|
||||
__origin_override(err, "AT");
|
||||
err->flags |= status.flags;
|
||||
return nullptr;
|
||||
}
|
||||
if (idx >= ptr->size)
|
||||
{
|
||||
__origin_override(err, "AT");
|
||||
err->flags |= ERR_OUT_OF_BOUNDS;
|
||||
return nullptr;
|
||||
}
|
||||
return &ptr->array[idx];
|
||||
}
|
||||
|
||||
size_t
|
||||
vec_string_begin(const vec_string* ptr, err_t* err)
|
||||
{
|
||||
err_t status = ERR_T_INIT;
|
||||
if (__null_check(ptr, &status) != 0)
|
||||
{
|
||||
__origin_override(err, "BEGIN");
|
||||
err->flags |= status.flags;
|
||||
return status.flags;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t
|
||||
vec_string_end(const vec_string* ptr, err_t* err)
|
||||
{
|
||||
err_t status = ERR_T_INIT;
|
||||
if (__null_check(ptr, &status) != 0)
|
||||
{
|
||||
__origin_override(err, "END");
|
||||
err->flags |= status.flags;
|
||||
return status.flags;
|
||||
}
|
||||
if (ptr->size == 0)
|
||||
{
|
||||
__origin_override(err, "END");
|
||||
err->flags |= ERR_SIZE_ZERO;
|
||||
return status.flags;
|
||||
}
|
||||
return (size_t)(ptr->size - 1);
|
||||
}
|
||||
|
||||
String
|
||||
vec_string_front(const vec_string* ptr, err_t* err)
|
||||
{
|
||||
err_t status = ERR_T_INIT;
|
||||
String tmp = STR_INIT;
|
||||
if (__null_check(ptr, &status) != 0)
|
||||
{
|
||||
__origin_override(err, "FRONT");
|
||||
err->flags |= status.flags;
|
||||
return tmp;
|
||||
}
|
||||
if (vec_string_at(ptr, 0, err) == nullptr)
|
||||
{
|
||||
err->flags |= ERR_OUT_OF_BOUNDS;
|
||||
return tmp;
|
||||
}
|
||||
return *vec_string_at(ptr, 0, err);
|
||||
}
|
||||
|
||||
String
|
||||
vec_string_back(const vec_string* ptr, err_t* err)
|
||||
{
|
||||
err_t status = ERR_T_INIT;
|
||||
if (__null_check(ptr, &status) != 0)
|
||||
{
|
||||
__origin_override(err, "BACK");
|
||||
err->flags |= status.flags;
|
||||
return (String)STR_INIT;
|
||||
}
|
||||
if (vec_string_at(ptr, ptr->size - 1, err) == nullptr)
|
||||
{
|
||||
err->flags |= ERR_OUT_OF_BOUNDS;
|
||||
return (String)STR_INIT;
|
||||
}
|
||||
return *vec_string_at(ptr, ptr->size - 1, err);
|
||||
}
|
||||
|
||||
size_t
|
||||
vec_string_empty(const vec_string* ptr, err_t* err)
|
||||
{
|
||||
err_t status = ERR_T_INIT;
|
||||
if (__null_check(ptr, &status) != 0)
|
||||
{
|
||||
__origin_override(err, "EMPTY");
|
||||
err->flags |= status.flags;
|
||||
return status.flags;
|
||||
}
|
||||
if (ptr->size == 0)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
__attribute__((overloadable)) void
|
||||
vec_string_erase(vec_string* ptr, const size_t iter, err_t* err)
|
||||
{
|
||||
err_t status = ERR_T_INIT;
|
||||
if (__null_check(ptr, &status) != 0)
|
||||
{
|
||||
__origin_override(err, "ERASE");
|
||||
err->flags |= status.flags;
|
||||
return;
|
||||
}
|
||||
if (iter >= ptr->size)
|
||||
{
|
||||
__origin_override(err, "ERASE");
|
||||
err->flags |= ERR_OUT_OF_BOUNDS;
|
||||
return;
|
||||
}
|
||||
memmove(&ptr->array[iter], &ptr->array[iter + 1],
|
||||
(ptr->size - iter - 1) * sizeof(String));
|
||||
ptr->array[ptr->size - 1] = (String)STR_INIT;
|
||||
ptr->size--;
|
||||
return;
|
||||
}
|
||||
|
||||
__attribute__((overloadable)) void
|
||||
vec_string_erase(vec_string* ptr, const size_t iter_start,
|
||||
const size_t iter_end, err_t* err)
|
||||
{
|
||||
err_t status = ERR_T_INIT;
|
||||
if (__null_check(ptr, &status) != 0)
|
||||
{
|
||||
__origin_override(err, "ERASE");
|
||||
err->flags |= status.flags;
|
||||
return;
|
||||
}
|
||||
|
||||
if (ptr->size < iter_end || iter_end <= iter_start)
|
||||
{
|
||||
__origin_override(err, "ERASE");
|
||||
err->flags |= ERR_OUT_OF_BOUNDS;
|
||||
return;
|
||||
}
|
||||
size_t diff = iter_end - iter_start;
|
||||
memmove(&ptr->array[iter_start], &ptr->array[iter_end],
|
||||
(ptr->size - iter_end) * sizeof(String));
|
||||
memset(&ptr->array[ptr->size - diff], 0, sizeof(String) * diff);
|
||||
ptr->size -= diff;
|
||||
return;
|
||||
}
|
||||
|
||||
__attribute__((overloadable)) void
|
||||
vec_string_resize(vec_string* ptr, const size_t size, err_t* err)
|
||||
{
|
||||
err_t status = ERR_T_INIT;
|
||||
__null_check(ptr, &status);
|
||||
if ((status.flags & ERR_VEC_NULL) != 0)
|
||||
{
|
||||
__origin_override(err, "RESIZE");
|
||||
err->flags |= ERR_VEC_NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
if (ptr->size == size)
|
||||
{
|
||||
__origin_override(err, "RESIZE");
|
||||
err->flags |= ERR_OUT_OF_BOUNDS;
|
||||
return;
|
||||
}
|
||||
|
||||
else if (size > ptr->max_size)
|
||||
{
|
||||
__origin_override(err, "RESIZE");
|
||||
err->flags |= ERR_SIZE_OVERFLOW;
|
||||
return;
|
||||
}
|
||||
|
||||
else if ((status.flags & ERR_BUF_NULL) != 0 || ptr->size == 0)
|
||||
{
|
||||
size_t max = ptr->max_size;
|
||||
err_t verr = ERR_T_INIT;
|
||||
vec_string_reserve(ptr, size, &verr);
|
||||
if (verr.flags != 0)
|
||||
{
|
||||
__origin_override(err, "RESIZE");
|
||||
err->flags |= verr.flags;
|
||||
return;
|
||||
}
|
||||
if (ptr->capacity != size)
|
||||
{
|
||||
__origin_override(err, "RESIZE");
|
||||
err->flags |= ERR_ALLOC_FAIL;
|
||||
return;
|
||||
}
|
||||
for (size_t i = 0; i < size; i++)
|
||||
{
|
||||
ptr->array[i] = (String)STR_INIT;
|
||||
}
|
||||
ptr->max_size = max;
|
||||
ptr->size = size;
|
||||
return;
|
||||
}
|
||||
else if (size > ptr->capacity)
|
||||
{
|
||||
size_t tmpcp = ptr->capacity;
|
||||
size_t tmpmx = ptr->max_size;
|
||||
err_t verr = ERR_T_INIT;
|
||||
while (size > tmpcp)
|
||||
{
|
||||
tmpcp *= 2;
|
||||
}
|
||||
if (tmpcp > ptr->max_size)
|
||||
{
|
||||
tmpcp = size;
|
||||
}
|
||||
vec_string_reserve(ptr, tmpcp, &verr);
|
||||
if (verr.flags != 0)
|
||||
{
|
||||
__origin_override(err, "RESIZE");
|
||||
err->flags |= verr.flags;
|
||||
return;
|
||||
}
|
||||
if (ptr->capacity != tmpcp)
|
||||
{
|
||||
__origin_override(err, "RESIZE");
|
||||
err->flags |= ERR_ALLOC_FAIL;
|
||||
return;
|
||||
}
|
||||
ptr->max_size = tmpmx;
|
||||
}
|
||||
if (size < ptr->size)
|
||||
{
|
||||
for (size_t i = size; i < ptr->size; i++)
|
||||
{
|
||||
ptr->array[i] = (String)STR_INIT;
|
||||
}
|
||||
}
|
||||
if (ptr->size < size && size <= ptr->capacity)
|
||||
{
|
||||
for (size_t i = ptr->size; i < size; i++)
|
||||
{
|
||||
ptr->array[i] = (String)STR_INIT;
|
||||
}
|
||||
}
|
||||
ptr->size = size;
|
||||
return;
|
||||
}
|
||||
|
||||
__attribute__((overloadable)) void
|
||||
vec_string_resize(vec_string* ptr, const size_t size, const String val,
|
||||
err_t* err)
|
||||
{
|
||||
err_t status = ERR_T_INIT;
|
||||
__null_check(ptr, &status);
|
||||
if ((status.flags & ERR_VEC_NULL) != 0)
|
||||
{
|
||||
__origin_override(err, "RESIZE");
|
||||
err->flags |= ERR_VEC_NULL;
|
||||
return;
|
||||
}
|
||||
if (ptr->size == size)
|
||||
{
|
||||
__origin_override(err, "RESIZE");
|
||||
err->flags |= ERR_OUT_OF_BOUNDS;
|
||||
return;
|
||||
}
|
||||
|
||||
else if (size > ptr->max_size)
|
||||
{
|
||||
__origin_override(err, "RESIZE");
|
||||
err->flags |= ERR_SIZE_OVERFLOW;
|
||||
return;
|
||||
}
|
||||
|
||||
else if ((status.flags & ERR_BUF_NULL) != 0 || ptr->size == 0)
|
||||
{
|
||||
size_t max = ptr->max_size;
|
||||
err_t verr = ERR_T_INIT;
|
||||
vec_string_reserve(ptr, size, &verr);
|
||||
if (verr.flags != 0)
|
||||
{
|
||||
__origin_override(err, "RESIZE");
|
||||
err->flags |= verr.flags;
|
||||
return;
|
||||
}
|
||||
if (ptr->capacity != size)
|
||||
{
|
||||
__origin_override(err, "RESIZE");
|
||||
err->flags |= ERR_ALLOC_FAIL;
|
||||
return;
|
||||
}
|
||||
for (size_t i = 0; i < size; i++)
|
||||
{
|
||||
ptr->array[i] = val;
|
||||
}
|
||||
ptr->max_size = max;
|
||||
ptr->size = size;
|
||||
return;
|
||||
}
|
||||
else if (size > ptr->capacity)
|
||||
{
|
||||
size_t tmpcp = ptr->capacity;
|
||||
size_t tmpmx = ptr->max_size;
|
||||
err_t verr = ERR_T_INIT;
|
||||
while (size > tmpcp)
|
||||
{
|
||||
tmpcp *= 2;
|
||||
}
|
||||
if (tmpcp > ptr->max_size)
|
||||
{
|
||||
tmpcp = size;
|
||||
}
|
||||
vec_string_reserve(ptr, tmpcp, &verr);
|
||||
if (verr.flags != 0)
|
||||
{
|
||||
__origin_override(err, "RESIZE");
|
||||
err->flags |= verr.flags;
|
||||
return;
|
||||
}
|
||||
ptr->max_size = tmpmx;
|
||||
}
|
||||
if (size < ptr->size)
|
||||
{
|
||||
for (size_t i = size; i < ptr->size; i++)
|
||||
{
|
||||
ptr->array[i] = val;
|
||||
}
|
||||
}
|
||||
if (ptr->size < size && size <= ptr->capacity)
|
||||
{
|
||||
for (size_t i = ptr->size; i < size; i++)
|
||||
{
|
||||
ptr->array[i] = val;
|
||||
}
|
||||
}
|
||||
ptr->size = size;
|
||||
return;
|
||||
}
|
||||
|
||||
__attribute__((overloadable)) void
|
||||
vec_string_assign(vec_string* ptr, const vec_string* iterator,
|
||||
const size_t iter_start, const size_t iter_end, err_t* err)
|
||||
{
|
||||
err_t status = ERR_T_INIT;
|
||||
if (__null_check(ptr, &status) != 0 ||
|
||||
__null_check(iterator, &status) != 0)
|
||||
{
|
||||
__origin_override(err, "ASSIGN");
|
||||
err->flags |= status.flags;
|
||||
return;
|
||||
}
|
||||
if (ptr->array == iterator->array)
|
||||
{
|
||||
__origin_override(err, "ASSIGN");
|
||||
err->flags |= ERR_DOUBLE_BUF;
|
||||
return;
|
||||
}
|
||||
if (iterator->size < iter_end || iter_end <= iter_start)
|
||||
{
|
||||
__origin_override(err, "ASSIGN");
|
||||
err->flags |= ERR_OUT_OF_BOUNDS;
|
||||
return;
|
||||
}
|
||||
if (ptr->size > 0)
|
||||
{
|
||||
vec_string_erase(ptr, 0, ptr->size, &status);
|
||||
}
|
||||
if (status.flags != 0)
|
||||
{
|
||||
__origin_override(err, "ASSIGN");
|
||||
err->flags |= status.flags;
|
||||
return;
|
||||
}
|
||||
vec_string_reserve(ptr, (iter_end - iter_start), &status);
|
||||
if (status.flags != 0)
|
||||
{
|
||||
__origin_override(err, "ASSIGN");
|
||||
err->flags |= status.flags;
|
||||
return;
|
||||
}
|
||||
for (size_t i = iter_start; i < iter_end; i++)
|
||||
{
|
||||
String* res = vec_string_at(iterator, i, &status);
|
||||
if (res == nullptr)
|
||||
{
|
||||
err->flags |= ERR_OUT_OF_BOUNDS;
|
||||
return;
|
||||
}
|
||||
vec_string_push_back(ptr, *res, &status);
|
||||
if (status.flags != 0)
|
||||
{
|
||||
__origin_override(err, "ASSIGN");
|
||||
err->flags |= status.flags;
|
||||
return;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
__attribute__((overloadable)) void
|
||||
vec_string_assign(vec_string* ptr, const size_t amount, const String val,
|
||||
err_t* err)
|
||||
{
|
||||
err_t status = ERR_T_INIT;
|
||||
if (__null_check(ptr, &status) != 0)
|
||||
{
|
||||
__origin_override(err, "ASSIGN");
|
||||
err->flags |= status.flags;
|
||||
return;
|
||||
}
|
||||
if (amount == 0)
|
||||
{
|
||||
__origin_override(err, "ASSIGN");
|
||||
err->flags |= ERR_SIZE_ZERO;
|
||||
return;
|
||||
}
|
||||
if (ptr->size > 0)
|
||||
{
|
||||
vec_string_erase(ptr, vec_string_begin(ptr, &status),
|
||||
vec_string_end(ptr, &status) + 1, &status);
|
||||
}
|
||||
if (status.flags != 0)
|
||||
{
|
||||
__origin_override(err, "ASSIGN");
|
||||
err->flags |= status.flags;
|
||||
return;
|
||||
}
|
||||
vec_string_reserve(ptr, amount, &status);
|
||||
if (status.flags != 0)
|
||||
{
|
||||
__origin_override(err, "ASSIGN");
|
||||
err->flags |= status.flags;
|
||||
return;
|
||||
}
|
||||
for (size_t i = 0; i < amount; i++)
|
||||
{
|
||||
vec_string_push_back(ptr, val, &status);
|
||||
if (status.flags != 0)
|
||||
{
|
||||
__origin_override(err, "ASSIGN");
|
||||
err->flags |= status.flags;
|
||||
return;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
__attribute__((overloadable)) void
|
||||
vec_string_insert(vec_string* ptr, const size_t iter, const String val,
|
||||
err_t* err)
|
||||
{
|
||||
err_t status = ERR_T_INIT;
|
||||
__null_check(ptr, &status);
|
||||
if ((status.flags & ERR_VEC_NULL) != 0)
|
||||
{
|
||||
__origin_override(err, "INSERT");
|
||||
err->flags |= status.flags;
|
||||
return;
|
||||
}
|
||||
if ((status.flags & ERR_BUF_NULL) != 0)
|
||||
{
|
||||
String* res = malloc(1 * sizeof(String));
|
||||
if (res == nullptr)
|
||||
{
|
||||
__origin_override(err, "INSERT");
|
||||
err->flags |= ERR_BUF_NULL;
|
||||
return;
|
||||
}
|
||||
ptr->array = res;
|
||||
ptr->capacity = 1;
|
||||
ptr->array[0] = val;
|
||||
ptr->size = 1;
|
||||
return;
|
||||
}
|
||||
if (ptr->max_size < ptr->size + 1)
|
||||
{
|
||||
__origin_override(err, "INSERT");
|
||||
err->flags |= ERR_SIZE_OVERFLOW;
|
||||
return;
|
||||
}
|
||||
if (iter > ptr->size)
|
||||
{
|
||||
__origin_override(err, "INSERT");
|
||||
err->flags |= ERR_OUT_OF_BOUNDS;
|
||||
return;
|
||||
}
|
||||
|
||||
String empty = STR_INIT;
|
||||
vec_string_push_back(ptr, empty, &status);
|
||||
if (status.flags != 0)
|
||||
{
|
||||
__origin_override(err, "INSERT");
|
||||
err->flags |= status.flags;
|
||||
return;
|
||||
}
|
||||
for (size_t i = ptr->size - 1; i > iter; i--)
|
||||
{
|
||||
ptr->array[i] = ptr->array[i - 1];
|
||||
}
|
||||
ptr->array[iter] = val;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
__attribute__((overloadable)) void
|
||||
vec_string_insert(vec_string* ptr, const size_t iter, const size_t amount,
|
||||
const String val, err_t* err)
|
||||
{
|
||||
err_t status = ERR_T_INIT;
|
||||
__null_check(ptr, &status);
|
||||
if ((status.flags & ERR_VEC_NULL) != 0)
|
||||
{
|
||||
__origin_override(err, "INSERT");
|
||||
err->flags |= status.flags;
|
||||
return;
|
||||
}
|
||||
if (iter > ptr->size)
|
||||
{
|
||||
__origin_override(err, "INSERT");
|
||||
err->flags |= ERR_OUT_OF_BOUNDS;
|
||||
return;
|
||||
}
|
||||
if (amount == 0)
|
||||
{
|
||||
__origin_override(err, "INSERT");
|
||||
err->flags |= ERR_SIZE_ZERO;
|
||||
return;
|
||||
}
|
||||
for (size_t i = iter; i < iter + amount; i++)
|
||||
{
|
||||
vec_string_insert(ptr, i, val, &status);
|
||||
if (status.flags != 0)
|
||||
{
|
||||
__origin_override(err, "INSERT");
|
||||
err->flags |= status.flags;
|
||||
return;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
__attribute__((overloadable)) void
|
||||
vec_string_insert(vec_string* ptr, const vec_string* iterator,
|
||||
const size_t iter, const size_t iter_start,
|
||||
const size_t iter_end, err_t* err)
|
||||
{
|
||||
err_t status = ERR_T_INIT;
|
||||
__null_check(ptr, &status);
|
||||
__null_check(iterator, &status);
|
||||
if ((status.flags & (ERR_VEC_NULL | ERR_BUF_NULL)) != 0)
|
||||
{
|
||||
__origin_override(err, "INSERT");
|
||||
err->flags |= status.flags;
|
||||
return;
|
||||
}
|
||||
if (iter_end <= iter_start || iter_end > iterator->size ||
|
||||
iter > ptr->size)
|
||||
{
|
||||
__origin_override(err, "INSERT");
|
||||
err->flags |= ERR_OUT_OF_BOUNDS;
|
||||
return;
|
||||
}
|
||||
if (ptr->array == iterator->array)
|
||||
{
|
||||
__origin_override(err, "INSERT");
|
||||
err->flags |= ERR_DOUBLE_BUF;
|
||||
return;
|
||||
}
|
||||
for (size_t i = iter_start; i < iter_end; i++)
|
||||
{
|
||||
vec_string_insert(ptr, iter + (i - iter_start),
|
||||
iterator->array[i], &status);
|
||||
if (status.flags != 0)
|
||||
{
|
||||
__origin_override(err, "INSERT");
|
||||
err->flags |= status.flags;
|
||||
return;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
+91
-11
@@ -1,12 +1,92 @@
|
||||
#include <utils.h>
|
||||
#include <libvec/utils.h>
|
||||
#include <stdio.h>
|
||||
|
||||
const char* error_messages[] = {
|
||||
[ERR_ALLOC_FAIL] = "Calloc :- Failed to allocate",
|
||||
[ERR_BUF_NULL] = "Buffer :- NULL",
|
||||
[ERR_SIZE_ZERO] = "Size :- Size is or is less than 0 or invalid",
|
||||
[ERR_VECTOR_NULL] = "Vector :- Given vector is null",
|
||||
[ERR_MAX_PASSED] = "Max :- Vector Max value is overloaded",
|
||||
[ERR_OUT_OF_BOUNDS] = "Bounds:- Value is out of bounds",
|
||||
[ERR_NULL] = "Null:- Vector or buffer is null",
|
||||
[ERR_DOUBLE_BUF] = "Buffer :- Both buffers are copies of each other",
|
||||
};
|
||||
const char*
|
||||
vec_get_error_desc(ERROR_CODES err)
|
||||
{
|
||||
switch (err)
|
||||
{
|
||||
#define X(name, val, desc) \
|
||||
case name: \
|
||||
return desc;
|
||||
ERROR_LIST(X)
|
||||
#undef X
|
||||
default:
|
||||
return "Unknown";
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
vec_print_errs(const err_t err)
|
||||
{
|
||||
if (err.flags == SUCCESS)
|
||||
{
|
||||
printf("%s: %s\n", err.origin, vec_get_error_desc(SUCCESS));
|
||||
return;
|
||||
}
|
||||
{
|
||||
#define X(name, val, desc) \
|
||||
if ((val) != 0 && ((err.flags) & (val))) \
|
||||
{ \
|
||||
printf("%s\n", vec_get_error_desc(name)); \
|
||||
}
|
||||
ERROR_LIST(X)
|
||||
#undef X
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
vec_print_bits(unsigned int num)
|
||||
{
|
||||
unsigned int total_bits = sizeof(num) * 8;
|
||||
|
||||
for (unsigned int i = total_bits - 1; i >= 0; i--)
|
||||
{
|
||||
unsigned int bit = (num >> i) & 1;
|
||||
printf("%d ", bit);
|
||||
|
||||
if (i % 8 == 0)
|
||||
{
|
||||
printf(" ");
|
||||
}
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
size_t
|
||||
__origin_override(err_t* status, char* str)
|
||||
{
|
||||
if (status == nullptr)
|
||||
{
|
||||
return ERR_ERR_T_NULL;
|
||||
}
|
||||
if (status->origin != nullptr)
|
||||
{
|
||||
status->flags |= ERR_ORIGIN_UNALTERABLE;
|
||||
return status->flags;
|
||||
}
|
||||
else if (str == nullptr)
|
||||
{
|
||||
status->flags |= ERR_STR_NULL;
|
||||
return status->flags;
|
||||
}
|
||||
else
|
||||
{
|
||||
status->origin = str;
|
||||
return status->flags;
|
||||
}
|
||||
}
|
||||
|
||||
__attribute__((overloadable)) size_t
|
||||
__null_check(const char* ptr, err_t* status)
|
||||
{
|
||||
if (status == nullptr)
|
||||
{
|
||||
return ERR_ERR_T_NULL;
|
||||
}
|
||||
if (ptr == nullptr)
|
||||
{
|
||||
status->flags |= ERR_BUF_NULL;
|
||||
}
|
||||
return status->flags;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "char/char.h"
|
||||
#include "utils/utils.h"
|
||||
|
||||
int
|
||||
LLVMFuzzerTestOneInput(const uint8_t* data, size_t size)
|
||||
{
|
||||
if (size < 2) return 0;
|
||||
|
||||
err_t err = ERR_T_INIT;
|
||||
_VecCharInternal vec = VEC_INIT;
|
||||
|
||||
// Use input bytes to drive arbitrary vector operations
|
||||
for (size_t i = 0; i < size; i++)
|
||||
{
|
||||
uint8_t op = data[i] % 5;
|
||||
switch (op)
|
||||
{
|
||||
case 0:
|
||||
_vec_char_push_back(&vec, (char)data[i], &err);
|
||||
break;
|
||||
case 1:
|
||||
_vec_char_pop_back(&vec, &err);
|
||||
break;
|
||||
case 2:
|
||||
if (vec._internal_size > 0)
|
||||
{
|
||||
size_t idx = (size_t)data[i] %
|
||||
vec._internal_size;
|
||||
_vec_char_erase(&vec, idx, &err);
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
_vec_char_reserve(&vec, (size_t)data[i], &err);
|
||||
break;
|
||||
case 4:
|
||||
_vec_char_shrink_to_fit(&vec, &err);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
_vec_char_delete(&vec, &err);
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,104 @@
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "char/char.h"
|
||||
#include "utils/utils.h"
|
||||
|
||||
static void
|
||||
test_empty_vector_underflows(void)
|
||||
{
|
||||
printf("[RUN] Testing empty vector boundaries & underflows...\n");
|
||||
err_t err = ERR_T_INIT;
|
||||
_VecCharInternal vec = VEC_INIT;
|
||||
|
||||
// 1. Pop back on an empty container must not underflow size_t (0 - 1)
|
||||
_vec_char_pop_back(&vec, &err);
|
||||
assert((err.flags & ERR_SIZE_ZERO) != 0 || err.flags != 0);
|
||||
|
||||
// 2. Reading back/end of an empty container
|
||||
err = (err_t)ERR_T_INIT;
|
||||
_vec_char_back(&vec, &err);
|
||||
assert(err.flags != 0);
|
||||
|
||||
// 3. Reserving 0 capacity
|
||||
err = (err_t)ERR_T_INIT;
|
||||
_vec_char_reserve(&vec, 0, &err);
|
||||
assert((err.flags & ERR_SIZE_ZERO) != 0);
|
||||
|
||||
_vec_char_delete(&vec, &err);
|
||||
printf("[PASS] Empty vector boundaries handled.\n");
|
||||
}
|
||||
|
||||
static void
|
||||
test_push_growth_and_shrink(void)
|
||||
{
|
||||
printf("[RUN] Testing push, capacity growth, and indexing...\n");
|
||||
err_t err = ERR_T_INIT;
|
||||
_VecCharInternal vec = VEC_INIT;
|
||||
|
||||
// Push elements to trigger initial malloc then realloc
|
||||
for (char c = 'a'; c <= 'z'; c++)
|
||||
{
|
||||
_vec_char_push_back(&vec, c, &err);
|
||||
assert(err.flags == 0);
|
||||
}
|
||||
assert(vec._internal_size == 26);
|
||||
assert(vec._internal_capacity >= 26);
|
||||
|
||||
// Verify boundary indexing
|
||||
assert(_vec_char_front(&vec, &err) == 'a');
|
||||
assert(_vec_char_back(&vec, &err) == 'z');
|
||||
|
||||
// Index out of bounds check
|
||||
err = (err_t)ERR_T_INIT;
|
||||
_vec_char_at(&vec, 26, &err);
|
||||
assert(err.flags != 0);
|
||||
|
||||
// Shrink to fit verification
|
||||
err = (err_t)ERR_T_INIT;
|
||||
_vec_char_shrink_to_fit(&vec, &err);
|
||||
assert(vec._internal_capacity == 26);
|
||||
|
||||
_vec_char_delete(&vec, &err);
|
||||
printf("[PASS] Growth and indexing passed.\n");
|
||||
}
|
||||
|
||||
static void
|
||||
test_range_insert_and_erase(void)
|
||||
{
|
||||
printf("[RUN] Testing range insertions and erasures...\n");
|
||||
err_t err = ERR_T_INIT;
|
||||
_VecCharInternal vec = VEC_INIT;
|
||||
|
||||
_vec_char_push_back(&vec, 'A', &err);
|
||||
_vec_char_push_back(&vec, 'B', &err);
|
||||
_vec_char_push_back(&vec, 'E', &err);
|
||||
|
||||
// Single insert between 'B' and 'E' at index 2
|
||||
_vec_char_insert(&vec, 2, 'C', &err);
|
||||
assert(vec._internal_size == 4);
|
||||
assert(*_vec_char_at(&vec, 2, &err) == 'C');
|
||||
|
||||
// Erase test
|
||||
_vec_char_erase(&vec, 2, &err);
|
||||
assert(vec._internal_size == 3);
|
||||
assert(*_vec_char_at(&vec, 2, &err) == 'E');
|
||||
|
||||
// Inverted range check: iter_end <= iter_start must report error
|
||||
err = (err_t)ERR_T_INIT;
|
||||
_vec_char_erase(&vec, 2, 1, &err);
|
||||
assert(err.flags != 0);
|
||||
|
||||
_vec_char_delete(&vec, &err);
|
||||
printf("[PASS] Range insert and erase passed.\n");
|
||||
}
|
||||
|
||||
int
|
||||
main(void)
|
||||
{
|
||||
test_empty_vector_underflows();
|
||||
test_push_growth_and_shrink();
|
||||
test_range_insert_and_erase();
|
||||
printf("\nAll char vector edge-case tests passed cleanly!\n");
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,689 @@
|
||||
#include <assert.h>
|
||||
#include <int/int.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <utils/utils.h>
|
||||
|
||||
#if defined(__has_feature)
|
||||
#if __has_feature(address_sanitizer)
|
||||
const char*
|
||||
__asan_default_options(void)
|
||||
{
|
||||
return "allocator_may_return_null=1";
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* =========================================================================
|
||||
* 1. BASIC LIFECYCLE & NULL GUARDS
|
||||
* ========================================================================= */
|
||||
|
||||
static void
|
||||
test_push_back_single(void)
|
||||
{
|
||||
printf("[1] Testing push_back with a single integer...\n");
|
||||
_VecIntInternal vec = VEC_INIT;
|
||||
err_t err = ERR_T_INIT;
|
||||
_vec_int_push_back(&vec, 65, &err);
|
||||
|
||||
assert(err.flags == 0);
|
||||
assert(vec._internal_size == 1);
|
||||
assert(vec._internal_arr[0] == 65);
|
||||
_vec_int_delete(&vec, &err);
|
||||
printf("Passed\n");
|
||||
}
|
||||
|
||||
static void
|
||||
test_null_guards(void)
|
||||
{
|
||||
printf("[2] Testing null pointer checks in __null_check...\n");
|
||||
_VecIntInternal vec = VEC_INIT;
|
||||
err_t err = ERR_T_INIT;
|
||||
|
||||
size_t res1 = __null_check(&vec, nullptr);
|
||||
assert(res1 == ERR_ERR_T_NULL);
|
||||
|
||||
size_t res2 = __null_check((const _VecIntInternal*)nullptr, &err);
|
||||
assert(res2 == ERR_VEC_NULL);
|
||||
assert((err.flags & ERR_VEC_NULL) != 0);
|
||||
|
||||
err = (err_t)ERR_T_INIT;
|
||||
size_t res3 = __null_check(&vec, &err);
|
||||
assert(res3 == ERR_BUF_NULL);
|
||||
assert((err.flags & ERR_BUF_NULL) != 0);
|
||||
|
||||
err = (err_t)ERR_T_INIT;
|
||||
size_t res4 = __null_check(vec._internal_arr, &err);
|
||||
assert(res4 == ERR_BUF_NULL);
|
||||
assert((err.flags & ERR_BUF_NULL) != 0);
|
||||
|
||||
err = (err_t)ERR_T_INIT;
|
||||
size_t res5 = __null_check((const int*)nullptr, nullptr);
|
||||
assert(res5 == ERR_ERR_T_NULL);
|
||||
|
||||
printf("Passed\n");
|
||||
}
|
||||
|
||||
static void
|
||||
test_origin_override(void)
|
||||
{
|
||||
printf("[3] Testing __origin_override...\n");
|
||||
err_t err = ERR_T_INIT;
|
||||
|
||||
size_t res_null_status = __origin_override(nullptr, "TEST");
|
||||
assert(res_null_status == ERR_ERR_T_NULL);
|
||||
|
||||
size_t res = __origin_override(&err, nullptr);
|
||||
assert(res == ERR_STR_NULL);
|
||||
assert((err.flags & ERR_STR_NULL) != 0);
|
||||
|
||||
err = (err_t)ERR_T_INIT;
|
||||
__origin_override(&err, "INITIAL");
|
||||
assert(strcmp(err.origin, "INITIAL") == 0);
|
||||
|
||||
// Override existing origin -> ERR_ORIGIN_UNALTERABLE
|
||||
__origin_override(&err, "REPLACED");
|
||||
assert((err.flags & ERR_ORIGIN_UNALTERABLE) != 0);
|
||||
assert(strcmp(err.origin, "INITIAL") == 0);
|
||||
|
||||
printf("Passed\n");
|
||||
}
|
||||
|
||||
/* =========================================================================
|
||||
* 2. PRINT & COPY
|
||||
* ========================================================================= */
|
||||
|
||||
static void
|
||||
test_print_vec(void)
|
||||
{
|
||||
_VecIntInternal vec = VEC_INIT;
|
||||
err_t err = ERR_T_INIT;
|
||||
|
||||
printf("[4] Testing print_vec with null vector\n");
|
||||
_vec_int_print_vec(nullptr, &err);
|
||||
assert((err.flags & ERR_VEC_NULL) != 0);
|
||||
printf("Passed\n");
|
||||
|
||||
printf("[5] Testing print_vec with null array\n");
|
||||
err = (err_t)ERR_T_INIT;
|
||||
_vec_int_print_vec(&vec, &err);
|
||||
assert((err.flags & ERR_BUF_NULL) != 0);
|
||||
printf("Passed\n");
|
||||
|
||||
printf("[6] Testing print_vec with null err\n");
|
||||
_vec_int_print_vec(&vec, nullptr);
|
||||
printf("Passed\n");
|
||||
|
||||
printf("[7] Testing print_vec with valid parameters\n");
|
||||
err = (err_t)ERR_T_INIT;
|
||||
_vec_int_push_back(&vec, 1, &err);
|
||||
_vec_int_push_back(&vec, 2, &err);
|
||||
_vec_int_print_vec(&vec, &err);
|
||||
_vec_int_delete(&vec, &err);
|
||||
printf("Passed\n");
|
||||
}
|
||||
|
||||
static void
|
||||
test_cpy(void)
|
||||
{
|
||||
int arr[3] = { 1, 2, 3 };
|
||||
_VecIntInternal blank = VEC_INIT;
|
||||
|
||||
printf("[8] Testing _vec_int_cpy with null source arr\n");
|
||||
err_t err1 = ERR_T_INIT;
|
||||
_VecIntInternal tmp = _vec_int_cpy(nullptr, 3, &err1);
|
||||
assert(blank._internal_arr == tmp._internal_arr &&
|
||||
blank._internal_capacity == tmp._internal_capacity &&
|
||||
blank._internal_size == tmp._internal_size &&
|
||||
blank._internal_max_size == tmp._internal_max_size);
|
||||
assert((err1.flags & ERR_BUF_NULL) != 0);
|
||||
printf("Passed\n");
|
||||
|
||||
printf("[9] Testing _vec_int_cpy with null err\n");
|
||||
_VecIntInternal res2 = _vec_int_cpy(arr, 3, nullptr);
|
||||
assert(blank._internal_arr == res2._internal_arr &&
|
||||
blank._internal_capacity == res2._internal_capacity &&
|
||||
blank._internal_size == res2._internal_size &&
|
||||
blank._internal_max_size == res2._internal_max_size);
|
||||
printf("Passed\n");
|
||||
|
||||
printf("[10] Testing _vec_int_cpy with size 0\n");
|
||||
err_t err3 = ERR_T_INIT;
|
||||
_VecIntInternal res3 = _vec_int_cpy(arr, 0, &err3);
|
||||
assert(blank._internal_arr == res3._internal_arr &&
|
||||
blank._internal_capacity == res3._internal_capacity &&
|
||||
blank._internal_size == res3._internal_size &&
|
||||
blank._internal_max_size == res3._internal_max_size);
|
||||
assert((err3.flags & ERR_SIZE_ZERO) != 0);
|
||||
printf("Passed\n");
|
||||
|
||||
printf("[11] Testing _vec_int_cpy with size exceeding max_size\n");
|
||||
err_t err4 = ERR_T_INIT;
|
||||
_VecIntInternal res4 =
|
||||
_vec_int_cpy(arr, res3._internal_max_size + 1, &err4);
|
||||
assert(blank._internal_arr == res4._internal_arr &&
|
||||
blank._internal_capacity == res4._internal_capacity &&
|
||||
blank._internal_size == res4._internal_size &&
|
||||
blank._internal_max_size == res4._internal_max_size);
|
||||
assert((err4.flags & ERR_SIZE_OVERFLOW) != 0);
|
||||
printf("Passed\n");
|
||||
|
||||
printf("[12] Testing _vec_int_cpy allocation failure\n");
|
||||
err_t err5 = ERR_T_INIT;
|
||||
size_t huge_size = ((size_t)1 << 40);
|
||||
_VecIntInternal res5 = _vec_int_cpy(arr, huge_size, &err5);
|
||||
assert(res5._internal_arr == blank._internal_arr);
|
||||
assert((err5.flags & ERR_ALLOC_FAIL) != 0);
|
||||
printf("Passed\n");
|
||||
|
||||
printf("[13] Testing _vec_int_cpy with valid inputs\n");
|
||||
err_t err = ERR_T_INIT;
|
||||
int res[4] = { 10, 20, 30, 40 };
|
||||
_VecIntInternal vec = _vec_int_cpy(res, 4, &err);
|
||||
assert(err.flags == 0);
|
||||
assert(vec._internal_size == 4);
|
||||
assert(vec._internal_capacity == 4);
|
||||
assert(memcmp(vec._internal_arr, res, sizeof(int) * 4) == 0);
|
||||
_vec_int_delete(&vec, &err);
|
||||
printf("Passed\n");
|
||||
}
|
||||
|
||||
/* =========================================================================
|
||||
* 3. PUSH, POP, CAPACITY & SIZING
|
||||
* ========================================================================= */
|
||||
|
||||
static void
|
||||
test_push_back(void)
|
||||
{
|
||||
printf("[14] Testing _vec_int_push_back null vec\n");
|
||||
err_t err = ERR_T_INIT;
|
||||
_vec_int_push_back(nullptr, 1, &err);
|
||||
assert((err.flags & ERR_VEC_NULL) != 0);
|
||||
printf("Passed\n");
|
||||
|
||||
printf("[15] Testing _vec_int_push_back null err\n");
|
||||
_VecIntInternal vec1 = VEC_INIT;
|
||||
_vec_int_push_back(&vec1, 1, nullptr);
|
||||
assert(vec1._internal_size == 1);
|
||||
_vec_int_delete(&vec1, &err);
|
||||
printf("Passed\n");
|
||||
|
||||
printf("[16] Testing _vec_int_push_back size overflow\n");
|
||||
_VecIntInternal vec2 = VEC_INIT;
|
||||
err_t err2 = ERR_T_INIT;
|
||||
vec2._internal_size = vec2._internal_max_size;
|
||||
_vec_int_push_back(&vec2, 1, &err2);
|
||||
assert((err2.flags & ERR_SIZE_OVERFLOW) != 0);
|
||||
printf("Passed\n");
|
||||
|
||||
printf("[17] Testing push_back capacity growth realloc\n");
|
||||
err_t err3 = ERR_T_INIT;
|
||||
_VecIntInternal vec3 = VEC_INIT;
|
||||
for (int val = 0; val < 10; val++)
|
||||
{
|
||||
_vec_int_push_back(&vec3, val, &err3);
|
||||
assert(err3.flags == 0);
|
||||
}
|
||||
assert(vec3._internal_size == 10);
|
||||
assert(vec3._internal_capacity >= 10);
|
||||
_vec_int_delete(&vec3, &err3);
|
||||
printf("Passed\n");
|
||||
}
|
||||
|
||||
static void
|
||||
test_pop_back(void)
|
||||
{
|
||||
_VecIntInternal vec = VEC_INIT;
|
||||
err_t err = ERR_T_INIT;
|
||||
|
||||
printf("[18] Testing _vec_int_pop_back null vector\n");
|
||||
_vec_int_pop_back(nullptr, &err);
|
||||
assert((err.flags & ERR_VEC_NULL) != 0);
|
||||
printf("Passed\n");
|
||||
|
||||
printf("[19] Testing _vec_int_pop_back size 0\n");
|
||||
err = (err_t)ERR_T_INIT;
|
||||
_vec_int_push_back(&vec, 42, &err);
|
||||
_vec_int_pop_back(&vec,
|
||||
&err); // size is now 0, but buffer is allocated
|
||||
err = (err_t)ERR_T_INIT;
|
||||
_vec_int_pop_back(&vec, &err);
|
||||
assert((err.flags & ERR_SIZE_ZERO) != 0);
|
||||
printf("Passed\n");
|
||||
|
||||
printf("[20] Testing _vec_int_pop_back valid pop\n");
|
||||
err = (err_t)ERR_T_INIT;
|
||||
_vec_int_push_back(&vec, 1, &err);
|
||||
_vec_int_push_back(&vec, 2, &err);
|
||||
assert(vec._internal_size == 2);
|
||||
_vec_int_pop_back(&vec, &err);
|
||||
assert(vec._internal_size == 1);
|
||||
assert(vec._internal_arr[0] == 1);
|
||||
assert(vec._internal_arr[1] == 0);
|
||||
_vec_int_delete(&vec, &err);
|
||||
printf("Passed\n");
|
||||
}
|
||||
|
||||
static void
|
||||
test_reserve(void)
|
||||
{
|
||||
_VecIntInternal vec = VEC_INIT;
|
||||
err_t err = ERR_T_INIT;
|
||||
|
||||
printf("[21] Testing _vec_int_reserve null vector\n");
|
||||
_vec_int_reserve(nullptr, 1, &err);
|
||||
assert((err.flags & ERR_VEC_NULL) != 0);
|
||||
printf("Passed\n");
|
||||
|
||||
printf("[22] Testing _vec_int_reserve capacity 0\n");
|
||||
err = (err_t)ERR_T_INIT;
|
||||
_vec_int_reserve(&vec, 0, &err);
|
||||
assert((err.flags & ERR_SIZE_ZERO) != 0);
|
||||
printf("Passed\n");
|
||||
|
||||
printf("[23] Testing _vec_int_reserve calloc on unallocated buffer\n");
|
||||
err = (err_t)ERR_T_INIT;
|
||||
_vec_int_reserve(&vec, 32, &err);
|
||||
assert(err.flags == 0);
|
||||
assert(vec._internal_capacity == 32);
|
||||
assert(vec._internal_arr != nullptr);
|
||||
printf("Passed\n");
|
||||
|
||||
printf("[24] Testing _vec_int_reserve realloc to larger capacity\n");
|
||||
_vec_int_reserve(&vec, 64, &err);
|
||||
assert(err.flags == 0);
|
||||
assert(vec._internal_capacity == 64);
|
||||
printf("Passed\n");
|
||||
|
||||
printf("[25] Testing _vec_int_reserve truncating size\n");
|
||||
vec._internal_size = 50;
|
||||
_vec_int_reserve(&vec, 20, &err);
|
||||
assert(vec._internal_size == 20);
|
||||
assert(vec._internal_capacity == 20);
|
||||
_vec_int_delete(&vec, &err);
|
||||
printf("Passed\n");
|
||||
}
|
||||
|
||||
static void
|
||||
test_shrink_to_fit(void)
|
||||
{
|
||||
_VecIntInternal vec = VEC_INIT;
|
||||
err_t err = ERR_T_INIT;
|
||||
|
||||
printf("[26] Testing _vec_int_shrink_to_fit null vector\n");
|
||||
_vec_int_shrink_to_fit(nullptr, &err);
|
||||
assert((err.flags & ERR_VEC_NULL) != 0);
|
||||
printf("Passed\n");
|
||||
|
||||
printf(
|
||||
"[27] Testing _vec_int_shrink_to_fit size 0 with allocated "
|
||||
"buffer\n");
|
||||
err = (err_t)ERR_T_INIT;
|
||||
_vec_int_push_back(&vec, 1, &err);
|
||||
_vec_int_pop_back(&vec, &err);
|
||||
err = (err_t)ERR_T_INIT;
|
||||
_vec_int_shrink_to_fit(&vec, &err);
|
||||
assert((err.flags & ERR_SIZE_ZERO) != 0);
|
||||
printf("Passed\n");
|
||||
|
||||
printf("[28] Testing _vec_int_shrink_to_fit normal shrinkage\n");
|
||||
_vec_int_reserve(&vec, 128, &err);
|
||||
for (int val = 0; val < 5; val++)
|
||||
{
|
||||
_vec_int_push_back(&vec, val, &err);
|
||||
}
|
||||
assert(vec._internal_capacity == 128);
|
||||
assert(vec._internal_size == 5);
|
||||
err = (err_t)ERR_T_INIT;
|
||||
_vec_int_shrink_to_fit(&vec, &err);
|
||||
assert(err.flags == 0);
|
||||
assert(vec._internal_capacity == 5);
|
||||
assert(vec._internal_size == 5);
|
||||
_vec_int_delete(&vec, &err);
|
||||
printf("Passed\n");
|
||||
}
|
||||
|
||||
/* =========================================================================
|
||||
* 4. GETTERS, ELEMENT ACCESS & CLEAR
|
||||
* ========================================================================= */
|
||||
|
||||
static void
|
||||
test_getters_and_access(void)
|
||||
{
|
||||
printf("[29] Testing getters, clear, and boundary element access...\n");
|
||||
_VecIntInternal vec = VEC_INIT;
|
||||
err_t err = ERR_T_INIT;
|
||||
|
||||
// 1. Null pointer check
|
||||
assert(_vec_int_data(nullptr, &err) == nullptr);
|
||||
assert((err.flags & ERR_VEC_NULL) != 0);
|
||||
|
||||
err = (err_t)ERR_T_INIT;
|
||||
assert(_vec_int_size(nullptr, &err) == 0);
|
||||
assert((err.flags & ERR_VEC_NULL) != 0);
|
||||
|
||||
err = (err_t)ERR_T_INIT;
|
||||
assert(_vec_int_capacity(nullptr, &err) == 0);
|
||||
assert((err.flags & ERR_VEC_NULL) != 0);
|
||||
|
||||
err = (err_t)ERR_T_INIT;
|
||||
assert(_vec_int_max_size(nullptr, &err) == 0);
|
||||
assert((err.flags & ERR_VEC_NULL) != 0);
|
||||
|
||||
// 2. Unallocated buffer check for empty()
|
||||
err = (err_t)ERR_T_INIT;
|
||||
size_t unalloc_empty = _vec_int_empty(&vec, &err);
|
||||
assert((err.flags & ERR_BUF_NULL) != 0);
|
||||
assert(unalloc_empty != 0);
|
||||
|
||||
// 3. Allocate the buffer and pop so size is 0 with valid arr
|
||||
err = (err_t)ERR_T_INIT;
|
||||
_vec_int_push_back(&vec, 100, &err);
|
||||
_vec_int_pop_back(&vec, &err);
|
||||
err = (err_t)ERR_T_INIT;
|
||||
|
||||
// Now _internal_arr is non-null and size is 0:
|
||||
assert(_vec_int_empty(&vec, &err) == 0);
|
||||
|
||||
// Boundary element access on size 0
|
||||
err = (err_t)ERR_T_INIT;
|
||||
assert(_vec_int_front(&vec, &err) == 0 ||
|
||||
(err.flags & ERR_OUT_OF_BOUNDS) != 0);
|
||||
|
||||
err = (err_t)ERR_T_INIT;
|
||||
assert(_vec_int_back(&vec, &err) == 0 ||
|
||||
(err.flags & ERR_OUT_OF_BOUNDS) != 0);
|
||||
|
||||
// 4. Populate container
|
||||
err = (err_t)ERR_T_INIT;
|
||||
_vec_int_push_back(&vec, 10, &err);
|
||||
_vec_int_push_back(&vec, 20, &err);
|
||||
_vec_int_push_back(&vec, 30, &err);
|
||||
|
||||
assert(_vec_int_size(&vec, &err) == 3);
|
||||
assert(_vec_int_capacity(&vec, &err) >= 3);
|
||||
assert(_vec_int_data(&vec, &err) == vec._internal_arr);
|
||||
assert(_vec_int_front(&vec, &err) == 10);
|
||||
assert(_vec_int_back(&vec, &err) == 30);
|
||||
assert(_vec_int_begin(&vec, &err) == 0);
|
||||
assert(_vec_int_end(&vec, &err) == 2);
|
||||
|
||||
// Out of bounds at()
|
||||
err = (err_t)ERR_T_INIT;
|
||||
assert(_vec_int_at(&vec, 10, &err) == nullptr);
|
||||
assert((err.flags & ERR_OUT_OF_BOUNDS) != 0);
|
||||
|
||||
// Clear container
|
||||
err = (err_t)ERR_T_INIT;
|
||||
_vec_int_clear(&vec, &err);
|
||||
assert(vec._internal_size == 0);
|
||||
assert(vec._internal_arr[0] == 0);
|
||||
|
||||
_vec_int_delete(&vec, &err);
|
||||
assert(vec._internal_arr == nullptr);
|
||||
assert(vec._internal_size == 0);
|
||||
assert(vec._internal_capacity == 0);
|
||||
|
||||
printf("Passed\n");
|
||||
}
|
||||
|
||||
/* =========================================================================
|
||||
* 5. SWAP, ERASE, RESIZE, ASSIGN & INSERT
|
||||
* ========================================================================= */
|
||||
|
||||
static void
|
||||
test_swap(void)
|
||||
{
|
||||
printf("[30] Testing _vec_int_swap...\n");
|
||||
_VecIntInternal a = VEC_INIT;
|
||||
_VecIntInternal b = VEC_INIT;
|
||||
err_t err = ERR_T_INIT;
|
||||
|
||||
// Null vector checks
|
||||
_vec_int_swap(nullptr, &b, &err);
|
||||
assert((err.flags & ERR_VEC_NULL) != 0);
|
||||
|
||||
err = (err_t)ERR_T_INIT;
|
||||
_vec_int_swap(&a, nullptr, &err);
|
||||
assert((err.flags & ERR_VEC_NULL) != 0);
|
||||
|
||||
// Normal swap
|
||||
err = (err_t)ERR_T_INIT;
|
||||
_vec_int_push_back(&a, 100, &err);
|
||||
_vec_int_push_back(&b, 200, &err);
|
||||
_vec_int_push_back(&b, 300, &err);
|
||||
|
||||
_vec_int_swap(&a, &b, &err);
|
||||
assert(a._internal_size == 2);
|
||||
assert(a._internal_arr[0] == 200);
|
||||
assert(b._internal_size == 1);
|
||||
assert(b._internal_arr[0] == 100);
|
||||
|
||||
_vec_int_delete(&a, &err);
|
||||
_vec_int_delete(&b, &err);
|
||||
printf("Passed\n");
|
||||
}
|
||||
|
||||
static void
|
||||
test_erase_variants(void)
|
||||
{
|
||||
printf("[31] Testing _vec_int_erase single & range overloads...\n");
|
||||
_VecIntInternal vec = VEC_INIT;
|
||||
err_t err = ERR_T_INIT;
|
||||
|
||||
for (int val = 0; val <= 5; val++)
|
||||
{
|
||||
_vec_int_push_back(&vec, val, &err);
|
||||
} // {0, 1, 2, 3, 4, 5}
|
||||
|
||||
// Single element erase out of bounds (noop)
|
||||
_vec_int_erase(&vec, 10, &err);
|
||||
assert(vec._internal_size == 6);
|
||||
|
||||
// Erase index 2 (value 2) -> {0, 1, 3, 4, 5}
|
||||
_vec_int_erase(&vec, 2, &err);
|
||||
assert(vec._internal_size == 5);
|
||||
assert(vec._internal_arr[2] == 3);
|
||||
|
||||
// Range erase invalid bounds
|
||||
err = (err_t)ERR_T_INIT;
|
||||
_vec_int_erase(&vec, 4, 2, &err); // iter_end <= iter_start
|
||||
assert((err.flags & ERR_OUT_OF_BOUNDS) != 0);
|
||||
|
||||
err = (err_t)ERR_T_INIT;
|
||||
_vec_int_erase(&vec, 0, 10, &err); // iter_end > size
|
||||
assert((err.flags & ERR_OUT_OF_BOUNDS) != 0);
|
||||
|
||||
// Range erase middle: index 1 through 3 ({0, [1, 3], 4, 5} -> {0, 4,
|
||||
// 5})
|
||||
err = (err_t)ERR_T_INIT;
|
||||
_vec_int_erase(&vec, 1, 3, &err);
|
||||
assert(vec._internal_size == 3);
|
||||
assert(vec._internal_arr[0] == 0);
|
||||
assert(vec._internal_arr[1] == 4);
|
||||
assert(vec._internal_arr[2] == 5);
|
||||
|
||||
_vec_int_delete(&vec, &err);
|
||||
printf("Passed\n");
|
||||
}
|
||||
|
||||
static void
|
||||
test_resize(void)
|
||||
{
|
||||
printf("[32] Testing _vec_int_resize (zero-fill & value-fill)...\n");
|
||||
_VecIntInternal vec = VEC_INIT;
|
||||
err_t err = ERR_T_INIT;
|
||||
|
||||
// Null vector
|
||||
_vec_int_resize((_VecIntInternal*)nullptr, 10, &err);
|
||||
assert((err.flags & ERR_VEC_NULL) != 0);
|
||||
|
||||
// Resize unallocated buffer to size 5
|
||||
err = (err_t)ERR_T_INIT;
|
||||
_vec_int_resize(&vec, 5, &err);
|
||||
assert(err.flags == 0);
|
||||
assert(vec._internal_size == 5);
|
||||
assert(vec._internal_arr[0] == 0);
|
||||
|
||||
// Same size requested
|
||||
err = (err_t)ERR_T_INIT;
|
||||
_vec_int_resize(&vec, 5, &err);
|
||||
assert((err.flags & ERR_OUT_OF_BOUNDS) != 0);
|
||||
|
||||
// Exceeds max size
|
||||
err = (err_t)ERR_T_INIT;
|
||||
_vec_int_resize(&vec, vec._internal_max_size + 1, &err);
|
||||
assert((err.flags & ERR_SIZE_OVERFLOW) != 0);
|
||||
|
||||
// Grow with value fill
|
||||
err = (err_t)ERR_T_INIT;
|
||||
_vec_int_resize(&vec, 8, 5, &err);
|
||||
assert(vec._internal_size == 8);
|
||||
assert(vec._internal_arr[5] == 5);
|
||||
assert(vec._internal_arr[7] == 5);
|
||||
|
||||
// Shrink with value fill
|
||||
err = (err_t)ERR_T_INIT;
|
||||
_vec_int_resize(&vec, 3, 10, &err);
|
||||
assert(vec._internal_size == 3);
|
||||
|
||||
_vec_int_delete(&vec, &err);
|
||||
printf("Passed\n");
|
||||
}
|
||||
|
||||
static void
|
||||
test_assign(void)
|
||||
{
|
||||
printf("[33] Testing _vec_int_assign overloads...\n");
|
||||
_VecIntInternal dst = VEC_INIT;
|
||||
_VecIntInternal src = VEC_INIT;
|
||||
err_t err = ERR_T_INIT;
|
||||
|
||||
// Populate src: 1, 2, 3, 4, 5
|
||||
for (int val = 1; val <= 5; val++)
|
||||
{
|
||||
_vec_int_push_back(&src, val, &err);
|
||||
}
|
||||
|
||||
// Allocate dst buffer first so it is not unallocated
|
||||
_vec_int_push_back(&dst, 999, &err);
|
||||
err = (err_t)ERR_T_INIT;
|
||||
|
||||
// 1. Fill assign: 4 42's
|
||||
_vec_int_assign(&dst, 4, 42, &err);
|
||||
assert(err.flags == 0);
|
||||
assert(dst._internal_size == 4);
|
||||
assert(dst._internal_arr[0] == 42);
|
||||
assert(dst._internal_arr[3] == 42);
|
||||
|
||||
// 2. Fill assign with 0 amount
|
||||
err = (err_t)ERR_T_INIT;
|
||||
_vec_int_assign(&dst, 0, 50, &err);
|
||||
assert((err.flags & ERR_SIZE_ZERO) != 0);
|
||||
|
||||
// 3. Range assign self-buffer check
|
||||
err = (err_t)ERR_T_INIT;
|
||||
_vec_int_assign(&dst, &dst, 0, 2, &err);
|
||||
assert((err.flags & ERR_DOUBLE_BUF) != 0);
|
||||
|
||||
// 4. Range assign invalid sub-range (start >= end)
|
||||
err = (err_t)ERR_T_INIT;
|
||||
_vec_int_assign(&dst, &src, 3, 2, &err);
|
||||
assert((err.flags & ERR_OUT_OF_BOUNDS) != 0);
|
||||
|
||||
// 5. Range assign out of bounds end
|
||||
err = (err_t)ERR_T_INIT;
|
||||
_vec_int_assign(&dst, &src, 0, 10, &err);
|
||||
assert((err.flags & ERR_OUT_OF_BOUNDS) != 0);
|
||||
|
||||
_vec_int_delete(&dst, &err);
|
||||
_vec_int_delete(&src, &err);
|
||||
printf("Passed\n");
|
||||
}
|
||||
|
||||
static void
|
||||
test_insert(void)
|
||||
{
|
||||
printf("[34] Testing _vec_int_insert overloads...\n");
|
||||
_VecIntInternal vec = VEC_INIT;
|
||||
_VecIntInternal other = VEC_INIT;
|
||||
err_t err = ERR_T_INIT;
|
||||
|
||||
// Single insert on unallocated buffer
|
||||
_vec_int_insert(&vec, 0, 500, &err);
|
||||
assert(vec._internal_size == 1);
|
||||
assert(vec._internal_arr[0] == 500);
|
||||
|
||||
// Single insert out of bounds
|
||||
err = (err_t)ERR_T_INIT;
|
||||
_vec_int_insert(&vec, 5, 999, &err);
|
||||
assert((err.flags & ERR_OUT_OF_BOUNDS) != 0);
|
||||
|
||||
// Single insert at middle: index 0 (100, then 500 shifts to 1)
|
||||
err = (err_t)ERR_T_INIT;
|
||||
_vec_int_insert(&vec, 0, 100, &err);
|
||||
assert(vec._internal_size == 2);
|
||||
assert(vec._internal_arr[0] == 100);
|
||||
assert(vec._internal_arr[1] == 500);
|
||||
|
||||
// Repeated insert: insert 3 200s at index 1 -> {100, 200, 200, 200,
|
||||
// 500}
|
||||
_vec_int_insert(&vec, 1, 3, 200, &err);
|
||||
assert(vec._internal_size == 5);
|
||||
assert(vec._internal_arr[1] == 200);
|
||||
assert(vec._internal_arr[3] == 200);
|
||||
assert(vec._internal_arr[4] == 500);
|
||||
|
||||
// Repeated insert amount 0
|
||||
err = (err_t)ERR_T_INIT;
|
||||
_vec_int_insert(&vec, 0, 0, 300, &err);
|
||||
assert((err.flags & ERR_SIZE_ZERO) != 0);
|
||||
|
||||
// Vector-from-vector range insert
|
||||
_vec_int_push_back(&other, 1, &err);
|
||||
_vec_int_push_back(&other, 2, &err);
|
||||
|
||||
// Double buffer check
|
||||
err = (err_t)ERR_T_INIT;
|
||||
_vec_int_insert(&vec, &vec, 0, 0, 1, &err);
|
||||
assert((err.flags & ERR_DOUBLE_BUF) != 0);
|
||||
|
||||
_vec_int_delete(&vec, &err);
|
||||
_vec_int_delete(&other, &err);
|
||||
printf("Passed\n");
|
||||
}
|
||||
|
||||
/* =========================================================================
|
||||
* MAIN TEST RUNNER
|
||||
* ========================================================================= */
|
||||
|
||||
int
|
||||
main(void)
|
||||
{
|
||||
printf("=========================================\n");
|
||||
printf(" Starting Complete libvec Unit Test Suite\n");
|
||||
printf("=========================================\n");
|
||||
|
||||
test_push_back_single();
|
||||
test_null_guards();
|
||||
test_origin_override();
|
||||
test_print_vec();
|
||||
test_cpy();
|
||||
test_push_back();
|
||||
test_pop_back();
|
||||
test_reserve();
|
||||
test_shrink_to_fit();
|
||||
test_getters_and_access();
|
||||
test_swap();
|
||||
test_erase_variants();
|
||||
test_resize();
|
||||
test_assign();
|
||||
test_insert();
|
||||
|
||||
printf("=========================================\n");
|
||||
printf(" All 34 Test Suites Executed Successfully!\n");
|
||||
printf("=========================================\n");
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user