aboutsummaryrefslogtreecommitdiff
path: root/src/openvic-simulation/types
diff options
context:
space:
mode:
Diffstat (limited to 'src/openvic-simulation/types')
-rw-r--r--src/openvic-simulation/types/Date.cpp13
-rw-r--r--src/openvic-simulation/types/Date.hpp4
-rw-r--r--src/openvic-simulation/types/IdentifierRegistry.cpp2
-rw-r--r--src/openvic-simulation/types/IdentifierRegistry.hpp176
-rw-r--r--src/openvic-simulation/types/Vector.cpp4
-rw-r--r--src/openvic-simulation/types/Vector.hpp12
6 files changed, 131 insertions, 80 deletions
diff --git a/src/openvic-simulation/types/Date.cpp b/src/openvic-simulation/types/Date.cpp
index 27d554c..f167b7b 100644
--- a/src/openvic-simulation/types/Date.cpp
+++ b/src/openvic-simulation/types/Date.cpp
@@ -64,6 +64,19 @@ Timespan::operator std::string() const {
return to_string();
}
+Timespan Timespan::fromYears(day_t num) {
+ return num * Date::DAYS_IN_YEAR;
+}
+
+Timespan Timespan::fromMonths(day_t num) {
+ return (num / Date::MONTHS_IN_YEAR) * Date::DAYS_IN_YEAR +
+ Date::DAYS_UP_TO_MONTH[num % Date::MONTHS_IN_YEAR];
+}
+
+Timespan Timespan::fromDays(day_t num) {
+ return num;
+}
+
std::ostream& OpenVic::operator<<(std::ostream& out, Timespan const& timespan) {
return out << timespan.to_string();
}
diff --git a/src/openvic-simulation/types/Date.hpp b/src/openvic-simulation/types/Date.hpp
index b2df666..718de80 100644
--- a/src/openvic-simulation/types/Date.hpp
+++ b/src/openvic-simulation/types/Date.hpp
@@ -35,6 +35,10 @@ namespace OpenVic {
explicit operator double() const;
std::string to_string() const;
explicit operator std::string() const;
+
+ static Timespan fromYears(day_t num);
+ static Timespan fromMonths(day_t num);
+ static Timespan fromDays(day_t num);
};
std::ostream& operator<<(std::ostream& out, Timespan const& timespan);
diff --git a/src/openvic-simulation/types/IdentifierRegistry.cpp b/src/openvic-simulation/types/IdentifierRegistry.cpp
index d6afd3a..8e93cb1 100644
--- a/src/openvic-simulation/types/IdentifierRegistry.cpp
+++ b/src/openvic-simulation/types/IdentifierRegistry.cpp
@@ -9,7 +9,7 @@ HasIdentifier::HasIdentifier(std::string_view new_identifier)
assert(!identifier.empty());
}
-std::string const& HasIdentifier::get_identifier() const {
+std::string_view HasIdentifier::get_identifier() const {
return identifier;
}
diff --git a/src/openvic-simulation/types/IdentifierRegistry.hpp b/src/openvic-simulation/types/IdentifierRegistry.hpp
index 7fe2656..3ba7fc4 100644
--- a/src/openvic-simulation/types/IdentifierRegistry.hpp
+++ b/src/openvic-simulation/types/IdentifierRegistry.hpp
@@ -6,6 +6,10 @@
#include "openvic-simulation/dataloader/NodeTools.hpp"
#include "openvic-simulation/utility/Logger.hpp"
+#define REF_GETTERS(var) \
+ constexpr decltype(var)& get_##var() { return var; } \
+ constexpr decltype(var) const& get_##var() const { return var; }
+
namespace OpenVic {
/*
* Base class for objects with a non-empty string identifier,
@@ -24,7 +28,7 @@ namespace OpenVic {
HasIdentifier& operator=(HasIdentifier const&) = delete;
HasIdentifier& operator=(HasIdentifier&&) = delete;
- std::string const& get_identifier() const;
+ std::string_view get_identifier() const;
};
std::ostream& operator<<(std::ostream& stream, HasIdentifier const& obj);
@@ -68,42 +72,50 @@ namespace OpenVic {
distribution_t::value_type get_largest_item(distribution_t const& dist);
- /*
- * Template for a list of objects with unique string identifiers that can
- * be locked to prevent any further additions. The template argument T is
- * the type of object that the registry will store, and the second part ensures
- * that HasIdentifier is a base class of T.
- */
template<typename T>
- requires(std::derived_from<T, HasIdentifier>)
- class IdentifierRegistry {
- using identifier_index_map_t = std::map<std::string, size_t, std::less<void>>;
+ using get_identifier_func_t = std::string_view(T::*)(void) const;
+
+ template<typename _Base, std::derived_from<_Base> _Type, get_identifier_func_t<_Base> get_identifier,
+ typename _Storage, _Type* (*get_ptr)(_Storage&), _Type const* (*get_cptr)(_Storage const&)>
+ class UniqueKeyRegistry {
const std::string name;
const bool log_lock;
- std::vector<T> items;
+ std::vector<_Storage> items;
bool locked = false;
- identifier_index_map_t identifier_index_map;
+ string_map_t<size_t> identifier_index_map;
public:
- IdentifierRegistry(std::string_view new_name, bool new_log_lock = true)
+ using value_type = _Type;
+ using storage_type = _Storage;
+
+ UniqueKeyRegistry(std::string_view new_name, bool new_log_lock = true)
: name { new_name }, log_lock { new_log_lock } {}
- std::string const& get_name() const {
+ std::string_view get_name() const {
return name;
}
- bool add_item(T&& item) {
+ bool add_item(storage_type&& item, bool fail_on_duplicate = true) {
if (locked) {
Logger::error("Cannot add item to the ", name, " registry - locked!");
return false;
}
- T const* old_item = get_item_by_identifier(item.get_identifier());
+ value_type const* new_item = (*get_cptr)(item);
+ const std::string_view new_identifier = (new_item->*get_identifier)();
+ value_type const* old_item = get_item_by_identifier(new_identifier);
if (old_item != nullptr) {
- Logger::error("Cannot add item to the ", name, " registry - an item with the identifier \"", item.get_identifier(), "\" already exists!");
- return false;
+#define DUPLICATE_MESSAGE "Cannot add item to the ", name, " registry - an item with the identifier \"", new_identifier, "\" already exists!"
+ if (fail_on_duplicate) {
+ Logger::error(DUPLICATE_MESSAGE);
+ return false;
+ } else {
+ Logger::warning(DUPLICATE_MESSAGE);
+ return true;
+ }
+#undef DUPLICATE_MESSAGE
}
- identifier_index_map[item.get_identifier()] = items.size();
+ identifier_index_map.emplace(new_identifier, items.size());
items.push_back(std::move(item));
return true;
}
@@ -143,15 +155,15 @@ namespace OpenVic {
}
}
- T* get_item_by_identifier(std::string_view identifier) {
- const identifier_index_map_t::const_iterator it = identifier_index_map.find(identifier);
- if (it != identifier_index_map.end()) return &items[it->second];
+ value_type* get_item_by_identifier(std::string_view identifier) {
+ const typename decltype(identifier_index_map)::const_iterator it = identifier_index_map.find(identifier);
+ if (it != identifier_index_map.end()) return (*get_ptr)(items[it->second]);
return nullptr;
}
- T const* get_item_by_identifier(std::string_view identifier) const {
- const identifier_index_map_t::const_iterator it = identifier_index_map.find(identifier);
- if (it != identifier_index_map.end()) return &items[it->second];
+ value_type const* get_item_by_identifier(std::string_view identifier) const {
+ const typename decltype(identifier_index_map)::const_iterator it = identifier_index_map.find(identifier);
+ if (it != identifier_index_map.end()) return (*get_cptr)(items[it->second]);
return nullptr;
}
@@ -159,11 +171,11 @@ namespace OpenVic {
return get_item_by_identifier(identifier) != nullptr;
}
- T* get_item_by_index(size_t index) {
+ value_type* get_item_by_index(size_t index) {
return index < items.size() ? &items[index] : nullptr;
}
- T const* get_item_by_index(size_t index) const {
+ value_type const* get_item_by_index(size_t index) const {
return index < items.size() ? &items[index] : nullptr;
}
@@ -171,48 +183,38 @@ namespace OpenVic {
return get_item_by_index(index) != nullptr;
}
- std::vector<T>& get_items() {
- return items;
- }
-
- std::vector<T> const& get_items() const {
- return items;
- }
+ REF_GETTERS(items)
std::vector<std::string_view> get_item_identifiers() const {
std::vector<std::string_view> identifiers;
identifiers.reserve(items.size());
- for (identifier_index_map_t::value_type const& entry : identifier_index_map) {
+ for (typename decltype(identifier_index_map)::value_type const& entry : identifier_index_map) {
identifiers.push_back(entry.first);
}
return identifiers;
}
- NodeTools::node_callback_t expect_item_identifier(NodeTools::callback_t<T&> callback) {
- return NodeTools::expect_identifier(
- [this, callback](std::string_view identifier) -> bool {
- T* item = get_item_by_identifier(identifier);
- if (item != nullptr) return callback(*item);
- Logger::error("Invalid ", name, ": ", identifier);
- return false;
- }
- );
+ NodeTools::callback_t<std::string_view> expect_item_identifier(NodeTools::callback_t<value_type&> callback) {
+ return [this, callback](std::string_view identifier) -> bool {
+ value_type* item = get_item_by_identifier(identifier);
+ if (item != nullptr) return callback(*item);
+ Logger::error("Invalid ", name, ": ", identifier);
+ return false;
+ };
}
- NodeTools::node_callback_t expect_item_identifier(NodeTools::callback_t<T const&> callback) const {
- return NodeTools::expect_identifier(
- [this, callback](std::string_view identifier) -> bool {
- T const* item = get_item_by_identifier(identifier);
- if (item != nullptr) return callback(*item);
- Logger::error("Invalid ", name, ": ", identifier);
- return false;
- }
- );
+ NodeTools::callback_t<std::string_view> expect_item_identifier(NodeTools::callback_t<value_type const&> callback) const {
+ return [this, callback](std::string_view identifier) -> bool {
+ value_type const* item = get_item_by_identifier(identifier);
+ if (item != nullptr) return callback(*item);
+ Logger::error("Invalid ", name, ": ", identifier);
+ return false;
+ };
}
- NodeTools::node_callback_t expect_item_dictionary(NodeTools::callback_t<T&, ast::NodeCPtr> callback) {
+ NodeTools::node_callback_t expect_item_dictionary(NodeTools::callback_t<value_type&, ast::NodeCPtr> callback) {
return NodeTools::expect_dictionary([this, callback](std::string_view key, ast::NodeCPtr value) -> bool {
- T* item = get_item_by_identifier(key);
+ value_type* item = get_item_by_identifier(key);
if (item != nullptr) {
return callback(*item, value);
}
@@ -221,9 +223,9 @@ namespace OpenVic {
});
}
- NodeTools::node_callback_t expect_item_dictionary(NodeTools::callback_t<T const&, ast::NodeCPtr> callback) const {
+ NodeTools::node_callback_t expect_item_dictionary(NodeTools::callback_t<value_type const&, ast::NodeCPtr> callback) const {
return NodeTools::expect_dictionary([this, callback](std::string_view key, ast::NodeCPtr value) -> bool {
- T const* item = get_item_by_identifier(key);
+ value_type const* item = get_item_by_identifier(key);
if (item != nullptr) {
return callback(*item, value);
}
@@ -232,10 +234,10 @@ namespace OpenVic {
});
}
- NodeTools::node_callback_t expect_item_decimal_map(NodeTools::callback_t<std::map<T const*, fixed_point_t>&&> callback) const {
+ NodeTools::node_callback_t expect_item_decimal_map(NodeTools::callback_t<std::map<value_type const*, fixed_point_t>&&> callback) const {
return [this, callback](ast::NodeCPtr node) -> bool {
- std::map<T const*, fixed_point_t> map;
- bool ret = expect_item_dictionary([&map](T const& key, ast::NodeCPtr value) -> bool {
+ std::map<value_type const*, fixed_point_t> map;
+ bool ret = expect_item_dictionary([&map](value_type const& key, ast::NodeCPtr value) -> bool {
fixed_point_t val;
const bool ret = NodeTools::expect_fixed_point(NodeTools::assign_variable_callback(val))(value);
map.emplace(&key, val);
@@ -247,34 +249,64 @@ namespace OpenVic {
}
};
-#define IDENTIFIER_REGISTRY_ACCESSORS_CUSTOM_PLURAL(type, singular, plural) \
+ template<typename T>
+ [[nodiscard]] inline constexpr T* _addressof(T& v) noexcept {
+ return std::addressof<T>(v);
+ }
+
+ template<typename T>
+ const T* _addressof(const T&&) = delete;
+
+ template<typename _Base, std::derived_from<_Base> _Type, get_identifier_func_t<_Base> get_identifier>
+ using ValueRegistry = UniqueKeyRegistry<_Base, _Type, get_identifier, _Type, _addressof<_Type>, _addressof<const _Type>>;
+
+ template<typename _Type>
+ constexpr _Type* get_ptr(std::unique_ptr<_Type>& storage) {
+ return storage.get();
+ }
+ template<typename _Type>
+ constexpr _Type const* get_cptr(std::unique_ptr<_Type> const& storage) {
+ return storage.get();
+ }
+
+ template<typename _Base, std::derived_from<_Base> _Type, get_identifier_func_t<_Base> get_identifier>
+ using InstanceRegistry = UniqueKeyRegistry<_Base, _Type, get_identifier, std::unique_ptr<_Type>,
+ get_ptr<_Type>, get_cptr<_Type>>;
+
+ template<std::derived_from<HasIdentifier> _Type>
+ using IdentifierRegistry = ValueRegistry<HasIdentifier, _Type, &HasIdentifier::get_identifier>;
+
+ template<std::derived_from<HasIdentifier> _Type>
+ using IdentifierInstanceRegistry = InstanceRegistry<HasIdentifier, _Type, &HasIdentifier::get_identifier>;
+
+#define IDENTIFIER_REGISTRY_ACCESSORS_CUSTOM_PLURAL(singular, plural) \
void lock_##plural() { plural.lock(); } \
bool plural##_are_locked() const { return plural.is_locked(); } \
- type const* get_##singular##_by_identifier(std::string_view identifier) const { \
+ decltype(plural)::value_type const* get_##singular##_by_identifier(std::string_view identifier) const { \
return plural.get_item_by_identifier(identifier); } \
bool has_##singular##_identifier(std::string_view identifier) const { \
return plural.has_identifier(identifier); } \
size_t get_##singular##_count() const { \
return plural.size(); } \
- std::vector<type> const& get_##plural() const { \
+ std::vector<decltype(plural)::storage_type> const& get_##plural() const { \
return plural.get_items(); } \
std::vector<std::string_view> get_##singular##_identifiers() const { \
return plural.get_item_identifiers(); } \
- NodeTools::node_callback_t expect_##singular##_identifier(NodeTools::callback_t<type const&> callback) const { \
+ NodeTools::callback_t<std::string_view> expect_##singular##_identifier(NodeTools::callback_t<decltype(plural)::value_type const&> callback) const { \
return plural.expect_item_identifier(callback); } \
- NodeTools::node_callback_t expect_##singular##_dictionary(NodeTools::callback_t<type const&, ast::NodeCPtr> callback) const { \
+ NodeTools::node_callback_t expect_##singular##_dictionary(NodeTools::callback_t<decltype(plural)::value_type const&, ast::NodeCPtr> callback) const { \
return plural.expect_item_dictionary(callback); } \
- NodeTools::node_callback_t expect_##singular##_decimal_map(NodeTools::callback_t<std::map<type const*, fixed_point_t>&&> callback) const { \
+ NodeTools::node_callback_t expect_##singular##_decimal_map(NodeTools::callback_t<std::map<decltype(plural)::value_type const*, fixed_point_t>&&> callback) const { \
return plural.expect_item_decimal_map(callback); }
-#define IDENTIFIER_REGISTRY_NON_CONST_ACCESSORS_CUSTOM_PLURAL(type, singular, plural) \
- type* get_##singular##_by_identifier(std::string_view identifier) { \
+#define IDENTIFIER_REGISTRY_NON_CONST_ACCESSORS_CUSTOM_PLURAL(singular, plural) \
+ decltype(plural)::value_type* get_##singular##_by_identifier(std::string_view identifier) { \
return plural.get_item_by_identifier(identifier); } \
- NodeTools::node_callback_t expect_##singular##_identifier(NodeTools::callback_t<type&> callback) { \
+ NodeTools::callback_t<std::string_view> expect_##singular##_identifier(NodeTools::callback_t<decltype(plural)::value_type&> callback) { \
return plural.expect_item_identifier(callback); } \
- NodeTools::node_callback_t expect_##singular##_dictionary(NodeTools::callback_t<type&, ast::NodeCPtr> callback) { \
+ NodeTools::node_callback_t expect_##singular##_dictionary(NodeTools::callback_t<decltype(plural)::value_type&, ast::NodeCPtr> callback) { \
return plural.expect_item_dictionary(callback); }
-#define IDENTIFIER_REGISTRY_ACCESSORS(type, name) IDENTIFIER_REGISTRY_ACCESSORS_CUSTOM_PLURAL(type, name, name##s)
-#define IDENTIFIER_REGISTRY_NON_CONST_ACCESSORS(type, name) IDENTIFIER_REGISTRY_NON_CONST_ACCESSORS_CUSTOM_PLURAL(type, name, name##s)
+#define IDENTIFIER_REGISTRY_ACCESSORS(name) IDENTIFIER_REGISTRY_ACCESSORS_CUSTOM_PLURAL(name, name##s)
+#define IDENTIFIER_REGISTRY_NON_CONST_ACCESSORS(name) IDENTIFIER_REGISTRY_NON_CONST_ACCESSORS_CUSTOM_PLURAL(name, name##s)
}
diff --git a/src/openvic-simulation/types/Vector.cpp b/src/openvic-simulation/types/Vector.cpp
index aa44710..10d2dd2 100644
--- a/src/openvic-simulation/types/Vector.cpp
+++ b/src/openvic-simulation/types/Vector.cpp
@@ -76,5 +76,5 @@ constexpr std::ostream& operator<<(std::ostream& stream, vec2_t<T> const& value)
template struct OpenVic::vec2_t<int64_t>;
template struct OpenVic::vec2_t<fixed_point_t>;
-static_assert(sizeof(ivec2_t) == 2 * sizeof(int64_t), "ivec2_t size does not equal the sum of its parts' sizes");
-static_assert(sizeof(fvec2_t) == 2 * sizeof(fixed_point_t), "fvec2_t size does not equal the sum of its parts' sizes");
+static_assert(sizeof(ivec2_t) == 2 * sizeof(ivec2_t::type), "ivec2_t size does not equal the sum of its parts' sizes");
+static_assert(sizeof(fvec2_t) == 2 * sizeof(fvec2_t::type), "fvec2_t size does not equal the sum of its parts' sizes");
diff --git a/src/openvic-simulation/types/Vector.hpp b/src/openvic-simulation/types/Vector.hpp
index eecd738..9f576d7 100644
--- a/src/openvic-simulation/types/Vector.hpp
+++ b/src/openvic-simulation/types/Vector.hpp
@@ -6,6 +6,8 @@ namespace OpenVic {
template<typename T>
struct vec2_t {
+ using type = T;
+
T x, y;
constexpr vec2_t() = default;
@@ -21,21 +23,21 @@ namespace OpenVic {
constexpr T& operator[](size_t index);
constexpr T const& operator[](size_t index) const;
- template <typename S>
+ template<typename S>
constexpr friend vec2_t<S> operator+(vec2_t<S> const& left, vec2_t<S> const& right);
constexpr vec2_t& operator+=(vec2_t const& right);
- template <typename S>
+ template<typename S>
constexpr friend vec2_t<S> operator-(vec2_t<S> const& arg);
- template <typename S>
+ template<typename S>
constexpr friend vec2_t<S> operator-(vec2_t<S> const& left, vec2_t<S> const& right);
constexpr vec2_t& operator-=(vec2_t const& right);
- template <typename S>
+ template<typename S>
constexpr friend std::ostream& operator<<(std::ostream& stream, vec2_t<S> const& value);
};
- using ivec2_t = vec2_t<int64_t>;
+ using ivec2_t = vec2_t<int32_t>;
using fvec2_t = vec2_t<fixed_point_t>;
}