From 22a2ccc0393f0d4a0abca3875ede38c1e1f1c901 Mon Sep 17 00:00:00 2001 From: George Evmenov Date: Wed, 2 Oct 2024 14:32:48 +0300 Subject: [PATCH 01/12] remove duplicate CMake code in REFLECTCPP_USE_BUNDLED_DEPENDENCIES --- CMakeLists.txt | 58 +++++++++++++++++++++++--------------------------- 1 file changed, 27 insertions(+), 31 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 3d4a6882..b642c24a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -40,50 +40,46 @@ project(reflectcpp LANGUAGES CXX) set(CMAKE_CXX_STANDARD 20) -if(REFLECTCPP_USE_BUNDLED_DEPENDENCIES) - if (REFLECTCPP_BUILD_SHARED) - add_library(reflectcpp SHARED) - else() - add_library(reflectcpp STATIC) - endif() +if (REFLECTCPP_BUILD_SHARED) + add_library(reflectcpp SHARED) +else() + add_library(reflectcpp STATIC) +endif() - target_sources(reflectcpp PRIVATE src/reflectcpp.cpp src/yyjson.c) - set_source_files_properties(src/yyjson.c PROPERTIES LANGUAGE CXX) +if (MSVC) + target_compile_options(reflectcpp PRIVATE $<$:-Wall>) +else() + target_compile_options(reflectcpp PRIVATE $<$:-Wall -Wextra>) +endif() - target_compile_features(reflectcpp PUBLIC cxx_std_20) +target_compile_features(reflectcpp PUBLIC cxx_std_20) - if (MSVC) - target_compile_options(reflectcpp PRIVATE $<$:-Wall>) - else() - target_compile_options(reflectcpp PRIVATE $<$:-Wall -Wextra>) - endif() +set(REFLECT_CPP_SOURCES + src/reflectcpp.cpp +) - target_include_directories( - reflectcpp PUBLIC - $ - $ - $) -else() - if (REFLECTCPP_BUILD_SHARED) - add_library(reflectcpp SHARED) - else() - add_library(reflectcpp STATIC) - endif() +target_include_directories( + reflectcpp PUBLIC + $ + $) - target_sources(reflectcpp PRIVATE src/reflectcpp.cpp) +if(REFLECTCPP_USE_BUNDLED_DEPENDENCIES) + list(APPEND REFLECT_CPP_SOURCES + src/yyjson.c + ) + set_source_files_properties(src/yyjson.c PROPERTIES LANGUAGE CXX) target_include_directories( reflectcpp PUBLIC - $ - $) - - target_compile_features(reflectcpp PUBLIC cxx_std_20) - + $) +else() find_package(ctre CONFIG REQUIRED) find_package(yyjson CONFIG REQUIRED) target_link_libraries(reflectcpp INTERFACE ctre::ctre yyjson::yyjson) endif() +target_sources(reflectcpp PRIVATE ${REFLECT_CPP_SOURCES}) + set_target_properties(reflectcpp PROPERTIES LINKER_LANGUAGE CXX) if (REFLECTCPP_BSON) From f67432e51bcf338f90549e0596936ef8af2dc162 Mon Sep 17 00:00:00 2001 From: George Evmenov Date: Wed, 2 Oct 2024 14:33:00 +0300 Subject: [PATCH 02/12] split reflectcpp.cpp file into multiple source files, without changing build --- src/Generic.cpp | 114 ++++++++++++++ src/Type.cpp | 40 +++++ src/reflectcpp.cpp | 373 +-------------------------------------------- src/to_schema.cpp | 279 +++++++++++++++++++++++++++++++++ 4 files changed, 441 insertions(+), 365 deletions(-) create mode 100644 src/Generic.cpp create mode 100644 src/Type.cpp create mode 100644 src/to_schema.cpp diff --git a/src/Generic.cpp b/src/Generic.cpp new file mode 100644 index 00000000..cdc78d54 --- /dev/null +++ b/src/Generic.cpp @@ -0,0 +1,114 @@ +/* + +MIT License + +Copyright (c) 2023-2024 Code17 GmbH + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +*/ + +#include "rfl/Generic.hpp" + +namespace rfl { + +Generic::Generic() : value_(false) {} + +Generic::Generic(Generic&& _other) noexcept = default; + +Generic::Generic(const Generic& _other) = default; + +Generic::Generic(const ReflectionType& _value) : value_(_value) {} + +Generic::Generic(ReflectionType&& _value) noexcept + : value_(std::move(_value)) {} + +Generic::~Generic() = default; + +Generic& Generic::operator=(const ReflectionType& _value) { + value_ = _value; + return *this; +} + +Generic& Generic::operator=(ReflectionType&& _value) noexcept { + value_ = std::move(_value); + return *this; +} + +Generic& Generic::operator=(const Generic& _other) = default; + +Generic& Generic::operator=(Generic&& _other) = default; + +Result Generic::to_array() const noexcept { + if (const auto* ptr = std::get_if(&value_)) { + return *ptr; + } else { + return Error( + "rfl::Generic: Could not cast the underlying value to an " + "rfl::Generic::Array."); + } +} + +Result Generic::to_bool() const noexcept { + if (const auto* ptr = std::get_if(&value_)) { + return *ptr; + } else { + return Error( + "rfl::Generic: Could not cast the underlying value to a boolean."); + } +} + +Result Generic::to_double() const noexcept { + if (const auto* ptr = std::get_if(&value_)) { + return *ptr; + } else { + return Error( + "rfl::Generic: Could not cast the underlying value to a double."); + } +} + +Result Generic::to_int() const noexcept { + if (const auto* ptr = std::get_if(&value_)) { + return *ptr; + } else { + return Error( + "rfl::Generic: Could not cast the underlying value to an integer."); + } +} + +Result Generic::to_object() const noexcept { + if (const auto* ptr = std::get_if(&value_)) { + return *ptr; + } else { + return Error( + "rfl::Generic: Could not cast the underlying value to an " + "rfl::Generic::Object."); + } +} + +Result Generic::to_string() const noexcept { + if (const auto* ptr = std::get_if(&value_)) { + return *ptr; + } else { + return Error( + "rfl::Generic: Could not cast the underlying value to a string."); + } +} + +} // namespace rfl diff --git a/src/Type.cpp b/src/Type.cpp new file mode 100644 index 00000000..d05da4ea --- /dev/null +++ b/src/Type.cpp @@ -0,0 +1,40 @@ +/* + +MIT License + +Copyright (c) 2023-2024 Code17 GmbH + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +*/ + +#include "rfl/parsing/schema/Type.hpp" + +namespace rfl::parsing::schema { + +/// Requires a lot of template instantiation, so we do not want this to be +/// inlined. + +Type::Type() : variant_() {} + +Type::Type(const VariantType& _variant) : variant_(_variant) {} + +Type::~Type() = default; + +} // namespace rfl::parsing::schema diff --git a/src/reflectcpp.cpp b/src/reflectcpp.cpp index b6adc401..6071dd43 100644 --- a/src/reflectcpp.cpp +++ b/src/reflectcpp.cpp @@ -24,368 +24,11 @@ SOFTWARE. */ -// ---------------------------------------------------------------------------- - -#include "rfl/Generic.hpp" - -namespace rfl { - -Generic::Generic() : value_(false) {} - -Generic::Generic(Generic&& _other) noexcept = default; - -Generic::Generic(const Generic& _other) = default; - -Generic::Generic(const ReflectionType& _value) : value_(_value) {} - -Generic::Generic(ReflectionType&& _value) noexcept - : value_(std::move(_value)) {} - -Generic::~Generic() = default; - -Generic& Generic::operator=(const ReflectionType& _value) { - value_ = _value; - return *this; -} - -Generic& Generic::operator=(ReflectionType&& _value) noexcept { - value_ = std::move(_value); - return *this; -} - -Generic& Generic::operator=(const Generic& _other) = default; - -Generic& Generic::operator=(Generic&& _other) = default; - -Result Generic::to_array() const noexcept { - if (const auto* ptr = std::get_if(&value_)) { - return *ptr; - } else { - return Error( - "rfl::Generic: Could not cast the underlying value to an " - "rfl::Generic::Array."); - } -} - -Result Generic::to_bool() const noexcept { - if (const auto* ptr = std::get_if(&value_)) { - return *ptr; - } else { - return Error( - "rfl::Generic: Could not cast the underlying value to a boolean."); - } -} - -Result Generic::to_double() const noexcept { - if (const auto* ptr = std::get_if(&value_)) { - return *ptr; - } else { - return Error( - "rfl::Generic: Could not cast the underlying value to a double."); - } -} - -Result Generic::to_int() const noexcept { - if (const auto* ptr = std::get_if(&value_)) { - return *ptr; - } else { - return Error( - "rfl::Generic: Could not cast the underlying value to an integer."); - } -} - -Result Generic::to_object() const noexcept { - if (const auto* ptr = std::get_if(&value_)) { - return *ptr; - } else { - return Error( - "rfl::Generic: Could not cast the underlying value to an " - "rfl::Generic::Object."); - } -} - -Result Generic::to_string() const noexcept { - if (const auto* ptr = std::get_if(&value_)) { - return *ptr; - } else { - return Error( - "rfl::Generic: Could not cast the underlying value to a string."); - } -} - -} // namespace rfl - -// ---------------------------------------------------------------------------- - -#include "rfl/json/to_schema.hpp" - -namespace rfl::json { - -schema::Type type_to_json_schema_type(const parsing::schema::Type& _type); - -bool is_optional(const parsing::schema::Type& _t) { - const auto handle = [](const auto& _v) -> bool { - using T = std::remove_cvref_t; - return std::is_same(); - }; - return rfl::visit(handle, _t.variant_); -} - -std::string numeric_type_to_string(const parsing::schema::Type& _type) { - const auto handle_variant = [](const auto& _t) -> std::string { - using T = std::remove_cvref_t; - using Type = parsing::schema::Type; - if constexpr (std::is_same() || - std::is_same() || - std::is_same() || - std::is_same() || - std::is_same()) { - return schema::Type::Integer{}.type.str(); - } else { - return schema::Type::Number{}.type.str(); - } - }; - return rfl::visit(handle_variant, _type.variant_); -} - -schema::Type handle_validation_type( - const parsing::schema::Type& _type, - const parsing::schema::ValidationType& _validation_type) { - auto handle_variant = [&](const auto& _v) -> schema::Type { - using T = std::remove_cvref_t; - using ValidationType = parsing::schema::ValidationType; - if constexpr (std::is_same()) { - auto all_of = std::vector(); - for (const auto& t : _v.types_) { - all_of.emplace_back(handle_validation_type(_type, t)); - } - return schema::Type{.value = schema::Type::AllOf{.allOf = all_of}}; - - } else if constexpr (std::is_same()) { - auto any_of = std::vector(); - for (const auto& t : _v.types_) { - any_of.emplace_back(handle_validation_type(_type, t)); - } - return schema::Type{.value = schema::Type::AnyOf{.anyOf = any_of}}; - - } else if constexpr (std::is_same()) { - auto one_of = std::vector(); - for (const auto& t : _v.types_) { - one_of.emplace_back(handle_validation_type(_type, t)); - } - return schema::Type{.value = schema::Type::OneOf{.oneOf = one_of}}; - - } else if constexpr (std::is_same()) { - return schema::Type{.value = schema::Type::Regex{.pattern = _v.pattern_}}; - - } else if constexpr (std::is_same()) { - auto t = type_to_json_schema_type(_type); - const auto to_size = [](const auto _v) { - return static_cast(_v); - }; - auto handle_size_variant = [&](auto& _t, const auto& _size_limit) { - using U = std::remove_cvref_t; - using V = std::remove_cvref_t; - if constexpr (std::is_same() || - std::is_same()) { - if constexpr (std::is_same()) { - _t.minSize = _size_limit.value_.visit(to_size); - return t; - - } else if constexpr (std::is_same()) { - _t.maxSize = _size_limit.value_.visit(to_size); - return t; - - } else if constexpr (std::is_same()) { - _t.minSize = _size_limit.value_.visit(to_size); - _t.maxSize = _size_limit.value_.visit(to_size); - return t; - - } else if constexpr (std::is_same() || - std::is_same()) { - V v; - for (const auto& limiter : _size_limit.types_) { - v.types_.push_back(ValidationType{ValidationType::Size{ - .size_limit_ = rfl::Ref::make(limiter)}}); - } - return handle_validation_type(_type, ValidationType{.variant_ = v}); - } - } - return t; - }; - - return rfl::visit(handle_size_variant, t.value, _v.size_limit_->variant_); - - } else if constexpr (std::is_same()) { - return schema::Type{.value = schema::Type::ExclusiveMaximum{ - .exclusiveMaximum = _v.value_, - .type = numeric_type_to_string(_type)}}; - - } else if constexpr (std::is_same()) { - return schema::Type{.value = schema::Type::ExclusiveMinimum{ - .exclusiveMinimum = _v.value_, - .type = numeric_type_to_string(_type)}}; - - } else if constexpr (std::is_same()) { - return schema::Type{ - .value = schema::Type::Maximum{ - .maximum = _v.value_, .type = numeric_type_to_string(_type)}}; - - } else if constexpr (std::is_same()) { - return schema::Type{ - .value = schema::Type::Minimum{ - .minimum = _v.value_, .type = numeric_type_to_string(_type)}}; - - } else if constexpr (std::is_same()) { - const auto maximum = schema::Type{ - .value = schema::Type::Maximum{ - .maximum = _v.value_, .type = numeric_type_to_string(_type)}}; - const auto minimum = schema::Type{ - .value = schema::Type::Minimum{ - .minimum = _v.value_, .type = numeric_type_to_string(_type)}}; - return schema::Type{.value = - schema::Type::AllOf{.allOf = {maximum, minimum}}}; - - } else if constexpr (std::is_same()) { - const auto excl_maximum = - schema::Type{.value = schema::Type::ExclusiveMaximum{ - .exclusiveMaximum = _v.value_, - .type = numeric_type_to_string(_type)}}; - const auto excl_minimum = - schema::Type{.value = schema::Type::ExclusiveMinimum{ - .exclusiveMinimum = _v.value_, - .type = numeric_type_to_string(_type)}}; - return schema::Type{ - .value = schema::Type::AnyOf{.anyOf = {excl_maximum, excl_minimum}}}; - - } else { - static_assert(rfl::always_false_v, "Not all cases were covered."); - } - }; - - return rfl::visit(handle_variant, _validation_type.variant_); -} - -schema::Type type_to_json_schema_type(const parsing::schema::Type& _type) { - auto handle_variant = [](const auto& _t) -> schema::Type { - using T = std::remove_cvref_t; - using Type = parsing::schema::Type; - if constexpr (std::is_same()) { - return schema::Type{.value = schema::Type::Boolean{}}; - - } else if constexpr (std::is_same() || - std::is_same() || - std::is_same() || - std::is_same() || - std::is_same()) { - return schema::Type{.value = schema::Type::Integer{}}; - - } else if constexpr (std::is_same() || - std::is_same()) { - return schema::Type{.value = schema::Type::Number{}}; - - } else if constexpr (std::is_same()) { - return schema::Type{.value = schema::Type::String{}}; - - } else if constexpr (std::is_same()) { - auto any_of = std::vector(); - for (const auto& t : _t.types_) { - any_of.emplace_back(type_to_json_schema_type(t)); - } - return schema::Type{.value = schema::Type::AnyOf{.anyOf = any_of}}; - - } else if constexpr (std::is_same()) { - auto res = type_to_json_schema_type(*_t.type_); - const auto update_prediction = [&](auto _v) -> schema::Type { - _v.description = _t.description_; - return schema::Type{_v}; - }; - return rfl::visit(update_prediction, res.value); - - } else if constexpr (std::is_same()) { - return schema::Type{.value = schema::Type::FixedSizeTypedArray{ - .items = Ref::make( - type_to_json_schema_type(*_t.type_)), - .minItems = _t.size_, - .maxItems = _t.size_}}; - - } else if constexpr (std::is_same()) { - return schema::Type{.value = - schema::Type::StringEnum{.values = _t.values_}}; - - } else if constexpr (std::is_same()) { - auto properties = std::map(); - auto required = std::vector(); - for (const auto& [k, v] : _t.types_) { - properties[k] = type_to_json_schema_type(v); - if (!is_optional(v)) { - required.push_back(k); - } - } - auto additional_properties = - _t.additional_properties_ - ? std::make_shared( - type_to_json_schema_type(*_t.additional_properties_)) - : std::shared_ptr(); - return schema::Type{.value = schema::Type::Object{ - .properties = properties, - .required = required, - .additionalProperties = additional_properties}}; - - } else if constexpr (std::is_same()) { - return schema::Type{.value = schema::Type::AnyOf{ - .anyOf = {type_to_json_schema_type(*_t.type_), - schema::Type{schema::Type::Null{}}}}}; - - } else if constexpr (std::is_same()) { - return schema::Type{ - .value = schema::Type::Reference{.ref = "#/definitions/" + _t.name_}}; - - } else if constexpr (std::is_same()) { - return schema::Type{.value = schema::Type::StringMap{ - .additionalProperties = Ref::make( - type_to_json_schema_type(*_t.value_type_))}}; - - } else if constexpr (std::is_same()) { - auto items = std::vector(); - for (const auto& t : _t.types_) { - items.emplace_back(type_to_json_schema_type(t)); - } - return schema::Type{.value = schema::Type::Tuple{.prefixItems = items}}; - - } else if constexpr (std::is_same()) { - return schema::Type{.value = schema::Type::TypedArray{ - .items = Ref::make( - type_to_json_schema_type(*_t.type_))}}; - - } else if constexpr (std::is_same()) { - return handle_validation_type(*_t.type_, _t.validation_); - - } else { - static_assert(rfl::always_false_v, "Not all cases were covered."); - } - }; - - return rfl::visit(handle_variant, _type.variant_); -} - -} // namespace rfl::json - -// ---------------------------------------------------------------------------- - -#include "rfl/parsing/schema/Type.hpp" - -namespace rfl::parsing::schema { - -/// Requires a lot of template instantiation, so we do not want this to be -/// inlined. - -Type::Type() : variant_() {} - -Type::Type(const VariantType& _variant) : variant_(_variant) {} - -Type::~Type() = default; - -} // namespace rfl::parsing::schema - -// ---------------------------------------------------------------------------- +// This file include all other source files, so that the user of the library +// don't need to add multiple source files into their build. +// Also, this speeds up compile time, compared to multiple separate .cpp files +// compilation. + +#include "Generic.cpp" +#include "to_schema.cpp" +#include "Type.cpp" diff --git a/src/to_schema.cpp b/src/to_schema.cpp new file mode 100644 index 00000000..8b51f472 --- /dev/null +++ b/src/to_schema.cpp @@ -0,0 +1,279 @@ +/* + +MIT License + +Copyright (c) 2023-2024 Code17 GmbH + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +*/ + +#include "rfl/json/to_schema.hpp" + +namespace rfl::json { + +schema::Type type_to_json_schema_type(const parsing::schema::Type& _type); + +bool is_optional(const parsing::schema::Type& _t) { + const auto handle = [](const auto& _v) -> bool { + using T = std::remove_cvref_t; + return std::is_same(); + }; + return rfl::visit(handle, _t.variant_); +} + +std::string numeric_type_to_string(const parsing::schema::Type& _type) { + const auto handle_variant = [](const auto& _t) -> std::string { + using T = std::remove_cvref_t; + using Type = parsing::schema::Type; + if constexpr (std::is_same() || + std::is_same() || + std::is_same() || + std::is_same() || + std::is_same()) { + return schema::Type::Integer{}.type.str(); + } else { + return schema::Type::Number{}.type.str(); + } + }; + return rfl::visit(handle_variant, _type.variant_); +} + +schema::Type handle_validation_type( + const parsing::schema::Type& _type, + const parsing::schema::ValidationType& _validation_type) { + auto handle_variant = [&](const auto& _v) -> schema::Type { + using T = std::remove_cvref_t; + using ValidationType = parsing::schema::ValidationType; + if constexpr (std::is_same()) { + auto all_of = std::vector(); + for (const auto& t : _v.types_) { + all_of.emplace_back(handle_validation_type(_type, t)); + } + return schema::Type{.value = schema::Type::AllOf{.allOf = all_of}}; + + } else if constexpr (std::is_same()) { + auto any_of = std::vector(); + for (const auto& t : _v.types_) { + any_of.emplace_back(handle_validation_type(_type, t)); + } + return schema::Type{.value = schema::Type::AnyOf{.anyOf = any_of}}; + + } else if constexpr (std::is_same()) { + auto one_of = std::vector(); + for (const auto& t : _v.types_) { + one_of.emplace_back(handle_validation_type(_type, t)); + } + return schema::Type{.value = schema::Type::OneOf{.oneOf = one_of}}; + + } else if constexpr (std::is_same()) { + return schema::Type{.value = schema::Type::Regex{.pattern = _v.pattern_}}; + + } else if constexpr (std::is_same()) { + auto t = type_to_json_schema_type(_type); + const auto to_size = [](const auto _v) { + return static_cast(_v); + }; + auto handle_size_variant = [&](auto& _t, const auto& _size_limit) { + using U = std::remove_cvref_t; + using V = std::remove_cvref_t; + if constexpr (std::is_same() || + std::is_same()) { + if constexpr (std::is_same()) { + _t.minSize = _size_limit.value_.visit(to_size); + return t; + + } else if constexpr (std::is_same()) { + _t.maxSize = _size_limit.value_.visit(to_size); + return t; + + } else if constexpr (std::is_same()) { + _t.minSize = _size_limit.value_.visit(to_size); + _t.maxSize = _size_limit.value_.visit(to_size); + return t; + + } else if constexpr (std::is_same() || + std::is_same()) { + V v; + for (const auto& limiter : _size_limit.types_) { + v.types_.push_back(ValidationType{ValidationType::Size{ + .size_limit_ = rfl::Ref::make(limiter)}}); + } + return handle_validation_type(_type, ValidationType{.variant_ = v}); + } + } + return t; + }; + + return rfl::visit(handle_size_variant, t.value, _v.size_limit_->variant_); + + } else if constexpr (std::is_same()) { + return schema::Type{.value = schema::Type::ExclusiveMaximum{ + .exclusiveMaximum = _v.value_, + .type = numeric_type_to_string(_type)}}; + + } else if constexpr (std::is_same()) { + return schema::Type{.value = schema::Type::ExclusiveMinimum{ + .exclusiveMinimum = _v.value_, + .type = numeric_type_to_string(_type)}}; + + } else if constexpr (std::is_same()) { + return schema::Type{ + .value = schema::Type::Maximum{ + .maximum = _v.value_, .type = numeric_type_to_string(_type)}}; + + } else if constexpr (std::is_same()) { + return schema::Type{ + .value = schema::Type::Minimum{ + .minimum = _v.value_, .type = numeric_type_to_string(_type)}}; + + } else if constexpr (std::is_same()) { + const auto maximum = schema::Type{ + .value = schema::Type::Maximum{ + .maximum = _v.value_, .type = numeric_type_to_string(_type)}}; + const auto minimum = schema::Type{ + .value = schema::Type::Minimum{ + .minimum = _v.value_, .type = numeric_type_to_string(_type)}}; + return schema::Type{.value = + schema::Type::AllOf{.allOf = {maximum, minimum}}}; + + } else if constexpr (std::is_same()) { + const auto excl_maximum = + schema::Type{.value = schema::Type::ExclusiveMaximum{ + .exclusiveMaximum = _v.value_, + .type = numeric_type_to_string(_type)}}; + const auto excl_minimum = + schema::Type{.value = schema::Type::ExclusiveMinimum{ + .exclusiveMinimum = _v.value_, + .type = numeric_type_to_string(_type)}}; + return schema::Type{ + .value = schema::Type::AnyOf{.anyOf = {excl_maximum, excl_minimum}}}; + + } else { + static_assert(rfl::always_false_v, "Not all cases were covered."); + } + }; + + return rfl::visit(handle_variant, _validation_type.variant_); +} + +schema::Type type_to_json_schema_type(const parsing::schema::Type& _type) { + auto handle_variant = [](const auto& _t) -> schema::Type { + using T = std::remove_cvref_t; + using Type = parsing::schema::Type; + if constexpr (std::is_same()) { + return schema::Type{.value = schema::Type::Boolean{}}; + + } else if constexpr (std::is_same() || + std::is_same() || + std::is_same() || + std::is_same() || + std::is_same()) { + return schema::Type{.value = schema::Type::Integer{}}; + + } else if constexpr (std::is_same() || + std::is_same()) { + return schema::Type{.value = schema::Type::Number{}}; + + } else if constexpr (std::is_same()) { + return schema::Type{.value = schema::Type::String{}}; + + } else if constexpr (std::is_same()) { + auto any_of = std::vector(); + for (const auto& t : _t.types_) { + any_of.emplace_back(type_to_json_schema_type(t)); + } + return schema::Type{.value = schema::Type::AnyOf{.anyOf = any_of}}; + + } else if constexpr (std::is_same()) { + auto res = type_to_json_schema_type(*_t.type_); + const auto update_prediction = [&](auto _v) -> schema::Type { + _v.description = _t.description_; + return schema::Type{_v}; + }; + return rfl::visit(update_prediction, res.value); + + } else if constexpr (std::is_same()) { + return schema::Type{.value = schema::Type::FixedSizeTypedArray{ + .items = Ref::make( + type_to_json_schema_type(*_t.type_)), + .minItems = _t.size_, + .maxItems = _t.size_}}; + + } else if constexpr (std::is_same()) { + return schema::Type{.value = + schema::Type::StringEnum{.values = _t.values_}}; + + } else if constexpr (std::is_same()) { + auto properties = std::map(); + auto required = std::vector(); + for (const auto& [k, v] : _t.types_) { + properties[k] = type_to_json_schema_type(v); + if (!is_optional(v)) { + required.push_back(k); + } + } + auto additional_properties = + _t.additional_properties_ + ? std::make_shared( + type_to_json_schema_type(*_t.additional_properties_)) + : std::shared_ptr(); + return schema::Type{.value = schema::Type::Object{ + .properties = properties, + .required = required, + .additionalProperties = additional_properties}}; + + } else if constexpr (std::is_same()) { + return schema::Type{.value = schema::Type::AnyOf{ + .anyOf = {type_to_json_schema_type(*_t.type_), + schema::Type{schema::Type::Null{}}}}}; + + } else if constexpr (std::is_same()) { + return schema::Type{ + .value = schema::Type::Reference{.ref = "#/definitions/" + _t.name_}}; + + } else if constexpr (std::is_same()) { + return schema::Type{.value = schema::Type::StringMap{ + .additionalProperties = Ref::make( + type_to_json_schema_type(*_t.value_type_))}}; + + } else if constexpr (std::is_same()) { + auto items = std::vector(); + for (const auto& t : _t.types_) { + items.emplace_back(type_to_json_schema_type(t)); + } + return schema::Type{.value = schema::Type::Tuple{.prefixItems = items}}; + + } else if constexpr (std::is_same()) { + return schema::Type{.value = schema::Type::TypedArray{ + .items = Ref::make( + type_to_json_schema_type(*_t.type_))}}; + + } else if constexpr (std::is_same()) { + return handle_validation_type(*_t.type_, _t.validation_); + + } else { + static_assert(rfl::always_false_v, "Not all cases were covered."); + } + }; + + return rfl::visit(handle_variant, _type.variant_); +} + +} // namespace rfl::json From 32cba784622906472000830bf1f3328a405d7dcf Mon Sep 17 00:00:00 2001 From: George Evmenov Date: Thu, 3 Oct 2024 03:08:58 +0300 Subject: [PATCH 03/12] move json/Writer and Reader implementation into .cpp --- include/rfl/json/Reader.hpp | 39 +++----------- include/rfl/json/Writer.hpp | 71 ++++++------------------- src/json/Reader.cpp | 69 +++++++++++++++++++++++++ src/json/Writer.cpp | 100 ++++++++++++++++++++++++++++++++++++ src/reflectcpp.cpp | 4 +- 5 files changed, 194 insertions(+), 89 deletions(-) create mode 100644 src/json/Reader.cpp create mode 100644 src/json/Writer.cpp diff --git a/include/rfl/json/Reader.hpp b/include/rfl/json/Reader.hpp index b0e0102a..60fb0de0 100644 --- a/include/rfl/json/Reader.hpp +++ b/include/rfl/json/Reader.hpp @@ -48,31 +48,16 @@ struct Reader { using InputVarType = YYJSONInputVar; template - static constexpr bool has_custom_constructor = (requires(InputVarType var) { - T::from_json_obj(var); - }); + static constexpr bool has_custom_constructor = + (requires(InputVarType var) { T::from_json_obj(var); }); rfl::Result get_field_from_array( - const size_t _idx, const InputArrayType _arr) const noexcept { - const auto var = InputVarType(yyjson_arr_get(_arr.val_, _idx)); - if (!var.val_) { - return rfl::Error("Index " + std::to_string(_idx) + " of of bounds."); - } - return var; - } + const size_t _idx, const InputArrayType _arr) const noexcept; rfl::Result get_field_from_object( - const std::string& _name, const InputObjectType _obj) const noexcept { - const auto var = InputVarType(yyjson_obj_get(_obj.val_, _name.c_str())); - if (!var.val_) { - return rfl::Error("Object contains no field named '" + _name + "'."); - } - return var; - } + const std::string& _name, const InputObjectType _obj) const noexcept; - bool is_empty(const InputVarType _var) const noexcept { - return !_var.val_ || yyjson_is_null(_var.val_); - } + bool is_empty(const InputVarType _var) const noexcept; template std::optional read_array(const ArrayReader& _array_reader, @@ -135,20 +120,10 @@ struct Reader { } } - rfl::Result to_array(const InputVarType _var) const noexcept { - if (!yyjson_is_arr(_var.val_)) { - return rfl::Error("Could not cast to array!"); - } - return InputArrayType(_var.val_); - } + rfl::Result to_array(const InputVarType _var) const noexcept; rfl::Result to_object( - const InputVarType _var) const noexcept { - if (!yyjson_is_obj(_var.val_)) { - return rfl::Error("Could not cast to object!"); - } - return InputObjectType(_var.val_); - } + const InputVarType _var) const noexcept; template rfl::Result use_custom_constructor( diff --git a/include/rfl/json/Writer.hpp b/include/rfl/json/Writer.hpp index 44731c06..2dcd6ddb 100644 --- a/include/rfl/json/Writer.hpp +++ b/include/rfl/json/Writer.hpp @@ -48,27 +48,13 @@ class Writer { using OutputObjectType = YYJSONOutputObject; using OutputVarType = YYJSONOutputVar; - Writer(yyjson_mut_doc* _doc) : doc_(_doc) {} + Writer(yyjson_mut_doc* _doc); - ~Writer() = default; + OutputArrayType array_as_root(const size_t) const noexcept; - OutputArrayType array_as_root(const size_t) const noexcept { - const auto arr = yyjson_mut_arr(doc_); - yyjson_mut_doc_set_root(doc_, arr); - return OutputArrayType(arr); - } - - OutputObjectType object_as_root(const size_t) const noexcept { - const auto obj = yyjson_mut_obj(doc_); - yyjson_mut_doc_set_root(doc_, obj); - return OutputObjectType(obj); - } + OutputObjectType object_as_root(const size_t) const noexcept; - OutputVarType null_as_root() const noexcept { - const auto null = yyjson_mut_null(doc_); - yyjson_mut_doc_set_root(doc_, null); - return OutputVarType(null); - } + OutputVarType null_as_root() const noexcept; template OutputVarType value_as_root(const T& _var) const noexcept { @@ -78,36 +64,18 @@ class Writer { } OutputArrayType add_array_to_array(const size_t, - OutputArrayType* _parent) const noexcept { - const auto arr = yyjson_mut_arr(doc_); - yyjson_mut_arr_add_val(_parent->val_, arr); - return OutputArrayType(arr); - } + OutputArrayType* _parent) const noexcept; - OutputArrayType add_array_to_object( - const std::string_view& _name, const size_t, - OutputObjectType* _parent) const noexcept { - const auto arr = yyjson_mut_arr(doc_); - yyjson_mut_obj_add(_parent->val_, yyjson_mut_strcpy(doc_, _name.data()), - arr); - return OutputArrayType(arr); - } + OutputArrayType add_array_to_object(const std::string_view& _name, + const size_t, + OutputObjectType* _parent) const noexcept; - OutputObjectType add_object_to_array( - const size_t, OutputArrayType* _parent) const noexcept { - const auto obj = yyjson_mut_obj(doc_); - yyjson_mut_arr_add_val(_parent->val_, obj); - return OutputObjectType(obj); - } + OutputObjectType add_object_to_array(const size_t, + OutputArrayType* _parent) const noexcept; OutputObjectType add_object_to_object( const std::string_view& _name, const size_t, - OutputObjectType* _parent) const noexcept { - const auto obj = yyjson_mut_obj(doc_); - yyjson_mut_obj_add(_parent->val_, yyjson_mut_strcpy(doc_, _name.data()), - obj); - return OutputObjectType(obj); - } + OutputObjectType* _parent) const noexcept; template OutputVarType add_value_to_array(const T& _var, @@ -127,23 +95,14 @@ class Writer { return OutputVarType(val); } - OutputVarType add_null_to_array(OutputArrayType* _parent) const noexcept { - const auto null = yyjson_mut_null(doc_); - yyjson_mut_arr_add_val(_parent->val_, null); - return OutputVarType(null); - } + OutputVarType add_null_to_array(OutputArrayType* _parent) const noexcept; OutputVarType add_null_to_object(const std::string_view& _name, - OutputObjectType* _parent) const noexcept { - const auto null = yyjson_mut_null(doc_); - yyjson_mut_obj_add(_parent->val_, yyjson_mut_strcpy(doc_, _name.data()), - null); - return OutputVarType(null); - } + OutputObjectType* _parent) const noexcept; - void end_array(OutputArrayType*) const noexcept {} + void end_array(OutputArrayType*) const noexcept; - void end_object(OutputObjectType*) const noexcept {} + void end_object(OutputObjectType*) const noexcept; private: template diff --git a/src/json/Reader.cpp b/src/json/Reader.cpp new file mode 100644 index 00000000..7aa4cbf9 --- /dev/null +++ b/src/json/Reader.cpp @@ -0,0 +1,69 @@ +/* + +MIT License + +Copyright (c) 2023-2024 Code17 GmbH + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +*/ + +#include "rfl/json/Reader.hpp" + +namespace rfl::json { + +rfl::Result Reader::get_field_from_array( + const size_t _idx, const InputArrayType _arr) const noexcept { + const auto var = InputVarType(yyjson_arr_get(_arr.val_, _idx)); + if (!var.val_) { + return rfl::Error("Index " + std::to_string(_idx) + " of of bounds."); + } + return var; +} + +rfl::Result Reader::get_field_from_object( + const std::string& _name, const InputObjectType _obj) const noexcept { + const auto var = InputVarType(yyjson_obj_get(_obj.val_, _name.c_str())); + if (!var.val_) { + return rfl::Error("Object contains no field named '" + _name + "'."); + } + return var; +} + +bool Reader::is_empty(const InputVarType _var) const noexcept { + return !_var.val_ || yyjson_is_null(_var.val_); +} + +rfl::Result Reader::to_array( + const InputVarType _var) const noexcept { + if (!yyjson_is_arr(_var.val_)) { + return rfl::Error("Could not cast to array!"); + } + return InputArrayType(_var.val_); +} + +rfl::Result Reader::to_object( + const InputVarType _var) const noexcept { + if (!yyjson_is_obj(_var.val_)) { + return rfl::Error("Could not cast to object!"); + } + return InputObjectType(_var.val_); +} + +} // namespace rfl::json diff --git a/src/json/Writer.cpp b/src/json/Writer.cpp new file mode 100644 index 00000000..49244a0b --- /dev/null +++ b/src/json/Writer.cpp @@ -0,0 +1,100 @@ +/* + +MIT License + +Copyright (c) 2023-2024 Code17 GmbH + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +*/ + +#include "rfl/json/Writer.hpp" + +namespace rfl::json { + +Writer::Writer(yyjson_mut_doc* _doc) : doc_(_doc) {} + +Writer::OutputArrayType Writer::array_as_root(const size_t) const noexcept { + const auto arr = yyjson_mut_arr(doc_); + yyjson_mut_doc_set_root(doc_, arr); + return OutputArrayType(arr); +} + +Writer::OutputObjectType Writer::object_as_root(const size_t) const noexcept { + const auto obj = yyjson_mut_obj(doc_); + yyjson_mut_doc_set_root(doc_, obj); + return OutputObjectType(obj); +} + +Writer::OutputVarType Writer::null_as_root() const noexcept { + const auto null = yyjson_mut_null(doc_); + yyjson_mut_doc_set_root(doc_, null); + return OutputVarType(null); +} + +Writer::OutputArrayType Writer::add_array_to_array( + const size_t, OutputArrayType* _parent) const noexcept { + const auto arr = yyjson_mut_arr(doc_); + yyjson_mut_arr_add_val(_parent->val_, arr); + return OutputArrayType(arr); +} + +Writer::OutputArrayType Writer::add_array_to_object( + const std::string_view& _name, const size_t, + OutputObjectType* _parent) const noexcept { + const auto arr = yyjson_mut_arr(doc_); + yyjson_mut_obj_add(_parent->val_, yyjson_mut_strcpy(doc_, _name.data()), arr); + return OutputArrayType(arr); +} + +Writer::OutputObjectType Writer::add_object_to_array( + const size_t, OutputArrayType* _parent) const noexcept { + const auto obj = yyjson_mut_obj(doc_); + yyjson_mut_arr_add_val(_parent->val_, obj); + return OutputObjectType(obj); +} + +Writer::OutputObjectType Writer::add_object_to_object( + const std::string_view& _name, const size_t, + OutputObjectType* _parent) const noexcept { + const auto obj = yyjson_mut_obj(doc_); + yyjson_mut_obj_add(_parent->val_, yyjson_mut_strcpy(doc_, _name.data()), obj); + return OutputObjectType(obj); +} + +Writer::OutputVarType Writer::add_null_to_array( + OutputArrayType* _parent) const noexcept { + const auto null = yyjson_mut_null(doc_); + yyjson_mut_arr_add_val(_parent->val_, null); + return OutputVarType(null); +} + +Writer::OutputVarType Writer::add_null_to_object( + const std::string_view& _name, OutputObjectType* _parent) const noexcept { + const auto null = yyjson_mut_null(doc_); + yyjson_mut_obj_add(_parent->val_, yyjson_mut_strcpy(doc_, _name.data()), + null); + return OutputVarType(null); +} + +void Writer::end_array(OutputArrayType*) const noexcept {} + +void Writer::end_object(OutputObjectType*) const noexcept {} + +} // namespace rfl::json diff --git a/src/reflectcpp.cpp b/src/reflectcpp.cpp index 6071dd43..911306ab 100644 --- a/src/reflectcpp.cpp +++ b/src/reflectcpp.cpp @@ -30,5 +30,7 @@ SOFTWARE. // compilation. #include "Generic.cpp" -#include "to_schema.cpp" #include "Type.cpp" +#include "json/Reader.cpp" +#include "json/Writer.cpp" +#include "to_schema.cpp" From 6d5105becdca9474af74560c9c5b286764469624 Mon Sep 17 00:00:00 2001 From: George Evmenov Date: Thu, 3 Oct 2024 04:26:50 +0300 Subject: [PATCH 04/12] remove not used Output***Type aliases, kept only in Writers and Parent --- include/rfl/bson/Parser.hpp | 1 - include/rfl/parsing/FieldVariantParser.hpp | 3 --- include/rfl/parsing/MapParser.hpp | 3 --- include/rfl/parsing/NamedTupleParser.hpp | 1 - include/rfl/parsing/Parser_array.hpp | 3 --- include/rfl/parsing/Parser_box.hpp | 1 - include/rfl/parsing/Parser_c_array.hpp | 3 --- include/rfl/parsing/Parser_default.hpp | 1 - include/rfl/parsing/Parser_filepath.hpp | 1 - include/rfl/parsing/Parser_optional.hpp | 1 - include/rfl/parsing/Parser_pair.hpp | 1 - include/rfl/parsing/Parser_ptr.hpp | 1 - include/rfl/parsing/Parser_ref.hpp | 1 - include/rfl/parsing/Parser_reference_wrapper.hpp | 1 - include/rfl/parsing/Parser_rename.hpp | 1 - include/rfl/parsing/Parser_result.hpp | 1 - include/rfl/parsing/Parser_rfl_array.hpp | 3 --- include/rfl/parsing/Parser_rfl_variant.hpp | 1 - include/rfl/parsing/Parser_shared_ptr.hpp | 1 - include/rfl/parsing/Parser_skip.hpp | 1 - include/rfl/parsing/Parser_string_view.hpp | 1 - include/rfl/parsing/Parser_tagged_union.hpp | 3 --- include/rfl/parsing/Parser_unique_ptr.hpp | 1 - include/rfl/parsing/Parser_variant.hpp | 1 - include/rfl/parsing/Parser_wstring.hpp | 1 - include/rfl/parsing/TupleParser.hpp | 3 --- include/rfl/parsing/VectorParser.hpp | 3 --- 27 files changed, 43 deletions(-) diff --git a/include/rfl/bson/Parser.hpp b/include/rfl/bson/Parser.hpp index 60352b2b..df7294a9 100644 --- a/include/rfl/bson/Parser.hpp +++ b/include/rfl/bson/Parser.hpp @@ -15,7 +15,6 @@ template requires AreReaderAndWriter struct Parser { using InputVarType = typename R::InputVarType; - using OutputVarType = typename W::OutputVarType; using ParentType = Parent; diff --git a/include/rfl/parsing/FieldVariantParser.hpp b/include/rfl/parsing/FieldVariantParser.hpp index 5008c65f..59238516 100644 --- a/include/rfl/parsing/FieldVariantParser.hpp +++ b/include/rfl/parsing/FieldVariantParser.hpp @@ -30,9 +30,6 @@ struct FieldVariantParser { using InputObjectType = typename R::InputObjectType; using InputVarType = typename R::InputVarType; - using OutputObjectType = typename W::OutputObjectType; - using OutputVarType = typename W::OutputVarType; - static ResultType read(const R& _r, const InputVarType& _var) noexcept { static_assert( internal::no_duplicate_field_names>(), diff --git a/include/rfl/parsing/MapParser.hpp b/include/rfl/parsing/MapParser.hpp index 379f889e..c8b03fcb 100644 --- a/include/rfl/parsing/MapParser.hpp +++ b/include/rfl/parsing/MapParser.hpp @@ -25,9 +25,6 @@ struct MapParser { using InputObjectType = typename R::InputObjectType; using InputVarType = typename R::InputVarType; - using OutputObjectType = typename W::OutputObjectType; - using OutputVarType = typename W::OutputVarType; - using KeyType = std::remove_cvref_t; using ValueType = std::remove_cvref_t; diff --git a/include/rfl/parsing/NamedTupleParser.hpp b/include/rfl/parsing/NamedTupleParser.hpp index 4251191e..d78b5434 100644 --- a/include/rfl/parsing/NamedTupleParser.hpp +++ b/include/rfl/parsing/NamedTupleParser.hpp @@ -40,7 +40,6 @@ template > struct NamedTupleParser { using InputVarType = typename R::InputVarType; - using OutputVarType = typename W::OutputVarType; using ParentType = Parent; diff --git a/include/rfl/parsing/Parser_array.hpp b/include/rfl/parsing/Parser_array.hpp index 35c3185b..22a6b691 100644 --- a/include/rfl/parsing/Parser_array.hpp +++ b/include/rfl/parsing/Parser_array.hpp @@ -23,9 +23,6 @@ struct Parser, ProcessorsType> { using InputArrayType = typename R::InputArrayType; using InputVarType = typename R::InputVarType; - using OutputArrayType = typename W::OutputArrayType; - using OutputVarType = typename W::OutputVarType; - using ParentType = Parent; static Result> read(const R& _r, diff --git a/include/rfl/parsing/Parser_box.hpp b/include/rfl/parsing/Parser_box.hpp index 89c41eaf..590e1eee 100644 --- a/include/rfl/parsing/Parser_box.hpp +++ b/include/rfl/parsing/Parser_box.hpp @@ -16,7 +16,6 @@ template requires AreReaderAndWriter> struct Parser, ProcessorsType> { using InputVarType = typename R::InputVarType; - using OutputVarType = typename W::OutputVarType; static Result> read(const R& _r, const InputVarType& _var) noexcept { const auto to_box = [](auto&& _t) { return Box::make(std::move(_t)); }; diff --git a/include/rfl/parsing/Parser_c_array.hpp b/include/rfl/parsing/Parser_c_array.hpp index 1d9d2dcb..be117145 100644 --- a/include/rfl/parsing/Parser_c_array.hpp +++ b/include/rfl/parsing/Parser_c_array.hpp @@ -23,9 +23,6 @@ struct Parser { using InputArrayType = typename R::InputArrayType; using InputVarType = typename R::InputVarType; - using OutputArrayType = typename W::OutputArrayType; - using OutputVarType = typename W::OutputVarType; - using ParentType = Parent; using CArray = T[_size]; diff --git a/include/rfl/parsing/Parser_default.hpp b/include/rfl/parsing/Parser_default.hpp index 5ab8f90b..87b7c21c 100644 --- a/include/rfl/parsing/Parser_default.hpp +++ b/include/rfl/parsing/Parser_default.hpp @@ -36,7 +36,6 @@ requires AreReaderAndWriter struct Parser { public: using InputVarType = typename R::InputVarType; - using OutputVarType = typename W::OutputVarType; using ParentType = Parent; diff --git a/include/rfl/parsing/Parser_filepath.hpp b/include/rfl/parsing/Parser_filepath.hpp index 95d88e07..e19f352f 100644 --- a/include/rfl/parsing/Parser_filepath.hpp +++ b/include/rfl/parsing/Parser_filepath.hpp @@ -15,7 +15,6 @@ template requires AreReaderAndWriter struct Parser { using InputVarType = typename R::InputVarType; - using OutputVarType = typename W::OutputVarType; /// Expresses the variables as type T. static Result read(const R& _r, diff --git a/include/rfl/parsing/Parser_optional.hpp b/include/rfl/parsing/Parser_optional.hpp index c099a025..50e7a40d 100644 --- a/include/rfl/parsing/Parser_optional.hpp +++ b/include/rfl/parsing/Parser_optional.hpp @@ -19,7 +19,6 @@ template requires AreReaderAndWriter> struct Parser, ProcessorsType> { using InputVarType = typename R::InputVarType; - using OutputVarType = typename W::OutputVarType; using ParentType = Parent; diff --git a/include/rfl/parsing/Parser_pair.hpp b/include/rfl/parsing/Parser_pair.hpp index 351090e7..6559a474 100644 --- a/include/rfl/parsing/Parser_pair.hpp +++ b/include/rfl/parsing/Parser_pair.hpp @@ -19,7 +19,6 @@ template > struct Parser, ProcessorsType> { using InputVarType = typename R::InputVarType; - using OutputVarType = typename W::OutputVarType; /// Expresses the variables as type T. static Result> read( diff --git a/include/rfl/parsing/Parser_ptr.hpp b/include/rfl/parsing/Parser_ptr.hpp index f4c0bfcf..20950796 100644 --- a/include/rfl/parsing/Parser_ptr.hpp +++ b/include/rfl/parsing/Parser_ptr.hpp @@ -18,7 +18,6 @@ template requires AreReaderAndWriter struct Parser { using InputVarType = typename R::InputVarType; - using OutputVarType = typename W::OutputVarType; using ParentType = Parent; diff --git a/include/rfl/parsing/Parser_ref.hpp b/include/rfl/parsing/Parser_ref.hpp index 961ad55d..1c1348e7 100644 --- a/include/rfl/parsing/Parser_ref.hpp +++ b/include/rfl/parsing/Parser_ref.hpp @@ -17,7 +17,6 @@ template requires AreReaderAndWriter> struct Parser, ProcessorsType> { using InputVarType = typename R::InputVarType; - using OutputVarType = typename W::OutputVarType; static Result> read(const R& _r, const InputVarType& _var) noexcept { const auto to_ref = [&](auto&& _t) { return Ref::make(std::move(_t)); }; diff --git a/include/rfl/parsing/Parser_reference_wrapper.hpp b/include/rfl/parsing/Parser_reference_wrapper.hpp index d4ec0976..7a6c2376 100644 --- a/include/rfl/parsing/Parser_reference_wrapper.hpp +++ b/include/rfl/parsing/Parser_reference_wrapper.hpp @@ -17,7 +17,6 @@ template requires AreReaderAndWriter> struct Parser, ProcessorsType> { using InputVarType = typename R::InputVarType; - using OutputVarType = typename W::OutputVarType; static Result> read( const R&, const InputVarType&) noexcept { diff --git a/include/rfl/parsing/Parser_rename.hpp b/include/rfl/parsing/Parser_rename.hpp index 641a357b..161a8e57 100644 --- a/include/rfl/parsing/Parser_rename.hpp +++ b/include/rfl/parsing/Parser_rename.hpp @@ -19,7 +19,6 @@ template > struct Parser, ProcessorsType> { using InputVarType = typename R::InputVarType; - using OutputVarType = typename W::OutputVarType; static Result> read(const R& _r, const InputVarType& _var) noexcept { diff --git a/include/rfl/parsing/Parser_result.hpp b/include/rfl/parsing/Parser_result.hpp index e91b66ac..f287c59a 100644 --- a/include/rfl/parsing/Parser_result.hpp +++ b/include/rfl/parsing/Parser_result.hpp @@ -17,7 +17,6 @@ template requires AreReaderAndWriter> struct Parser, ProcessorsType> { using InputVarType = typename R::InputVarType; - using OutputVarType = typename W::OutputVarType; using ErrorType = NamedTuple>; using VariantType = std::variant, ErrorType>; diff --git a/include/rfl/parsing/Parser_rfl_array.hpp b/include/rfl/parsing/Parser_rfl_array.hpp index 604aed69..1c6d9a73 100644 --- a/include/rfl/parsing/Parser_rfl_array.hpp +++ b/include/rfl/parsing/Parser_rfl_array.hpp @@ -22,9 +22,6 @@ struct Parser, ProcessorsType> { using InputArrayType = typename R::InputArrayType; using InputVarType = typename R::InputVarType; - using OutputArrayType = typename W::OutputArrayType; - using OutputVarType = typename W::OutputVarType; - using StdArray = internal::to_std_array_t; static Result> read(const R& _r, diff --git a/include/rfl/parsing/Parser_rfl_variant.hpp b/include/rfl/parsing/Parser_rfl_variant.hpp index d05553a8..28b0d90c 100644 --- a/include/rfl/parsing/Parser_rfl_variant.hpp +++ b/include/rfl/parsing/Parser_rfl_variant.hpp @@ -20,7 +20,6 @@ requires AreReaderAndWriter> class Parser, ProcessorsType> { public: using InputVarType = typename R::InputVarType; - using OutputVarType = typename W::OutputVarType; static Result> read( const R& _r, const InputVarType& _var) noexcept { diff --git a/include/rfl/parsing/Parser_shared_ptr.hpp b/include/rfl/parsing/Parser_shared_ptr.hpp index 7af759e1..3fe93fe4 100644 --- a/include/rfl/parsing/Parser_shared_ptr.hpp +++ b/include/rfl/parsing/Parser_shared_ptr.hpp @@ -18,7 +18,6 @@ template requires AreReaderAndWriter> struct Parser, ProcessorsType> { using InputVarType = typename R::InputVarType; - using OutputVarType = typename W::OutputVarType; using ParentType = Parent; diff --git a/include/rfl/parsing/Parser_skip.hpp b/include/rfl/parsing/Parser_skip.hpp index 135b0e25..abcfb0c6 100644 --- a/include/rfl/parsing/Parser_skip.hpp +++ b/include/rfl/parsing/Parser_skip.hpp @@ -21,7 +21,6 @@ struct Parser, ProcessorsType> { using InputVarType = typename R::InputVarType; - using OutputVarType = typename W::OutputVarType; static Result> read(const R& _r, const InputVarType& _var) noexcept { diff --git a/include/rfl/parsing/Parser_string_view.hpp b/include/rfl/parsing/Parser_string_view.hpp index 7a19b076..45ae1e5e 100644 --- a/include/rfl/parsing/Parser_string_view.hpp +++ b/include/rfl/parsing/Parser_string_view.hpp @@ -18,7 +18,6 @@ template requires AreReaderAndWriter struct Parser { using InputVarType = typename R::InputVarType; - using OutputVarType = typename W::OutputVarType; static Result read(const R&, const InputVarType&) noexcept { diff --git a/include/rfl/parsing/Parser_tagged_union.hpp b/include/rfl/parsing/Parser_tagged_union.hpp index d9442ad6..937b5e96 100644 --- a/include/rfl/parsing/Parser_tagged_union.hpp +++ b/include/rfl/parsing/Parser_tagged_union.hpp @@ -30,9 +30,6 @@ struct Parser, using InputObjectType = typename R::InputObjectType; using InputVarType = typename R::InputVarType; - using OutputObjectType = typename W::OutputObjectType; - using OutputVarType = typename W::OutputVarType; - constexpr static bool no_field_names_ = ProcessorsType::no_field_names_; using InputObjectOrArrayType = diff --git a/include/rfl/parsing/Parser_unique_ptr.hpp b/include/rfl/parsing/Parser_unique_ptr.hpp index 655c9590..0e07cf39 100644 --- a/include/rfl/parsing/Parser_unique_ptr.hpp +++ b/include/rfl/parsing/Parser_unique_ptr.hpp @@ -19,7 +19,6 @@ template requires AreReaderAndWriter> struct Parser, ProcessorsType> { using InputVarType = typename R::InputVarType; - using OutputVarType = typename W::OutputVarType; using ParentType = Parent; diff --git a/include/rfl/parsing/Parser_variant.hpp b/include/rfl/parsing/Parser_variant.hpp index 284b74bd..84150971 100644 --- a/include/rfl/parsing/Parser_variant.hpp +++ b/include/rfl/parsing/Parser_variant.hpp @@ -28,7 +28,6 @@ class Parser, ProcessorsType> { public: using InputVarType = typename R::InputVarType; - using OutputVarType = typename W::OutputVarType; static Result> read( const R& _r, const InputVarType& _var) noexcept { diff --git a/include/rfl/parsing/Parser_wstring.hpp b/include/rfl/parsing/Parser_wstring.hpp index d433c50c..b3853996 100644 --- a/include/rfl/parsing/Parser_wstring.hpp +++ b/include/rfl/parsing/Parser_wstring.hpp @@ -18,7 +18,6 @@ requires AreReaderAndWriter struct Parser { public: using InputVarType = typename R::InputVarType; - using OutputVarType = typename W::OutputVarType; using ParentType = Parent; diff --git a/include/rfl/parsing/TupleParser.hpp b/include/rfl/parsing/TupleParser.hpp index f5d6f792..3b1bd63f 100644 --- a/include/rfl/parsing/TupleParser.hpp +++ b/include/rfl/parsing/TupleParser.hpp @@ -24,9 +24,6 @@ struct TupleParser { using InputArrayType = typename R::InputArrayType; using InputVarType = typename R::InputVarType; - using OutputArrayType = typename W::OutputArrayType; - using OutputVarType = typename W::OutputVarType; - using ParentType = Parent; static Result read(const R& _r, diff --git a/include/rfl/parsing/VectorParser.hpp b/include/rfl/parsing/VectorParser.hpp index 42c29e98..54ae5327 100644 --- a/include/rfl/parsing/VectorParser.hpp +++ b/include/rfl/parsing/VectorParser.hpp @@ -33,9 +33,6 @@ struct VectorParser { using InputArrayType = typename R::InputArrayType; using InputVarType = typename R::InputVarType; - using OutputArrayType = typename W::OutputArrayType; - using OutputVarType = typename W::OutputVarType; - using ParentType = Parent; using T = typename VecType::value_type; From 632c70848eee90e133e80dc6930d3311da99ffd7 Mon Sep 17 00:00:00 2001 From: George Evmenov Date: Thu, 3 Oct 2024 14:16:20 +0300 Subject: [PATCH 05/12] move heavy json::to_schema implementation into cpp --- include/rfl/json/to_schema.hpp | 21 +++++---------------- src/to_schema.cpp | 19 +++++++++++++++++++ 2 files changed, 24 insertions(+), 16 deletions(-) diff --git a/include/rfl/json/to_schema.hpp b/include/rfl/json/to_schema.hpp index 8203f065..758d14bf 100644 --- a/include/rfl/json/to_schema.hpp +++ b/include/rfl/json/to_schema.hpp @@ -25,8 +25,6 @@ namespace rfl::json { -schema::Type type_to_json_schema_type(const parsing::schema::Type& _type); - template struct TypeHelper {}; @@ -35,25 +33,16 @@ struct TypeHelper> { using JSONSchemaType = rfl::Variant...>; }; +std::string to_schema_internal_schema( + const parsing::schema::Definition& internal_schema, + const yyjson_write_flag); + /// Returns the JSON schema for a class. template std::string to_schema(const yyjson_write_flag _flag = 0) { const auto internal_schema = parsing::schema::make>(); - auto definitions = std::map(); - for (const auto& [k, v] : internal_schema.definitions_) { - definitions[k] = type_to_json_schema_type(v); - } - using JSONSchemaType = - typename TypeHelper::JSONSchemaType; - const auto to_schema = [&](auto&& _root) -> JSONSchemaType { - using U = std::decay_t; - return schema::JSONSchema{.root = std::move(_root), - .definitions = definitions}; - }; - auto root = type_to_json_schema_type(internal_schema.root_); - const auto json_schema = rfl::visit(to_schema, std::move(root.value)); - return write(json_schema, _flag); + return to_schema_internal_schema(internal_schema, _flag); } } // namespace rfl::json diff --git a/src/to_schema.cpp b/src/to_schema.cpp index 8b51f472..bc1e87c7 100644 --- a/src/to_schema.cpp +++ b/src/to_schema.cpp @@ -276,4 +276,23 @@ schema::Type type_to_json_schema_type(const parsing::schema::Type& _type) { return rfl::visit(handle_variant, _type.variant_); } +std::string to_schema_internal_schema( + const parsing::schema::Definition& internal_schema, + const yyjson_write_flag _flag) { + auto definitions = std::map(); + for (const auto& [k, v] : internal_schema.definitions_) { + definitions[k] = type_to_json_schema_type(v); + } + using JSONSchemaType = + typename TypeHelper::JSONSchemaType; + const auto to_schema = [&](auto&& _root) -> JSONSchemaType { + using U = std::decay_t; + return schema::JSONSchema{.root = std::move(_root), + .definitions = definitions}; + }; + auto root = type_to_json_schema_type(internal_schema.root_); + const auto json_schema = rfl::visit(to_schema, std::move(root.value)); + return write(json_schema, _flag); +} + } // namespace rfl::json From 8b4651def5490f08d0950a4d73bf481618164465 Mon Sep 17 00:00:00 2001 From: George Evmenov Date: Fri, 4 Oct 2024 13:41:48 +0300 Subject: [PATCH 06/12] add REFLECTCPP_JSON, which is ON by default --- CMakeLists.txt | 36 +++++++++++++++++++++++++----------- reflectcpp-config.cmake.in | 5 +++-- tests/CMakeLists.txt | 6 ++++-- 3 files changed, 32 insertions(+), 15 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index b642c24a..83fca3c0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,6 +2,7 @@ cmake_minimum_required(VERSION 3.23) option(REFLECTCPP_BUILD_SHARED "Build shared library" ${BUILD_SHARED_LIBS}) +option(REFLECTCPP_JSON "Enable JSON support" ON) # enabled by default option(REFLECTCPP_BSON "Enable BSON support" OFF) option(REFLECTCPP_CBOR "Enable CBOR support" OFF) option(REFLECTCPP_FLEXBUFFERS "Enable flexbuffers support" OFF) @@ -17,6 +18,7 @@ option(REFLECTCPP_USE_BUNDLED_DEPENDENCIES "Use the bundled dependencies" ON) set(REFLECTCPP_USE_VCPKG_DEFAULT OFF) if(REFLECTCPP_BUILD_BENCHMARKS) + set(REFLECTCPP_JSON ON CACHE BOOL "" FORCE) set(REFLECTCPP_BSON ON CACHE BOOL "" FORCE) set(REFLECTCPP_CBOR ON CACHE BOOL "" FORCE) set(REFLECTCPP_FLEXBUFFERS ON CACHE BOOL "" FORCE) @@ -25,7 +27,9 @@ if(REFLECTCPP_BUILD_BENCHMARKS) set(REFLECTCPP_TOML ON CACHE BOOL "" FORCE) set(REFLECTCPP_YAML ON CACHE BOOL "" FORCE) endif() -if (REFLECTCPP_BUILD_TESTS OR REFLECTCPP_BUILD_BENCHMARKS OR REFLECTCPP_BSON OR REFLECTCPP_CBOR OR REFLECTCPP_FLEXBUFFERS OR REFLECTCPP_MSGPACK OR REFLECTCPP_XML OR REFLECTCPP_TOML OR REFLECTCPP_YAML) +if (REFLECTCPP_BUILD_TESTS OR REFLECTCPP_BUILD_BENCHMARKS OR + (REFLECTCPP_JSON AND NOT REFLECTCPP_USE_BUNDLED_DEPENDENCIES) OR + REFLECTCPP_BSON OR REFLECTCPP_CBOR OR REFLECTCPP_FLEXBUFFERS OR REFLECTCPP_MSGPACK OR REFLECTCPP_XML OR REFLECTCPP_TOML OR REFLECTCPP_YAML) # enable vcpkg per default if require features other than JSON set(REFLECTCPP_USE_VCPKG_DEFAULT ON) endif() @@ -63,20 +67,30 @@ target_include_directories( $ $) -if(REFLECTCPP_USE_BUNDLED_DEPENDENCIES) - list(APPEND REFLECT_CPP_SOURCES - src/yyjson.c - ) - set_source_files_properties(src/yyjson.c PROPERTIES LANGUAGE CXX) - +if (REFLECTCPP_USE_BUNDLED_DEPENDENCIES) target_include_directories( reflectcpp PUBLIC $) -else() +else () find_package(ctre CONFIG REQUIRED) - find_package(yyjson CONFIG REQUIRED) - target_link_libraries(reflectcpp INTERFACE ctre::ctre yyjson::yyjson) -endif() + target_link_libraries(reflectcpp INTERFACE ctre::ctre) +endif () + +if (REFLECTCPP_JSON) + if (REFLECTCPP_USE_BUNDLED_DEPENDENCIES) + list(APPEND REFLECT_CPP_SOURCES + src/yyjson.c + ) + set_source_files_properties(src/yyjson.c PROPERTIES LANGUAGE CXX) + + target_include_directories( + reflectcpp PUBLIC + $) + else () + find_package(yyjson CONFIG REQUIRED) + target_link_libraries(reflectcpp INTERFACE yyjson::yyjson) + endif () +endif () target_sources(reflectcpp PRIVATE ${REFLECT_CPP_SOURCES}) diff --git a/reflectcpp-config.cmake.in b/reflectcpp-config.cmake.in index 62ac44be..f1e409d8 100644 --- a/reflectcpp-config.cmake.in +++ b/reflectcpp-config.cmake.in @@ -1,5 +1,6 @@ @PACKAGE_INIT@ +set(REFLECTCPP_JSON @REFLECTCPP_JSON@) set(REFLECTCPP_BSON @REFLECTCPP_BSON@) set(REFLECTCPP_FLEXBUFFERS @REFLECTCPP_FLEXBUFFERS@) set(REFLECTCPP_TOML @REFLECTCPP_TOML@) @@ -7,13 +8,13 @@ set(REFLECTCPP_XML @REFLECTCPP_XML@) set(REFLECTCPP_YAML @REFLECTCPP_YAML@) set(REFLECTCPP_USE_BUNDLED_DEPENDENCIES @REFLECTCPP_USE_BUNDLED_DEPENDENCIES@) -if(REFLECTCPP_BSON OR REFLECTCPP_FLEXBUFFERS OR REFLECTCPP_XML OR REFLECTCPP_YAML OR NOT REFLECTCPP_USE_BUNDLED_DEPENDENCIES) +if(REFLECTCPP_BSON OR REFLECTCPP_FLEXBUFFERS OR REFLECTCPP_XML OR REFLECTCPP_YAML OR (REFLECTCPP_JSON AND NOT REFLECTCPP_USE_BUNDLED_DEPENDENCIES)) include(CMakeFindDependencyMacro) endif() include(${CMAKE_CURRENT_LIST_DIR}/reflectcpp-exports.cmake) -if (NOT REFLECTCPP_USE_BUNDLED_DEPENDENCIES) +if (REFLECTCPP_JSON AND NOT REFLECTCPP_USE_BUNDLED_DEPENDENCIES) find_dependency(ctre) find_dependency(yyjson) endif() diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 1c0ee2b2..277f6238 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -6,8 +6,10 @@ else() set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++20 -Wall -Wno-sign-compare -Wno-missing-braces -Wno-psabi -pthread -fno-strict-aliasing -fwrapv -O2 -ftemplate-backtrace-limit=0 -fsanitize=undefined") endif() -add_subdirectory(json) -add_subdirectory(json_c_arrays_and_inheritance) +if (REFLECTCPP_JSON) + add_subdirectory(json) + add_subdirectory(json_c_arrays_and_inheritance) +endif () if (REFLECTCPP_BSON) add_subdirectory(bson) From 902577430c4746bd5250a12a405ac123a324e1ac Mon Sep 17 00:00:00 2001 From: George Evmenov Date: Fri, 4 Oct 2024 13:59:33 +0300 Subject: [PATCH 07/12] add separate reflectcpp_json.cpp --- CMakeLists.txt | 3 +++ README.md | 6 ++++-- src/reflectcpp.cpp | 2 -- src/reflectcpp_json.cpp | 33 +++++++++++++++++++++++++++++++++ 4 files changed, 40 insertions(+), 4 deletions(-) create mode 100644 src/reflectcpp_json.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 83fca3c0..5f28a632 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -77,6 +77,9 @@ else () endif () if (REFLECTCPP_JSON) + list(APPEND REFLECT_CPP_SOURCES + src/reflectcpp_json.cpp + ) if (REFLECTCPP_USE_BUNDLED_DEPENDENCIES) list(APPEND REFLECT_CPP_SOURCES src/yyjson.c diff --git a/README.md b/README.md index a446fd1b..7a899d09 100644 --- a/README.md +++ b/README.md @@ -527,8 +527,10 @@ The following compilers are supported: ### Option 1: Include source files into your own build -Simply copy the contents of the folder `include` into your source repository or add it to your include path and also add `src/reflectcpp.cpp` and `src/yyjson.c` to your source files for compilation. -If you don't need JSON support or want to link to your own version of YYJSON, then only copy `src/reflectcpp.cpp`. +Simply copy the contents of the folders `include` and `src` into your source repository or add it to your include path +and also add `src/reflectcpp.cpp` and `src/reflectcpp_json.cpp` and `src/yyjson.c` to your source files for compilation. +If you want to link to your own version of YYJSON, then only copy `src/reflectcpp.cpp` and `src/reflectcpp_json.cpp`. +If you don't need JSON support, then only copy `src/reflectcpp.cpp`. If you need support for other serialization formats like flexbuffers or XML, you should also include and link the respective libraries, as listed in the section on serialization formats. diff --git a/src/reflectcpp.cpp b/src/reflectcpp.cpp index 911306ab..7181b5a7 100644 --- a/src/reflectcpp.cpp +++ b/src/reflectcpp.cpp @@ -31,6 +31,4 @@ SOFTWARE. #include "Generic.cpp" #include "Type.cpp" -#include "json/Reader.cpp" -#include "json/Writer.cpp" #include "to_schema.cpp" diff --git a/src/reflectcpp_json.cpp b/src/reflectcpp_json.cpp new file mode 100644 index 00000000..9235369c --- /dev/null +++ b/src/reflectcpp_json.cpp @@ -0,0 +1,33 @@ +/* + +MIT License + +Copyright (c) 2023-2024 Code17 GmbH + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +*/ + +// This file include all other source files, so that the user of the library +// don't need to add multiple source files into their build. +// Also, this speeds up compile time, compared to multiple separate .cpp files +// compilation. + +#include "json/Reader.cpp" +#include "json/Writer.cpp" From 7f9b25ff8d5afa08c33e339e4c8a333325dec617 Mon Sep 17 00:00:00 2001 From: George Evmenov Date: Fri, 4 Oct 2024 16:23:47 +0300 Subject: [PATCH 08/12] move to_schema.cpp -> json/to_schema.cpp since this is a json/to_schema.hpp counterpart --- src/{ => json}/to_schema.cpp | 0 src/reflectcpp.cpp | 1 - src/reflectcpp_json.cpp | 1 + 3 files changed, 1 insertion(+), 1 deletion(-) rename src/{ => json}/to_schema.cpp (100%) diff --git a/src/to_schema.cpp b/src/json/to_schema.cpp similarity index 100% rename from src/to_schema.cpp rename to src/json/to_schema.cpp diff --git a/src/reflectcpp.cpp b/src/reflectcpp.cpp index 7181b5a7..63c93c5d 100644 --- a/src/reflectcpp.cpp +++ b/src/reflectcpp.cpp @@ -31,4 +31,3 @@ SOFTWARE. #include "Generic.cpp" #include "Type.cpp" -#include "to_schema.cpp" diff --git a/src/reflectcpp_json.cpp b/src/reflectcpp_json.cpp index 9235369c..afcdb833 100644 --- a/src/reflectcpp_json.cpp +++ b/src/reflectcpp_json.cpp @@ -31,3 +31,4 @@ SOFTWARE. #include "json/Reader.cpp" #include "json/Writer.cpp" +#include "json/to_schema.cpp" From 2b0e9c46d506b9c56aeb5229589c32ab90afac14 Mon Sep 17 00:00:00 2001 From: George Evmenov Date: Sat, 5 Oct 2024 03:41:12 +0300 Subject: [PATCH 09/12] move source files to match with include directory structure --- src/reflectcpp.cpp | 4 ++-- src/reflectcpp_json.cpp | 6 +++--- src/{ => rfl}/Generic.cpp | 0 src/{ => rfl}/json/Reader.cpp | 0 src/{ => rfl}/json/Writer.cpp | 0 src/{ => rfl}/json/to_schema.cpp | 0 src/{ => rfl/parsing/schema}/Type.cpp | 0 7 files changed, 5 insertions(+), 5 deletions(-) rename src/{ => rfl}/Generic.cpp (100%) rename src/{ => rfl}/json/Reader.cpp (100%) rename src/{ => rfl}/json/Writer.cpp (100%) rename src/{ => rfl}/json/to_schema.cpp (100%) rename src/{ => rfl/parsing/schema}/Type.cpp (100%) diff --git a/src/reflectcpp.cpp b/src/reflectcpp.cpp index 63c93c5d..cbd73b92 100644 --- a/src/reflectcpp.cpp +++ b/src/reflectcpp.cpp @@ -29,5 +29,5 @@ SOFTWARE. // Also, this speeds up compile time, compared to multiple separate .cpp files // compilation. -#include "Generic.cpp" -#include "Type.cpp" +#include "rfl/Generic.cpp" +#include "rfl/parsing/schema/Type.cpp" diff --git a/src/reflectcpp_json.cpp b/src/reflectcpp_json.cpp index afcdb833..e1e9a032 100644 --- a/src/reflectcpp_json.cpp +++ b/src/reflectcpp_json.cpp @@ -29,6 +29,6 @@ SOFTWARE. // Also, this speeds up compile time, compared to multiple separate .cpp files // compilation. -#include "json/Reader.cpp" -#include "json/Writer.cpp" -#include "json/to_schema.cpp" +#include "rfl/json/Reader.cpp" +#include "rfl/json/Writer.cpp" +#include "rfl/json/to_schema.cpp" diff --git a/src/Generic.cpp b/src/rfl/Generic.cpp similarity index 100% rename from src/Generic.cpp rename to src/rfl/Generic.cpp diff --git a/src/json/Reader.cpp b/src/rfl/json/Reader.cpp similarity index 100% rename from src/json/Reader.cpp rename to src/rfl/json/Reader.cpp diff --git a/src/json/Writer.cpp b/src/rfl/json/Writer.cpp similarity index 100% rename from src/json/Writer.cpp rename to src/rfl/json/Writer.cpp diff --git a/src/json/to_schema.cpp b/src/rfl/json/to_schema.cpp similarity index 100% rename from src/json/to_schema.cpp rename to src/rfl/json/to_schema.cpp diff --git a/src/Type.cpp b/src/rfl/parsing/schema/Type.cpp similarity index 100% rename from src/Type.cpp rename to src/rfl/parsing/schema/Type.cpp From 1fb144453c37751cda14eeb1474f95cd02c33f8e Mon Sep 17 00:00:00 2001 From: George Evmenov Date: Sat, 5 Oct 2024 04:09:57 +0300 Subject: [PATCH 10/12] move some xml::Reader and Writer imlpementations into cpp --- CMakeLists.txt | 7 +- include/rfl/parsing/ViewReader.hpp | 1 + include/rfl/xml/Reader.hpp | 59 ++-------------- include/rfl/xml/Writer.hpp | 73 +++++--------------- src/reflectcpp_xml.cpp | 33 +++++++++ src/rfl/xml/Reader.cpp | 87 +++++++++++++++++++++++ src/rfl/xml/Writer.cpp | 107 +++++++++++++++++++++++++++++ 7 files changed, 255 insertions(+), 112 deletions(-) create mode 100644 src/reflectcpp_xml.cpp create mode 100644 src/rfl/xml/Reader.cpp create mode 100644 src/rfl/xml/Writer.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 5f28a632..97862276 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -95,8 +95,6 @@ if (REFLECTCPP_JSON) endif () endif () -target_sources(reflectcpp PRIVATE ${REFLECT_CPP_SOURCES}) - set_target_properties(reflectcpp PROPERTIES LINKER_LANGUAGE CXX) if (REFLECTCPP_BSON) @@ -135,6 +133,9 @@ if (REFLECTCPP_TOML) endif() if (REFLECTCPP_XML) + list(APPEND REFLECT_CPP_SOURCES + src/reflectcpp_xml.cpp + ) find_package(pugixml CONFIG REQUIRED) target_link_libraries(reflectcpp INTERFACE pugixml::pugixml) endif () @@ -144,6 +145,8 @@ if (REFLECTCPP_YAML) target_link_libraries(reflectcpp INTERFACE yaml-cpp::yaml-cpp) endif () +target_sources(reflectcpp PRIVATE ${REFLECT_CPP_SOURCES}) + if (REFLECTCPP_BUILD_TESTS) if (MSVC) set(REFLECT_CPP_GTEST_LIB "${VCPKG_INSTALLED_DIR}/${VCPKG_TARGET_TRIPLET}/lib/gtest${CMAKE_STATIC_LIBRARY_SUFFIX}") diff --git a/include/rfl/parsing/ViewReader.hpp b/include/rfl/parsing/ViewReader.hpp index 65dcc0a1..1c58fe8e 100644 --- a/include/rfl/parsing/ViewReader.hpp +++ b/include/rfl/parsing/ViewReader.hpp @@ -10,6 +10,7 @@ #include "../Result.hpp" #include "../Tuple.hpp" #include "../internal/is_array.hpp" +#include "Parser_base.hpp" namespace rfl::parsing { diff --git a/include/rfl/xml/Reader.hpp b/include/rfl/xml/Reader.hpp index a7542b98..a5961bb6 100644 --- a/include/rfl/xml/Reader.hpp +++ b/include/rfl/xml/Reader.hpp @@ -1,20 +1,13 @@ #ifndef RFL_XML_READER_HPP_ #define RFL_XML_READER_HPP_ -#include #include -#include -#include #include #include -#include -#include #include #include #include -#include #include -#include #include "../Result.hpp" #include "../always_false.hpp" @@ -49,49 +42,13 @@ struct Reader { template static constexpr bool has_custom_constructor = false; - /// XML-only helper function. This is needed because XML distinguishes between - /// nodes and attributes. - static rfl::Result cast_as_node( - const std::variant& - _node_or_attribute) { - const auto cast = [](const auto& _n) -> Result { - using Type = std::remove_cvref_t; - if constexpr (std::is_same()) { - return _n; - } else { - return Error("Field '" + std::string(_n.name()) + "' is an attribute."); - } - }; - return std::visit(cast, _node_or_attribute); - } - rfl::Result get_field_from_array( - const size_t _idx, const InputArrayType& _arr) const noexcept { - const auto name = _arr.node_.name(); - size_t i = 0; - for (auto node = _arr.node_; node; node = node.next_sibling(name)) { - if (i == _idx) { - return InputVarType(node); - } - } - return rfl::Error("Index " + std::to_string(_idx) + " of of bounds."); - } + const size_t _idx, const InputArrayType& _arr) const noexcept; rfl::Result get_field_from_object( - const std::string& _name, const InputObjectType _obj) const noexcept { - const auto node = _obj.node_.child(_name.c_str()); - if (!node) { - return rfl::Error("Object contains no field named '" + _name + "'."); - } - return InputVarType(node); - } + const std::string& _name, const InputObjectType _obj) const noexcept; - bool is_empty(const InputVarType _var) const noexcept { - const auto wrap = [](const auto& _node) { return !_node; }; - return std::visit(cast_as_node, _var.node_or_attribute_) - .transform(wrap) - .value_or(false); - } + bool is_empty(const InputVarType _var) const noexcept; template rfl::Result to_basic_type(const InputVarType _var) const noexcept { @@ -128,10 +85,7 @@ struct Reader { } } - rfl::Result to_array(const InputVarType _var) const noexcept { - const auto wrap = [](const auto& _node) { return InputArrayType(_node); }; - return std::visit(cast_as_node, _var.node_or_attribute_).transform(wrap); - } + rfl::Result to_array(const InputVarType _var) const noexcept; template std::optional read_array(const ArrayReader& _array_reader, @@ -168,10 +122,7 @@ struct Reader { } rfl::Result to_object( - const InputVarType _var) const noexcept { - const auto wrap = [](const auto& _node) { return InputObjectType(_node); }; - return std::visit(cast_as_node, _var.node_or_attribute_).transform(wrap); - } + const InputVarType _var) const noexcept; template rfl::Result use_custom_constructor( diff --git a/include/rfl/xml/Writer.hpp b/include/rfl/xml/Writer.hpp index be9131ac..d56cca70 100644 --- a/include/rfl/xml/Writer.hpp +++ b/include/rfl/xml/Writer.hpp @@ -43,28 +43,15 @@ struct Writer { using OutputObjectType = XMLOutputObject; using OutputVarType = XMLOutputVar; - Writer(const Ref& _root, const std::string& _root_name) - : root_(_root), root_name_(_root_name) {} + Writer(const Ref& _root, const std::string& _root_name); - ~Writer() = default; + ~Writer(); - OutputArrayType array_as_root(const size_t _size) const noexcept { - auto node_child = - Ref::make(root_->append_child(root_name_.c_str())); - return OutputArrayType(root_name_, node_child); - } + OutputArrayType array_as_root(const size_t _size) const noexcept; - OutputObjectType object_as_root(const size_t _size) const noexcept { - auto node_child = - Ref::make(root_->append_child(root_name_.c_str())); - return OutputObjectType(node_child); - } + OutputObjectType object_as_root(const size_t _size) const noexcept; - OutputVarType null_as_root() const noexcept { - auto node_child = - Ref::make(root_->append_child(root_name_.c_str())); - return OutputVarType(node_child); - } + OutputVarType null_as_root() const noexcept; template OutputVarType value_as_root(const T& _var) const noexcept { @@ -76,30 +63,18 @@ struct Writer { } OutputArrayType add_array_to_array(const size_t _size, - OutputArrayType* _parent) const noexcept { - return *_parent; - } + OutputArrayType* _parent) const noexcept; - OutputArrayType add_array_to_object( - const std::string_view& _name, const size_t _size, - OutputObjectType* _parent) const noexcept { - return OutputArrayType(_name, _parent->node_); - } + OutputArrayType add_array_to_object(const std::string_view& _name, + const size_t _size, + OutputObjectType* _parent) const noexcept; - OutputObjectType add_object_to_array( - const size_t _size, OutputArrayType* _parent) const noexcept { - auto node_child = Ref::make( - _parent->node_->append_child(_parent->name_.data())); - return OutputObjectType(node_child); - } + OutputObjectType add_object_to_array(const size_t _size, + OutputArrayType* _parent) const noexcept; OutputObjectType add_object_to_object( const std::string_view& _name, const size_t _size, - OutputObjectType* _parent) const noexcept { - auto node_child = - Ref::make(_parent->node_->append_child(_name.data())); - return OutputObjectType(node_child); - } + OutputObjectType* _parent) const noexcept; template OutputVarType add_value_to_array(const T& _var, @@ -130,29 +105,15 @@ struct Writer { } } - OutputVarType add_null_to_array(OutputArrayType* _parent) const noexcept { - auto node_child = Ref::make( - _parent->node_->append_child(_parent->name_.data())); - return OutputVarType(node_child); - } + OutputVarType add_null_to_array(OutputArrayType* _parent) const noexcept; OutputVarType add_null_to_object( const std::string_view& _name, OutputObjectType* _parent, - const bool _is_attribute = false) const noexcept { - if (_is_attribute) { - return OutputVarType(_parent->node_); - } else if (_name == XML_CONTENT) { - return OutputVarType(_parent->node_); - } else { - auto node_child = - Ref::make(_parent->node_->append_child(_name.data())); - return OutputVarType(node_child); - } - } + const bool _is_attribute = false) const noexcept; - void end_array(OutputArrayType* _arr) const noexcept {} + void end_array(OutputArrayType* _arr) const noexcept; - void end_object(OutputObjectType* _obj) const noexcept {} + void end_object(OutputObjectType* _obj) const noexcept; private: template @@ -178,4 +139,4 @@ struct Writer { } // namespace xml } // namespace rfl -#endif // XML_PARSER_HPP_ +#endif // RFL_XML_WRITER_HPP_ diff --git a/src/reflectcpp_xml.cpp b/src/reflectcpp_xml.cpp new file mode 100644 index 00000000..a20066a3 --- /dev/null +++ b/src/reflectcpp_xml.cpp @@ -0,0 +1,33 @@ +/* + +MIT License + +Copyright (c) 2023-2024 Code17 GmbH + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +*/ + +// This file include all other source files, so that the user of the library +// don't need to add multiple source files into their build. +// Also, this speeds up compile time, compared to multiple separate .cpp files +// compilation. + +#include "rfl/xml/Reader.cpp" +#include "rfl/xml/Writer.cpp" diff --git a/src/rfl/xml/Reader.cpp b/src/rfl/xml/Reader.cpp new file mode 100644 index 00000000..c06ed912 --- /dev/null +++ b/src/rfl/xml/Reader.cpp @@ -0,0 +1,87 @@ +/* + +MIT License + +Copyright (c) 2023-2024 Code17 GmbH + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +*/ + +#include "rfl/xml/Reader.hpp" + +namespace rfl::xml { + +/// XML-only helper function. This is needed because XML distinguishes between +/// nodes and attributes. +static rfl::Result cast_as_node( + const std::variant& + _node_or_attribute) { + const auto cast = [](const auto& _n) -> Result { + using Type = std::remove_cvref_t; + if constexpr (std::is_same()) { + return _n; + } else { + return Error("Field '" + std::string(_n.name()) + "' is an attribute."); + } + }; + return std::visit(cast, _node_or_attribute); +} + +rfl::Result Reader::get_field_from_array( + const size_t _idx, const InputArrayType& _arr) const noexcept { + const auto name = _arr.node_.name(); + size_t i = 0; + for (auto node = _arr.node_; node; node = node.next_sibling(name)) { + if (i == _idx) { + return InputVarType(node); + } + } + return rfl::Error("Index " + std::to_string(_idx) + " of of bounds."); +} + +rfl::Result Reader::get_field_from_object( + const std::string& _name, const InputObjectType _obj) const noexcept { + const auto node = _obj.node_.child(_name.c_str()); + if (!node) { + return rfl::Error("Object contains no field named '" + _name + "'."); + } + return InputVarType(node); +} + +bool Reader::is_empty(const InputVarType _var) const noexcept { + const auto wrap = [](const auto& _node) { return !_node; }; + return std::visit(cast_as_node, _var.node_or_attribute_) + .transform(wrap) + .value_or(false); +} + +rfl::Result Reader::to_array( + const InputVarType _var) const noexcept { + const auto wrap = [](const auto& _node) { return InputArrayType(_node); }; + return std::visit(cast_as_node, _var.node_or_attribute_).transform(wrap); +} + +rfl::Result Reader::to_object( + const InputVarType _var) const noexcept { + const auto wrap = [](const auto& _node) { return InputObjectType(_node); }; + return std::visit(cast_as_node, _var.node_or_attribute_).transform(wrap); +} + +} // namespace rfl::xml diff --git a/src/rfl/xml/Writer.cpp b/src/rfl/xml/Writer.cpp new file mode 100644 index 00000000..35630207 --- /dev/null +++ b/src/rfl/xml/Writer.cpp @@ -0,0 +1,107 @@ +/* + +MIT License + +Copyright (c) 2023-2024 Code17 GmbH + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +*/ + +#include "rfl/xml/Writer.hpp" + +namespace rfl::xml { + +Writer::Writer(const Ref& _root, const std::string& _root_name) + : root_(_root), root_name_(_root_name) {} + +Writer::~Writer() = default; + +Writer::OutputArrayType Writer::array_as_root( + const size_t _size) const noexcept { + auto node_child = + Ref::make(root_->append_child(root_name_.c_str())); + return OutputArrayType(root_name_, node_child); +} + +Writer::OutputObjectType Writer::object_as_root( + const size_t _size) const noexcept { + auto node_child = + Ref::make(root_->append_child(root_name_.c_str())); + return OutputObjectType(node_child); +} + +Writer::OutputVarType Writer::null_as_root() const noexcept { + auto node_child = + Ref::make(root_->append_child(root_name_.c_str())); + return OutputVarType(node_child); +} + +Writer::OutputArrayType Writer::add_array_to_array( + const size_t _size, OutputArrayType* _parent) const noexcept { + return *_parent; +} + +Writer::OutputArrayType Writer::add_array_to_object( + const std::string_view& _name, const size_t _size, + OutputObjectType* _parent) const noexcept { + return OutputArrayType(_name, _parent->node_); +} + +Writer::OutputObjectType Writer::add_object_to_array( + const size_t _size, OutputArrayType* _parent) const noexcept { + auto node_child = Ref::make( + _parent->node_->append_child(_parent->name_.data())); + return OutputObjectType(node_child); +} + +Writer::OutputObjectType Writer::add_object_to_object( + const std::string_view& _name, const size_t _size, + OutputObjectType* _parent) const noexcept { + auto node_child = + Ref::make(_parent->node_->append_child(_name.data())); + return OutputObjectType(node_child); +} + +Writer::OutputVarType Writer::add_null_to_array( + OutputArrayType* _parent) const noexcept { + auto node_child = Ref::make( + _parent->node_->append_child(_parent->name_.data())); + return OutputVarType(node_child); +} + +Writer::OutputVarType Writer::add_null_to_object( + const std::string_view& _name, OutputObjectType* _parent, + const bool _is_attribute = false) const noexcept { + if (_is_attribute) { + return OutputVarType(_parent->node_); + } else if (_name == XML_CONTENT) { + return OutputVarType(_parent->node_); + } else { + auto node_child = + Ref::make(_parent->node_->append_child(_name.data())); + return OutputVarType(node_child); + } +} + +void Writer::end_array(OutputArrayType* _arr) const noexcept {} + +void Writer::end_object(OutputObjectType* _obj) const noexcept {} + +} // namespace rfl::xml From 86d68bc0732c8f98eccaf54866c89a1055612d3e Mon Sep 17 00:00:00 2001 From: George Evmenov Date: Sat, 5 Oct 2024 04:27:47 +0300 Subject: [PATCH 11/12] refactor heavy xml templates and move parts into cpp --- include/rfl/xml/Writer.hpp | 42 ++++++++++++-------------------------- src/rfl/xml/Writer.cpp | 39 ++++++++++++++++++++++++++++++++++- 2 files changed, 51 insertions(+), 30 deletions(-) diff --git a/include/rfl/xml/Writer.hpp b/include/rfl/xml/Writer.hpp index d56cca70..e0eb3972 100644 --- a/include/rfl/xml/Writer.hpp +++ b/include/rfl/xml/Writer.hpp @@ -1,26 +1,17 @@ #ifndef RFL_XML_WRITER_HPP_ #define RFL_XML_WRITER_HPP_ -#include -#include -#include -#include -#include #include #include #include -#include #include "../Ref.hpp" -#include "../Result.hpp" #include "../always_false.hpp" namespace rfl { namespace xml { struct Writer { - static constexpr const char* XML_CONTENT = "xml_content"; - struct XMLOutputArray { XMLOutputArray(const std::string_view& _name, const Ref& _node) @@ -56,10 +47,7 @@ struct Writer { template OutputVarType value_as_root(const T& _var) const noexcept { const auto str = to_string(_var); - auto node_child = - Ref::make(root_->append_child(root_name_.c_str())); - node_child->append_child(pugi::node_pcdata).set_value(str.c_str()); - return OutputVarType(node_child); + return value_as_root_impl(str); } OutputArrayType add_array_to_array(const size_t _size, @@ -80,10 +68,7 @@ struct Writer { OutputVarType add_value_to_array(const T& _var, OutputArrayType* _parent) const noexcept { const auto str = to_string(_var); - auto node_child = Ref::make( - _parent->node_->append_child(_parent->name_.data())); - node_child->append_child(pugi::node_pcdata).set_value(str.c_str()); - return OutputVarType(node_child); + return add_value_to_array_impl(str, _parent); } template @@ -91,18 +76,7 @@ struct Writer { const std::string_view& _name, const T& _var, OutputObjectType* _parent, const bool _is_attribute = false) const noexcept { const auto str = to_string(_var); - if (_is_attribute) { - _parent->node_->append_attribute(_name.data()) = str.c_str(); - return OutputVarType(_parent->node_); - } else if (_name == XML_CONTENT) { - _parent->node_->append_child(pugi::node_pcdata).set_value(str.c_str()); - return OutputVarType(_parent->node_); - } else { - auto node_child = - Ref::make(_parent->node_->append_child(_name.data())); - node_child->append_child(pugi::node_pcdata).set_value(str.c_str()); - return OutputVarType(node_child); - } + return add_value_to_object_impl(_name, str, _parent, _is_attribute); } OutputVarType add_null_to_array(OutputArrayType* _parent) const noexcept; @@ -130,6 +104,16 @@ struct Writer { } } + OutputVarType value_as_root_impl(const std::string& _str) const noexcept; + + OutputVarType add_value_to_array_impl( + const std::string& _str, OutputArrayType* _parent) const noexcept; + + OutputVarType add_value_to_object_impl( + const std::string_view& _name, const std::string& _str, + OutputObjectType* _parent, + const bool _is_attribute = false) const noexcept; + public: Ref root_; diff --git a/src/rfl/xml/Writer.cpp b/src/rfl/xml/Writer.cpp index 35630207..6667a8e9 100644 --- a/src/rfl/xml/Writer.cpp +++ b/src/rfl/xml/Writer.cpp @@ -26,8 +26,12 @@ SOFTWARE. #include "rfl/xml/Writer.hpp" +#include + namespace rfl::xml { +static constexpr const char* XML_CONTENT = "xml_content"; + Writer::Writer(const Ref& _root, const std::string& _root_name) : root_(_root), root_name_(_root_name) {} @@ -53,6 +57,14 @@ Writer::OutputVarType Writer::null_as_root() const noexcept { return OutputVarType(node_child); } +Writer::OutputVarType Writer::value_as_root_impl( + const std::string& _str) const noexcept { + auto node_child = + Ref::make(root_->append_child(root_name_.c_str())); + node_child->append_child(pugi::node_pcdata).set_value(_str.c_str()); + return OutputVarType(node_child); +} + Writer::OutputArrayType Writer::add_array_to_array( const size_t _size, OutputArrayType* _parent) const noexcept { return *_parent; @@ -64,6 +76,31 @@ Writer::OutputArrayType Writer::add_array_to_object( return OutputArrayType(_name, _parent->node_); } +Writer::OutputVarType Writer::add_value_to_array_impl( + const std::string& _str, OutputArrayType* _parent) const noexcept { + auto node_child = Ref::make( + _parent->node_->append_child(_parent->name_.data())); + node_child->append_child(pugi::node_pcdata).set_value(_str.c_str()); + return OutputVarType(node_child); +} + +Writer::OutputVarType Writer::add_value_to_object_impl( + const std::string_view& _name, const std::string& _str, + OutputObjectType* _parent, const bool _is_attribute) const noexcept { + if (_is_attribute) { + _parent->node_->append_attribute(_name.data()) = _str.c_str(); + return OutputVarType(_parent->node_); + } else if (_name == XML_CONTENT) { + _parent->node_->append_child(pugi::node_pcdata).set_value(_str.c_str()); + return OutputVarType(_parent->node_); + } else { + auto node_child = + Ref::make(_parent->node_->append_child(_name.data())); + node_child->append_child(pugi::node_pcdata).set_value(_str.c_str()); + return OutputVarType(node_child); + } +} + Writer::OutputObjectType Writer::add_object_to_array( const size_t _size, OutputArrayType* _parent) const noexcept { auto node_child = Ref::make( @@ -88,7 +125,7 @@ Writer::OutputVarType Writer::add_null_to_array( Writer::OutputVarType Writer::add_null_to_object( const std::string_view& _name, OutputObjectType* _parent, - const bool _is_attribute = false) const noexcept { + const bool _is_attribute) const noexcept { if (_is_attribute) { return OutputVarType(_parent->node_); } else if (_name == XML_CONTENT) { From e8e7ee07870726a9f9bd5ff78be3f67140b1bf35 Mon Sep 17 00:00:00 2001 From: George Evmenov Date: Mon, 7 Oct 2024 11:41:40 +0300 Subject: [PATCH 12/12] move all formats Writer/Reader into cpp (trivial changes only, add missing include paths in CMake) --- CMakeLists.txt | 23 ++++++- README.md | 3 +- include/rfl/bson/Reader.hpp | 65 ++---------------- include/rfl/bson/Writer.hpp | 90 ++++--------------------- include/rfl/bson/write.hpp | 2 +- include/rfl/cbor/Reader.hpp | 107 +++--------------------------- include/rfl/cbor/Writer.hpp | 70 +++++--------------- include/rfl/flexbuf/Reader.hpp | 37 ++--------- include/rfl/flexbuf/Writer.hpp | 71 +++++--------------- include/rfl/json/Reader.hpp | 2 +- include/rfl/json/Writer.hpp | 2 +- include/rfl/json/write.hpp | 2 +- include/rfl/msgpack/Reader.hpp | 43 ++---------- include/rfl/msgpack/Writer.hpp | 69 +++++--------------- include/rfl/toml/Reader.hpp | 41 ++---------- include/rfl/toml/Writer.hpp | 60 +++++------------ include/rfl/xml/write.hpp | 2 +- include/rfl/yaml/Reader.hpp | 39 ++--------- include/rfl/yaml/Writer.hpp | 76 ++++++--------------- src/reflectcpp_bson.cpp | 33 ++++++++++ src/reflectcpp_cbor.cpp | 33 ++++++++++ src/reflectcpp_flexbuf.cpp | 33 ++++++++++ src/reflectcpp_msgpack.cpp | 33 ++++++++++ src/reflectcpp_toml.cpp | 33 ++++++++++ src/reflectcpp_yaml.cpp | 33 ++++++++++ src/rfl/bson/Reader.cpp | 72 ++++++++++++++++++++ src/rfl/bson/Writer.cpp | 102 +++++++++++++++++++++++++++++ src/rfl/cbor/Reader.cpp | 116 +++++++++++++++++++++++++++++++++ src/rfl/cbor/Writer.cpp | 83 +++++++++++++++++++++++ src/rfl/flexbuf/Reader.cpp | 44 +++++++++++++ src/rfl/flexbuf/Writer.cpp | 88 +++++++++++++++++++++++++ src/rfl/msgpack/Reader.cpp | 50 ++++++++++++++ src/rfl/msgpack/Writer.cpp | 78 ++++++++++++++++++++++ src/rfl/toml/Reader.cpp | 44 +++++++++++++ src/rfl/toml/Writer.cpp | 62 ++++++++++++++++++ src/rfl/yaml/Reader.cpp | 42 ++++++++++++ src/rfl/yaml/Writer.cpp | 85 ++++++++++++++++++++++++ 37 files changed, 1235 insertions(+), 633 deletions(-) create mode 100644 src/reflectcpp_bson.cpp create mode 100644 src/reflectcpp_cbor.cpp create mode 100644 src/reflectcpp_flexbuf.cpp create mode 100644 src/reflectcpp_msgpack.cpp create mode 100644 src/reflectcpp_toml.cpp create mode 100644 src/reflectcpp_yaml.cpp create mode 100644 src/rfl/bson/Reader.cpp create mode 100644 src/rfl/bson/Writer.cpp create mode 100644 src/rfl/cbor/Reader.cpp create mode 100644 src/rfl/cbor/Writer.cpp create mode 100644 src/rfl/flexbuf/Reader.cpp create mode 100644 src/rfl/flexbuf/Writer.cpp create mode 100644 src/rfl/msgpack/Reader.cpp create mode 100644 src/rfl/msgpack/Writer.cpp create mode 100644 src/rfl/toml/Reader.cpp create mode 100644 src/rfl/toml/Writer.cpp create mode 100644 src/rfl/yaml/Reader.cpp create mode 100644 src/rfl/yaml/Writer.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 97862276..e56105ce 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -95,14 +95,20 @@ if (REFLECTCPP_JSON) endif () endif () -set_target_properties(reflectcpp PROPERTIES LINKER_LANGUAGE CXX) - if (REFLECTCPP_BSON) + list(APPEND REFLECT_CPP_SOURCES + src/reflectcpp_bson.cpp + ) find_package(bson-1.0 CONFIG REQUIRED) target_link_libraries(reflectcpp PRIVATE $,mongo::bson_static,mongo::bson_shared>) endif () if (REFLECTCPP_CBOR) + list(APPEND REFLECT_CPP_SOURCES + src/reflectcpp_cbor.cpp + ) + target_include_directories(reflectcpp SYSTEM PRIVATE "${VCPKG_INSTALLED_DIR}/${VCPKG_TARGET_TRIPLET}/include") + target_include_directories(reflectcpp SYSTEM PRIVATE "${VCPKG_INSTALLED_DIR}/${VCPKG_TARGET_TRIPLET}/include/tinycbor") if (MSVC) target_link_libraries(reflectcpp PRIVATE "${VCPKG_INSTALLED_DIR}/${VCPKG_TARGET_TRIPLET}/lib/tinycbor${CMAKE_STATIC_LIBRARY_SUFFIX}") else () @@ -111,11 +117,17 @@ if (REFLECTCPP_CBOR) endif () if (REFLECTCPP_FLEXBUFFERS) + list(APPEND REFLECT_CPP_SOURCES + src/reflectcpp_flexbuf.cpp + ) find_package(flatbuffers CONFIG REQUIRED) target_link_libraries(reflectcpp INTERFACE flatbuffers::flatbuffers) endif () if (REFLECTCPP_MSGPACK) + list(APPEND REFLECT_CPP_SOURCES + src/reflectcpp_msgpack.cpp + ) find_package(msgpack-c CONFIG REQUIRED) if (MSVC) target_link_libraries(reflectcpp PRIVATE "${VCPKG_INSTALLED_DIR}/${VCPKG_TARGET_TRIPLET}/lib/msgpack-c${CMAKE_STATIC_LIBRARY_SUFFIX}") @@ -125,6 +137,9 @@ if (REFLECTCPP_MSGPACK) endif () if (REFLECTCPP_TOML) + list(APPEND REFLECT_CPP_SOURCES + src/reflectcpp_toml.cpp + ) if (MSVC) target_link_libraries(reflectcpp PRIVATE "${VCPKG_INSTALLED_DIR}/${VCPKG_TARGET_TRIPLET}/lib/tomlplusplus${CMAKE_STATIC_LIBRARY_SUFFIX}") else () @@ -141,10 +156,14 @@ if (REFLECTCPP_XML) endif () if (REFLECTCPP_YAML) + list(APPEND REFLECT_CPP_SOURCES + src/reflectcpp_yaml.cpp + ) find_package(yaml-cpp CONFIG REQUIRED) target_link_libraries(reflectcpp INTERFACE yaml-cpp::yaml-cpp) endif () +set_target_properties(reflectcpp PROPERTIES LINKER_LANGUAGE CXX) target_sources(reflectcpp PRIVATE ${REFLECT_CPP_SOURCES}) if (REFLECTCPP_BUILD_TESTS) diff --git a/README.md b/README.md index 7a899d09..a214a2d5 100644 --- a/README.md +++ b/README.md @@ -532,7 +532,8 @@ and also add `src/reflectcpp.cpp` and `src/reflectcpp_json.cpp` and `src/yyjson. If you want to link to your own version of YYJSON, then only copy `src/reflectcpp.cpp` and `src/reflectcpp_json.cpp`. If you don't need JSON support, then only copy `src/reflectcpp.cpp`. -If you need support for other serialization formats like flexbuffers or XML, you should also include and link the respective libraries, as listed in the section on serialization formats. +If you need support for other serialization formats like flexbuffers or XML, you should also add `src/reflectcpp_.cpp` +and include and link the respective libraries, as listed in the section on serialization formats. ### Option 2: Compilation using cmake diff --git a/include/rfl/bson/Reader.hpp b/include/rfl/bson/Reader.hpp index 0cff0554..ffe29a44 100644 --- a/include/rfl/bson/Reader.hpp +++ b/include/rfl/bson/Reader.hpp @@ -50,49 +50,12 @@ struct Reader { }); rfl::Result get_field_from_array( - const size_t _idx, const InputArrayType& _arr) const noexcept { - bson_t b; - bson_iter_t iter; - const auto doc = _arr.val_->value.v_doc; - if (bson_init_static(&b, doc.data, doc.data_len)) { - if (bson_iter_init(&iter, &b)) { - size_t i = 0; - while (bson_iter_next(&iter)) { - if (i == _idx) { - return to_input_var(&iter); - } - ++i; - } - } else { - return Error("Could not init the array iteration."); - } - } else { - return Error("Could not init array."); - } - return Error("Index " + std::to_string(_idx) + " of of bounds."); - } + const size_t _idx, const InputArrayType& _arr) const noexcept; rfl::Result get_field_from_object( - const std::string& _name, const InputObjectType& _obj) const noexcept { - bson_t b; - bson_iter_t iter; - const auto doc = _obj.val_->value.v_doc; - if (bson_init_static(&b, doc.data, doc.data_len)) { - if (bson_iter_init(&iter, &b)) { - while (bson_iter_next(&iter)) { - auto key = std::string(bson_iter_key(&iter)); - if (key == _name) { - return to_input_var(&iter); - } - } - } - } - return Error("No field named '" + _name + "' was found."); - } + const std::string& _name, const InputObjectType& _obj) const noexcept; - bool is_empty(const InputVarType& _var) const noexcept { - return _var.val_->value_type == BSON_TYPE_NULL; - } + bool is_empty(const InputVarType& _var) const noexcept; template rfl::Result to_basic_type(const InputVarType& _var) const noexcept { @@ -159,13 +122,7 @@ struct Reader { } rfl::Result to_array( - const InputVarType& _var) const noexcept { - const auto btype = _var.val_->value_type; - if (btype != BSON_TYPE_ARRAY && btype != BSON_TYPE_DOCUMENT) { - return Error("Could not cast to an array."); - } - return InputArrayType{_var.val_}; - } + const InputVarType& _var) const noexcept; template std::optional read_array(const ArrayReader& _array_reader, @@ -212,13 +169,7 @@ struct Reader { } rfl::Result to_object( - const InputVarType& _var) const noexcept { - const auto btype = _var.val_->value_type; - if (btype != BSON_TYPE_DOCUMENT) { - return Error("Could not cast to a document."); - } - return InputObjectType{_var.val_}; - } + const InputVarType& _var) const noexcept; template rfl::Result use_custom_constructor( @@ -231,12 +182,10 @@ struct Reader { } private: - InputVarType to_input_var(bson_iter_t* _iter) const noexcept { - return InputVarType{bson_iter_value(_iter)}; - } + InputVarType to_input_var(bson_iter_t* _iter) const noexcept; }; } // namespace bson } // namespace rfl -#endif // JSON_PARSER_HPP_ +#endif diff --git a/include/rfl/bson/Writer.hpp b/include/rfl/bson/Writer.hpp index 80a7d730..dc10febd 100644 --- a/include/rfl/bson/Writer.hpp +++ b/include/rfl/bson/Writer.hpp @@ -62,23 +62,15 @@ class Writer { using OutputObjectType = BSONOutputObject; using OutputVarType = BSONOutputVar; - Writer(bson_t* _doc) : doc_(_doc) {} + Writer(bson_t* _doc); - ~Writer() = default; + ~Writer(); - OutputArrayType array_as_root(const size_t _size) const noexcept { - bson_array_builder_t* val = bson_array_builder_new(); - return OutputArrayType(val, IsRoot{}); - } + OutputArrayType array_as_root(const size_t _size) const noexcept; - OutputObjectType object_as_root(const size_t _size) const noexcept { - return OutputObjectType(doc_, IsRoot{}); - } + OutputObjectType object_as_root(const size_t _size) const noexcept; - OutputVarType null_as_root() const noexcept { - // Appears to be unsupported by the BSON C API. - return OutputVarType{}; - } + OutputVarType null_as_root() const noexcept; template OutputVarType value_as_root(const T& _var) const noexcept { @@ -88,38 +80,18 @@ class Writer { } OutputArrayType add_array_to_array(const size_t _size, - OutputArrayType* _parent) const noexcept { - bson_array_builder_t* val; - bson_array_builder_append_array_builder_begin(_parent->val_, &val); - return OutputArrayType(val, IsArray{_parent->val_}); - } + OutputArrayType* _parent) const noexcept; OutputArrayType add_array_to_object( const std::string_view& _name, const size_t _size, - OutputObjectType* _parent) const noexcept { - bson_array_builder_t* val; - bson_append_array_builder_begin(_parent->val_, _name.data(), - static_cast(_name.size()), &val); - return OutputArrayType(val, IsObject{_parent->val_}); - } + OutputObjectType* _parent) const noexcept; OutputObjectType add_object_to_array( - const size_t _size, OutputArrayType* _parent) const noexcept { - subdocs_->emplace_back(rfl::Box()); - bson_array_builder_append_document_begin(_parent->val_, - &(subdocs_->back()->val_)); - return OutputObjectType(&subdocs_->back()->val_, IsArray{_parent->val_}); - } + const size_t _size, OutputArrayType* _parent) const noexcept; OutputObjectType add_object_to_object( const std::string_view& _name, const size_t _size, - OutputObjectType* _parent) const noexcept { - subdocs_->emplace_back(rfl::Box()); - bson_append_document_begin(_parent->val_, _name.data(), - static_cast(_name.size()), - &(subdocs_->back()->val_)); - return OutputObjectType(&subdocs_->back()->val_, IsObject{_parent->val_}); - } + OutputObjectType* _parent) const noexcept; template OutputVarType add_value_to_array(const T& _var, @@ -183,48 +155,14 @@ class Writer { return OutputVarType{}; } - OutputVarType add_null_to_array(OutputArrayType* _parent) const noexcept { - bson_array_builder_append_null(_parent->val_); - return OutputVarType{}; - } + OutputVarType add_null_to_array(OutputArrayType* _parent) const noexcept; OutputVarType add_null_to_object(const std::string_view& _name, - OutputObjectType* _parent) const noexcept { - bson_append_null(_parent->val_, _name.data(), - static_cast(_name.size())); - return OutputVarType{}; - } + OutputObjectType* _parent) const noexcept; - void end_array(OutputArrayType* _arr) const noexcept { - const auto handle = [&](const auto _parent) { - using Type = std::remove_cvref_t; - if constexpr (std::is_same()) { - bson_array_builder_append_array_builder_end(_parent.ptr_, _arr->val_); - } else if constexpr (std::is_same()) { - bson_append_array_builder_end(_parent.ptr_, _arr->val_); - } else if constexpr (std::is_same()) { - bson_array_builder_build(_arr->val_, doc_); - } else { - static_assert(rfl::always_false_v, "Unsupported type."); - } - }; - std::visit(handle, _arr->parent_); - } + void end_array(OutputArrayType* _arr) const noexcept; - void end_object(OutputObjectType* _obj) const noexcept { - const auto handle = [&](const auto _parent) { - using Type = std::remove_cvref_t; - if constexpr (std::is_same()) { - bson_array_builder_append_document_end(_parent.ptr_, _obj->val_); - } else if constexpr (std::is_same()) { - bson_append_document_end(_parent.ptr_, _obj->val_); - } else if constexpr (std::is_same()) { - } else { - static_assert(rfl::always_false_v, "Unsupported type."); - } - }; - std::visit(handle, _obj->parent_); - } + void end_object(OutputObjectType* _obj) const noexcept; private: /// Pointer to the main document. In BSON, documents are what are usually @@ -238,4 +176,4 @@ class Writer { } // namespace bson } // namespace rfl -#endif // BSON_PARSER_HPP_ +#endif diff --git a/include/rfl/bson/write.hpp b/include/rfl/bson/write.hpp index db94cb88..eb827b54 100644 --- a/include/rfl/bson/write.hpp +++ b/include/rfl/bson/write.hpp @@ -62,4 +62,4 @@ std::ostream& write(const auto& _obj, std::ostream& _stream) noexcept { } // namespace bson } // namespace rfl -#endif // BSON_PARSER_HPP_ +#endif diff --git a/include/rfl/cbor/Reader.hpp b/include/rfl/cbor/Reader.hpp index 5b6ebddc..cee4f084 100644 --- a/include/rfl/cbor/Reader.hpp +++ b/include/rfl/cbor/Reader.hpp @@ -41,68 +41,12 @@ struct Reader { }); rfl::Result get_field_from_array( - const size_t _idx, const InputArrayType& _arr) const noexcept { - InputVarType var; - auto err = cbor_value_enter_container(&_arr.val_, &var.val_); - if (err != CborNoError && err != CborErrorOutOfMemory) { - return Error(cbor_error_string(err)); - } - size_t length = 0; - err = cbor_value_get_array_length(&_arr.val_, &length); - if (err != CborNoError && err != CborErrorOutOfMemory) { - return Error(cbor_error_string(err)); - } - if (_idx >= length) { - return Error("Index " + std::to_string(_idx) + " of of bounds."); - } - for (size_t i = 0; i < _idx; ++i) { - err = cbor_value_advance(&var.val_); - if (err != CborNoError && err != CborErrorOutOfMemory) { - return Error(cbor_error_string(err)); - } - } - return var; - } + const size_t _idx, const InputArrayType& _arr) const noexcept; rfl::Result get_field_from_object( - const std::string& _name, const InputObjectType& _obj) const noexcept { - InputVarType var; - auto buffer = std::string(); - auto err = cbor_value_enter_container(&_obj.val_, &var.val_); - if (err != CborNoError) { - return Error(cbor_error_string(err)); - } - size_t length = 0; - err = cbor_value_get_map_length(&_obj.val_, &length); - if (err != CborNoError) { - return Error(cbor_error_string(err)); - } - for (size_t i = 0; i < length; ++i) { - if (!cbor_value_is_text_string(&var.val_)) { - return Error("Expected the key to be a string value."); - } - err = get_string(&var.val_, &buffer); - if (err != CborNoError) { - return Error(cbor_error_string(err)); - } - err = cbor_value_advance(&var.val_); - if (err != CborNoError) { - return Error(cbor_error_string(err)); - } - if (_name == buffer) { - return var; - } - err = cbor_value_advance(&var.val_); - if (err != CborNoError) { - return Error(cbor_error_string(err)); - } - } - return Error("No field named '" + _name + "' was found."); - } + const std::string& _name, const InputObjectType& _obj) const noexcept; - bool is_empty(const InputVarType& _var) const noexcept { - return cbor_value_is_null(&_var.val_); - } + bool is_empty(const InputVarType& _var) const noexcept; template rfl::Result to_basic_type(const InputVarType& _var) const noexcept { @@ -171,20 +115,10 @@ struct Reader { } rfl::Result to_array( - const InputVarType& _var) const noexcept { - if (!cbor_value_is_array(&_var.val_)) { - return Error("Could not cast to an array."); - } - return InputArrayType{_var.val_}; - } + const InputVarType& _var) const noexcept; rfl::Result to_object( - const InputVarType& _var) const noexcept { - if (!cbor_value_is_map(&_var.val_)) { - return Error("Could not cast to an object."); - } - return InputObjectType{_var.val_}; - } + const InputVarType& _var) const noexcept; template std::optional read_array(const ArrayReader& _array_reader, @@ -259,38 +193,13 @@ struct Reader { private: CborError get_bytestring(const CborValue* _ptr, - rfl::Bytestring* _str) const noexcept { - size_t length = 0; - auto err = cbor_value_get_string_length(_ptr, &length); - if (err != CborNoError && err != CborErrorOutOfMemory) { - return err; - } - _str->resize(length); - if (length > 0) { - return cbor_value_copy_byte_string( - _ptr, reinterpret_cast(&((*_str)[0])), &length, NULL); - } else { - return CborNoError; - } - } + rfl::Bytestring* _str) const noexcept; CborError get_string(const CborValue* _ptr, - std::string* _str) const noexcept { - size_t length = 0; - auto err = cbor_value_get_string_length(_ptr, &length); - if (err != CborNoError && err != CborErrorOutOfMemory) { - return err; - } - _str->resize(length); - if (length > 0) { - return cbor_value_copy_text_string(_ptr, &((*_str)[0]), &length, NULL); - } else { - return CborNoError; - } - } + std::string* _str) const noexcept; }; } // namespace cbor } // namespace rfl -#endif // JSON_PARSER_HPP_ +#endif diff --git a/include/rfl/cbor/Writer.hpp b/include/rfl/cbor/Writer.hpp index 87f06bb6..e6f9c51a 100644 --- a/include/rfl/cbor/Writer.hpp +++ b/include/rfl/cbor/Writer.hpp @@ -40,22 +40,15 @@ class Writer { using OutputObjectType = CBOROutputObject; using OutputVarType = CBOROutputVar; - Writer(CborEncoder* _encoder) : encoder_(_encoder) {} + Writer(CborEncoder* _encoder); - ~Writer() = default; + ~Writer(); - OutputArrayType array_as_root(const size_t _size) const noexcept { - return new_array(_size, encoder_); - } + OutputArrayType array_as_root(const size_t _size) const noexcept; - OutputObjectType object_as_root(const size_t _size) const noexcept { - return new_object(_size, encoder_); - } + OutputObjectType object_as_root(const size_t _size) const noexcept; - OutputVarType null_as_root() const noexcept { - cbor_encode_null(encoder_); - return OutputVarType{}; - } + OutputVarType null_as_root() const noexcept; template OutputVarType value_as_root(const T& _var) const noexcept { @@ -63,28 +56,18 @@ class Writer { } OutputArrayType add_array_to_array(const size_t _size, - OutputArrayType* _parent) const noexcept { - return new_array(_size, _parent->encoder_); - } + OutputArrayType* _parent) const noexcept; OutputArrayType add_array_to_object( const std::string_view& _name, const size_t _size, - OutputObjectType* _parent) const noexcept { - cbor_encode_text_string(_parent->encoder_, _name.data(), _name.size()); - return new_array(_size, _parent->encoder_); - } + OutputObjectType* _parent) const noexcept; - OutputObjectType add_object_to_array( - const size_t _size, OutputArrayType* _parent) const noexcept { - return new_object(_size, _parent->encoder_); - } + OutputObjectType add_object_to_array(const size_t _size, + OutputArrayType* _parent) const noexcept; OutputObjectType add_object_to_object( const std::string_view& _name, const size_t _size, - OutputObjectType* _parent) const noexcept { - cbor_encode_text_string(_parent->encoder_, _name.data(), _name.size()); - return new_object(_size, _parent->encoder_); - } + OutputObjectType* _parent) const noexcept; template OutputVarType add_value_to_array(const T& _var, @@ -100,40 +83,21 @@ class Writer { return new_value(_var, _parent->encoder_); } - OutputVarType add_null_to_array(OutputArrayType* _parent) const noexcept { - cbor_encode_null(_parent->encoder_); - return OutputVarType{}; - } + OutputVarType add_null_to_array(OutputArrayType* _parent) const noexcept; OutputVarType add_null_to_object(const std::string_view& _name, - OutputObjectType* _parent) const noexcept { - cbor_encode_text_string(_parent->encoder_, _name.data(), _name.size()); - cbor_encode_null(_parent->encoder_); - return OutputVarType{}; - } + OutputObjectType* _parent) const noexcept; - void end_array(OutputArrayType* _arr) const noexcept { - cbor_encoder_close_container(_arr->parent_, _arr->encoder_); - } + void end_array(OutputArrayType* _arr) const noexcept; - void end_object(OutputObjectType* _obj) const noexcept { - cbor_encoder_close_container(_obj->parent_, _obj->encoder_); - } + void end_object(OutputObjectType* _obj) const noexcept; private: OutputArrayType new_array(const size_t _size, - CborEncoder* _parent) const noexcept { - subencoders_->emplace_back(rfl::Box::make()); - cbor_encoder_create_array(_parent, subencoders_->back().get(), _size); - return OutputArrayType{subencoders_->back().get(), _parent}; - } + CborEncoder* _parent) const noexcept; OutputObjectType new_object(const size_t _size, - CborEncoder* _parent) const noexcept { - subencoders_->emplace_back(rfl::Box::make()); - cbor_encoder_create_map(_parent, subencoders_->back().get(), _size); - return OutputObjectType{subencoders_->back().get(), _parent}; - } + CborEncoder* _parent) const noexcept; template OutputVarType new_value(const T& _var, CborEncoder* _parent) const noexcept { @@ -166,4 +130,4 @@ class Writer { } // namespace cbor } // namespace rfl -#endif // CBOR_PARSER_HPP_ +#endif diff --git a/include/rfl/flexbuf/Reader.hpp b/include/rfl/flexbuf/Reader.hpp index a1f8cfe5..c554fc69 100644 --- a/include/rfl/flexbuf/Reader.hpp +++ b/include/rfl/flexbuf/Reader.hpp @@ -44,28 +44,12 @@ struct Reader { static constexpr bool has_custom_constructor = has_from_flexbuf::value; rfl::Result get_field_from_array( - const size_t _idx, const InputArrayType& _arr) const noexcept { - if (_idx >= _arr.size()) { - return rfl::Error("Index " + std::to_string(_idx) + " of of bounds."); - } - return _arr[_idx]; - } + const size_t _idx, const InputArrayType& _arr) const noexcept; rfl::Result get_field_from_object( - const std::string& _name, const InputObjectType& _obj) const noexcept { - const auto keys = _obj.Keys(); - for (size_t i = 0; i < keys.size(); ++i) { - if (_name == keys[i].AsString().c_str()) { - return _obj.Values()[i]; - } - } - return rfl::Error("Map does not contain any element called '" + _name + - "'."); - } + const std::string& _name, const InputObjectType& _obj) const noexcept; - bool is_empty(const InputVarType& _var) const noexcept { - return _var.IsNull(); - } + bool is_empty(const InputVarType& _var) const noexcept; template rfl::Result to_basic_type(const InputVarType& _var) const noexcept { @@ -130,21 +114,10 @@ struct Reader { return std::nullopt; } - rfl::Result to_array( - const InputVarType& _var) const noexcept { - if (!_var.IsVector()) { - return rfl::Error("Could not cast to Vector."); - } - return _var.AsVector(); - } + rfl::Result to_array(const InputVarType& _var) const noexcept; rfl::Result to_object( - const InputVarType& _var) const noexcept { - if (!_var.IsMap()) { - return rfl::Error("Could not cast to Map!"); - } - return _var.AsMap(); - } + const InputVarType& _var) const noexcept; template rfl::Result use_custom_constructor( diff --git a/include/rfl/flexbuf/Writer.hpp b/include/rfl/flexbuf/Writer.hpp index 16e66725..d43a00ae 100644 --- a/include/rfl/flexbuf/Writer.hpp +++ b/include/rfl/flexbuf/Writer.hpp @@ -38,22 +38,15 @@ struct Writer { using OutputObjectType = OutputObject; using OutputVarType = OutputVar; - Writer(const Ref& _fbb) : fbb_(_fbb) {} + Writer(const Ref& _fbb); - ~Writer() = default; + ~Writer(); - OutputArrayType array_as_root(const size_t _size) const noexcept { - return new_array(); - } + OutputArrayType array_as_root(const size_t _size) const noexcept; - OutputObjectType object_as_root(const size_t _size) const noexcept { - return new_object(); - } + OutputObjectType object_as_root(const size_t _size) const noexcept; - OutputVarType null_as_root() const noexcept { - fbb_->Null(); - return OutputVarType{}; - } + OutputVarType null_as_root() const noexcept; template OutputVarType value_as_root(const T& _var) const noexcept { @@ -61,26 +54,18 @@ struct Writer { } OutputArrayType add_array_to_array(const size_t _size, - OutputArrayType* _parent) const noexcept { - return new_array(); - } + OutputArrayType* _parent) const noexcept; OutputArrayType add_array_to_object( const std::string_view& _name, const size_t _size, - OutputObjectType* _parent) const noexcept { - return new_array(_name); - } + OutputObjectType* _parent) const noexcept; OutputObjectType add_object_to_array( - const size_t _size, OutputArrayType* _parent) const noexcept { - return new_object(); - } + const size_t _size, OutputArrayType* _parent) const noexcept; OutputObjectType add_object_to_object( const std::string_view& _name, const size_t _size, - OutputObjectType* _parent) const noexcept { - return new_object(_name); - } + OutputObjectType* _parent) const noexcept; template OutputVarType add_value_to_array(const T& _var, @@ -95,24 +80,14 @@ struct Writer { return insert_value(_name, _var); } - OutputVarType add_null_to_array(OutputArrayType* _parent) const noexcept { - fbb_->Null(); - return OutputVarType{}; - } + OutputVarType add_null_to_array(OutputArrayType* _parent) const noexcept; OutputVarType add_null_to_object(const std::string_view& _name, - OutputObjectType* _parent) const noexcept { - fbb_->Null(_name.data()); - return OutputVarType{}; - } + OutputObjectType* _parent) const noexcept; - void end_array(OutputArrayType* _arr) const noexcept { - fbb_->EndVector(_arr->start_, false, false); - } + void end_array(OutputArrayType* _arr) const noexcept; - void end_object(OutputObjectType* _obj) const noexcept { - fbb_->EndMap(_obj->start_); - } + void end_object(OutputObjectType* _obj) const noexcept; private: template @@ -154,25 +129,13 @@ struct Writer { return OutputVarType{}; } - OutputArrayType new_array(const std::string_view& _name) const noexcept { - const auto start = fbb_->StartVector(_name.data()); - return OutputArrayType{start}; - } + OutputArrayType new_array(const std::string_view& _name) const noexcept; - OutputArrayType new_array() const noexcept { - const auto start = fbb_->StartVector(); - return OutputArrayType{start}; - } + OutputArrayType new_array() const noexcept; - OutputObjectType new_object(const std::string_view& _name) const noexcept { - const auto start = fbb_->StartMap(_name.data()); - return OutputObjectType{start}; - } + OutputObjectType new_object(const std::string_view& _name) const noexcept; - OutputObjectType new_object() const noexcept { - const auto start = fbb_->StartMap(); - return OutputObjectType{start}; - } + OutputObjectType new_object() const noexcept; private: Ref fbb_; diff --git a/include/rfl/json/Reader.hpp b/include/rfl/json/Reader.hpp index 60fb0de0..ef54f2bd 100644 --- a/include/rfl/json/Reader.hpp +++ b/include/rfl/json/Reader.hpp @@ -139,4 +139,4 @@ struct Reader { } // namespace json } // namespace rfl -#endif // JSON_PARSER_HPP_ +#endif diff --git a/include/rfl/json/Writer.hpp b/include/rfl/json/Writer.hpp index 2dcd6ddb..6b02c83e 100644 --- a/include/rfl/json/Writer.hpp +++ b/include/rfl/json/Writer.hpp @@ -129,4 +129,4 @@ class Writer { } // namespace json } // namespace rfl -#endif // JSON_PARSER_HPP_ +#endif diff --git a/include/rfl/json/write.hpp b/include/rfl/json/write.hpp index cf8f9688..4cc85ab4 100644 --- a/include/rfl/json/write.hpp +++ b/include/rfl/json/write.hpp @@ -53,4 +53,4 @@ std::ostream& write(const auto& _obj, std::ostream& _stream, } // namespace json } // namespace rfl -#endif // JSON_PARSER_HPP_ +#endif diff --git a/include/rfl/msgpack/Reader.hpp b/include/rfl/msgpack/Reader.hpp index 1c670449..36475ae4 100644 --- a/include/rfl/msgpack/Reader.hpp +++ b/include/rfl/msgpack/Reader.hpp @@ -27,33 +27,12 @@ struct Reader { }); rfl::Result get_field_from_array( - const size_t _idx, const InputArrayType _arr) const noexcept { - if (_idx >= _arr.size) { - return rfl::Error("Index " + std::to_string(_idx) + " of of bounds."); - } - return _arr.ptr[_idx]; - } + const size_t _idx, const InputArrayType _arr) const noexcept; rfl::Result get_field_from_object( - const std::string& _name, const InputObjectType& _obj) const noexcept { - for (uint32_t i = 0; i < _obj.size; ++i) { - const auto& key = _obj.ptr[i].key; - if (key.type != MSGPACK_OBJECT_STR) { - return Error("Key in element " + std::to_string(i) + - " was not a string."); - } - const auto current_name = - std::string_view(key.via.str.ptr, key.via.str.size); - if (_name == current_name) { - return _obj.ptr[i].val; - } - } - return Error("No field named '" + _name + "' was found."); - } + const std::string& _name, const InputObjectType& _obj) const noexcept ; - bool is_empty(const InputVarType& _var) const noexcept { - return _var.type == MSGPACK_OBJECT_NIL; - } + bool is_empty(const InputVarType& _var) const noexcept; template rfl::Result to_basic_type(const InputVarType& _var) const noexcept { @@ -96,20 +75,10 @@ struct Reader { } rfl::Result to_array( - const InputVarType& _var) const noexcept { - if (_var.type != MSGPACK_OBJECT_ARRAY) { - return Error("Could not cast to an array."); - } - return _var.via.array; - } + const InputVarType& _var) const noexcept; rfl::Result to_object( - const InputVarType& _var) const noexcept { - if (_var.type != MSGPACK_OBJECT_MAP) { - return Error("Could not cast to a map."); - } - return _var.via.map; - } + const InputVarType& _var) const noexcept; template std::optional read_array(const ArrayReader& _array_reader, @@ -153,4 +122,4 @@ struct Reader { } // namespace msgpack } // namespace rfl -#endif // JSON_PARSER_HPP_ +#endif diff --git a/include/rfl/msgpack/Writer.hpp b/include/rfl/msgpack/Writer.hpp index 8cdfa7b2..82b47d84 100644 --- a/include/rfl/msgpack/Writer.hpp +++ b/include/rfl/msgpack/Writer.hpp @@ -32,53 +32,32 @@ class Writer { using OutputObjectType = MsgpackOutputObject; using OutputVarType = MsgpackOutputVar; - Writer(msgpack_packer* _pk) : pk_(_pk) {} + Writer(msgpack_packer* _pk); - ~Writer() = default; + ~Writer(); - OutputArrayType array_as_root(const size_t _size) const noexcept { - return new_array(_size); - } + OutputArrayType array_as_root(const size_t _size) const noexcept; - OutputObjectType object_as_root(const size_t _size) const noexcept { - return new_object(_size); - } + OutputObjectType object_as_root(const size_t _size) const noexcept; - OutputVarType null_as_root() const noexcept { - msgpack_pack_nil(pk_); - return OutputVarType{}; - } + OutputVarType null_as_root() const noexcept; template - OutputVarType value_as_root(const T& _var) const noexcept { - return new_value(_var); - } + OutputVarType value_as_root(const T& _var) const noexcept; OutputArrayType add_array_to_array(const size_t _size, - OutputArrayType* _parent) const noexcept { - return new_array(_size); - } + OutputArrayType* _parent) const noexcept; OutputArrayType add_array_to_object( const std::string_view& _name, const size_t _size, - OutputObjectType* _parent) const noexcept { - msgpack_pack_str(pk_, _name.size()); - msgpack_pack_str_body(pk_, _name.data(), _name.size()); - return new_array(_size); - } + OutputObjectType* _parent) const noexcept; OutputObjectType add_object_to_array( - const size_t _size, OutputArrayType* _parent) const noexcept { - return new_object(_size); - } + const size_t _size, OutputArrayType* _parent) const noexcept; OutputObjectType add_object_to_object( const std::string_view& _name, const size_t _size, - OutputObjectType* _parent) const noexcept { - msgpack_pack_str(pk_, _name.size()); - msgpack_pack_str_body(pk_, _name.data(), _name.size()); - return new_object(_size); - } + OutputObjectType* _parent) const noexcept; template OutputVarType add_value_to_array(const T& _var, @@ -95,33 +74,19 @@ class Writer { return new_value(_var); } - OutputVarType add_null_to_array(OutputArrayType* _parent) const noexcept { - msgpack_pack_nil(pk_); - return OutputVarType{}; - } + OutputVarType add_null_to_array(OutputArrayType* _parent) const noexcept; OutputVarType add_null_to_object(const std::string_view& _name, - OutputObjectType* _parent) const noexcept { - msgpack_pack_str(pk_, _name.size()); - msgpack_pack_str_body(pk_, _name.data(), _name.size()); - msgpack_pack_nil(pk_); - return OutputVarType{}; - } + OutputObjectType* _parent) const noexcept; - void end_array(OutputArrayType* _arr) const noexcept {} + void end_array(OutputArrayType* _arr) const noexcept; - void end_object(OutputObjectType* _obj) const noexcept {} + void end_object(OutputObjectType* _obj) const noexcept; private: - OutputArrayType new_array(const size_t _size) const noexcept { - msgpack_pack_array(pk_, _size); - return OutputArrayType{}; - } + OutputArrayType new_array(const size_t _size) const noexcept; - OutputObjectType new_object(const size_t _size) const noexcept { - msgpack_pack_map(pk_, _size); - return OutputObjectType{}; - } + OutputObjectType new_object(const size_t _size) const noexcept; template OutputVarType new_value(const T& _var) const noexcept { @@ -155,4 +120,4 @@ class Writer { } // namespace rfl::msgpack -#endif // MSGPACK_PARSER_HPP_ +#endif diff --git a/include/rfl/toml/Reader.hpp b/include/rfl/toml/Reader.hpp index cb1d0875..41ae2f95 100644 --- a/include/rfl/toml/Reader.hpp +++ b/include/rfl/toml/Reader.hpp @@ -25,30 +25,16 @@ struct Reader { using InputVarType = ::toml::node*; template - static constexpr bool has_custom_constructor = (requires(InputVarType var) { - T::from_toml_obj(var); - }); + static constexpr bool has_custom_constructor = + (requires(InputVarType var) { T::from_toml_obj(var); }); rfl::Result get_field_from_array( - const size_t _idx, const InputArrayType _arr) const noexcept { - if (_idx >= _arr->size()) { - return rfl::Error("Index " + std::to_string(_idx) + " of of bounds."); - } - return _arr->get(_idx); - } + const size_t _idx, const InputArrayType _arr) const noexcept; rfl::Result get_field_from_object( - const std::string& _name, const InputObjectType& _obj) const noexcept { - auto var = (*_obj)[_name]; - if (!var) { - return rfl::Error("Object contains no field named '" + _name + "'."); - } - return var.node(); - } + const std::string& _name, const InputObjectType& _obj) const noexcept; - bool is_empty(const InputVarType& _var) const noexcept { - return !_var && true; - } + bool is_empty(const InputVarType& _var) const noexcept; template rfl::Result to_basic_type(const InputVarType& _var) const noexcept { @@ -81,14 +67,7 @@ struct Reader { } } - rfl::Result to_array( - const InputVarType& _var) const noexcept { - const auto ptr = _var->as_array(); - if (!ptr) { - return rfl::Error("Could not cast to an array!"); - } - return ptr; - } + rfl::Result to_array(const InputVarType& _var) const noexcept; template std::optional read_array(const ArrayReader& _array_reader, @@ -112,13 +91,7 @@ struct Reader { } rfl::Result to_object( - const InputVarType& _var) const noexcept { - const auto ptr = _var->as_table(); - if (!ptr) { - return rfl::Error("Could not cast to a table!"); - } - return ptr; - } + const InputVarType& _var) const noexcept; template rfl::Result use_custom_constructor( diff --git a/include/rfl/toml/Writer.hpp b/include/rfl/toml/Writer.hpp index d43b155e..e53c96b4 100644 --- a/include/rfl/toml/Writer.hpp +++ b/include/rfl/toml/Writer.hpp @@ -33,22 +33,16 @@ class Writer { using OutputObjectType = TOMLObject; using OutputVarType = TOMLVar; - Writer(::toml::table* _root) : root_(_root) {} + Writer(::toml::table* _root); - ~Writer() = default; + ~Writer(); template - OutputArrayType array_as_root(const T _size) const noexcept { - static_assert(rfl::always_false_v, - "TOML only allows tables as the root element."); - return OutputArrayType{nullptr}; - } + OutputArrayType array_as_root(const T _size) const noexcept; - OutputObjectType object_as_root(const size_t _size) const noexcept { - return OutputObjectType{root_}; - } + OutputObjectType object_as_root(const size_t _size) const noexcept; - OutputVarType null_as_root() const noexcept { return OutputVarType{}; } + OutputVarType null_as_root() const noexcept; template OutputVarType value_as_root(const T& _var) const noexcept { @@ -58,32 +52,18 @@ class Writer { } OutputArrayType add_array_to_array(const size_t _size, - OutputArrayType* _parent) const noexcept { - const auto i = _parent->val_->size(); - _parent->val_->push_back(::toml::array()); - return OutputArrayType{_parent->val_->at(i).as_array()}; - } + OutputArrayType* _parent) const noexcept; - OutputArrayType add_array_to_object( - const std::string_view& _name, const size_t _size, - OutputObjectType* _parent) const noexcept { - _parent->val_->emplace(_name, ::toml::array()); - return OutputArrayType{_parent->val_->at_path(_name).as_array()}; - } + OutputArrayType add_array_to_object(const std::string_view& _name, + const size_t _size, + OutputObjectType* _parent) const noexcept; - OutputObjectType add_object_to_array( - const size_t _size, OutputArrayType* _parent) const noexcept { - const auto i = _parent->val_->size(); - _parent->val_->push_back(::toml::table()); - return OutputObjectType{_parent->val_->at(i).as_table()}; - } + OutputObjectType add_object_to_array(const size_t _size, + OutputArrayType* _parent) const noexcept; OutputObjectType add_object_to_object( const std::string_view& _name, const size_t _size, - OutputObjectType* _parent) const noexcept { - _parent->val_->emplace(_name, ::toml::table()); - return OutputObjectType{_parent->val_->at_path(_name).as_table()}; - } + OutputObjectType* _parent) const noexcept; template OutputVarType add_value_to_array(const T& _var, @@ -100,20 +80,14 @@ class Writer { return OutputVarType{}; } - OutputVarType add_null_to_array(OutputArrayType* _parent) const noexcept { - _parent->val_->push_back(std::string("")); - return OutputVarType{}; - } + OutputVarType add_null_to_array(OutputArrayType* _parent) const noexcept; OutputVarType add_null_to_object(const std::string_view& _name, - OutputObjectType* _parent) const noexcept { - _parent->val_->emplace(_name, ::toml::value(std::string(""))); - return OutputVarType{}; - } + OutputObjectType* _parent) const noexcept; - void end_array(OutputArrayType* _arr) const noexcept {} + void end_array(OutputArrayType* _arr) const noexcept; - void end_object(OutputObjectType* _obj) const noexcept {} + void end_object(OutputObjectType* _obj) const noexcept; private: ::toml::table* root_; @@ -121,4 +95,4 @@ class Writer { } // namespace rfl::toml -#endif // JSON_PARSER_HPP_ +#endif diff --git a/include/rfl/xml/write.hpp b/include/rfl/xml/write.hpp index 2ba76c84..fd2859fb 100644 --- a/include/rfl/xml/write.hpp +++ b/include/rfl/xml/write.hpp @@ -75,4 +75,4 @@ std::string write(const auto& _obj, const std::string& _indent = " ") { } // namespace xml } // namespace rfl -#endif // XML_PARSER_HPP_ +#endif diff --git a/include/rfl/yaml/Reader.hpp b/include/rfl/yaml/Reader.hpp index 7b935630..231192ae 100644 --- a/include/rfl/yaml/Reader.hpp +++ b/include/rfl/yaml/Reader.hpp @@ -45,30 +45,16 @@ struct Reader { struct has_from_json_obj : std::false_type {}; template - static constexpr bool has_custom_constructor = (requires(InputVarType var) { - T::from_yaml_obj(var); - }); + static constexpr bool has_custom_constructor = + (requires(InputVarType var) { T::from_yaml_obj(var); }); rfl::Result get_field_from_array( - const size_t _idx, const InputArrayType& _arr) const noexcept { - if (_idx >= _arr.node_.size()) { - return rfl::Error("Index " + std::to_string(_idx) + " of of bounds."); - } - return InputVarType(_arr.node_[_idx]); - } + const size_t _idx, const InputArrayType& _arr) const noexcept; rfl::Result get_field_from_object( - const std::string& _name, const InputObjectType& _obj) const noexcept { - auto var = InputVarType(_obj.node_[_name]); - if (!var.node_) { - return rfl::Error("Object contains no field named '" + _name + "'."); - } - return var; - } + const std::string& _name, const InputObjectType& _obj) const noexcept; - bool is_empty(const InputVarType& _var) const noexcept { - return !_var.node_ && true; - } + bool is_empty(const InputVarType& _var) const noexcept; template rfl::Result to_basic_type(const InputVarType& _var) const noexcept { @@ -86,13 +72,7 @@ struct Reader { } } - rfl::Result to_array( - const InputVarType& _var) const noexcept { - if (!_var.node_.IsSequence()) { - return rfl::Error("Could not cast to sequence!"); - } - return InputArrayType(_var.node_); - } + rfl::Result to_array(const InputVarType& _var) const noexcept; template std::optional read_array(const ArrayReader& _array_reader, @@ -121,12 +101,7 @@ struct Reader { } rfl::Result to_object( - const InputVarType& _var) const noexcept { - if (!_var.node_.IsMap()) { - return rfl::Error("Could not cast to map!"); - } - return InputObjectType(_var.node_); - } + const InputVarType& _var) const noexcept; template rfl::Result use_custom_constructor( diff --git a/include/rfl/yaml/Writer.hpp b/include/rfl/yaml/Writer.hpp index c55d88ef..59b1d9d7 100644 --- a/include/rfl/yaml/Writer.hpp +++ b/include/rfl/yaml/Writer.hpp @@ -31,21 +31,15 @@ class Writer { using OutputObjectType = YAMLObject; using OutputVarType = YAMLVar; - Writer(const Ref& _out) : out_(_out) {} + Writer(const Ref& _out); - ~Writer() = default; + ~Writer(); - OutputArrayType array_as_root(const size_t _size) const noexcept { - return new_array(); - } + OutputArrayType array_as_root(const size_t _size) const noexcept; - OutputObjectType object_as_root(const size_t _size) const noexcept { - return new_object(); - } + OutputObjectType object_as_root(const size_t _size) const noexcept; - OutputVarType null_as_root() const noexcept { - return insert_value(YAML::Null); - } + OutputVarType null_as_root() const noexcept; template OutputVarType value_as_root(const T& _var) const noexcept { @@ -53,26 +47,18 @@ class Writer { } OutputArrayType add_array_to_array(const size_t _size, - OutputArrayType* _parent) const noexcept { - return new_array(); - } + OutputArrayType* _parent) const noexcept; - OutputArrayType add_array_to_object( - const std::string_view& _name, const size_t _size, - OutputObjectType* _parent) const noexcept { - return new_array(_name); - } + OutputArrayType add_array_to_object(const std::string_view& _name, + const size_t _size, + OutputObjectType* _parent) const noexcept; - OutputObjectType add_object_to_array( - const size_t _size, OutputArrayType* _parent) const noexcept { - return new_object(); - } + OutputObjectType add_object_to_array(const size_t _size, + OutputArrayType* _parent) const noexcept; OutputObjectType add_object_to_object( const std::string_view& _name, const size_t _size, - OutputObjectType* _parent) const noexcept { - return new_object(_name); - } + OutputObjectType* _parent) const noexcept; template OutputVarType add_value_to_array(const T& _var, @@ -87,22 +73,14 @@ class Writer { return insert_value(_name, _var); } - OutputVarType add_null_to_array(OutputArrayType* _parent) const noexcept { - return insert_value(YAML::Null); - } + OutputVarType add_null_to_array(OutputArrayType* _parent) const noexcept; OutputVarType add_null_to_object(const std::string_view& _name, - OutputObjectType* _parent) const noexcept { - return insert_value(_name, YAML::Null); - } + OutputObjectType* _parent) const noexcept; - void end_array(OutputArrayType* _arr) const noexcept { - (*out_) << YAML::EndSeq; - } + void end_array(OutputArrayType* _arr) const noexcept; - void end_object(OutputObjectType* _obj) const noexcept { - (*out_) << YAML::EndMap; - } + void end_object(OutputObjectType* _obj) const noexcept; private: template @@ -118,25 +96,13 @@ class Writer { return OutputVarType{}; } - OutputArrayType new_array(const std::string_view& _name) const noexcept { - (*out_) << YAML::Key << _name.data() << YAML::Value << YAML::BeginSeq; - return OutputArrayType{}; - } + OutputArrayType new_array(const std::string_view& _name) const noexcept; - OutputArrayType new_array() const noexcept { - (*out_) << YAML::BeginSeq; - return OutputArrayType{}; - } + OutputArrayType new_array() const noexcept; - OutputObjectType new_object(const std::string_view& _name) const noexcept { - (*out_) << YAML::Key << _name.data() << YAML::Value << YAML::BeginMap; - return OutputObjectType{}; - } + OutputObjectType new_object(const std::string_view& _name) const noexcept; - OutputObjectType new_object() const noexcept { - (*out_) << YAML::BeginMap; - return OutputObjectType{}; - } + OutputObjectType new_object() const noexcept; public: const Ref out_; @@ -145,4 +111,4 @@ class Writer { } // namespace yaml } // namespace rfl -#endif // JSON_PARSER_HPP_ +#endif diff --git a/src/reflectcpp_bson.cpp b/src/reflectcpp_bson.cpp new file mode 100644 index 00000000..11be3f60 --- /dev/null +++ b/src/reflectcpp_bson.cpp @@ -0,0 +1,33 @@ +/* + +MIT License + +Copyright (c) 2023-2024 Code17 GmbH + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +*/ + +// This file include all other source files, so that the user of the library +// don't need to add multiple source files into their build. +// Also, this speeds up compile time, compared to multiple separate .cpp files +// compilation. + +#include "rfl/bson/Reader.cpp" +#include "rfl/bson/Writer.cpp" diff --git a/src/reflectcpp_cbor.cpp b/src/reflectcpp_cbor.cpp new file mode 100644 index 00000000..0c9890e0 --- /dev/null +++ b/src/reflectcpp_cbor.cpp @@ -0,0 +1,33 @@ +/* + +MIT License + +Copyright (c) 2023-2024 Code17 GmbH + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +*/ + +// This file include all other source files, so that the user of the library +// don't need to add multiple source files into their build. +// Also, this speeds up compile time, compared to multiple separate .cpp files +// compilation. + +#include "rfl/cbor/Reader.cpp" +#include "rfl/cbor/Writer.cpp" diff --git a/src/reflectcpp_flexbuf.cpp b/src/reflectcpp_flexbuf.cpp new file mode 100644 index 00000000..0d636abf --- /dev/null +++ b/src/reflectcpp_flexbuf.cpp @@ -0,0 +1,33 @@ +/* + +MIT License + +Copyright (c) 2023-2024 Code17 GmbH + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +*/ + +// This file include all other source files, so that the user of the library +// don't need to add multiple source files into their build. +// Also, this speeds up compile time, compared to multiple separate .cpp files +// compilation. + +#include "rfl/flexbuf/Reader.cpp" +#include "rfl/flexbuf/Writer.cpp" diff --git a/src/reflectcpp_msgpack.cpp b/src/reflectcpp_msgpack.cpp new file mode 100644 index 00000000..529b7903 --- /dev/null +++ b/src/reflectcpp_msgpack.cpp @@ -0,0 +1,33 @@ +/* + +MIT License + +Copyright (c) 2023-2024 Code17 GmbH + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +*/ + +// This file include all other source files, so that the user of the library +// don't need to add multiple source files into their build. +// Also, this speeds up compile time, compared to multiple separate .cpp files +// compilation. + +#include "rfl/msgpack/Reader.cpp" +#include "rfl/msgpack/Writer.cpp" diff --git a/src/reflectcpp_toml.cpp b/src/reflectcpp_toml.cpp new file mode 100644 index 00000000..bac9d211 --- /dev/null +++ b/src/reflectcpp_toml.cpp @@ -0,0 +1,33 @@ +/* + +MIT License + +Copyright (c) 2023-2024 Code17 GmbH + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +*/ + +// This file include all other source files, so that the user of the library +// don't need to add multiple source files into their build. +// Also, this speeds up compile time, compared to multiple separate .cpp files +// compilation. + +#include "rfl/toml/Reader.cpp" +#include "rfl/toml/Writer.cpp" diff --git a/src/reflectcpp_yaml.cpp b/src/reflectcpp_yaml.cpp new file mode 100644 index 00000000..8e6b2aad --- /dev/null +++ b/src/reflectcpp_yaml.cpp @@ -0,0 +1,33 @@ +/* + +MIT License + +Copyright (c) 2023-2024 Code17 GmbH + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +*/ + +// This file include all other source files, so that the user of the library +// don't need to add multiple source files into their build. +// Also, this speeds up compile time, compared to multiple separate .cpp files +// compilation. + +#include "rfl/yaml/Reader.cpp" +#include "rfl/yaml/Writer.cpp" diff --git a/src/rfl/bson/Reader.cpp b/src/rfl/bson/Reader.cpp new file mode 100644 index 00000000..6d28b770 --- /dev/null +++ b/src/rfl/bson/Reader.cpp @@ -0,0 +1,72 @@ +#include "rfl/bson/Reader.hpp" + +namespace rfl::bson { + +rfl::Result Reader::get_field_from_array( + const size_t _idx, const InputArrayType& _arr) const noexcept { + bson_t b; + bson_iter_t iter; + const auto doc = _arr.val_->value.v_doc; + if (bson_init_static(&b, doc.data, doc.data_len)) { + if (bson_iter_init(&iter, &b)) { + size_t i = 0; + while (bson_iter_next(&iter)) { + if (i == _idx) { + return to_input_var(&iter); + } + ++i; + } + } else { + return Error("Could not init the array iteration."); + } + } else { + return Error("Could not init array."); + } + return Error("Index " + std::to_string(_idx) + " of of bounds."); +} + +rfl::Result Reader::get_field_from_object( + const std::string& _name, const InputObjectType& _obj) const noexcept { + bson_t b; + bson_iter_t iter; + const auto doc = _obj.val_->value.v_doc; + if (bson_init_static(&b, doc.data, doc.data_len)) { + if (bson_iter_init(&iter, &b)) { + while (bson_iter_next(&iter)) { + auto key = std::string(bson_iter_key(&iter)); + if (key == _name) { + return to_input_var(&iter); + } + } + } + } + return Error("No field named '" + _name + "' was found."); +} + +bool Reader::is_empty(const InputVarType& _var) const noexcept { + return _var.val_->value_type == BSON_TYPE_NULL; +} + +rfl::Result Reader::to_array( + const InputVarType& _var) const noexcept { + const auto btype = _var.val_->value_type; + if (btype != BSON_TYPE_ARRAY && btype != BSON_TYPE_DOCUMENT) { + return Error("Could not cast to an array."); + } + return InputArrayType{_var.val_}; +} + +rfl::Result Reader::to_object( + const InputVarType& _var) const noexcept { + const auto btype = _var.val_->value_type; + if (btype != BSON_TYPE_DOCUMENT) { + return Error("Could not cast to a document."); + } + return InputObjectType{_var.val_}; +} + +Reader::InputVarType Reader::to_input_var(bson_iter_t* _iter) const noexcept { + return InputVarType{bson_iter_value(_iter)}; +} + +} // namespace rfl::bson diff --git a/src/rfl/bson/Writer.cpp b/src/rfl/bson/Writer.cpp new file mode 100644 index 00000000..a5355664 --- /dev/null +++ b/src/rfl/bson/Writer.cpp @@ -0,0 +1,102 @@ +#include "rfl/bson/Writer.hpp" + +namespace rfl::bson { + +Writer::Writer(bson_t* _doc) : doc_(_doc) {} + +Writer::~Writer() = default; + +Writer::OutputArrayType Writer::array_as_root( + const size_t _size) const noexcept { + bson_array_builder_t* val = bson_array_builder_new(); + return OutputArrayType(val, IsRoot{}); +} + +Writer::OutputObjectType Writer::object_as_root( + const size_t _size) const noexcept { + return OutputObjectType(doc_, IsRoot{}); +} + +Writer::OutputVarType Writer::null_as_root() const noexcept { + // Appears to be unsupported by the BSON C API. + return OutputVarType{}; +} + +Writer::OutputArrayType Writer::add_array_to_array( + const size_t _size, OutputArrayType* _parent) const noexcept { + bson_array_builder_t* val; + bson_array_builder_append_array_builder_begin(_parent->val_, &val); + return OutputArrayType(val, IsArray{_parent->val_}); +} + +Writer::OutputArrayType Writer::add_array_to_object( + const std::string_view& _name, const size_t _size, + OutputObjectType* _parent) const noexcept { + bson_array_builder_t* val; + bson_append_array_builder_begin(_parent->val_, _name.data(), + static_cast(_name.size()), &val); + return OutputArrayType(val, IsObject{_parent->val_}); +} + +Writer::OutputObjectType Writer::add_object_to_array( + const size_t _size, OutputArrayType* _parent) const noexcept { + subdocs_->emplace_back(rfl::Box()); + bson_array_builder_append_document_begin(_parent->val_, + &(subdocs_->back()->val_)); + return OutputObjectType(&subdocs_->back()->val_, IsArray{_parent->val_}); +} + +Writer::OutputObjectType Writer::add_object_to_object( + const std::string_view& _name, const size_t _size, + OutputObjectType* _parent) const noexcept { + subdocs_->emplace_back(rfl::Box()); + bson_append_document_begin(_parent->val_, _name.data(), + static_cast(_name.size()), + &(subdocs_->back()->val_)); + return OutputObjectType(&subdocs_->back()->val_, IsObject{_parent->val_}); +} + +Writer::OutputVarType Writer::add_null_to_array( + OutputArrayType* _parent) const noexcept { + bson_array_builder_append_null(_parent->val_); + return OutputVarType{}; +} + +Writer::OutputVarType Writer::add_null_to_object( + const std::string_view& _name, OutputObjectType* _parent) const noexcept { + bson_append_null(_parent->val_, _name.data(), static_cast(_name.size())); + return OutputVarType{}; +} + +void Writer::end_array(OutputArrayType* _arr) const noexcept { + const auto handle = [&](const auto _parent) { + using Type = std::remove_cvref_t; + if constexpr (std::is_same()) { + bson_array_builder_append_array_builder_end(_parent.ptr_, _arr->val_); + } else if constexpr (std::is_same()) { + bson_append_array_builder_end(_parent.ptr_, _arr->val_); + } else if constexpr (std::is_same()) { + bson_array_builder_build(_arr->val_, doc_); + } else { + static_assert(rfl::always_false_v, "Unsupported type."); + } + }; + std::visit(handle, _arr->parent_); +} + +void Writer::end_object(OutputObjectType* _obj) const noexcept { + const auto handle = [&](const auto _parent) { + using Type = std::remove_cvref_t; + if constexpr (std::is_same()) { + bson_array_builder_append_document_end(_parent.ptr_, _obj->val_); + } else if constexpr (std::is_same()) { + bson_append_document_end(_parent.ptr_, _obj->val_); + } else if constexpr (std::is_same()) { + } else { + static_assert(rfl::always_false_v, "Unsupported type."); + } + }; + std::visit(handle, _obj->parent_); +} + +} // namespace rfl::bson diff --git a/src/rfl/cbor/Reader.cpp b/src/rfl/cbor/Reader.cpp new file mode 100644 index 00000000..f508ad21 --- /dev/null +++ b/src/rfl/cbor/Reader.cpp @@ -0,0 +1,116 @@ +#include "rfl/cbor/Reader.hpp" + +namespace rfl::cbor { + +rfl::Result Reader::get_field_from_array( + const size_t _idx, const InputArrayType& _arr) const noexcept { + InputVarType var; + auto err = cbor_value_enter_container(&_arr.val_, &var.val_); + if (err != CborNoError && err != CborErrorOutOfMemory) { + return Error(cbor_error_string(err)); + } + size_t length = 0; + err = cbor_value_get_array_length(&_arr.val_, &length); + if (err != CborNoError && err != CborErrorOutOfMemory) { + return Error(cbor_error_string(err)); + } + if (_idx >= length) { + return Error("Index " + std::to_string(_idx) + " of of bounds."); + } + for (size_t i = 0; i < _idx; ++i) { + err = cbor_value_advance(&var.val_); + if (err != CborNoError && err != CborErrorOutOfMemory) { + return Error(cbor_error_string(err)); + } + } + return var; +} + +rfl::Result Reader::get_field_from_object( + const std::string& _name, const InputObjectType& _obj) const noexcept { + InputVarType var; + auto buffer = std::string(); + auto err = cbor_value_enter_container(&_obj.val_, &var.val_); + if (err != CborNoError) { + return Error(cbor_error_string(err)); + } + size_t length = 0; + err = cbor_value_get_map_length(&_obj.val_, &length); + if (err != CborNoError) { + return Error(cbor_error_string(err)); + } + for (size_t i = 0; i < length; ++i) { + if (!cbor_value_is_text_string(&var.val_)) { + return Error("Expected the key to be a string value."); + } + err = get_string(&var.val_, &buffer); + if (err != CborNoError) { + return Error(cbor_error_string(err)); + } + err = cbor_value_advance(&var.val_); + if (err != CborNoError) { + return Error(cbor_error_string(err)); + } + if (_name == buffer) { + return var; + } + err = cbor_value_advance(&var.val_); + if (err != CborNoError) { + return Error(cbor_error_string(err)); + } + } + return Error("No field named '" + _name + "' was found."); +} + +bool Reader::is_empty(const InputVarType& _var) const noexcept { + return cbor_value_is_null(&_var.val_); +} + +rfl::Result Reader::to_array( + const InputVarType& _var) const noexcept { + if (!cbor_value_is_array(&_var.val_)) { + return Error("Could not cast to an array."); + } + return InputArrayType{_var.val_}; +} + +rfl::Result Reader::to_object( + const InputVarType& _var) const noexcept { + if (!cbor_value_is_map(&_var.val_)) { + return Error("Could not cast to an object."); + } + return InputObjectType{_var.val_}; +} + +CborError Reader::get_bytestring(const CborValue* _ptr, + rfl::Bytestring* _str) const noexcept { + size_t length = 0; + auto err = cbor_value_get_string_length(_ptr, &length); + if (err != CborNoError && err != CborErrorOutOfMemory) { + return err; + } + _str->resize(length); + if (length > 0) { + return cbor_value_copy_byte_string( + _ptr, reinterpret_cast(&((*_str)[0])), &length, NULL); + } else { + return CborNoError; + } +} + +CborError Reader::get_string(const CborValue* _ptr, + std::string* _str) const noexcept { + size_t length = 0; + auto err = cbor_value_get_string_length(_ptr, &length); + if (err != CborNoError && err != CborErrorOutOfMemory) { + return err; + } + _str->resize(length); + if (length > 0) { + return cbor_value_copy_text_string(_ptr, &((*_str)[0]), &length, NULL); + } else { + return CborNoError; + } +} + +} // namespace rfl::cbor diff --git a/src/rfl/cbor/Writer.cpp b/src/rfl/cbor/Writer.cpp new file mode 100644 index 00000000..8958419a --- /dev/null +++ b/src/rfl/cbor/Writer.cpp @@ -0,0 +1,83 @@ +#include "rfl/cbor/Writer.hpp" + +namespace rfl::cbor { + +Writer::Writer(CborEncoder* _encoder) : encoder_(_encoder) {} + +Writer::~Writer() = default; + +Writer::OutputArrayType Writer::array_as_root( + const size_t _size) const noexcept { + return new_array(_size, encoder_); +} + +Writer::OutputObjectType Writer::object_as_root( + const size_t _size) const noexcept { + return new_object(_size, encoder_); +} + +Writer::OutputVarType Writer::null_as_root() const noexcept { + cbor_encode_null(encoder_); + return OutputVarType{}; +} + +Writer::OutputArrayType Writer::add_array_to_array( + const size_t _size, OutputArrayType* _parent) const noexcept { + return new_array(_size, _parent->encoder_); +} + +Writer::OutputArrayType Writer::add_array_to_object( + const std::string_view& _name, const size_t _size, + OutputObjectType* _parent) const noexcept { + cbor_encode_text_string(_parent->encoder_, _name.data(), _name.size()); + return new_array(_size, _parent->encoder_); +} + +Writer::OutputObjectType Writer::add_object_to_array( + const size_t _size, OutputArrayType* _parent) const noexcept { + return new_object(_size, _parent->encoder_); +} + +Writer::OutputObjectType Writer::add_object_to_object( + const std::string_view& _name, const size_t _size, + OutputObjectType* _parent) const noexcept { + cbor_encode_text_string(_parent->encoder_, _name.data(), _name.size()); + return new_object(_size, _parent->encoder_); +} + +Writer::OutputVarType Writer::add_null_to_array( + OutputArrayType* _parent) const noexcept { + cbor_encode_null(_parent->encoder_); + return OutputVarType{}; +} + +Writer::OutputVarType Writer::add_null_to_object( + const std::string_view& _name, OutputObjectType* _parent) const noexcept { + cbor_encode_text_string(_parent->encoder_, _name.data(), _name.size()); + cbor_encode_null(_parent->encoder_); + return OutputVarType{}; +} + +void Writer::end_array(OutputArrayType* _arr) const noexcept { + cbor_encoder_close_container(_arr->parent_, _arr->encoder_); +} + +void Writer::end_object(OutputObjectType* _obj) const noexcept { + cbor_encoder_close_container(_obj->parent_, _obj->encoder_); +} + +Writer::OutputArrayType Writer::new_array(const size_t _size, + CborEncoder* _parent) const noexcept { + subencoders_->emplace_back(rfl::Box::make()); + cbor_encoder_create_array(_parent, subencoders_->back().get(), _size); + return OutputArrayType{subencoders_->back().get(), _parent}; +} + +Writer::OutputObjectType Writer::new_object( + const size_t _size, CborEncoder* _parent) const noexcept { + subencoders_->emplace_back(rfl::Box::make()); + cbor_encoder_create_map(_parent, subencoders_->back().get(), _size); + return OutputObjectType{subencoders_->back().get(), _parent}; +} + +} // namespace rfl::cbor diff --git a/src/rfl/flexbuf/Reader.cpp b/src/rfl/flexbuf/Reader.cpp new file mode 100644 index 00000000..ff5888f1 --- /dev/null +++ b/src/rfl/flexbuf/Reader.cpp @@ -0,0 +1,44 @@ +#include "rfl/flexbuf/Reader.hpp" + +namespace rfl::flexbuf { + +rfl::Result Reader::get_field_from_array( + const size_t _idx, const InputArrayType& _arr) const noexcept { + if (_idx >= _arr.size()) { + return rfl::Error("Index " + std::to_string(_idx) + " of of bounds."); + } + return _arr[_idx]; +} + +rfl::Result Reader::get_field_from_object( + const std::string& _name, const InputObjectType& _obj) const noexcept { + const auto keys = _obj.Keys(); + for (size_t i = 0; i < keys.size(); ++i) { + if (_name == keys[i].AsString().c_str()) { + return _obj.Values()[i]; + } + } + return rfl::Error("Map does not contain any element called '" + _name + "'."); +} + +bool Reader::is_empty(const InputVarType& _var) const noexcept { + return _var.IsNull(); +} + +rfl::Result Reader::to_array( + const InputVarType& _var) const noexcept { + if (!_var.IsVector()) { + return rfl::Error("Could not cast to Vector."); + } + return _var.AsVector(); +} + +rfl::Result Reader::to_object( + const InputVarType& _var) const noexcept { + if (!_var.IsMap()) { + return rfl::Error("Could not cast to Map!"); + } + return _var.AsMap(); +} + +} // namespace rfl::flexbuf diff --git a/src/rfl/flexbuf/Writer.cpp b/src/rfl/flexbuf/Writer.cpp new file mode 100644 index 00000000..4be52ce8 --- /dev/null +++ b/src/rfl/flexbuf/Writer.cpp @@ -0,0 +1,88 @@ +#include "rfl/flexbuf/Writer.hpp" + +namespace rfl::flexbuf { + +Writer::Writer(const Ref& _fbb) : fbb_(_fbb) {} + +Writer::~Writer() = default; + +Writer::OutputArrayType Writer::array_as_root( + const size_t _size) const noexcept { + return new_array(); +} + +Writer::OutputObjectType Writer::object_as_root( + const size_t _size) const noexcept { + return new_object(); +} + +Writer::OutputVarType Writer::null_as_root() const noexcept { + fbb_->Null(); + return OutputVarType{}; +} + +Writer::OutputArrayType Writer::add_array_to_array( + const size_t _size, OutputArrayType* _parent) const noexcept { + return new_array(); +} + +Writer::OutputArrayType Writer::add_array_to_object( + const std::string_view& _name, const size_t _size, + OutputObjectType* _parent) const noexcept { + return new_array(_name); +} + +Writer::OutputObjectType Writer::add_object_to_array( + const size_t _size, OutputArrayType* _parent) const noexcept { + return new_object(); +} + +Writer::OutputObjectType Writer::add_object_to_object( + const std::string_view& _name, const size_t _size, + OutputObjectType* _parent) const noexcept { + return new_object(_name); +} + +Writer::OutputVarType Writer::add_null_to_array( + OutputArrayType* _parent) const noexcept { + fbb_->Null(); + return OutputVarType{}; +} + +Writer::OutputVarType Writer::add_null_to_object( + const std::string_view& _name, OutputObjectType* _parent) const noexcept { + fbb_->Null(_name.data()); + return OutputVarType{}; +} + +void Writer::end_array(OutputArrayType* _arr) const noexcept { + fbb_->EndVector(_arr->start_, false, false); +} + +void Writer::end_object(OutputObjectType* _obj) const noexcept { + fbb_->EndMap(_obj->start_); +} + +Writer::OutputArrayType Writer::new_array( + const std::string_view& _name) const noexcept { + const auto start = fbb_->StartVector(_name.data()); + return OutputArrayType{start}; +} + +Writer::OutputArrayType Writer::new_array() const noexcept { + const auto start = fbb_->StartVector(); + return OutputArrayType{start}; +} + +Writer::OutputObjectType Writer::new_object( + const std::string_view& _name) const noexcept { + const auto start = fbb_->StartMap(_name.data()); + return OutputObjectType{start}; +} + +Writer::OutputObjectType Writer::new_object() const noexcept { + const auto start = fbb_->StartMap(); + return OutputObjectType{start}; +} + +} // namespace rfl::flexbuf diff --git a/src/rfl/msgpack/Reader.cpp b/src/rfl/msgpack/Reader.cpp new file mode 100644 index 00000000..5c88b7fe --- /dev/null +++ b/src/rfl/msgpack/Reader.cpp @@ -0,0 +1,50 @@ +#include "rfl/msgpack/Reader.hpp" + +namespace rfl::msgpack { + +rfl::Result Reader::get_field_from_array( + const size_t _idx, const InputArrayType _arr) const noexcept { + if (_idx >= _arr.size) { + return rfl::Error("Index " + std::to_string(_idx) + " of of bounds."); + } + return _arr.ptr[_idx]; +} + +rfl::Result Reader::get_field_from_object( + const std::string& _name, const InputObjectType& _obj) const noexcept { + for (uint32_t i = 0; i < _obj.size; ++i) { + const auto& key = _obj.ptr[i].key; + if (key.type != MSGPACK_OBJECT_STR) { + return Error("Key in element " + std::to_string(i) + + " was not a string."); + } + const auto current_name = + std::string_view(key.via.str.ptr, key.via.str.size); + if (_name == current_name) { + return _obj.ptr[i].val; + } + } + return Error("No field named '" + _name + "' was found."); +} + +bool Reader::is_empty(const InputVarType& _var) const noexcept { + return _var.type == MSGPACK_OBJECT_NIL; +} + +rfl::Result Reader::to_array( + const InputVarType& _var) const noexcept { + if (_var.type != MSGPACK_OBJECT_ARRAY) { + return Error("Could not cast to an array."); + } + return _var.via.array; +} + +rfl::Result Reader::to_object( + const InputVarType& _var) const noexcept { + if (_var.type != MSGPACK_OBJECT_MAP) { + return Error("Could not cast to a map."); + } + return _var.via.map; +} + +} // namespace rfl::msgpack diff --git a/src/rfl/msgpack/Writer.cpp b/src/rfl/msgpack/Writer.cpp new file mode 100644 index 00000000..f711a0f4 --- /dev/null +++ b/src/rfl/msgpack/Writer.cpp @@ -0,0 +1,78 @@ +#include "rfl/msgpack/Writer.hpp" + +namespace rfl::msgpack { + +Writer::Writer(msgpack_packer* _pk) : pk_(_pk) {} + +Writer::~Writer() = default; + +Writer::OutputArrayType Writer::array_as_root( + const size_t _size) const noexcept { + return new_array(_size); +} + +Writer::OutputObjectType Writer::object_as_root( + const size_t _size) const noexcept { + return new_object(_size); +} + +Writer::OutputVarType Writer::null_as_root() const noexcept { + msgpack_pack_nil(pk_); + return OutputVarType{}; +} + +Writer::OutputArrayType Writer::add_array_to_array( + const size_t _size, OutputArrayType* _parent) const noexcept { + return new_array(_size); +} + +Writer::OutputArrayType Writer::add_array_to_object( + const std::string_view& _name, const size_t _size, + OutputObjectType* _parent) const noexcept { + msgpack_pack_str(pk_, _name.size()); + msgpack_pack_str_body(pk_, _name.data(), _name.size()); + return new_array(_size); +} + +Writer::OutputObjectType Writer::add_object_to_array( + const size_t _size, OutputArrayType* _parent) const noexcept { + return new_object(_size); +} + +Writer::OutputObjectType Writer::add_object_to_object( + const std::string_view& _name, const size_t _size, + OutputObjectType* _parent) const noexcept { + msgpack_pack_str(pk_, _name.size()); + msgpack_pack_str_body(pk_, _name.data(), _name.size()); + return new_object(_size); +} + +Writer::OutputVarType Writer::add_null_to_array( + OutputArrayType* _parent) const noexcept { + msgpack_pack_nil(pk_); + return OutputVarType{}; +} + +Writer::OutputVarType Writer::add_null_to_object( + const std::string_view& _name, OutputObjectType* _parent) const noexcept { + msgpack_pack_str(pk_, _name.size()); + msgpack_pack_str_body(pk_, _name.data(), _name.size()); + msgpack_pack_nil(pk_); + return OutputVarType{}; +} + +void Writer::end_array(OutputArrayType* _arr) const noexcept {} + +void Writer::end_object(OutputObjectType* _obj) const noexcept {} + +Writer::OutputArrayType Writer::new_array(const size_t _size) const noexcept { + msgpack_pack_array(pk_, _size); + return OutputArrayType{}; +} + +Writer::OutputObjectType Writer::new_object(const size_t _size) const noexcept { + msgpack_pack_map(pk_, _size); + return OutputObjectType{}; +} + +} // namespace rfl::msgpack diff --git a/src/rfl/toml/Reader.cpp b/src/rfl/toml/Reader.cpp new file mode 100644 index 00000000..74b91d8d --- /dev/null +++ b/src/rfl/toml/Reader.cpp @@ -0,0 +1,44 @@ +#include "rfl/toml/Reader.hpp" + +namespace rfl::toml { + +rfl::Result Reader::get_field_from_array( + const size_t _idx, const InputArrayType _arr) const noexcept { + if (_idx >= _arr->size()) { + return rfl::Error("Index " + std::to_string(_idx) + " of of bounds."); + } + return _arr->get(_idx); +} + +rfl::Result Reader::get_field_from_object( + const std::string& _name, const InputObjectType& _obj) const noexcept { + auto var = (*_obj)[_name]; + if (!var) { + return rfl::Error("Object contains no field named '" + _name + "'."); + } + return var.node(); +} + +bool Reader::is_empty(const InputVarType& _var) const noexcept { + return !_var && true; +} + +rfl::Result Reader::to_array( + const InputVarType& _var) const noexcept { + const auto ptr = _var->as_array(); + if (!ptr) { + return rfl::Error("Could not cast to an array!"); + } + return ptr; +} + +rfl::Result Reader::to_object( + const InputVarType& _var) const noexcept { + const auto ptr = _var->as_table(); + if (!ptr) { + return rfl::Error("Could not cast to a table!"); + } + return ptr; +} + +} // namespace rfl::toml diff --git a/src/rfl/toml/Writer.cpp b/src/rfl/toml/Writer.cpp new file mode 100644 index 00000000..22e19032 --- /dev/null +++ b/src/rfl/toml/Writer.cpp @@ -0,0 +1,62 @@ +#include "rfl/toml/Writer.hpp" + +namespace rfl::toml { + +Writer::Writer(::toml::table* _root) : root_(_root) {} + +Writer::~Writer() = default; + +Writer::OutputObjectType Writer::object_as_root( + const size_t _size) const noexcept { + return OutputObjectType{root_}; +} + +Writer::OutputVarType Writer::null_as_root() const noexcept { + return OutputVarType{}; +} + +Writer::OutputArrayType Writer::add_array_to_array( + const size_t _size, OutputArrayType* _parent) const noexcept { + const auto i = _parent->val_->size(); + _parent->val_->push_back(::toml::array()); + return OutputArrayType{_parent->val_->at(i).as_array()}; +} + +Writer::OutputArrayType Writer::add_array_to_object( + const std::string_view& _name, const size_t _size, + OutputObjectType* _parent) const noexcept { + _parent->val_->emplace(_name, ::toml::array()); + return OutputArrayType{_parent->val_->at_path(_name).as_array()}; +} + +Writer::OutputObjectType Writer::add_object_to_array( + const size_t _size, OutputArrayType* _parent) const noexcept { + const auto i = _parent->val_->size(); + _parent->val_->push_back(::toml::table()); + return OutputObjectType{_parent->val_->at(i).as_table()}; +} + +Writer::OutputObjectType Writer::add_object_to_object( + const std::string_view& _name, const size_t _size, + OutputObjectType* _parent) const noexcept { + _parent->val_->emplace(_name, ::toml::table()); + return OutputObjectType{_parent->val_->at_path(_name).as_table()}; +} + +Writer::OutputVarType Writer::add_null_to_array( + OutputArrayType* _parent) const noexcept { + _parent->val_->push_back(std::string("")); + return OutputVarType{}; +} + +Writer::OutputVarType Writer::add_null_to_object( + const std::string_view& _name, OutputObjectType* _parent) const noexcept { + _parent->val_->emplace(_name, ::toml::value(std::string(""))); + return OutputVarType{}; +} + +void Writer::end_array(OutputArrayType* _arr) const noexcept {} + +void Writer::end_object(OutputObjectType* _obj) const noexcept {} + +} // namespace rfl::toml diff --git a/src/rfl/yaml/Reader.cpp b/src/rfl/yaml/Reader.cpp new file mode 100644 index 00000000..8f77f65d --- /dev/null +++ b/src/rfl/yaml/Reader.cpp @@ -0,0 +1,42 @@ +#include "rfl/yaml/Reader.hpp" + +namespace rfl::yaml { + +rfl::Result Reader::get_field_from_array( + const size_t _idx, const InputArrayType& _arr) const noexcept { + if (_idx >= _arr.node_.size()) { + return rfl::Error("Index " + std::to_string(_idx) + " of of bounds."); + } + return InputVarType(_arr.node_[_idx]); +} + +rfl::Result Reader::get_field_from_object( + const std::string& _name, const InputObjectType& _obj) const noexcept { + auto var = InputVarType(_obj.node_[_name]); + if (!var.node_) { + return rfl::Error("Object contains no field named '" + _name + "'."); + } + return var; +} + +bool Reader::is_empty(const InputVarType& _var) const noexcept { + return !_var.node_ && true; +} + +rfl::Result Reader::to_array( + const InputVarType& _var) const noexcept { + if (!_var.node_.IsSequence()) { + return rfl::Error("Could not cast to sequence!"); + } + return InputArrayType(_var.node_); +} + +rfl::Result Reader::to_object( + const InputVarType& _var) const noexcept { + if (!_var.node_.IsMap()) { + return rfl::Error("Could not cast to map!"); + } + return InputObjectType(_var.node_); +} + +} // namespace rfl::yaml diff --git a/src/rfl/yaml/Writer.cpp b/src/rfl/yaml/Writer.cpp new file mode 100644 index 00000000..8482377f --- /dev/null +++ b/src/rfl/yaml/Writer.cpp @@ -0,0 +1,85 @@ +#include "rfl/yaml/Writer.hpp" + +namespace rfl::yaml { + +Writer::Writer(const Ref& _out) : out_(_out) {} + +Writer::~Writer() = default; + +Writer::OutputArrayType Writer::array_as_root( + const size_t _size) const noexcept { + return new_array(); +} + +Writer::OutputObjectType Writer::object_as_root( + const size_t _size) const noexcept { + return new_object(); +} + +Writer::OutputVarType Writer::null_as_root() const noexcept { + return insert_value(YAML::Null); +} + +Writer::OutputArrayType Writer::add_array_to_array( + const size_t _size, OutputArrayType* _parent) const noexcept { + return new_array(); +} + +Writer::OutputArrayType Writer::add_array_to_object( + const std::string_view& _name, const size_t _size, + OutputObjectType* _parent) const noexcept { + return new_array(_name); +} + +Writer::OutputObjectType Writer::add_object_to_array( + const size_t _size, OutputArrayType* _parent) const noexcept { + return new_object(); +} + +Writer::OutputObjectType Writer::add_object_to_object( + const std::string_view& _name, const size_t _size, + OutputObjectType* _parent) const noexcept { + return new_object(_name); +} + +Writer::OutputVarType Writer::add_null_to_array( + OutputArrayType* _parent) const noexcept { + return insert_value(YAML::Null); +} + +Writer::OutputVarType Writer::add_null_to_object( + const std::string_view& _name, OutputObjectType* _parent) const noexcept { + return insert_value(_name, YAML::Null); +} + +void Writer::end_array(OutputArrayType* _arr) const noexcept { + (*out_) << YAML::EndSeq; +} + +void Writer::end_object(OutputObjectType* _obj) const noexcept { + (*out_) << YAML::EndMap; +} + +Writer::OutputArrayType Writer::new_array( + const std::string_view& _name) const noexcept { + (*out_) << YAML::Key << _name.data() << YAML::Value << YAML::BeginSeq; + return OutputArrayType{}; +} + +Writer::OutputArrayType Writer::new_array() const noexcept { + (*out_) << YAML::BeginSeq; + return OutputArrayType{}; +} + +Writer::OutputObjectType Writer::new_object( + const std::string_view& _name) const noexcept { + (*out_) << YAML::Key << _name.data() << YAML::Value << YAML::BeginMap; + return OutputObjectType{}; +} + +Writer::OutputObjectType Writer::new_object() const noexcept { + (*out_) << YAML::BeginMap; + return OutputObjectType{}; +} + +} // namespace rfl::yaml