Add extracted tools: CitrineOS, OpenOCPP, ShapeShifter
- CitrineOS core extracted (CSMS OCPP 2.0.1) - OpenOCPP extracted (firmware OCPP 1.6J/2.0.1) - ShapeShifter library installed (pip install -e) - ShapeShifter specification extracted - EVerest extracted TODO updated with progress
This commit is contained in:
@@ -0,0 +1,19 @@
|
||||
{% from "helper_macros.j2" import insert_block, print_template_info %}
|
||||
{{ print_template_info('3', 'marked regions will be kept', '#') }}
|
||||
|
||||
# module setup:
|
||||
# - ${MODULE_NAME}: module name
|
||||
ev_setup_cpp_module()
|
||||
|
||||
{{ insert_block(info.blocks.add_general) }}
|
||||
|
||||
{% if provides %}
|
||||
target_sources(${MODULE_NAME}
|
||||
PRIVATE
|
||||
{% for impl in provides %}
|
||||
"{{ impl.cpp_file_rel_path }}"
|
||||
{% endfor %}
|
||||
)
|
||||
|
||||
{% endif %}
|
||||
{{ insert_block(info.blocks.add_other) }}
|
||||
@@ -0,0 +1,127 @@
|
||||
{% macro cpp_type(type, interface=none, call=false) -%}
|
||||
{% if type.is_variant -%}
|
||||
std::variant<{{ type.cpp_type|join(', ') }}>
|
||||
{%- else -%}
|
||||
{% if interface is not none and 'object_type' in type %}
|
||||
{{ interface + '::' + type.object_type }}
|
||||
{% else %}
|
||||
{% if call -%}{{'const '}}{%- endif %}
|
||||
{% if 'object_type' in type -%}
|
||||
{{ type.object_type }}
|
||||
{%- elif 'enum_type' in type -%}
|
||||
{{ type.enum_type }}
|
||||
{%- elif 'array_type' in type -%}
|
||||
std::vector<{{ type.array_type }}>
|
||||
{%- else -%}
|
||||
{{ type.cpp_type }}
|
||||
{%- endif %}
|
||||
{% if call -%}&{%- endif %}
|
||||
{%- endif %}
|
||||
{%- endif %}
|
||||
{%- endmacro %}
|
||||
|
||||
{% macro result_type(type, interface=none) -%}
|
||||
{% if type -%}
|
||||
{{ cpp_type(type) }}
|
||||
{%- else -%}
|
||||
void
|
||||
{%- endif %}
|
||||
{%- endmacro %}
|
||||
|
||||
{% macro var_to_any(var, name) -%}
|
||||
{% if var.is_variant -%}
|
||||
Everest::variant_to_json({{ name }})
|
||||
{%- else -%}
|
||||
{{ name }}
|
||||
{%- endif %}
|
||||
{%- endmacro %}
|
||||
|
||||
{% macro var_to_cpp(arg) -%}
|
||||
{% if arg.is_variant -%}
|
||||
Everest::json_to_variant<{{ arg.cpp_type|join(', ')}}>
|
||||
{%- else -%}
|
||||
static_cast<{{ arg.cpp_type }}>
|
||||
{%- endif %}
|
||||
{%- endmacro %}
|
||||
|
||||
{% macro call_cmd_signature(cmd, interface=none) -%}
|
||||
{{ result_type(cmd.result, interface) }} call_{{ cmd.name }}(
|
||||
{%- for arg in cmd.args -%}
|
||||
{{ cpp_type(arg, none, true) }} {{ arg.name }}{{ ', ' if not loop.last }}
|
||||
{%- endfor -%}
|
||||
)
|
||||
{%- endmacro %}
|
||||
|
||||
{% macro handle_cmd_signature(cmd, class_name=None, interface=none) -%}
|
||||
{% if not class_name %}virtual {% endif -%}
|
||||
{{ result_type(cmd.result, interface) }} {% if class_name %}{{ class_name }}::{% endif -%}
|
||||
handle_{{ cmd.name }}(
|
||||
{%- for arg in cmd.args -%}
|
||||
{{ cpp_type(arg) }}& {{ arg.name }}{{ ', ' if not loop.last }}
|
||||
{%- endfor -%}
|
||||
)
|
||||
{%- endmacro %}
|
||||
|
||||
{% macro publish_var_signature(var) %}
|
||||
void publish_{{ var.name }}({% if var.json_type != 'null' %}{{ cpp_type(var) }} value{% endif %}) {
|
||||
_ev->publish(_name, "{{ var.name }}", {% if var.json_type != 'null' %}{{ var_to_any(var, 'value')}}{% else %}nullptr{% endif %});
|
||||
}
|
||||
{% endmacro %}
|
||||
|
||||
{% macro list_json_types(json_type) -%}
|
||||
{% if json_type is iterable and json_type is not string -%}
|
||||
{
|
||||
{%- for type in json_type -%}
|
||||
"{{ type }}"{{ ', ' if not loop.last}}
|
||||
{%- endfor -%}
|
||||
}
|
||||
{%- else -%}
|
||||
{"{{ json_type }}"}
|
||||
{%- endif %}
|
||||
{%- endmacro %}
|
||||
|
||||
{% macro insert_block(block, indent=0) %}
|
||||
{{ block.tag }}
|
||||
{{ " "*indent if block.first_use }}{{ block.content }}
|
||||
{{ " "*indent }}{{ block.tag }}
|
||||
{%- endmacro %}
|
||||
|
||||
{% macro print_spdx_line(license, year_tag=None) %}
|
||||
// SPDX-License-Identifier: {{ license }}
|
||||
// Copyright{% if year_tag %} {{ year_tag }}{% endif %} Pionix GmbH and Contributors to EVerest
|
||||
{%- endmacro %}
|
||||
|
||||
{% macro print_license_header(license) %}
|
||||
{{ license }}
|
||||
{%- endmacro %}
|
||||
|
||||
{% macro print_template_info(version, title='DO NOT EDIT!', comment_sep='//') %}
|
||||
{{ comment_sep }}
|
||||
{{ comment_sep }} AUTO GENERATED - {{ title|upper }}
|
||||
{{ comment_sep }} template version {{ version }}
|
||||
{{ comment_sep }}
|
||||
{%- endmacro %}
|
||||
|
||||
{% macro string_to_enum(enum_type) %}
|
||||
{% if '::' not in enum_type %}
|
||||
string_to_{{ enum_type | snake_case -}}
|
||||
{% else %}
|
||||
{{ enum_type[:enum_type.rfind('::')] }}::string_to_{{ enum_type[(enum_type.rfind('::')+2):] | snake_case -}}
|
||||
{% endif %}
|
||||
{%- endmacro %}
|
||||
|
||||
{% macro enum_to_string(enum_type) %}
|
||||
{% if '::' not in enum_type %}
|
||||
{{ enum_type | snake_case }}_to_string
|
||||
{%- else %}
|
||||
{{ enum_type[:enum_type.rfind('::')] }}::{{ enum_type[(enum_type.rfind('::')+2):] | snake_case }}_to_string
|
||||
{%- endif %}
|
||||
{%- endmacro %}
|
||||
|
||||
{% macro enum_to_string_view(enum_type) %}
|
||||
{% if '::' not in enum_type %}
|
||||
{{ enum_type | snake_case }}_to_string_view
|
||||
{%- else %}
|
||||
{{ enum_type[:enum_type.rfind('::')] }}::{{ enum_type[(enum_type.rfind('::')+2):] | snake_case }}_to_string_view
|
||||
{%- endif %}
|
||||
{%- endmacro %}
|
||||
@@ -0,0 +1,24 @@
|
||||
.. _everest_modules_handwritten_{{ info.name }}:
|
||||
|
||||
.. This file is a placeholder for optional multiple files
|
||||
handwritten documentation for the {{ info.name }} module.
|
||||
|
||||
.. This handwritten documentation is optional. In case
|
||||
you do not want to write it, you can delete the doc/ directory.
|
||||
|
||||
.. The documentation can be written in reStructuredText,
|
||||
and will be converted to HTML and PDF by Sphinx.
|
||||
This index.rst file is the entry point for the module documentation.
|
||||
|
||||
.. Use underlined-only headlines inside this document (highest-level
|
||||
sub-section headline should use "=" characters)
|
||||
|
||||
.. The content of this file will be included in the auto-generated HTML
|
||||
page for the module. You can link to it using the following
|
||||
reference: everest_modules_{{ info.name }}.
|
||||
|
||||
.. *******************************************
|
||||
.. {{ info.name }}
|
||||
.. *******************************************
|
||||
|
||||
{{ info.desc }}
|
||||
@@ -0,0 +1,194 @@
|
||||
{% from "helper_macros.j2" import handle_cmd_signature, publish_var_signature, list_json_types, var_to_cpp, var_to_any, print_template_info, print_spdx_line, string_to_enum, enum_to_string, enum_to_string_view %}
|
||||
{{ print_spdx_line('Apache-2.0') }}
|
||||
#ifndef {{ info.hpp_guard }}
|
||||
#define {{ info.hpp_guard }}
|
||||
|
||||
{{ print_template_info('6') }}
|
||||
|
||||
#include <framework/ModuleAdapter.hpp>
|
||||
#include <utils/types.hpp>
|
||||
#include <utils/error.hpp>
|
||||
#include <utils/error/error_state_monitor.hpp>
|
||||
#include <utils/error/error_manager_impl.hpp>
|
||||
#include <utils/error/error_factory.hpp>
|
||||
|
||||
#include "Types.hpp"
|
||||
|
||||
class {{ info.class_name }} : public Everest::ImplementationBase {
|
||||
public:
|
||||
{{ info.class_name }}(Everest::ModuleAdapter* ev, const std::string& name)
|
||||
: Everest::ImplementationBase(),
|
||||
_ev(ev),
|
||||
_name(name) {
|
||||
if (ev == nullptr) {
|
||||
EVLOG_error << "ev is nullptr, please check the initialization of the module";
|
||||
error_manager = nullptr;
|
||||
error_state_monitor = nullptr;
|
||||
error_factory = nullptr;
|
||||
EVLOG_error << "error_manager, error_state_monitor and error_factory are nullptr";
|
||||
} else {
|
||||
error_manager = ev->get_error_manager_impl(name);
|
||||
if (error_manager == nullptr) {
|
||||
EVLOG_error << "error_manager is nullptr";
|
||||
}
|
||||
error_state_monitor = ev->get_error_state_monitor_impl(name);
|
||||
if (error_state_monitor == nullptr) {
|
||||
EVLOG_error << "error_state_monitor is nullptr";
|
||||
}
|
||||
error_factory = ev->get_error_factory(name);
|
||||
if (error_factory == nullptr) {
|
||||
EVLOG_error << "error_factory is nullptr";
|
||||
}
|
||||
impl_mapping = Everest::get_impl_mapping(ev->get_mapping(), name);
|
||||
}
|
||||
}
|
||||
|
||||
{% if not vars %}
|
||||
// no variables defined for this interface
|
||||
{% else %}
|
||||
// publish functions for variables
|
||||
{% for var in vars %}
|
||||
void publish_{{ var.name }}(
|
||||
{%- if 'array_type' in var %}
|
||||
const std::vector<{{ var.array_type }}>&
|
||||
{%- elif 'object_type' in var %}
|
||||
{{- 'const '}} {{- var.object_type }}&
|
||||
{%- elif 'enum_type' in var %}
|
||||
{{- 'const '}} {{- var.enum_type }}&
|
||||
{%- else %}
|
||||
{{- 'const '}} {{- var.cpp_type }}&
|
||||
{%- endif -%}
|
||||
{{ ' value) {' }}
|
||||
{% if 'object_type' in var %}
|
||||
_ev->publish(_name, "{{ var.name }}", value);
|
||||
{% elif 'enum_type' in var %}
|
||||
_ev->publish(_name, "{{ var.name }}", {{ enum_to_string_view(var.enum_type) }}(value));
|
||||
{% elif 'array_type' in var %}
|
||||
{% if 'array_type_contains_enum' in var %}
|
||||
std::vector<std::string> string_array;
|
||||
string_array.reserve(value.size());
|
||||
for (const auto& entry : value) {
|
||||
string_array.push_back({{ enum_to_string(var.array_type) }}(entry));
|
||||
}
|
||||
_ev->publish(_name, "{{ var.name }}", string_array);
|
||||
{% else %}
|
||||
_ev->publish(_name, "{{ var.name }}", value);
|
||||
{% endif %}
|
||||
{% else %}
|
||||
_ev->publish(_name, "{{ var.name }}", value);
|
||||
{% endif %}
|
||||
}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
|
||||
void raise_error(const Everest::error::Error& error) {
|
||||
error_manager->raise_error(error);
|
||||
}
|
||||
|
||||
void clear_error(const Everest::error::ErrorType& type) {
|
||||
error_manager->clear_error(type);
|
||||
}
|
||||
|
||||
void clear_error(const Everest::error::ErrorType& type, const Everest::error::ErrorSubType& sub_type) {
|
||||
error_manager->clear_error(type, sub_type);
|
||||
}
|
||||
|
||||
void clear_all_errors_of_impl() {
|
||||
error_manager->clear_all_errors();
|
||||
}
|
||||
|
||||
void clear_all_errors_of_impl(const Everest::error::ErrorType& type) {
|
||||
error_manager->clear_all_errors(type);
|
||||
}
|
||||
|
||||
std::shared_ptr<Everest::error::ErrorStateMonitor> error_state_monitor;
|
||||
std::shared_ptr<Everest::error::ErrorFactory> error_factory;
|
||||
std::shared_ptr<Everest::error::ErrorManagerImpl> error_manager;
|
||||
|
||||
std::optional<Mapping> get_mapping() {
|
||||
return impl_mapping;
|
||||
}
|
||||
|
||||
protected:
|
||||
{% if not cmds %}
|
||||
// no commands defined for this interface
|
||||
{% else %}
|
||||
// command handler functions (virtual)
|
||||
{% for cmd in cmds %}
|
||||
{{ handle_cmd_signature(cmd, none, info.interface_name) }} = 0;
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
|
||||
private:
|
||||
Everest::ModuleAdapter* const _ev;
|
||||
const std::string _name;
|
||||
std::optional<Mapping> impl_mapping;
|
||||
|
||||
// helper function for getting all commands
|
||||
void _gather_cmds([[maybe_unused]] std::vector<Everest::cmd>& cmds) override {
|
||||
{% if not cmds %}
|
||||
// this interface does not offer any commands
|
||||
{% else %}
|
||||
{% for cmd in cmds %}
|
||||
// {{ cmd.name }} command
|
||||
Everest::cmd {{ cmd.name }}_cmd;
|
||||
{{ cmd.name }}_cmd.impl_id = _name;
|
||||
{{ cmd.name }}_cmd.cmd_name = "{{ cmd.name }}";
|
||||
{% if not cmd.args %}
|
||||
// cmd {{ cmd.name }} has no arguments
|
||||
{% else %}
|
||||
{{ cmd.name }}_cmd.arg_types = {
|
||||
{% for arg in cmd.args %}
|
||||
{"{{ arg.name }}", {{ list_json_types(arg.json_type) + '}' }}{{ ',' if not loop.last }}
|
||||
{% endfor %}
|
||||
};
|
||||
{% endif %}
|
||||
{{ cmd.name }}_cmd.cmd = [this](const Parameters& args) -> Result {
|
||||
{% for arg in cmd.args %}
|
||||
{% if 'object_type' in arg %}
|
||||
auto {{ arg.name }} = args.at("{{ arg.name }}").get<{{ arg.object_type }}>();
|
||||
{% elif 'enum_type' in arg %}
|
||||
auto {{ arg.name }} = {{ string_to_enum(arg.enum_type) }}(args.at("{{ arg.name }}").get<std::string>());
|
||||
{% elif 'array_type' in arg %}
|
||||
json {{ arg.name }}_json_array = args["{{ arg.name }}"];
|
||||
{% if 'array_type_contains_enum' in arg %}
|
||||
std::vector<{{ arg.array_type }}> {{ arg.name }};
|
||||
for (auto entry : {{ arg.name }}_json_array) {
|
||||
{{ arg.name }}.push_back({{ string_to_enum(arg.array_type) }}(entry));
|
||||
}
|
||||
{% else %}
|
||||
auto {{ arg.name }} = args.at("{{ arg.name }}").get<std::vector<{{ arg.array_type }}>>();
|
||||
{% endif %}
|
||||
{% else %}
|
||||
auto {{ arg.name }} = {{ var_to_cpp(arg) }}(args.at("{{ arg.name }}"));
|
||||
{% endif %}
|
||||
{% else %}
|
||||
(void) args; // no arguments used for this callback
|
||||
{% endfor %}
|
||||
|
||||
{{ 'auto result = ' if cmd.result }}this->handle_{{ cmd.name }}(
|
||||
{%- for arg in cmd.args -%}
|
||||
{{ arg.name }}{{ ', ' if not loop.last }}
|
||||
{%- endfor -%}
|
||||
);
|
||||
{% if cmd.result and 'object_type' in cmd.result %}
|
||||
return result;
|
||||
{% elif cmd.result and 'enum_type' in cmd.result %}
|
||||
return {{ enum_to_string(cmd.result.enum_type) }}(result);
|
||||
{% else %}
|
||||
return {{ var_to_any(cmd.result, 'result') if cmd.result else 'nullptr'}};
|
||||
{% endif %}
|
||||
};
|
||||
{% if cmd.result %}
|
||||
{{ cmd.name }}_cmd.return_type = {{ list_json_types(cmd.result.json_type) }};
|
||||
{% endif %}
|
||||
cmds.emplace_back(std::move({{ cmd.name }}_cmd));
|
||||
{% if not loop.last %}
|
||||
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
};
|
||||
};
|
||||
|
||||
#endif // {{ info.hpp_guard }}
|
||||
@@ -0,0 +1,163 @@
|
||||
{% from "helper_macros.j2" import call_cmd_signature, var_to_any, var_to_cpp, print_template_info, cpp_type, result_type, print_spdx_line, string_to_enum, enum_to_string %}
|
||||
{{ print_spdx_line('Apache-2.0') }}
|
||||
#ifndef {{ info.hpp_guard }}
|
||||
#define {{ info.hpp_guard }}
|
||||
|
||||
{{ print_template_info('5') }}
|
||||
|
||||
#include <framework/ModuleAdapter.hpp>
|
||||
#include <utils/types.hpp>
|
||||
#include <utils/error.hpp>
|
||||
#include <utils/error/error_state_monitor.hpp>
|
||||
#include <utils/error/error_manager_req.hpp>
|
||||
|
||||
#include "Types.hpp"
|
||||
|
||||
class {{ info.class_name }} {
|
||||
public:
|
||||
{{ info.class_name }}(Everest::ModuleAdapter* adapter, Requirement req, const std::string& module_id, std::optional<Mapping> mapping)
|
||||
: module_id(module_id),
|
||||
_adapter(adapter),
|
||||
_req(req),
|
||||
_mapping(mapping) {
|
||||
if (adapter == nullptr) {
|
||||
EVLOG_error << "adapter is nullptr, please check the initialization of the module";
|
||||
error_manager = nullptr;
|
||||
error_state_monitor = nullptr;
|
||||
EVLOG_error << "error_manager and error_state_monitor are nullptr";
|
||||
} else {
|
||||
error_manager = adapter->get_error_manager_req(req);
|
||||
if (error_manager == nullptr) {
|
||||
EVLOG_error << "error_manager is nullptr";
|
||||
}
|
||||
error_state_monitor = adapter->get_error_state_monitor_req(req);
|
||||
if (error_state_monitor == nullptr) {
|
||||
EVLOG_error << "error_state_monitor is nullptr";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const std::string module_id;
|
||||
|
||||
{% if not vars %}
|
||||
// this interface does not export any variables to subscribe to
|
||||
{% else %}
|
||||
// variables available for subscription
|
||||
{% for var in vars %}
|
||||
void subscribe_{{ var.name }}(const std::function<void({% if var.json_type != 'null' %}const {{ cpp_type(var) }}&{% endif %})>& listener) {
|
||||
_adapter->subscribe(_req, "{{ var.name }}", [func = std::move(listener)](const Value& value) {
|
||||
{% if 'object_type' in var %}
|
||||
func(value);
|
||||
{% elif 'enum_type' in var %}
|
||||
func({{ string_to_enum(var.enum_type) }}({{ var_to_cpp(var) }}(value)));
|
||||
{% elif 'array_type' in var %}
|
||||
{% if 'array_type_contains_enum' in var %}
|
||||
std::vector<{{ var.array_type }}> typed_value;
|
||||
for (auto& entry : value) {
|
||||
typed_value.push_back({{ string_to_enum(var.array_type) }}(entry));
|
||||
}
|
||||
func(typed_value);
|
||||
{% else %}
|
||||
func(value);
|
||||
{% endif %}
|
||||
{% elif var.json_type != 'null' %}
|
||||
func({{ var_to_cpp(var) }}(value));
|
||||
{% else %}
|
||||
if (not Everest::detail::is_type_compatible<{{ cpp_type(var) }}>(value.type())) {
|
||||
EVLOG_error << "Callback for variable '{{ var.name }}' in interface '{{ info.interface }}' has wrong type!";
|
||||
}
|
||||
func();
|
||||
{% endif %}
|
||||
});
|
||||
}
|
||||
{% if not loop.last %}
|
||||
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
|
||||
void subscribe_error(
|
||||
const Everest::error::ErrorType& type,
|
||||
const Everest::error::ErrorCallback& callback,
|
||||
const Everest::error::ErrorCallback& clear_callback
|
||||
) {
|
||||
error_manager->subscribe_error(type, callback, clear_callback);
|
||||
}
|
||||
|
||||
void subscribe_all_errors(
|
||||
const Everest::error::ErrorCallback& callback,
|
||||
const Everest::error::ErrorCallback& clear_callback
|
||||
) {
|
||||
error_manager->subscribe_all_errors(callback, clear_callback);
|
||||
}
|
||||
|
||||
{% if not cmds %}
|
||||
// this interface does not export any commands to call
|
||||
{% else %}
|
||||
// commands available to call
|
||||
{% for cmd in cmds %}
|
||||
{{ call_cmd_signature(cmd, info.interface_name) }} {
|
||||
{% for arg in cmd.args %}
|
||||
{% if 'array_type' in arg %}
|
||||
{% if 'array_type_contains_enum' in arg %}
|
||||
Array {{ arg.name }}_array;
|
||||
for (const auto& {{ arg.name }}_entry : {{ arg.name }}) {
|
||||
{{ arg.name }}_array.push_back({{ enum_to_string(arg.array_type) }}({{ arg.name }}_entry));
|
||||
}
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{{ '' }}{% if cmd.result %}Result result = {% endif %}_adapter->call(_req, "{{ cmd.name }}",
|
||||
{{ 'Parameters{' }}
|
||||
{% for arg in cmd.args %}
|
||||
{% if 'enum_type' in arg %}
|
||||
{"{{ arg.name }}", {{ enum_to_string(arg.enum_type) }}({{ arg.name }})}
|
||||
{% elif 'object_type' in arg %}
|
||||
{"{{ arg.name }}", {{ arg.name }}}
|
||||
{% elif 'array_type' in arg %}
|
||||
{% if 'array_type_contains_enum' in arg %}
|
||||
{"{{ arg.name }}", {{ var_to_any(arg, arg.name + '_array') }}}
|
||||
{% else %}
|
||||
{"{{ arg.name }}", {{ var_to_any(arg, arg.name) }}}
|
||||
{% endif %}
|
||||
{% else %}
|
||||
{"{{ arg.name }}", {{ var_to_any(arg, arg.name) }}}
|
||||
{% endif%}
|
||||
{% if not loop.last %},{% endif %}
|
||||
{% endfor %}
|
||||
{{ '}' }}
|
||||
);
|
||||
{% if cmd.result %}
|
||||
{% if 'enum_type' in cmd.result %}
|
||||
auto retval = {{ string_to_enum(cmd.result.enum_type) }}({{ var_to_cpp(cmd.result) }}(result.value()));
|
||||
{% elif 'object_type' in cmd.result %}
|
||||
json retval_json = result.value();
|
||||
{{ result_type(cmd.result) }} retval = retval_json;
|
||||
{% elif 'array_type' in cmd.result %}
|
||||
{{ result_type(cmd.result) }} retval (result.value().begin(), result.value().end());
|
||||
{% else %}
|
||||
auto retval = {{ var_to_cpp(cmd.result) }}(result.value());
|
||||
{% endif %}
|
||||
return retval;
|
||||
{% endif %}
|
||||
}
|
||||
{% if not loop.last %}
|
||||
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
|
||||
std::shared_ptr<Everest::error::ErrorStateMonitor> error_state_monitor;
|
||||
|
||||
std::optional<Mapping> get_mapping() {
|
||||
return _mapping;
|
||||
}
|
||||
|
||||
private:
|
||||
std::shared_ptr<Everest::error::ErrorManagerReq> error_manager;
|
||||
Everest::ModuleAdapter* const _adapter;
|
||||
Requirement _req;
|
||||
std::optional<Mapping> _mapping;
|
||||
};
|
||||
|
||||
#endif // {{ info.hpp_guard }}
|
||||
@@ -0,0 +1,27 @@
|
||||
{% from "helper_macros.j2" import handle_cmd_signature, print_license_header %}
|
||||
{{ print_license_header(info.license_header) }}
|
||||
|
||||
#include "{{ info.class_name}}.hpp"
|
||||
|
||||
namespace module {
|
||||
namespace {{ info.interface_implementation_id }} {
|
||||
|
||||
void {{ info.class_name }}::init() {
|
||||
|
||||
}
|
||||
|
||||
void {{ info.class_name }}::ready() {
|
||||
|
||||
}
|
||||
{% for cmd in cmds %}
|
||||
|
||||
{{ handle_cmd_signature(cmd, info.class_name, '::'+info.interface) }}{
|
||||
// your code for cmd {{ cmd.name }} goes here
|
||||
{% if cmd.result %}
|
||||
return {{ cmd.result.json_type|create_dummy_result }};
|
||||
{% endif %}
|
||||
}
|
||||
{% endfor %}
|
||||
|
||||
} // namespace {{ info.interface_implementation_id }}
|
||||
} // namespace module
|
||||
@@ -0,0 +1,61 @@
|
||||
{% from "helper_macros.j2" import handle_cmd_signature, print_template_info, insert_block, cpp_type, print_license_header %}
|
||||
{{ print_license_header(info.license_header) }}
|
||||
#ifndef {{ info.hpp_guard }}
|
||||
#define {{ info.hpp_guard }}
|
||||
|
||||
{{ print_template_info('3', 'marked regions will be kept') }}
|
||||
|
||||
#include <{{ info.base_class_header }}>
|
||||
|
||||
#include "{{ info.module_header }}"
|
||||
|
||||
{{ insert_block(info.blocks.add_headers) }}
|
||||
|
||||
namespace module {
|
||||
namespace {{ info.interface_implementation_id }} {
|
||||
|
||||
struct Conf {
|
||||
{% for item in info.config %}
|
||||
{{ cpp_type(item) }} {{ item.name }};
|
||||
{% endfor %}
|
||||
};
|
||||
|
||||
class {{ info.class_name }} : public {{ info.class_parent}} {
|
||||
public:
|
||||
{{ info.class_name }}() = delete;
|
||||
{{ info.class_name }}(Everest::ModuleAdapter* ev, const Everest::PtrContainer<{{ info.module_class }}> &mod, Conf& config) :
|
||||
{{ info.class_parent }}(ev, "{{ info.interface_implementation_id }}"),
|
||||
mod(mod),
|
||||
config(config)
|
||||
{};
|
||||
|
||||
{{ insert_block(info.blocks.public_defs, indent=4) }}
|
||||
|
||||
protected:
|
||||
{% if not cmds %}
|
||||
// no commands defined for this interface
|
||||
{% else %}
|
||||
// command handler functions (virtual)
|
||||
{% for cmd in cmds %}
|
||||
{{ handle_cmd_signature(cmd, none, '::'+info.interface) }} override;
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
|
||||
{{ insert_block(info.blocks.protected_defs, indent=4) }}
|
||||
|
||||
private:
|
||||
const Everest::PtrContainer<{{ info.module_class }}>& mod;
|
||||
const Conf& config;
|
||||
|
||||
virtual void init() override;
|
||||
virtual void ready() override;
|
||||
|
||||
{{ insert_block(info.blocks.private_defs, indent=4) }}
|
||||
};
|
||||
|
||||
{{ insert_block(info.blocks.after_class) }}
|
||||
|
||||
} // namespace {{ info.interface_implementation_id }}
|
||||
} // namespace module
|
||||
|
||||
#endif // {{ info.hpp_guard }}
|
||||
@@ -0,0 +1,172 @@
|
||||
{% from "helper_macros.j2" import print_template_info, var_to_cpp, print_spdx_line %}
|
||||
{{ print_spdx_line('Apache-2.0') }}
|
||||
{{ print_template_info('5') }}
|
||||
|
||||
#include "{{ info.ld_ev_header }}"
|
||||
|
||||
#ifdef EVEREST_COVERAGE_ENABLED
|
||||
#include <everest/helpers/coverage.hpp>
|
||||
#endif
|
||||
|
||||
#include "{{ info.module_header }}"
|
||||
{% for impl in provides %}
|
||||
#include "{{ impl.class_header }}"
|
||||
{% endfor %}
|
||||
|
||||
#include <framework/runtime.hpp>
|
||||
#include <utils/types.hpp>
|
||||
#include <generated/version_information.hpp>
|
||||
#ifndef PROJECT_NAME
|
||||
#define PROJECT_NAME "undefined project"
|
||||
#endif
|
||||
#ifndef PROJECT_VERSION
|
||||
#define PROJECT_VERSION "undefined version"
|
||||
#endif
|
||||
#ifndef GIT_VERSION
|
||||
#define GIT_VERSION "undefined git version"
|
||||
#endif
|
||||
|
||||
{% if info.enable_global_errors %}
|
||||
#include <utils/error/error_manager_req_global.hpp>
|
||||
|
||||
{% endif %}
|
||||
namespace module {
|
||||
|
||||
// FIXME (aw): could this way of keeping static variables be changed somehow?
|
||||
static Everest::ModuleAdapter adapter {};
|
||||
static Everest::PtrContainer<{{info.class_name }}> mod_ptr {};
|
||||
|
||||
// per module configs
|
||||
{# FIXME (aw): instead of being static, this could also be inside a map #}
|
||||
{% for impl in provides %}
|
||||
static {{ impl.id }}::Conf {{ impl.id }}_config;
|
||||
{% endfor %}
|
||||
static Conf module_conf;
|
||||
static ModuleInfo module_info;
|
||||
|
||||
{% if info.enable_global_errors %}
|
||||
void subscribe_global_all_errors(
|
||||
const Everest::error::ErrorCallback& callback,
|
||||
const Everest::error::ErrorCallback& clear_callback
|
||||
) {
|
||||
adapter.get_global_error_manager()->subscribe_global_all_errors(callback, clear_callback);
|
||||
}
|
||||
|
||||
std::shared_ptr<Everest::error::ErrorStateMonitor> get_global_error_state_monitor() {
|
||||
return adapter.get_global_error_state_monitor();
|
||||
}
|
||||
|
||||
{% endif %}
|
||||
|
||||
std::shared_ptr<Everest::config::ConfigServiceClient> get_config_service_client() {
|
||||
return adapter.get_config_service_client();
|
||||
}
|
||||
|
||||
void LdEverest::init(ModuleConfigs module_configs, const ModuleInfo& mod_info) {
|
||||
EVLOG_debug << "init() called on module {{ info.name }}";
|
||||
|
||||
// populate config for provided implementations
|
||||
{% for impl in provides %}
|
||||
auto {{ impl.id }}_config_input = std::move(module_configs["{{ impl.id }}"]);
|
||||
{% for item in impl.config %}
|
||||
{{ impl.id }}_config.{{ item.name }} = std::get<{{ item.cpp_type }}>({{ impl.id }}_config_input["{{ item.name }}"]);
|
||||
{% endfor %}
|
||||
|
||||
{% endfor %}
|
||||
{% if info.module_config|length %}
|
||||
|
||||
{% for item in info.module_config %}
|
||||
module_conf.{{ item.name }} = std::get<{{ item.cpp_type }}>(module_configs["!module"]["{{ item.name }}"]);
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
|
||||
module_info = mod_info;
|
||||
|
||||
mod_ptr->init();
|
||||
}
|
||||
|
||||
void LdEverest::ready() {
|
||||
EVLOG_debug << "ready() called on module {{ info.name }}";
|
||||
mod_ptr->ready();
|
||||
}
|
||||
|
||||
void register_module_adapter(Everest::ModuleAdapter module_adapter) {
|
||||
adapter = std::move(module_adapter);
|
||||
}
|
||||
|
||||
std::vector<Everest::cmd> everest_register(const RequirementInitialization& requirement_init) {
|
||||
EVLOG_debug << "everest_register() called on module {{ info.name }}";
|
||||
|
||||
adapter.check_complete();
|
||||
|
||||
{% for impl in provides %}
|
||||
auto p_{{ impl.id }} = std::make_unique<{{ impl.id }}::{{ impl.class_name }}>(&adapter, mod_ptr, {{ impl.id }}_config);
|
||||
adapter.gather_cmds(*p_{{ impl.id }});
|
||||
|
||||
{% endfor %}
|
||||
{% for requirement in requires %}
|
||||
{# FIXME: needs refactoring #}
|
||||
{% if requirement.is_vector %}
|
||||
auto r_{{ requirement.id }} = std::vector<std::unique_ptr<{{ requirement.class_name }}>>();
|
||||
if (auto it = requirement_init.find("{{ requirement.id }}"); it != requirement_init.end()) {
|
||||
for (const auto& requirement_initializer : (*it).second) {
|
||||
auto requirement_module_id = requirement_initializer.fulfillment.module_id;
|
||||
auto requirement = requirement_initializer.requirement;
|
||||
auto mapping = requirement_initializer.mapping;
|
||||
r_{{ requirement.id }}.emplace_back(std::make_unique<{{ requirement.class_name }}>(&adapter, requirement, requirement_module_id, mapping));
|
||||
}
|
||||
}
|
||||
{% else %}
|
||||
std::string r_{{ requirement.id }}_requirement_module_id;
|
||||
Requirement r_{{ requirement.id }}_requirement;
|
||||
std::optional<Mapping> r_{{ requirement.id }}_mapping;
|
||||
if (auto it = requirement_init.find("{{ requirement.id }}"); it != requirement_init.end()) {
|
||||
auto requirement_initializer = (*it).second;
|
||||
if (requirement_initializer.size() > 0) {
|
||||
r_{{ requirement.id }}_requirement_module_id = requirement_initializer.at(0).fulfillment.module_id;
|
||||
r_{{ requirement.id }}_requirement = requirement_initializer.at(0).requirement;
|
||||
r_{{ requirement.id }}_mapping = requirement_initializer.at(0).mapping;
|
||||
}
|
||||
}
|
||||
auto r_{{ requirement.id }} = std::make_unique<{{ requirement.class_name }}>(&adapter, r_{{ requirement.id }}_requirement, r_{{ requirement.id }}_requirement_module_id, r_{{ requirement.id }}_mapping);
|
||||
{% endif %}
|
||||
{% else %}
|
||||
(void) requirement_init; // no requirements -> unused requirement initialization
|
||||
{% endfor %}
|
||||
|
||||
{% if info.enable_external_mqtt %}
|
||||
static Everest::MqttProvider mqtt_provider(adapter);
|
||||
{% endif %}
|
||||
static Everest::TelemetryProvider telemetry_provider(adapter);
|
||||
|
||||
static {{ info.class_name }} module(
|
||||
module_info,
|
||||
{%- if info.enable_external_mqtt %}mqtt_provider, {% endif -%}
|
||||
{%- if info.enable_telemetry %}telemetry_provider, {% endif -%}
|
||||
{%- for impl in provides -%}
|
||||
std::move(p_{{ impl.id }}){{ ', ' }}
|
||||
{%- endfor -%}
|
||||
{%- for requirement in requires -%}
|
||||
std::move(r_{{ requirement.id }}){{ ', ' }}
|
||||
{%- endfor -%}
|
||||
module_conf);
|
||||
|
||||
mod_ptr.set(&module);
|
||||
|
||||
return adapter.registered_commands;
|
||||
}
|
||||
|
||||
} // namespace module
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
#ifdef EVEREST_COVERAGE_ENABLED
|
||||
everest::helpers::install_signal_handlers_for_gcov();
|
||||
#endif
|
||||
|
||||
auto module_loader = Everest::ModuleLoader(argc, argv, Everest::ModuleCallbacks(
|
||||
module::register_module_adapter, module::everest_register,
|
||||
module::LdEverest::init, module::LdEverest::ready),
|
||||
{PROJECT_NAME, PROJECT_VERSION, GIT_VERSION});
|
||||
|
||||
return module_loader.initialize();
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
{% from "helper_macros.j2" import print_template_info, print_spdx_line %}
|
||||
{{ print_spdx_line('Apache-2.0') }}
|
||||
#ifndef {{ info.hpp_guard }}
|
||||
#define {{ info.hpp_guard }}
|
||||
|
||||
{{ print_template_info('3') }}
|
||||
|
||||
#include <framework/ModuleAdapter.hpp>
|
||||
#include <framework/everest.hpp>
|
||||
|
||||
#include <everest/logging.hpp>
|
||||
|
||||
namespace module {
|
||||
|
||||
// helper class for invoking private functions on module
|
||||
struct LdEverest {
|
||||
static void init(ModuleConfigs module_configs, const ModuleInfo& info);
|
||||
static void ready();
|
||||
};
|
||||
|
||||
void register_module_adapter(Everest::ModuleAdapter module_adapter);
|
||||
|
||||
std::vector<Everest::cmd> everest_register(const RequirementInitialization& requirement_init);
|
||||
|
||||
{% if info.enable_global_errors %}
|
||||
void subscribe_global_all_errors(
|
||||
const Everest::error::ErrorCallback& callback,
|
||||
const Everest::error::ErrorCallback& clear_callback
|
||||
);
|
||||
std::shared_ptr<Everest::error::ErrorStateMonitor> get_global_error_state_monitor();
|
||||
{% endif %}
|
||||
|
||||
std::shared_ptr<Everest::config::ConfigServiceClient> get_config_service_client();
|
||||
|
||||
} // namespace module
|
||||
|
||||
#endif // {{ info.hpp_guard }}
|
||||
@@ -0,0 +1,19 @@
|
||||
{% from "helper_macros.j2" import print_license_header %}
|
||||
{{ print_license_header(info.license_header) }}
|
||||
#include "{{ info.module_header }}"
|
||||
|
||||
namespace module {
|
||||
|
||||
void {{ info.class_name }}::init() {
|
||||
{% for impl in provides %}
|
||||
invoke_init(*p_{{ impl.id }});
|
||||
{% endfor %}
|
||||
}
|
||||
|
||||
void {{ info.class_name }}::ready() {
|
||||
{% for impl in provides %}
|
||||
invoke_ready(*p_{{ impl.id }});
|
||||
{% endfor %}
|
||||
}
|
||||
|
||||
} // namespace module
|
||||
@@ -0,0 +1,109 @@
|
||||
{% from "helper_macros.j2" import print_template_info, insert_block, cpp_type, print_license_header %}
|
||||
{{ print_license_header(info.license_header) }}
|
||||
#ifndef {{ info.hpp_guard }}
|
||||
#define {{ info.hpp_guard }}
|
||||
|
||||
{{ print_template_info('2', 'marked regions will be kept') }}
|
||||
|
||||
#include "{{ info.ld_ev_header }}"
|
||||
|
||||
{% for impl in provides %}
|
||||
{% if loop.first %}
|
||||
// headers for provided interface implementations
|
||||
{% endif %}
|
||||
#include <{{ impl.base_class_header }}>
|
||||
{% endfor %}
|
||||
|
||||
{% for interface in requires %}
|
||||
{% if loop.first %}
|
||||
// headers for required interface implementations
|
||||
{% endif %}
|
||||
#include <{{ interface.exports_header }}>
|
||||
{% endfor %}
|
||||
|
||||
{{ insert_block(info.blocks.add_headers) }}
|
||||
|
||||
namespace module {
|
||||
|
||||
struct Conf {
|
||||
{% for item in info.module_config %}
|
||||
{{ cpp_type(item) }} {{ item.name }};
|
||||
{% endfor %}
|
||||
};
|
||||
|
||||
class {{ info.class_name }} : public Everest::ModuleBase {
|
||||
public:
|
||||
{{ info.class_name }}() = delete;
|
||||
{{ info.class_name }}(
|
||||
const ModuleInfo& info,
|
||||
{% if info.enable_external_mqtt %}
|
||||
Everest::MqttProvider& mqtt_provider,
|
||||
{% endif %}
|
||||
{% if info.enable_telemetry %}
|
||||
Everest::TelemetryProvider& telemetry,
|
||||
{% endif %}
|
||||
{% for impl in provides %}
|
||||
std::unique_ptr<{{ impl.base_class }}> p_{{ impl.id }},
|
||||
{% endfor %}
|
||||
{% for requirement in requires %}
|
||||
{% if requirement.is_vector %}
|
||||
std::vector<std::unique_ptr<{{ requirement.class_name }}>> r_{{ requirement.id }},
|
||||
{% else %}
|
||||
std::unique_ptr<{{ requirement.class_name }}> r_{{ requirement.id }},
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
Conf& config
|
||||
) :
|
||||
ModuleBase(info),
|
||||
{% if info.enable_external_mqtt %}
|
||||
mqtt(mqtt_provider),
|
||||
{% endif %}
|
||||
{% if info.enable_telemetry %}
|
||||
telemetry(telemetry),
|
||||
{% endif %}
|
||||
{% for impl in provides %}
|
||||
p_{{ impl.id }}(std::move(p_{{ impl.id }})),
|
||||
{% endfor %}
|
||||
{% for requirement in requires %}
|
||||
r_{{ requirement.id }}(std::move(r_{{ requirement.id }})),
|
||||
{% endfor %}
|
||||
config(config)
|
||||
{};
|
||||
|
||||
{% if info.enable_external_mqtt %}
|
||||
Everest::MqttProvider& mqtt;
|
||||
{% endif %}
|
||||
{% if info.enable_telemetry %}
|
||||
Everest::TelemetryProvider& telemetry;
|
||||
{% endif %}
|
||||
{% for impl in provides %}
|
||||
const std::unique_ptr<{{ impl.base_class }}> p_{{ impl.id }};
|
||||
{% endfor %}
|
||||
{% for requirement in requires %}
|
||||
{% if requirement.is_vector %}
|
||||
const std::vector<std::unique_ptr<{{ requirement.class_name }}>> r_{{ requirement.id }};
|
||||
{% else %}
|
||||
const std::unique_ptr<{{ requirement.class_name }}> r_{{ requirement.id }};
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
const Conf& config;
|
||||
|
||||
{{ insert_block(info.blocks.public_defs, indent=4) }}
|
||||
|
||||
protected:
|
||||
{{ insert_block(info.blocks.protected_defs, indent=4) }}
|
||||
|
||||
private:
|
||||
friend class LdEverest;
|
||||
void init();
|
||||
void ready();
|
||||
|
||||
{{ insert_block(info.blocks.private_defs, indent=4) }}
|
||||
|
||||
};
|
||||
|
||||
{{ insert_block(info.blocks.after_class) }}
|
||||
|
||||
} // namespace module
|
||||
|
||||
#endif // {{ info.hpp_guard }}
|
||||
@@ -0,0 +1,243 @@
|
||||
{% from "helper_macros.j2" import print_template_info, print_spdx_line, string_to_enum, enum_to_string, enum_to_string_view %}
|
||||
{{ print_spdx_line('Apache-2.0') }}
|
||||
#ifndef {{ info.hpp_guard }}
|
||||
#define {{ info.hpp_guard }}
|
||||
|
||||
{{ print_template_info('5') }}
|
||||
|
||||
#include <optional>
|
||||
#include <ostream>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <tuple>
|
||||
#include <vector>
|
||||
|
||||
#include <nlohmann/json.hpp>
|
||||
|
||||
{% if 'type_headers' in info %}
|
||||
{% for type_header in info.type_headers %}
|
||||
#include <{{type_header}}>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
|
||||
using nlohmann::json;
|
||||
|
||||
{% if not enums %}
|
||||
// no enums defined for this interface
|
||||
{% else %}
|
||||
|
||||
// enums of {{ info.interface_name }}
|
||||
|
||||
{% for enum in enums %}
|
||||
{% for namespace in info.namespace %}
|
||||
namespace {{ namespace }} {
|
||||
{% endfor %}
|
||||
enum class {{ enum.enum_type}}
|
||||
{
|
||||
{% for e in enum.enum %}
|
||||
{{e}},
|
||||
{% endfor %}
|
||||
};
|
||||
|
||||
/// \brief Converts the given {{ enum.enum_type }} \p e to human readable string
|
||||
/// \returns a string representation of the {{ enum.enum_type }}
|
||||
inline std::string {{ enum.enum_type | snake_case }}_to_string(const {{ enum.enum_type }}& e) {
|
||||
switch (e) {
|
||||
{% for e in enum.enum %}
|
||||
case {{ enum.enum_type }}::{{ e }}: return "{{e}}";
|
||||
{% endfor %}
|
||||
}
|
||||
|
||||
throw std::out_of_range("No known string conversion for provided enum of type {{ enum.enum_type }}");
|
||||
}
|
||||
|
||||
/// \brief Converts the given {{ enum.enum_type }} \p e to human readable string
|
||||
/// \returns a string_view representation of the {{ enum.enum_type }}
|
||||
inline constexpr std::string_view {{ enum.enum_type | snake_case }}_to_string_view(const {{ enum.enum_type }}& e) {
|
||||
switch (e) {
|
||||
{% for e in enum.enum %}
|
||||
case {{ enum.enum_type }}::{{ e }}: return "{{e}}";
|
||||
{% endfor %}
|
||||
}
|
||||
|
||||
throw std::out_of_range("No known string conversion for provided enum of type {{ enum.enum_type }}");
|
||||
}
|
||||
|
||||
/// \brief Converts the given std::string \p s to {{ enum.enum_type }}
|
||||
/// \returns a {{ enum.enum_type }} from a string representation
|
||||
inline {{ enum.enum_type }} string_to_{{ enum.enum_type | snake_case }}(const std::string& s) {
|
||||
{% for e in enum.enum %}
|
||||
if (s == "{{e}}") {
|
||||
return {{ enum.enum_type }}::{{ e }};
|
||||
}
|
||||
{% endfor %}
|
||||
|
||||
throw std::out_of_range("Provided string " + s + " could not be converted to enum of type {{ enum.enum_type }}");
|
||||
}
|
||||
|
||||
/// \brief Writes the string representation of the given {{ enum.enum_type }} \p {{ enum.enum_type | snake_case }} to the given output stream \p os
|
||||
/// \returns an output stream with the {{ enum.enum_type }} written to
|
||||
inline std::ostream& operator<<(std::ostream& os, const types::{{ info.interface_name }}::{{ enum.enum_type }}& {{ enum.enum_type | snake_case }}) {
|
||||
os << types::{{info.interface_name}}::{{ enum.enum_type | snake_case }}_to_string({{ enum.enum_type | snake_case }});
|
||||
return os;
|
||||
}
|
||||
|
||||
{% for namespace in info.namespace|reverse %}
|
||||
} // namespace {{namespace}}
|
||||
{% endfor %}
|
||||
|
||||
{% endfor %}
|
||||
{% endif%}
|
||||
|
||||
{% if not types %}
|
||||
// no types defined for this interface
|
||||
{% else %}
|
||||
// types of {{ info.interface_name }}
|
||||
{% for namespace in info.namespace %}
|
||||
namespace {{ namespace }} {
|
||||
{% endfor %}
|
||||
|
||||
{% for parsed_type in types %}
|
||||
{% if parsed_type.properties|length > 0 %}
|
||||
struct {{ parsed_type.name }} {
|
||||
{% for property in parsed_type.properties %}
|
||||
{# Constraints will be checked by the framework #}
|
||||
{{ 'std::optional<' if not property.required -}}
|
||||
{{ property.type -}}
|
||||
{{ '>' if not property.required -}}
|
||||
{{ ' ' + property.name + ';' }} ///< {{ property.info.description }}
|
||||
{% endfor %}
|
||||
|
||||
/// \brief Conversion from a given {{ parsed_type.name }} \p k to a given json object \p j
|
||||
friend void to_json(json& j, const {{ parsed_type.name }}& k) {
|
||||
// the required parts of the type
|
||||
{% if parsed_type.properties|selectattr('required')|list|length %}
|
||||
j = json{
|
||||
{%- endif %}
|
||||
{%- for property in parsed_type.properties %}
|
||||
{%- if property.required +%}
|
||||
{"{{property.name}}",
|
||||
{%- if property.enum %} {{ enum_to_string_view(property.type) }}(k.{{ property.name }})
|
||||
{%- else %}
|
||||
{%- if property.type == 'DateTime' %} k.{{property.name}}.to_rfc3339()
|
||||
{%- else %} k.{{property.name}}
|
||||
{%- endif %}
|
||||
{%- endif %}},
|
||||
{%- endif %}
|
||||
{%- endfor %}
|
||||
{% if not parsed_type.properties|selectattr('required')|list|length %}
|
||||
j = json ({});
|
||||
{%- else +%}
|
||||
};
|
||||
{%- endif %}
|
||||
|
||||
// the optional parts of the type
|
||||
{% for property in parsed_type.properties %}
|
||||
{% if not property.required %}
|
||||
if (k.{{property.name}}) {
|
||||
{% if property.type.startswith('std::vector<') %}
|
||||
{%- if parsed_type.properties|selectattr('required')|list|length %}
|
||||
j.emplace("{{property.name}}", *k.{{property.name}});
|
||||
{%- else %}
|
||||
{#only optional keys in json#}
|
||||
{#TODO: add key to json when there are no required keys but multiple optional keys#}
|
||||
{# FIXME: this is never generated?#}
|
||||
if (j.size() == 0) {
|
||||
j = json{{'{{"'+property.name+'", json::array()}};'}}
|
||||
} else {
|
||||
j.emplace("{{property.name}}", *k.{{property.name}});
|
||||
}
|
||||
{% endif %}
|
||||
{% else %}
|
||||
{%- if property.enum %}
|
||||
j.emplace("{{property.name}}", {{ enum_to_string_view(property.type) }}(*k.{{ property.name }}));
|
||||
{%- else %}
|
||||
{%- if property.type == 'DateTime' %}
|
||||
j.emplace("{{property.name}}", k.{{property.name}}->to_rfc3339());
|
||||
{%- else %}
|
||||
j.emplace("{{property.name}}", *k.{{property.name}});
|
||||
{%- endif %}
|
||||
{%- endif %}
|
||||
{% endif %}
|
||||
|
||||
}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
}
|
||||
|
||||
/// \brief Conversion from a given json object \p j to a given {{ parsed_type.name }} \p k
|
||||
friend void from_json(const json& j, {{ parsed_type.name }}& k) {
|
||||
// the required parts of the type
|
||||
{% for property in parsed_type.properties %}
|
||||
{% if property.required %}
|
||||
{% if property.type.startswith('std::vector<') %}
|
||||
k.{{property.name}} = std::move(j.at("{{property.name}}").get<{{property.type}}>());
|
||||
{% else %}
|
||||
k.{{property.name}} =
|
||||
{%- if property.enum %} {{ string_to_enum(property.type) }}(j.at("{{property.name}}"))
|
||||
{%- else %}
|
||||
{%- if property.type == 'DateTime' %} DateTime(std::string(j.at("{{property.name}}")));
|
||||
{%- else %} j.at("{{property.name}}")
|
||||
{%- endif %}
|
||||
{%- endif %};
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{%- endfor %}
|
||||
|
||||
// the optional parts of the type
|
||||
auto it = j.end();
|
||||
{% for property in parsed_type.properties %}
|
||||
{% if not property.required %}
|
||||
it = it = j.find("{{property.name}}");
|
||||
if (it != j.end()) {
|
||||
{% if property.type.startswith('std::vector<') %}
|
||||
k.{{property.name}} = j.at("{{property.name}}").get<{{property.type}}>();
|
||||
{% else %}
|
||||
{%- if property.enum %}
|
||||
k.{{property.name}} = {{ string_to_enum(property.type) }}(it->get<std::string>());
|
||||
{%- else %}
|
||||
k.{{property.name}} = it->get<{{property.type}}>();
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
}
|
||||
|
||||
/// \brief Compares objects of type {{ parsed_type.name }} for equality
|
||||
friend constexpr bool operator==(const {{ parsed_type.name }}& k, const {{ parsed_type.name }}& l) {
|
||||
{%- for var, tuple in [('k.', 'lhs'), ('l.', 'rhs')] +%}
|
||||
const auto& {{ tuple }}_tuple = std::tie(
|
||||
{%- for property in parsed_type.properties +%}
|
||||
{{ var }}{{ property.name }}
|
||||
{%- if not loop.last %},
|
||||
{%- endif %}
|
||||
{%- endfor +%}
|
||||
);
|
||||
{%- endfor +%}
|
||||
return lhs_tuple == rhs_tuple;
|
||||
}
|
||||
|
||||
/// \brief Compares objects of type {{ parsed_type.name }} for inequality
|
||||
friend constexpr bool operator!=(const {{ parsed_type.name }}& k, const {{ parsed_type.name }}& l) {
|
||||
return not operator==(k, l);
|
||||
}
|
||||
|
||||
/// \brief Writes the string representation of the given {{ parsed_type.name }} \p k to the given output stream \p os
|
||||
/// \returns an output stream with the {{ parsed_type.name }} written to
|
||||
friend std::ostream& operator<<(std::ostream& os, const {{ parsed_type.name }}& k) {
|
||||
os << json(k).dump(4);
|
||||
return os;
|
||||
}
|
||||
|
||||
};
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{% for namespace in info.namespace|reverse %}
|
||||
} // namespace {{namespace}}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
|
||||
|
||||
#endif // {{ info.hpp_guard }}
|
||||
Reference in New Issue
Block a user