aboutsummaryrefslogtreecommitdiff
path: root/src/openvic-simulation/utility
diff options
context:
space:
mode:
Diffstat (limited to 'src/openvic-simulation/utility')
-rw-r--r--src/openvic-simulation/utility/Getters.hpp66
-rw-r--r--src/openvic-simulation/utility/Logger.cpp34
-rw-r--r--src/openvic-simulation/utility/Logger.hpp46
-rw-r--r--src/openvic-simulation/utility/StringUtils.hpp68
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;
+ }
}