diff options
author | Hop311 <Hop3114@gmail.com> | 2024-01-24 09:49:58 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-01-24 09:49:58 +0100 |
commit | 3e2ee2cd3553cb0a5949d7a34c5ef2f10ff5c949 (patch) | |
tree | b370690ab7c7d3360d2a567f7f4ed8611aa6b23e /src/openvic-simulation | |
parent | 76d9463cc1a72c24592f79d3d7a9c8e337165d8c (diff) | |
parent | c56131a7d615e20e117114e005d0a3e4c9fae2ca (diff) |
Merge pull request #139 from OpenVicProject/constexpr-date
Made Date constexpr so that PROPERTY getters can be constexpr
Diffstat (limited to 'src/openvic-simulation')
-rw-r--r-- | src/openvic-simulation/types/Date.cpp | 204 | ||||
-rw-r--r-- | src/openvic-simulation/types/Date.hpp | 254 | ||||
-rw-r--r-- | src/openvic-simulation/types/IdentifierRegistry.hpp | 14 | ||||
-rw-r--r-- | src/openvic-simulation/utility/Getters.hpp | 16 |
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 6396e75..4d002e7 100644 --- a/src/openvic-simulation/types/IdentifierRegistry.hpp +++ b/src/openvic-simulation/types/IdentifierRegistry.hpp @@ -185,19 +185,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 @@ -233,10 +229,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: - -} |