Compare commits
36 Commits
7fff67a1c1
...
master
Author | SHA1 | Date | |
---|---|---|---|
0bb85e6364 | |||
0fb0160b5e | |||
fdb22819b4 | |||
6f79fb9c44 | |||
ef5e3e1706 | |||
8e247c7a0b | |||
ec3bf6061d | |||
41badf33d9 | |||
8c1694d3d9 | |||
055f0bc2f5 | |||
b1e03148b7 | |||
da1725982c | |||
75c2f27f8b | |||
570a5fab88 | |||
296e6467c6 | |||
1d40c785f8 | |||
80af330d1b | |||
3d8f2270ef | |||
2ec675a320 | |||
1a2b697349 | |||
92eefe800b | |||
e8f34b341e | |||
f1e4804167 | |||
a8ea92dd5c | |||
dbaf6d16ce | |||
3bc6e879d8 | |||
8b0463c94a | |||
5fcbb97f7a | |||
93ddf7738c | |||
12d8930b2b | |||
20ce36924e | |||
ade3939e17 | |||
874a2e234b | |||
e49654efb1 | |||
0b5c556f84 | |||
82f5e3b77e |
@@ -14,13 +14,11 @@ jobs:
|
||||
matrix:
|
||||
os: [ubuntu-latest]
|
||||
shared: ["ON", "OFF"]
|
||||
pthread_support: ["ON", "OFF"]
|
||||
posix_support: ["ON", "OFF"]
|
||||
exclude:
|
||||
- posix_support: "OFF"
|
||||
pthread_support: "ON"
|
||||
runs-on: ${{ matrix.os }}
|
||||
name: ${{ matrix.os }} - shared=${{ matrix.shared }}, pthread=${{ matrix.pthread_support }}, posix=${{ matrix.posix_support }}
|
||||
name: ${{ matrix.os }} - shared=${{ matrix.shared }}, posix=${{ matrix.posix_support }}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Install dependencies
|
||||
@@ -31,7 +29,6 @@ jobs:
|
||||
run: |
|
||||
cmake -Bbuild -S . \
|
||||
-DDCFG_BUILD_SHARED=${{ matrix.shared }} \
|
||||
-DDCFG_PTHREAD_SUPPORT=${{ matrix.pthread_support }} \
|
||||
-DDCFG_POSIX_SUPPORT=${{ matrix.posix_support }}
|
||||
- name: Build
|
||||
run: |
|
||||
|
8
.gitignore
vendored
8
.gitignore
vendored
@@ -1,3 +1,9 @@
|
||||
[Bb]uild
|
||||
[Bb]uild*/
|
||||
.cache
|
||||
/*.txt
|
||||
*.o
|
||||
*.so
|
||||
*.a
|
||||
BUILD
|
||||
install
|
||||
result
|
||||
|
106
CMakeLists.txt
106
CMakeLists.txt
@@ -2,55 +2,85 @@ cmake_minimum_required(VERSION 3.10)
|
||||
|
||||
project(DCFG C)
|
||||
|
||||
option(DCFG_POSIX_SUPPORT "Enable POSIX support" ON)
|
||||
option(DCFG_BUILD_PROGRAMS "Build DCFG example programs" ON)
|
||||
option(DCFG_ASAN "Enable AddressSanitizer" OFF)
|
||||
|
||||
set(CMAKE_C_STANDARD 99)
|
||||
set(CMAKE_C_STANDARD_REQUIRED ON)
|
||||
set(CMAKE_C_EXTENSIONS ON) # Would've done OFF but I need typeof (for now)
|
||||
|
||||
option(DCFG_BUILD_SHARED "Build DCFG as a shared library" ON)
|
||||
option(DCFG_PTHREAD_SUPPORT "Enable pthreads support" ON)
|
||||
option(DCFG_POSIX_SUPPORT "Enable POSIX support" ON)
|
||||
set(CMAKE_C_EXTENSIONS OFF)
|
||||
|
||||
find_package(Threads)
|
||||
|
||||
set(SRC_DIR ${CMAKE_CURRENT_SOURCE_DIR}/src)
|
||||
set(INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/include)
|
||||
|
||||
if(DCFG_BUILD_SHARED)
|
||||
add_library(${PROJECT_NAME} SHARED ${SRC_DIR}/dcfg.c)
|
||||
target_include_directories(${PROJECT_NAME} PUBLIC ${INCLUDE_DIR})
|
||||
|
||||
if(DCFG_PTHREAD_SUPPORT)
|
||||
find_package(Threads REQUIRED)
|
||||
target_link_libraries(${PROJECT_NAME} PRIVATE Threads::Threads)
|
||||
target_compile_definitions(${PROJECT_NAME} PRIVATE DCFG_PTHREAD_SUPPORT)
|
||||
if(DCFG_ASAN)
|
||||
if(MSVC)
|
||||
set(ASAN_COMPILE_FLAGS /fsanitize=address)
|
||||
set(ASAN_LINK_FLAGS /fsanitize=address)
|
||||
else()
|
||||
set(ASAN_COMPILE_FLAGS -fsanitize=address -fno-omit-frame-pointer)
|
||||
set(ASAN_LINK_FLAGS -fsanitize=address)
|
||||
endif()
|
||||
if (DCFG_POSIX_SUPPORT)
|
||||
target_compile_definitions(${PROJECT_NAME} PRIVATE DCFG_POSIX_SUPPORT)
|
||||
endif()
|
||||
|
||||
set_target_properties(${PROJECT_NAME} PROPERTIES OUTPUT_NAME "dcfg")
|
||||
install(TARGETS ${PROJECT_NAME} DESTINATION lib)
|
||||
else()
|
||||
add_library(${PROJECT_NAME} STATIC ${SRC_DIR}/dcfg.c)
|
||||
target_include_directories(${PROJECT_NAME} PUBLIC ${INCLUDE_DIR})
|
||||
|
||||
if(DCFG_PTHREAD_SUPPORT)
|
||||
find_package(Threads REQUIRED)
|
||||
target_link_libraries(${PROJECT_NAME} PRIVATE Threads::Threads)
|
||||
target_compile_definitions(${PROJECT_NAME} PRIVATE DCFG_PTHREAD_SUPPORT)
|
||||
endif()
|
||||
if (DCFG_POSIX_SUPPORT)
|
||||
target_compile_definitions(${PROJECT_NAME} PRIVATE DCFG_POSIX_SUPPORT)
|
||||
endif()
|
||||
|
||||
set_target_properties(${PROJECT_NAME} PROPERTIES OUTPUT_NAME "dcfg")
|
||||
install(TARGETS ${PROJECT_NAME} DESTINATION lib)
|
||||
endif()
|
||||
|
||||
# Shared library
|
||||
add_library(${PROJECT_NAME}_shared SHARED ${SRC_DIR}/dcfg.c)
|
||||
target_include_directories(${PROJECT_NAME}_shared PUBLIC ${INCLUDE_DIR})
|
||||
set_target_properties(${PROJECT_NAME}_shared PROPERTIES OUTPUT_NAME "dcfg")
|
||||
|
||||
# Static library
|
||||
add_library(${PROJECT_NAME}_static STATIC ${SRC_DIR}/dcfg.c)
|
||||
target_include_directories(${PROJECT_NAME}_static PUBLIC ${INCLUDE_DIR})
|
||||
set_target_properties(${PROJECT_NAME}_static PROPERTIES OUTPUT_NAME "dcfg")
|
||||
|
||||
foreach(TARGET ${PROJECT_NAME}_shared ${PROJECT_NAME}_static)
|
||||
if(DCFG_POSIX_SUPPORT)
|
||||
target_compile_definitions(${TARGET} PRIVATE DCFG_POSIX_SUPPORT)
|
||||
endif()
|
||||
|
||||
if(MSVC)
|
||||
target_compile_options(${TARGET} PRIVATE /W4 /permissive-)
|
||||
else()
|
||||
target_compile_options(${TARGET} PRIVATE -Wall -Wextra -pedantic -Werror -Wno-newline-eof -Wno-language-extension-token)
|
||||
endif()
|
||||
|
||||
if(NOT MSVC)
|
||||
target_link_libraries(${TARGET} PRIVATE m)
|
||||
endif()
|
||||
|
||||
# AddressSanitizer
|
||||
if(DCFG_ASAN)
|
||||
target_compile_options(${TARGET} PRIVATE ${ASAN_COMPILE_FLAGS})
|
||||
target_link_libraries(${TARGET} PRIVATE ${ASAN_LINK_FLAGS})
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
install(TARGETS ${PROJECT_NAME}_shared ${PROJECT_NAME}_static DESTINATION lib)
|
||||
install(DIRECTORY ${INCLUDE_DIR}/ DESTINATION include)
|
||||
|
||||
if(MSVC)
|
||||
target_compile_options(${PROJECT_NAME} PRIVATE /W4 /permissive-)
|
||||
else()
|
||||
target_compile_options(${PROJECT_NAME} PRIVATE -Wall -Wextra -pedantic -Werror -Wno-newline-eof -Wno-language-extension-token)
|
||||
if(DCFG_BUILD_PROGRAMS)
|
||||
set(PROGRAMS_DIR ${CMAKE_CURRENT_SOURCE_DIR}/programs)
|
||||
file(GLOB PROGRAM_SOURCES "${PROGRAMS_DIR}/*.c")
|
||||
|
||||
foreach(PROG_SRC ${PROGRAM_SOURCES})
|
||||
get_filename_component(PROG_NAME ${PROG_SRC} NAME_WE)
|
||||
add_executable(${PROG_NAME} ${PROG_SRC})
|
||||
target_include_directories(${PROG_NAME} PRIVATE ${INCLUDE_DIR})
|
||||
target_link_libraries(${PROG_NAME} PRIVATE ${PROJECT_NAME}_static)
|
||||
|
||||
if(MSVC)
|
||||
target_compile_options(${PROG_NAME} PRIVATE /W4 /permissive-)
|
||||
else()
|
||||
target_compile_options(${PROG_NAME} PRIVATE -Wall -Wextra -pedantic -Werror -Wno-newline-eof -Wno-language-extension-token)
|
||||
endif()
|
||||
|
||||
if(DCFG_ASAN)
|
||||
target_compile_options(${PROG_NAME} PRIVATE ${ASAN_COMPILE_FLAGS})
|
||||
target_link_libraries(${PROG_NAME} PRIVATE ${ASAN_LINK_FLAGS})
|
||||
endif()
|
||||
|
||||
install(TARGETS ${PROG_NAME} DESTINATION bin)
|
||||
endforeach()
|
||||
endif()
|
||||
|
84
build.sh
Executable file
84
build.sh
Executable file
@@ -0,0 +1,84 @@
|
||||
#!/bin/sh
|
||||
|
||||
set -e
|
||||
|
||||
BUILD_DIR="BUILD"
|
||||
INSTALL_DIR=$PWD/install
|
||||
CFLAGS="-Wall -Wextra -pedantic -Werror -Wno-newline-eof -Wno-language-extension-token -Wno-unused-command-line-argument"
|
||||
BUILD_SHARED=1
|
||||
POSIX_SUPPORT=1
|
||||
BUILD_PROGRAMS=1
|
||||
SRC_DIR="src"
|
||||
INCLUDE_DIR="include"
|
||||
PROGRAMS_DIR="programs"
|
||||
OUTPUT_NAME="libdcfg"
|
||||
|
||||
for arg in "$@"; do
|
||||
case $arg in
|
||||
--debug) CFLAGS="$CFLAGS -g -O0" ;;
|
||||
--release) CFLAGS="$CFLAGS -O2" ;;
|
||||
--no-posix) POSIX_SUPPORT=0 ;;
|
||||
--no-programs) BUILD_PROGRAMS=0 ;;
|
||||
--clean) rm -rf "$BUILD_DIR" "$INSTALL_DIR"; echo "Cleaned."; exit 0 ;;
|
||||
esac
|
||||
done
|
||||
|
||||
# Detect SunOS
|
||||
OS=`uname`
|
||||
echo "Detected os:" $OS
|
||||
SHARED_FLAG="-shared"
|
||||
PIC_FLAG="-fPIC"
|
||||
if [ "$OS" = "SunOS" ]; then
|
||||
SHARED_FLAG="-G"
|
||||
PIC_FLAG="-KPIC"
|
||||
CFLAGS=`echo "$CFLAGS" | sed 's/-pedantic//g'`
|
||||
fi
|
||||
|
||||
# Setup directories
|
||||
mkdir -p "$BUILD_DIR" "$INSTALL_DIR/lib" "$INSTALL_DIR/include" "$INSTALL_DIR/bin"
|
||||
|
||||
# Compiler and linker
|
||||
CC=${CC:-cc}
|
||||
|
||||
if [ "$OS" = "SunOS" ] && [ "$CC" = "cc" ]; then
|
||||
CFLAGS="$CFLAGS -xc99"
|
||||
else
|
||||
CFLAGS="$CFLAGS -std=c99"
|
||||
fi
|
||||
|
||||
if [ "$POSIX_SUPPORT" -eq 1 ]; then
|
||||
CFLAGS="$CFLAGS -DDCFG_POSIX_SUPPORT=1"
|
||||
fi
|
||||
|
||||
CFLAGS="$CFLAGS $PIC_FLAG -lm"
|
||||
|
||||
echo "Building DCFG..."
|
||||
cd "$BUILD_DIR"
|
||||
|
||||
set -x
|
||||
|
||||
# Shared library
|
||||
$CC $CFLAGS $SHARED_FLAG "../$SRC_DIR/dcfg.c" -I"../$INCLUDE_DIR" -o "$OUTPUT_NAME.so" $LIBS
|
||||
|
||||
# Static library
|
||||
$CC -c $CFLAGS "../$SRC_DIR/dcfg.c" -I"../$INCLUDE_DIR" -o dcfg.o
|
||||
if [ "$OS" = "SunOS" ]; then
|
||||
CC -xar -o "$OUTPUT_NAME.a" dcfg.o
|
||||
else
|
||||
ar rcs "$OUTPUT_NAME.a" dcfg.o
|
||||
fi
|
||||
|
||||
|
||||
cp "$OUTPUT_NAME.so" "$INSTALL_DIR/lib/"
|
||||
cp "$OUTPUT_NAME.a" "$INSTALL_DIR/lib/"
|
||||
cp -r "../$INCLUDE_DIR/"* "$INSTALL_DIR/include/"
|
||||
|
||||
if [ "$BUILD_PROGRAMS" -eq 1 ]; then
|
||||
for prog in ../"$PROGRAMS_DIR"/*.c; do
|
||||
prog_name=`basename "$prog" .c`
|
||||
$CC $CFLAGS "$prog" -I"../$INCLUDE_DIR" $OUTPUT_NAME.a $LIBS -o "$prog_name"
|
||||
cp "$prog_name" "$INSTALL_DIR/bin/"
|
||||
done
|
||||
fi
|
||||
|
||||
echo "Done. Installed to $INSTALL_DIR"
|
15
flake.nix
15
flake.nix
@@ -20,7 +20,7 @@
|
||||
};
|
||||
in
|
||||
{
|
||||
devShells.default = pkgs.mkShell.override { stdenv = pkgs.llvmPackages_20.libcxxStdenv; } {
|
||||
devShells.default = pkgs.mkShell {
|
||||
packages = with pkgs; [
|
||||
cmake
|
||||
ninja
|
||||
@@ -28,8 +28,21 @@
|
||||
lldb
|
||||
pkg-config
|
||||
tokei
|
||||
valgrind
|
||||
];
|
||||
};
|
||||
|
||||
packages.default = pkgs.stdenv.mkDerivation {
|
||||
pname = "dcfg";
|
||||
version = "master";
|
||||
src = ./.;
|
||||
|
||||
nativeBuildInputs = [
|
||||
pkgs.cmake
|
||||
pkgs.pkg-config
|
||||
];
|
||||
buildInputs = [ ];
|
||||
};
|
||||
}
|
||||
);
|
||||
}
|
||||
|
@@ -1,9 +1,32 @@
|
||||
/*
|
||||
* Copyright 2025 Slendi <slendi@socopon.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the “Software”), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef DCFG_H
|
||||
#define DCFG_H
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
@@ -17,6 +40,7 @@ typedef struct dcfg_StringView {
|
||||
char const *data;
|
||||
size_t size;
|
||||
} dcfg_StringView;
|
||||
#define dcfg_SV(cstr) ((dcfg_StringView) { .data = cstr, .size = strlen(cstr) })
|
||||
|
||||
typedef void *(*dcfg_AllocFn)(size_t); // This should automatically zero memory.
|
||||
typedef void (*dcfg_FreeFn)(void *);
|
||||
@@ -47,9 +71,19 @@ typedef enum dcfg_ValueKind {
|
||||
dcfg_ValueType_Object,
|
||||
dcfg_ValueType_Array,
|
||||
dcfg_ValueType_Function,
|
||||
dcfg_ValueType_MemberAccess,
|
||||
dcfg_ValueType_FunctionCall,
|
||||
} dcfg_ValueType;
|
||||
|
||||
typedef dcfg_Value *(*dcfg_BuiltIn)(dcfg_Value **argv, size_t argc);
|
||||
|
||||
typedef uint64_t dcfg_Version;
|
||||
#define DCFG_GET_MAJOR(v) (((v) >> 48) & 0xFFFF)
|
||||
#define DCFG_GET_MINOR(v) (((v) >> 32) & 0xFFFF)
|
||||
#define DCFG_GET_PATCH(v) ((v) & 0xFFFFFFFF)
|
||||
|
||||
dcfg_Version dcfg_get_version(void);
|
||||
|
||||
dcfg_Instance *dcfg_make_instance(dcfg_InstanceCreateInfo const *create_info);
|
||||
void dcfg_destroy_instance(dcfg_Instance *instance);
|
||||
|
||||
@@ -75,6 +109,8 @@ bool dcfg_Value_get_object_field_ex(dcfg_Value *value,
|
||||
dcfg_StringView const key, dcfg_Value **out_value, bool const evaluate);
|
||||
bool dcfg_Value_get_array_item_ex(dcfg_Value *value, size_t const index,
|
||||
dcfg_Value **out_value, bool const evaluate);
|
||||
bool dcfg_Value_get_function_body_ex(
|
||||
dcfg_Value *value, dcfg_Value **out_value, bool evaluate);
|
||||
|
||||
bool dcfg_Value_get_boolean(dcfg_Value *value, bool *out_value);
|
||||
bool dcfg_Value_get_integer(dcfg_Value *value, int64_t *out_value);
|
||||
@@ -95,10 +131,21 @@ static inline bool dcfg_Value_get_array_item(
|
||||
{
|
||||
return dcfg_Value_get_array_item_ex(value, index, out_value, true);
|
||||
}
|
||||
static inline bool dcfg_Value_get_function_body(
|
||||
dcfg_Value *value, dcfg_Value **out_value)
|
||||
{
|
||||
return dcfg_Value_get_function_body_ex(value, out_value, true);
|
||||
}
|
||||
|
||||
// Allocates new values
|
||||
bool dcfg_call_function(dcfg_Value *function, dcfg_Value **args,
|
||||
size_t arg_count, dcfg_Value **out_value);
|
||||
// Allocates new values
|
||||
bool dcfg_Value_evaluate(dcfg_Value *value, dcfg_Value **out_value);
|
||||
// Allocates new values
|
||||
bool dcfg_Value_evaluate_toplevel(dcfg_Value *top, dcfg_Value **out_value,
|
||||
dcfg_StringView *function_names, dcfg_BuiltIn *functions,
|
||||
size_t function_count);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
179
programs/dcfg_dump.c
Normal file
179
programs/dcfg_dump.c
Normal file
@@ -0,0 +1,179 @@
|
||||
#include <dcfg.h>
|
||||
|
||||
#include <getopt.h>
|
||||
#include <inttypes.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
|
||||
void walk_value(dcfg_Value *value, bool evaluate, int indent, bool first);
|
||||
#define WALK(v, e, i) walk_value((v), (e), (i), true)
|
||||
|
||||
static void print_indent(int indent)
|
||||
{
|
||||
for (int i = 0; i < indent; ++i)
|
||||
putchar('\t');
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
bool evaluate = false;
|
||||
int opt;
|
||||
while ((opt = getopt(argc, argv, "e")) != -1) {
|
||||
switch (opt) {
|
||||
case 'e':
|
||||
evaluate = true;
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "Usage: %s [-e] <dcfg file>\n", argv[0]);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
if (optind >= argc) {
|
||||
fprintf(stderr, "Usage: %s [-e] <dcfg file>\n", argv[0]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
char const *path = argv[optind];
|
||||
|
||||
dcfg_InstanceCreateInfo ci = { 0 };
|
||||
dcfg_Instance *instance = dcfg_make_instance(&ci);
|
||||
if (!instance) {
|
||||
printf("Failed to create DCFG instance. Error: %s\n",
|
||||
dcfg_last_error(instance));
|
||||
return 1;
|
||||
}
|
||||
|
||||
dcfg_Value *value = dcfg_parse(instance, dcfg_SV(path));
|
||||
if (!value) {
|
||||
printf("Failed to parse DCFG file. Error: %s\n",
|
||||
dcfg_last_error(instance));
|
||||
dcfg_destroy_instance(instance);
|
||||
return 1;
|
||||
}
|
||||
|
||||
WALK(value, evaluate, 0);
|
||||
|
||||
dcfg_destroy(value);
|
||||
dcfg_destroy_instance(instance);
|
||||
}
|
||||
|
||||
void walk_value(dcfg_Value *value, bool evaluate, int indent, bool first)
|
||||
{
|
||||
if (first)
|
||||
print_indent(indent);
|
||||
|
||||
dcfg_ValueType type = dcfg_Value_type_ex(value, evaluate);
|
||||
|
||||
switch (type) {
|
||||
case dcfg_ValueType_Nil:
|
||||
printf("null");
|
||||
break;
|
||||
|
||||
case dcfg_ValueType_Boolean: {
|
||||
bool b;
|
||||
dcfg_Value_get_boolean(value, &b);
|
||||
printf("%s", b ? "true" : "false");
|
||||
} break;
|
||||
|
||||
case dcfg_ValueType_Integer: {
|
||||
int64_t v;
|
||||
dcfg_Value_get_integer(value, &v);
|
||||
printf("%" PRId64, v);
|
||||
} break;
|
||||
|
||||
case dcfg_ValueType_Real: {
|
||||
double v;
|
||||
dcfg_Value_get_real(value, &v);
|
||||
printf("%g", v);
|
||||
} break;
|
||||
|
||||
case dcfg_ValueType_String: {
|
||||
dcfg_StringView sv;
|
||||
dcfg_Value_get_string(value, &sv);
|
||||
printf("\"%.*s\"", (int)sv.size, sv.data);
|
||||
} break;
|
||||
|
||||
case dcfg_ValueType_Path: {
|
||||
dcfg_StringView sv;
|
||||
dcfg_Value_get_path(value, &sv);
|
||||
printf("<path \"%.*s\">", (int)sv.size, sv.data);
|
||||
} break;
|
||||
|
||||
case dcfg_ValueType_Object: {
|
||||
size_t n = 0;
|
||||
dcfg_Value_get_object_keys(value, 0, &n, NULL);
|
||||
dcfg_StringView *keys
|
||||
= n ? (dcfg_StringView *)calloc(1, n * sizeof(*keys)) : NULL;
|
||||
dcfg_Value_get_object_keys(value, n, &n, keys);
|
||||
|
||||
printf("{\n");
|
||||
for (size_t i = 0; i < n; ++i) {
|
||||
dcfg_Value *child;
|
||||
if (!dcfg_Value_get_object_field_ex(
|
||||
value, keys[i], &child, evaluate))
|
||||
continue;
|
||||
|
||||
print_indent(indent + 1);
|
||||
printf("\"%.*s\": ", (int)keys[i].size, keys[i].data);
|
||||
walk_value(child, evaluate, indent + 1, false);
|
||||
if (i + 1 < n)
|
||||
printf(",");
|
||||
printf("\n");
|
||||
}
|
||||
print_indent(indent);
|
||||
printf("}");
|
||||
} break;
|
||||
|
||||
case dcfg_ValueType_Array: {
|
||||
size_t sz = 0;
|
||||
dcfg_Value_get_array_size(value, &sz);
|
||||
|
||||
printf("[\n");
|
||||
for (size_t i = 0; i < sz; ++i) {
|
||||
dcfg_Value *item;
|
||||
if (!dcfg_Value_get_array_item_ex(value, i, &item, evaluate))
|
||||
continue;
|
||||
|
||||
print_indent(indent + 1);
|
||||
walk_value(item, evaluate, indent + 1, false);
|
||||
if (i + 1 < sz)
|
||||
printf(",");
|
||||
printf("\n");
|
||||
}
|
||||
print_indent(indent);
|
||||
printf("]");
|
||||
} break;
|
||||
|
||||
case dcfg_ValueType_Function: {
|
||||
dcfg_Value *body = NULL;
|
||||
|
||||
if (dcfg_Value_get_function_body_ex(value, &body, evaluate) && body) {
|
||||
printf("<fn>\t");
|
||||
walk_value(body, evaluate, indent + 1, false);
|
||||
} else {
|
||||
printf("<builtin-fn>");
|
||||
}
|
||||
} break;
|
||||
|
||||
case dcfg_ValueType_FunctionCall:
|
||||
if (evaluate) {
|
||||
dcfg_Value *res;
|
||||
if (dcfg_Value_evaluate(value, &res))
|
||||
walk_value(res, evaluate, indent, first);
|
||||
else
|
||||
printf("<error-evaluating-call>");
|
||||
} else {
|
||||
printf("<function-call>");
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
printf("<unknown>");
|
||||
break;
|
||||
}
|
||||
|
||||
if (indent == 0) {
|
||||
putchar('\n');
|
||||
}
|
||||
}
|
143
programs/dcfgq.c
Normal file
143
programs/dcfgq.c
Normal file
@@ -0,0 +1,143 @@
|
||||
#include <dcfg.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
typedef enum {
|
||||
T_FIELD,
|
||||
T_INDEX,
|
||||
} TokenType;
|
||||
|
||||
typedef struct {
|
||||
TokenType type;
|
||||
union {
|
||||
dcfg_StringView field;
|
||||
size_t index;
|
||||
} v;
|
||||
} Token;
|
||||
|
||||
#define MAX_TOKENS 256
|
||||
|
||||
static size_t tokenize(char const *query, Token *out)
|
||||
{
|
||||
size_t count = 0;
|
||||
size_t i = 0;
|
||||
if (query[i] == '.')
|
||||
i++;
|
||||
while (query[i] && count < MAX_TOKENS) {
|
||||
if (query[i] == '.') {
|
||||
i++;
|
||||
size_t start = i;
|
||||
while (query[i] && query[i] != '.' && query[i] != '[')
|
||||
i++;
|
||||
out[count].type = T_FIELD;
|
||||
out[count].v.field.data = query + start;
|
||||
out[count].v.field.size = i - start;
|
||||
count++;
|
||||
} else if (query[i] == '[') {
|
||||
i++;
|
||||
char *end;
|
||||
size_t idx = strtoul(query + i, &end, 10);
|
||||
if (*end != ']') {
|
||||
fprintf(stderr, "invalid index\n");
|
||||
exit(1);
|
||||
}
|
||||
i = (size_t)(end - query) + 1;
|
||||
out[count].type = T_INDEX;
|
||||
out[count].v.index = idx;
|
||||
count++;
|
||||
} else {
|
||||
size_t start = i;
|
||||
while (query[i] && query[i] != '.' && query[i] != '[')
|
||||
i++;
|
||||
out[count].type = T_FIELD;
|
||||
out[count].v.field.data = query + start;
|
||||
out[count].v.field.size = i - start;
|
||||
count++;
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
static void print_value(dcfg_Value *v)
|
||||
{
|
||||
dcfg_StringView sv;
|
||||
if (dcfg_serialize_value(v, &sv)) {
|
||||
fwrite(sv.data, 1, sv.size, stdout);
|
||||
free((void *)sv.data);
|
||||
putchar('\n');
|
||||
} else {
|
||||
puts("null");
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
if (argc < 3) {
|
||||
fprintf(stderr, "usage: %s <query> <file>\n", argv[0]);
|
||||
return 1;
|
||||
}
|
||||
char const *query = argv[1];
|
||||
char const *file = argv[2];
|
||||
|
||||
dcfg_Instance *inst = dcfg_make_instance(&(dcfg_InstanceCreateInfo) { 0 });
|
||||
if (!inst) {
|
||||
fprintf(stderr, "failed to create instance\n");
|
||||
return 1;
|
||||
}
|
||||
dcfg_Value *root = dcfg_parse(inst, dcfg_SV(file));
|
||||
if (!root) {
|
||||
fprintf(stderr, "parse error: %s\n", dcfg_last_error(inst));
|
||||
dcfg_destroy_instance(inst);
|
||||
return 1;
|
||||
}
|
||||
|
||||
Token toks[MAX_TOKENS];
|
||||
size_t n = tokenize(query, toks);
|
||||
|
||||
dcfg_Value *evaled;
|
||||
if (!dcfg_Value_evaluate_toplevel(root, &evaled, NULL, NULL, 0)) {
|
||||
fprintf(stderr, "evaluation error: %s\n", dcfg_last_error(inst));
|
||||
dcfg_destroy(root);
|
||||
dcfg_destroy_instance(inst);
|
||||
return 1;
|
||||
}
|
||||
|
||||
dcfg_Value *cur = evaled;
|
||||
for (size_t i = 0; i < n; i++) {
|
||||
Token *t = &toks[i];
|
||||
dcfg_Value *next = NULL;
|
||||
|
||||
if (t->type == T_FIELD) {
|
||||
if (!dcfg_Value_get_object_field_ex(cur, t->v.field, &next, true)) {
|
||||
fprintf(stderr, "no such field\n");
|
||||
dcfg_destroy(evaled);
|
||||
dcfg_destroy(root);
|
||||
dcfg_destroy_instance(inst);
|
||||
return 1;
|
||||
}
|
||||
} else {
|
||||
if (!dcfg_Value_get_array_item_ex(cur, t->v.index, &next, true)) {
|
||||
fprintf(stderr, "index out of bounds\n");
|
||||
dcfg_destroy(evaled);
|
||||
dcfg_destroy(root);
|
||||
dcfg_destroy_instance(inst);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (cur != evaled)
|
||||
dcfg_destroy(cur);
|
||||
|
||||
cur = next;
|
||||
}
|
||||
print_value(cur);
|
||||
if (cur != evaled)
|
||||
dcfg_destroy(cur);
|
||||
|
||||
dcfg_destroy(evaled);
|
||||
dcfg_destroy(root);
|
||||
dcfg_destroy_instance(inst);
|
||||
return 0;
|
||||
}
|
@@ -8,6 +8,6 @@ fn lib = {
|
||||
partitions = {
|
||||
automount = [ 'boot' 'root' ]
|
||||
swap.enable = true
|
||||
swap.size = 2g
|
||||
swap.size = 2_000_000_000
|
||||
}
|
||||
}
|
||||
|
5
samples/invalid_block.dcfg
Normal file
5
samples/invalid_block.dcfg
Normal file
@@ -0,0 +1,5 @@
|
||||
{
|
||||
test = 123
|
||||
test.field = 456 # This should be invalid. `test` is an int, not an object.
|
||||
}
|
||||
|
12
samples/testing.dcfg
Normal file
12
samples/testing.dcfg
Normal file
@@ -0,0 +1,12 @@
|
||||
fn lib = [
|
||||
123
|
||||
"string"
|
||||
./path
|
||||
80085.3
|
||||
{
|
||||
key1 = 123
|
||||
key2.member = "str"
|
||||
key2.another_member = ./amazing
|
||||
}
|
||||
]
|
||||
|
11
samples/utf8.dcfg
Normal file
11
samples/utf8.dcfg
Normal file
@@ -0,0 +1,11 @@
|
||||
fn lib = {
|
||||
english = "The quick brown fox jumps over the lazy dog."
|
||||
日本語 = "はじめまして!"
|
||||
Română = "Salutare! ĂÂÎȘȚăâîșț"
|
||||
😀 = "👋🌍😊🚀🤖"
|
||||
diacritics = "ŠĐĆŽšđž"
|
||||
français = "Ça déjà vu?"
|
||||
español = "¡El pingüino Wenceslao bebe whisky y zumo de piña!"
|
||||
русский = "Съешь же ещё этих мягких французских булок, да выпей чаю."
|
||||
}
|
||||
|
@@ -1,8 +1,8 @@
|
||||
fn lib = {
|
||||
keybindings = [
|
||||
{ key = 'Main-Shift-Escape' action = lib.quit_wm }
|
||||
{ key = 'Main-Shift-Q' action = lib.kill_application }
|
||||
{ key = 'Main-Shift-C' action = lib.close_application }
|
||||
{ key = 'Main-Shift-Escape' action = (lib.quit_wm) }
|
||||
{ key = 'Main-Shift-Q' action = (lib.kill_application) }
|
||||
{ key = 'Main-Shift-C' action = (lib.close_application) }
|
||||
{ key = 'Main-Space' action = (lib.execute 'alacritty') }
|
||||
]
|
||||
}
|
||||
|
1210
src/dcfg.c
1210
src/dcfg.c
File diff suppressed because it is too large
Load Diff
30
src/meta.h
Normal file
30
src/meta.h
Normal file
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
* Copyright 2025 Slendi <slendi@socopon.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the “Software”), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef META_H
|
||||
#define META_H
|
||||
|
||||
#define VERSION_MAJOR 0
|
||||
#define VERSION_MINOR 1
|
||||
#define VERSION_PATCH 0
|
||||
|
||||
#endif // META_H
|
74
src/vendor/vec.c
vendored
74
src/vendor/vec.c
vendored
@@ -33,18 +33,20 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#include "vec.h"
|
||||
#include <string.h>
|
||||
|
||||
typedef struct
|
||||
{
|
||||
typedef struct {
|
||||
vec_size_t size;
|
||||
vec_size_t capacity;
|
||||
unsigned char data[];
|
||||
unsigned char data[];
|
||||
} vector_header;
|
||||
|
||||
vector_header* vector_get_header(vector vec) { return &((vector_header*)vec)[-1]; }
|
||||
vector_header *vector_get_header(vector vec)
|
||||
{
|
||||
return &((vector_header *)vec)[-1];
|
||||
}
|
||||
|
||||
vector vector_create(void)
|
||||
{
|
||||
vector_header* h = (vector_header*)malloc(sizeof(vector_header));
|
||||
vector_header *h = (vector_header *)malloc(sizeof(vector_header));
|
||||
h->capacity = 0;
|
||||
h->size = 0;
|
||||
|
||||
@@ -55,28 +57,28 @@ void vector_free(vector vec) { free(vector_get_header(vec)); }
|
||||
|
||||
vec_size_t vector_size(vector vec) { return vector_get_header(vec)->size; }
|
||||
|
||||
vec_size_t vector_capacity(vector vec) { return vector_get_header(vec)->capacity; }
|
||||
vec_size_t vector_capacity(vector vec)
|
||||
{
|
||||
return vector_get_header(vec)->capacity;
|
||||
}
|
||||
|
||||
vector_header* vector_realloc(vector_header* h, vec_type_t type_size)
|
||||
vector_header *vector_realloc(vector_header *h, vec_type_t type_size)
|
||||
{
|
||||
vec_size_t new_capacity = (h->capacity == 0) ? 1 : h->capacity * 2;
|
||||
vector_header* new_h = (vector_header*)realloc(h, sizeof(vector_header) + new_capacity * type_size);
|
||||
vector_header *new_h = (vector_header *)realloc(
|
||||
h, sizeof(vector_header) + new_capacity * type_size);
|
||||
new_h->capacity = new_capacity;
|
||||
|
||||
return new_h;
|
||||
}
|
||||
|
||||
bool vector_has_space(vector_header* h)
|
||||
{
|
||||
return h->capacity - h->size > 0;
|
||||
}
|
||||
bool vector_has_space(vector_header *h) { return h->capacity - h->size > 0; }
|
||||
|
||||
void* _vector_add_dst(vector* vec_addr, vec_type_t type_size)
|
||||
void *_vector_add_dst(vector *vec_addr, vec_type_t type_size)
|
||||
{
|
||||
vector_header* h = vector_get_header(*vec_addr);
|
||||
vector_header *h = vector_get_header(*vec_addr);
|
||||
|
||||
if (!vector_has_space(h))
|
||||
{
|
||||
if (!vector_has_space(h)) {
|
||||
h = vector_realloc(h, type_size);
|
||||
*vec_addr = h->data;
|
||||
}
|
||||
@@ -84,34 +86,32 @@ void* _vector_add_dst(vector* vec_addr, vec_type_t type_size)
|
||||
return &h->data[type_size * h->size++];
|
||||
}
|
||||
|
||||
void* _vector_insert_dst(vector* vec_addr, vec_type_t type_size, vec_size_t pos)
|
||||
void *_vector_insert_dst(vector *vec_addr, vec_type_t type_size, vec_size_t pos)
|
||||
{
|
||||
vector_header* h = vector_get_header(*vec_addr);
|
||||
vector_header *h = vector_get_header(*vec_addr);
|
||||
|
||||
vec_size_t new_length = h->size + 1;
|
||||
|
||||
// make sure there is enough room for the new element
|
||||
if (!vector_has_space(h))
|
||||
{
|
||||
if (!vector_has_space(h)) {
|
||||
h = vector_realloc(h, type_size);
|
||||
*vec_addr = h->data;
|
||||
}
|
||||
// move trailing elements
|
||||
memmove(&h->data[(pos + 1) * type_size],
|
||||
&h->data[pos * type_size],
|
||||
(h->size - pos) * type_size);
|
||||
memmove(&h->data[(pos + 1) * type_size], &h->data[pos * type_size],
|
||||
(h->size - pos) * type_size);
|
||||
|
||||
h->size = new_length;
|
||||
|
||||
return &h->data[pos * type_size];
|
||||
}
|
||||
|
||||
void _vector_erase(vector vec, vec_type_t type_size, vec_size_t pos, vec_size_t len)
|
||||
void _vector_erase(
|
||||
vector vec, vec_type_t type_size, vec_size_t pos, vec_size_t len)
|
||||
{
|
||||
vector_header* h = vector_get_header(vec);
|
||||
memmove(&h->data[pos * type_size],
|
||||
&h->data[(pos + len) * type_size],
|
||||
(h->size - pos - len) * type_size);
|
||||
vector_header *h = vector_get_header(vec);
|
||||
memmove(&h->data[pos * type_size], &h->data[(pos + len) * type_size],
|
||||
(h->size - pos - len) * type_size);
|
||||
|
||||
h->size -= len;
|
||||
}
|
||||
@@ -123,26 +123,28 @@ void _vector_remove(vector vec, vec_type_t type_size, vec_size_t pos)
|
||||
|
||||
void vector_pop(vector vec) { --vector_get_header(vec)->size; }
|
||||
|
||||
void _vector_reserve(vector* vec_addr, vec_type_t type_size, vec_size_t capacity)
|
||||
void _vector_reserve(
|
||||
vector *vec_addr, vec_type_t type_size, vec_size_t capacity)
|
||||
{
|
||||
vector_header* h = vector_get_header(*vec_addr);
|
||||
if (h->capacity >= capacity)
|
||||
{
|
||||
vector_header *h = vector_get_header(*vec_addr);
|
||||
if (h->capacity >= capacity) {
|
||||
return;
|
||||
}
|
||||
|
||||
h = (vector_header*)realloc(h, sizeof(vector_header) + capacity * type_size);
|
||||
h = (vector_header *)realloc(
|
||||
h, sizeof(vector_header) + capacity * type_size);
|
||||
h->capacity = capacity;
|
||||
*vec_addr = &h->data;
|
||||
}
|
||||
|
||||
vector _vector_copy(vector vec, vec_type_t type_size)
|
||||
{
|
||||
vector_header* h = vector_get_header(vec);
|
||||
vector_header *h = vector_get_header(vec);
|
||||
size_t alloc_size = sizeof(vector_header) + h->size * type_size;
|
||||
vector_header* copy_h = (vector_header*)malloc(alloc_size);
|
||||
vector_header *copy_h = (vector_header *)malloc(alloc_size);
|
||||
memcpy(copy_h, h, alloc_size);
|
||||
copy_h->capacity = copy_h->size;
|
||||
|
||||
return ©_h->data;
|
||||
}
|
||||
}
|
||||
|
||||
|
65
src/vendor/vec.h
vendored
65
src/vendor/vec.h
vendored
@@ -33,11 +33,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#ifndef vec_h
|
||||
#define vec_h
|
||||
|
||||
#ifdef __cpp_decltype
|
||||
#include <type_traits>
|
||||
#define typeof(T) std::remove_reference<std::add_lvalue_reference<decltype(T)>::type>::type
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
@@ -46,72 +41,50 @@ extern "C" {
|
||||
#include <stdlib.h>
|
||||
|
||||
// generic type for internal use
|
||||
typedef void* vector;
|
||||
typedef void *vector;
|
||||
// number of elements in a vector
|
||||
typedef size_t vec_size_t;
|
||||
// number of bytes for a type
|
||||
typedef size_t vec_type_t;
|
||||
|
||||
// TODO: more rigorous check for typeof support with different compilers
|
||||
#if _MSC_VER == 0 || __STDC_VERSION__ >= 202311L || defined __cpp_decltype
|
||||
#define vector_add_dst(vec_addr, type) \
|
||||
((type *)_vector_add_dst((vector *)vec_addr, sizeof(type)))
|
||||
#define vector_insert_dst(vec_addr, type, pos) \
|
||||
((type *)_vector_insert_dst((vector *)vec_addr, sizeof(type), pos))
|
||||
|
||||
// shortcut defines
|
||||
|
||||
// vec_addr is a vector* (aka type**)
|
||||
#define vector_add_dst(vec_addr)\
|
||||
((typeof(*vec_addr))(\
|
||||
_vector_add_dst((vector*)vec_addr, sizeof(**vec_addr))\
|
||||
))
|
||||
#define vector_insert_dst(vec_addr, pos)\
|
||||
((typeof(*vec_addr))(\
|
||||
_vector_insert_dst((vector*)vec_addr, sizeof(**vec_addr), pos)))
|
||||
|
||||
#define vector_add(vec_addr, value)\
|
||||
(*vector_add_dst(vec_addr) = value)
|
||||
#define vector_insert(vec_addr, pos, value)\
|
||||
(*vector_insert_dst(vec_addr, pos) = value)
|
||||
|
||||
#else
|
||||
|
||||
#define vector_add_dst(vec_addr, type)\
|
||||
((type*)_vector_add_dst((vector*)vec_addr, sizeof(type)))
|
||||
#define vector_insert_dst(vec_addr, type, pos)\
|
||||
((type*)_vector_insert_dst((vector*)vec_addr, sizeof(type), pos))
|
||||
|
||||
#define vector_add(vec_addr, type, value)\
|
||||
#define vector_add(vec_addr, type, value) \
|
||||
(*vector_add_dst(vec_addr, type) = value)
|
||||
#define vector_insert(vec_addr, type, pos, value)\
|
||||
#define vector_insert(vec_addr, type, pos, value) \
|
||||
(*vector_insert_dst(vec_addr, type, pos) = value)
|
||||
|
||||
#endif
|
||||
|
||||
// vec is a vector (aka type*)
|
||||
#define vector_erase(vec, pos, len)\
|
||||
#define vector_erase(vec, pos, len) \
|
||||
(_vector_erase((vector)vec, sizeof(*vec), pos, len))
|
||||
#define vector_remove(vec, pos)\
|
||||
(_vector_remove((vector)vec, sizeof(*vec), pos))
|
||||
#define vector_remove(vec, pos) (_vector_remove((vector)vec, sizeof(*vec), pos))
|
||||
|
||||
#define vector_reserve(vec_addr, capacity)\
|
||||
(_vector_reserve((vector*)vec_addr, sizeof(**vec_addr), capacity))
|
||||
#define vector_reserve(vec_addr, capacity) \
|
||||
(_vector_reserve((vector *)vec_addr, sizeof(**vec_addr), capacity))
|
||||
|
||||
#define vector_copy(vec)\
|
||||
(_vector_copy((vector)vec, sizeof(*vec)))
|
||||
#define vector_copy(vec) (_vector_copy((vector)vec, sizeof(*vec)))
|
||||
|
||||
vector vector_create(void);
|
||||
|
||||
void vector_free(vector vec);
|
||||
|
||||
void* _vector_add_dst(vector* vec_addr, vec_type_t type_size);
|
||||
void *_vector_add_dst(vector *vec_addr, vec_type_t type_size);
|
||||
|
||||
void* _vector_insert_dst(vector* vec_addr, vec_type_t type_size, vec_size_t pos);
|
||||
void *_vector_insert_dst(
|
||||
vector *vec_addr, vec_type_t type_size, vec_size_t pos);
|
||||
|
||||
void _vector_erase(vector vec_addr, vec_type_t type_size, vec_size_t pos, vec_size_t len);
|
||||
void _vector_erase(
|
||||
vector vec_addr, vec_type_t type_size, vec_size_t pos, vec_size_t len);
|
||||
|
||||
void _vector_remove(vector vec_addr, vec_type_t type_size, vec_size_t pos);
|
||||
|
||||
void vector_pop(vector vec);
|
||||
|
||||
void _vector_reserve(vector* vec_addr, vec_type_t type_size, vec_size_t capacity);
|
||||
void _vector_reserve(
|
||||
vector *vec_addr, vec_type_t type_size, vec_size_t capacity);
|
||||
|
||||
vector _vector_copy(vector vec, vec_type_t type_size);
|
||||
|
||||
|
4
tools/clean.sh
Executable file
4
tools/clean.sh
Executable file
@@ -0,0 +1,4 @@
|
||||
#!/bin/sh
|
||||
|
||||
rm -rf install build BUILD result
|
||||
|
Reference in New Issue
Block a user