diff options
Diffstat (limited to 'src/openvic-simulation/utility')
-rw-r--r-- | src/openvic-simulation/utility/Getters.hpp | 66 | ||||
-rw-r--r-- | src/openvic-simulation/utility/Logger.cpp | 34 | ||||
-rw-r--r-- | src/openvic-simulation/utility/Logger.hpp | 46 | ||||
-rw-r--r-- | src/openvic-simulation/utility/StringUtils.hpp | 68 |
4 files changed, 162 insertions, 52 deletions
diff --git a/src/openvic-simulation/utility/Getters.hpp b/src/openvic-simulation/utility/Getters.hpp new file mode 100644 index 0000000..c8f2193 --- /dev/null +++ b/src/openvic-simulation/utility/Getters.hpp @@ -0,0 +1,66 @@ +#pragma once + +#include <concepts> +#include <string> +#include <string_view> + +#define REF_GETTERS(var) \ + constexpr decltype(var)& get_##var() { \ + return var; \ + } \ + constexpr decltype(var) const& get_##var() const { \ + return var; \ + } + +namespace OpenVic { + struct ReturnByValueProperty {}; + + /* + * Template function used to choose the return type and provide the implementation for the + * for variable getters created using the PROPERTY macro. + */ + template<typename decl, typename T> + inline constexpr decltype(auto) _get_property(const T& property) { + if constexpr(std::is_reference_v<decl>) { + /* Return const reference */ + return property; + } else if constexpr (std::same_as<T, std::string>) { + /* Return std::string_view looking at std::string */ + return std::string_view { property }; + } else if constexpr ( + std::integral<T> || std::floating_point<T> || std::is_enum<T>::value || std::derived_from<T, ReturnByValueProperty> + ) { + /* Return value */ + return T { property }; + } else if constexpr(std::is_pointer<T>::value) { + /* Return const pointer */ + return static_cast<std::add_pointer_t<std::add_const_t<std::remove_pointer_t<T>>>>(property); + } else { + /* Return const reference */ + return property; + } + } + +/* + * Use this on a variable delcaration to generate a getter function. It assumes the variable is private and so + * sets the accessibility modifier state back to private after declaring the getter as public. + * Examples: + * int PROPERTY(x); // int x; int get_x() const; + * const std::string PROPERTY(name); // const std::string name; std::string_view get_name() const; + * std::vector<int> PROPERTY(sizes); // std::vector<int> sizes; std::vector<int> const& get_sizes() const; + * uint8_t const* PROPERTY(data); // uint8_t const* data; uint8_t const* get_data() const; + * colour_t* PROPERTY(pixels); // colour_t* pixels; colour_t const* get_pixels() const; + * CultureGroup const& PROPERTY(group);// CultureGroup const& group; CultureGroup const& get_group() const; + * Province& PROPERTY(province); // Province& province; Province const& get_province() const; + */ +#define PROPERTY(NAME) \ + NAME; \ +\ +public: \ + auto get_##NAME() const -> decltype(OpenVic::_get_property<decltype(NAME)>(NAME)) { \ + return OpenVic::_get_property<decltype(NAME)>(NAME); \ + } \ +\ +private: + +} diff --git a/src/openvic-simulation/utility/Logger.cpp b/src/openvic-simulation/utility/Logger.cpp deleted file mode 100644 index 5e25c98..0000000 --- a/src/openvic-simulation/utility/Logger.cpp +++ /dev/null @@ -1,34 +0,0 @@ -#include "Logger.hpp" - -#include <iostream> - -using namespace OpenVic; - -void Logger::set_logger_funcs() { - Logger::set_info_func([](std::string&& str) { - std::cout << str; - }); - Logger::set_warning_func([](std::string&& str) { - std::cerr << str; - }); - Logger::set_error_func([](std::string&& str) { - std::cerr << str; - }); -} - -char const* Logger::get_filename(char const* filepath, char const* default_path) { - if (filepath == nullptr) { - return default_path; - } - char const* last_slash = filepath; - while (*filepath != '\0') { - if (*filepath == '\\' || *filepath == '/') { - last_slash = filepath + 1; - } - filepath++; - } - if (*last_slash == '\0') { - return default_path; - } - return last_slash; -} diff --git a/src/openvic-simulation/utility/Logger.hpp b/src/openvic-simulation/utility/Logger.hpp index a1c599d..20c7fdd 100644 --- a/src/openvic-simulation/utility/Logger.hpp +++ b/src/openvic-simulation/utility/Logger.hpp @@ -1,12 +1,16 @@ #pragma once #include <functional> +#include <iostream> #include <queue> #include <sstream> + #ifdef __cpp_lib_source_location #include <source_location> #endif +#include "openvic-simulation/utility/StringUtils.hpp" + namespace OpenVic { #ifndef __cpp_lib_source_location @@ -52,8 +56,17 @@ namespace OpenVic { #endif public: - static void set_logger_funcs(); - static char const* get_filename(char const* filepath, char const* default_path = nullptr); + static void set_logger_funcs() { + set_info_func([](std::string&& str) { + std::cout << "[INFO] " << str; + }); + set_warning_func([](std::string&& str) { + std::cerr << "[WARNING] " << str; + }); + set_error_func([](std::string&& str) { + std::cerr << "[ERROR] " << str; + }); + } private: struct log_channel_t { @@ -65,7 +78,7 @@ namespace OpenVic { struct log { log(log_channel_t& log_channel, Ts&&... ts, source_location const& location) { std::stringstream stream; - stream << "\n" << get_filename(location.file_name()) << "(" + stream << StringUtils::get_filename(location.file_name()) << "(" /* Function name removed to reduce clutter. It is already included * in Godot's print functions, so this was repeating it. */ //<< location.line() << ") `" << location.function_name() << "`: "; @@ -83,20 +96,21 @@ namespace OpenVic { }; #define LOG_FUNC(name) \ - private: \ - static inline log_channel_t name##_channel {}; \ - public: \ - static inline void set_##name##_func(log_func_t log_func) { \ - name##_channel.func = log_func; \ +private: \ + static inline log_channel_t name##_channel {}; \ +\ +public: \ + static inline void set_##name##_func(log_func_t log_func) { \ + name##_channel.func = log_func; \ + } \ + template<typename... Ts> \ + struct name { \ + name(Ts&&... ts, source_location const& location = source_location::current()) { \ + log<Ts...> { name##_channel, std::forward<Ts>(ts)..., location }; \ } \ - template<typename... Ts> \ - struct name { \ - name(Ts&&... ts, source_location const& location = source_location::current()) { \ - log<Ts...> { name##_channel, std::forward<Ts>(ts)..., location }; \ - } \ - }; \ - template<typename... Ts> \ - name(Ts&&...) -> name<Ts...>; + }; \ + template<typename... Ts> \ + name(Ts&&...) -> name<Ts...>; LOG_FUNC(info) LOG_FUNC(warning) diff --git a/src/openvic-simulation/utility/StringUtils.hpp b/src/openvic-simulation/utility/StringUtils.hpp index d968bf6..ede1d6b 100644 --- a/src/openvic-simulation/utility/StringUtils.hpp +++ b/src/openvic-simulation/utility/StringUtils.hpp @@ -1,4 +1,7 @@ +#pragma once + #include <cstdint> +#include <cstring> #include <limits> #include <string_view> @@ -90,7 +93,7 @@ namespace OpenVic::StringUtils { return result; } - constexpr uint64_t string_to_uint64(char const* str, size_t length, bool* successful = nullptr, int base = 10) { + inline constexpr uint64_t string_to_uint64(char const* str, size_t length, bool* successful = nullptr, int base = 10) { return string_to_uint64(str, str + length, successful, base); } @@ -135,11 +138,72 @@ namespace OpenVic::StringUtils { } } - constexpr int64_t string_to_int64(char const* str, size_t length, bool* successful = nullptr, int base = 10) { + inline constexpr int64_t string_to_int64(char const* str, size_t length, bool* successful = nullptr, int base = 10) { return string_to_int64(str, str + length, successful, base); } inline int64_t string_to_int64(std::string_view str, bool* successful = nullptr, int base = 10) { return string_to_int64(str.data(), str.length(), successful, base); } + + inline constexpr std::string_view get_filename(std::string_view path) { + size_t pos = path.size(); + while (pos > 0 && path[pos - 1] != '/' && path[pos - 1] != '\\') { + --pos; + } + path.remove_prefix(pos); + return path; + } + + inline constexpr char const* get_filename(char const* filepath, char const* default_path = nullptr) { + const std::string_view filename { get_filename(std::string_view { filepath }) }; + if (!filename.empty()) { + return filename.data(); + } + return default_path; + } + + inline std::string make_forward_slash_path(std::string_view path) { + std::string ret { path }; + std::replace(ret.begin(), ret.end(), '\\', '/'); + for (char& c : ret) { + if (c == '\\') { + c = '/'; + } + } + return ret; + } + + inline constexpr std::string_view remove_leading_slashes(std::string_view path) { + size_t count = 0; + while (count < path.size() && (path[count] == '/' || path[count] == '\\')) { + ++count; + } + path.remove_prefix(count); + return path; + } + + template<typename... Args> + requires (std::is_same_v<std::string_view, Args> && ...) + inline std::string _append_string_views(Args... args) { + std::string ret; + ret.reserve((args.size() + ...)); + (ret.append(args), ...); + return ret; + } + + template<typename... Args> + requires (std::is_convertible_v<Args, std::string_view> && ...) + inline std::string append_string_views(Args... args) { + return _append_string_views(std::string_view { args }...); + } + + inline constexpr std::string_view remove_extension(std::string_view path) { + size_t pos = path.size(); + while (pos > 0 && path[--pos] != '.') {} + if (path[pos] == '.') { + path.remove_suffix(path.size() - pos); + } + return path; + } } |