aboutsummaryrefslogtreecommitdiff
path: root/src/openvic-simulation
diff options
context:
space:
mode:
author hop311 <hop3114@gmail.com>2024-01-24 00:12:36 +0100
committer hop311 <hop3114@gmail.com>2024-01-24 00:12:36 +0100
commitc56131a7d615e20e117114e005d0a3e4c9fae2ca (patch)
treea87fef0d6ee4ba06fd2e6d720553a5c1f2d6923c /src/openvic-simulation
parent268a6948c0400905dfc335427395519689f067f5 (diff)
Made Date constexpr so that PROPERTY getters can be constexprconstexpr-date
Diffstat (limited to 'src/openvic-simulation')
-rw-r--r--src/openvic-simulation/types/Date.cpp204
-rw-r--r--src/openvic-simulation/types/Date.hpp254
-rw-r--r--src/openvic-simulation/types/IdentifierRegistry.hpp14
-rw-r--r--src/openvic-simulation/utility/Getters.hpp16
4 files changed, 204 insertions, 284 deletions
diff --git a/src/openvic-simulation/types/Date.cpp b/src/openvic-simulation/types/Date.cpp
index 37ac0b6..c63ced3 100644
--- a/src/openvic-simulation/types/Date.cpp
+++ b/src/openvic-simulation/types/Date.cpp
@@ -1,81 +1,12 @@
#include "Date.hpp"
-#include <algorithm>
-#include <cassert>
#include <cctype>
-#include <charconv>
#include "openvic-simulation/utility/Logger.hpp"
#include "openvic-simulation/utility/StringUtils.hpp"
using namespace OpenVic;
-Timespan::Timespan(day_t value) : days { value } {}
-
-bool Timespan::operator<(Timespan other) const {
- return days < other.days;
-};
-bool Timespan::operator>(Timespan other) const {
- return days > other.days;
-};
-bool Timespan::operator<=(Timespan other) const {
- return days <= other.days;
-};
-bool Timespan::operator>=(Timespan other) const {
- return days >= other.days;
-};
-bool Timespan::operator==(Timespan other) const {
- return days == other.days;
-};
-bool Timespan::operator!=(Timespan other) const {
- return days != other.days;
-};
-
-Timespan Timespan::operator+(Timespan other) const {
- return days + other.days;
-}
-
-Timespan Timespan::operator-(Timespan other) const {
- return days - other.days;
-}
-
-Timespan Timespan::operator*(day_t factor) const {
- return days * factor;
-}
-
-Timespan Timespan::operator/(day_t factor) const {
- return days / factor;
-}
-
-Timespan& Timespan::operator+=(Timespan other) {
- days += other.days;
- return *this;
-}
-
-Timespan& Timespan::operator-=(Timespan other) {
- days -= other.days;
- return *this;
-}
-
-Timespan& Timespan::operator++() {
- days++;
- return *this;
-}
-
-Timespan Timespan::operator++(int) {
- Timespan old = *this;
- ++(*this);
- return old;
-}
-
-Timespan::day_t Timespan::to_int() const {
- return days;
-}
-
-Timespan::operator day_t() const {
- return days;
-}
-
std::string Timespan::to_string() const {
return std::to_string(days);
}
@@ -84,145 +15,10 @@ Timespan::operator std::string() const {
return to_string();
}
-Timespan Timespan::from_years(day_t num) {
- return num * Date::DAYS_IN_YEAR;
-}
-
-Timespan Timespan::from_months(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::from_days(day_t num) {
- return num;
-}
-
std::ostream& OpenVic::operator<<(std::ostream& out, Timespan const& timespan) {
return out << timespan.to_string();
}
-const std::string Date::MONTH_NAMES[MONTHS_IN_YEAR] = {
- "January", "February", "March", "April", "May", "June",
- "July", "August", "September", "October", "November",
- "December"
-};
-
-Timespan Date::_date_to_timespan(year_t year, month_t month, day_t day) {
- month = std::clamp<month_t>(month, 1, MONTHS_IN_YEAR);
- day = std::clamp<day_t>(day, 1, DAYS_IN_MONTH[month - 1]);
- return year * DAYS_IN_YEAR + DAYS_UP_TO_MONTH[month - 1] + day - 1;
-}
-
-Timespan::day_t const* Date::DAYS_UP_TO_MONTH = generate_days_up_to_month();
-
-Timespan::day_t const* Date::generate_days_up_to_month() {
- static Timespan::day_t days_up_to_month[MONTHS_IN_YEAR];
- Timespan::day_t days = 0;
- int month = 0;
- while (month < MONTHS_IN_YEAR) {
- days_up_to_month[month] = days;
- days += DAYS_IN_MONTH[month++];
- }
- assert(days == DAYS_IN_YEAR);
- return days_up_to_month;
-}
-
-Date::month_t const* Date::MONTH_FROM_DAY_IN_YEAR = generate_month_from_day_in_year();
-
-Date::month_t const* Date::generate_month_from_day_in_year() {
- static month_t month_from_day_in_year[DAYS_IN_YEAR];
- Timespan::day_t days_left = 0;
- int day = 0, month = 0;
- while (day < DAYS_IN_YEAR) {
- days_left = (days_left > 0 ? days_left : DAYS_IN_MONTH[month++]) - 1;
- month_from_day_in_year[day++] = month;
- }
- assert(days_left == 0);
- assert(month_from_day_in_year[DAYS_IN_YEAR - 1] == MONTHS_IN_YEAR);
- return month_from_day_in_year;
-}
-
-Date::Date(Timespan total_days) : timespan { total_days } {
- if (timespan < 0) {
- Logger::error("Invalid timespan for date: ", timespan, " (cannot be negative)");
- timespan = 0;
- }
-}
-
-Date::Date(year_t year, month_t month, day_t day) : timespan { _date_to_timespan(year, month, day) } {}
-
-Date::year_t Date::get_year() const {
- return static_cast<Timespan::day_t>(timespan) / DAYS_IN_YEAR;
-}
-
-Date::month_t Date::get_month() const {
- return MONTH_FROM_DAY_IN_YEAR[static_cast<Timespan::day_t>(timespan) % DAYS_IN_YEAR];
-}
-
-Date::day_t Date::get_day() const {
- return (static_cast<Timespan::day_t>(timespan) % DAYS_IN_YEAR) - DAYS_UP_TO_MONTH[get_month() - 1] + 1;
-}
-
-bool Date::operator<(Date other) const {
- return timespan < other.timespan;
-};
-bool Date::operator>(Date other) const {
- return timespan > other.timespan;
-};
-bool Date::operator<=(Date other) const {
- return timespan <= other.timespan;
-};
-bool Date::operator>=(Date other) const {
- return timespan >= other.timespan;
-};
-bool Date::operator==(Date other) const {
- return timespan == other.timespan;
-};
-bool Date::operator!=(Date other) const {
- return timespan != other.timespan;
-};
-
-Date Date::operator+(Timespan other) const {
- return timespan + other;
-}
-
-Timespan Date::operator-(Date other) const {
- return timespan - other.timespan;
-}
-
-Date& Date::operator+=(Timespan other) {
- timespan += other;
- return *this;
-}
-
-Date& Date::operator-=(Timespan other) {
- timespan -= other;
- return *this;
-}
-
-Date& Date::operator++() {
- timespan++;
- return *this;
-}
-
-Date Date::operator++(int) {
- Date old = *this;
- ++(*this);
- return old;
-}
-
-bool Date::in_range(Date start, Date end) const {
- return start <= *this && *this <= end;
-}
-
-std::string const& Date::get_month_name() const {
- const month_t month = get_month();
- if (1 <= month && month <= MONTHS_IN_YEAR) {
- return MONTH_NAMES[month - 1];
- }
- static const std::string invalid_month_name = "Invalid Month";
- return invalid_month_name;
-}
-
std::string Date::to_string() const {
std::stringstream ss;
ss << *this;
diff --git a/src/openvic-simulation/types/Date.hpp b/src/openvic-simulation/types/Date.hpp
index 2bf08e8..9178e6e 100644
--- a/src/openvic-simulation/types/Date.hpp
+++ b/src/openvic-simulation/types/Date.hpp
@@ -1,6 +1,6 @@
#pragma once
-#include <climits>
+#include <algorithm>
#include <cstdint>
#include <ostream>
#include <string>
@@ -17,32 +17,70 @@ namespace OpenVic {
day_t days;
public:
- Timespan(day_t value = 0);
-
- bool operator<(Timespan other) const;
- bool operator>(Timespan other) const;
- bool operator<=(Timespan other) const;
- bool operator>=(Timespan other) const;
- bool operator==(Timespan other) const;
- bool operator!=(Timespan other) const;
-
- Timespan operator+(Timespan other) const;
- Timespan operator-(Timespan other) const;
- Timespan operator*(day_t factor) const;
- Timespan operator/(day_t factor) const;
- Timespan& operator+=(Timespan other);
- Timespan& operator-=(Timespan other);
- Timespan& operator++();
- Timespan operator++(int);
-
- day_t to_int() const;
- explicit operator day_t() const;
+ constexpr Timespan(day_t value = 0) : days { value } {}
+
+ constexpr bool operator<(Timespan other) const {
+ return days < other.days;
+ };
+ constexpr bool operator>(Timespan other) const {
+ return days > other.days;
+ };
+ constexpr bool operator<=(Timespan other) const {
+ return days <= other.days;
+ };
+ constexpr bool operator>=(Timespan other) const {
+ return days >= other.days;
+ };
+ constexpr bool operator==(Timespan other) const {
+ return days == other.days;
+ };
+ constexpr bool operator!=(Timespan other) const {
+ return days != other.days;
+ };
+
+ constexpr Timespan operator+(Timespan other) const {
+ return days + other.days;
+ }
+ constexpr Timespan operator-(Timespan other) const {
+ return days - other.days;
+ }
+ constexpr Timespan operator*(day_t factor) const {
+ return days * factor;
+ }
+ constexpr Timespan operator/(day_t factor) const {
+ return days / factor;
+ }
+ constexpr Timespan& operator+=(Timespan other) {
+ days += other.days;
+ return *this;
+ }
+ constexpr Timespan& operator-=(Timespan other) {
+ days -= other.days;
+ return *this;
+ }
+ constexpr Timespan& operator++() {
+ days++;
+ return *this;
+ }
+ constexpr Timespan operator++(int) {
+ Timespan old = *this;
+ ++(*this);
+ return old;
+ }
+
+ constexpr day_t to_int() const {
+ return days;
+ }
+ explicit constexpr operator day_t() const {
+ return days;
+ }
+
std::string to_string() const;
explicit operator std::string() const;
- static Timespan from_years(day_t num);
- static Timespan from_months(day_t num);
- static Timespan from_days(day_t num);
+ static constexpr Timespan from_years(day_t num);
+ static constexpr Timespan from_months(day_t num);
+ static constexpr Timespan from_days(day_t num);
};
std::ostream& operator<<(std::ostream& out, Timespan const& timespan);
@@ -54,69 +92,159 @@ namespace OpenVic {
using day_t = uint8_t;
static constexpr Timespan::day_t MONTHS_IN_YEAR = 12;
- static constexpr Timespan::day_t DAYS_IN_YEAR = 365;
- static constexpr Timespan::day_t DAYS_IN_MONTH[MONTHS_IN_YEAR] { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
- static Timespan::day_t const* DAYS_UP_TO_MONTH;
- static month_t const* MONTH_FROM_DAY_IN_YEAR;
+
+ static constexpr std::array<Timespan::day_t, MONTHS_IN_YEAR> DAYS_IN_MONTH {
+ 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
+ };
+
+ static constexpr Timespan::day_t DAYS_IN_YEAR { []() {
+ Timespan::day_t days = 0;
+ for (Timespan::day_t days_in_month : DAYS_IN_MONTH) {
+ days += days_in_month;
+ }
+ return days;
+ }() };
+ static_assert(DAYS_IN_YEAR == 365);
+
+ static constexpr std::array<Timespan::day_t, MONTHS_IN_YEAR> DAYS_UP_TO_MONTH { []() {
+ std::array<Timespan::day_t, MONTHS_IN_YEAR> days_up_to_month;
+ Timespan::day_t days = 0;
+ for (Timespan::day_t month = 0; month < MONTHS_IN_YEAR; month++) {
+ days_up_to_month[month] = days;
+ days += DAYS_IN_MONTH[month];
+ }
+ return days_up_to_month;
+ }() };
+
+ static constexpr std::array<month_t, DAYS_IN_YEAR> MONTH_FROM_DAY_IN_YEAR { []() {
+ std::array<month_t, DAYS_IN_YEAR> month_from_day_in_year;
+ Timespan::day_t days_left = 0;
+ month_t month = 0;
+ for (Timespan::day_t day = 0; day < DAYS_IN_YEAR; day++) {
+ days_left = (days_left > 0 ? days_left : DAYS_IN_MONTH[month++]) - 1;
+ month_from_day_in_year[day] = month;
+ }
+ return month_from_day_in_year;
+ }() };
static constexpr char SEPARATOR_CHARACTER = '.';
- static const std::string MONTH_NAMES[MONTHS_IN_YEAR];
+
+ static constexpr std::array<std::string_view, MONTHS_IN_YEAR> MONTH_NAMES {
+ "January", "February", "March", "April", "May", "June",
+ "July", "August", "September", "October", "November",
+ "December"
+ };
+ static constexpr std::string_view INVALID_MONTH_NAME = "Invalid Month";
private:
// Number of days since Jan 1st, Year 0
Timespan timespan;
- static Timespan _date_to_timespan(year_t year, month_t month, day_t day);
- static Timespan::day_t const* generate_days_up_to_month();
- static month_t const* generate_month_from_day_in_year();
+ static constexpr Timespan _date_to_timespan(year_t year, month_t month, day_t day) {
+ month = std::clamp<month_t>(month, 1, MONTHS_IN_YEAR);
+ day = std::clamp<day_t>(day, 1, DAYS_IN_MONTH[month - 1]);
+ return year * DAYS_IN_YEAR + DAYS_UP_TO_MONTH[month - 1] + day - 1;
+ }
public:
// The Timespan is considered to be the number of days since Jan 1st, Year 0
- Date(Timespan total_days);
+ constexpr Date(Timespan total_days) : timespan { total_days >= 0 ? total_days : 0 } {}
// Year month day specification
- Date(year_t year = 0, month_t month = 1, day_t day = 1);
-
- year_t get_year() const;
- month_t get_month() const;
- day_t get_day() const;
-
- bool operator<(Date other) const;
- bool operator>(Date other) const;
- bool operator<=(Date other) const;
- bool operator>=(Date other) const;
- bool operator==(Date other) const;
- bool operator!=(Date other) const;
-
- Date operator+(Timespan other) const;
- Timespan operator-(Date other) const;
- Date& operator+=(Timespan other);
- Date& operator-=(Timespan other);
- Date& operator++();
- Date operator++(int);
-
- bool in_range(Date start, Date end) const;
-
- /* This returns a std::string const&, rather than a std::string_view, as it needs to be converted to a
- * godot::StringName in order to be localised, and std::string_view to a godot::StringName conversion requires an
- * intermediary std::string. */
- std::string const& get_month_name() const;
+ constexpr Date(year_t year = 0, month_t month = 1, day_t day = 1) : timespan { _date_to_timespan(year, month, day) } {}
+
+ constexpr year_t get_year() const {
+ return static_cast<Timespan::day_t>(timespan) / DAYS_IN_YEAR;
+ }
+ constexpr month_t get_month() const {
+ return MONTH_FROM_DAY_IN_YEAR[static_cast<Timespan::day_t>(timespan) % DAYS_IN_YEAR];
+ }
+ constexpr day_t get_day() const {
+ return (static_cast<Timespan::day_t>(timespan) % DAYS_IN_YEAR) - DAYS_UP_TO_MONTH[get_month() - 1] + 1;
+ }
+
+ constexpr bool operator<(Date other) const {
+ return timespan < other.timespan;
+ };
+ constexpr bool operator>(Date other) const {
+ return timespan > other.timespan;
+ };
+ constexpr bool operator<=(Date other) const {
+ return timespan <= other.timespan;
+ };
+ constexpr bool operator>=(Date other) const {
+ return timespan >= other.timespan;
+ };
+ constexpr bool operator==(Date other) const {
+ return timespan == other.timespan;
+ };
+ constexpr bool operator!=(Date other) const {
+ return timespan != other.timespan;
+ };
+
+ constexpr Date operator+(Timespan other) const {
+ return timespan + other;
+ }
+ constexpr Timespan operator-(Date other) const {
+ return timespan - other.timespan;
+ }
+ constexpr Date& operator+=(Timespan other) {
+ timespan += other;
+ return *this;
+ }
+ constexpr Date& operator-=(Timespan other) {
+ timespan -= other;
+ return *this;
+ }
+ constexpr Date& operator++() {
+ timespan++;
+ return *this;
+ }
+ constexpr Date operator++(int) {
+ Date old = *this;
+ ++(*this);
+ return old;
+ }
+
+ constexpr bool in_range(Date start, Date end) const {
+ return start <= *this && *this <= end;
+ }
+
+ constexpr std::string_view get_month_name() const {
+ const month_t month = get_month();
+ if (1 <= month && month <= MONTHS_IN_YEAR) {
+ return MONTH_NAMES[month - 1];
+ }
+ return INVALID_MONTH_NAME;
+ }
+
std::string to_string() const;
explicit operator std::string() const;
+
// Parsed from string of the form YYYY.MM.DD
static Date from_string(char const* str, char const* end, bool* successful = nullptr, bool quiet = false);
- static Date from_string(char const* str, size_t length, bool* successful = nullptr, bool quiet = false);
+ static Date from_string(char const* str, std::size_t length, bool* successful = nullptr, bool quiet = false);
static Date from_string(std::string_view str, bool* successful = nullptr, bool quiet = false);
};
std::ostream& operator<<(std::ostream& out, Date date);
+
+ constexpr Timespan Timespan::from_years(day_t num) {
+ return num * Date::DAYS_IN_YEAR;
+ }
+ constexpr Timespan Timespan::from_months(day_t num) {
+ return (num / Date::MONTHS_IN_YEAR) * Date::DAYS_IN_YEAR + Date::DAYS_UP_TO_MONTH[num % Date::MONTHS_IN_YEAR];
+ }
+ constexpr Timespan Timespan::from_days(day_t num) {
+ return num;
+ }
}
namespace std {
template<>
struct hash<OpenVic::Date> {
- [[nodiscard]] size_t operator()(OpenVic::Date date) const {
- size_t result = 0;
+ [[nodiscard]] std::size_t operator()(OpenVic::Date date) const {
+ std::size_t result = 0;
OpenVic::utility::perfect_hash(result, date.get_day(), date.get_month(), date.get_year());
return result;
}
};
-} \ No newline at end of file
+}
diff --git a/src/openvic-simulation/types/IdentifierRegistry.hpp b/src/openvic-simulation/types/IdentifierRegistry.hpp
index 10248cc..1774bb0 100644
--- a/src/openvic-simulation/types/IdentifierRegistry.hpp
+++ b/src/openvic-simulation/types/IdentifierRegistry.hpp
@@ -158,19 +158,15 @@ namespace OpenVic {
static constexpr bool storage_type_reservable = Reservable<storage_type>;
private:
- const std::string name;
+ const std::string PROPERTY(name);
const bool log_lock;
storage_type PROPERTY_REF(items);
- bool locked = false;
+ bool PROPERTY_CUSTOM_PREFIX(locked, is);
identifier_index_map_t identifier_index_map;
public:
constexpr UniqueKeyRegistry(std::string_view new_name, bool new_log_lock = true)
- : name { new_name }, log_lock { new_log_lock } {}
-
- constexpr std::string_view get_name() const {
- return name;
- }
+ : name { new_name }, log_lock { new_log_lock }, locked { false } {}
constexpr bool add_item(
item_type&& item, NodeTools::Callback<std::string_view, std::string_view> auto duplicate_callback
@@ -206,10 +202,6 @@ namespace OpenVic {
}
}
- constexpr bool is_locked() const {
- return locked;
- }
-
constexpr void reset() {
identifier_index_map.clear();
items.clear();
diff --git a/src/openvic-simulation/utility/Getters.hpp b/src/openvic-simulation/utility/Getters.hpp
index 1fb82b1..33aa5a2 100644
--- a/src/openvic-simulation/utility/Getters.hpp
+++ b/src/openvic-simulation/utility/Getters.hpp
@@ -36,6 +36,8 @@
constexpr std::string_view get_base_type() const override { \
return ::ovdl::detail::type_name<std::decay_t<decltype(*this)>>(); }
+/* Create const and non-const reference getters for a variable, applied to its name in its declaration, e
+ * for example: GameManager PROPERTY_REF(game_manager); */
#define PROPERTY_REF(NAME) PROPERTY_REF_FULL(NAME, private)
#define PROPERTY_REF_FULL(NAME, ACCESS) \
NAME; \
@@ -49,6 +51,9 @@ public: \
ACCESS:
namespace OpenVic {
+ /* Any struct extending ReturnByValueProperty will be returned by value by PROPERTY-generated getter functions,
+ * instead of by const reference as structs are by default. Use this for small structs which don't contain any
+ * dynamically allocated memory, e.g. Date and fixed_point_t. */
struct ReturnByValueProperty {
constexpr bool operator==(ReturnByValueProperty const&) const = default;
constexpr std::strong_ordering operator<=>(ReturnByValueProperty const&) const = default;
@@ -60,18 +65,18 @@ namespace OpenVic {
*/
template<typename decl, typename T>
inline constexpr decltype(auto) _get_property(const T& property) {
- if constexpr(std::is_reference_v<decl>) {
+ 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>
+ std::integral<T> || std::floating_point<T> || std::is_enum_v<T> || std::derived_from<T, ReturnByValueProperty>
) {
/* Return value */
return T { property };
- } else if constexpr(std::is_pointer<T>::value) {
+ } else if constexpr (std::is_pointer_v<T>) {
/* Return const pointer */
return static_cast<std::add_pointer_t<std::add_const_t<std::remove_pointer_t<T>>>>(property);
} else {
@@ -79,6 +84,7 @@ namespace OpenVic {
return property;
}
}
+}
/*
* Use this on a variable declaration to generate a getter function. PROPERTY assumes the variable is private and so
@@ -101,7 +107,7 @@ namespace OpenVic {
#define PROPERTY_FULL(NAME, GETTER_NAME, ACCESS) \
NAME; \
public: \
- auto GETTER_NAME() const -> decltype(OpenVic::_get_property<decltype(NAME)>(NAME)) { \
+ constexpr auto GETTER_NAME() const -> decltype(OpenVic::_get_property<decltype(NAME)>(NAME)) { \
return OpenVic::_get_property<decltype(NAME)>(NAME); \
} \
ACCESS:
@@ -117,5 +123,3 @@ public: \
NAME = new_##NAME; \
} \
ACCESS:
-
-}