Add Toml support using toml++ and custom preprocessor macros
Some checks failed
buildbot/IOCore-macos-builder Build done.
Some checks failed
buildbot/IOCore-macos-builder Build done.
This commit is contained in:
parent
98e672042d
commit
a0a0df6f19
10
.gitignore
vendored
10
.gitignore
vendored
@ -132,10 +132,14 @@ Thumbs.db
|
||||
venv/
|
||||
env/
|
||||
|
||||
*.bak
|
||||
|
||||
.cache/
|
||||
# Build files
|
||||
CMakeCache.txt
|
||||
compile_commands.json
|
||||
vim-debug
|
||||
CMakeFiles/*
|
||||
*.bak
|
||||
.cache/
|
||||
docs/
|
||||
.vim/*
|
||||
build/*
|
||||
.cmake/*
|
||||
|
@ -1,4 +1,3 @@
|
||||
|
||||
" editorconfig/local.vimrc
|
||||
" Copyright © 2023-2024 Saul D. Beniquez @{
|
||||
"
|
||||
@ -24,7 +23,7 @@
|
||||
" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
" POSSIBILITY OF SUCH DAMAGE. @}
|
||||
|
||||
let s:build_dir = 'debug'
|
||||
let s:build_dir = 'build/Debug'
|
||||
let s:build_cores = 6
|
||||
let s:make_args = '-C '. s:build_dir . ' -j ' . s:build_cores . ' all'
|
||||
|
||||
|
43
include/util/macros.hpp
Normal file
43
include/util/macros.hpp
Normal file
@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Copyright © 2024 Saul D. Beniquez
|
||||
* License: Mozilla Public License v. 2.0
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public License,
|
||||
* v.2.0. If a copy of the MPL was not distributed with this file, You can
|
||||
* obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
// clang-format off
|
||||
//
|
||||
#pragma once
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#define IOCORE_EXPAND(x) x
|
||||
|
||||
#define IOCORE_FOREACH_1(func, param) func(param)
|
||||
#define IOCORE_FOREACH_2(func, param, ...) func(param); IOCORE_EXPAND(IOCORE_FOREACH_1(func, __VA_ARGS__))
|
||||
#define IOCORE_FOREACH_3(func, param, ...) func(param); IOCORE_EXPAND(IOCORE_FOREACH_2(func, __VA_ARGS__))
|
||||
#define IOCORE_FOREACH_4(func, param, ...) func(param); IOCORE_EXPAND(IOCORE_FOREACH_3(func, __VA_ARGS__))
|
||||
#define IOCORE_FOREACH_5(func, param, ...) func(param); IOCORE_EXPAND(IOCORE_FOREACH_4(func, __VA_ARGS__))
|
||||
#define IOCORE_FOREACH_6(func, param, ...) func(param); IOCORE_EXPAND(IOCORE_FOREACH_5(func, __VA_ARGS__))
|
||||
#define IOCORE_FOREACH_7(func, param, ...) func(param); IOCORE_EXPAND(IOCORE_FOREACH_6(func, __VA_ARGS__))
|
||||
#define IOCORE_FOREACH_8(func, param, ...) func(param); IOCORE_EXPAND(IOCORE_FOREACH_7(func, __VA_ARGS__))
|
||||
#define IOCORE_FOREACH_9(func, param, ...) func(param); IOCORE_EXPAND(IOCORE_FOREACH_8(func, __VA_ARGS__))
|
||||
#define IOCORE_FOREACH_10(func, param, ...) func(param); IOCORE_EXPAND(IOCORE_FOREACH_9(func, __VA_ARGS__))
|
||||
#define IOCORE_FOREACH_11(func, param, ...) func(param); IOCORE_EXPAND(IOCORE_FOREACH_10(func, __VA_ARGS__))
|
||||
#define IOCORE_FOREACH_12(func, param, ...) func(param); IOCORE_EXPAND(IOCORE_FOREACH_11(func, __VA_ARGS__))
|
||||
#define IOCORE_FOREACH_13(func, param, ...) func(param); IOCORE_EXPAND(IOCORE_FOREACH_12(func, __VA_ARGS__))
|
||||
#define IOCORE_FOREACH_14(func, param, ...) func(param); IOCORE_EXPAND(IOCORE_FOREACH_13(func, __VA_ARGS__))
|
||||
#define IOCORE_FOREACH_15(func, param, ...) func(param); IOCORE_EXPAND(IOCORE_FOREACH_14(func, __VA_ARGS__))
|
||||
#define IOCORE_FOREACH_16(func, param, ...) func(param); IOCORE_EXPAND(IOCORE_FOREACH_15(func, __VA_ARGS__))
|
||||
#define IOCORE_FOREACH_17(func, param, ...) func(param); IOCORE_EXPAND(IOCORE_FOREACH_16(func, __VA_ARGS__))
|
||||
#define IOCORE_FOREACH_18(func, param, ...) func(param); IOCORE_EXPAND(IOCORE_FOREACH_17(func, __VA_ARGS__))
|
||||
#define IOCORE_FOREACH_19(func, param, ...) func(param); IOCORE_EXPAND(IOCORE_FOREACH_18(func, __VA_ARGS__))
|
||||
#define IOCORE_FOREACH_20(func, param, ...) func(param); IOCORE_EXPAND(IOCORE_FOREACH_19(func, __VA_ARGS__))
|
||||
#define IOCORE_FOREACH_21(func, param, ...) func(param); IOCORE_EXPAND(IOCORE_FOREACH_20(func, __VA_ARGS__))
|
||||
|
||||
#define GET_FOREACH_MACRO(_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,_21,NAME,...) NAME
|
||||
#define IOCORE_FOREACH(func, ...) IOCORE_EXPAND(GET_FOREACH_MACRO(__VA_ARGS__, IOCORE_FOREACH_21, IOCORE_FOREACH_20, IOCORE_FOREACH_19, IOCORE_FOREACH_18, IOCORE_FOREACH_17, IOCORE_FOREACH_16, IOCORE_FOREACH_15, IOCORE_FOREACH_14, IOCORE_FOREACH_13, IOCORE_FOREACH_12, IOCORE_FOREACH_11, IOCORE_FOREACH_10, IOCORE_FOREACH_9, IOCORE_FOREACH_8, IOCORE_FOREACH_7, IOCORE_FOREACH_6, IOCORE_FOREACH_5, IOCORE_FOREACH_4, IOCORE_FOREACH_3, IOCORE_FOREACH_2, IOCORE_FOREACH_1)(func, __VA_ARGS__))
|
||||
|
||||
// clang-format off
|
||||
// vim: set foldmethod=syntax foldminlines=10 textwidth=80 ts=8 sts=0 sw=8 noexpandtab ft=cpp.doxygen :
|
90
include/util/toml.hpp
Normal file
90
include/util/toml.hpp
Normal file
@ -0,0 +1,90 @@
|
||||
/* toml.hpp
|
||||
* Copyright © 2024 Saul D. Beniquez
|
||||
* License: Mozilla Public License v. 2.0
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public License,
|
||||
* v.2.0. If a copy of the MPL was not distributed with this file, You can
|
||||
* obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <initializer_list>
|
||||
#include <utility>
|
||||
|
||||
#include <toml++/toml.hpp>
|
||||
|
||||
#include "../Exception.hpp"
|
||||
#include "./macros.hpp"
|
||||
|
||||
#define IOCORE_TOML_TO(field) tbl.insert_or_assign(#field, obj.field);
|
||||
#define IOCORE_TOML_FROM(field) \
|
||||
if (!tbl.contains(#field)) { \
|
||||
throw IOCore::Toml::TomlException("Missing field " #field); \
|
||||
} \
|
||||
\
|
||||
obj.field = tbl[#field].value<decltype(obj.field)>().value();
|
||||
|
||||
#define IOCORE_INIT_METADATA(T) \
|
||||
auto metadata = toml::table(); \
|
||||
metadata.insert_or_assign("type", #T); \
|
||||
tbl.insert_or_assign("General", metadata);
|
||||
|
||||
#define IOCORE_TOML_SERIALIZABLE(T, ...) \
|
||||
const char* _class_name = #T; \
|
||||
friend void to_toml_table(toml::table& tbl, const T& obj) \
|
||||
{ \
|
||||
IOCORE_INIT_METADATA(T) \
|
||||
IOCORE_FOREACH(IOCORE_TOML_TO, __VA_ARGS__) \
|
||||
} \
|
||||
friend void from_toml_table(const toml::table& table, T& obj) \
|
||||
{ \
|
||||
auto tbl = table; \
|
||||
tbl.erase("General"); \
|
||||
IOCORE_FOREACH(IOCORE_TOML_FROM, __VA_ARGS__) \
|
||||
}
|
||||
|
||||
namespace IOCore::Toml {
|
||||
|
||||
struct TomlException : public Exception {
|
||||
|
||||
TomlException()
|
||||
: Exception("TOML Serialization/Deseralization Exception")
|
||||
{
|
||||
}
|
||||
explicit TomlException(const std::string& message) : Exception(message)
|
||||
{
|
||||
}
|
||||
~TomlException() override = default;
|
||||
};
|
||||
|
||||
struct Table : public toml::table {
|
||||
Table() = default;
|
||||
Table(const toml::table& tbl) : toml::table(tbl) {}
|
||||
Table(const Table& tbl) : toml::table(tbl) {}
|
||||
Table(Table&& tbl) noexcept : toml::table(std::move(tbl)) {}
|
||||
|
||||
template<typename T>
|
||||
Table(const T& obj)
|
||||
{
|
||||
to_toml_table(*this, obj);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
auto operator=(const T& obj) -> Table&
|
||||
{
|
||||
to_toml_table(*this, obj);
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
auto operator=(T&& obj) -> Table&
|
||||
{
|
||||
to_toml_table(*this, obj);
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// clang-format off
|
||||
// vim: set foldmethod=marker foldmarker=@{,@} foldminlines=10 textwidth=80 ts=8 sts=0 sw=8 noexpandtab ft=cpp.doxygen :
|
@ -4,6 +4,8 @@ add_executable(test-runner
|
||||
Application.test.cpp
|
||||
FileResource.test.cpp
|
||||
Exception.test.cpp
|
||||
Util.macros.test.cpp
|
||||
Util.toml.test.cpp
|
||||
)
|
||||
|
||||
target_include_directories(test-runner PRIVATE
|
||||
|
33
tests/Util.macros.test.cpp
Normal file
33
tests/Util.macros.test.cpp
Normal file
@ -0,0 +1,33 @@
|
||||
/* Util.test.cpp
|
||||
* Copyright © 2024 Saul D. Beniquez
|
||||
* License: Mozilla Public License v. 2.0
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public License,
|
||||
* v.2.0. If a copy of the MPL was not distributed with this file, You can
|
||||
* obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
#include "test-utils/common.hpp"
|
||||
|
||||
#include "../include/util/macros.hpp"
|
||||
#include "../include/util/toml.hpp"
|
||||
|
||||
#include <sstream>
|
||||
|
||||
#define PRINT_MACRO(x) buffer << #x << ": " << x << ", " << std::flush;
|
||||
|
||||
BEGIN_TEST_SUITE("Util.Macros")
|
||||
{
|
||||
TEST_CASE("IOCORE_FOREACH Macro works")
|
||||
{
|
||||
std::stringstream buffer;
|
||||
int field1 = 10;
|
||||
int field2 = 20;
|
||||
|
||||
IOCORE_FOREACH(PRINT_MACRO, field1, field2)
|
||||
REQUIRE(buffer.str() == "field1: 10, field2: 20, ");
|
||||
}
|
||||
}
|
||||
|
||||
// clang-format off
|
||||
// vim: set foldmethod=syntax foldminlines=10 textwidth=80 ts=8 sts=0 sw=8 noexpandtab ft=cpp.doxygen :
|
75
tests/Util.toml.test.cpp
Normal file
75
tests/Util.toml.test.cpp
Normal file
@ -0,0 +1,75 @@
|
||||
/* Util.toml.test.cpp
|
||||
* Copyright © 2024 Saul D. Beniquez
|
||||
* License: Mozilla Public License v. 2.0
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public License,
|
||||
* v.2.0. If a copy of the MPL was not distributed with this file, You can
|
||||
* obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
#include "test-utils/common.hpp"
|
||||
|
||||
#include "../include/util/toml.hpp"
|
||||
|
||||
BEGIN_TEST_SUITE("Util.Toml")
|
||||
{
|
||||
struct TestStruct {
|
||||
int field1;
|
||||
int field2;
|
||||
|
||||
friend void
|
||||
to_toml_table(toml::table& tbl, const TestStruct& obj)
|
||||
{
|
||||
IOCORE_TOML_TO(field1);
|
||||
IOCORE_TOML_TO(field2);
|
||||
}
|
||||
};
|
||||
|
||||
struct SerializableStruct {
|
||||
int field1;
|
||||
int field2;
|
||||
|
||||
IOCORE_TOML_SERIALIZABLE(SerializableStruct, field1, field2);
|
||||
};
|
||||
|
||||
TEST_CASE("IOCORE_TOML_TO Macro works")
|
||||
{
|
||||
|
||||
toml::table table;
|
||||
TestStruct data;
|
||||
|
||||
to_toml_table(table, data);
|
||||
REQUIRE(table.size() == 2);
|
||||
}
|
||||
TEST_CASE("IOCORE_TOML_SERIALIZABLE Macro works")
|
||||
{
|
||||
|
||||
toml::table table;
|
||||
SerializableStruct data = { 11, 22 };
|
||||
SerializableStruct newdest;
|
||||
|
||||
to_toml_table(table, data);
|
||||
from_toml_table(table, newdest);
|
||||
|
||||
REQUIRE(table.size() == 3);
|
||||
|
||||
REQUIRE(table["field1"].value<int>() == 11);
|
||||
REQUIRE(table["field2"].value<int>() == 22);
|
||||
|
||||
REQUIRE(newdest.field1 == data.field1);
|
||||
REQUIRE(newdest.field2 == data.field2);
|
||||
}
|
||||
TEST_CASE("Toml::Table class construction and basic operators")
|
||||
{
|
||||
IOCore::Toml::Table table = SerializableStruct{ 11, 22 };
|
||||
|
||||
REQUIRE(table.size() == 3);
|
||||
REQUIRE(
|
||||
table["General"]["type"].value<std::string>().value() ==
|
||||
"SerializableStruct"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// clang-format off
|
||||
// vim: set foldmethod=syntax foldminlines=10 textwidth=80 ts=8 sts=0 sw=8 noexpandtab ft=cpp.doxygen :
|
Loading…
Reference in New Issue
Block a user