Skip to content
Snippets Groups Projects
Verified Commit 1c5b0a5b authored by Timm Fitschen's avatar Timm Fitschen
Browse files

Remove boost::json from headers as well

parent 670638e7
Branches
Tags
2 merge requests!42Release 0.2.0,!39F remove boost rdep
Pipeline #24559 failed
......@@ -323,7 +323,7 @@ if(_LINTING)
else()
message(STATUS "clang-tidy: ${clang_tidy}")
set(_CMAKE_CXX_CLANG_TIDY_CHECKS
"--checks=*,-fuchsia-*,-llvmlibc-*,-readability-convert-member-functions-to-static,-cppcoreguidelines-pro-bounds-array-to-pointer-decay,-hicpp-no-array-decay,-llvm-else-after-return,-readability-else-after-return,-modernize-use-trailing-return-type,-bugprone-branch-clone,-altera-*")
"--checks=*,-fuchsia-*,-llvmlibc-*,-readability-convert-member-functions-to-static,-cppcoreguidelines-pro-bounds-array-to-pointer-decay,-hicpp-no-array-decay,-llvm-else-after-return,-readability-else-after-return,-modernize-use-trailing-return-type,-bugprone-branch-clone,-altera-*,-cppcoreguidelines-macro-usage,-*-avoid-c-arrays")
set(_CMAKE_C_CLANG_TIDY_CHECKS "${_CMAKE_CXX_CLANG_TIDY_CHECKS}")
set(_CMAKE_CXX_CLANG_TIDY "${clang_tidy}"
"--header-filter=caosdb/.*[^\(\.pb\.h\)]$"
......
......@@ -25,27 +25,20 @@
#include "caosdb/authentication.h" // for Authenticator, PlainPassw...
#include "caosdb/certificate_provider.h" // for CertificateProvider, path
#include "caosdb/exceptions.h" // for ConfigurationError
#include "caosdb/logging.h" // for SinkConfiguration, Loggin...
#include "caosdb/utility.h" // for load_json_file
#include <google/protobuf/arena.h> // for Arena
#include <google/protobuf/extension_set.h> // for Arena
#include <grpcpp/security/credentials.h> // for ChannelCredentials
#include <boost/json/object.hpp> // for object
#include <boost/json/value.hpp> // for value
#include <boost/json/value_ref.hpp> // for array, object
// IWYU pragma: no_include "boost/json/fwd.hpp"
#include <filesystem> // for path, exists
#include <iosfwd> // for ostream
#include <memory> // for shared_ptr, unique_ptr
#include <string> // for string
#include <filesystem> // for path, exists
#include <iosfwd> // for ostream
#include <memory> // for shared_ptr, unique_ptr
#include <string> // for string
namespace caosdb::configuration {
using boost::json::array;
using boost::json::object;
using boost::json::value;
using caosdb::authentication::Authenticator;
using caosdb::authentication::PlainPasswordAuthenticator;
using caosdb::exceptions::ConfigurationError;
using caosdb::utility::JsonValue;
using caosdb::utility::load_json_file;
using google::protobuf::Arena;
using grpc::ChannelCredentials;
......@@ -102,69 +95,6 @@ public:
[[nodiscard]] auto ToString() const -> std::string override;
};
/**
* Helper class (no state, just member functions) which should only be used by
* the ConfigurationManager to initialize the logging framework from the stored
* configuration.
*/
class LoggingConfigurationHelper {
public:
friend class ConfigurationManager;
private:
auto ConvertLogLevel(const std::string &string_level) const -> int;
auto CreateConsoleSinkConfiguration(const object &from, const std::string &name, int level) const
-> std::shared_ptr<caosdb::logging::SinkConfiguration>;
auto CreateSyslogSinkConfiguration(const object &from, const std::string &name, int level) const
-> std::shared_ptr<caosdb::logging::SinkConfiguration>;
auto CreateFileSinkConfiguration(const object &from, const std::string &name, int level) const
-> std::shared_ptr<caosdb::logging::SinkConfiguration>;
auto CreateSinkConfiguration(const object &from, const std::string &name, int default_level) const
-> std::shared_ptr<caosdb::logging::SinkConfiguration>;
auto CreateLoggingConfiguration(const object &from) const
-> caosdb::logging::LoggingConfiguration;
};
/**
* Helper class (no state, just member functions) which should only be used by
* the ConfigurationManager to construct Connection instances from the stored
* configuration.
*/
class ConnectionConfigurationHelper {
public:
friend class ConfigurationManager;
private:
/**
* @param from - a single connection configuration.
*/
auto CreateCertificateProvider(const object &from) const -> std::unique_ptr<CertificateProvider>;
/**
* @param from - a single connection configuration.
*/
auto CreateAuthenticator(const object &from) const -> std::unique_ptr<Authenticator>;
/**
* @param from - a single connection configuration.
*/
auto CreateConnectionConfiguration(const bool tls, const std::string &host, const int port,
const CertificateProvider *certificate_provider,
const Authenticator *authenticator) const
-> std::unique_ptr<ConnectionConfiguration>;
/**
* @param from - a single connection configuration.
*/
auto IsTls(const object &from) const -> bool;
/**
* @param from - a single connection configuration.
*/
auto CreateConnectionConfiguration(const object &from) const
-> std::unique_ptr<ConnectionConfiguration>;
};
/**
* Reads the configuration file and keeps the configuration. Singleton.
*
......@@ -225,13 +155,12 @@ public:
private:
Arena arena;
value json_configuration;
ConnectionConfigurationHelper connection_configuration_helper;
LoggingConfigurationHelper logging_configuration_helper;
JsonValue json_configuration;
inline ConfigurationManager(){
// InitializeDefaults();
};
inline ConfigurationManager()
: json_configuration(nullptr){
// InitializeDefaults();
};
/**
* Initialize this ConfigurationManager with the defaults.
......@@ -242,22 +171,6 @@ private:
*/
auto InitializeDefaults() -> int;
/**
* Return a json object representing the current configuration.
*/
auto GetConfiguration() const -> const object &;
/**
* Return the connection configurations.
*/
auto GetConnections() const -> const object &;
/**
* Return the configuration for the connection with the given name (as a json
* object).
*/
auto GetConnection(const std::string &name) const -> const object &;
/**
* Reset this ConfigurationManager.
*
......
......@@ -21,27 +21,14 @@
#ifndef CAOSDB_UTILS_H
#define CAOSDB_UTILS_H
#include "caosdb/data_type.h" // for AtomicDataType
#include "caosdb/entity.h" // for Importance, Role
#include <boost/beast/core/detail/base64.hpp> // for encoded_size
#include <boost/beast/core/detail/base64.ipp> // for encode
#include <boost/filesystem/string_file.hpp> // for load_string_file
#include <boost/json/stream_parser.hpp> // for stream_parser
#include <boost/json/value.hpp> // for value
#include <boost/lexical_cast.hpp> // for lexical_cast
#include <cassert> // for assert
#include <cstdlib> // for getenv
#include <filesystem> // for path
#include <fstream> // for basic_istream<>::__ist...
#include <memory> // for allocator, unique_ptr
#include <stdexcept> // for logic_error
#include <string> // for string, operator+, cha...
#include <type_traits> // for underlying_type_t
#include <typeinfo> // for type_info
#include "caosdb/data_type.h" // for AtomicDataType
#include "caosdb/entity.h" // for Importance, Role
#include <cstdlib> // for getenv
#include <filesystem> // for path
#include <fstream> // for basic_istream<>::__ist...
#include <string> // for string, operator+, cha...
namespace caosdb::utility {
using boost::json::stream_parser;
using boost::json::value;
using std::ifstream;
using std::filesystem::exists;
using std::filesystem::path;
......@@ -49,12 +36,7 @@ using std::filesystem::path;
/**
* @brief Get the name of the enum value. May be useful for higher-order CaosDB clients.
*/
template <typename Enum> auto getEnumNameFromValue(Enum v) -> std::string {
if (std::is_same_v<std::underlying_type_t<Enum>, int>) {
return boost::lexical_cast<std::string>(static_cast<int>(v));
}
throw std::logic_error(std::string("Enum type ") + typeid(v).name() + " not implemented.");
}
template <typename Enum> auto getEnumNameFromValue(Enum v) -> std::string;
// Forward declaration of specializations
template <>
......@@ -84,11 +66,7 @@ auto getEnumValueFromName<caosdb::entity::Role>(const std::string &name) -> caos
/**
* @brief Read a text file into a string and return the file's content.
*/
inline auto load_string_file(const path &file_path) -> std::string {
std::string result;
boost::filesystem::load_string_file(file_path.string(), result);
return result;
}
auto load_string_file(const path &file_path) -> std::string;
/**
* @brief Return the environment variable KEY, or FALLBACK if it does not exist.
......@@ -115,37 +93,81 @@ inline auto get_env_fallback(const std::string &key, const std::string &fallback
}
/**
* @brief Encode string as base64
* @brief JsonValue is a thin wrapper around a implementation specific
* third-party json object (e.g. boost).
*/
inline auto base64_encode(const std::string &plain) -> std::string {
auto size_plain = plain.size();
auto size_encoded = boost::beast::detail::base64::encoded_size(size_plain);
std::unique_ptr<char[]> encoded(new char[size_encoded]);
boost::beast::detail::base64::encode(encoded.get(), plain.c_str(), size_plain);
// the encoded char[] is not null terminated, so explicitely set the length
return std::string(encoded.get(), encoded.get() + size_encoded);
}
inline auto load_json_file(const path &json_file) -> value {
assert(exists(json_file));
class JsonValue {
public:
/**
* Constructor.
*
* By calling this constructor the ownership of the `wrapped` parameter is
* transferred to this object.
*/
JsonValue(void *wrapped) : wrapped(wrapped) {}
/**
* Destructor.
*
* Also deletes the `wrapped` object.
*/
~JsonValue();
/**
* Copy Constructor.
*
* Also copies the `wrapped` object.
*/
JsonValue(const JsonValue &other);
/**
* Copy Assigment.
*
* Also copies the `wrapped` object.
*/
auto operator=(const JsonValue &other) -> JsonValue & = default;
/**
* Move Constructor.
*
* Also moves the `wrapped` object.
*/
JsonValue(JsonValue &&other);
/**
* Move Assigment.
*
* Also moves the `wrapped` object.
*/
auto operator=(JsonValue &&other) -> JsonValue & = default;
/**
* Return true if the `wrapped` object is the nullptr.
*/
inline auto IsNull() const -> bool { return this->wrapped == nullptr; }
/**
* Reset this object.
*
* Also deletes `wrapped` sets it to the nullptr.
*/
auto Reset() -> void;
/**
* An object which represents a JSON value. The object's class is an
* implementation detail.
*/
void *wrapped;
};
constexpr auto buffer_size = std::size_t(4096);
auto stream = ifstream(json_file);
stream.exceptions(std::ios_base::badbit);
stream_parser parser;
auto result = std::string();
auto buffer = std::string(buffer_size, '\0');
while (stream.read(&buffer[0], buffer_size)) {
parser.write(buffer.c_str(), stream.gcount());
}
parser.write(buffer.c_str(), stream.gcount());
/**
* @brief Load json object from a json file and return it.
*/
auto load_json_file(const path &json_file) -> JsonValue;
assert(parser.done());
return parser.release();
}
/**
* @brief Encode string as base64
*/
auto base64_encode(const std::string &plain) -> std::string;
inline auto get_home_directory() -> const path {
const auto *const home = getenv("HOME");
......
......@@ -24,6 +24,7 @@
#include "caosdb/constants.h" // for LIBCAOSDB_CONF...
#include "caosdb/exceptions.h" // for ConfigurationE...
#include "caosdb/log_level.h" // for CAOSDB_DEFAULT...
#include "caosdb/logging.h" // for SinkConfiguration, Loggin...
#include "caosdb/status_code.h" // for StatusCode
#include "caosdb/utility.h" // for get_home_direc...
#include <boost/json/impl/object.hpp> // for object::at
......@@ -44,6 +45,27 @@
#include <string> // for string, operator+
#include <utility> // for move
#define WRAPPED_JSON_CONFIGURATION(obj) (static_cast<value *>((obj)->json_configuration.wrapped))
#define GET_CONNECTIONS \
if (this->json_configuration.IsNull()) { \
throw ConfigurationError("This CaosDB client has not been configured."); \
} \
assert(WRAPPED_JSON_CONFIGURATION(this)->is_object()); \
const auto &configuration = WRAPPED_JSON_CONFIGURATION(this)->as_object(); \
if (!configuration.contains("connections")) { \
throw ConfigurationError("This CaosDB client hasn't any configured connections."); \
} \
const auto &connections_value = configuration.at("connections"); \
if (connections_value.is_null()) { \
throw ConfigurationError("This CaosDB client hasn't any configured connections."); \
} \
assert(connections_value.is_object()); \
const auto &connections = connections_value.as_object(); \
if (connections.empty()) { \
throw ConfigurationError("This CaosDB client hasn't any configured connections."); \
}
namespace caosdb::configuration {
using boost::json::object;
using boost::json::value;
......@@ -151,8 +173,7 @@ auto TlsConnectionConfiguration::ToString() const -> std::string {
"," + this->certificate_provider + ")";
}
auto ConnectionConfigurationHelper::CreateCertificateProvider(const object &from) const
-> std::unique_ptr<CertificateProvider> {
auto CreateCertificateProvider(const object &from) -> std::unique_ptr<CertificateProvider> {
std::unique_ptr<CertificateProvider> certificate_provider;
if (from.contains("server_certificate_path")) {
const value &path_str = from.at("server_certificate_path");
......@@ -168,8 +189,7 @@ auto ConnectionConfigurationHelper::CreateCertificateProvider(const object &from
return certificate_provider;
}
auto ConnectionConfigurationHelper::CreateAuthenticator(const object &from) const
-> std::unique_ptr<Authenticator> {
auto CreateAuthenticator(const object &from) -> std::unique_ptr<Authenticator> {
std::unique_ptr<Authenticator> authenticator;
if (from.contains("authentication")) {
assert(from.at("authentication").is_object());
......@@ -197,9 +217,9 @@ auto ConnectionConfigurationHelper::CreateAuthenticator(const object &from) cons
return authenticator;
}
auto ConnectionConfigurationHelper::CreateConnectionConfiguration(
const bool tls, const std::string &host, const int port,
const CertificateProvider *certificate_provider, const Authenticator *authenticator) const
auto CreateConnectionConfiguration(const bool tls, const std::string &host, const int port,
const CertificateProvider *certificate_provider,
const Authenticator *authenticator)
-> std::unique_ptr<ConnectionConfiguration> {
if (tls) {
if (certificate_provider != nullptr && authenticator != nullptr) {
......@@ -220,7 +240,7 @@ auto ConnectionConfigurationHelper::CreateConnectionConfiguration(
}
}
auto ConnectionConfigurationHelper::IsTls(const object &from) const -> bool {
auto IsTls(const object &from) -> bool {
bool tls = true;
if (from.contains("tls")) {
auto tls_switch = from.at("tls");
......@@ -230,8 +250,7 @@ auto ConnectionConfigurationHelper::IsTls(const object &from) const -> bool {
return tls;
}
auto ConnectionConfigurationHelper::CreateConnectionConfiguration(const object &from) const
-> std::unique_ptr<ConnectionConfiguration> {
auto CreateConnectionConfiguration(const object &from) -> std::unique_ptr<ConnectionConfiguration> {
assert(from.contains("host"));
const auto &host = from.at("host");
assert(host.is_string());
......@@ -251,25 +270,19 @@ auto ConnectionConfigurationHelper::CreateConnectionConfiguration(const object &
certificate_provider.get(), authenticator.get());
}
auto LoggingConfigurationHelper::CreateConsoleSinkConfiguration(const object & /*from*/,
const std::string &name,
int level) const
auto CreateConsoleSinkConfiguration(const object & /*from*/, const std::string &name, int level)
-> std::shared_ptr<caosdb::logging::SinkConfiguration> {
auto result = std::make_shared<ConsoleSinkConfiguration>(name, level);
return result;
}
auto LoggingConfigurationHelper::CreateSyslogSinkConfiguration(const object & /*from*/,
const std::string &name,
int level) const
auto CreateSyslogSinkConfiguration(const object & /*from*/, const std::string &name, int level)
-> std::shared_ptr<caosdb::logging::SinkConfiguration> {
auto result = std::make_shared<SyslogSinkConfiguration>(name, level);
return result;
}
auto LoggingConfigurationHelper::CreateFileSinkConfiguration(const object &from,
const std::string &name,
int level) const
auto CreateFileSinkConfiguration(const object &from, const std::string &name, int level)
-> std::shared_ptr<caosdb::logging::SinkConfiguration> {
auto result = std::make_shared<FileSinkConfiguration>(name, level);
if (from.contains("directory")) {
......@@ -278,9 +291,21 @@ auto LoggingConfigurationHelper::CreateFileSinkConfiguration(const object &from,
return result;
}
auto LoggingConfigurationHelper::CreateSinkConfiguration(const object &from,
const std::string &name,
int default_level) const
auto ConvertLogLevel(const std::string &string_level) -> int {
static std::map<std::string, int> log_level_names = {
{"", CAOSDB_DEFAULT_LOG_LEVEL}, {"off", CAOSDB_LOG_LEVEL_OFF},
{"fatal", CAOSDB_LOG_LEVEL_FATAL}, {"error", CAOSDB_LOG_LEVEL_ERROR},
{"warn", CAOSDB_LOG_LEVEL_WARN}, {"info", CAOSDB_LOG_LEVEL_INFO},
{"debug", CAOSDB_LOG_LEVEL_DEBUG}, {"trace", CAOSDB_LOG_LEVEL_TRACE},
{"all", CAOSDB_LOG_LEVEL_ALL}};
try {
return log_level_names.at(string_level);
} catch (const std::out_of_range &exc) {
throw ConfigurationError("Unknown log level: " + string_level);
}
}
auto CreateSinkConfiguration(const object &from, const std::string &name, int default_level)
-> std::shared_ptr<caosdb::logging::SinkConfiguration> {
assert(from.contains("destination"));
const auto &destination = std::string(from.at("destination").as_string().c_str());
......@@ -299,22 +324,7 @@ auto LoggingConfigurationHelper::CreateSinkConfiguration(const object &from,
}
}
auto LoggingConfigurationHelper::ConvertLogLevel(const std::string &string_level) const -> int {
static std::map<std::string, int> log_level_names = {
{"", CAOSDB_DEFAULT_LOG_LEVEL}, {"off", CAOSDB_LOG_LEVEL_OFF},
{"fatal", CAOSDB_LOG_LEVEL_FATAL}, {"error", CAOSDB_LOG_LEVEL_ERROR},
{"warn", CAOSDB_LOG_LEVEL_WARN}, {"info", CAOSDB_LOG_LEVEL_INFO},
{"debug", CAOSDB_LOG_LEVEL_DEBUG}, {"trace", CAOSDB_LOG_LEVEL_TRACE},
{"all", CAOSDB_LOG_LEVEL_ALL}};
try {
return log_level_names.at(string_level);
} catch (const std::out_of_range &exc) {
throw ConfigurationError("Unknown log level: " + string_level);
}
}
auto LoggingConfigurationHelper::CreateLoggingConfiguration(const object &from) const
-> LoggingConfiguration {
auto CreateLoggingConfiguration(const object &from) -> LoggingConfiguration {
auto default_level_str =
from.contains("level") ? std::string(from.at("level").as_string().c_str()) : "";
int default_level = ConvertLogLevel(default_level_str);
......@@ -356,7 +366,7 @@ auto ConfigurationManager::mReset() noexcept -> int {
auto ConfigurationManager::mClear() noexcept -> int {
try {
json_configuration = value(nullptr);
json_configuration.Reset();
ConnectionManager::Reset();
return StatusCode::SUCCESS;
} catch (const caosdb::exceptions::Exception &exc) {
......@@ -369,7 +379,7 @@ auto ConfigurationManager::mClear() noexcept -> int {
}
auto ConfigurationManager::mLoadSingleJSONConfiguration(const path &json_file) -> void {
if (!json_configuration.is_null()) {
if (!json_configuration.IsNull()) {
throw ConfigurationError("This CaosDB client has already been configured.");
}
if (!exists(json_file)) {
......@@ -381,12 +391,17 @@ auto ConfigurationManager::mLoadSingleJSONConfiguration(const path &json_file) -
auto ConfigurationManager::mGetConnectionConfiguration(const std::string &name) const
-> std::unique_ptr<ConnectionConfiguration> {
auto connection_json = GetConnection(name);
return connection_configuration_helper.CreateConnectionConfiguration(connection_json);
GET_CONNECTIONS
if (connections.contains(name)) {
const auto &result_connection = connections.at(name);
assert(result_connection.is_object());
return CreateConnectionConfiguration(result_connection.as_object());
}
throw ConfigurationError("The connection '" + name + "' has not been defined.");
}
auto ConfigurationManager::mGetDefaultConnectionName() const -> std::string {
auto connections = GetConnections();
GET_CONNECTIONS
if (connections.contains("default")) {
auto default_connection = connections.at("default");
if (default_connection.is_object()) {
......@@ -406,41 +421,6 @@ auto ConfigurationManager::mGetDefaultConnectionName() const -> std::string {
throw ConfigurationError("Could not determine the default connection.");
}
auto ConfigurationManager::GetConfiguration() const -> const object & {
if (json_configuration.is_null()) {
throw ConfigurationError("This CaosDB client has not been configured.");
}
assert(json_configuration.is_object());
return json_configuration.as_object();
}
auto ConfigurationManager::GetConnections() const -> const object & {
const auto &configuration = GetConfiguration();
if (!configuration.contains("connections")) {
throw ConfigurationError("This CaosDB client hasn't any configured connections.");
}
const auto &connections_value = configuration.at("connections");
if (connections_value.is_null()) {
throw ConfigurationError("This CaosDB client hasn't any configured connections.");
}
assert(connections_value.is_object());
const auto &connections_object = connections_value.as_object();
if (connections_object.empty()) {
throw ConfigurationError("This CaosDB client hasn't any configured connections.");
}
return connections_object;
}
auto ConfigurationManager::GetConnection(const std::string &name) const -> const object & {
const auto &connections = GetConnections();
if (connections.contains(name)) {
const auto &result_connection = connections.at(name);
assert(result_connection.is_object());
return result_connection.as_object();
}
throw ConfigurationError("The connection '" + name + "' has not been defined.");
}
// TODO(tf) This has apparently a cognitive complexity of 34>25 (threshold).
auto ConfigurationManager::InitializeDefaults() -> int { // NOLINT
......@@ -488,11 +468,10 @@ auto ConfigurationManager::InitializeDefaults() -> int { // NOLINT
}
// Logging in the configuration leads to additional content.
if (this->json_configuration.is_object() &&
this->json_configuration.as_object().contains("logging")) {
if (WRAPPED_JSON_CONFIGURATION(this)->is_object() &&
WRAPPED_JSON_CONFIGURATION(this)->as_object().contains("logging")) {
LoggingConfiguration logging_configuration =
logging_configuration_helper.CreateLoggingConfiguration(
json_configuration.at("logging").as_object());
CreateLoggingConfiguration(WRAPPED_JSON_CONFIGURATION(this)->at("logging").as_object());
logging::initialize_logging(logging_configuration);
} else {
logging::initialize_logging_defaults();
......@@ -500,7 +479,7 @@ auto ConfigurationManager::InitializeDefaults() -> int { // NOLINT
"We are using the default configuration";
}
if (configuration_file_path != nullptr && this->json_configuration.is_object()) {
if (configuration_file_path != nullptr && WRAPPED_JSON_CONFIGURATION(this)->is_object()) {
CAOSDB_LOG_INFO(logger_name) << "Loaded configuration from " << *(configuration_file_path)
<< ".";
}
......
......@@ -19,18 +19,35 @@
*
*/
#include "caosdb/utility.h"
#include "caosdb/data_type.h" // for AtomicDataType, atomicdatatype_names
#include "caosdb/entity.h" // for Importance, Role, importance_names
#include <map> // for map, operator!=, _Rb_tree_const_iterator
#include <utility> // for pair
#include "caosdb/data_type.h" // for AtomicDataType, atomicdatatype_names
#include "caosdb/entity.h" // for Importance, Role, importance_names
#include <boost/beast/core/detail/base64.hpp> // for encoded_size
#include <boost/beast/core/detail/base64.ipp> // for encode
#include <boost/filesystem/string_file.hpp> // for load_string_file
#include <boost/json/stream_parser.hpp> // for stream_parser
#include <boost/json/value.hpp> // for value
#include <cassert> // for assert
#include <map> // for map, operator!=, _Rb_tree_const_iterator
#include <memory> // for allocator, unique_ptr
#include <stdexcept> // for logic_error
#include <type_traits> // for underlying_type_t
#include <typeinfo> // for type_info
#include <utility> // for pair
namespace caosdb::utility {
using boost::json::stream_parser;
using boost::json::value;
using caosdb::entity::AtomicDataType;
using caosdb::entity::Importance;
using caosdb::entity::Role;
// using emap = std::map<int, std::string>; // enum mapping
template <typename Enum> auto getEnumNameFromValue(Enum v) -> std::string {
if (std::is_same_v<std::underlying_type_t<Enum>, int>) {
return std::to_string(static_cast<int>(v));
}
throw std::logic_error(std::string("Enum type ") + typeid(v).name() + " not implemented.");
}
// Enum helper template specializations //////////////////////////////////////
template <> auto getEnumNameFromValue<Importance>(Importance v) -> std::string {
......@@ -87,4 +104,53 @@ template <> auto getEnumValueFromName<Role>(const std::string &name) -> Role {
// End of template specialization /////////////////////////////////////////////
auto load_string_file(const path &file_path) -> std::string {
std::string result;
boost::filesystem::load_string_file(file_path.string(), result);
return result;
}
auto base64_encode(const std::string &plain) -> std::string {
auto size_plain = plain.size();
auto size_encoded = boost::beast::detail::base64::encoded_size(size_plain);
std::unique_ptr<char[]> encoded(new char[size_encoded]);
boost::beast::detail::base64::encode(encoded.get(), plain.c_str(), size_plain);
// the encoded char[] is not null terminated, so explicitely set the length
return {encoded.get(), encoded.get() + size_encoded};
}
auto _load_json_file(const path &json_file) -> value {
assert(exists(json_file));
constexpr auto buffer_size = std::size_t(4096);
auto stream = ifstream(json_file);
stream.exceptions(std::ios_base::badbit);
stream_parser parser;
auto result = std::string();
auto buffer = std::string(buffer_size, '\0');
while (stream.read(&buffer[0], buffer_size)) {
parser.write(buffer.c_str(), stream.gcount());
}
parser.write(buffer.c_str(), stream.gcount());
assert(parser.done());
return parser.release();
}
auto load_json_file(const path &json_file) -> JsonValue {
return {new value(_load_json_file(json_file))};
}
JsonValue::~JsonValue() { this->Reset(); }
auto JsonValue::Reset() -> void {
if (!IsNull()) {
delete static_cast<value *>(this->wrapped);
}
this->wrapped = nullptr;
}
} // namespace caosdb::utility
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment