feat: bemanitools 6 initial refactoring drop, alpha 1
**THIS IS A HIGHLY WORK/DEVELOPMENT IN PROGRESS VERSION**
**THINGS ARE BROKEN AND EVERYTHING IS SUBJECT TO CHANGE**
First cut after massive refactoring with most critical and fundamental changes implemented.
We need to start somewhere, and this might be as good as anything else, so we can get started
with testing, bug fixing and iterating for the next releases.
The following list is non-exhaustive, does not guarantee anything does work, yet, and is supposed
to give a high level idea of what all of this is about. Updated documentation will reflect all of
this at some later point in time in more detail.
* A common "core" now abstracts logging, thread, property and configuration infrastructure and
provides a common interface. This is used by bemanitools internally as well as all tools, hooks
and APIs provided and don't depend on the game, version of the game or AVS version available
anymore
* New bemanitools (public) API
* Versioned API allowing for handling incremental API changes as well as breaking changes by
providing a new/different version when necessary
* Unified interfaces for bemanitools core API, i.e. logging, threads, configuration
* SDK with examples (TBD)
* Dogfooding approach: Bemanitools uses its own (public) API to implement and provide fundamental
features like configurable keyboard implementations for IO or hooks for different games and
versions
* All bemanitools hooks and IO libraries have been or are about to be re-worked to use the new APIs
* New hook API allows for more fine grained runtime control when stages of the hook are to be
executed, i.e. pre AVS, before main game, iat hooking instead of relying purely on DllMain
(which is still a compatible option though)
* launcher as a replacement for bootstrap: Bring it significantly closer to the original bootstrap
by supporting completely vanilla data and bootstrap.xml configurations to run the games. Note
that bemanitools does not include any code or means to run DRM'd data, only decrypted
* inject is also being reworked to use as much of the same "infrastructure" as launcher to provide
a more seamless bootstrapping process for games that keeps pre-eapki data as vanilla as possible
Summary:
Test Plan:
Summary:
Test Plan:
Summary:
Test Plan:
Summary:
Test Plan:
This commit is contained in:
+10
-4
@@ -4,6 +4,8 @@ libs_core := \
|
||||
util \
|
||||
|
||||
src_core := \
|
||||
boot.c \
|
||||
config-property-node.c \
|
||||
log-bt-ext.c \
|
||||
log-bt.c \
|
||||
log-sink-async.c \
|
||||
@@ -13,8 +15,12 @@ src_core := \
|
||||
log-sink-mutex.c \
|
||||
log-sink-null.c \
|
||||
log-sink-std.c \
|
||||
log.c \
|
||||
thread-crt-ext.c \
|
||||
property-ext.c \
|
||||
property-mxml.c \
|
||||
property-mxml.c \
|
||||
property-node-ext.c \
|
||||
property-node-trace.c \
|
||||
property-node.c \
|
||||
property-trace.c \
|
||||
property.c \
|
||||
thread-crt.c \
|
||||
thread.c \
|
||||
|
||||
|
||||
@@ -0,0 +1,107 @@
|
||||
#define LOG_MODULE "core-boot"
|
||||
|
||||
#include <debugapi.h>
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "core/property-mxml.h"
|
||||
#include "core/property-node-mxml.h"
|
||||
#include "core/thread-crt.h"
|
||||
|
||||
#include "iface-core/log.h"
|
||||
|
||||
#include "util/str.h"
|
||||
|
||||
#define CORE_BOOT_LOG_MODULE_SIZE_MAX 128
|
||||
/* 64k so we can log data dumps of rs232 without crashing */
|
||||
#define CORE_BOOT_LOG_MSG_SIZE_MAX 65536
|
||||
|
||||
static void _core_boot_log_std_msg(const char *module, const char *fmt, ...)
|
||||
{
|
||||
va_list args;
|
||||
|
||||
va_start(args, fmt);
|
||||
|
||||
printf("[%s] ", module);
|
||||
vprintf(fmt, args);
|
||||
printf("\n");
|
||||
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
static void _core_boot_log_debug_msg(const char *module, const char *fmt, ...)
|
||||
{
|
||||
char module_str[CORE_BOOT_LOG_MODULE_SIZE_MAX];
|
||||
char msg[CORE_BOOT_LOG_MSG_SIZE_MAX];
|
||||
va_list args;
|
||||
|
||||
va_start(args, fmt);
|
||||
|
||||
str_format(module_str, sizeof(module_str), "[%s] ", module);
|
||||
str_vformat(msg, sizeof(msg), fmt, args);
|
||||
OutputDebugStringA(module_str);
|
||||
OutputDebugStringA(msg);
|
||||
OutputDebugStringA("\n");
|
||||
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
static void _core_boot_minimal_logging_std_env_init()
|
||||
{
|
||||
_core_boot_log_std_msg(
|
||||
LOG_MODULE, "Init minimal logging environment (std)");
|
||||
|
||||
// Initialize logging directly to avoid a bootstrapping issue
|
||||
// with not having any kind of logging to bootstrap the full
|
||||
// featured logging system
|
||||
_bt_core_log_api.version = 1;
|
||||
|
||||
_bt_core_log_api.v1.misc = _core_boot_log_std_msg;
|
||||
_bt_core_log_api.v1.info = _core_boot_log_std_msg;
|
||||
_bt_core_log_api.v1.warning = _core_boot_log_std_msg;
|
||||
_bt_core_log_api.v1.fatal = _core_boot_log_std_msg;
|
||||
|
||||
log_info("Init minimal logging environment done");
|
||||
}
|
||||
|
||||
static void _core_boot_minimal_logging_debug_env_init()
|
||||
{
|
||||
_core_boot_log_debug_msg(
|
||||
LOG_MODULE, "Init minimal logging environment (debug)");
|
||||
|
||||
// Initialize logging directly to avoid a bootstrapping issue
|
||||
// with not having any kind of logging to bootstrap the full
|
||||
// featured logging system
|
||||
_bt_core_log_api.version = 1;
|
||||
|
||||
_bt_core_log_api.v1.misc = _core_boot_log_debug_msg;
|
||||
_bt_core_log_api.v1.info = _core_boot_log_debug_msg;
|
||||
_bt_core_log_api.v1.warning = _core_boot_log_debug_msg;
|
||||
_bt_core_log_api.v1.fatal = _core_boot_log_debug_msg;
|
||||
|
||||
log_info("Init minimal logging environment done");
|
||||
}
|
||||
|
||||
void core_boot(const char *name)
|
||||
{
|
||||
_core_boot_log_std_msg(LOG_MODULE, "Boot: %s", name);
|
||||
|
||||
_core_boot_minimal_logging_std_env_init();
|
||||
|
||||
core_thread_crt_core_api_set();
|
||||
|
||||
core_property_mxml_core_api_set();
|
||||
core_property_node_mxml_core_api_set();
|
||||
}
|
||||
|
||||
void core_boot_dll(const char *name)
|
||||
{
|
||||
_core_boot_log_debug_msg(LOG_MODULE, "Boot: %s", name);
|
||||
|
||||
_core_boot_minimal_logging_debug_env_init();
|
||||
|
||||
core_thread_crt_core_api_set();
|
||||
|
||||
core_property_mxml_core_api_set();
|
||||
core_property_node_mxml_core_api_set();
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
#ifndef CORE_BOOT_H
|
||||
#define CORE_BOOT_H
|
||||
|
||||
void core_boot(const char *name);
|
||||
|
||||
void core_boot_dll(const char *name);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,346 @@
|
||||
#define LOG_MODULE "core-config-property-node"
|
||||
|
||||
#include "api/core/config.h"
|
||||
|
||||
#include "main/core/config-property-node.h"
|
||||
#include "main/core/property-node.h"
|
||||
#include "main/core/property.h"
|
||||
|
||||
#include "iface-core/log.h"
|
||||
|
||||
#include "util/mem.h"
|
||||
|
||||
typedef struct core_config_property_node {
|
||||
const core_property_node_t *node;
|
||||
} core_config_property_node_t;
|
||||
|
||||
static bt_core_config_result_t
|
||||
_core_config_property_node_result_map(core_property_node_result_t result)
|
||||
{
|
||||
switch (result) {
|
||||
case CORE_PROPERTY_NODE_RESULT_SUCCESS:
|
||||
return BT_CORE_CONFIG_RESULT_SUCCESS;
|
||||
case CORE_PROPERTY_NODE_RESULT_ERROR_INTERNAL:
|
||||
return BT_CORE_CONFIG_RESULT_ERROR_INTERNAL;
|
||||
case CORE_PROPERTY_NODE_RESULT_NODE_NOT_FOUND:
|
||||
return BT_CORE_CONFIG_RESULT_VALUE_NOT_FOUND;
|
||||
default:
|
||||
return BT_CORE_CONFIG_RESULT_ERROR_INTERNAL;
|
||||
}
|
||||
}
|
||||
|
||||
static bt_core_config_result_t _core_config_property_node_s8_get(
|
||||
const bt_core_config_t *config_, const char *path, int8_t *value)
|
||||
{
|
||||
const core_config_property_node_t *config;
|
||||
core_property_node_t node;
|
||||
core_property_node_result_t result;
|
||||
|
||||
config = (const core_config_property_node_t *) config_;
|
||||
|
||||
result = core_property_node_search(config->node, path, &node);
|
||||
|
||||
if (CORE_PROPERTY_NODE_RESULT_IS_ERROR(result)) {
|
||||
return _core_config_property_node_result_map(result);
|
||||
}
|
||||
|
||||
result = core_property_node_s8_read(&node, value);
|
||||
|
||||
return _core_config_property_node_result_map(result);
|
||||
}
|
||||
|
||||
static bt_core_config_result_t _core_config_property_node_u8_get(
|
||||
const bt_core_config_t *config_, const char *path, uint8_t *value)
|
||||
{
|
||||
const core_config_property_node_t *config;
|
||||
core_property_node_t node;
|
||||
core_property_node_result_t result;
|
||||
|
||||
config = (const core_config_property_node_t *) config_;
|
||||
|
||||
result = core_property_node_search(config->node, path, &node);
|
||||
|
||||
if (CORE_PROPERTY_NODE_RESULT_IS_ERROR(result)) {
|
||||
return _core_config_property_node_result_map(result);
|
||||
}
|
||||
|
||||
result = core_property_node_u8_read(&node, value);
|
||||
|
||||
return _core_config_property_node_result_map(result);
|
||||
}
|
||||
|
||||
static bt_core_config_result_t _core_config_property_node_s16_get(
|
||||
const bt_core_config_t *config_, const char *path, int16_t *value)
|
||||
{
|
||||
const core_config_property_node_t *config;
|
||||
core_property_node_t node;
|
||||
core_property_node_result_t result;
|
||||
|
||||
config = (const core_config_property_node_t *) config_;
|
||||
|
||||
result = core_property_node_search(config->node, path, &node);
|
||||
|
||||
if (CORE_PROPERTY_NODE_RESULT_IS_ERROR(result)) {
|
||||
return _core_config_property_node_result_map(result);
|
||||
}
|
||||
|
||||
result = core_property_node_s16_read(&node, value);
|
||||
|
||||
return _core_config_property_node_result_map(result);
|
||||
}
|
||||
|
||||
static bt_core_config_result_t _core_config_property_node_u16_get(
|
||||
const bt_core_config_t *config_, const char *path, uint16_t *value)
|
||||
{
|
||||
const core_config_property_node_t *config;
|
||||
core_property_node_t node;
|
||||
core_property_node_result_t result;
|
||||
|
||||
config = (const core_config_property_node_t *) config_;
|
||||
|
||||
result = core_property_node_search(config->node, path, &node);
|
||||
|
||||
if (CORE_PROPERTY_NODE_RESULT_IS_ERROR(result)) {
|
||||
return _core_config_property_node_result_map(result);
|
||||
}
|
||||
|
||||
result = core_property_node_u16_read(&node, value);
|
||||
|
||||
return _core_config_property_node_result_map(result);
|
||||
}
|
||||
|
||||
static bt_core_config_result_t _core_config_property_node_s32_get(
|
||||
const bt_core_config_t *config_, const char *path, int32_t *value)
|
||||
{
|
||||
const core_config_property_node_t *config;
|
||||
core_property_node_t node;
|
||||
core_property_node_result_t result;
|
||||
|
||||
config = (const core_config_property_node_t *) config_;
|
||||
|
||||
result = core_property_node_search(config->node, path, &node);
|
||||
|
||||
if (CORE_PROPERTY_NODE_RESULT_IS_ERROR(result)) {
|
||||
return _core_config_property_node_result_map(result);
|
||||
}
|
||||
|
||||
result = core_property_node_s32_read(&node, value);
|
||||
|
||||
return _core_config_property_node_result_map(result);
|
||||
}
|
||||
|
||||
static bt_core_config_result_t _core_config_property_node_u32_get(
|
||||
const bt_core_config_t *config_, const char *path, uint32_t *value)
|
||||
{
|
||||
const core_config_property_node_t *config;
|
||||
core_property_node_t node;
|
||||
core_property_node_result_t result;
|
||||
|
||||
config = (const core_config_property_node_t *) config_;
|
||||
|
||||
result = core_property_node_search(config->node, path, &node);
|
||||
|
||||
if (CORE_PROPERTY_NODE_RESULT_IS_ERROR(result)) {
|
||||
return _core_config_property_node_result_map(result);
|
||||
}
|
||||
|
||||
result = core_property_node_u32_read(&node, value);
|
||||
|
||||
return _core_config_property_node_result_map(result);
|
||||
}
|
||||
|
||||
static bt_core_config_result_t _core_config_property_node_s64_get(
|
||||
const bt_core_config_t *config_, const char *path, int64_t *value)
|
||||
{
|
||||
const core_config_property_node_t *config;
|
||||
core_property_node_t node;
|
||||
core_property_node_result_t result;
|
||||
|
||||
config = (const core_config_property_node_t *) config_;
|
||||
|
||||
result = core_property_node_search(config->node, path, &node);
|
||||
|
||||
if (CORE_PROPERTY_NODE_RESULT_IS_ERROR(result)) {
|
||||
return _core_config_property_node_result_map(result);
|
||||
}
|
||||
|
||||
result = core_property_node_s64_read(&node, value);
|
||||
|
||||
return _core_config_property_node_result_map(result);
|
||||
}
|
||||
|
||||
static bt_core_config_result_t _core_config_property_node_u64_get(
|
||||
const bt_core_config_t *config_, const char *path, uint64_t *value)
|
||||
{
|
||||
const core_config_property_node_t *config;
|
||||
core_property_node_t node;
|
||||
core_property_node_result_t result;
|
||||
|
||||
config = (const core_config_property_node_t *) config_;
|
||||
|
||||
result = core_property_node_search(config->node, path, &node);
|
||||
|
||||
if (CORE_PROPERTY_NODE_RESULT_IS_ERROR(result)) {
|
||||
return _core_config_property_node_result_map(result);
|
||||
}
|
||||
|
||||
result = core_property_node_u64_read(&node, value);
|
||||
|
||||
return _core_config_property_node_result_map(result);
|
||||
}
|
||||
|
||||
static bt_core_config_result_t _core_config_property_node_float_get(
|
||||
const bt_core_config_t *config_, const char *path, float *value)
|
||||
{
|
||||
const core_config_property_node_t *config;
|
||||
core_property_node_t node;
|
||||
core_property_node_result_t result;
|
||||
|
||||
config = (const core_config_property_node_t *) config_;
|
||||
|
||||
result = core_property_node_search(config->node, path, &node);
|
||||
|
||||
if (CORE_PROPERTY_NODE_RESULT_IS_ERROR(result)) {
|
||||
return _core_config_property_node_result_map(result);
|
||||
}
|
||||
|
||||
result = core_property_node_float_read(&node, value);
|
||||
|
||||
return _core_config_property_node_result_map(result);
|
||||
}
|
||||
|
||||
static bt_core_config_result_t _core_config_property_node_double_get(
|
||||
const bt_core_config_t *config_, const char *path, double *value)
|
||||
{
|
||||
const core_config_property_node_t *config;
|
||||
core_property_node_t node;
|
||||
core_property_node_result_t result;
|
||||
|
||||
config = (const core_config_property_node_t *) config_;
|
||||
|
||||
result = core_property_node_search(config->node, path, &node);
|
||||
|
||||
if (CORE_PROPERTY_NODE_RESULT_IS_ERROR(result)) {
|
||||
return _core_config_property_node_result_map(result);
|
||||
}
|
||||
|
||||
result = core_property_node_double_read(&node, value);
|
||||
|
||||
return _core_config_property_node_result_map(result);
|
||||
}
|
||||
|
||||
static bt_core_config_result_t _core_config_property_node_bool_get(
|
||||
const bt_core_config_t *config_, const char *path, bool *value)
|
||||
{
|
||||
const core_config_property_node_t *config;
|
||||
core_property_node_t node;
|
||||
core_property_node_result_t result;
|
||||
|
||||
config = (const core_config_property_node_t *) config_;
|
||||
|
||||
result = core_property_node_search(config->node, path, &node);
|
||||
|
||||
if (CORE_PROPERTY_NODE_RESULT_IS_ERROR(result)) {
|
||||
return _core_config_property_node_result_map(result);
|
||||
}
|
||||
|
||||
result = core_property_node_bool_read(&node, value);
|
||||
|
||||
return _core_config_property_node_result_map(result);
|
||||
}
|
||||
|
||||
static bt_core_config_result_t _core_config_property_node_bin_get(
|
||||
const bt_core_config_t *config_, const char *path, void *value, size_t len)
|
||||
{
|
||||
const core_config_property_node_t *config;
|
||||
core_property_node_t node;
|
||||
core_property_node_result_t result;
|
||||
|
||||
config = (const core_config_property_node_t *) config_;
|
||||
|
||||
result = core_property_node_search(config->node, path, &node);
|
||||
|
||||
if (CORE_PROPERTY_NODE_RESULT_IS_ERROR(result)) {
|
||||
return _core_config_property_node_result_map(result);
|
||||
}
|
||||
|
||||
result = core_property_node_bin_read(&node, value, len);
|
||||
|
||||
return _core_config_property_node_result_map(result);
|
||||
}
|
||||
|
||||
static bt_core_config_result_t _core_config_property_node_str_get(
|
||||
const bt_core_config_t *config_, const char *path, char *value, size_t len)
|
||||
{
|
||||
const core_config_property_node_t *config;
|
||||
core_property_node_t node;
|
||||
core_property_node_result_t result;
|
||||
|
||||
config = (const core_config_property_node_t *) config_;
|
||||
|
||||
result = core_property_node_search(config->node, path, &node);
|
||||
|
||||
if (CORE_PROPERTY_NODE_RESULT_IS_ERROR(result)) {
|
||||
return _core_config_property_node_result_map(result);
|
||||
}
|
||||
|
||||
result = core_property_node_str_read(&node, value, len);
|
||||
|
||||
return _core_config_property_node_result_map(result);
|
||||
}
|
||||
|
||||
static void _core_config_property_node_core_api_get(bt_core_config_api_t *api)
|
||||
{
|
||||
log_assert(api);
|
||||
|
||||
api->version = 1;
|
||||
|
||||
api->v1.s8_get = _core_config_property_node_s8_get;
|
||||
api->v1.u8_get = _core_config_property_node_u8_get;
|
||||
api->v1.s16_get = _core_config_property_node_s16_get;
|
||||
api->v1.u16_get = _core_config_property_node_u16_get;
|
||||
api->v1.s32_get = _core_config_property_node_s32_get;
|
||||
api->v1.u32_get = _core_config_property_node_u32_get;
|
||||
api->v1.s64_get = _core_config_property_node_s64_get;
|
||||
api->v1.u64_get = _core_config_property_node_u64_get;
|
||||
api->v1.float_get = _core_config_property_node_float_get;
|
||||
api->v1.double_get = _core_config_property_node_double_get;
|
||||
api->v1.bool_get = _core_config_property_node_bool_get;
|
||||
api->v1.bin_get = _core_config_property_node_bin_get;
|
||||
api->v1.str_get = _core_config_property_node_str_get;
|
||||
}
|
||||
|
||||
void core_config_property_node_core_api_set()
|
||||
{
|
||||
bt_core_config_api_t api;
|
||||
|
||||
_core_config_property_node_core_api_get(&api);
|
||||
bt_core_config_api_set(&api);
|
||||
}
|
||||
|
||||
void core_config_property_node_init(
|
||||
const core_property_node_t *node, bt_core_config_t **config_)
|
||||
{
|
||||
core_config_property_node_t *config;
|
||||
|
||||
log_assert(node);
|
||||
log_assert(config_);
|
||||
|
||||
config = xmalloc(sizeof(core_config_property_node_t));
|
||||
|
||||
config->node = node;
|
||||
|
||||
*config_ = (bt_core_config_t *) config;
|
||||
}
|
||||
|
||||
void core_config_property_node_free(bt_core_config_t **config_)
|
||||
{
|
||||
core_config_property_node_t **config;
|
||||
|
||||
log_assert(config_);
|
||||
|
||||
config = (core_config_property_node_t **) config_;
|
||||
|
||||
free(*config);
|
||||
*config = NULL;
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
#ifndef CORE_CONFIG_PROPERTY_NODE_H
|
||||
#define CORE_CONFIG_PROPERTY_NODE_H
|
||||
|
||||
#include "iface-core/config.h"
|
||||
|
||||
#include "core/property-node.h"
|
||||
|
||||
void core_config_property_node_core_api_set();
|
||||
|
||||
void core_config_property_node_init(
|
||||
const core_property_node_t *node, bt_core_config_t **config);
|
||||
|
||||
void core_config_property_node_free(bt_core_config_t **config);
|
||||
|
||||
#endif
|
||||
+25
-17
@@ -1,3 +1,5 @@
|
||||
#define LOG_MODULE "core-log-bt-ext"
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "core/log-bt.h"
|
||||
@@ -6,20 +8,10 @@
|
||||
#include "core/log-sink-list.h"
|
||||
#include "core/log-sink-mutex.h"
|
||||
#include "core/log-sink-std.h"
|
||||
#include "core/log.h"
|
||||
|
||||
void core_log_bt_ext_impl_set()
|
||||
{
|
||||
core_log_impl_set(
|
||||
core_log_bt_log_misc,
|
||||
core_log_bt_log_info,
|
||||
core_log_bt_log_warning,
|
||||
core_log_bt_log_fatal);
|
||||
}
|
||||
|
||||
void core_log_bt_ext_init_with_stdout()
|
||||
{
|
||||
struct core_log_sink sink;
|
||||
core_log_sink_t sink;
|
||||
|
||||
core_log_sink_std_out_open(true, &sink);
|
||||
core_log_bt_init(&sink);
|
||||
@@ -27,7 +19,7 @@ void core_log_bt_ext_init_with_stdout()
|
||||
|
||||
void core_log_bt_ext_init_with_stderr()
|
||||
{
|
||||
struct core_log_sink sink;
|
||||
core_log_sink_t sink;
|
||||
|
||||
core_log_sink_std_err_open(true, &sink);
|
||||
core_log_bt_init(&sink);
|
||||
@@ -35,7 +27,7 @@ void core_log_bt_ext_init_with_stderr()
|
||||
|
||||
void core_log_bt_ext_init_with_debug()
|
||||
{
|
||||
struct core_log_sink sink;
|
||||
core_log_sink_t sink;
|
||||
|
||||
core_log_sink_debug_open(&sink);
|
||||
core_log_bt_init(&sink);
|
||||
@@ -44,7 +36,7 @@ void core_log_bt_ext_init_with_debug()
|
||||
void core_log_bt_ext_init_with_file(
|
||||
const char *path, bool append, bool rotate, uint8_t max_rotations)
|
||||
{
|
||||
struct core_log_sink sink;
|
||||
core_log_sink_t sink;
|
||||
|
||||
core_log_sink_file_open(path, append, rotate, max_rotations, &sink);
|
||||
core_log_bt_init(&sink);
|
||||
@@ -53,9 +45,9 @@ void core_log_bt_ext_init_with_file(
|
||||
void core_log_bt_ext_init_with_stdout_and_file(
|
||||
const char *path, bool append, bool rotate, uint8_t max_rotations)
|
||||
{
|
||||
struct core_log_sink sinks[2];
|
||||
struct core_log_sink sink_composed;
|
||||
struct core_log_sink sink_mutex;
|
||||
core_log_sink_t sinks[2];
|
||||
core_log_sink_t sink_composed;
|
||||
core_log_sink_t sink_mutex;
|
||||
|
||||
core_log_sink_std_out_open(true, &sinks[0]);
|
||||
core_log_sink_file_open(path, append, rotate, max_rotations, &sinks[1]);
|
||||
@@ -63,5 +55,21 @@ void core_log_bt_ext_init_with_stdout_and_file(
|
||||
|
||||
core_log_sink_mutex_open(&sink_composed, &sink_mutex);
|
||||
|
||||
core_log_bt_init(&sink_mutex);
|
||||
}
|
||||
|
||||
void core_log_bt_ext_init_with_stderr_and_file(
|
||||
const char *path, bool append, bool rotate, uint8_t max_rotations)
|
||||
{
|
||||
core_log_sink_t sinks[2];
|
||||
core_log_sink_t sink_composed;
|
||||
core_log_sink_t sink_mutex;
|
||||
|
||||
core_log_sink_std_err_open(true, &sinks[0]);
|
||||
core_log_sink_file_open(path, append, rotate, max_rotations, &sinks[1]);
|
||||
core_log_sink_list_open(sinks, 2, &sink_composed);
|
||||
|
||||
core_log_sink_mutex_open(&sink_composed, &sink_mutex);
|
||||
|
||||
core_log_bt_init(&sink_mutex);
|
||||
}
|
||||
@@ -4,12 +4,6 @@
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
/**
|
||||
* Set the current thread API implementation to use the bemanitools log
|
||||
* implementation
|
||||
*/
|
||||
void core_log_bt_ext_impl_set();
|
||||
|
||||
/**
|
||||
* Helper to setup the bemanitools log implementation with a stdout sink.
|
||||
*/
|
||||
@@ -56,4 +50,7 @@ void core_log_bt_ext_init_with_file(
|
||||
void core_log_bt_ext_init_with_stdout_and_file(
|
||||
const char *path, bool append, bool rotate, uint8_t max_rotations);
|
||||
|
||||
void core_log_bt_ext_init_with_stderr_and_file(
|
||||
const char *path, bool append, bool rotate, uint8_t max_rotations);
|
||||
|
||||
#endif
|
||||
+111
-63
@@ -1,18 +1,25 @@
|
||||
#define LOG_MODULE "core-log-bt"
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
|
||||
#include "core/log-bt.h"
|
||||
#include "core/log-sink.h"
|
||||
#include "core/log.h"
|
||||
#include "iface-core/log.h"
|
||||
|
||||
#include "main/core/log-bt.h"
|
||||
#include "main/core/log-sink.h"
|
||||
|
||||
#include "util/mem.h"
|
||||
#include "util/str.h"
|
||||
|
||||
static enum core_log_bt_log_level _core_log_bt_log_level;
|
||||
static struct core_log_sink *_core_log_bt_sink;
|
||||
/* 64k so we can log data dumps of rs232 without crashing */
|
||||
#define CORE_LOG_MSG_SIZE_MAX 65536
|
||||
#define CORE_LOG_TIMESTAMP_SIZE_MAX 64
|
||||
|
||||
static void _core_log_bt_vformat_write(
|
||||
static enum core_log_bt_log_level _core_log_bt_log_level;
|
||||
static core_log_sink_t *_core_log_bt_sink;
|
||||
|
||||
static void _core_log_bt_vformat_timestamp_log_level_write(
|
||||
enum core_log_bt_log_level level,
|
||||
const char *module,
|
||||
const char *fmt,
|
||||
@@ -20,10 +27,9 @@ static void _core_log_bt_vformat_write(
|
||||
{
|
||||
static const char chars[] = "FFWIM";
|
||||
|
||||
char timestamp[64];
|
||||
/* 64k so we can log data dumps of rs232 without crashing */
|
||||
char msg[65536];
|
||||
char line[65536];
|
||||
char timestamp[CORE_LOG_TIMESTAMP_SIZE_MAX];
|
||||
char msg[CORE_LOG_MSG_SIZE_MAX];
|
||||
char line[CORE_LOG_MSG_SIZE_MAX];
|
||||
int result;
|
||||
|
||||
time_t curtime;
|
||||
@@ -51,20 +57,106 @@ static void _core_log_bt_vformat_write(
|
||||
_core_log_bt_sink->write(_core_log_bt_sink->ctx, line, result);
|
||||
}
|
||||
|
||||
void core_log_bt_init(const struct core_log_sink *sink)
|
||||
static void _core_log_bt_log_misc(const char *module, const char *fmt, ...)
|
||||
{
|
||||
if (sink == NULL) {
|
||||
abort();
|
||||
}
|
||||
va_list args;
|
||||
|
||||
_core_log_bt_sink = xmalloc(sizeof(struct core_log_sink));
|
||||
memcpy(_core_log_bt_sink, sink, sizeof(struct core_log_sink));
|
||||
if (_core_log_bt_log_level >= CORE_LOG_BT_LOG_LEVEL_MISC) {
|
||||
va_start(args, fmt);
|
||||
_core_log_bt_vformat_timestamp_log_level_write(
|
||||
CORE_LOG_BT_LOG_LEVEL_MISC, module, fmt, args);
|
||||
va_end(args);
|
||||
}
|
||||
}
|
||||
|
||||
static void _core_log_bt_log_info(const char *module, const char *fmt, ...)
|
||||
{
|
||||
va_list args;
|
||||
|
||||
if (_core_log_bt_log_level >= CORE_LOG_BT_LOG_LEVEL_INFO) {
|
||||
va_start(args, fmt);
|
||||
_core_log_bt_vformat_timestamp_log_level_write(
|
||||
CORE_LOG_BT_LOG_LEVEL_INFO, module, fmt, args);
|
||||
va_end(args);
|
||||
}
|
||||
}
|
||||
|
||||
static void _core_log_bt_log_warning(const char *module, const char *fmt, ...)
|
||||
{
|
||||
va_list args;
|
||||
|
||||
if (_core_log_bt_log_level >= CORE_LOG_BT_LOG_LEVEL_WARNING) {
|
||||
va_start(args, fmt);
|
||||
_core_log_bt_vformat_timestamp_log_level_write(
|
||||
CORE_LOG_BT_LOG_LEVEL_WARNING, module, fmt, args);
|
||||
va_end(args);
|
||||
}
|
||||
}
|
||||
|
||||
static void _core_log_bt_log_fatal(const char *module, const char *fmt, ...)
|
||||
{
|
||||
va_list args;
|
||||
|
||||
if (_core_log_bt_log_level >= CORE_LOG_BT_LOG_LEVEL_FATAL) {
|
||||
va_start(args, fmt);
|
||||
_core_log_bt_vformat_timestamp_log_level_write(
|
||||
CORE_LOG_BT_LOG_LEVEL_FATAL, module, fmt, args);
|
||||
va_end(args);
|
||||
}
|
||||
}
|
||||
|
||||
void core_log_bt_core_api_get(bt_core_log_api_t *api)
|
||||
{
|
||||
log_assert(api);
|
||||
|
||||
api->version = 1;
|
||||
|
||||
api->v1.misc = _core_log_bt_log_misc;
|
||||
api->v1.info = _core_log_bt_log_info;
|
||||
api->v1.warning = _core_log_bt_log_warning;
|
||||
api->v1.fatal = _core_log_bt_log_fatal;
|
||||
}
|
||||
|
||||
void core_log_bt_core_api_set()
|
||||
{
|
||||
bt_core_log_api_t api;
|
||||
|
||||
core_log_bt_core_api_get(&api);
|
||||
bt_core_log_api_set(&api);
|
||||
}
|
||||
|
||||
void core_log_bt_init(const core_log_sink_t *sink)
|
||||
{
|
||||
log_assert(sink);
|
||||
|
||||
log_misc("Init");
|
||||
|
||||
_core_log_bt_sink = xmalloc(sizeof(core_log_sink_t));
|
||||
memcpy(_core_log_bt_sink, sink, sizeof(core_log_sink_t));
|
||||
|
||||
_core_log_bt_log_level = CORE_LOG_BT_LOG_LEVEL_OFF;
|
||||
}
|
||||
|
||||
void core_log_bt_reinit(const core_log_sink_t *sink)
|
||||
{
|
||||
log_assert(_core_log_bt_sink);
|
||||
|
||||
log_misc("Re-init");
|
||||
|
||||
_core_log_bt_sink->close(_core_log_bt_sink->ctx);
|
||||
|
||||
free(_core_log_bt_sink);
|
||||
|
||||
_core_log_bt_sink = xmalloc(sizeof(core_log_sink_t));
|
||||
memcpy(_core_log_bt_sink, sink, sizeof(core_log_sink_t));
|
||||
|
||||
_core_log_bt_log_level = CORE_LOG_BT_LOG_LEVEL_OFF;
|
||||
}
|
||||
|
||||
void core_log_bt_level_set(enum core_log_bt_log_level level)
|
||||
{
|
||||
log_misc("Log level change from %d to %d", _core_log_bt_log_level, level);
|
||||
|
||||
_core_log_bt_log_level = level;
|
||||
}
|
||||
|
||||
@@ -72,58 +164,14 @@ void core_log_bt_fini()
|
||||
{
|
||||
log_assert(_core_log_bt_sink);
|
||||
|
||||
log_misc("Fini");
|
||||
|
||||
_core_log_bt_sink->close(_core_log_bt_sink->ctx);
|
||||
|
||||
free(_core_log_bt_sink);
|
||||
}
|
||||
|
||||
void core_log_bt_log_fatal(const char *module, const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
if (_core_log_bt_log_level >= CORE_LOG_BT_LOG_LEVEL_FATAL) {
|
||||
va_start(ap, fmt);
|
||||
_core_log_bt_vformat_write(
|
||||
CORE_LOG_BT_LOG_LEVEL_FATAL, module, fmt, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
}
|
||||
|
||||
void core_log_bt_log_warning(const char *module, const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
if (_core_log_bt_log_level >= CORE_LOG_BT_LOG_LEVEL_WARNING) {
|
||||
va_start(ap, fmt);
|
||||
_core_log_bt_vformat_write(
|
||||
CORE_LOG_BT_LOG_LEVEL_WARNING, module, fmt, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
}
|
||||
|
||||
void core_log_bt_log_info(const char *module, const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
if (_core_log_bt_log_level >= CORE_LOG_BT_LOG_LEVEL_INFO) {
|
||||
va_start(ap, fmt);
|
||||
_core_log_bt_vformat_write(CORE_LOG_BT_LOG_LEVEL_INFO, module, fmt, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
}
|
||||
|
||||
void core_log_bt_log_misc(const char *module, const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
if (_core_log_bt_log_level >= CORE_LOG_BT_LOG_LEVEL_MISC) {
|
||||
va_start(ap, fmt);
|
||||
_core_log_bt_vformat_write(CORE_LOG_BT_LOG_LEVEL_MISC, module, fmt, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
}
|
||||
|
||||
void core_log_bt_direct_sink_write(const char *chars, size_t nchars)
|
||||
{
|
||||
_core_log_bt_sink->write(_core_log_bt_sink->ctx, chars, nchars);
|
||||
}
|
||||
}
|
||||
|
||||
+13
-22
@@ -1,7 +1,9 @@
|
||||
#ifndef CORE_LOG_BT_H
|
||||
#define CORE_LOG_BT_H
|
||||
|
||||
#include "core/log-sink.h"
|
||||
#include "api/core/log.h"
|
||||
|
||||
#include "main/core/log-sink.h"
|
||||
|
||||
/**
|
||||
* Log API implementation for games/applications without AVS
|
||||
@@ -15,6 +17,12 @@ enum core_log_bt_log_level {
|
||||
CORE_LOG_BT_LOG_LEVEL_MISC = 4,
|
||||
};
|
||||
|
||||
void core_log_bt_core_api_get(bt_core_log_api_t *api);
|
||||
|
||||
// Note: this logger requires a minimal logger to be set-up beforehand
|
||||
// (log-mini)
|
||||
void core_log_bt_core_api_set();
|
||||
|
||||
/**
|
||||
* Initialize the logging backend
|
||||
*
|
||||
@@ -28,7 +36,10 @@ enum core_log_bt_log_level {
|
||||
* @param sink Pointer to a log sink implementation. The caller owns the memory
|
||||
* of this.
|
||||
*/
|
||||
void core_log_bt_init(const struct core_log_sink *sink);
|
||||
void core_log_bt_init(const core_log_sink_t *sink);
|
||||
|
||||
// special version to use when switching loggers
|
||||
void core_log_bt_reinit(const core_log_sink_t *sink);
|
||||
|
||||
/**
|
||||
* Set the current logging level. This can be changed at any given time, e.g.
|
||||
@@ -45,26 +56,6 @@ void core_log_bt_level_set(enum core_log_bt_log_level level);
|
||||
*/
|
||||
void core_log_bt_fini();
|
||||
|
||||
/**
|
||||
* Implementation of the log API.
|
||||
*/
|
||||
void core_log_bt_log_fatal(const char *module, const char *fmt, ...);
|
||||
|
||||
/**
|
||||
* Implementation of the log API.
|
||||
*/
|
||||
void core_log_bt_log_warning(const char *module, const char *fmt, ...);
|
||||
|
||||
/**
|
||||
* Implementation of the log API.
|
||||
*/
|
||||
void core_log_bt_log_info(const char *module, const char *fmt, ...);
|
||||
|
||||
/**
|
||||
* Implementation of the log API.
|
||||
*/
|
||||
void core_log_bt_log_misc(const char *module, const char *fmt, ...);
|
||||
|
||||
/**
|
||||
* Allow AVS to by-pass the core log API/engine.
|
||||
*
|
||||
|
||||
@@ -1,7 +1,11 @@
|
||||
#define LOG_MODULE "core-log-sink-async"
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "core/log-sink.h"
|
||||
|
||||
#include "iface-core/log.h"
|
||||
|
||||
static void
|
||||
_core_log_sink_file_write(void *ctx, const char *chars, size_t nchars)
|
||||
{
|
||||
@@ -13,10 +17,14 @@ static void _core_log_sink_file_close(void *ctx)
|
||||
// TODO
|
||||
}
|
||||
|
||||
void core_log_sink_async_open(struct core_log_sink *sink)
|
||||
void core_log_sink_async_open(core_log_sink_t *sink)
|
||||
{
|
||||
log_assert(sink);
|
||||
|
||||
// TODO
|
||||
|
||||
log_misc("Open");
|
||||
|
||||
sink->ctx = NULL;
|
||||
sink->write = _core_log_sink_file_write;
|
||||
sink->close = _core_log_sink_file_close;
|
||||
|
||||
@@ -14,6 +14,6 @@
|
||||
*
|
||||
* @param sink Pointer to allocated memory that receives the opened sink
|
||||
*/
|
||||
void core_log_sink_async_open(struct core_log_sink *sink);
|
||||
void core_log_sink_async_open(core_log_sink_t *sink);
|
||||
|
||||
#endif
|
||||
@@ -1,9 +1,13 @@
|
||||
#define LOG_MODULE "core-log-sink-debug"
|
||||
|
||||
#include <debugapi.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "core/log-sink.h"
|
||||
|
||||
#include "iface-core/log.h"
|
||||
|
||||
static void
|
||||
_core_log_sink_debug_write(void *ctx, const char *chars, size_t nchars)
|
||||
{
|
||||
@@ -15,8 +19,12 @@ static void _core_log_sink_debug_close(void *ctx)
|
||||
// noop
|
||||
}
|
||||
|
||||
void core_log_sink_debug_open(struct core_log_sink *sink)
|
||||
void core_log_sink_debug_open(core_log_sink_t *sink)
|
||||
{
|
||||
log_assert(sink);
|
||||
|
||||
log_misc("Open");
|
||||
|
||||
sink->ctx = NULL;
|
||||
sink->write = _core_log_sink_debug_write;
|
||||
sink->close = _core_log_sink_debug_close;
|
||||
|
||||
@@ -10,6 +10,6 @@
|
||||
*
|
||||
* @param sink Pointer to allocated memory that receives the opened sink
|
||||
*/
|
||||
void core_log_sink_debug_open(struct core_log_sink *sink);
|
||||
void core_log_sink_debug_open(core_log_sink_t *sink);
|
||||
|
||||
#endif
|
||||
@@ -1,3 +1,5 @@
|
||||
#define LOG_MODULE "core-log-sink-file"
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
#include <stdbool.h>
|
||||
@@ -7,6 +9,8 @@
|
||||
|
||||
#include "core/log-sink.h"
|
||||
|
||||
#include "iface-core/log.h"
|
||||
|
||||
#include "util/fs.h"
|
||||
#include "util/str.h"
|
||||
|
||||
@@ -64,10 +68,20 @@ void core_log_sink_file_open(
|
||||
bool append,
|
||||
bool rotate,
|
||||
uint8_t max_rotations,
|
||||
struct core_log_sink *sink)
|
||||
core_log_sink_t *sink)
|
||||
{
|
||||
FILE *file;
|
||||
|
||||
log_assert(path);
|
||||
log_assert(sink);
|
||||
|
||||
log_info(
|
||||
"Open: %s, append %s, rotate %d, max_rotations %d",
|
||||
path,
|
||||
append,
|
||||
rotate,
|
||||
max_rotations);
|
||||
|
||||
if (rotate) {
|
||||
_core_log_sink_file_rotate(path, max_rotations);
|
||||
|
||||
@@ -82,8 +96,7 @@ void core_log_sink_file_open(
|
||||
}
|
||||
|
||||
if (!file) {
|
||||
printf("Cannot open log file: %s", path);
|
||||
abort();
|
||||
log_fatal("Cannot open log file: %s", path);
|
||||
}
|
||||
|
||||
sink->ctx = (void *) file;
|
||||
|
||||
@@ -23,6 +23,6 @@ void core_log_sink_file_open(
|
||||
bool append,
|
||||
bool rotate,
|
||||
uint8_t max_rotations,
|
||||
struct core_log_sink *sink);
|
||||
core_log_sink_t *sink);
|
||||
|
||||
#endif
|
||||
@@ -1,25 +1,29 @@
|
||||
#define LOG_MODULE "core-log-sink-list"
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "core/log-sink-list.h"
|
||||
#include "core/log-sink.h"
|
||||
|
||||
#include "iface-core/log.h"
|
||||
|
||||
#include "util/mem.h"
|
||||
|
||||
#define MAX_SINKS 8
|
||||
|
||||
struct core_log_sink_list {
|
||||
struct core_log_sink entries[MAX_SINKS];
|
||||
typedef struct core_log_sink_list {
|
||||
core_log_sink_t entries[MAX_SINKS];
|
||||
uint8_t num;
|
||||
};
|
||||
} core_log_sink_list_t;
|
||||
|
||||
static void
|
||||
_core_log_sink_list_write(void *ctx, const char *chars, size_t nchars)
|
||||
{
|
||||
struct core_log_sink_list *sink_list;
|
||||
core_log_sink_list_t *sink_list;
|
||||
int i;
|
||||
|
||||
sink_list = (struct core_log_sink_list *) ctx;
|
||||
sink_list = (core_log_sink_list_t *) ctx;
|
||||
|
||||
for (i = 0; i < sink_list->num; i++) {
|
||||
sink_list->entries[i].write(sink_list->entries[i].ctx, chars, nchars);
|
||||
@@ -28,10 +32,10 @@ _core_log_sink_list_write(void *ctx, const char *chars, size_t nchars)
|
||||
|
||||
static void _core_log_sink_list_close(void *ctx)
|
||||
{
|
||||
struct core_log_sink_list *sink_list;
|
||||
core_log_sink_list_t *sink_list;
|
||||
int i;
|
||||
|
||||
sink_list = (struct core_log_sink_list *) ctx;
|
||||
sink_list = (core_log_sink_list_t *) ctx;
|
||||
|
||||
for (i = 0; i < sink_list->num; i++) {
|
||||
sink_list->entries[i].close(sink_list->entries[i].ctx);
|
||||
@@ -41,16 +45,21 @@ static void _core_log_sink_list_close(void *ctx)
|
||||
}
|
||||
|
||||
void core_log_sink_list_open(
|
||||
const struct core_log_sink *entry, uint8_t num, struct core_log_sink *sink)
|
||||
const core_log_sink_t *entry, uint8_t num, core_log_sink_t *sink)
|
||||
{
|
||||
struct core_log_sink_list *sink_list;
|
||||
core_log_sink_list_t *sink_list;
|
||||
int i;
|
||||
|
||||
log_assert(entry);
|
||||
log_assert(sink);
|
||||
|
||||
log_misc("Open: %d", num);
|
||||
|
||||
if (num > MAX_SINKS) {
|
||||
abort();
|
||||
}
|
||||
|
||||
sink_list = xmalloc(sizeof(struct core_log_sink_list));
|
||||
sink_list = xmalloc(sizeof(core_log_sink_list_t));
|
||||
|
||||
for (i = 0; i < num; i++) {
|
||||
sink_list->entries[i].ctx = entry[i].ctx;
|
||||
|
||||
@@ -19,6 +19,6 @@
|
||||
* @param sink Pointer to allocated memory that receives the opened sink
|
||||
*/
|
||||
void core_log_sink_list_open(
|
||||
const struct core_log_sink *entry, uint8_t num, struct core_log_sink *sink);
|
||||
const core_log_sink_t *entry, uint8_t num, core_log_sink_t *sink);
|
||||
|
||||
#endif
|
||||
@@ -1,50 +1,59 @@
|
||||
#define LOG_MODULE "core-log-sink-mutex"
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "core/log-sink.h"
|
||||
|
||||
#include "iface-core/log.h"
|
||||
|
||||
#include "util/mem.h"
|
||||
|
||||
struct core_log_sink_mutex_ctx {
|
||||
struct core_log_sink *child;
|
||||
typedef struct core_log_sink_mutex {
|
||||
core_log_sink_t child;
|
||||
HANDLE mutex;
|
||||
};
|
||||
} core_log_sink_mutex_t;
|
||||
|
||||
static void
|
||||
_core_log_sink_mutex_write(void *ctx_, const char *chars, size_t nchars)
|
||||
{
|
||||
struct core_log_sink_mutex_ctx *ctx;
|
||||
core_log_sink_mutex_t *ctx;
|
||||
|
||||
ctx = (struct core_log_sink_mutex_ctx *) ctx_;
|
||||
ctx = (core_log_sink_mutex_t *) ctx_;
|
||||
|
||||
WaitForSingleObject(ctx->mutex, INFINITE);
|
||||
|
||||
ctx->child->write(ctx->child->ctx, chars, nchars);
|
||||
ctx->child.write(ctx->child.ctx, chars, nchars);
|
||||
|
||||
ReleaseMutex(ctx->mutex);
|
||||
}
|
||||
|
||||
static void _core_log_sink_mutex_close(void *ctx_)
|
||||
{
|
||||
struct core_log_sink_mutex_ctx *ctx;
|
||||
core_log_sink_mutex_t *ctx;
|
||||
|
||||
ctx = (struct core_log_sink_mutex_ctx *) ctx_;
|
||||
ctx = (core_log_sink_mutex_t *) ctx_;
|
||||
|
||||
CloseHandle(ctx->mutex);
|
||||
|
||||
ctx->child->close(ctx->child->ctx);
|
||||
ctx->child.close(ctx->child.ctx);
|
||||
free(ctx);
|
||||
}
|
||||
|
||||
void core_log_sink_mutex_open(
|
||||
const struct core_log_sink *child_sink, struct core_log_sink *sink)
|
||||
const core_log_sink_t *child_sink, core_log_sink_t *sink)
|
||||
{
|
||||
struct core_log_sink_mutex_ctx *ctx;
|
||||
core_log_sink_mutex_t *ctx;
|
||||
|
||||
ctx = xmalloc(sizeof(struct core_log_sink_mutex_ctx));
|
||||
log_assert(child_sink);
|
||||
log_assert(sink);
|
||||
|
||||
memcpy(ctx->child, child_sink, sizeof(struct core_log_sink));
|
||||
log_misc("Open");
|
||||
|
||||
ctx = xmalloc(sizeof(core_log_sink_mutex_t));
|
||||
|
||||
memcpy(&ctx->child, child_sink, sizeof(core_log_sink_t));
|
||||
ctx->mutex = CreateMutex(NULL, FALSE, NULL);
|
||||
|
||||
sink->ctx = ctx;
|
||||
|
||||
@@ -16,6 +16,6 @@
|
||||
* @param sink Pointer to allocated memory that receives the opened sink
|
||||
*/
|
||||
void core_log_sink_mutex_open(
|
||||
const struct core_log_sink *child_sink, struct core_log_sink *sink);
|
||||
const core_log_sink_t *child_sink, core_log_sink_t *sink);
|
||||
|
||||
#endif
|
||||
@@ -1,7 +1,11 @@
|
||||
#define LOG_MODULE "core-log-sink-null"
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "core/log-sink.h"
|
||||
|
||||
#include "iface-core/log.h"
|
||||
|
||||
static void
|
||||
_core_log_sink_null_write(void *ctx, const char *chars, size_t nchars)
|
||||
{
|
||||
@@ -13,8 +17,12 @@ static void _core_log_sink_null_close(void *ctx)
|
||||
// noop
|
||||
}
|
||||
|
||||
void core_log_sink_null_open(struct core_log_sink *sink)
|
||||
void core_log_sink_null_open(core_log_sink_t *sink)
|
||||
{
|
||||
log_assert(sink);
|
||||
|
||||
log_misc("Open");
|
||||
|
||||
sink->ctx = NULL;
|
||||
sink->write = _core_log_sink_null_write;
|
||||
sink->close = _core_log_sink_null_close;
|
||||
|
||||
@@ -12,6 +12,6 @@
|
||||
*
|
||||
* @param sink Pointer to allocated memory that receives the opened sink
|
||||
*/
|
||||
void core_log_sink_null_open(struct core_log_sink *sink);
|
||||
void core_log_sink_null_open(core_log_sink_t *sink);
|
||||
|
||||
#endif
|
||||
@@ -1,15 +1,19 @@
|
||||
#define LOG_MODULE "core-log-sink-std"
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "core/log-sink.h"
|
||||
|
||||
#include "iface-core/log.h"
|
||||
|
||||
#include "util/mem.h"
|
||||
|
||||
struct core_log_sink_std_ctx {
|
||||
typedef struct core_log_sink_std {
|
||||
HANDLE handle;
|
||||
bool color;
|
||||
};
|
||||
} core_log_sink_std_t;
|
||||
|
||||
static char _core_log_sink_std_determine_color(const char *str)
|
||||
{
|
||||
@@ -79,7 +83,7 @@ _core_log_sink_std_write(void *ctx_, const char *chars, size_t nchars)
|
||||
{
|
||||
static const size_t timestamp_len = strlen("[----/--/-- --:--:--]");
|
||||
|
||||
struct core_log_sink_std_ctx *ctx;
|
||||
core_log_sink_std_t *ctx;
|
||||
|
||||
char color;
|
||||
size_t color_len;
|
||||
@@ -89,7 +93,7 @@ _core_log_sink_std_write(void *ctx_, const char *chars, size_t nchars)
|
||||
DWORD written;
|
||||
DWORD write_pos;
|
||||
|
||||
ctx = (struct core_log_sink_std_ctx *) ctx_;
|
||||
ctx = (core_log_sink_std_t *) ctx_;
|
||||
|
||||
if (ctx->color) {
|
||||
write_pos = 0;
|
||||
@@ -155,20 +159,24 @@ _core_log_sink_std_write(void *ctx_, const char *chars, size_t nchars)
|
||||
|
||||
static void _core_log_sink_std_close(void *ctx_)
|
||||
{
|
||||
struct core_log_sink_std_ctx *ctx;
|
||||
core_log_sink_std_t *ctx;
|
||||
|
||||
ctx = (struct core_log_sink_std_ctx *) ctx_;
|
||||
ctx = (core_log_sink_std_t *) ctx_;
|
||||
|
||||
// Remark: Don't close the ctx->handle, see win API docs
|
||||
|
||||
free(ctx);
|
||||
}
|
||||
|
||||
void core_log_sink_std_out_open(bool color, struct core_log_sink *sink)
|
||||
void core_log_sink_std_out_open(bool color, core_log_sink_t *sink)
|
||||
{
|
||||
struct core_log_sink_std_ctx *ctx;
|
||||
core_log_sink_std_t *ctx;
|
||||
|
||||
ctx = xmalloc(sizeof(struct core_log_sink_std_ctx));
|
||||
log_assert(sink);
|
||||
|
||||
log_misc("Open stdout");
|
||||
|
||||
ctx = xmalloc(sizeof(core_log_sink_std_t));
|
||||
|
||||
ctx->handle = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||
ctx->color = color;
|
||||
@@ -178,11 +186,15 @@ void core_log_sink_std_out_open(bool color, struct core_log_sink *sink)
|
||||
sink->close = _core_log_sink_std_close;
|
||||
}
|
||||
|
||||
void core_log_sink_std_err_open(bool color, struct core_log_sink *sink)
|
||||
void core_log_sink_std_err_open(bool color, core_log_sink_t *sink)
|
||||
{
|
||||
struct core_log_sink_std_ctx *ctx;
|
||||
core_log_sink_std_t *ctx;
|
||||
|
||||
ctx = xmalloc(sizeof(struct core_log_sink_std_ctx));
|
||||
log_assert(sink);
|
||||
|
||||
log_misc("Open stderr");
|
||||
|
||||
ctx = xmalloc(sizeof(core_log_sink_std_t));
|
||||
|
||||
ctx->handle = GetStdHandle(STD_ERROR_HANDLE);
|
||||
ctx->color = color;
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#ifndef CORE_LOG_SINK_STD_H
|
||||
#define CORE_LOG_SINK_STD_H
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "core/log-sink.h"
|
||||
@@ -11,7 +12,7 @@
|
||||
* @param color If true, messages are colored by log level.
|
||||
* @param sink Pointer to allocated memory that receives the opened sink
|
||||
*/
|
||||
void core_log_sink_std_out_open(bool color, struct core_log_sink *sink);
|
||||
void core_log_sink_std_out_open(bool color, core_log_sink_t *sink);
|
||||
|
||||
/**
|
||||
* Create a sink that writes to stderr.
|
||||
@@ -19,6 +20,6 @@ void core_log_sink_std_out_open(bool color, struct core_log_sink *sink);
|
||||
* @param color If true, messages are colored by log level.
|
||||
* @param sink Pointer to allocated memory that receives the opened sink
|
||||
*/
|
||||
void core_log_sink_std_err_open(bool color, struct core_log_sink *sink);
|
||||
void core_log_sink_std_err_open(bool color, core_log_sink_t *sink);
|
||||
|
||||
#endif
|
||||
@@ -36,10 +36,10 @@ typedef void (*core_log_sink_close_t)(void *ctx);
|
||||
* to operate, e.g. a file handle, additional buffers etc. Make sure these
|
||||
* resources are cleaned up upon closing the sink.
|
||||
*/
|
||||
struct core_log_sink {
|
||||
typedef struct core_log_sink {
|
||||
void *ctx;
|
||||
core_log_sink_write_t write;
|
||||
core_log_sink_close_t close;
|
||||
};
|
||||
} core_log_sink_t;
|
||||
|
||||
#endif
|
||||
@@ -1,74 +0,0 @@
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "core/log.h"
|
||||
|
||||
core_log_message_t _core_log_misc_impl;
|
||||
core_log_message_t _core_log_info_impl;
|
||||
core_log_message_t _core_log_warning_impl;
|
||||
core_log_message_t _core_log_fatal_impl;
|
||||
|
||||
void core_log_impl_set(
|
||||
core_log_message_t misc,
|
||||
core_log_message_t info,
|
||||
core_log_message_t warning,
|
||||
core_log_message_t fatal)
|
||||
{
|
||||
if (misc == NULL || info == NULL || warning == NULL || fatal == NULL) {
|
||||
abort();
|
||||
}
|
||||
|
||||
_core_log_misc_impl = misc;
|
||||
_core_log_info_impl = info;
|
||||
_core_log_warning_impl = warning;
|
||||
_core_log_fatal_impl = fatal;
|
||||
}
|
||||
|
||||
void core_log_impl_assign(core_log_impl_set_t impl_set)
|
||||
{
|
||||
if (_core_log_misc_impl == NULL || _core_log_info_impl == NULL ||
|
||||
_core_log_warning_impl == NULL || _core_log_fatal_impl == NULL) {
|
||||
abort();
|
||||
}
|
||||
|
||||
impl_set(
|
||||
_core_log_misc_impl,
|
||||
_core_log_info_impl,
|
||||
_core_log_warning_impl,
|
||||
_core_log_fatal_impl);
|
||||
}
|
||||
|
||||
core_log_message_t core_log_misc_impl_get()
|
||||
{
|
||||
if (_core_log_misc_impl == NULL) {
|
||||
abort();
|
||||
}
|
||||
|
||||
return _core_log_misc_impl;
|
||||
}
|
||||
|
||||
core_log_message_t core_log_info_impl_get()
|
||||
{
|
||||
if (_core_log_info_impl == NULL) {
|
||||
abort();
|
||||
}
|
||||
|
||||
return _core_log_info_impl;
|
||||
}
|
||||
|
||||
core_log_message_t core_log_warning_impl_get()
|
||||
{
|
||||
if (_core_log_warning_impl == NULL) {
|
||||
abort();
|
||||
}
|
||||
|
||||
return _core_log_warning_impl;
|
||||
}
|
||||
|
||||
core_log_message_t core_log_fatal_impl_get()
|
||||
{
|
||||
if (_core_log_fatal_impl == NULL) {
|
||||
abort();
|
||||
}
|
||||
|
||||
return _core_log_fatal_impl;
|
||||
}
|
||||
@@ -1,197 +0,0 @@
|
||||
#ifndef CORE_LOG_H
|
||||
#define CORE_LOG_H
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "util/defs.h"
|
||||
|
||||
/**
|
||||
* The core log API of bemanitools.
|
||||
*
|
||||
* To a large extent, this reflects the AVS logging API and allows for swapping
|
||||
* out the backends with different implementations. Most games should have some
|
||||
* version of the AVS API available while some (legacy) games do not. These
|
||||
* can use a bemanitools private logging implementation by configuring it
|
||||
* in the bootstrapping process.
|
||||
*/
|
||||
|
||||
/* BUILD_MODULE is passed in as a command-line #define by the makefile */
|
||||
|
||||
#ifndef LOG_MODULE
|
||||
#define LOG_MODULE STRINGIFY(BUILD_MODULE)
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Log a message on misc level
|
||||
*
|
||||
* Always use this interface in your application which hides the currently
|
||||
* configured implementation.
|
||||
*
|
||||
* The macro is required to make things work with varargs.
|
||||
* The log message is only printed if the log level is set to misc
|
||||
*
|
||||
* @param fmt printf format string
|
||||
* @param ... Additional arguments according to the specified arguments in the
|
||||
* printf format string
|
||||
*/
|
||||
#define log_misc(...) _core_log_misc_impl(LOG_MODULE, __VA_ARGS__)
|
||||
|
||||
/**
|
||||
* Log a message on info level
|
||||
*
|
||||
* Always use this interface in your application which hides the currently
|
||||
* configured implementation.
|
||||
*
|
||||
* The macro is required to make things work with varargs.
|
||||
* The log message is only printed if the log level is set to info or lower
|
||||
*
|
||||
* @param fmt printf format string
|
||||
* @param ... Additional arguments according to the specified arguments in the
|
||||
* printf format string
|
||||
*/
|
||||
#define log_info(...) _core_log_info_impl(LOG_MODULE, __VA_ARGS__)
|
||||
|
||||
/**
|
||||
* Log a message on warning level
|
||||
*
|
||||
* Always use this interface in your application which hides the currently
|
||||
* configured implementation.
|
||||
*
|
||||
* The macro is required to make things work with varargs.
|
||||
* The log message is only printed if the log level is set to warning or lower
|
||||
*
|
||||
* @param fmt printf format string
|
||||
* @param ... Additional arguments according to the specified arguments in the
|
||||
* printf format string
|
||||
*/
|
||||
#define log_warning(...) _core_log_warning_impl(LOG_MODULE, __VA_ARGS__)
|
||||
|
||||
/**
|
||||
* Log a message on fatal level
|
||||
*
|
||||
* Always use this interface in your application which hides the currently
|
||||
* configured implementation.
|
||||
*
|
||||
* The macro is required to make things work with varargs.
|
||||
* The log message is only printed if the log level is set to fatal.
|
||||
*
|
||||
* This call will also terminate the application.
|
||||
*
|
||||
* @param fmt printf format string
|
||||
* @param ... Additional arguments according to the specified arguments in the
|
||||
* printf format string
|
||||
*/
|
||||
#define log_fatal(...) \
|
||||
do { \
|
||||
_core_log_fatal_impl(LOG_MODULE, __VA_ARGS__); \
|
||||
abort(); \
|
||||
} while (0)
|
||||
|
||||
/**
|
||||
* Log a message and terminate the application if given condition fails
|
||||
*
|
||||
* Always use this interface in your application which hides the currently
|
||||
* configured implementation.
|
||||
*
|
||||
* The macro is required to make things work with varargs.
|
||||
*
|
||||
* @param x Condition to evaluate. If false, the application terminates
|
||||
*/
|
||||
#define log_assert(x) \
|
||||
do { \
|
||||
if (!(x)) { \
|
||||
_core_log_fatal_impl( \
|
||||
"assert", \
|
||||
"%s:%d: function `%s'", \
|
||||
__FILE__, \
|
||||
__LINE__, \
|
||||
__FUNCTION__); \
|
||||
abort(); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
/**
|
||||
* Log a message in an exception handler
|
||||
*
|
||||
* Only use this function in an exception handler, e.g. for stack traces. It
|
||||
* logs the message on fatal level but does not terminate.
|
||||
*
|
||||
* @param fmt printf format string
|
||||
* @param ... Additional arguments according to the specified arguments in the
|
||||
* printf format string
|
||||
*/
|
||||
#define log_exception_handler(...) \
|
||||
_core_log_fatal_impl("exception", __VA_ARGS__)
|
||||
|
||||
typedef void (*core_log_message_t)(const char *module, const char *fmt, ...);
|
||||
|
||||
typedef void (*core_log_impl_set_t)(
|
||||
core_log_message_t misc,
|
||||
core_log_message_t info,
|
||||
core_log_message_t warning,
|
||||
core_log_message_t fatal);
|
||||
|
||||
/**
|
||||
* Configure the log API implementations
|
||||
*
|
||||
* Advised to do this as early in your application/library module as possible
|
||||
* as calls to the getter functions below will return the currently configured
|
||||
* implementations.
|
||||
*
|
||||
* @param misc Pointer to a function implementing logging on misc level
|
||||
* @param info Pointer to a function implementing logging on info level
|
||||
* @param warning Pointer to a function implementing logging on warning level
|
||||
* @param fatal Pointer to a function implementing logging on fatal level
|
||||
*/
|
||||
void core_log_impl_set(
|
||||
core_log_message_t misc,
|
||||
core_log_message_t info,
|
||||
core_log_message_t warning,
|
||||
core_log_message_t fatal);
|
||||
|
||||
/**
|
||||
* Supporting function to inject/assign the currently set implementation
|
||||
* with the given setter function.
|
||||
*
|
||||
* @param impl_set Setter function to call with the currently configured log
|
||||
* function implementations
|
||||
*/
|
||||
void core_log_impl_assign(core_log_impl_set_t impl_set);
|
||||
|
||||
/**
|
||||
* Get the currently configured implementation of the misc level log function
|
||||
*
|
||||
* @return Pointer to the currently configured implementation of the function
|
||||
*/
|
||||
core_log_message_t core_log_misc_impl_get();
|
||||
|
||||
/**
|
||||
* Get the currently configured implementation of the info level log function
|
||||
*
|
||||
* @return Pointer to the currently configured implementation of the function
|
||||
*/
|
||||
core_log_message_t core_log_info_impl_get();
|
||||
|
||||
/**
|
||||
* Get the currently configured implementation of the warning level log function
|
||||
*
|
||||
* @return Pointer to the currently configured implementation of the function
|
||||
*/
|
||||
core_log_message_t core_log_warning_impl_get();
|
||||
|
||||
/**
|
||||
* Get the currently configured implementation of the fatal level log function
|
||||
*
|
||||
* @return Pointer to the currently configured implementation of the function
|
||||
*/
|
||||
core_log_message_t core_log_fatal_impl_get();
|
||||
|
||||
// Do not use these directly.
|
||||
// These are only here to allow usage in the macros above.
|
||||
extern core_log_message_t _core_log_misc_impl;
|
||||
extern core_log_message_t _core_log_info_impl;
|
||||
extern core_log_message_t _core_log_warning_impl;
|
||||
extern core_log_message_t _core_log_fatal_impl;
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,75 @@
|
||||
#define LOG_MODULE "core-property-ext"
|
||||
|
||||
#include "iface-core/log.h"
|
||||
|
||||
#include "main/core/property-node-ext.h"
|
||||
#include "main/core/property.h"
|
||||
|
||||
core_property_result_t core_property_ext_many_merge(
|
||||
const core_property_t **properties,
|
||||
size_t count,
|
||||
core_property_t **out_property)
|
||||
{
|
||||
core_property_t *merged_property;
|
||||
core_property_t *tmp;
|
||||
core_property_result_t result;
|
||||
core_property_node_result_t result2;
|
||||
int i;
|
||||
|
||||
log_assert(properties);
|
||||
log_assert(count > 0);
|
||||
log_assert(out_property);
|
||||
|
||||
result = core_property_clone(properties[0], &merged_property);
|
||||
|
||||
if (CORE_PROPERTY_RESULT_IS_ERROR(result)) {
|
||||
return result;
|
||||
}
|
||||
|
||||
if (count == 1) {
|
||||
*out_property = merged_property;
|
||||
return CORE_PROPERTY_RESULT_SUCCESS;
|
||||
}
|
||||
|
||||
core_property_log(merged_property, log_misc_func);
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
core_property_log(properties[i], log_misc_func);
|
||||
}
|
||||
|
||||
for (i = 1; i < count; i++) {
|
||||
result2 = core_property_node_ext_merge_do(
|
||||
merged_property, properties[i], &tmp);
|
||||
|
||||
core_property_log(tmp, log_misc_func);
|
||||
|
||||
if (CORE_PROPERTY_NODE_RESULT_IS_ERROR(result2)) {
|
||||
core_property_free(&merged_property);
|
||||
return CORE_PROPERTY_RESULT_ERROR_INTERNAL;
|
||||
}
|
||||
|
||||
core_property_free(&merged_property);
|
||||
merged_property = tmp;
|
||||
}
|
||||
|
||||
*out_property = merged_property;
|
||||
|
||||
return CORE_PROPERTY_RESULT_SUCCESS;
|
||||
}
|
||||
|
||||
core_property_result_t core_property_ext_merge(
|
||||
const core_property_t *property_1,
|
||||
const core_property_t *property_2,
|
||||
core_property_t **out_property)
|
||||
{
|
||||
const core_property_t *properties[2];
|
||||
|
||||
log_assert(property_1);
|
||||
log_assert(property_2);
|
||||
log_assert(out_property);
|
||||
|
||||
properties[0] = property_1;
|
||||
properties[1] = property_2;
|
||||
|
||||
return core_property_ext_many_merge(properties, 2, out_property);
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
#ifndef CORE_PROPERTY_EXT_H
|
||||
#define CORE_PROPERTY_EXT_H
|
||||
|
||||
#include "main/core/property.h"
|
||||
|
||||
core_property_result_t core_property_ext_many_merge(
|
||||
core_property_t **properties, size_t count, core_property_t **out_property);
|
||||
|
||||
core_property_result_t core_property_ext_merge(
|
||||
const core_property_t *property_1,
|
||||
const core_property_t *property_2,
|
||||
core_property_t **out_property);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,750 @@
|
||||
#define LOG_MODULE "core-property-node-ext"
|
||||
|
||||
#include "iface-core/log.h"
|
||||
|
||||
#include "core/property-node-ext.h"
|
||||
#include "core/property-node.h"
|
||||
|
||||
#include "util/str.h"
|
||||
|
||||
struct core_property_node_ext_merge_ctx {
|
||||
const char *path;
|
||||
const core_property_node_ext_merge_strategies_t *strategies;
|
||||
};
|
||||
|
||||
typedef struct core_property_node_ext_merge_ctx
|
||||
core_property_node_ext_merge_ctx_t;
|
||||
|
||||
static core_property_node_result_t _core_property_node_ext_merge_recursive_do(
|
||||
core_property_node_t *parent,
|
||||
const core_property_node_t *source,
|
||||
void *ctx_)
|
||||
{
|
||||
const core_property_node_ext_merge_ctx_t *ctx;
|
||||
core_property_node_ext_merge_ctx_t ctx_next;
|
||||
|
||||
char parent_name[CORE_PROPERTY_NODE_NAME_SIZE_MAX];
|
||||
char parent_path[CORE_PROPERTY_NODE_PATH_LEN_MAX];
|
||||
|
||||
core_property_node_result_t result;
|
||||
bool consumed;
|
||||
uint8_t i;
|
||||
|
||||
log_assert(parent);
|
||||
log_assert(source);
|
||||
log_assert(ctx_);
|
||||
|
||||
ctx = (const core_property_node_ext_merge_ctx_t *) ctx_;
|
||||
|
||||
log_assert(ctx->path);
|
||||
log_assert(ctx->strategies);
|
||||
log_assert(ctx->strategies->num > 0);
|
||||
|
||||
result =
|
||||
core_property_node_name_get(parent, parent_name, sizeof(parent_name));
|
||||
|
||||
if (CORE_PROPERTY_NODE_RESULT_IS_ERROR(result)) {
|
||||
return result;
|
||||
}
|
||||
|
||||
str_cpy(parent_path, sizeof(parent_path), ctx->path);
|
||||
str_cat(parent_path, sizeof(parent_path), "/");
|
||||
str_cat(parent_path, sizeof(parent_path), parent_name);
|
||||
|
||||
ctx_next.path = parent_path;
|
||||
ctx_next.strategies = ctx->strategies;
|
||||
|
||||
consumed = false;
|
||||
|
||||
// Apply given strategies, one MUST consume
|
||||
for (i = 0; i < ctx->strategies->num; i++) {
|
||||
log_assert(ctx->strategies->entry[i].path);
|
||||
|
||||
// path == "" matches everything
|
||||
if (str_eq(ctx->strategies->entry[i].path, "") ||
|
||||
str_eq(ctx->strategies->entry[i].path, parent_path)) {
|
||||
|
||||
result = ctx->strategies->entry[i].merge_strategy_do(
|
||||
parent,
|
||||
source,
|
||||
&ctx_next,
|
||||
&consumed,
|
||||
_core_property_node_ext_merge_recursive_do);
|
||||
|
||||
if (CORE_PROPERTY_NODE_RESULT_IS_ERROR(result)) {
|
||||
return result;
|
||||
}
|
||||
|
||||
log_misc(
|
||||
"Merge strategy for '%s' consumed: %d",
|
||||
ctx->strategies->entry[i].path,
|
||||
consumed);
|
||||
|
||||
if (consumed) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
log_assert(consumed);
|
||||
|
||||
return CORE_PROPERTY_NODE_RESULT_SUCCESS;
|
||||
}
|
||||
|
||||
core_property_node_result_t core_property_node_ext_u8_read(
|
||||
const core_property_node_t *node, const char *name, uint8_t *value)
|
||||
{
|
||||
core_property_node_t tmp;
|
||||
core_property_node_result_t result;
|
||||
|
||||
log_assert(node);
|
||||
log_assert(name);
|
||||
log_assert(value);
|
||||
|
||||
result = core_property_node_search(node, name, &tmp);
|
||||
|
||||
if (CORE_PROPERTY_NODE_RESULT_IS_ERROR(result)) {
|
||||
return result;
|
||||
}
|
||||
|
||||
return core_property_node_u8_read(&tmp, value);
|
||||
}
|
||||
|
||||
core_property_node_result_t core_property_node_ext_u16_read(
|
||||
const core_property_node_t *node, const char *name, uint16_t *value)
|
||||
{
|
||||
core_property_node_t tmp;
|
||||
core_property_node_result_t result;
|
||||
|
||||
log_assert(node);
|
||||
log_assert(name);
|
||||
log_assert(value);
|
||||
|
||||
result = core_property_node_search(node, name, &tmp);
|
||||
|
||||
if (CORE_PROPERTY_NODE_RESULT_IS_ERROR(result)) {
|
||||
return result;
|
||||
}
|
||||
|
||||
return core_property_node_u16_read(&tmp, value);
|
||||
}
|
||||
|
||||
core_property_node_result_t core_property_node_ext_u32_read(
|
||||
const core_property_node_t *node, const char *name, uint32_t *value)
|
||||
{
|
||||
core_property_node_t tmp;
|
||||
core_property_node_result_t result;
|
||||
|
||||
log_assert(node);
|
||||
log_assert(name);
|
||||
log_assert(value);
|
||||
|
||||
result = core_property_node_search(node, name, &tmp);
|
||||
|
||||
if (CORE_PROPERTY_NODE_RESULT_IS_ERROR(result)) {
|
||||
return result;
|
||||
}
|
||||
|
||||
return core_property_node_u32_read(&tmp, value);
|
||||
}
|
||||
|
||||
core_property_node_result_t core_property_node_ext_bool_read(
|
||||
const core_property_node_t *node, const char *name, bool *value)
|
||||
{
|
||||
core_property_node_t tmp;
|
||||
core_property_node_result_t result;
|
||||
|
||||
log_assert(node);
|
||||
log_assert(name);
|
||||
log_assert(value);
|
||||
|
||||
result = core_property_node_search(node, name, &tmp);
|
||||
|
||||
if (CORE_PROPERTY_NODE_RESULT_IS_ERROR(result)) {
|
||||
return result;
|
||||
}
|
||||
|
||||
return core_property_node_bool_read(&tmp, value);
|
||||
}
|
||||
|
||||
core_property_node_result_t core_property_node_ext_str_read(
|
||||
const core_property_node_t *node, const char *name, char *value, size_t len)
|
||||
{
|
||||
core_property_node_t tmp;
|
||||
core_property_node_result_t result;
|
||||
|
||||
log_assert(node);
|
||||
log_assert(name);
|
||||
log_assert(value);
|
||||
log_assert(len > 0);
|
||||
|
||||
result = core_property_node_search(node, name, &tmp);
|
||||
|
||||
if (CORE_PROPERTY_NODE_RESULT_IS_ERROR(result)) {
|
||||
return result;
|
||||
}
|
||||
|
||||
return core_property_node_str_read(&tmp, value, len);
|
||||
}
|
||||
|
||||
core_property_node_result_t core_property_node_ext_attr_read(
|
||||
const core_property_node_t *node, const char *name, char *value, size_t len)
|
||||
{
|
||||
core_property_node_t tmp;
|
||||
core_property_node_result_t result;
|
||||
|
||||
log_assert(node);
|
||||
log_assert(name);
|
||||
log_assert(value);
|
||||
log_assert(len > 0);
|
||||
|
||||
result = core_property_node_search(node, name, &tmp);
|
||||
|
||||
if (CORE_PROPERTY_NODE_RESULT_IS_ERROR(result)) {
|
||||
return result;
|
||||
}
|
||||
|
||||
return core_property_node_attr_read(&tmp, value, len);
|
||||
}
|
||||
|
||||
core_property_node_result_t core_property_node_ext_u8_read_or_default(
|
||||
const core_property_node_t *node,
|
||||
const char *name,
|
||||
uint8_t *value,
|
||||
uint8_t _default)
|
||||
{
|
||||
core_property_node_result_t result;
|
||||
|
||||
log_assert(node);
|
||||
log_assert(name);
|
||||
log_assert(value);
|
||||
|
||||
result = core_property_node_ext_u8_read(node, name, value);
|
||||
|
||||
if (result == CORE_PROPERTY_NODE_RESULT_NODE_NOT_FOUND) {
|
||||
*value = _default;
|
||||
|
||||
return CORE_PROPERTY_NODE_RESULT_SUCCESS;
|
||||
} else {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
core_property_node_result_t core_property_node_ext_u16_read_or_default(
|
||||
const core_property_node_t *node,
|
||||
const char *name,
|
||||
uint16_t *value,
|
||||
uint16_t _default)
|
||||
{
|
||||
core_property_node_result_t result;
|
||||
|
||||
log_assert(node);
|
||||
log_assert(name);
|
||||
log_assert(value);
|
||||
|
||||
result = core_property_node_ext_u16_read(node, name, value);
|
||||
|
||||
if (result == CORE_PROPERTY_NODE_RESULT_NODE_NOT_FOUND) {
|
||||
*value = _default;
|
||||
|
||||
return CORE_PROPERTY_NODE_RESULT_SUCCESS;
|
||||
} else {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
core_property_node_result_t core_property_node_ext_u32_read_or_default(
|
||||
const core_property_node_t *node,
|
||||
const char *name,
|
||||
uint32_t *value,
|
||||
uint32_t _default)
|
||||
{
|
||||
core_property_node_result_t result;
|
||||
|
||||
log_assert(node);
|
||||
log_assert(name);
|
||||
log_assert(value);
|
||||
|
||||
result = core_property_node_ext_u32_read(node, name, value);
|
||||
|
||||
if (result == CORE_PROPERTY_NODE_RESULT_NODE_NOT_FOUND) {
|
||||
*value = _default;
|
||||
|
||||
return CORE_PROPERTY_NODE_RESULT_SUCCESS;
|
||||
} else {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
core_property_node_result_t core_property_node_ext_bool_read_or_default(
|
||||
const core_property_node_t *node,
|
||||
const char *name,
|
||||
bool *value,
|
||||
bool _default)
|
||||
{
|
||||
core_property_node_result_t result;
|
||||
|
||||
log_assert(node);
|
||||
log_assert(name);
|
||||
log_assert(value);
|
||||
|
||||
result = core_property_node_ext_bool_read(node, name, value);
|
||||
|
||||
if (result == CORE_PROPERTY_NODE_RESULT_NODE_NOT_FOUND) {
|
||||
*value = _default;
|
||||
|
||||
return CORE_PROPERTY_NODE_RESULT_SUCCESS;
|
||||
} else {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
core_property_node_result_t core_property_node_ext_str_read_or_default(
|
||||
const core_property_node_t *node,
|
||||
const char *name,
|
||||
char *value,
|
||||
size_t len,
|
||||
const char *_default)
|
||||
{
|
||||
core_property_node_result_t result;
|
||||
|
||||
log_assert(node);
|
||||
log_assert(name);
|
||||
log_assert(value);
|
||||
log_assert(len > 0);
|
||||
log_assert(_default);
|
||||
|
||||
result = core_property_node_ext_str_read(node, name, value, len);
|
||||
|
||||
if (result == CORE_PROPERTY_NODE_RESULT_NODE_NOT_FOUND) {
|
||||
str_cpy(value, len, _default);
|
||||
|
||||
return CORE_PROPERTY_NODE_RESULT_SUCCESS;
|
||||
} else {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
core_property_node_result_t core_property_node_ext_u8_replace(
|
||||
core_property_node_t *node, const char *name, uint8_t val)
|
||||
{
|
||||
core_property_node_t tmp;
|
||||
core_property_node_result_t result;
|
||||
|
||||
log_assert(node);
|
||||
log_assert(name);
|
||||
|
||||
result = core_property_node_search(node, name, &tmp);
|
||||
|
||||
if (result != CORE_PROPERTY_NODE_RESULT_NODE_NOT_FOUND) {
|
||||
if (CORE_PROPERTY_NODE_RESULT_IS_ERROR(result)) {
|
||||
return result;
|
||||
}
|
||||
|
||||
result = core_property_node_remove(&tmp);
|
||||
|
||||
if (CORE_PROPERTY_NODE_RESULT_IS_ERROR(result)) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
return core_property_node_u8_create(node, name, val, NULL);
|
||||
}
|
||||
|
||||
core_property_node_result_t core_property_node_ext_u16_replace(
|
||||
core_property_node_t *node, const char *name, uint16_t val)
|
||||
{
|
||||
core_property_node_t tmp;
|
||||
core_property_node_result_t result;
|
||||
|
||||
log_assert(node);
|
||||
log_assert(name);
|
||||
|
||||
result = core_property_node_search(node, name, &tmp);
|
||||
|
||||
if (result != CORE_PROPERTY_NODE_RESULT_NODE_NOT_FOUND) {
|
||||
if (CORE_PROPERTY_NODE_RESULT_IS_ERROR(result)) {
|
||||
return result;
|
||||
}
|
||||
|
||||
result = core_property_node_remove(&tmp);
|
||||
|
||||
if (CORE_PROPERTY_NODE_RESULT_IS_ERROR(result)) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
return core_property_node_u16_create(node, name, val, NULL);
|
||||
}
|
||||
|
||||
core_property_node_result_t core_property_node_ext_u32_replace(
|
||||
core_property_node_t *node, const char *name, uint32_t val)
|
||||
{
|
||||
core_property_node_t tmp;
|
||||
core_property_node_result_t result;
|
||||
|
||||
log_assert(node);
|
||||
log_assert(name);
|
||||
|
||||
result = core_property_node_search(node, name, &tmp);
|
||||
|
||||
if (result != CORE_PROPERTY_NODE_RESULT_NODE_NOT_FOUND) {
|
||||
if (CORE_PROPERTY_NODE_RESULT_IS_ERROR(result)) {
|
||||
return result;
|
||||
}
|
||||
|
||||
result = core_property_node_remove(&tmp);
|
||||
|
||||
if (CORE_PROPERTY_NODE_RESULT_IS_ERROR(result)) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
return core_property_node_u32_create(node, name, val, NULL);
|
||||
}
|
||||
|
||||
core_property_node_result_t core_property_node_ext_str_replace(
|
||||
core_property_node_t *node, const char *name, const char *val)
|
||||
{
|
||||
core_property_node_t tmp;
|
||||
core_property_node_result_t result;
|
||||
|
||||
log_assert(node);
|
||||
log_assert(name);
|
||||
|
||||
result = core_property_node_search(node, name, &tmp);
|
||||
|
||||
if (result != CORE_PROPERTY_NODE_RESULT_NODE_NOT_FOUND) {
|
||||
if (CORE_PROPERTY_NODE_RESULT_IS_ERROR(result)) {
|
||||
return result;
|
||||
}
|
||||
|
||||
result = core_property_node_remove(&tmp);
|
||||
|
||||
if (CORE_PROPERTY_NODE_RESULT_IS_ERROR(result)) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
return core_property_node_str_create(node, name, val, NULL);
|
||||
}
|
||||
|
||||
core_property_node_result_t core_property_node_ext_bool_replace(
|
||||
core_property_node_t *node, const char *name, bool val)
|
||||
{
|
||||
core_property_node_t tmp;
|
||||
core_property_node_result_t result;
|
||||
|
||||
log_assert(node);
|
||||
log_assert(name);
|
||||
|
||||
result = core_property_node_search(node, name, &tmp);
|
||||
|
||||
if (result != CORE_PROPERTY_NODE_RESULT_NODE_NOT_FOUND) {
|
||||
if (CORE_PROPERTY_NODE_RESULT_IS_ERROR(result)) {
|
||||
return result;
|
||||
}
|
||||
|
||||
result = core_property_node_remove(&tmp);
|
||||
|
||||
if (CORE_PROPERTY_NODE_RESULT_IS_ERROR(result)) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
return core_property_node_bool_create(node, name, val, NULL);
|
||||
}
|
||||
|
||||
core_property_node_result_t core_property_node_ext_attr_replace(
|
||||
core_property_node_t *node, const char *name, const char *val)
|
||||
{
|
||||
core_property_node_t tmp;
|
||||
core_property_node_result_t result;
|
||||
|
||||
log_assert(node);
|
||||
log_assert(name);
|
||||
|
||||
result = core_property_node_search(node, name, &tmp);
|
||||
|
||||
if (result != CORE_PROPERTY_NODE_RESULT_NODE_NOT_FOUND) {
|
||||
if (CORE_PROPERTY_NODE_RESULT_IS_ERROR(result)) {
|
||||
return result;
|
||||
}
|
||||
|
||||
result = core_property_node_remove(&tmp);
|
||||
|
||||
if (CORE_PROPERTY_NODE_RESULT_IS_ERROR(result)) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
return core_property_node_attr_create(node, name, val, NULL);
|
||||
}
|
||||
|
||||
core_property_node_result_t core_property_node_ext_extract(
|
||||
const core_property_node_t *node, core_property_t **out_property)
|
||||
{
|
||||
size_t size;
|
||||
core_property_node_result_t result;
|
||||
core_property_t *property;
|
||||
core_property_result_t property_result;
|
||||
|
||||
log_assert(node);
|
||||
log_assert(out_property);
|
||||
|
||||
result = core_property_node_size(node, &size);
|
||||
|
||||
if (CORE_PROPERTY_NODE_RESULT_IS_ERROR(result)) {
|
||||
return result;
|
||||
}
|
||||
|
||||
property_result = core_property_create(size, &property);
|
||||
|
||||
if (CORE_PROPERTY_RESULT_IS_ERROR(property_result)) {
|
||||
return CORE_PROPERTY_NODE_RESULT_ERROR_INTERNAL;
|
||||
}
|
||||
|
||||
result = core_property_other_node_insert(property, node);
|
||||
|
||||
if (CORE_PROPERTY_NODE_RESULT_IS_ERROR(result)) {
|
||||
core_property_free(&property);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
*out_property = property;
|
||||
|
||||
return CORE_PROPERTY_NODE_RESULT_SUCCESS;
|
||||
}
|
||||
|
||||
core_property_node_result_t core_property_node_ext_merge_do(
|
||||
const core_property_t *parent,
|
||||
const core_property_t *source,
|
||||
core_property_t **out_property)
|
||||
{
|
||||
core_property_node_ext_merge_strategies_t strategies;
|
||||
|
||||
log_assert(parent);
|
||||
log_assert(source);
|
||||
log_assert(out_property);
|
||||
|
||||
strategies.num = 1;
|
||||
|
||||
strategies.entry[0].path = "";
|
||||
strategies.entry[0].merge_strategy_do =
|
||||
core_property_node_ext_merge_strategy_default_do;
|
||||
|
||||
return core_property_node_ext_merge_with_strategies_do(
|
||||
parent, source, &strategies, out_property);
|
||||
}
|
||||
|
||||
core_property_node_result_t core_property_node_ext_merge_with_strategies_do(
|
||||
const core_property_t *parent,
|
||||
const core_property_t *source,
|
||||
const core_property_node_ext_merge_strategies_t *strategies,
|
||||
core_property_t **merged)
|
||||
{
|
||||
size_t size;
|
||||
size_t total_size;
|
||||
core_property_result_t property_result;
|
||||
core_property_node_result_t property_node_result;
|
||||
core_property_t *merged_property;
|
||||
core_property_node_t parent_node;
|
||||
core_property_node_t merged_node;
|
||||
core_property_node_t source_node;
|
||||
core_property_node_ext_merge_ctx_t ctx;
|
||||
|
||||
log_assert(parent);
|
||||
log_assert(source);
|
||||
log_assert(strategies);
|
||||
|
||||
// We can't estimate how these two are being merged as in how much new
|
||||
// data is being inserted from source into parent. Therefore, worse-case
|
||||
// estimate memory requirement for no overlap
|
||||
total_size = 0;
|
||||
|
||||
property_result = core_property_size(parent, &size);
|
||||
|
||||
if (CORE_PROPERTY_RESULT_IS_ERROR(property_result)) {
|
||||
return CORE_PROPERTY_NODE_RESULT_ERROR_INTERNAL;
|
||||
}
|
||||
|
||||
total_size += size;
|
||||
|
||||
property_result = core_property_size(source, &size);
|
||||
|
||||
if (CORE_PROPERTY_RESULT_IS_ERROR(property_result)) {
|
||||
return CORE_PROPERTY_NODE_RESULT_ERROR_INTERNAL;
|
||||
}
|
||||
|
||||
total_size += size;
|
||||
|
||||
property_result = core_property_create(total_size, &merged_property);
|
||||
|
||||
if (CORE_PROPERTY_RESULT_IS_ERROR(property_result)) {
|
||||
return CORE_PROPERTY_NODE_RESULT_ERROR_INTERNAL;
|
||||
}
|
||||
|
||||
property_result = core_property_root_node_get(parent, &parent_node);
|
||||
|
||||
if (CORE_PROPERTY_RESULT_IS_ERROR(property_result)) {
|
||||
core_property_free(&merged_property);
|
||||
|
||||
return CORE_PROPERTY_NODE_RESULT_ERROR_INTERNAL;
|
||||
}
|
||||
|
||||
property_result =
|
||||
core_property_other_node_insert(merged_property, &parent_node);
|
||||
|
||||
if (CORE_PROPERTY_RESULT_IS_ERROR(property_result)) {
|
||||
core_property_free(&merged_property);
|
||||
|
||||
return CORE_PROPERTY_NODE_RESULT_ERROR_INTERNAL;
|
||||
}
|
||||
|
||||
property_result =
|
||||
core_property_root_node_get(merged_property, &merged_node);
|
||||
|
||||
if (CORE_PROPERTY_RESULT_IS_ERROR(property_result)) {
|
||||
core_property_free(&merged_property);
|
||||
|
||||
return CORE_PROPERTY_NODE_RESULT_ERROR_INTERNAL;
|
||||
}
|
||||
|
||||
property_result = core_property_root_node_get(source, &source_node);
|
||||
|
||||
if (CORE_PROPERTY_RESULT_IS_ERROR(property_result)) {
|
||||
core_property_free(&merged_property);
|
||||
|
||||
return CORE_PROPERTY_NODE_RESULT_ERROR_INTERNAL;
|
||||
}
|
||||
|
||||
core_property_node_log(&merged_node, log_misc_func);
|
||||
core_property_node_log(&source_node, log_misc_func);
|
||||
|
||||
ctx.path = "";
|
||||
ctx.strategies = strategies;
|
||||
|
||||
property_node_result = _core_property_node_ext_merge_recursive_do(
|
||||
&merged_node, &source_node, &ctx);
|
||||
|
||||
core_property_node_log(&merged_node, log_misc_func);
|
||||
|
||||
if (CORE_PROPERTY_NODE_RESULT_IS_ERROR(property_node_result)) {
|
||||
core_property_free(&merged_property);
|
||||
}
|
||||
|
||||
*merged = merged_property;
|
||||
|
||||
return CORE_PROPERTY_NODE_RESULT_SUCCESS;
|
||||
}
|
||||
|
||||
core_property_node_result_t core_property_node_ext_merge_strategy_default_do(
|
||||
core_property_node_t *parent,
|
||||
const core_property_node_t *source,
|
||||
void *ctx,
|
||||
bool *consumed,
|
||||
core_property_node_ext_merge_recursion_do_t node_merge_recursion_do)
|
||||
{
|
||||
core_property_node_t tmp;
|
||||
core_property_node_t source_child;
|
||||
core_property_node_result_t result;
|
||||
char source_child_name[CORE_PROPERTY_NODE_NAME_SIZE_MAX];
|
||||
core_property_node_t parent_child;
|
||||
core_property_node_t source_child_child;
|
||||
|
||||
log_assert(parent);
|
||||
log_assert(source);
|
||||
log_assert(consumed);
|
||||
|
||||
result = core_property_node_child_get(source, &source_child);
|
||||
|
||||
if (result == CORE_PROPERTY_NODE_RESULT_NODE_NOT_FOUND) {
|
||||
*consumed = true;
|
||||
return CORE_PROPERTY_NODE_RESULT_SUCCESS;
|
||||
}
|
||||
|
||||
if (CORE_PROPERTY_NODE_RESULT_IS_ERROR(result)) {
|
||||
*consumed = false;
|
||||
return result;
|
||||
}
|
||||
|
||||
while (true) {
|
||||
result = core_property_node_name_get(
|
||||
&source_child, source_child_name, sizeof(source_child_name));
|
||||
|
||||
if (CORE_PROPERTY_NODE_RESULT_IS_ERROR(result)) {
|
||||
*consumed = false;
|
||||
return result;
|
||||
}
|
||||
|
||||
result =
|
||||
core_property_node_search(parent, source_child_name, &parent_child);
|
||||
|
||||
if (result == CORE_PROPERTY_NODE_RESULT_NODE_NOT_FOUND) {
|
||||
// Could not find an identical child on parent, copy entire source
|
||||
// to parent
|
||||
result = core_property_node_copy(parent, &source_child);
|
||||
|
||||
if (CORE_PROPERTY_NODE_RESULT_IS_ERROR(result)) {
|
||||
*consumed = false;
|
||||
return result;
|
||||
}
|
||||
} else if (CORE_PROPERTY_NODE_RESULT_IS_ERROR(result)) {
|
||||
*consumed = false;
|
||||
return result;
|
||||
} else {
|
||||
// Go deeper, more levels to traverse
|
||||
result = core_property_node_child_get(
|
||||
&source_child, &source_child_child);
|
||||
|
||||
if (result == CORE_PROPERTY_NODE_RESULT_NODE_NOT_FOUND) {
|
||||
// Found identical leaf node, remove the matching parent's child
|
||||
// and copy the source child over to the parent and terminate
|
||||
// the recursion
|
||||
result = core_property_node_remove(&parent_child);
|
||||
|
||||
if (CORE_PROPERTY_NODE_RESULT_IS_ERROR(result)) {
|
||||
*consumed = false;
|
||||
return result;
|
||||
}
|
||||
|
||||
result = core_property_node_copy(parent, &source_child);
|
||||
|
||||
if (CORE_PROPERTY_NODE_RESULT_IS_ERROR(result)) {
|
||||
*consumed = false;
|
||||
return result;
|
||||
}
|
||||
} else if (CORE_PROPERTY_NODE_RESULT_IS_ERROR(result)) {
|
||||
*consumed = false;
|
||||
return result;
|
||||
} else {
|
||||
// Continue recursion if there are actually more children
|
||||
result =
|
||||
node_merge_recursion_do(&parent_child, &source_child, ctx);
|
||||
|
||||
if (CORE_PROPERTY_NODE_RESULT_IS_ERROR(result)) {
|
||||
*consumed = false;
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Iterate siblings on same level
|
||||
result = core_property_node_next_sibling_get(&source_child, &tmp);
|
||||
memcpy(&source_child, &tmp, sizeof(core_property_node_t));
|
||||
|
||||
if (result == CORE_PROPERTY_NODE_RESULT_NODE_NOT_FOUND) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (CORE_PROPERTY_NODE_RESULT_IS_ERROR(result)) {
|
||||
*consumed = false;
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
// Default strategy always consumes when successful
|
||||
*consumed = true;
|
||||
return CORE_PROPERTY_NODE_RESULT_SUCCESS;
|
||||
}
|
||||
@@ -0,0 +1,115 @@
|
||||
#ifndef CORE_PROPERTY_NODE_EXT_H
|
||||
#define CORE_PROPERTY_NODE_EXT_H
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "core/property-node.h"
|
||||
|
||||
#define CORE_PROPERTY_NODE_EXT_MAX_NODE_NAME_RESOLVERS 4
|
||||
|
||||
typedef core_property_node_result_t (
|
||||
*core_property_node_ext_merge_recursion_do_t)(
|
||||
core_property_node_t *parent,
|
||||
const core_property_node_t *source,
|
||||
void *ctx);
|
||||
|
||||
typedef core_property_node_result_t (
|
||||
*core_property_node_ext_merge_strategy_do_t)(
|
||||
core_property_node_t *parent,
|
||||
const core_property_node_t *source,
|
||||
void *ctx,
|
||||
bool *consumed,
|
||||
core_property_node_ext_merge_recursion_do_t node_merge_recursion_do);
|
||||
|
||||
typedef struct core_property_node_ext_merge_strategies {
|
||||
struct {
|
||||
const char *path;
|
||||
core_property_node_ext_merge_strategy_do_t merge_strategy_do;
|
||||
} entry[CORE_PROPERTY_NODE_EXT_MAX_NODE_NAME_RESOLVERS];
|
||||
uint8_t num;
|
||||
} core_property_node_ext_merge_strategies_t;
|
||||
|
||||
core_property_node_result_t core_property_node_ext_u8_read(
|
||||
const core_property_node_t *node, const char *name, uint8_t *value);
|
||||
core_property_node_result_t core_property_node_ext_u16_read(
|
||||
const core_property_node_t *node, const char *name, uint16_t *value);
|
||||
core_property_node_result_t core_property_node_ext_u32_read(
|
||||
const core_property_node_t *node, const char *name, uint32_t *value);
|
||||
core_property_node_result_t core_property_node_ext_bool_read(
|
||||
const core_property_node_t *node, const char *name, bool *value);
|
||||
core_property_node_result_t core_property_node_ext_str_read(
|
||||
const core_property_node_t *node,
|
||||
const char *name,
|
||||
char *value,
|
||||
size_t len);
|
||||
core_property_node_result_t core_property_node_ext_attr_read(
|
||||
const core_property_node_t *node,
|
||||
const char *name,
|
||||
char *value,
|
||||
size_t len);
|
||||
|
||||
core_property_node_result_t core_property_node_ext_u8_read_or_default(
|
||||
const core_property_node_t *node,
|
||||
const char *name,
|
||||
uint8_t *value,
|
||||
uint8_t _default);
|
||||
core_property_node_result_t core_property_node_ext_u16_read_or_default(
|
||||
const core_property_node_t *node,
|
||||
const char *name,
|
||||
uint16_t *value,
|
||||
uint16_t _default);
|
||||
core_property_node_result_t core_property_node_ext_u32_read_or_default(
|
||||
const core_property_node_t *node,
|
||||
const char *name,
|
||||
uint32_t *value,
|
||||
uint32_t _default);
|
||||
core_property_node_result_t core_property_node_ext_bool_read_or_default(
|
||||
const core_property_node_t *node,
|
||||
const char *name,
|
||||
bool *value,
|
||||
bool _default);
|
||||
core_property_node_result_t core_property_node_ext_str_read_or_default(
|
||||
const core_property_node_t *node,
|
||||
const char *name,
|
||||
char *value,
|
||||
size_t len,
|
||||
const char *_default);
|
||||
|
||||
core_property_node_result_t core_property_node_ext_u8_replace(
|
||||
core_property_node_t *node, const char *name, uint8_t val);
|
||||
core_property_node_result_t core_property_node_ext_u16_replace(
|
||||
core_property_node_t *node, const char *name, uint16_t val);
|
||||
core_property_node_result_t core_property_node_ext_u32_replace(
|
||||
core_property_node_t *node, const char *name, uint32_t val);
|
||||
core_property_node_result_t core_property_node_ext_str_replace(
|
||||
core_property_node_t *node, const char *name, const char *val);
|
||||
core_property_node_result_t core_property_node_ext_bool_replace(
|
||||
core_property_node_t *node, const char *name, bool val);
|
||||
core_property_node_result_t core_property_node_ext_attr_replace(
|
||||
core_property_node_t *node, const char *name, const char *val);
|
||||
|
||||
core_property_node_result_t core_property_node_ext_extract(
|
||||
const core_property_node_t *node, core_property_t **out_property);
|
||||
|
||||
core_property_node_result_t core_property_node_ext_merge_do(
|
||||
const core_property_t *parent,
|
||||
const core_property_t *source,
|
||||
core_property_t **out_property);
|
||||
// Strategies are applied in order and first consumer terminates
|
||||
// applying further strategies Typically, you want to include the default
|
||||
// strategy after your custom strategies for special cases
|
||||
core_property_node_result_t core_property_node_ext_merge_with_strategies_do(
|
||||
const core_property_t *parent,
|
||||
const core_property_t *source,
|
||||
const core_property_node_ext_merge_strategies_t *strategies,
|
||||
core_property_t **merged);
|
||||
|
||||
core_property_node_result_t core_property_node_ext_merge_strategy_default_do(
|
||||
core_property_node_t *parent,
|
||||
const core_property_node_t *source,
|
||||
void *ctx,
|
||||
bool *consumed,
|
||||
core_property_node_ext_merge_recursion_do_t node_merge_recursion_do);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,877 @@
|
||||
#define LOG_MODULE "property-node-trace"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "core/property-node.h"
|
||||
|
||||
#include "iface-core/log.h"
|
||||
|
||||
static core_property_node_api_t _core_property_node_trace_target_api;
|
||||
|
||||
static void _core_property_node_trace_log(
|
||||
const core_property_node_t *node, bt_core_log_message_t log_message)
|
||||
{
|
||||
log_misc(">>> log(%p)", node);
|
||||
|
||||
_core_property_node_trace_target_api.v1.log(node, log_message);
|
||||
|
||||
log_misc("<<< log(%p)", node);
|
||||
}
|
||||
|
||||
static core_property_node_result_t _core_property_node_trace_name_get(
|
||||
const core_property_node_t *node, char *name, size_t len)
|
||||
{
|
||||
core_property_node_result_t result;
|
||||
|
||||
log_misc(">>> name_get(%p, %p, %d)", node, name, len);
|
||||
|
||||
result = _core_property_node_trace_target_api.v1.name_get(node, name, len);
|
||||
|
||||
log_misc(
|
||||
"<<< name_get(%p, %s): %s",
|
||||
node,
|
||||
name,
|
||||
core_property_node_result_to_str(result));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static core_property_node_result_t
|
||||
_core_property_node_trace_size(const core_property_node_t *node, size_t *size)
|
||||
{
|
||||
core_property_node_result_t result;
|
||||
|
||||
log_misc(">>> size(%p)", node);
|
||||
|
||||
result = _core_property_node_trace_target_api.v1.size(node, size);
|
||||
|
||||
log_misc(
|
||||
"<<< size(%p, %d): %s",
|
||||
node,
|
||||
*size,
|
||||
core_property_node_result_to_str(result));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static core_property_node_result_t _core_property_node_trace_search(
|
||||
const core_property_node_t *node,
|
||||
const char *path,
|
||||
core_property_node_t *node_out)
|
||||
{
|
||||
core_property_node_result_t result;
|
||||
|
||||
log_misc(">>> search(%p, %s, %p)", node, path, node_out);
|
||||
|
||||
result =
|
||||
_core_property_node_trace_target_api.v1.search(node, path, node_out);
|
||||
|
||||
log_misc(
|
||||
"<<< search(%p, %s): %s",
|
||||
node,
|
||||
path,
|
||||
core_property_node_result_to_str(result));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static core_property_node_result_t _core_property_node_trace_next_result_search(
|
||||
const core_property_node_t *node, core_property_node_t *node_out)
|
||||
{
|
||||
core_property_node_result_t result;
|
||||
|
||||
log_misc(">>> next_result_search(%p, %p)", node, node_out);
|
||||
|
||||
result = _core_property_node_trace_target_api.v1.next_result_search(
|
||||
node, node_out);
|
||||
|
||||
log_misc(
|
||||
"<<< next_result_search(%p): %s",
|
||||
node,
|
||||
core_property_node_result_to_str(result));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static core_property_node_result_t _core_property_node_trace_child_get(
|
||||
const core_property_node_t *node, core_property_node_t *node_out)
|
||||
{
|
||||
core_property_node_result_t result;
|
||||
|
||||
log_misc(">>> child_get(%p, %p)", node, node_out);
|
||||
|
||||
result = _core_property_node_trace_target_api.v1.child_get(node, node_out);
|
||||
|
||||
log_misc(
|
||||
"<<< child_get(%p): %s",
|
||||
node,
|
||||
core_property_node_result_to_str(result));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static core_property_node_result_t _core_property_node_trace_next_sibling_get(
|
||||
const core_property_node_t *node, core_property_node_t *node_out)
|
||||
{
|
||||
core_property_node_result_t result;
|
||||
|
||||
log_misc(">>> next_sibling_get(%p, %p)", node, node_out);
|
||||
|
||||
result = _core_property_node_trace_target_api.v1.next_sibling_get(
|
||||
node, node_out);
|
||||
|
||||
log_misc(
|
||||
"<<< next_sibling_get(%p): %s",
|
||||
node,
|
||||
core_property_node_result_to_str(result));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static core_property_node_result_t _core_property_node_trace_void_create(
|
||||
const core_property_node_t *parent_node,
|
||||
const char *key,
|
||||
core_property_node_t *node_out)
|
||||
{
|
||||
core_property_node_result_t result;
|
||||
|
||||
log_misc(">>> void_create(%p, %s, %p)", parent_node, key, node_out);
|
||||
|
||||
result = _core_property_node_trace_target_api.v1.void_create(
|
||||
parent_node, key, node_out);
|
||||
|
||||
log_misc(
|
||||
"<<< void_create(%p, %s): %s",
|
||||
parent_node,
|
||||
key,
|
||||
core_property_node_result_to_str(result));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static core_property_node_result_t _core_property_node_trace_s8_create(
|
||||
const core_property_node_t *parent_node,
|
||||
const char *key,
|
||||
int8_t value,
|
||||
core_property_node_t *node_out)
|
||||
{
|
||||
core_property_node_result_t result;
|
||||
|
||||
log_misc(
|
||||
">>> s8_create(%p, %s, %d, %p)", parent_node, key, value, node_out);
|
||||
|
||||
result = _core_property_node_trace_target_api.v1.s8_create(
|
||||
parent_node, key, value, node_out);
|
||||
|
||||
log_misc(
|
||||
"<<< s8_create(%p, %s): %s",
|
||||
parent_node,
|
||||
key,
|
||||
core_property_node_result_to_str(result));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static core_property_node_result_t _core_property_node_trace_u8_create(
|
||||
const core_property_node_t *parent_node,
|
||||
const char *key,
|
||||
uint8_t value,
|
||||
core_property_node_t *node_out)
|
||||
{
|
||||
core_property_node_result_t result;
|
||||
|
||||
log_misc(
|
||||
">>> u8_create(%p, %s, %d, %p)", parent_node, key, value, node_out);
|
||||
|
||||
result = _core_property_node_trace_target_api.v1.u8_create(
|
||||
parent_node, key, value, node_out);
|
||||
|
||||
log_misc(
|
||||
"<<< u8_create(%p, %s): %s",
|
||||
parent_node,
|
||||
key,
|
||||
core_property_node_result_to_str(result));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static core_property_node_result_t _core_property_node_trace_s16_create(
|
||||
const core_property_node_t *parent_node,
|
||||
const char *key,
|
||||
int16_t value,
|
||||
core_property_node_t *node_out)
|
||||
{
|
||||
core_property_node_result_t result;
|
||||
|
||||
log_misc(
|
||||
">>> s16_create(%p, %s, %d, %p)", parent_node, key, value, node_out);
|
||||
|
||||
result = _core_property_node_trace_target_api.v1.s16_create(
|
||||
parent_node, key, value, node_out);
|
||||
|
||||
log_misc(
|
||||
"<<< s16_create(%p, %s): %s",
|
||||
parent_node,
|
||||
key,
|
||||
core_property_node_result_to_str(result));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static core_property_node_result_t _core_property_node_trace_u16_create(
|
||||
const core_property_node_t *parent_node,
|
||||
const char *key,
|
||||
uint16_t value,
|
||||
core_property_node_t *node_out)
|
||||
{
|
||||
core_property_node_result_t result;
|
||||
|
||||
log_misc(
|
||||
">>> u16_create(%p, %s, %d, %p)", parent_node, key, value, node_out);
|
||||
|
||||
result = _core_property_node_trace_target_api.v1.u16_create(
|
||||
parent_node, key, value, node_out);
|
||||
|
||||
log_misc(
|
||||
"<<< u16_create(%p, %s): %s",
|
||||
parent_node,
|
||||
key,
|
||||
core_property_node_result_to_str(result));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static core_property_node_result_t _core_property_node_trace_s32_create(
|
||||
const core_property_node_t *parent_node,
|
||||
const char *key,
|
||||
int32_t value,
|
||||
core_property_node_t *node_out)
|
||||
{
|
||||
core_property_node_result_t result;
|
||||
|
||||
log_misc(
|
||||
">>> s32_create(%p, %s, %d, %p)", parent_node, key, value, node_out);
|
||||
|
||||
result = _core_property_node_trace_target_api.v1.s32_create(
|
||||
parent_node, key, value, node_out);
|
||||
|
||||
log_misc(
|
||||
"<<< s32_create(%p, %s): %s",
|
||||
parent_node,
|
||||
key,
|
||||
core_property_node_result_to_str(result));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static core_property_node_result_t _core_property_node_trace_u32_create(
|
||||
const core_property_node_t *parent_node,
|
||||
const char *key,
|
||||
uint32_t value,
|
||||
core_property_node_t *node_out)
|
||||
{
|
||||
core_property_node_result_t result;
|
||||
|
||||
log_misc(
|
||||
">>> u32_create(%p, %s, %d, %p)", parent_node, key, value, node_out);
|
||||
|
||||
result = _core_property_node_trace_target_api.v1.u32_create(
|
||||
parent_node, key, value, node_out);
|
||||
|
||||
log_misc(
|
||||
"<<< u32_create(%p, %s): %s",
|
||||
parent_node,
|
||||
key,
|
||||
core_property_node_result_to_str(result));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static core_property_node_result_t _core_property_node_trace_s64_create(
|
||||
const core_property_node_t *parent_node,
|
||||
const char *key,
|
||||
int64_t value,
|
||||
core_property_node_t *node_out)
|
||||
{
|
||||
core_property_node_result_t result;
|
||||
|
||||
log_misc(
|
||||
">>> s64_create(%p, %s, %d, %p)", parent_node, key, value, node_out);
|
||||
|
||||
result = _core_property_node_trace_target_api.v1.s64_create(
|
||||
parent_node, key, value, node_out);
|
||||
|
||||
log_misc(
|
||||
"<<< s64_create(%p, %s): %s",
|
||||
parent_node,
|
||||
key,
|
||||
core_property_node_result_to_str(result));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static core_property_node_result_t _core_property_node_trace_u64_create(
|
||||
const core_property_node_t *parent_node,
|
||||
const char *key,
|
||||
uint64_t value,
|
||||
core_property_node_t *node_out)
|
||||
{
|
||||
core_property_node_result_t result;
|
||||
|
||||
log_misc(
|
||||
">>> u64_create(%p, %s, %d, %p)", parent_node, key, value, node_out);
|
||||
|
||||
result = _core_property_node_trace_target_api.v1.u64_create(
|
||||
parent_node, key, value, node_out);
|
||||
|
||||
log_misc(
|
||||
"<<< u64_create(%p, %s): %s",
|
||||
parent_node,
|
||||
key,
|
||||
core_property_node_result_to_str(result));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static core_property_node_result_t _core_property_node_trace_bin_create(
|
||||
const core_property_node_t *parent_node,
|
||||
const char *key,
|
||||
void *data,
|
||||
size_t len,
|
||||
core_property_node_t *node_out)
|
||||
{
|
||||
core_property_node_result_t result;
|
||||
|
||||
log_misc(
|
||||
">>> bin_create(%p, %s, %p, %d, %p)",
|
||||
parent_node,
|
||||
key,
|
||||
data,
|
||||
len,
|
||||
node_out);
|
||||
|
||||
result = _core_property_node_trace_target_api.v1.bin_create(
|
||||
parent_node, key, data, len, node_out);
|
||||
|
||||
log_misc(
|
||||
"<<< bin_create(%p, %s): %s",
|
||||
parent_node,
|
||||
key,
|
||||
core_property_node_result_to_str(result));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static core_property_node_result_t _core_property_node_trace_str_create(
|
||||
const core_property_node_t *parent_node,
|
||||
const char *key,
|
||||
const char *value,
|
||||
core_property_node_t *node_out)
|
||||
{
|
||||
core_property_node_result_t result;
|
||||
|
||||
log_misc(
|
||||
">>> str_create(%p, %s, %s, %p)", parent_node, key, value, node_out);
|
||||
|
||||
result = _core_property_node_trace_target_api.v1.str_create(
|
||||
parent_node, key, value, node_out);
|
||||
|
||||
log_misc(
|
||||
"<<< str_create(%p, %s): %s",
|
||||
parent_node,
|
||||
key,
|
||||
core_property_node_result_to_str(result));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static core_property_node_result_t _core_property_node_trace_ipv4_create(
|
||||
const core_property_node_t *parent_node,
|
||||
const char *key,
|
||||
uint32_t value,
|
||||
core_property_node_t *node_out)
|
||||
{
|
||||
core_property_node_result_t result;
|
||||
|
||||
log_misc(
|
||||
">>> ipv4_create(%p, %s, %X, %p)", parent_node, key, value, node_out);
|
||||
|
||||
result = _core_property_node_trace_target_api.v1.ipv4_create(
|
||||
parent_node, key, value, node_out);
|
||||
|
||||
log_misc(
|
||||
"<<< ipv4_create(%p, %s): %s",
|
||||
parent_node,
|
||||
key,
|
||||
core_property_node_result_to_str(result));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static core_property_node_result_t _core_property_node_trace_float_create(
|
||||
const core_property_node_t *parent_node,
|
||||
const char *key,
|
||||
float value,
|
||||
core_property_node_t *node_out)
|
||||
{
|
||||
core_property_node_result_t result;
|
||||
|
||||
log_misc(
|
||||
">>> float_create(%p, %s, %f, %p)", parent_node, key, value, node_out);
|
||||
|
||||
result = _core_property_node_trace_target_api.v1.float_create(
|
||||
parent_node, key, value, node_out);
|
||||
|
||||
log_misc(
|
||||
"<<< float_create(%p, %s): %s",
|
||||
parent_node,
|
||||
key,
|
||||
core_property_node_result_to_str(result));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static core_property_node_result_t _core_property_node_trace_double_create(
|
||||
const core_property_node_t *parent_node,
|
||||
const char *key,
|
||||
double value,
|
||||
core_property_node_t *node_out)
|
||||
{
|
||||
core_property_node_result_t result;
|
||||
|
||||
log_misc(
|
||||
">>> double_create(%p, %s, %f, %p)", parent_node, key, value, node_out);
|
||||
|
||||
result = _core_property_node_trace_target_api.v1.double_create(
|
||||
parent_node, key, value, node_out);
|
||||
|
||||
log_misc(
|
||||
"<<< double_create(%p, %s): %s",
|
||||
parent_node,
|
||||
key,
|
||||
core_property_node_result_to_str(result));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static core_property_node_result_t _core_property_node_trace_attr_create(
|
||||
const core_property_node_t *parent_node,
|
||||
const char *key,
|
||||
const char *value,
|
||||
core_property_node_t *node_out)
|
||||
{
|
||||
core_property_node_result_t result;
|
||||
|
||||
log_misc(
|
||||
">>> attr_create(%p, %s, %s, %p)", parent_node, key, value, node_out);
|
||||
|
||||
result = _core_property_node_trace_target_api.v1.attr_create(
|
||||
parent_node, key, value, node_out);
|
||||
|
||||
log_misc(
|
||||
"<<< attr_create(%p, %s): %s",
|
||||
parent_node,
|
||||
key,
|
||||
core_property_node_result_to_str(result));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static core_property_node_result_t _core_property_node_trace_bool_create(
|
||||
const core_property_node_t *parent_node,
|
||||
const char *key,
|
||||
bool value,
|
||||
core_property_node_t *node_out)
|
||||
{
|
||||
core_property_node_result_t result;
|
||||
|
||||
log_misc(
|
||||
">>> bool_create(%p, %s, %d, %p)", parent_node, key, value, node_out);
|
||||
|
||||
result = _core_property_node_trace_target_api.v1.bool_create(
|
||||
parent_node, key, value, node_out);
|
||||
|
||||
log_misc(
|
||||
"<<< bool_create(%p, %s): %s",
|
||||
parent_node,
|
||||
key,
|
||||
core_property_node_result_to_str(result));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static core_property_node_result_t _core_property_node_trace_s8_read(
|
||||
const core_property_node_t *parent_node, int8_t *value)
|
||||
{
|
||||
core_property_node_result_t result;
|
||||
|
||||
log_misc(">>> s8_read(%p)", parent_node);
|
||||
|
||||
result =
|
||||
_core_property_node_trace_target_api.v1.s8_read(parent_node, value);
|
||||
|
||||
log_misc(
|
||||
"<<< s8_read(%p, %d): %s",
|
||||
parent_node,
|
||||
*value,
|
||||
core_property_node_result_to_str(result));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static core_property_node_result_t _core_property_node_trace_u8_read(
|
||||
const core_property_node_t *parent_node, uint8_t *value)
|
||||
{
|
||||
core_property_node_result_t result;
|
||||
|
||||
log_misc(">>> u8_read(%p)", parent_node);
|
||||
|
||||
result =
|
||||
_core_property_node_trace_target_api.v1.u8_read(parent_node, value);
|
||||
|
||||
log_misc(
|
||||
"<<< u8_read(%p, %d): %s",
|
||||
parent_node,
|
||||
*value,
|
||||
core_property_node_result_to_str(result));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static core_property_node_result_t _core_property_node_trace_s16_read(
|
||||
const core_property_node_t *parent_node, int16_t *value)
|
||||
{
|
||||
core_property_node_result_t result;
|
||||
|
||||
log_misc(">>> s16_read(%p)", parent_node);
|
||||
|
||||
result =
|
||||
_core_property_node_trace_target_api.v1.s16_read(parent_node, value);
|
||||
|
||||
log_misc(
|
||||
"<<< s16_read(%p, %d): %s",
|
||||
parent_node,
|
||||
*value,
|
||||
core_property_node_result_to_str(result));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static core_property_node_result_t _core_property_node_trace_u16_read(
|
||||
const core_property_node_t *parent_node, uint16_t *value)
|
||||
{
|
||||
core_property_node_result_t result;
|
||||
|
||||
log_misc(">>> u16_read(%p)", parent_node);
|
||||
|
||||
result =
|
||||
_core_property_node_trace_target_api.v1.u16_read(parent_node, value);
|
||||
|
||||
log_misc(
|
||||
"<<< u16_read(%p, %d): %s",
|
||||
parent_node,
|
||||
*value,
|
||||
core_property_node_result_to_str(result));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static core_property_node_result_t _core_property_node_trace_s32_read(
|
||||
const core_property_node_t *parent_node, int32_t *value)
|
||||
{
|
||||
core_property_node_result_t result;
|
||||
|
||||
log_misc(">>> s32_read(%p)", parent_node);
|
||||
|
||||
result =
|
||||
_core_property_node_trace_target_api.v1.s32_read(parent_node, value);
|
||||
|
||||
log_misc(
|
||||
"<<< s32_read(%p, %d): %s",
|
||||
parent_node,
|
||||
*value,
|
||||
core_property_node_result_to_str(result));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static core_property_node_result_t _core_property_node_trace_u32_read(
|
||||
const core_property_node_t *parent_node, uint32_t *value)
|
||||
{
|
||||
core_property_node_result_t result;
|
||||
|
||||
log_misc(">>> u32_read(%p)", parent_node);
|
||||
|
||||
result =
|
||||
_core_property_node_trace_target_api.v1.u32_read(parent_node, value);
|
||||
|
||||
log_misc(
|
||||
"<<< u32_read(%p, %d): %s",
|
||||
parent_node,
|
||||
*value,
|
||||
core_property_node_result_to_str(result));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static core_property_node_result_t _core_property_node_trace_s64_read(
|
||||
const core_property_node_t *parent_node, int64_t *value)
|
||||
{
|
||||
core_property_node_result_t result;
|
||||
|
||||
log_misc(">>> s64_read(%p)", parent_node);
|
||||
|
||||
result =
|
||||
_core_property_node_trace_target_api.v1.s64_read(parent_node, value);
|
||||
|
||||
log_misc(
|
||||
"<<< s64_read(%p, %d): %s",
|
||||
parent_node,
|
||||
*value,
|
||||
core_property_node_result_to_str(result));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static core_property_node_result_t _core_property_node_trace_u64_read(
|
||||
const core_property_node_t *parent_node, uint64_t *value)
|
||||
{
|
||||
core_property_node_result_t result;
|
||||
|
||||
log_misc(">>> u64_read(%p)", parent_node);
|
||||
|
||||
result =
|
||||
_core_property_node_trace_target_api.v1.u64_read(parent_node, value);
|
||||
|
||||
log_misc(
|
||||
"<<< u64_read(%p, %d): %s",
|
||||
parent_node,
|
||||
*value,
|
||||
core_property_node_result_to_str(result));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static core_property_node_result_t _core_property_node_trace_bin_read(
|
||||
const core_property_node_t *parent_node, void *value, size_t len)
|
||||
{
|
||||
core_property_node_result_t result;
|
||||
|
||||
log_misc(">>> bin_read(%p, %p, %d)", parent_node, value, len);
|
||||
|
||||
result = _core_property_node_trace_target_api.v1.bin_read(
|
||||
parent_node, value, len);
|
||||
|
||||
log_misc(
|
||||
"<<< bin_read(%p): %s",
|
||||
parent_node,
|
||||
core_property_node_result_to_str(result));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static core_property_node_result_t _core_property_node_trace_str_read(
|
||||
const core_property_node_t *parent_node, char *value, size_t len)
|
||||
{
|
||||
core_property_node_result_t result;
|
||||
|
||||
log_misc(">>> str_read(%p, %p, %d)", parent_node, value, len);
|
||||
|
||||
result = _core_property_node_trace_target_api.v1.str_read(
|
||||
parent_node, value, len);
|
||||
|
||||
log_misc(
|
||||
"<<< str_read(%p, %s): %s",
|
||||
parent_node,
|
||||
value,
|
||||
core_property_node_result_to_str(result));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static core_property_node_result_t _core_property_node_trace_ipv4_read(
|
||||
const core_property_node_t *parent_node, uint32_t *value)
|
||||
{
|
||||
core_property_node_result_t result;
|
||||
|
||||
log_misc(">>> ipv4_read(%p)", parent_node);
|
||||
|
||||
result =
|
||||
_core_property_node_trace_target_api.v1.ipv4_read(parent_node, value);
|
||||
|
||||
log_misc(
|
||||
"<<< ipv4_read(%p, %X): %s",
|
||||
parent_node,
|
||||
*value,
|
||||
core_property_node_result_to_str(result));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static core_property_node_result_t _core_property_node_trace_float_read(
|
||||
const core_property_node_t *parent_node, float *value)
|
||||
{
|
||||
core_property_node_result_t result;
|
||||
|
||||
log_misc(">>> float_read(%p)", parent_node);
|
||||
|
||||
result =
|
||||
_core_property_node_trace_target_api.v1.float_read(parent_node, value);
|
||||
|
||||
log_misc(
|
||||
"<<< float_read(%p, %f): %s",
|
||||
parent_node,
|
||||
*value,
|
||||
core_property_node_result_to_str(result));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static core_property_node_result_t _core_property_node_trace_double_read(
|
||||
const core_property_node_t *parent_node, double *value)
|
||||
{
|
||||
core_property_node_result_t result;
|
||||
|
||||
log_misc(">>> double_read(%p)", parent_node);
|
||||
|
||||
result =
|
||||
_core_property_node_trace_target_api.v1.double_read(parent_node, value);
|
||||
|
||||
log_misc(
|
||||
"<<< double_read(%p, %f): %s",
|
||||
parent_node,
|
||||
*value,
|
||||
core_property_node_result_to_str(result));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static core_property_node_result_t _core_property_node_trace_attr_read(
|
||||
const core_property_node_t *parent_node, char *value, size_t len)
|
||||
{
|
||||
core_property_node_result_t result;
|
||||
|
||||
log_misc(">>> attr_read(%p, %p, %d)", parent_node, value, len);
|
||||
|
||||
result = _core_property_node_trace_target_api.v1.attr_read(
|
||||
parent_node, value, len);
|
||||
|
||||
log_misc(
|
||||
"<<< attr_read(%p, %s): %s",
|
||||
parent_node,
|
||||
value,
|
||||
core_property_node_result_to_str(result));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static core_property_node_result_t _core_property_node_trace_bool_read(
|
||||
const core_property_node_t *parent_node, bool *value)
|
||||
{
|
||||
core_property_node_result_t result;
|
||||
|
||||
log_misc(">>> bool_read(%p)", parent_node);
|
||||
|
||||
result =
|
||||
_core_property_node_trace_target_api.v1.bool_read(parent_node, value);
|
||||
|
||||
log_misc(
|
||||
"<<< bool_read(%p, %d): %s",
|
||||
parent_node,
|
||||
*value,
|
||||
core_property_node_result_to_str(result));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static core_property_node_result_t
|
||||
_core_property_node_trace_remove(const core_property_node_t *node)
|
||||
{
|
||||
core_property_node_result_t result;
|
||||
|
||||
log_misc(">>> remove(%p)", node);
|
||||
|
||||
result = _core_property_node_trace_target_api.v1.remove(node);
|
||||
|
||||
log_misc(
|
||||
"<<< remove(%p): %s", node, core_property_node_result_to_str(result));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static core_property_node_result_t _core_property_node_trace_copy(
|
||||
core_property_node_t *dst_node, const core_property_node_t *src_node)
|
||||
{
|
||||
core_property_node_result_t result;
|
||||
|
||||
log_misc(">>> copy(%p, %p)", dst_node, src_node);
|
||||
|
||||
result = _core_property_node_trace_target_api.v1.copy(dst_node, src_node);
|
||||
|
||||
log_misc(
|
||||
"<<< copy(%p, %p): %s",
|
||||
dst_node,
|
||||
src_node,
|
||||
core_property_node_result_to_str(result));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void core_property_node_trace_target_api_set(
|
||||
const core_property_node_api_t *target_api)
|
||||
{
|
||||
log_assert(target_api);
|
||||
|
||||
memcpy(
|
||||
&_core_property_node_trace_target_api,
|
||||
target_api,
|
||||
sizeof(core_property_node_api_t));
|
||||
}
|
||||
|
||||
void core_property_node_trace_core_api_get(core_property_node_api_t *api)
|
||||
{
|
||||
log_assert(api);
|
||||
|
||||
api->version = 1;
|
||||
|
||||
api->v1.log = _core_property_node_trace_log;
|
||||
api->v1.name_get = _core_property_node_trace_name_get;
|
||||
api->v1.size = _core_property_node_trace_size;
|
||||
api->v1.search = _core_property_node_trace_search;
|
||||
api->v1.next_result_search = _core_property_node_trace_next_result_search;
|
||||
api->v1.child_get = _core_property_node_trace_child_get;
|
||||
api->v1.next_sibling_get = _core_property_node_trace_next_sibling_get;
|
||||
api->v1.void_create = _core_property_node_trace_void_create;
|
||||
api->v1.s8_create = _core_property_node_trace_s8_create;
|
||||
api->v1.u8_create = _core_property_node_trace_u8_create;
|
||||
api->v1.s16_create = _core_property_node_trace_s16_create;
|
||||
api->v1.u16_create = _core_property_node_trace_u16_create;
|
||||
api->v1.s32_create = _core_property_node_trace_s32_create;
|
||||
api->v1.u32_create = _core_property_node_trace_u32_create;
|
||||
api->v1.s64_create = _core_property_node_trace_s64_create;
|
||||
api->v1.u64_create = _core_property_node_trace_u64_create;
|
||||
api->v1.bin_create = _core_property_node_trace_bin_create;
|
||||
api->v1.str_create = _core_property_node_trace_str_create;
|
||||
api->v1.ipv4_create = _core_property_node_trace_ipv4_create;
|
||||
api->v1.float_create = _core_property_node_trace_float_create;
|
||||
api->v1.double_create = _core_property_node_trace_double_create;
|
||||
api->v1.attr_create = _core_property_node_trace_attr_create;
|
||||
api->v1.bool_create = _core_property_node_trace_bool_create;
|
||||
api->v1.s8_read = _core_property_node_trace_s8_read;
|
||||
api->v1.u8_read = _core_property_node_trace_u8_read;
|
||||
api->v1.s16_read = _core_property_node_trace_s16_read;
|
||||
api->v1.u16_read = _core_property_node_trace_u16_read;
|
||||
api->v1.s32_read = _core_property_node_trace_s32_read;
|
||||
api->v1.u32_read = _core_property_node_trace_u32_read;
|
||||
api->v1.s64_read = _core_property_node_trace_s64_read;
|
||||
api->v1.u64_read = _core_property_node_trace_u64_read;
|
||||
api->v1.bin_read = _core_property_node_trace_bin_read;
|
||||
api->v1.str_read = _core_property_node_trace_str_read;
|
||||
api->v1.ipv4_read = _core_property_node_trace_ipv4_read;
|
||||
api->v1.float_read = _core_property_node_trace_float_read;
|
||||
api->v1.double_read = _core_property_node_trace_double_read;
|
||||
api->v1.attr_read = _core_property_node_trace_attr_read;
|
||||
api->v1.bool_read = _core_property_node_trace_bool_read;
|
||||
api->v1.remove = _core_property_node_trace_remove;
|
||||
api->v1.copy = _core_property_node_trace_copy;
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
#ifndef CORE_PROPERTY_NODE_TRACE_H
|
||||
#define CORE_PROPERTY_NODE_TRACE_H
|
||||
|
||||
#include "main/core/property-node.h"
|
||||
|
||||
void core_property_node_trace_target_api_set(
|
||||
const core_property_node_api_t *target_api);
|
||||
|
||||
void core_property_node_trace_core_api_get(core_property_node_api_t *api);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,605 @@
|
||||
#define LOG_MODULE "core-property-node"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "iface-core/log.h"
|
||||
|
||||
#include "main/core/property-node-trace.h"
|
||||
#include "main/core/property-node.h"
|
||||
|
||||
#define CORE_PROPERTY_NODE_ASSERT_IMPLEMENTED(func, name) \
|
||||
if (!func) { \
|
||||
log_fatal("Function %s not implemented", STRINGIFY(name)); \
|
||||
}
|
||||
|
||||
static bool _core_property_node_trace_log_enable;
|
||||
static core_property_node_api_t _core_property_node_api;
|
||||
|
||||
static bool _core_property_node_api_is_valid()
|
||||
{
|
||||
return _core_property_node_api.version > 0;
|
||||
}
|
||||
|
||||
void core_property_node_trace_log_enable(bool enable)
|
||||
{
|
||||
_core_property_node_trace_log_enable = enable;
|
||||
}
|
||||
|
||||
void core_property_node_api_set(const core_property_node_api_t *api)
|
||||
{
|
||||
core_property_node_api_t trace_api;
|
||||
|
||||
log_assert(api);
|
||||
|
||||
if (_core_property_node_api_is_valid()) {
|
||||
log_warning("Re-initialize");
|
||||
}
|
||||
|
||||
if (api->version == 1) {
|
||||
CORE_PROPERTY_NODE_ASSERT_IMPLEMENTED(api->v1.log, log);
|
||||
CORE_PROPERTY_NODE_ASSERT_IMPLEMENTED(api->v1.name_get, name_get);
|
||||
CORE_PROPERTY_NODE_ASSERT_IMPLEMENTED(api->v1.size, size);
|
||||
CORE_PROPERTY_NODE_ASSERT_IMPLEMENTED(api->v1.search, search);
|
||||
CORE_PROPERTY_NODE_ASSERT_IMPLEMENTED(
|
||||
api->v1.next_result_search, next_result_search);
|
||||
CORE_PROPERTY_NODE_ASSERT_IMPLEMENTED(api->v1.child_get, child_get);
|
||||
CORE_PROPERTY_NODE_ASSERT_IMPLEMENTED(
|
||||
api->v1.next_sibling_get, next_sibling_get);
|
||||
CORE_PROPERTY_NODE_ASSERT_IMPLEMENTED(api->v1.void_create, void_create);
|
||||
CORE_PROPERTY_NODE_ASSERT_IMPLEMENTED(api->v1.s8_create, s8_create);
|
||||
CORE_PROPERTY_NODE_ASSERT_IMPLEMENTED(api->v1.u8_create, u8_create);
|
||||
CORE_PROPERTY_NODE_ASSERT_IMPLEMENTED(api->v1.s16_create, s16_create);
|
||||
CORE_PROPERTY_NODE_ASSERT_IMPLEMENTED(api->v1.u16_create, u16_create);
|
||||
CORE_PROPERTY_NODE_ASSERT_IMPLEMENTED(api->v1.s32_create, s32_create);
|
||||
CORE_PROPERTY_NODE_ASSERT_IMPLEMENTED(api->v1.u32_create, u32_create);
|
||||
CORE_PROPERTY_NODE_ASSERT_IMPLEMENTED(api->v1.s64_create, s64_create);
|
||||
CORE_PROPERTY_NODE_ASSERT_IMPLEMENTED(api->v1.u64_create, u64_create);
|
||||
CORE_PROPERTY_NODE_ASSERT_IMPLEMENTED(api->v1.bin_create, bin_create);
|
||||
CORE_PROPERTY_NODE_ASSERT_IMPLEMENTED(api->v1.str_create, str_create);
|
||||
CORE_PROPERTY_NODE_ASSERT_IMPLEMENTED(api->v1.ipv4_create, ipv4_create);
|
||||
CORE_PROPERTY_NODE_ASSERT_IMPLEMENTED(
|
||||
api->v1.float_create, float_create);
|
||||
CORE_PROPERTY_NODE_ASSERT_IMPLEMENTED(
|
||||
api->v1.double_create, double_create);
|
||||
CORE_PROPERTY_NODE_ASSERT_IMPLEMENTED(api->v1.attr_create, attr_create);
|
||||
CORE_PROPERTY_NODE_ASSERT_IMPLEMENTED(api->v1.bool_create, bool_create);
|
||||
CORE_PROPERTY_NODE_ASSERT_IMPLEMENTED(api->v1.s8_read, s8_read);
|
||||
CORE_PROPERTY_NODE_ASSERT_IMPLEMENTED(api->v1.u8_read, u8_read);
|
||||
CORE_PROPERTY_NODE_ASSERT_IMPLEMENTED(api->v1.s16_read, s16_read);
|
||||
CORE_PROPERTY_NODE_ASSERT_IMPLEMENTED(api->v1.u16_read, u16_read);
|
||||
CORE_PROPERTY_NODE_ASSERT_IMPLEMENTED(api->v1.s32_read, s32_read);
|
||||
CORE_PROPERTY_NODE_ASSERT_IMPLEMENTED(api->v1.u32_read, u32_read);
|
||||
CORE_PROPERTY_NODE_ASSERT_IMPLEMENTED(api->v1.s64_read, s64_read);
|
||||
CORE_PROPERTY_NODE_ASSERT_IMPLEMENTED(api->v1.u64_read, u64_read);
|
||||
CORE_PROPERTY_NODE_ASSERT_IMPLEMENTED(api->v1.bin_read, bin_read);
|
||||
CORE_PROPERTY_NODE_ASSERT_IMPLEMENTED(api->v1.str_read, str_read);
|
||||
CORE_PROPERTY_NODE_ASSERT_IMPLEMENTED(api->v1.ipv4_read, ipv4_read);
|
||||
CORE_PROPERTY_NODE_ASSERT_IMPLEMENTED(api->v1.float_read, float_read);
|
||||
CORE_PROPERTY_NODE_ASSERT_IMPLEMENTED(api->v1.double_read, double_read);
|
||||
CORE_PROPERTY_NODE_ASSERT_IMPLEMENTED(api->v1.attr_read, attr_read);
|
||||
CORE_PROPERTY_NODE_ASSERT_IMPLEMENTED(api->v1.bool_read, bool_read);
|
||||
CORE_PROPERTY_NODE_ASSERT_IMPLEMENTED(api->v1.remove, remove);
|
||||
CORE_PROPERTY_NODE_ASSERT_IMPLEMENTED(api->v1.copy, copy);
|
||||
} else {
|
||||
log_fatal("Unsupported API version: %d", api->version);
|
||||
}
|
||||
|
||||
if (_core_property_node_trace_log_enable) {
|
||||
log_info("API trace log enabled");
|
||||
|
||||
core_property_node_trace_target_api_set(api);
|
||||
core_property_node_trace_core_api_get(&trace_api);
|
||||
|
||||
memcpy(
|
||||
&_core_property_node_api,
|
||||
&trace_api,
|
||||
sizeof(core_property_node_api_t));
|
||||
} else {
|
||||
memcpy(&_core_property_node_api, api, sizeof(core_property_node_api_t));
|
||||
}
|
||||
}
|
||||
|
||||
void core_property_node_api_get(core_property_node_api_t *api)
|
||||
{
|
||||
log_assert(api);
|
||||
log_assert(_core_property_node_api_is_valid());
|
||||
|
||||
memcpy(api, &_core_property_node_api, sizeof(core_property_node_api_t));
|
||||
}
|
||||
|
||||
const char *core_property_node_result_to_str(core_property_node_result_t result)
|
||||
{
|
||||
switch (result) {
|
||||
case CORE_PROPERTY_NODE_RESULT_SUCCESS:
|
||||
return "Success";
|
||||
case CORE_PROPERTY_NODE_RESULT_ERROR_INTERNAL:
|
||||
return "Internal";
|
||||
case CORE_PROPERTY_NODE_RESULT_NODE_NOT_FOUND:
|
||||
return "Node not found";
|
||||
default:
|
||||
return "Undefined error";
|
||||
}
|
||||
}
|
||||
|
||||
void core_property_node_fatal_on_error(core_property_node_result_t result)
|
||||
{
|
||||
switch (result) {
|
||||
case CORE_PROPERTY_NODE_RESULT_SUCCESS:
|
||||
return;
|
||||
case CORE_PROPERTY_NODE_RESULT_ERROR_INTERNAL:
|
||||
case CORE_PROPERTY_NODE_RESULT_NODE_NOT_FOUND:
|
||||
default:
|
||||
log_fatal(
|
||||
"Operation on property failed: %s",
|
||||
core_property_node_result_to_str(result));
|
||||
}
|
||||
}
|
||||
|
||||
void core_property_node_log(
|
||||
const core_property_node_t *node, bt_core_log_message_t log_message)
|
||||
{
|
||||
log_assert(_core_property_node_api_is_valid());
|
||||
log_assert(node);
|
||||
log_assert(log_message);
|
||||
|
||||
_core_property_node_api.v1.log(node, log_message);
|
||||
}
|
||||
|
||||
core_property_node_result_t core_property_node_name_get(
|
||||
const core_property_node_t *node, char *name, size_t len)
|
||||
{
|
||||
log_assert(_core_property_node_api_is_valid());
|
||||
log_assert(node);
|
||||
log_assert(name);
|
||||
log_assert(len > 0);
|
||||
|
||||
return _core_property_node_api.v1.name_get(node, name, len);
|
||||
}
|
||||
|
||||
core_property_node_result_t
|
||||
core_property_node_size(const core_property_node_t *node, size_t *size)
|
||||
{
|
||||
log_assert(_core_property_node_api_is_valid());
|
||||
log_assert(node);
|
||||
log_assert(size);
|
||||
|
||||
return _core_property_node_api.v1.size(node, size);
|
||||
}
|
||||
|
||||
core_property_node_result_t core_property_node_search(
|
||||
const core_property_node_t *node,
|
||||
const char *path,
|
||||
core_property_node_t *node_out)
|
||||
{
|
||||
log_assert(_core_property_node_api_is_valid());
|
||||
log_assert(node);
|
||||
log_assert(path);
|
||||
log_assert(node_out);
|
||||
|
||||
return _core_property_node_api.v1.search(node, path, node_out);
|
||||
}
|
||||
|
||||
core_property_node_result_t core_property_node_next_result_search(
|
||||
const core_property_node_t *node, core_property_node_t *node_out)
|
||||
{
|
||||
log_assert(_core_property_node_api_is_valid());
|
||||
log_assert(node);
|
||||
log_assert(node_out);
|
||||
|
||||
return _core_property_node_api.v1.next_result_search(node, node_out);
|
||||
}
|
||||
|
||||
core_property_node_result_t core_property_node_child_get(
|
||||
const core_property_node_t *node, core_property_node_t *node_out)
|
||||
{
|
||||
log_assert(_core_property_node_api_is_valid());
|
||||
log_assert(node);
|
||||
log_assert(node_out);
|
||||
|
||||
return _core_property_node_api.v1.child_get(node, node_out);
|
||||
}
|
||||
|
||||
core_property_node_result_t core_property_node_next_sibling_get(
|
||||
const core_property_node_t *node, core_property_node_t *node_out)
|
||||
{
|
||||
log_assert(_core_property_node_api_is_valid());
|
||||
log_assert(node);
|
||||
log_assert(node_out);
|
||||
|
||||
return _core_property_node_api.v1.next_sibling_get(node, node_out);
|
||||
}
|
||||
|
||||
core_property_node_result_t core_property_node_void_create(
|
||||
const core_property_node_t *parent_node,
|
||||
const char *key,
|
||||
core_property_node_t *node_out)
|
||||
{
|
||||
log_assert(_core_property_node_api_is_valid());
|
||||
log_assert(parent_node);
|
||||
log_assert(key);
|
||||
|
||||
return _core_property_node_api.v1.void_create(parent_node, key, node_out);
|
||||
}
|
||||
|
||||
core_property_node_result_t core_property_node_s8_create(
|
||||
const core_property_node_t *parent_node,
|
||||
const char *key,
|
||||
int8_t value,
|
||||
core_property_node_t *node_out)
|
||||
{
|
||||
log_assert(_core_property_node_api_is_valid());
|
||||
log_assert(parent_node);
|
||||
log_assert(key);
|
||||
|
||||
return _core_property_node_api.v1.s8_create(
|
||||
parent_node, key, value, node_out);
|
||||
}
|
||||
|
||||
core_property_node_result_t core_property_node_u8_create(
|
||||
const core_property_node_t *parent_node,
|
||||
const char *key,
|
||||
uint8_t value,
|
||||
core_property_node_t *node_out)
|
||||
{
|
||||
log_assert(_core_property_node_api_is_valid());
|
||||
log_assert(parent_node);
|
||||
log_assert(key);
|
||||
|
||||
return _core_property_node_api.v1.u8_create(
|
||||
parent_node, key, value, node_out);
|
||||
}
|
||||
|
||||
core_property_node_result_t core_property_node_s16_create(
|
||||
const core_property_node_t *parent_node,
|
||||
const char *key,
|
||||
int16_t value,
|
||||
core_property_node_t *node_out)
|
||||
{
|
||||
log_assert(_core_property_node_api_is_valid());
|
||||
log_assert(parent_node);
|
||||
log_assert(key);
|
||||
|
||||
return _core_property_node_api.v1.s16_create(
|
||||
parent_node, key, value, node_out);
|
||||
}
|
||||
|
||||
core_property_node_result_t core_property_node_u16_create(
|
||||
const core_property_node_t *parent_node,
|
||||
const char *key,
|
||||
uint16_t value,
|
||||
core_property_node_t *node_out)
|
||||
{
|
||||
log_assert(_core_property_node_api_is_valid());
|
||||
log_assert(parent_node);
|
||||
log_assert(key);
|
||||
|
||||
return _core_property_node_api.v1.u16_create(
|
||||
parent_node, key, value, node_out);
|
||||
}
|
||||
|
||||
core_property_node_result_t core_property_node_s32_create(
|
||||
const core_property_node_t *parent_node,
|
||||
const char *key,
|
||||
int32_t value,
|
||||
core_property_node_t *node_out)
|
||||
{
|
||||
log_assert(_core_property_node_api_is_valid());
|
||||
log_assert(parent_node);
|
||||
log_assert(key);
|
||||
|
||||
return _core_property_node_api.v1.s32_create(
|
||||
parent_node, key, value, node_out);
|
||||
}
|
||||
|
||||
core_property_node_result_t core_property_node_u32_create(
|
||||
const core_property_node_t *parent_node,
|
||||
const char *key,
|
||||
uint32_t value,
|
||||
core_property_node_t *node_out)
|
||||
{
|
||||
log_assert(_core_property_node_api_is_valid());
|
||||
log_assert(parent_node);
|
||||
log_assert(key);
|
||||
|
||||
return _core_property_node_api.v1.u32_create(
|
||||
parent_node, key, value, node_out);
|
||||
}
|
||||
|
||||
core_property_node_result_t core_property_node_s64_create(
|
||||
const core_property_node_t *parent_node,
|
||||
const char *key,
|
||||
int64_t value,
|
||||
core_property_node_t *node_out)
|
||||
{
|
||||
log_assert(_core_property_node_api_is_valid());
|
||||
log_assert(parent_node);
|
||||
log_assert(key);
|
||||
|
||||
return _core_property_node_api.v1.s64_create(
|
||||
parent_node, key, value, node_out);
|
||||
}
|
||||
|
||||
core_property_node_result_t core_property_node_u64_create(
|
||||
const core_property_node_t *parent_node,
|
||||
const char *key,
|
||||
uint64_t value,
|
||||
core_property_node_t *node_out)
|
||||
{
|
||||
log_assert(_core_property_node_api_is_valid());
|
||||
log_assert(parent_node);
|
||||
log_assert(key);
|
||||
|
||||
return _core_property_node_api.v1.u64_create(
|
||||
parent_node, key, value, node_out);
|
||||
}
|
||||
|
||||
core_property_node_result_t core_property_node_bin_create(
|
||||
const core_property_node_t *parent_node,
|
||||
const char *key,
|
||||
void *data,
|
||||
size_t len,
|
||||
core_property_node_t *node_out)
|
||||
{
|
||||
log_assert(_core_property_node_api_is_valid());
|
||||
log_assert(parent_node);
|
||||
log_assert(key);
|
||||
log_assert(data);
|
||||
|
||||
return _core_property_node_api.v1.bin_create(
|
||||
parent_node, key, data, len, node_out);
|
||||
}
|
||||
|
||||
core_property_node_result_t core_property_node_str_create(
|
||||
const core_property_node_t *parent_node,
|
||||
const char *key,
|
||||
const char *value,
|
||||
core_property_node_t *node_out)
|
||||
{
|
||||
log_assert(_core_property_node_api_is_valid());
|
||||
log_assert(parent_node);
|
||||
log_assert(key);
|
||||
log_assert(value);
|
||||
|
||||
return _core_property_node_api.v1.str_create(
|
||||
parent_node, key, value, node_out);
|
||||
}
|
||||
|
||||
core_property_node_result_t core_property_node_ipv4_create(
|
||||
const core_property_node_t *parent_node,
|
||||
const char *key,
|
||||
uint32_t value,
|
||||
core_property_node_t *node_out)
|
||||
{
|
||||
log_assert(_core_property_node_api_is_valid());
|
||||
log_assert(parent_node);
|
||||
log_assert(key);
|
||||
|
||||
return _core_property_node_api.v1.ipv4_create(
|
||||
parent_node, key, value, node_out);
|
||||
}
|
||||
|
||||
core_property_node_result_t core_property_node_float_create(
|
||||
const core_property_node_t *parent_node,
|
||||
const char *key,
|
||||
float value,
|
||||
core_property_node_t *node_out)
|
||||
{
|
||||
log_assert(_core_property_node_api_is_valid());
|
||||
log_assert(parent_node);
|
||||
log_assert(key);
|
||||
|
||||
return _core_property_node_api.v1.float_create(
|
||||
parent_node, key, value, node_out);
|
||||
}
|
||||
|
||||
core_property_node_result_t core_property_node_double_create(
|
||||
const core_property_node_t *parent_node,
|
||||
const char *key,
|
||||
double value,
|
||||
core_property_node_t *node_out)
|
||||
{
|
||||
log_assert(_core_property_node_api_is_valid());
|
||||
log_assert(parent_node);
|
||||
log_assert(key);
|
||||
|
||||
return _core_property_node_api.v1.double_create(
|
||||
parent_node, key, value, node_out);
|
||||
}
|
||||
|
||||
core_property_node_result_t core_property_node_attr_create(
|
||||
const core_property_node_t *parent_node,
|
||||
const char *key,
|
||||
const char *value,
|
||||
core_property_node_t *node_out)
|
||||
{
|
||||
log_assert(_core_property_node_api_is_valid());
|
||||
log_assert(parent_node);
|
||||
log_assert(key);
|
||||
log_assert(value);
|
||||
|
||||
return _core_property_node_api.v1.attr_create(
|
||||
parent_node, key, value, node_out);
|
||||
}
|
||||
|
||||
core_property_node_result_t core_property_node_bool_create(
|
||||
const core_property_node_t *parent_node,
|
||||
const char *key,
|
||||
bool value,
|
||||
core_property_node_t *node_out)
|
||||
{
|
||||
log_assert(_core_property_node_api_is_valid());
|
||||
log_assert(parent_node);
|
||||
log_assert(key);
|
||||
|
||||
return _core_property_node_api.v1.bool_create(
|
||||
parent_node, key, value, node_out);
|
||||
}
|
||||
|
||||
core_property_node_result_t core_property_node_s8_read(
|
||||
const core_property_node_t *parent_node, int8_t *value)
|
||||
{
|
||||
log_assert(_core_property_node_api_is_valid());
|
||||
log_assert(parent_node);
|
||||
log_assert(value);
|
||||
|
||||
return _core_property_node_api.v1.s8_read(parent_node, value);
|
||||
}
|
||||
|
||||
core_property_node_result_t core_property_node_u8_read(
|
||||
const core_property_node_t *parent_node, uint8_t *value)
|
||||
{
|
||||
log_assert(_core_property_node_api_is_valid());
|
||||
log_assert(parent_node);
|
||||
log_assert(value);
|
||||
|
||||
return _core_property_node_api.v1.u8_read(parent_node, value);
|
||||
}
|
||||
|
||||
core_property_node_result_t core_property_node_s16_read(
|
||||
const core_property_node_t *parent_node, int16_t *value)
|
||||
{
|
||||
log_assert(_core_property_node_api_is_valid());
|
||||
log_assert(parent_node);
|
||||
log_assert(value);
|
||||
|
||||
return _core_property_node_api.v1.s16_read(parent_node, value);
|
||||
}
|
||||
|
||||
core_property_node_result_t core_property_node_u16_read(
|
||||
const core_property_node_t *parent_node, uint16_t *value)
|
||||
{
|
||||
log_assert(_core_property_node_api_is_valid());
|
||||
log_assert(parent_node);
|
||||
log_assert(value);
|
||||
|
||||
return _core_property_node_api.v1.u16_read(parent_node, value);
|
||||
}
|
||||
|
||||
core_property_node_result_t core_property_node_s32_read(
|
||||
const core_property_node_t *parent_node, int32_t *value)
|
||||
{
|
||||
log_assert(_core_property_node_api_is_valid());
|
||||
log_assert(parent_node);
|
||||
log_assert(value);
|
||||
|
||||
return _core_property_node_api.v1.s32_read(parent_node, value);
|
||||
}
|
||||
|
||||
core_property_node_result_t core_property_node_u32_read(
|
||||
const core_property_node_t *parent_node, uint32_t *value)
|
||||
{
|
||||
log_assert(_core_property_node_api_is_valid());
|
||||
log_assert(parent_node);
|
||||
log_assert(value);
|
||||
|
||||
return _core_property_node_api.v1.u32_read(parent_node, value);
|
||||
}
|
||||
|
||||
core_property_node_result_t core_property_node_s64_read(
|
||||
const core_property_node_t *parent_node, int64_t *value)
|
||||
{
|
||||
log_assert(_core_property_node_api_is_valid());
|
||||
log_assert(parent_node);
|
||||
log_assert(value);
|
||||
|
||||
return _core_property_node_api.v1.s64_read(parent_node, value);
|
||||
}
|
||||
|
||||
core_property_node_result_t core_property_node_u64_read(
|
||||
const core_property_node_t *parent_node, uint64_t *value)
|
||||
{
|
||||
log_assert(_core_property_node_api_is_valid());
|
||||
log_assert(parent_node);
|
||||
log_assert(value);
|
||||
|
||||
return _core_property_node_api.v1.u64_read(parent_node, value);
|
||||
}
|
||||
|
||||
core_property_node_result_t core_property_node_bin_read(
|
||||
const core_property_node_t *parent_node, void *value, size_t len)
|
||||
{
|
||||
log_assert(_core_property_node_api_is_valid());
|
||||
log_assert(parent_node);
|
||||
log_assert(value);
|
||||
|
||||
return _core_property_node_api.v1.bin_read(parent_node, value, len);
|
||||
}
|
||||
|
||||
core_property_node_result_t core_property_node_str_read(
|
||||
const core_property_node_t *parent_node, char *value, size_t len)
|
||||
{
|
||||
log_assert(_core_property_node_api_is_valid());
|
||||
log_assert(parent_node);
|
||||
log_assert(value);
|
||||
|
||||
return _core_property_node_api.v1.str_read(parent_node, value, len);
|
||||
}
|
||||
|
||||
core_property_node_result_t core_property_node_ipv4_read(
|
||||
const core_property_node_t *parent_node, uint32_t *value)
|
||||
{
|
||||
log_assert(_core_property_node_api_is_valid());
|
||||
log_assert(parent_node);
|
||||
log_assert(value);
|
||||
|
||||
return _core_property_node_api.v1.ipv4_read(parent_node, value);
|
||||
}
|
||||
|
||||
core_property_node_result_t core_property_node_float_read(
|
||||
const core_property_node_t *parent_node, float *value)
|
||||
{
|
||||
log_assert(_core_property_node_api_is_valid());
|
||||
log_assert(parent_node);
|
||||
log_assert(value);
|
||||
|
||||
return _core_property_node_api.v1.float_read(parent_node, value);
|
||||
}
|
||||
|
||||
core_property_node_result_t core_property_node_double_read(
|
||||
const core_property_node_t *parent_node, double *value)
|
||||
{
|
||||
log_assert(_core_property_node_api_is_valid());
|
||||
log_assert(parent_node);
|
||||
log_assert(value);
|
||||
|
||||
return _core_property_node_api.v1.double_read(parent_node, value);
|
||||
}
|
||||
|
||||
core_property_node_result_t core_property_node_attr_read(
|
||||
const core_property_node_t *parent_node, char *value, size_t len)
|
||||
{
|
||||
log_assert(_core_property_node_api_is_valid());
|
||||
log_assert(parent_node);
|
||||
log_assert(value);
|
||||
|
||||
return _core_property_node_api.v1.attr_read(parent_node, value, len);
|
||||
}
|
||||
|
||||
core_property_node_result_t core_property_node_bool_read(
|
||||
const core_property_node_t *parent_node, bool *value)
|
||||
{
|
||||
log_assert(_core_property_node_api_is_valid());
|
||||
log_assert(parent_node);
|
||||
log_assert(value);
|
||||
|
||||
return _core_property_node_api.v1.bool_read(parent_node, value);
|
||||
}
|
||||
|
||||
core_property_node_result_t
|
||||
core_property_node_remove(const core_property_node_t *node)
|
||||
{
|
||||
log_assert(_core_property_node_api_is_valid());
|
||||
log_assert(node);
|
||||
|
||||
return _core_property_node_api.v1.remove(node);
|
||||
}
|
||||
|
||||
core_property_node_result_t core_property_node_copy(
|
||||
core_property_node_t *dst_node, const core_property_node_t *src_node)
|
||||
{
|
||||
log_assert(_core_property_node_api_is_valid());
|
||||
log_assert(dst_node);
|
||||
log_assert(src_node);
|
||||
|
||||
return _core_property_node_api.v1.copy(dst_node, src_node);
|
||||
}
|
||||
@@ -0,0 +1,347 @@
|
||||
#ifndef CORE_PROPERTY_NODE_H
|
||||
#define CORE_PROPERTY_NODE_H
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "api/core/log.h"
|
||||
|
||||
#include "main/core/property.h"
|
||||
|
||||
#define CORE_PROPERTY_NODE_RESULT_IS_ERROR(x) \
|
||||
(x > CORE_PROPERTY_NODE_RESULT_SUCCESS)
|
||||
// Based on actual AVS impl max size
|
||||
#define CORE_PROPERTY_NODE_NAME_SIZE_MAX 256
|
||||
// Guestimate, should be enough, I hope?
|
||||
#define CORE_PROPERTY_NODE_ATTR_NAME_SIZE_MAX 128
|
||||
// Guestimate, should be long enough, I hope?
|
||||
#define CORE_PROPERTY_NODE_PATH_LEN_MAX 4096
|
||||
|
||||
typedef struct core_property_node core_property_node_t;
|
||||
|
||||
typedef enum core_property_node_result {
|
||||
CORE_PROPERTY_NODE_RESULT_SUCCESS = 0,
|
||||
CORE_PROPERTY_NODE_RESULT_ERROR_INTERNAL = 1,
|
||||
CORE_PROPERTY_NODE_RESULT_NODE_NOT_FOUND = 2,
|
||||
} core_property_node_result_t;
|
||||
|
||||
typedef void (*core_property_node_log_t)(
|
||||
const core_property_node_t *node, bt_core_log_message_t log_message);
|
||||
typedef core_property_node_result_t (*core_property_node_name_get_t)(
|
||||
const core_property_node_t *node, char *name, size_t len);
|
||||
typedef core_property_node_result_t (*core_property_node_size_t)(
|
||||
const core_property_node_t *node, size_t *size);
|
||||
typedef core_property_node_result_t (*core_property_node_search_t)(
|
||||
const core_property_node_t *node,
|
||||
const char *path,
|
||||
core_property_node_t *node_out);
|
||||
typedef core_property_node_result_t (*core_property_node_next_result_search_t)(
|
||||
const core_property_node_t *node, core_property_node_t *node_out);
|
||||
typedef core_property_node_result_t (*core_property_node_child_get_t)(
|
||||
const core_property_node_t *node, core_property_node_t *node_out);
|
||||
typedef core_property_node_result_t (*core_property_node_next_sibling_get_t)(
|
||||
const core_property_node_t *node, core_property_node_t *node_out);
|
||||
typedef core_property_node_result_t (*core_property_node_void_create_t)(
|
||||
const core_property_node_t *parent_node,
|
||||
const char *key,
|
||||
core_property_node_t *node_out);
|
||||
typedef core_property_node_result_t (*core_property_node_s8_create_t)(
|
||||
const core_property_node_t *parent_node,
|
||||
const char *key,
|
||||
int8_t value,
|
||||
core_property_node_t *node_out);
|
||||
typedef core_property_node_result_t (*core_property_node_u8_create_t)(
|
||||
const core_property_node_t *parent_node,
|
||||
const char *key,
|
||||
uint8_t value,
|
||||
core_property_node_t *node_out);
|
||||
typedef core_property_node_result_t (*core_property_node_s16_create_t)(
|
||||
const core_property_node_t *parent_node,
|
||||
const char *key,
|
||||
int16_t value,
|
||||
core_property_node_t *node_out);
|
||||
typedef core_property_node_result_t (*core_property_node_u16_create_t)(
|
||||
const core_property_node_t *parent_node,
|
||||
const char *key,
|
||||
uint16_t value,
|
||||
core_property_node_t *node_out);
|
||||
typedef core_property_node_result_t (*core_property_node_s32_create_t)(
|
||||
const core_property_node_t *parent_node,
|
||||
const char *key,
|
||||
int32_t value,
|
||||
core_property_node_t *node_out);
|
||||
typedef core_property_node_result_t (*core_property_node_u32_create_t)(
|
||||
const core_property_node_t *parent_node,
|
||||
const char *key,
|
||||
uint32_t value,
|
||||
core_property_node_t *node_out);
|
||||
typedef core_property_node_result_t (*core_property_node_s64_create_t)(
|
||||
const core_property_node_t *parent_node,
|
||||
const char *key,
|
||||
int64_t value,
|
||||
core_property_node_t *node_out);
|
||||
typedef core_property_node_result_t (*core_property_node_u64_create_t)(
|
||||
const core_property_node_t *parent_node,
|
||||
const char *key,
|
||||
uint64_t value,
|
||||
core_property_node_t *node_out);
|
||||
typedef core_property_node_result_t (*core_property_node_bin_create_t)(
|
||||
const core_property_node_t *parent_node,
|
||||
const char *key,
|
||||
void *data,
|
||||
size_t len,
|
||||
core_property_node_t *node_out);
|
||||
typedef core_property_node_result_t (*core_property_node_str_create_t)(
|
||||
const core_property_node_t *parent_node,
|
||||
const char *key,
|
||||
const char *value,
|
||||
core_property_node_t *node_out);
|
||||
typedef core_property_node_result_t (*core_property_node_ipv4_create_t)(
|
||||
const core_property_node_t *parent_node,
|
||||
const char *key,
|
||||
uint32_t value,
|
||||
core_property_node_t *node_out);
|
||||
typedef core_property_node_result_t (*core_property_node_float_create_t)(
|
||||
const core_property_node_t *parent_node,
|
||||
const char *key,
|
||||
float value,
|
||||
core_property_node_t *node_out);
|
||||
typedef core_property_node_result_t (*core_property_node_double_create_t)(
|
||||
const core_property_node_t *parent_node,
|
||||
const char *key,
|
||||
double value,
|
||||
core_property_node_t *node_out);
|
||||
typedef core_property_node_result_t (*core_property_node_attr_create_t)(
|
||||
const core_property_node_t *parent_node,
|
||||
const char *key,
|
||||
const char *value,
|
||||
core_property_node_t *node_out);
|
||||
typedef core_property_node_result_t (*core_property_node_bool_create_t)(
|
||||
const core_property_node_t *parent_node,
|
||||
const char *key,
|
||||
bool value,
|
||||
core_property_node_t *node_out);
|
||||
typedef core_property_node_result_t (*core_property_node_s8_read_t)(
|
||||
const core_property_node_t *parent_node, int8_t *value);
|
||||
typedef core_property_node_result_t (*core_property_node_u8_read_t)(
|
||||
const core_property_node_t *parent_node, uint8_t *value);
|
||||
typedef core_property_node_result_t (*core_property_node_s16_read_t)(
|
||||
const core_property_node_t *parent_node, int16_t *value);
|
||||
typedef core_property_node_result_t (*core_property_node_u16_read_t)(
|
||||
const core_property_node_t *parent_node, uint16_t *value);
|
||||
typedef core_property_node_result_t (*core_property_node_s32_read_t)(
|
||||
const core_property_node_t *parent_node, int32_t *value);
|
||||
typedef core_property_node_result_t (*core_property_node_u32_read_t)(
|
||||
const core_property_node_t *parent_node, uint32_t *value);
|
||||
typedef core_property_node_result_t (*core_property_node_s64_read_t)(
|
||||
const core_property_node_t *parent_node, int64_t *value);
|
||||
typedef core_property_node_result_t (*core_property_node_u64_read_t)(
|
||||
const core_property_node_t *parent_node, uint64_t *value);
|
||||
typedef core_property_node_result_t (*core_property_node_bin_read_t)(
|
||||
const core_property_node_t *parent_node, void *value, size_t len);
|
||||
typedef core_property_node_result_t (*core_property_node_str_read_t)(
|
||||
const core_property_node_t *parent_node, char *value, size_t len);
|
||||
typedef core_property_node_result_t (*core_property_node_ipv4_read_t)(
|
||||
const core_property_node_t *parent_node, uint32_t *value);
|
||||
typedef core_property_node_result_t (*core_property_node_float_read_t)(
|
||||
const core_property_node_t *parent_node, float *value);
|
||||
typedef core_property_node_result_t (*core_property_node_double_read_t)(
|
||||
const core_property_node_t *parent_node, double *value);
|
||||
typedef core_property_node_result_t (*core_property_node_attr_read_t)(
|
||||
const core_property_node_t *parent_node, char *value, size_t len);
|
||||
typedef core_property_node_result_t (*core_property_node_bool_read_t)(
|
||||
const core_property_node_t *parent_node, bool *value);
|
||||
typedef core_property_node_result_t (*core_property_node_remove_t)(
|
||||
const core_property_node_t *node);
|
||||
typedef core_property_node_result_t (*core_property_node_copy_t)(
|
||||
core_property_node_t *dst_node, const core_property_node_t *src_node);
|
||||
|
||||
typedef struct core_property_node_api {
|
||||
uint16_t version;
|
||||
|
||||
struct {
|
||||
core_property_node_log_t log;
|
||||
core_property_node_name_get_t name_get;
|
||||
core_property_node_size_t size;
|
||||
core_property_node_search_t search;
|
||||
core_property_node_next_result_search_t next_result_search;
|
||||
core_property_node_child_get_t child_get;
|
||||
core_property_node_next_sibling_get_t next_sibling_get;
|
||||
core_property_node_void_create_t void_create;
|
||||
core_property_node_s8_create_t s8_create;
|
||||
core_property_node_u8_create_t u8_create;
|
||||
core_property_node_s16_create_t s16_create;
|
||||
core_property_node_u16_create_t u16_create;
|
||||
core_property_node_s32_create_t s32_create;
|
||||
core_property_node_u32_create_t u32_create;
|
||||
core_property_node_s64_create_t s64_create;
|
||||
core_property_node_u64_create_t u64_create;
|
||||
core_property_node_bin_create_t bin_create;
|
||||
core_property_node_str_create_t str_create;
|
||||
core_property_node_ipv4_create_t ipv4_create;
|
||||
core_property_node_float_create_t float_create;
|
||||
core_property_node_double_create_t double_create;
|
||||
core_property_node_attr_create_t attr_create;
|
||||
core_property_node_bool_create_t bool_create;
|
||||
core_property_node_s8_read_t s8_read;
|
||||
core_property_node_u8_read_t u8_read;
|
||||
core_property_node_s16_read_t s16_read;
|
||||
core_property_node_u16_read_t u16_read;
|
||||
core_property_node_s32_read_t s32_read;
|
||||
core_property_node_u32_read_t u32_read;
|
||||
core_property_node_s64_read_t s64_read;
|
||||
core_property_node_u64_read_t u64_read;
|
||||
core_property_node_bin_read_t bin_read;
|
||||
core_property_node_str_read_t str_read;
|
||||
core_property_node_ipv4_read_t ipv4_read;
|
||||
core_property_node_float_read_t float_read;
|
||||
core_property_node_double_read_t double_read;
|
||||
core_property_node_attr_read_t attr_read;
|
||||
core_property_node_bool_read_t bool_read;
|
||||
core_property_node_remove_t remove;
|
||||
core_property_node_copy_t copy;
|
||||
} v1;
|
||||
} core_property_node_api_t;
|
||||
|
||||
void core_property_node_trace_log_enable(bool enable);
|
||||
void core_property_node_api_set(const core_property_node_api_t *impl);
|
||||
void core_property_node_api_get(core_property_node_api_t *impl);
|
||||
|
||||
const char *
|
||||
core_property_node_result_to_str(core_property_node_result_t result);
|
||||
void core_property_node_fatal_on_error(core_property_node_result_t result);
|
||||
|
||||
void core_property_node_log(
|
||||
const core_property_node_t *node, bt_core_log_message_t log_message);
|
||||
core_property_node_result_t core_property_node_name_get(
|
||||
const core_property_node_t *node, char *name, size_t len);
|
||||
core_property_node_result_t
|
||||
core_property_node_size(const core_property_node_t *node, size_t *size);
|
||||
core_property_node_result_t core_property_node_search(
|
||||
const core_property_node_t *node,
|
||||
const char *path,
|
||||
core_property_node_t *node_out);
|
||||
core_property_node_result_t core_property_node_next_result_search(
|
||||
const core_property_node_t *node, core_property_node_t *node_out);
|
||||
core_property_node_result_t core_property_node_child_get(
|
||||
const core_property_node_t *node, core_property_node_t *node_out);
|
||||
core_property_node_result_t core_property_node_next_sibling_get(
|
||||
const core_property_node_t *node, core_property_node_t *node_out);
|
||||
// Doc remark: node_out is optional here
|
||||
core_property_node_result_t core_property_node_void_create(
|
||||
const core_property_node_t *parent_node,
|
||||
const char *key,
|
||||
core_property_node_t *node_out);
|
||||
core_property_node_result_t core_property_node_s8_create(
|
||||
const core_property_node_t *parent_node,
|
||||
const char *key,
|
||||
int8_t value,
|
||||
core_property_node_t *node_out);
|
||||
core_property_node_result_t core_property_node_u8_create(
|
||||
const core_property_node_t *parent_node,
|
||||
const char *key,
|
||||
uint8_t value,
|
||||
core_property_node_t *node_out);
|
||||
core_property_node_result_t core_property_node_s16_create(
|
||||
const core_property_node_t *parent_node,
|
||||
const char *key,
|
||||
int16_t value,
|
||||
core_property_node_t *node_out);
|
||||
core_property_node_result_t core_property_node_u16_create(
|
||||
const core_property_node_t *parent_node,
|
||||
const char *key,
|
||||
uint16_t value,
|
||||
core_property_node_t *node_out);
|
||||
core_property_node_result_t core_property_node_s32_create(
|
||||
const core_property_node_t *parent_node,
|
||||
const char *key,
|
||||
int32_t value,
|
||||
core_property_node_t *node_out);
|
||||
core_property_node_result_t core_property_node_u32_create(
|
||||
const core_property_node_t *parent_node,
|
||||
const char *key,
|
||||
uint32_t value,
|
||||
core_property_node_t *node_out);
|
||||
core_property_node_result_t core_property_node_s64_create(
|
||||
const core_property_node_t *parent_node,
|
||||
const char *key,
|
||||
int64_t value,
|
||||
core_property_node_t *node_out);
|
||||
core_property_node_result_t core_property_node_u64_create(
|
||||
const core_property_node_t *parent_node,
|
||||
const char *key,
|
||||
uint64_t value,
|
||||
core_property_node_t *node_out);
|
||||
core_property_node_result_t core_property_node_bin_create(
|
||||
const core_property_node_t *parent_node,
|
||||
const char *key,
|
||||
void *data,
|
||||
size_t len,
|
||||
core_property_node_t *node_out);
|
||||
core_property_node_result_t core_property_node_str_create(
|
||||
const core_property_node_t *parent_node,
|
||||
const char *key,
|
||||
const char *value,
|
||||
core_property_node_t *node_out);
|
||||
core_property_node_result_t core_property_node_ipv4_create(
|
||||
const core_property_node_t *parent_node,
|
||||
const char *key,
|
||||
uint32_t value,
|
||||
core_property_node_t *node_out);
|
||||
core_property_node_result_t core_property_node_float_create(
|
||||
const core_property_node_t *parent_node,
|
||||
const char *key,
|
||||
float value,
|
||||
core_property_node_t *node_out);
|
||||
core_property_node_result_t core_property_node_double_create(
|
||||
const core_property_node_t *parent_node,
|
||||
const char *key,
|
||||
double value,
|
||||
core_property_node_t *node_out);
|
||||
core_property_node_result_t core_property_node_attr_create(
|
||||
const core_property_node_t *parent_node,
|
||||
const char *key,
|
||||
const char *value,
|
||||
core_property_node_t *node_out);
|
||||
core_property_node_result_t core_property_node_bool_create(
|
||||
const core_property_node_t *parent_node,
|
||||
const char *key,
|
||||
bool value,
|
||||
core_property_node_t *node_out);
|
||||
core_property_node_result_t core_property_node_s8_read(
|
||||
const core_property_node_t *parent_node, int8_t *value);
|
||||
core_property_node_result_t core_property_node_u8_read(
|
||||
const core_property_node_t *parent_node, uint8_t *value);
|
||||
core_property_node_result_t core_property_node_s16_read(
|
||||
const core_property_node_t *parent_node, int16_t *value);
|
||||
core_property_node_result_t core_property_node_u16_read(
|
||||
const core_property_node_t *parent_node, uint16_t *value);
|
||||
core_property_node_result_t core_property_node_s32_read(
|
||||
const core_property_node_t *parent_node, int32_t *value);
|
||||
core_property_node_result_t core_property_node_u32_read(
|
||||
const core_property_node_t *parent_node, uint32_t *value);
|
||||
core_property_node_result_t core_property_node_s64_read(
|
||||
const core_property_node_t *parent_node, int64_t *value);
|
||||
core_property_node_result_t core_property_node_u64_read(
|
||||
const core_property_node_t *parent_node, uint64_t *value);
|
||||
core_property_node_result_t core_property_node_bin_read(
|
||||
const core_property_node_t *parent_node, void *value, size_t len);
|
||||
core_property_node_result_t core_property_node_str_read(
|
||||
const core_property_node_t *parent_node, char *value, size_t len);
|
||||
core_property_node_result_t core_property_node_ipv4_read(
|
||||
const core_property_node_t *parent_node, uint32_t *value);
|
||||
core_property_node_result_t core_property_node_float_read(
|
||||
const core_property_node_t *parent_node, float *value);
|
||||
core_property_node_result_t core_property_node_double_read(
|
||||
const core_property_node_t *parent_node, double *value);
|
||||
core_property_node_result_t core_property_node_attr_read(
|
||||
const core_property_node_t *parent_node, char *value, size_t len);
|
||||
core_property_node_result_t core_property_node_bool_read(
|
||||
const core_property_node_t *parent_node, bool *value);
|
||||
core_property_node_result_t
|
||||
core_property_node_remove(const core_property_node_t *node);
|
||||
core_property_node_result_t core_property_node_copy(
|
||||
core_property_node_t *dst_node, const core_property_node_t *src_node);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,183 @@
|
||||
#define LOG_MODULE "property-trace"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "core/property.h"
|
||||
|
||||
#include "iface-core/log.h"
|
||||
|
||||
static core_property_api_t _core_property_trace_target_api;
|
||||
|
||||
static core_property_result_t
|
||||
_core_property_trace_create(size_t size, core_property_t **property)
|
||||
{
|
||||
core_property_result_t result;
|
||||
|
||||
log_misc(">>> create(%d)", size);
|
||||
|
||||
result = _core_property_trace_target_api.v1.create(size, property);
|
||||
|
||||
log_misc(
|
||||
"<<< create(%d, %p): %s",
|
||||
size,
|
||||
*property,
|
||||
core_property_result_to_str(result));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static core_property_result_t
|
||||
_core_property_trace_file_load(const char *path, core_property_t **property)
|
||||
{
|
||||
core_property_result_t result;
|
||||
|
||||
log_misc(">>> file_load(%s)", path);
|
||||
|
||||
result = _core_property_trace_target_api.v1.file_load(path, property);
|
||||
|
||||
log_misc(
|
||||
"<<< file_load(%s, %p): %s",
|
||||
path,
|
||||
*property,
|
||||
core_property_result_to_str(result));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static core_property_result_t
|
||||
_core_property_trace_str_load(const char *str, core_property_t **property)
|
||||
{
|
||||
core_property_result_t result;
|
||||
|
||||
log_misc(">>> str_load(%p)", str);
|
||||
|
||||
result = _core_property_trace_target_api.v1.str_load(str, property);
|
||||
|
||||
log_misc(
|
||||
"<<< str_load(%p, %p): %s",
|
||||
str,
|
||||
*property,
|
||||
core_property_result_to_str(result));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static core_property_result_t
|
||||
_core_property_trace_size(const core_property_t *property, size_t *size)
|
||||
{
|
||||
core_property_result_t result;
|
||||
|
||||
log_misc(">>> size(%p)", property);
|
||||
|
||||
result = _core_property_trace_target_api.v1.size(property, size);
|
||||
|
||||
log_misc(
|
||||
"<<< size(%p, %d): %s",
|
||||
property,
|
||||
*size,
|
||||
core_property_result_to_str(result));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static core_property_result_t _core_property_trace_clone(
|
||||
const core_property_t *property, core_property_t **property_cloned)
|
||||
{
|
||||
core_property_result_t result;
|
||||
|
||||
log_misc(">>> clone(%p)", property);
|
||||
|
||||
result =
|
||||
_core_property_trace_target_api.v1.clone(property, property_cloned);
|
||||
|
||||
log_misc(
|
||||
"<<< clone(%p, %p): %s",
|
||||
property,
|
||||
*property_cloned,
|
||||
core_property_result_to_str(result));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static void _core_property_trace_log(
|
||||
const core_property_t *property, bt_core_log_message_t log_message)
|
||||
{
|
||||
log_misc(">>> log(%p)", property);
|
||||
|
||||
_core_property_trace_target_api.v1.log(property, log_message);
|
||||
|
||||
log_misc("<<< log(%p)", property);
|
||||
}
|
||||
|
||||
static core_property_result_t _core_property_trace_root_node_get(
|
||||
const core_property_t *property, core_property_node_t *node)
|
||||
{
|
||||
core_property_result_t result;
|
||||
|
||||
log_misc(">>> root_node_get(%p)", property);
|
||||
|
||||
result = _core_property_trace_target_api.v1.root_node_get(property, node);
|
||||
|
||||
log_misc(
|
||||
"<<< root_node_get(%p, %p): %s",
|
||||
property,
|
||||
node,
|
||||
core_property_result_to_str(result));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static core_property_result_t _core_property_trace_other_node_insert(
|
||||
core_property_t *property, const core_property_node_t *node)
|
||||
{
|
||||
core_property_result_t result;
|
||||
|
||||
log_misc(">>> other_node_insert(%p, %p)", property, node);
|
||||
|
||||
result =
|
||||
_core_property_trace_target_api.v1.other_node_insert(property, node);
|
||||
|
||||
log_misc(
|
||||
"<<< other_node_insert(%p, %p): %s",
|
||||
property,
|
||||
node,
|
||||
core_property_result_to_str(result));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static void _core_property_trace_free(core_property_t **property)
|
||||
{
|
||||
log_misc(">>> free(%p)", *property);
|
||||
|
||||
_core_property_trace_target_api.v1.free(property);
|
||||
|
||||
log_misc("<<< free(%p)", *property);
|
||||
}
|
||||
|
||||
void core_property_trace_target_api_set(const core_property_api_t *target_api)
|
||||
{
|
||||
log_assert(target_api);
|
||||
|
||||
memcpy(
|
||||
&_core_property_trace_target_api,
|
||||
target_api,
|
||||
sizeof(core_property_api_t));
|
||||
}
|
||||
|
||||
void core_property_trace_core_api_get(core_property_api_t *api)
|
||||
{
|
||||
log_assert(api);
|
||||
|
||||
api->version = 1;
|
||||
|
||||
api->v1.create = _core_property_trace_create;
|
||||
api->v1.file_load = _core_property_trace_file_load;
|
||||
api->v1.str_load = _core_property_trace_str_load;
|
||||
api->v1.size = _core_property_trace_size;
|
||||
api->v1.clone = _core_property_trace_clone;
|
||||
api->v1.log = _core_property_trace_log;
|
||||
api->v1.root_node_get = _core_property_trace_root_node_get;
|
||||
api->v1.other_node_insert = _core_property_trace_other_node_insert;
|
||||
api->v1.free = _core_property_trace_free;
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
#ifndef CORE_PROPERTY_TRACE_H
|
||||
#define CORE_PROPERTY_TRACE_H
|
||||
|
||||
#include "main/core/property.h"
|
||||
|
||||
void core_property_trace_target_api_set(const core_property_api_t *target_api);
|
||||
|
||||
void core_property_trace_core_api_get(core_property_api_t *api);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,198 @@
|
||||
#define LOG_MODULE "core-property"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "core/property-trace.h"
|
||||
#include "core/property.h"
|
||||
|
||||
#include "iface-core/log.h"
|
||||
|
||||
#include "util/defs.h"
|
||||
|
||||
#define CORE_PROPERTY_ASSERT_IMPLEMENTED(func, name) \
|
||||
if (!func) { \
|
||||
log_fatal("Function %s not implemented", STRINGIFY(name)); \
|
||||
}
|
||||
|
||||
static bool _core_property_trace_log_enable;
|
||||
static core_property_api_t _core_property_api;
|
||||
|
||||
static bool _core_property_api_is_valid()
|
||||
{
|
||||
return _core_property_api.version > 0;
|
||||
}
|
||||
|
||||
void core_property_trace_log_enable(bool enable)
|
||||
{
|
||||
_core_property_trace_log_enable = enable;
|
||||
}
|
||||
|
||||
void core_property_api_set(const core_property_api_t *api)
|
||||
{
|
||||
core_property_api_t trace_api;
|
||||
|
||||
log_assert(api);
|
||||
|
||||
if (_core_property_api_is_valid()) {
|
||||
log_warning("Re-initialize");
|
||||
}
|
||||
|
||||
if (api->version == 1) {
|
||||
CORE_PROPERTY_ASSERT_IMPLEMENTED(api->v1.create, create);
|
||||
CORE_PROPERTY_ASSERT_IMPLEMENTED(api->v1.file_load, file_load);
|
||||
CORE_PROPERTY_ASSERT_IMPLEMENTED(api->v1.str_load, str_load);
|
||||
CORE_PROPERTY_ASSERT_IMPLEMENTED(api->v1.size, size);
|
||||
CORE_PROPERTY_ASSERT_IMPLEMENTED(api->v1.clone, clone);
|
||||
CORE_PROPERTY_ASSERT_IMPLEMENTED(api->v1.log, log);
|
||||
CORE_PROPERTY_ASSERT_IMPLEMENTED(api->v1.root_node_get, root_node_get);
|
||||
CORE_PROPERTY_ASSERT_IMPLEMENTED(
|
||||
api->v1.other_node_insert, other_node_insert);
|
||||
CORE_PROPERTY_ASSERT_IMPLEMENTED(api->v1.free, free);
|
||||
} else {
|
||||
log_fatal("Unsupported API version: %d", api->version);
|
||||
}
|
||||
|
||||
if (_core_property_trace_log_enable) {
|
||||
log_info("API trace log enabled");
|
||||
|
||||
core_property_trace_target_api_set(api);
|
||||
core_property_trace_core_api_get(&trace_api);
|
||||
|
||||
memcpy(&_core_property_api, &trace_api, sizeof(core_property_api_t));
|
||||
} else {
|
||||
memcpy(&_core_property_api, api, sizeof(core_property_api_t));
|
||||
}
|
||||
}
|
||||
|
||||
void core_property_api_get(core_property_api_t *api)
|
||||
{
|
||||
log_assert(api);
|
||||
log_assert(_core_property_api_is_valid());
|
||||
|
||||
memcpy(api, &_core_property_api, sizeof(core_property_api_t));
|
||||
}
|
||||
|
||||
const char *core_property_result_to_str(core_property_result_t result)
|
||||
{
|
||||
switch (result) {
|
||||
case CORE_PROPERTY_RESULT_SUCCESS:
|
||||
return "Success";
|
||||
case CORE_PROPERTY_RESULT_ERROR_INTERNAL:
|
||||
return "Internal";
|
||||
case CORE_PROPERTY_RESULT_ERROR_ALLOC:
|
||||
return "Allocating memory";
|
||||
case CORE_PROPERTY_RESULT_NOT_FOUND:
|
||||
return "File or path not found";
|
||||
case CORE_PROPERTY_RESULT_ERROR_PERMISSIONS:
|
||||
return "Permissions";
|
||||
case CORE_PROPERTY_RESULT_ERROR_READ:
|
||||
return "Read error";
|
||||
default:
|
||||
return "Undefined error";
|
||||
}
|
||||
}
|
||||
|
||||
void core_property_fatal_on_error(core_property_result_t result)
|
||||
{
|
||||
switch (result) {
|
||||
case CORE_PROPERTY_RESULT_SUCCESS:
|
||||
return;
|
||||
case CORE_PROPERTY_RESULT_ERROR_INTERNAL:
|
||||
case CORE_PROPERTY_RESULT_ERROR_ALLOC:
|
||||
case CORE_PROPERTY_RESULT_NOT_FOUND:
|
||||
case CORE_PROPERTY_RESULT_ERROR_PERMISSIONS:
|
||||
case CORE_PROPERTY_RESULT_ERROR_READ:
|
||||
default:
|
||||
log_fatal(
|
||||
"Operation on property failed: %s",
|
||||
core_property_result_to_str(result));
|
||||
}
|
||||
}
|
||||
|
||||
core_property_result_t
|
||||
core_property_create(size_t size, core_property_t **property)
|
||||
{
|
||||
log_assert(_core_property_api_is_valid());
|
||||
log_assert(size > 0);
|
||||
log_assert(property);
|
||||
|
||||
return _core_property_api.v1.create(size, property);
|
||||
}
|
||||
|
||||
core_property_result_t
|
||||
core_property_file_load(const char *path, core_property_t **property)
|
||||
{
|
||||
log_assert(_core_property_api_is_valid());
|
||||
log_assert(path);
|
||||
log_assert(property);
|
||||
|
||||
return _core_property_api.v1.file_load(path, property);
|
||||
}
|
||||
|
||||
core_property_result_t
|
||||
core_property_str_load(const char *str, core_property_t **property)
|
||||
{
|
||||
log_assert(_core_property_api_is_valid());
|
||||
log_assert(str);
|
||||
log_assert(property);
|
||||
|
||||
return _core_property_api.v1.str_load(str, property);
|
||||
}
|
||||
|
||||
core_property_result_t
|
||||
core_property_size(const core_property_t *property, size_t *size)
|
||||
{
|
||||
log_assert(_core_property_api_is_valid());
|
||||
log_assert(property);
|
||||
log_assert(size);
|
||||
|
||||
return _core_property_api.v1.size(property, size);
|
||||
}
|
||||
|
||||
core_property_result_t core_property_clone(
|
||||
const core_property_t *property, core_property_t **property_cloned)
|
||||
{
|
||||
log_assert(_core_property_api_is_valid());
|
||||
log_assert(property);
|
||||
log_assert(property_cloned);
|
||||
|
||||
return _core_property_api.v1.clone(property, property_cloned);
|
||||
}
|
||||
|
||||
void core_property_log(
|
||||
const core_property_t *property, bt_core_log_message_t log_message)
|
||||
{
|
||||
log_assert(_core_property_api_is_valid());
|
||||
log_assert(property);
|
||||
log_assert(log_message);
|
||||
|
||||
_core_property_api.v1.log(property, log_message);
|
||||
}
|
||||
|
||||
core_property_result_t core_property_root_node_get(
|
||||
const core_property_t *property, core_property_node_t *node)
|
||||
{
|
||||
log_assert(_core_property_api_is_valid());
|
||||
log_assert(property);
|
||||
log_assert(node);
|
||||
|
||||
return _core_property_api.v1.root_node_get(property, node);
|
||||
}
|
||||
|
||||
core_property_result_t core_property_other_node_insert(
|
||||
core_property_t *property, const core_property_node_t *node)
|
||||
{
|
||||
log_assert(_core_property_api_is_valid());
|
||||
log_assert(property);
|
||||
log_assert(node);
|
||||
|
||||
return _core_property_api.v1.other_node_insert(property, node);
|
||||
}
|
||||
|
||||
void core_property_free(core_property_t **property)
|
||||
{
|
||||
log_assert(_core_property_api_is_valid());
|
||||
log_assert(property);
|
||||
|
||||
_core_property_api.v1.free(property);
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
#ifndef CORE_PROPERTY_H
|
||||
#define CORE_PROPERTY_H
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "api/core/log.h"
|
||||
|
||||
#define CORE_PROPERTY_RESULT_IS_ERROR(x) (x > CORE_PROPERTY_RESULT_SUCCESS)
|
||||
|
||||
typedef struct core_property {
|
||||
// Have size known, but not contents, to allow for stack allocations
|
||||
void *v1;
|
||||
} core_property_t;
|
||||
|
||||
typedef struct core_property_node {
|
||||
// Have size known, but not contents, to allow for stack allocations
|
||||
void *v1;
|
||||
void *v2;
|
||||
} core_property_node_t;
|
||||
|
||||
typedef enum core_property_result {
|
||||
CORE_PROPERTY_RESULT_SUCCESS = 0,
|
||||
CORE_PROPERTY_RESULT_ERROR_INTERNAL = 1,
|
||||
CORE_PROPERTY_RESULT_ERROR_ALLOC = 2,
|
||||
CORE_PROPERTY_RESULT_NOT_FOUND = 3,
|
||||
CORE_PROPERTY_RESULT_ERROR_PERMISSIONS = 4,
|
||||
CORE_PROPERTY_RESULT_ERROR_READ = 5,
|
||||
} core_property_result_t;
|
||||
|
||||
typedef core_property_result_t (*core_property_create_t)(
|
||||
size_t size, core_property_t **result);
|
||||
typedef core_property_result_t (*core_property_file_load_t)(
|
||||
const char *path, core_property_t **result);
|
||||
typedef core_property_result_t (*core_property_str_load_t)(
|
||||
const char *str, core_property_t **result);
|
||||
typedef core_property_result_t (*core_property_size_t)(
|
||||
const core_property_t *property, size_t *size);
|
||||
typedef core_property_result_t (*core_property_clone_t)(
|
||||
const core_property_t *property, core_property_t **result);
|
||||
typedef void (*core_property_log_t)(
|
||||
const core_property_t *property, bt_core_log_message_t log_message);
|
||||
typedef core_property_result_t (*core_property_root_node_get_t)(
|
||||
const core_property_t *property, core_property_node_t *result);
|
||||
typedef core_property_result_t (*core_property_other_node_insert_t)(
|
||||
core_property_t *property, const core_property_node_t *node);
|
||||
typedef void (*core_property_free_t)(core_property_t **property);
|
||||
|
||||
typedef struct core_property_api {
|
||||
uint16_t version;
|
||||
|
||||
struct {
|
||||
core_property_create_t create;
|
||||
core_property_file_load_t file_load;
|
||||
core_property_str_load_t str_load;
|
||||
core_property_size_t size;
|
||||
core_property_clone_t clone;
|
||||
core_property_log_t log;
|
||||
core_property_root_node_get_t root_node_get;
|
||||
core_property_other_node_insert_t other_node_insert;
|
||||
core_property_free_t free;
|
||||
} v1;
|
||||
} core_property_api_t;
|
||||
|
||||
void core_property_trace_log_enable(bool enable);
|
||||
void core_property_api_set(const core_property_api_t *api);
|
||||
void core_property_api_get(core_property_api_t *api);
|
||||
|
||||
const char *core_property_result_to_str(core_property_result_t result);
|
||||
void core_property_fatal_on_error(core_property_result_t result);
|
||||
|
||||
core_property_result_t
|
||||
core_property_create(size_t size, core_property_t **property);
|
||||
core_property_result_t
|
||||
core_property_file_load(const char *path, core_property_t **property);
|
||||
core_property_result_t
|
||||
core_property_str_load(const char *str, core_property_t **property);
|
||||
core_property_result_t
|
||||
core_property_size(const core_property_t *property, size_t *size);
|
||||
core_property_result_t core_property_clone(
|
||||
const core_property_t *property, core_property_t **property_cloned);
|
||||
void core_property_log(
|
||||
const core_property_t *property, bt_core_log_message_t log_message);
|
||||
core_property_result_t core_property_root_node_get(
|
||||
const core_property_t *property, core_property_node_t *node);
|
||||
core_property_result_t core_property_other_node_insert(
|
||||
core_property_t *property, const core_property_node_t *node);
|
||||
void core_property_free(core_property_t **property);
|
||||
|
||||
#endif
|
||||
@@ -1,8 +0,0 @@
|
||||
#include "core/thread-crt.h"
|
||||
#include "core/thread.h"
|
||||
|
||||
void core_thread_crt_ext_impl_set()
|
||||
{
|
||||
core_thread_impl_set(
|
||||
core_thread_crt_create, core_thread_crt_join, core_thread_crt_destroy);
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
#ifndef CORE_THREAD_CRT_EXT_H
|
||||
#define CORE_THREAD_CRT_EXT_H
|
||||
|
||||
/**
|
||||
* Set the current thread API implementation to use the C runtime thread API
|
||||
*/
|
||||
void core_thread_crt_ext_impl_set();
|
||||
|
||||
#endif
|
||||
+51
-16
@@ -4,23 +4,29 @@
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "api/core/thread.h"
|
||||
|
||||
#include "core/thread-crt.h"
|
||||
#include "core/thread.h"
|
||||
|
||||
#include "iface-core/log.h"
|
||||
#include "iface-core/thread.h"
|
||||
|
||||
#include "util/defs.h"
|
||||
|
||||
struct shim_ctx {
|
||||
struct core_thread_crt_shim_ctx {
|
||||
HANDLE barrier;
|
||||
int (*proc)(void *);
|
||||
void *ctx;
|
||||
};
|
||||
|
||||
static unsigned int STDCALL crt_thread_shim(void *outer_ctx)
|
||||
static unsigned int STDCALL _core_thread_crt_thread_shim(void *outer_ctx)
|
||||
{
|
||||
struct shim_ctx *sctx = outer_ctx;
|
||||
struct core_thread_crt_shim_ctx *sctx;
|
||||
int (*proc)(void *);
|
||||
void *inner_ctx;
|
||||
|
||||
sctx = outer_ctx;
|
||||
|
||||
proc = sctx->proc;
|
||||
inner_ctx = sctx->ctx;
|
||||
|
||||
@@ -29,34 +35,63 @@ static unsigned int STDCALL crt_thread_shim(void *outer_ctx)
|
||||
return proc(inner_ctx);
|
||||
}
|
||||
|
||||
int core_thread_crt_create(
|
||||
int (*proc)(void *), void *ctx, uint32_t stack_sz, unsigned int priority)
|
||||
static bt_core_thread_result_t _core_thread_crt_create(
|
||||
int (*proc)(void *),
|
||||
void *ctx,
|
||||
uint32_t stack_sz,
|
||||
unsigned int priority,
|
||||
bt_core_thread_id_t *thread_id)
|
||||
{
|
||||
struct shim_ctx sctx;
|
||||
uintptr_t thread_id;
|
||||
struct core_thread_crt_shim_ctx sctx;
|
||||
|
||||
sctx.barrier = CreateEvent(NULL, TRUE, FALSE, NULL);
|
||||
sctx.proc = proc;
|
||||
sctx.ctx = ctx;
|
||||
|
||||
thread_id = _beginthreadex(NULL, stack_sz, crt_thread_shim, &sctx, 0, NULL);
|
||||
*thread_id = _beginthreadex(
|
||||
NULL, stack_sz, _core_thread_crt_thread_shim, &sctx, 0, NULL);
|
||||
|
||||
WaitForSingleObject(sctx.barrier, INFINITE);
|
||||
CloseHandle(sctx.barrier);
|
||||
|
||||
return (int) thread_id;
|
||||
return BT_CORE_THREAD_RESULT_SUCCESS;
|
||||
}
|
||||
|
||||
void core_thread_crt_destroy(int thread_id)
|
||||
{
|
||||
CloseHandle((HANDLE) (uintptr_t) thread_id);
|
||||
}
|
||||
|
||||
void core_thread_crt_join(int thread_id, int *result)
|
||||
static bt_core_thread_result_t
|
||||
_core_thread_crt_join(bt_core_thread_id_t thread_id, int *result)
|
||||
{
|
||||
WaitForSingleObject((HANDLE) (uintptr_t) thread_id, INFINITE);
|
||||
|
||||
if (result) {
|
||||
GetExitCodeThread((HANDLE) (uintptr_t) thread_id, (DWORD *) result);
|
||||
}
|
||||
|
||||
return BT_CORE_THREAD_RESULT_SUCCESS;
|
||||
}
|
||||
|
||||
static bt_core_thread_result_t
|
||||
_core_thread_crt_destroy(bt_core_thread_id_t thread_id)
|
||||
{
|
||||
CloseHandle((HANDLE) (uintptr_t) thread_id);
|
||||
|
||||
return BT_CORE_THREAD_RESULT_SUCCESS;
|
||||
}
|
||||
|
||||
static void _core_thread_crt_core_api_get(bt_core_thread_api_t *api)
|
||||
{
|
||||
log_assert(api);
|
||||
|
||||
api->version = 1;
|
||||
|
||||
api->v1.create = _core_thread_crt_create;
|
||||
api->v1.join = _core_thread_crt_join;
|
||||
api->v1.destroy = _core_thread_crt_destroy;
|
||||
}
|
||||
|
||||
void core_thread_crt_core_api_set()
|
||||
{
|
||||
bt_core_thread_api_t api;
|
||||
|
||||
_core_thread_crt_core_api_get(&api);
|
||||
bt_core_thread_api_set(&api);
|
||||
}
|
||||
@@ -1,15 +1,8 @@
|
||||
#ifndef CORE_THREAD_CRT_H
|
||||
#define CORE_THREAD_CRT_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include "api/core/thread.h"
|
||||
|
||||
/**
|
||||
* Thread API implementation using the C runtime API
|
||||
*/
|
||||
|
||||
int core_thread_crt_create(
|
||||
int (*proc)(void *), void *ctx, uint32_t stack_sz, unsigned int priority);
|
||||
void core_thread_crt_join(int thread_id, int *result);
|
||||
void core_thread_crt_destroy(int thread_id);
|
||||
void core_thread_crt_core_api_set();
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,78 +0,0 @@
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "core/log.h"
|
||||
#include "core/thread.h"
|
||||
|
||||
core_thread_create_t core_thread_create_impl;
|
||||
core_thread_join_t core_thread_join_impl;
|
||||
core_thread_destroy_t core_thread_destroy_impl;
|
||||
|
||||
int core_thread_create(
|
||||
int (*proc)(void *), void *ctx, uint32_t stack_sz, unsigned int priority)
|
||||
{
|
||||
log_assert(core_thread_create_impl);
|
||||
|
||||
return core_thread_create_impl(proc, ctx, stack_sz, priority);
|
||||
}
|
||||
|
||||
void core_thread_join(int thread_id, int *result)
|
||||
{
|
||||
log_assert(core_thread_join_impl);
|
||||
|
||||
core_thread_join_impl(thread_id, result);
|
||||
}
|
||||
|
||||
void core_thread_destroy(int thread_id)
|
||||
{
|
||||
log_assert(core_thread_destroy_impl);
|
||||
|
||||
core_thread_destroy_impl(thread_id);
|
||||
}
|
||||
|
||||
void core_thread_impl_set(
|
||||
core_thread_create_t create,
|
||||
core_thread_join_t join,
|
||||
core_thread_destroy_t destroy)
|
||||
{
|
||||
if (create == NULL || join == NULL || destroy == NULL) {
|
||||
abort();
|
||||
}
|
||||
|
||||
core_thread_create_impl = create;
|
||||
core_thread_join_impl = join;
|
||||
core_thread_destroy_impl = destroy;
|
||||
}
|
||||
|
||||
void core_thread_impl_assign(core_thread_impl_set_t impl_set)
|
||||
{
|
||||
if (core_thread_create_impl == NULL || core_thread_join_impl == NULL ||
|
||||
core_thread_destroy_impl == NULL) {
|
||||
abort();
|
||||
}
|
||||
|
||||
impl_set(
|
||||
core_thread_create_impl,
|
||||
core_thread_join_impl,
|
||||
core_thread_destroy_impl);
|
||||
}
|
||||
|
||||
core_thread_create_t core_thread_create_impl_get()
|
||||
{
|
||||
log_assert(core_thread_create_impl);
|
||||
|
||||
return core_thread_create_impl;
|
||||
}
|
||||
|
||||
core_thread_join_t core_thread_join_impl_get()
|
||||
{
|
||||
log_assert(core_thread_join_impl);
|
||||
|
||||
return core_thread_join_impl;
|
||||
}
|
||||
|
||||
core_thread_destroy_t core_thread_destroy_impl_get()
|
||||
{
|
||||
log_assert(core_thread_destroy_impl);
|
||||
|
||||
return core_thread_destroy_impl;
|
||||
}
|
||||
@@ -1,117 +0,0 @@
|
||||
#ifndef CORE_THREAD_H
|
||||
#define CORE_THREAD_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/**
|
||||
* The core thread API of bemanitools.
|
||||
*
|
||||
* This essentially reflects the AVS threading API and allows for swapping out
|
||||
* the backends with different implementations. Most games should have some
|
||||
* version of the AVS API available while some (legacy) games do not. These
|
||||
* can use a bemanitools private threading implementation by configuring it
|
||||
* in the bootstrapping process.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Create a thread
|
||||
*
|
||||
* Always use this interface in your application which hides the currently
|
||||
* configured implementation.
|
||||
*
|
||||
* @param proc The function to run in a separate thread
|
||||
* @param ctx Additional data to pass to the function as a parameter
|
||||
* @param stack_sz The stack size to allocate for the thread in bytes
|
||||
* @param priority The thread's priority
|
||||
* @return The ID of the thread once created and started
|
||||
*/
|
||||
int core_thread_create(
|
||||
int (*proc)(void *), void *ctx, uint32_t stack_sz, unsigned int priority);
|
||||
|
||||
/**
|
||||
* Wait for a thread to finish
|
||||
*
|
||||
* Always use this interface in your application which hides the currently
|
||||
* configured implementation.
|
||||
*
|
||||
* The caller of this function blocks until the thread has finished executing.
|
||||
*
|
||||
* @param thread_id ID of the thread to wait for
|
||||
* @param result Pointer to a variable to write the return value of the function
|
||||
* the thread executed to
|
||||
*/
|
||||
void core_thread_join(int thread_id, int *result);
|
||||
|
||||
/**
|
||||
* Destroy a thread
|
||||
*
|
||||
* Always use this interface in your application which hides the currently
|
||||
* configured implementation.
|
||||
*
|
||||
* The thread must have finished execution before calling this. It is advised
|
||||
* to make threads terminate their execution flow, join them and destroy.
|
||||
*
|
||||
* @param thread_id The ID of the thread to destroy.
|
||||
*/
|
||||
void core_thread_destroy(int thread_id);
|
||||
|
||||
typedef int (*core_thread_create_t)(
|
||||
int (*proc)(void *), void *ctx, uint32_t stack_sz, unsigned int priority);
|
||||
typedef void (*core_thread_join_t)(int thread_id, int *result);
|
||||
typedef void (*core_thread_destroy_t)(int thread_id);
|
||||
|
||||
typedef void (*core_thread_impl_set_t)(
|
||||
core_thread_create_t create,
|
||||
core_thread_join_t join,
|
||||
core_thread_destroy_t destroy);
|
||||
|
||||
/**
|
||||
* Configure the thread API implementations
|
||||
*
|
||||
* Advised to do this as early in your application/library module as possible
|
||||
* as calls to the getter functions below will return the currently configured
|
||||
* implementations.
|
||||
*
|
||||
* @param create Pointer to a function implementing thread creation
|
||||
* @param join Pointer to a function implementing joining of a thread
|
||||
* @param destroy Pointer to a function implementing destroying of a thread
|
||||
*/
|
||||
void core_thread_impl_set(
|
||||
core_thread_create_t create,
|
||||
core_thread_join_t join,
|
||||
core_thread_destroy_t destroy);
|
||||
|
||||
/**
|
||||
* Supporting function to inject/assign the currently set implementation
|
||||
* with the given setter function.
|
||||
*
|
||||
* @param impl_set Setter function to call with the currently configured thread
|
||||
* function implementations
|
||||
*/
|
||||
void core_thread_impl_assign(core_thread_impl_set_t impl_set);
|
||||
|
||||
/**
|
||||
* Get the currently configured implementation for thread_create
|
||||
*
|
||||
* @return Pointer to the currently configured implementation of the
|
||||
* thread_create function
|
||||
*/
|
||||
core_thread_create_t core_thread_create_impl_get();
|
||||
|
||||
/**
|
||||
* Get the currently configured implementation for thread_join
|
||||
*
|
||||
* @return Pointer to the currently configured implementation of the thread_join
|
||||
* function
|
||||
*/
|
||||
core_thread_join_t core_thread_join_impl_get();
|
||||
|
||||
/**
|
||||
* Get the currently configured implementation for thread_destroy
|
||||
*
|
||||
* @return Pointer to the currently configured implementation of the
|
||||
* thread_destroy function
|
||||
*/
|
||||
core_thread_destroy_t core_thread_destroy_impl_get();
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user