Add dump
Some checks failed
CMake / ubuntu-latest - shared=OFF, pthread=OFF, posix=OFF (push) Failing after 13s
CMake / ubuntu-latest - shared=ON, pthread=OFF, posix=OFF (push) Successful in 16s
CMake / ubuntu-latest - shared=OFF, pthread=OFF, posix=ON (push) Failing after 14s
CMake / ubuntu-latest - shared=ON, pthread=OFF, posix=ON (push) Successful in 17s
CMake / ubuntu-latest - shared=OFF, pthread=ON, posix=ON (push) Failing after 18s
CMake / ubuntu-latest - shared=ON, pthread=ON, posix=ON (push) Successful in 15s
Some checks failed
CMake / ubuntu-latest - shared=OFF, pthread=OFF, posix=OFF (push) Failing after 13s
CMake / ubuntu-latest - shared=ON, pthread=OFF, posix=OFF (push) Successful in 16s
CMake / ubuntu-latest - shared=OFF, pthread=OFF, posix=ON (push) Failing after 14s
CMake / ubuntu-latest - shared=ON, pthread=OFF, posix=ON (push) Successful in 17s
CMake / ubuntu-latest - shared=OFF, pthread=ON, posix=ON (push) Failing after 18s
CMake / ubuntu-latest - shared=ON, pthread=ON, posix=ON (push) Successful in 15s
Signed-off-by: Slendi <slendi@socopon.com>
This commit is contained in:
@@ -9,6 +9,7 @@ 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)
|
||||
option(DCFG_BUILD_PROGRAMS "Build DCFG example programs" ON)
|
||||
|
||||
find_package(Threads)
|
||||
|
||||
@@ -54,3 +55,24 @@ if(MSVC)
|
||||
else()
|
||||
target_compile_options(${PROJECT_NAME} PRIVATE -Wall -Wextra -pedantic -Werror -Wno-newline-eof -Wno-language-extension-token)
|
||||
endif()
|
||||
|
||||
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})
|
||||
if(DCFG_PTHREAD_SUPPORT)
|
||||
target_link_libraries(${PROG_NAME} PRIVATE Threads::Threads)
|
||||
endif()
|
||||
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()
|
||||
install(TARGETS ${PROG_NAME} DESTINATION bin)
|
||||
endforeach()
|
||||
endif()
|
||||
|
22
build.sh
22
build.sh
@@ -1,4 +1,5 @@
|
||||
#!/bin/sh
|
||||
|
||||
set -e
|
||||
|
||||
BUILD_DIR="BUILD"
|
||||
@@ -7,8 +8,10 @@ CFLAGS="-std=gnu99 -Wall -Wextra -pedantic -Werror -Wno-newline-eof -Wno-languag
|
||||
BUILD_SHARED=1
|
||||
PTHREAD_SUPPORT=1
|
||||
POSIX_SUPPORT=1
|
||||
BUILD_PROGRAMS=0
|
||||
SRC_DIR="src"
|
||||
INCLUDE_DIR="include"
|
||||
PROGRAMS_DIR="programs"
|
||||
OUTPUT_NAME="libdcfg"
|
||||
|
||||
for arg in "$@"; do
|
||||
@@ -17,12 +20,13 @@ for arg in "$@"; do
|
||||
--release) CFLAGS="$CFLAGS -O2" ;;
|
||||
--no-pthread) PTHREAD_SUPPORT=0 ;;
|
||||
--no-posix) POSIX_SUPPORT=0 ;;
|
||||
--with-programs) BUILD_PROGRAMS=1 ;;
|
||||
--clean) rm -rf "$BUILD_DIR" "$INSTALL_DIR"; echo "Cleaned."; exit 0 ;;
|
||||
esac
|
||||
done
|
||||
|
||||
# Setup directories
|
||||
mkdir -p "$BUILD_DIR" "$INSTALL_DIR/lib" "$INSTALL_DIR/include"
|
||||
mkdir -p "$BUILD_DIR" "$INSTALL_DIR/lib" "$INSTALL_DIR/include" "$INSTALL_DIR/bin"
|
||||
|
||||
# Compiler and linker
|
||||
CC=${CC:-cc}
|
||||
@@ -39,16 +43,28 @@ echo "Building DCFG..."
|
||||
cd "$BUILD_DIR"
|
||||
|
||||
set -x
|
||||
# Shared library
|
||||
$CC $CFLAGS -fPIC -shared "../$SRC_DIR/dcfg.c" -I"../$INCLUDE_DIR" -o "$OUTPUT_NAME.so" $LIBS
|
||||
|
||||
# Static library
|
||||
$CC $CFLAGS -c "../$SRC_DIR/dcfg.c" -I"../$INCLUDE_DIR"
|
||||
ar rcs "$OUTPUT_NAME.a" dcfg.o
|
||||
|
||||
set +x
|
||||
|
||||
echo "Installing..."
|
||||
echo "Installing library..."
|
||||
cp -r "../$INCLUDE_DIR/"* "$INSTALL_DIR/include/"
|
||||
cp "$OUTPUT_NAME.so" "$INSTALL_DIR/lib/"
|
||||
cp "$OUTPUT_NAME.a" "$INSTALL_DIR/lib/"
|
||||
|
||||
# Build programs if requested
|
||||
if [ "$BUILD_PROGRAMS" -eq 1 ]; then
|
||||
echo "Building example programs..."
|
||||
for src in "../$PROGRAMS_DIR"/*.c; do
|
||||
prog=$(basename "$src" .c)
|
||||
echo "Building $prog..."
|
||||
$CC $CFLAGS "$src" -I"../$INCLUDE_DIR" "$OUTPUT_NAME.a" $LIBS -o "$prog"
|
||||
cp "$prog" "$INSTALL_DIR/bin/"
|
||||
done
|
||||
fi
|
||||
|
||||
echo "Done. Installed to $INSTALL_DIR"
|
||||
|
@@ -4,6 +4,7 @@
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
@@ -17,6 +18,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 *);
|
||||
@@ -75,6 +77,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,6 +99,10 @@ static inline bool dcfg_Value_get_array_item(
|
||||
{
|
||||
return dcfg_Value_get_array_item_ex(value, index, out_value, true);
|
||||
}
|
||||
bool dcfg_Value_get_function_body(dcfg_Value *value, dcfg_Value **out_value)
|
||||
{
|
||||
return dcfg_Value_get_function_body_ex(value, out_value, true);
|
||||
}
|
||||
|
||||
bool dcfg_call_function(dcfg_Value *function, dcfg_Value **args,
|
||||
size_t arg_count, dcfg_Value **out_value);
|
||||
|
159
programs/dcfg_dump.c
Normal file
159
programs/dcfg_dump.c
Normal file
@@ -0,0 +1,159 @@
|
||||
#include <dcfg.h>
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
void walk_value(dcfg_Value *value, bool evaluate, int indent);
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
if (argc < 2) {
|
||||
printf("Usage: %s <dcfg file>\n", argv[0]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
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(argv[1]));
|
||||
if (!value) {
|
||||
printf("Failed to parse DCFG file. Error: %s\n",
|
||||
dcfg_last_error(instance));
|
||||
return 1;
|
||||
}
|
||||
|
||||
walk_value(value, false, 0);
|
||||
|
||||
dcfg_destroy(value);
|
||||
dcfg_destroy_instance(instance);
|
||||
}
|
||||
|
||||
static void print_indent(int indent)
|
||||
{
|
||||
for (int i = 0; i < indent; ++i)
|
||||
putchar('\t');
|
||||
}
|
||||
|
||||
void walk_value(dcfg_Value *value, bool evaluate, int indent)
|
||||
{
|
||||
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 *)alloca(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);
|
||||
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;
|
||||
|
||||
walk_value(item, evaluate, indent + 1);
|
||||
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> ");
|
||||
walk_value(body, evaluate, indent + 1);
|
||||
} 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);
|
||||
else
|
||||
printf("<error‑evaluating‑call>");
|
||||
} else {
|
||||
printf("<function‑call>");
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
printf("<unknown>");
|
||||
break;
|
||||
}
|
||||
|
||||
if (indent == 0) {
|
||||
putchar('\n');
|
||||
}
|
||||
}
|
2
samples/testing.dcfg
Normal file
2
samples/testing.dcfg
Normal file
@@ -0,0 +1,2 @@
|
||||
fn lib = [ 123 "string" ./path 80085.3 ]
|
||||
|
222
src/dcfg.c
222
src/dcfg.c
@@ -343,8 +343,18 @@ static inline int32_t decode_cp(StringView src, int pos, int *len)
|
||||
*len = 0;
|
||||
return -1;
|
||||
}
|
||||
return (int32_t)utf8proc_iterate(
|
||||
(uint8_t const *)src.data + pos, (int)(src.size - pos), len);
|
||||
|
||||
int32_t cp;
|
||||
int bytes = utf8proc_iterate(
|
||||
(uint8_t const *)src.data + pos, (int)(src.size - pos), &cp);
|
||||
|
||||
if (bytes < 0) {
|
||||
*len = 0;
|
||||
return -1;
|
||||
}
|
||||
|
||||
*len = bytes;
|
||||
return cp;
|
||||
}
|
||||
|
||||
static inline bool is_space_cp(int32_t cp)
|
||||
@@ -625,13 +635,18 @@ typedef struct {
|
||||
AST **argv;
|
||||
} ASTFunctionCall;
|
||||
|
||||
typedef struct {
|
||||
bool is_str;
|
||||
StringView s;
|
||||
} ASTKey;
|
||||
|
||||
struct AST {
|
||||
ASTKind kind;
|
||||
SourceLocation location;
|
||||
union {
|
||||
int64_t i;
|
||||
double r;
|
||||
StringView s;
|
||||
ASTKey s;
|
||||
StringView p;
|
||||
bool b;
|
||||
ASTFunction f;
|
||||
@@ -653,20 +668,18 @@ bool Parser_next(Parser *parser)
|
||||
{
|
||||
parser->cur = parser->next;
|
||||
parser->next = Lexer_next(parser->lexer);
|
||||
bool ret = parser->next.type != TokenType_Error;
|
||||
if (!ret) {
|
||||
if (parser->next.type == TokenType_Error) {
|
||||
strcpy(parser->instance->last_error, "Failed to get parser token");
|
||||
}
|
||||
return ret;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Parser_init(Parser *out_parser, Lexer *lexer, Instance *instance)
|
||||
{
|
||||
memset(out_parser, 0, sizeof(*out_parser));
|
||||
out_parser->lexer = lexer;
|
||||
out_parser->instance = instance;
|
||||
if (!Parser_next(out_parser)) {
|
||||
return false;
|
||||
}
|
||||
out_parser->next = Lexer_next(lexer);
|
||||
if (!Parser_next(out_parser)) {
|
||||
return false;
|
||||
}
|
||||
@@ -781,7 +794,7 @@ AST *parser_parse_dot_access(Parser *parser, StringView *current)
|
||||
|
||||
if (vector_size(accessv) == 1) {
|
||||
ast->kind = ASTKind_Key;
|
||||
ast->v.s = accessv[0];
|
||||
ast->v.s.s = accessv[0];
|
||||
vector_free(accessv);
|
||||
}
|
||||
return ast;
|
||||
@@ -800,13 +813,14 @@ AST *parser_parse_value(Parser *parser)
|
||||
} else if (parser->cur.type == TokenType_String
|
||||
|| parser->cur.type == TokenType_Identifier) {
|
||||
ast->kind = ASTKind_Key;
|
||||
ast->v.s = parser->cur.v.s;
|
||||
ast->v.s.s = parser->cur.v.s;
|
||||
ast->v.s.is_str = parser->cur.type == TokenType_String;
|
||||
|
||||
if (parser->next.type == TokenType_Dot) {
|
||||
FREE(ast);
|
||||
return parser_parse_dot_access(parser, NULL);
|
||||
} else if (parser->cur.type == TokenType_Identifier) {
|
||||
if (sv_eq(ast->v.s, SV("fn"))) {
|
||||
if (sv_eq(ast->v.s.s, SV("fn"))) {
|
||||
if (!Parser_next(parser)) {
|
||||
strcpy(parser->instance->last_error,
|
||||
"Failed to advance fn keyword");
|
||||
@@ -837,6 +851,11 @@ AST *parser_parse_value(Parser *parser)
|
||||
}
|
||||
|
||||
vector_add(&ast->v.f.argv, parser->cur.v.s);
|
||||
if (!Parser_next(parser)) {
|
||||
vector_free(ast->v.f.argv);
|
||||
FREE(ast);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
ast->v.f.body = parser_parse_value(parser);
|
||||
@@ -847,12 +866,12 @@ AST *parser_parse_value(Parser *parser)
|
||||
}
|
||||
ast->location.range.end = ast->v.f.body->location.range.end;
|
||||
return ast;
|
||||
} else if (sv_eq(ast->v.s, SV("on"))
|
||||
|| sv_eq(ast->v.s, SV("true"))) {
|
||||
} else if (sv_eq(ast->v.s.s, SV("on"))
|
||||
|| sv_eq(ast->v.s.s, SV("true"))) {
|
||||
ast->kind = ASTKind_Boolean;
|
||||
ast->v.b = true;
|
||||
} else if (sv_eq(ast->v.s, SV("off"))
|
||||
|| sv_eq(ast->v.s, SV("false"))) {
|
||||
} else if (sv_eq(ast->v.s.s, SV("off"))
|
||||
|| sv_eq(ast->v.s.s, SV("false"))) {
|
||||
ast->kind = ASTKind_Boolean;
|
||||
ast->v.b = false;
|
||||
}
|
||||
@@ -1000,9 +1019,14 @@ Value *ast_to_value(dcfg_Instance *instance, AST *root)
|
||||
Value *value = ALLOC(sizeof(*value));
|
||||
value->instance = instance;
|
||||
if (root->kind == ASTKind_Key) {
|
||||
// FIXME: Implement
|
||||
FREE(value);
|
||||
return NULL;
|
||||
if (root->v.s.is_str) {
|
||||
value->type = dcfg_ValueType_String;
|
||||
value->v.s = root->v.s.s;
|
||||
} else {
|
||||
// FIXME: Implement
|
||||
FREE(value);
|
||||
return NULL;
|
||||
}
|
||||
} else if (root->kind == ASTKind_Path) {
|
||||
value->type = dcfg_ValueType_Path;
|
||||
value->v.p = root->v.p;
|
||||
@@ -1089,6 +1113,7 @@ dcfg_Value *dcfg_parse(dcfg_Instance *instance, dcfg_StringView const file_path)
|
||||
if (!abs) {
|
||||
snprintf(instance->last_error, sizeof(instance->last_error) - 1,
|
||||
"realpath: %s", strerror(errno));
|
||||
return NULL;
|
||||
}
|
||||
StringView abs_sv = SV(abs);
|
||||
|
||||
@@ -1146,25 +1171,33 @@ dcfg_Value *dcfg_parse(dcfg_Instance *instance, dcfg_StringView const file_path)
|
||||
|
||||
AST *ast = Parser_parse(&parser);
|
||||
if (!ast) {
|
||||
if (!*instance->last_error) {
|
||||
strcpy(instance->last_error, "Could not parse file");
|
||||
}
|
||||
FREE(abs);
|
||||
FREE((void *)str.data);
|
||||
fclose(fp);
|
||||
return NULL;
|
||||
}
|
||||
instance->last_error[0] = '\0';
|
||||
|
||||
Value *v = ast_to_value(instance, ast);
|
||||
if (!v) {
|
||||
if (!*instance->last_error) {
|
||||
strcpy(instance->last_error, "Could not get Value tree from AST");
|
||||
}
|
||||
dcfg_destroy(v);
|
||||
FREE(abs);
|
||||
FREE((void *)str.data);
|
||||
fclose(fp);
|
||||
return NULL;
|
||||
}
|
||||
instance->last_error[0] = '\0';
|
||||
|
||||
vector_add(&instance->sourcev, str);
|
||||
vector_add(&instance->source_pathv, abs_sv);
|
||||
|
||||
v->i_sourcev_idx = vector_size(instance->sourcev) - 1;
|
||||
|
||||
vector_add(&instance->source_pathv, abs_sv);
|
||||
v->i_source_pathv_idx = vector_size(instance->source_pathv) - 1;
|
||||
|
||||
return v;
|
||||
@@ -1176,6 +1209,153 @@ void dcfg_destroy(dcfg_Value *value)
|
||||
// FIXME: Implement
|
||||
}
|
||||
|
||||
dcfg_ValueType dcfg_Value_type_ex(dcfg_Value *value, bool evaluate)
|
||||
{
|
||||
if (!value)
|
||||
return dcfg_ValueType_Nil;
|
||||
(void)evaluate; /* eval ignored for now */
|
||||
return value->type;
|
||||
}
|
||||
|
||||
bool dcfg_Value_get_object_field_ex(dcfg_Value *value, dcfg_StringView key,
|
||||
dcfg_Value **out_value, bool evaluate)
|
||||
{
|
||||
if (!value || value->type != dcfg_ValueType_Object)
|
||||
return false;
|
||||
|
||||
ValueObject *obj = &value->v.o;
|
||||
for (size_t i = 0; i < vector_size(obj->entryv); ++i) {
|
||||
ValueObjectEntry *entry = &obj->entryv[i];
|
||||
if (sv_eq(entry->k, key)) {
|
||||
*out_value = entry->v;
|
||||
if (evaluate)
|
||||
dcfg_Value_evaluate(*out_value, out_value);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool dcfg_Value_get_array_item_ex(
|
||||
dcfg_Value *value, size_t index, dcfg_Value **out_value, bool evaluate)
|
||||
{
|
||||
if (!value || value->type != dcfg_ValueType_Array)
|
||||
return false;
|
||||
|
||||
ValueArray *arr = &value->v.a;
|
||||
if (index >= vector_size(arr->valuev))
|
||||
return false;
|
||||
|
||||
*out_value = arr->valuev[index];
|
||||
if (evaluate)
|
||||
dcfg_Value_evaluate(*out_value, out_value);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool dcfg_Value_get_function_body_ex(
|
||||
dcfg_Value *value, dcfg_Value **out_value, bool evaluate)
|
||||
{
|
||||
if (!value || value->type != dcfg_ValueType_Function
|
||||
|| value->v.f.is_builtin)
|
||||
return false;
|
||||
|
||||
if (out_value)
|
||||
*out_value = value->v.f.v.f.body;
|
||||
|
||||
if (evaluate && out_value && *out_value)
|
||||
dcfg_Value_evaluate(*out_value, out_value);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool dcfg_Value_get_boolean(dcfg_Value *value, bool *out_value)
|
||||
{
|
||||
if (!value || value->type != dcfg_ValueType_Boolean)
|
||||
return false;
|
||||
if (out_value)
|
||||
*out_value = value->v.b;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool dcfg_Value_get_integer(dcfg_Value *value, int64_t *out_value)
|
||||
{
|
||||
if (!value || value->type != dcfg_ValueType_Integer)
|
||||
return false;
|
||||
if (out_value)
|
||||
*out_value = value->v.i;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool dcfg_Value_get_real(dcfg_Value *value, double *out_value)
|
||||
{
|
||||
if (!value || value->type != dcfg_ValueType_Real)
|
||||
return false;
|
||||
if (out_value)
|
||||
*out_value = value->v.r;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool dcfg_Value_get_string(dcfg_Value *value, dcfg_StringView *out_sv)
|
||||
{
|
||||
if (!value || value->type != dcfg_ValueType_String)
|
||||
return false;
|
||||
if (out_sv)
|
||||
*out_sv = value->v.s;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool dcfg_Value_get_path(dcfg_Value *value, dcfg_StringView *out_sv)
|
||||
{
|
||||
if (!value || value->type != dcfg_ValueType_Path)
|
||||
return false;
|
||||
if (out_sv)
|
||||
*out_sv = value->v.p;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool dcfg_Value_get_object_keys(dcfg_Value *value, size_t capacity,
|
||||
size_t *out_count, dcfg_StringView *out_keys)
|
||||
{
|
||||
if (!value || value->type != dcfg_ValueType_Object)
|
||||
return false;
|
||||
|
||||
ValueObject *obj = &value->v.o;
|
||||
size_t count = vector_size(obj->entryv);
|
||||
if (out_count)
|
||||
*out_count = count;
|
||||
|
||||
if (out_keys) {
|
||||
size_t n = capacity < count ? capacity : count;
|
||||
for (size_t i = 0; i < n; ++i)
|
||||
out_keys[i] = obj->entryv[i].k;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool dcfg_Value_get_array_size(dcfg_Value *value, size_t *out_size)
|
||||
{
|
||||
if (!value || value->type != dcfg_ValueType_Array)
|
||||
return false;
|
||||
if (out_size)
|
||||
*out_size = vector_size(value->v.a.valuev);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool dcfg_call_function(dcfg_Value *function, dcfg_Value **args,
|
||||
size_t arg_count, dcfg_Value **out_value)
|
||||
{
|
||||
(void)function, (void)args, (void)arg_count, (void)out_value;
|
||||
// FIXME: Implement
|
||||
return false;
|
||||
}
|
||||
|
||||
bool dcfg_Value_evaluate(dcfg_Value *value, dcfg_Value **out_value)
|
||||
{
|
||||
(void)value, (void)out_value;
|
||||
// FIXME: Implement
|
||||
return false;
|
||||
}
|
||||
|
||||
// Libraries
|
||||
#include "vendor/utf8proc.c"
|
||||
#include "vendor/vec.c"
|
||||
|
Reference in New Issue
Block a user