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:
Eric F
2026-06-08 00:38:27 -04:00
parent 468cfeaa50
commit d398a6ced2
7326 changed files with 1177561 additions and 7 deletions

View File

@@ -0,0 +1,16 @@
load("@rules_cc//cc:defs.bzl", "cc_library")
cc_library(
name = "everest_yaml",
srcs = ["lib/yaml_loader.cpp"],
hdrs = ["include/utils/yaml_loader.hpp"],
strip_include_prefix = "include",
cxxopts = ["-std=c++17"],
visibility = ["//visibility:public"],
deps = [
"//lib/everest/log:liblog",
"@com_github_fmtlib_fmt//:fmt",
"@com_github_nlohmann_json//:json",
"@rapidyaml",
],
)

View File

@@ -0,0 +1,48 @@
add_library(everest_yaml STATIC)
add_library(everest::yaml ALIAS everest_yaml)
ev_register_library_target(everest_yaml)
target_sources(everest_yaml
PRIVATE
lib/yaml_loader.cpp
)
target_include_directories(everest_yaml
PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}/everest>
)
target_compile_features(everest_yaml PUBLIC cxx_std_17)
set_target_properties(everest_yaml PROPERTIES
EXPORT_NAME yaml
POSITION_INDEPENDENT_CODE ON
)
target_link_libraries(everest_yaml
PUBLIC
nlohmann_json::nlohmann_json
PRIVATE
ryml::ryml
fmt::fmt
everest::log
)
if (DISABLE_EDM)
include(GNUInstallDirs)
install(
TARGETS everest_yaml
EXPORT everest-core-targets
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/everest
)
install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/include/
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/everest
FILES_MATCHING PATTERN "*.hpp"
)
endif()

View File

@@ -0,0 +1,20 @@
// SPDX-License-Identifier: Apache-2.0
// Copyright Pionix GmbH and Contributors to EVerest
#ifndef UTILS_YAML_LOADER_HPP
#define UTILS_YAML_LOADER_HPP
#include <filesystem>
#include <nlohmann/json.hpp>
namespace Everest {
/// \brief Read the YAML file at \p path and returns its content as JSON
nlohmann::ordered_json load_yaml(const std::filesystem::path& path);
/// \brief Saves the JSON \p data to a YAML file at \p path
void save_yaml(const nlohmann::ordered_json& data, const std::filesystem::path& path);
} // namespace Everest
#endif // UTILS_YAML_LOADER_HPP

View File

@@ -0,0 +1,152 @@
// SPDX-License-Identifier: Apache-2.0
// Copyright Pionix GmbH and Contributors to EVerest
#include <utils/yaml_loader.hpp>
#include <cstddef>
#include <cstring>
#include <fstream>
#include <limits>
#include <stdexcept>
#include <fmt/core.h>
#include <ryml.hpp>
#include <ryml_std.hpp>
#include <everest/logging.hpp>
namespace {
template <typename T, typename U> T constexpr clamp_to(U len) {
return (len <= std::numeric_limits<T>::max()) ? static_cast<T>(len) : std::numeric_limits<T>::max();
}
void yaml_error_handler(const char* msg, std::size_t len, ryml::Location loc, void*) {
std::stringstream error_msg;
error_msg << "YAML parsing error: ";
if (loc) {
if (not loc.name.empty()) {
error_msg.write(loc.name.str, clamp_to<std::streamsize>(loc.name.len));
error_msg << ":";
}
error_msg << loc.line << ":";
if (loc.col) {
error_msg << loc.col << ":";
}
if (loc.offset) {
error_msg << " (" << loc.offset << "B):";
}
}
error_msg.write(msg, clamp_to<std::streamsize>(len));
throw std::runtime_error(error_msg.str());
}
} // namespace
struct RymlCallbackInitializer {
RymlCallbackInitializer() {
ryml::set_callbacks({nullptr, nullptr, nullptr, yaml_error_handler});
}
};
namespace {
// NOLINTNEXTLINE(misc-no-recursion): recursive parsing preferred for simplicity
nlohmann::ordered_json ryml_to_nlohmann_json(const c4::yml::ConstNodeRef& ryml_node) {
if (ryml_node.is_map()) {
// handle object
auto object = nlohmann::ordered_json::object();
for (const auto& child : ryml_node) {
object[std::string(child.key().data(), child.key().len)] = ryml_to_nlohmann_json(child);
}
return object;
} else if (ryml_node.is_seq()) {
// handle array
auto array = nlohmann::ordered_json::array();
for (const auto& child : ryml_node) {
array.emplace_back(ryml_to_nlohmann_json(child));
}
return array;
} else if (ryml_node.empty() or ryml_node.val_is_null()) {
return nullptr;
} else {
// check type of data
const auto& value = ryml_node.val();
std::string value_string(value.data(), value.len);
const auto value_quoted = ryml_node.is_val_quoted();
if (!value_quoted) {
// check for numbers and booleans
if (ryml_node.val().is_integer()) {
return std::stoi(value_string);
} else if (ryml_node.val().is_number()) {
return std::stod(value_string);
} else if (value_string == "true") {
return true;
} else if (value_string == "false") {
return false;
}
}
// nothing matched so far, should be string
return value_string;
}
}
std::string load_yaml_content(std::filesystem::path path) {
namespace fs = std::filesystem;
if (path.extension().string() == ".json") {
EVLOG_info << fmt::format("Deprecated: called load_yaml() with .json extension ('{}')", path.string());
// try yaml first
path.replace_extension(".yaml");
} else if (path.extension().string() != ".yaml") {
throw std::runtime_error(
fmt::format("Trying to load a yaml file without yaml extension (path was '{}')", path.string()));
}
// first check for yaml, if not found try fall back to json and evlog debug deprecated
if (fs::exists(path)) {
std::ifstream ifs(path.string());
return std::string(std::istreambuf_iterator<char>(ifs), std::istreambuf_iterator<char>());
}
path.replace_extension(".json");
if (fs::exists(path)) {
EVLOG_info << "Deprecated: loaded file in json format";
std::ifstream ifs(path.string());
return std::string(std::istreambuf_iterator<char>(ifs), std::istreambuf_iterator<char>());
}
// failed to find yaml and json
throw std::runtime_error(fmt::format("File '{}.(yaml|json)' does not exist", path.stem().string()));
}
} // namespace
namespace Everest {
nlohmann::ordered_json load_yaml(const std::filesystem::path& path) {
// FIXME (aw): using the static here this isn't a perfect solution
const static RymlCallbackInitializer ryml_callback_initializer;
const auto content = load_yaml_content(path);
// FIXME (aw): using parse_in_place would be faster but that will need the file as a whole char buffer
const auto tree = ryml::parse_in_arena(ryml::to_csubstr(content));
return ryml_to_nlohmann_json(tree.rootref());
}
void save_yaml(const nlohmann::ordered_json& data, const std::filesystem::path& path) {
if (!std::filesystem::exists(path.parent_path())) {
std::filesystem::create_directory(path.parent_path());
}
// FIXME: saving yaml seems to be quite complicated, but we should be able to just emit json here...
std::ofstream ofs(path);
ofs << data << std::endl;
ofs.close();
if (!ofs) {
const int ec = errno;
throw std::runtime_error(
fmt::format("Writing user-config to '{}' failed with ec: {}", path.string(), std::strerror(ec)));
}
}
} // namespace Everest