mirror of
https://github.com/djhackersdev/bemanitools.git
synced 2026-04-08 18:25:04 -05:00
feat: Property (node) API impl with mxml
To provide a unified backend for all games, no matter if they have AVS 2 available or now, use the property (node) abstraction for any means of configuration. This is somewhat annoying and a pain because the property API isn't amazing. However, the past has shown that having different means of providing and handling (structured) configuration data isn't great either. Thus, have a non AVS implementation that allows AVS independent applications/old games to use the same core bemanitools API. Summary: Test Plan: Summary: Test Plan:
This commit is contained in:
parent
7a6c3af9c8
commit
e3c97801ed
|
|
@ -11,6 +11,7 @@ libs_config := \
|
|||
geninput \
|
||||
util \
|
||||
iface-core \
|
||||
mxml \
|
||||
|
||||
ldflags_config := \
|
||||
-lcomctl32 \
|
||||
|
|
|
|||
|
|
@ -18,8 +18,8 @@ src_core := \
|
|||
log-sink-std.c \
|
||||
property-ext.c \
|
||||
property-mxml.c \
|
||||
property-mxml.c \
|
||||
property-node-ext.c \
|
||||
property-node-mxml.c \
|
||||
property-node-trace.c \
|
||||
property-node.c \
|
||||
property-trace.c \
|
||||
|
|
|
|||
33
src/main/core/property-mxml-internal.h
Normal file
33
src/main/core/property-mxml-internal.h
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
#ifndef CORE_PROPERTY_MXML_INTERNAL_H
|
||||
#define CORE_PROPERTY_MXML_INTERNAL_H
|
||||
|
||||
#include <mxml/mxml.h>
|
||||
|
||||
#include "core/property.h"
|
||||
#include "core/property-node.h"
|
||||
|
||||
// As there is no need to have a fixed size allocated for properties with
|
||||
// everything dynamically growing on the heap when necessary, just
|
||||
// use this as a dummy value to be compatible with the property interface
|
||||
#define CORE_PROPERTY_MXML_INTERNAL_FIXED_SIZE_DUMMY 573
|
||||
|
||||
typedef struct core_property_mxml_internal_property {
|
||||
mxml_node_t *document;
|
||||
} core_property_mxml_internal_property_t;
|
||||
|
||||
_Static_assert(
|
||||
sizeof(core_property_mxml_internal_property_t) <= sizeof(core_property_t),
|
||||
"Not enough space for stack allocations");
|
||||
|
||||
typedef struct core_property_mxml_internal_property_node {
|
||||
core_property_mxml_internal_property_t *property;
|
||||
mxml_node_t *node;
|
||||
// Used when node is being iterated to remember the root of the iteration
|
||||
mxml_node_t *node_root_iter;
|
||||
} core_property_mxml_internal_property_node_t;
|
||||
|
||||
_Static_assert(
|
||||
sizeof(core_property_mxml_internal_property_node_t) <= sizeof(core_property_node_t),
|
||||
"Not enough space for stack allocations");
|
||||
|
||||
#endif
|
||||
240
src/main/core/property-mxml.c
Normal file
240
src/main/core/property-mxml.c
Normal file
|
|
@ -0,0 +1,240 @@
|
|||
#define LOG_MODULE "core-property-mxml"
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include <mxml/mxml.h>
|
||||
|
||||
#include "core/property-mxml-internal.h"
|
||||
#include "core/property-node-mxml.h"
|
||||
#include "core/property-mxml.h"
|
||||
|
||||
#include "iface-core/log.h"
|
||||
|
||||
#include "util/fs.h"
|
||||
#include "util/mem.h"
|
||||
|
||||
static core_property_result_t
|
||||
_core_property_mxml_create(size_t size, core_property_t **property_)
|
||||
{
|
||||
mxml_node_t *node;
|
||||
core_property_mxml_internal_property_t *property;
|
||||
|
||||
// There is no need to use the size parameter here as everything's allocated
|
||||
// dynamically on the heap and no initial fixed size is needed
|
||||
node = mxmlNewXML(NULL);
|
||||
|
||||
if (!node) {
|
||||
return CORE_PROPERTY_RESULT_ERROR_ALLOC;
|
||||
}
|
||||
|
||||
property = xmalloc(sizeof(core_property_mxml_internal_property_t));
|
||||
|
||||
property->document = node;
|
||||
|
||||
*property_ = (core_property_t *) property;
|
||||
|
||||
return CORE_PROPERTY_RESULT_SUCCESS;
|
||||
}
|
||||
|
||||
static core_property_result_t
|
||||
_core_property_mxml_file_load(const char *path, core_property_t **property_)
|
||||
{
|
||||
mxml_node_t *node;
|
||||
core_property_mxml_internal_property_t *property;
|
||||
|
||||
// The return value NULL of the loading function
|
||||
// doesn't distinguish file not found and loading error =|
|
||||
if (!path_exists(path)) {
|
||||
return CORE_PROPERTY_RESULT_NOT_FOUND;
|
||||
}
|
||||
|
||||
node = mxmlLoadFilename(NULL, NULL, path);
|
||||
|
||||
if (!node) {
|
||||
return CORE_PROPERTY_RESULT_ERROR_READ;
|
||||
}
|
||||
|
||||
property = xmalloc(sizeof(core_property_mxml_internal_property_t));
|
||||
|
||||
property->document = node;
|
||||
|
||||
*property_ = (core_property_t *) property;
|
||||
|
||||
return CORE_PROPERTY_RESULT_SUCCESS;
|
||||
}
|
||||
|
||||
static core_property_result_t
|
||||
_core_property_mxml_str_load(const char *str, core_property_t **property_)
|
||||
{
|
||||
mxml_node_t *node;
|
||||
core_property_mxml_internal_property_t *property;
|
||||
|
||||
node = mxmlLoadString(NULL, NULL, str);
|
||||
|
||||
if (!node) {
|
||||
return CORE_PROPERTY_RESULT_ERROR_READ;
|
||||
}
|
||||
|
||||
property = xmalloc(sizeof(core_property_mxml_internal_property_t));
|
||||
|
||||
property->document = node;
|
||||
|
||||
*property_ = (core_property_t *) property;
|
||||
|
||||
return CORE_PROPERTY_RESULT_SUCCESS;
|
||||
}
|
||||
|
||||
static core_property_result_t
|
||||
_core_property_mxml_size(const core_property_t *property_, size_t *size)
|
||||
{
|
||||
*size = CORE_PROPERTY_MXML_INTERNAL_FIXED_SIZE_DUMMY;
|
||||
|
||||
return CORE_PROPERTY_RESULT_SUCCESS;
|
||||
}
|
||||
|
||||
static core_property_result_t _core_property_mxml_clone(
|
||||
const core_property_t *property_, core_property_t **property_cloned_)
|
||||
{
|
||||
const core_property_mxml_internal_property_t *property;
|
||||
core_property_mxml_internal_property_t **property_cloned;
|
||||
|
||||
char *str_copy;
|
||||
mxml_node_t *node_cloned;
|
||||
|
||||
property = (const core_property_mxml_internal_property_t*) property_;
|
||||
property_cloned = (core_property_mxml_internal_property_t**) property_cloned_;
|
||||
|
||||
// Ensure actual cloning by storing and loading this
|
||||
// Just "adding it" to the other tree with mxml creates a reference only
|
||||
|
||||
str_copy = mxmlSaveAllocString(property->document, NULL);
|
||||
|
||||
if (str_copy == NULL) {
|
||||
return CORE_PROPERTY_RESULT_ERROR_READ;
|
||||
}
|
||||
|
||||
node_cloned = mxmlLoadString(NULL, NULL, str_copy);
|
||||
|
||||
if (node_cloned == NULL) {
|
||||
return CORE_PROPERTY_RESULT_ERROR_WRITE;
|
||||
}
|
||||
|
||||
*property_cloned = xmalloc(sizeof(core_property_mxml_internal_property_t));
|
||||
|
||||
(*property_cloned)->document = node_cloned;
|
||||
|
||||
return CORE_PROPERTY_RESULT_SUCCESS;
|
||||
}
|
||||
|
||||
static core_property_result_t _core_property_mxml_root_node_get(
|
||||
const core_property_t *property_, core_property_node_t *node_)
|
||||
{
|
||||
core_property_mxml_internal_property_t *property;
|
||||
core_property_mxml_internal_property_node_t *node;
|
||||
mxml_node_t *mxml_node;
|
||||
mxml_type_t type;
|
||||
|
||||
property = (core_property_mxml_internal_property_t *) property_;
|
||||
node = (core_property_mxml_internal_property_node_t *) node_;
|
||||
|
||||
memset(node, 0, sizeof(core_property_mxml_internal_property_node_t));
|
||||
|
||||
// Walk the nodes as the loaded xml node is the document root
|
||||
// which can be the xml directive, or if missing, the first root
|
||||
// element
|
||||
for (mxml_node = property->document;
|
||||
mxml_node != NULL;
|
||||
mxml_node = mxmlWalkNext(mxml_node, property->document, MXML_DESCEND_FIRST))
|
||||
{
|
||||
type = mxmlGetType(mxml_node);
|
||||
// Consider the first element to be found the root element of the
|
||||
// document. Having multiple roots isn't a valid XML document
|
||||
// anyway
|
||||
if (type == MXML_TYPE_ELEMENT) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (mxml_node == NULL) {
|
||||
return CORE_PROPERTY_RESULT_NOT_FOUND;
|
||||
}
|
||||
|
||||
node->property = property;
|
||||
// No difference for property vs. property_node
|
||||
node->node = mxml_node;
|
||||
|
||||
return CORE_PROPERTY_RESULT_SUCCESS;
|
||||
}
|
||||
|
||||
static core_property_result_t _core_property_mxml_other_node_insert(
|
||||
core_property_t *property_, const core_property_node_t *node_)
|
||||
{
|
||||
core_property_mxml_internal_property_t *property;
|
||||
core_property_mxml_internal_property_node_t *node;
|
||||
|
||||
char *str_copy;
|
||||
mxml_node_t *node_cloned;
|
||||
|
||||
property = (core_property_mxml_internal_property_t *) property_;
|
||||
node = (core_property_mxml_internal_property_node_t *) node_;
|
||||
|
||||
// Ensure actual cloning by storing and loading this
|
||||
// Just "adding it" to the other tree with mxml creates a reference only
|
||||
|
||||
str_copy = mxmlSaveAllocString(node->node, NULL);
|
||||
|
||||
if (str_copy == NULL) {
|
||||
return CORE_PROPERTY_RESULT_ERROR_READ;
|
||||
}
|
||||
|
||||
node_cloned = mxmlLoadString(NULL, NULL, str_copy);
|
||||
|
||||
if (node_cloned == NULL) {
|
||||
return CORE_PROPERTY_RESULT_ERROR_WRITE;
|
||||
}
|
||||
|
||||
// Hook the new node into the existing tree
|
||||
|
||||
mxmlAdd(property->document, MXML_ADD_AFTER, NULL, node_cloned);
|
||||
|
||||
return CORE_PROPERTY_NODE_RESULT_SUCCESS;
|
||||
}
|
||||
|
||||
static void _core_property_mxml_free(core_property_t **property_)
|
||||
{
|
||||
core_property_mxml_internal_property_t *property;
|
||||
|
||||
property = (core_property_mxml_internal_property_t *) (*property_);
|
||||
|
||||
mxmlDelete(property->document);
|
||||
|
||||
free(*property_);
|
||||
*property_ = NULL;
|
||||
}
|
||||
|
||||
static void _core_property_mxml_core_api_get(core_property_api_t *api)
|
||||
{
|
||||
log_assert(api);
|
||||
|
||||
api->version = 1;
|
||||
|
||||
api->v1.create = _core_property_mxml_create;
|
||||
api->v1.file_load = _core_property_mxml_file_load;
|
||||
api->v1.str_load = _core_property_mxml_str_load;
|
||||
api->v1.size = _core_property_mxml_size;
|
||||
api->v1.clone = _core_property_mxml_clone;
|
||||
api->v1.root_node_get = _core_property_mxml_root_node_get;
|
||||
api->v1.other_node_insert = _core_property_mxml_other_node_insert;
|
||||
api->v1.free = _core_property_mxml_free;
|
||||
}
|
||||
|
||||
void core_property_mxml_core_api_set()
|
||||
{
|
||||
core_property_api_t api;
|
||||
|
||||
_core_property_mxml_core_api_get(&api);
|
||||
core_property_api_set(&api);
|
||||
}
|
||||
8
src/main/core/property-mxml.h
Normal file
8
src/main/core/property-mxml.h
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
#ifndef CORE_PROPERTY_MXML_H
|
||||
#define CORE_PROPERTY_MXML_H
|
||||
|
||||
#include "main/core/property.h"
|
||||
|
||||
void core_property_mxml_core_api_set();
|
||||
|
||||
#endif
|
||||
1086
src/main/core/property-node-mxml.c
Normal file
1086
src/main/core/property-node-mxml.c
Normal file
File diff suppressed because it is too large
Load Diff
10
src/main/core/property-node-mxml.h
Normal file
10
src/main/core/property-node-mxml.h
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
#ifndef CORE_PROPERTY_NODE_MXML_H
|
||||
#define CORE_PROPERTY_NODE_MXML_H
|
||||
|
||||
#include "main/core/property-node.h"
|
||||
|
||||
void core_property_node_mxml_core_api_get(core_property_node_api_t *api);
|
||||
|
||||
void core_property_node_mxml_core_api_set();
|
||||
|
||||
#endif
|
||||
|
|
@ -117,6 +117,12 @@ const char *core_property_node_result_to_str(core_property_node_result_t result)
|
|||
return "Internal";
|
||||
case CORE_PROPERTY_NODE_RESULT_NODE_NOT_FOUND:
|
||||
return "Node not found";
|
||||
case CORE_PROPERTY_NODE_RESULT_INVALID_NODE_TYPE:
|
||||
return "Invalid node type";
|
||||
case CORE_PROPERTY_NODE_RESULT_INVALID_NODE_STRUCTURE:
|
||||
return "Invalid node structure";
|
||||
case CORE_PROPERTY_NODE_RESULT_INVALID_NODE_DATA:
|
||||
return "Invalid node data";
|
||||
default:
|
||||
return "Undefined error";
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@
|
|||
#include "main/core/property.h"
|
||||
|
||||
#define CORE_PROPERTY_NODE_RESULT_IS_ERROR(x) \
|
||||
(x > CORE_PROPERTY_NODE_RESULT_SUCCESS)
|
||||
(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?
|
||||
|
|
@ -33,6 +33,9 @@ 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_INVALID_NODE_TYPE = 3,
|
||||
CORE_PROPERTY_NODE_RESULT_INVALID_NODE_STRUCTURE = 4,
|
||||
CORE_PROPERTY_NODE_RESULT_INVALID_NODE_DATA = 5,
|
||||
} core_property_node_result_t;
|
||||
|
||||
typedef core_property_node_result_t (*core_property_node_name_get_t)(
|
||||
|
|
|
|||
|
|
@ -88,6 +88,8 @@ const char *core_property_result_to_str(core_property_result_t result)
|
|||
return "Permissions";
|
||||
case CORE_PROPERTY_RESULT_ERROR_READ:
|
||||
return "Read error";
|
||||
case CORE_PROPERTY_RESULT_ERROR_WRITE:
|
||||
return "Write error";
|
||||
default:
|
||||
return "Undefined error";
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,7 +5,8 @@
|
|||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "api/core/log.h"
|
||||
#define CORE_PROPERTY_RESULT_IS_ERROR(x) \
|
||||
(x != CORE_PROPERTY_RESULT_SUCCESS)
|
||||
|
||||
// Macro to allow inlining of the caller function and line numbers
|
||||
// to make debugging easier
|
||||
|
|
@ -25,6 +26,7 @@ typedef struct core_property_node {
|
|||
// Have size known, but not contents, to allow for stack allocations
|
||||
void *v1;
|
||||
void *v2;
|
||||
void *v3;
|
||||
} core_property_node_t;
|
||||
|
||||
typedef enum core_property_result {
|
||||
|
|
@ -34,6 +36,7 @@ typedef enum core_property_result {
|
|||
CORE_PROPERTY_RESULT_NOT_FOUND = 3,
|
||||
CORE_PROPERTY_RESULT_ERROR_PERMISSIONS = 4,
|
||||
CORE_PROPERTY_RESULT_ERROR_READ = 5,
|
||||
CORE_PROPERTY_RESULT_ERROR_WRITE = 6,
|
||||
} core_property_result_t;
|
||||
|
||||
typedef core_property_result_t (*core_property_create_t)(
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ libs_extiotest := \
|
|||
core \
|
||||
util \
|
||||
iface-core \
|
||||
mxml \
|
||||
|
||||
src_extiotest := \
|
||||
main.c \
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ libs_iidxhook1 := \
|
|||
iface-io \
|
||||
iface-core \
|
||||
util \
|
||||
mxml \
|
||||
|
||||
src_iidxhook1 := \
|
||||
config-iidxhook1.c \
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ libs_iidxhook2 := \
|
|||
iface-core \
|
||||
module \
|
||||
util \
|
||||
mxml \
|
||||
|
||||
src_iidxhook2 := \
|
||||
config-iidxhook2.c \
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@ libs_iidxhook3 := \
|
|||
iface-core \
|
||||
module \
|
||||
util \
|
||||
mxml \
|
||||
|
||||
src_iidxhook3 := \
|
||||
avs-boot.c \
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@ libs_iidxhook4-cn := \
|
|||
iface-core \
|
||||
module \
|
||||
util \
|
||||
mxml \
|
||||
|
||||
src_iidxhook4-cn := \
|
||||
avs-boot.c \
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@ libs_iidxhook4 := \
|
|||
iface-core \
|
||||
module \
|
||||
util \
|
||||
mxml \
|
||||
|
||||
src_iidxhook4 := \
|
||||
dllmain.c \
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@ libs_iidxhook5-cn := \
|
|||
iface-core \
|
||||
module \
|
||||
util \
|
||||
mxml \
|
||||
|
||||
src_iidxhook5-cn := \
|
||||
avs-boot.c \
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@ libs_iidxhook5 := \
|
|||
iface-core \
|
||||
module \
|
||||
util \
|
||||
mxml \
|
||||
|
||||
src_iidxhook5 := \
|
||||
dllmain.c \
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ libs_inject := \
|
|||
util \
|
||||
dwarfstack \
|
||||
iface-core \
|
||||
mxml \
|
||||
|
||||
src_inject := \
|
||||
main.c \
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user