From 21c476c56f3e2405fdebf26149e9db0dfbb1271a Mon Sep 17 00:00:00 2001 From: "liuhaibo.2020" Date: Fri, 9 Oct 2020 20:54:43 +0800 Subject: [PATCH] update Duration --- .vscode/c_cpp_properties.json | 6 +- projects/kiwano/kiwano.vcxproj | 2 + projects/kiwano/kiwano.vcxproj.filters | 6 + src/kiwano/2d/DebugActor.cpp | 2 +- src/kiwano/core/Duration.cpp | 191 +++++++++++ src/kiwano/core/Duration.h | 433 +++++++++++++++++++++++++ src/kiwano/core/Time.cpp | 355 +------------------- src/kiwano/core/Time.h | 230 +------------ 8 files changed, 649 insertions(+), 576 deletions(-) create mode 100644 src/kiwano/core/Duration.cpp create mode 100644 src/kiwano/core/Duration.h diff --git a/.vscode/c_cpp_properties.json b/.vscode/c_cpp_properties.json index de7425e9..1eb88ef5 100644 --- a/.vscode/c_cpp_properties.json +++ b/.vscode/c_cpp_properties.json @@ -3,7 +3,8 @@ { "name": "Mac", "includePath": [ - "${workspaceFolder}/src/**" + "${workspaceFolder}/src", + "${workspaceFolder}/src/3rd-party" ], "defines": [ "TARGET_OS_MAC" @@ -19,7 +20,8 @@ { "name": "Linux", "includePath": [ - "${workspaceFolder}/src/**" + "${workspaceFolder}/src", + "${workspaceFolder}/src/3rd-party" ], "defines": [], "compilerPath": "/usr/bin/gcc", diff --git a/projects/kiwano/kiwano.vcxproj b/projects/kiwano/kiwano.vcxproj index 9007e707..64816eec 100644 --- a/projects/kiwano/kiwano.vcxproj +++ b/projects/kiwano/kiwano.vcxproj @@ -24,6 +24,7 @@ + @@ -139,6 +140,7 @@ + diff --git a/projects/kiwano/kiwano.vcxproj.filters b/projects/kiwano/kiwano.vcxproj.filters index e89b444b..2717e40a 100644 --- a/projects/kiwano/kiwano.vcxproj.filters +++ b/projects/kiwano/kiwano.vcxproj.filters @@ -132,6 +132,9 @@ core + + core + render @@ -599,6 +602,9 @@ render + + core + diff --git a/src/kiwano/2d/DebugActor.cpp b/src/kiwano/2d/DebugActor.cpp index c0ca5cba..5c0cf791 100644 --- a/src/kiwano/2d/DebugActor.cpp +++ b/src/kiwano/2d/DebugActor.cpp @@ -77,7 +77,7 @@ void DebugActor::OnRender(RenderContext& ctx) ctx.DrawTextLayout(debug_text_, Point(10, 10)); frame_buffer_.PushBack(Time::Now()); - while (frame_buffer_.Back() - frame_buffer_.Front() >= Duration::Second) + while (frame_buffer_.Back() - frame_buffer_.Front() >= time::Second) { frame_buffer_.PopFront(); } diff --git a/src/kiwano/core/Duration.cpp b/src/kiwano/core/Duration.cpp new file mode 100644 index 00000000..f06a706d --- /dev/null +++ b/src/kiwano/core/Duration.cpp @@ -0,0 +1,191 @@ +// Copyright (c) 2016-2018 Kiwano - Nomango +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +#include // std::regex +#include // std::unordered_map +#include // std::chrono::milliseconds +#include // std::this_thread::sleep_for +#include +#include // KGE_THROW + +namespace kiwano +{ + +const Duration time::Millisecond = 1L; +const Duration time::Second = 1000 * time::Millisecond; +const Duration time::Minute = 60 * time::Second; +const Duration time::Hour = 60 * time::Minute; + +namespace +{ +const auto duration_regex = std::regex(R"(^[-+]?([0-9]*(\.[0-9]*)?(h|m|s|ms)+)+$)"); + +typedef std::unordered_map UnitMap; + +const auto unit_map = UnitMap{ { "ms", time::Millisecond }, { "s", time::Second }, { "m", time::Minute }, { "h", time::Hour } }; +} // namespace + +float Duration::GetSeconds() const +{ + auto sec = milliseconds_ / time::Second.milliseconds_; + auto ms = milliseconds_ % time::Second.milliseconds_; + return static_cast(sec + ms) / 1000.f; +} + +float Duration::GetMinutes() const +{ + auto min = milliseconds_ / time::Minute.milliseconds_; + auto ms = milliseconds_ % time::Minute.milliseconds_; + return static_cast(min + ms) / (60 * 1000.f); +} + +float Duration::GetHours() const +{ + auto hour = milliseconds_ / time::Hour.milliseconds_; + auto ms = milliseconds_ % time::Hour.milliseconds_; + return static_cast(hour + ms) / (60 * 60 * 1000.f); +} + +void Duration::Sleep() const +{ + using std::chrono::milliseconds; + using std::this_thread::sleep_for; + + if (milliseconds_) + { + sleep_for(milliseconds(milliseconds_)); + } +} + +String Duration::ToString() const +{ + if (IsZero()) + { + return String("0s"); + } + + StringStream stream; + + int64_t total_ms = milliseconds_; + if (total_ms < 0) + { + stream << "-"; + total_ms = -total_ms; + } + + int64_t hour = total_ms / time::Hour.milliseconds_; + int64_t min = total_ms / time::Minute.milliseconds_ - hour * 60; + int64_t sec = total_ms / time::Second.milliseconds_ - (hour * 60 * 60 + min * 60); + int64_t ms = total_ms % time::Second.milliseconds_; + + if (hour) + { + stream << hour << 'h' << min << 'm'; + } + else if (min) + { + stream << min << 'm'; + } + + if (ms != 0) + { + stream << float(sec) + float(ms) / 1000.f << 's'; + } + else if (sec != 0) + { + stream << sec << 's'; + } + return stream.str(); +} + +Duration Duration::Parse(const String& format) +{ + bool negative = false; + size_t len = format.length(); + size_t pos = 0; + Duration ret; + + if (!std::regex_match(format.c_str(), duration_regex)) + { + KGE_THROW("Duration::Parse failed, invalid duration"); + } + + if (format.empty() || format == "0") + { + return ret; + } + + // 符号位 + if (format[0] == '-' || format[0] == '+') + { + negative = (format[0] == '-'); + pos++; + } + + while (pos < len) + { + // 数值 + size_t i = pos; + for (; i < len; ++i) + { + wchar_t ch = format[i]; + if (!(ch == '.' || '0' <= ch && ch <= '9')) + { + break; + } + } + + String num_str = format.substr(pos, i - pos); + + pos = i; + + if (num_str.empty() || num_str == ".") + KGE_THROW("Duration::Parse failed, invalid duration"); + + // 单位 + for (; i < len; ++i) + { + wchar_t ch = format[i]; + if (ch == '.' || '0' <= ch && ch <= '9') + { + break; + } + } + + String unit_str = format.substr(pos, i - pos); + + pos = i; + + if (unit_map.find(unit_str) == unit_map.end()) + KGE_THROW("Duration::Parse failed, invalid duration"); + + double num = std::stod(num_str.c_str()); + Duration unit = unit_map.at(unit_str); + ret += unit * num; + } + + if (negative) + { + ret = -ret; + } + return ret; +} + +} // namespace kiwano diff --git a/src/kiwano/core/Duration.h b/src/kiwano/core/Duration.h new file mode 100644 index 00000000..7afd81ff --- /dev/null +++ b/src/kiwano/core/Duration.h @@ -0,0 +1,433 @@ +// Copyright (c) 2016-2018 Kiwano - Nomango +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +#pragma once +#include + +namespace kiwano +{ + +/** + * \~chinese + * @brief 时间段 + * @par + * 时间段表示法: + * @code + * time::Millisecond * 50 // 50 毫秒 + * time::Second * 5 // 5 秒 + * time::Hour * 1.5 // 1.5 小时 + * time::Hour * 3 + time::Minute * 45 + time::Second * 15 // 3 小时 45 分 15秒 + * @endcode + * 在 VS2015 及更高版本可以使用 time literals: + * @code + * using namespace kiwano; + * 50_msec // 50 毫秒 + * 5_sec // 5 秒 + * 1.5_hour // 1.5 小时 + * 3_hour + 45_min + 15_sec // 3 小时 45 分 15 秒 + * @endcode + */ +struct KGE_API Duration +{ + /// \~chinese + /// @brief 构造时间段 + Duration(); + + /// \~chinese + /// @brief 构造时间段 + /// @param milliseconds 毫秒数 + Duration(int64_t milliseconds); + + /// \~chinese + /// @brief 获取毫秒数 + int64_t GetMilliseconds() const; + + /// \~chinese + /// @brief 获取秒数 + float GetSeconds() const; + + /// \~chinese + /// @brief 获取分钟数 + float GetMinutes() const; + + /// \~chinese + /// @brief 获取小时数 + float GetHours() const; + + /// \~chinese + /// @brief 时长是否是零 + /// @return 若时长是零,返回true + bool IsZero() const; + + /// \~chinese + /// @brief 设置毫秒数 + /// @param ms 毫秒数 + void SetMilliseconds(int64_t ms); + + /// \~chinese + /// @brief 设置秒数 + /// @param seconds 秒数 + void SetSeconds(float seconds); + + /// \~chinese + /// @brief 设置分钟数 + /// @param minutes 分钟数 + void SetMinutes(float minutes); + + /// \~chinese + /// @brief 设置小时数 + /// @param hours 小时数 + void SetHours(float hours); + + /// \~chinese + /// @brief 休眠 + void Sleep() const; + + /// \~chinese + /// @brief 转为字符串 + String ToString() const; + + /// \~chinese + /// @brief 解析时间段字符串 + /// @param str 时间段字符串 + /// @details + /// 时间段字符串允许是有符号的浮点数, 并且带有时间单位后缀 + /// 例如: "300ms", "-1.5h", "2h45m" + /// 允许的时间单位有 "ms", "s", "m", "h" + /// @return 解析出的时间段 + /// @throw kiwano::RuntimeError 传入一个不合法的格式时抛出 + static Duration Parse(const String& str); + + bool operator==(const Duration&) const; + bool operator!=(const Duration&) const; + bool operator>(const Duration&) const; + bool operator>=(const Duration&) const; + bool operator<(const Duration&) const; + bool operator<=(const Duration&) const; + + float operator/(const Duration&) const; + + const Duration operator+(const Duration&) const; + const Duration operator-(const Duration&) const; + const Duration operator-() const; + const Duration operator*(int)const; + const Duration operator*(unsigned long long)const; + const Duration operator*(float)const; + const Duration operator*(double)const; + const Duration operator*(long double)const; + const Duration operator/(int) const; + const Duration operator/(float) const; + const Duration operator/(double) const; + + Duration& operator+=(const Duration&); + Duration& operator-=(const Duration&); + Duration& operator*=(int); + Duration& operator*=(float); + Duration& operator*=(double); + Duration& operator/=(int); + Duration& operator/=(float); + Duration& operator/=(double); + + friend const Duration operator*(int, const Duration&); + friend const Duration operator*(float, const Duration&); + friend const Duration operator*(double, const Duration&); + friend const Duration operator*(long double, const Duration&); + friend const Duration operator/(int, const Duration&); + friend const Duration operator/(float, const Duration&); + friend const Duration operator/(double, const Duration&); + +private: + int64_t milliseconds_; +}; + +namespace time +{ + +extern const Duration Millisecond; ///< 毫秒 +extern const Duration Second; ///< 秒 +extern const Duration Minute; ///< 分钟 +extern const Duration Hour; ///< 小时 + +} // namespace time + +inline Duration::Duration() + : milliseconds_(0) +{ +} + +inline Duration::Duration(int64_t milliseconds) + : milliseconds_(milliseconds) +{ +} + +inline int64_t Duration::GetMilliseconds() const +{ + return milliseconds_; +} + +inline bool Duration::IsZero() const +{ + return milliseconds_ == 0LL; +} + +inline void Duration::SetMilliseconds(int64_t ms) +{ + milliseconds_ = ms; +} + +inline void Duration::SetSeconds(float seconds) +{ + milliseconds_ = static_cast(seconds * 1000.f); +} + +inline void Duration::SetMinutes(float minutes) +{ + milliseconds_ = static_cast(minutes * 60 * 1000.f); +} + +inline void Duration::SetHours(float hours) +{ + milliseconds_ = static_cast(hours * 60 * 60 * 1000.f); +} + +inline bool Duration::operator==(const Duration& other) const +{ + return milliseconds_ == other.milliseconds_; +} + +inline bool Duration::operator!=(const Duration& other) const +{ + return milliseconds_ != other.milliseconds_; +} + +inline bool Duration::operator>(const Duration& other) const +{ + return milliseconds_ > other.milliseconds_; +} + +inline bool Duration::operator>=(const Duration& other) const +{ + return milliseconds_ >= other.milliseconds_; +} + +inline bool Duration::operator<(const Duration& other) const +{ + return milliseconds_ < other.milliseconds_; +} + +inline bool Duration::operator<=(const Duration& other) const +{ + return milliseconds_ <= other.milliseconds_; +} + +inline float Duration::operator/(const Duration& other) const +{ + return static_cast(milliseconds_) / other.milliseconds_; +} + +inline const Duration Duration::operator+(const Duration& other) const +{ + return Duration(milliseconds_ + other.milliseconds_); +} + +inline const Duration Duration::operator-(const Duration& other) const +{ + return Duration(milliseconds_ - other.milliseconds_); +} + +inline const Duration Duration::operator-() const +{ + return Duration(-milliseconds_); +} + +inline const Duration Duration::operator*(int val) const +{ + return Duration(milliseconds_ * val); +} + +inline const Duration Duration::operator*(unsigned long long val) const +{ + return Duration(static_cast(milliseconds_ * val)); +} + +inline const Duration Duration::operator*(float val) const +{ + return Duration(static_cast(milliseconds_ * val)); +} + +inline const Duration Duration::operator*(double val) const +{ + return Duration(static_cast(milliseconds_ * val)); +} + +inline const Duration Duration::operator*(long double val) const +{ + return Duration(static_cast(milliseconds_ * val)); +} + +inline const Duration Duration::operator/(int val) const +{ + return Duration(milliseconds_ / val); +} + +inline const Duration Duration::operator/(float val) const +{ + return Duration(static_cast(milliseconds_ / val)); +} + +inline const Duration Duration::operator/(double val) const +{ + return Duration(static_cast(milliseconds_ / val)); +} + +inline Duration& Duration::operator+=(const Duration& other) +{ + milliseconds_ += other.milliseconds_; + return (*this); +} + +inline Duration& Duration::operator-=(const Duration& other) +{ + milliseconds_ -= other.milliseconds_; + return (*this); +} + +inline Duration& Duration::operator*=(int val) +{ + milliseconds_ *= val; + return (*this); +} + +inline Duration& Duration::operator/=(int val) +{ + milliseconds_ = static_cast(milliseconds_ / val); + return (*this); +} + +inline Duration& Duration::operator*=(float val) +{ + milliseconds_ = static_cast(milliseconds_ * val); + return (*this); +} + +inline Duration& Duration::operator/=(float val) +{ + milliseconds_ = static_cast(milliseconds_ / val); + return (*this); +} + +inline Duration& Duration::operator*=(double val) +{ + milliseconds_ = static_cast(milliseconds_ * val); + return (*this); +} + +inline Duration& Duration::operator/=(double val) +{ + milliseconds_ = static_cast(milliseconds_ / val); + return (*this); +} + +inline const Duration operator*(int val, const Duration& dur) +{ + return dur * val; +} + +inline const Duration operator/(int val, const Duration& dur) +{ + return dur / val; +} + +inline const Duration operator*(float val, const Duration& dur) +{ + return dur * val; +} + +inline const Duration operator/(float val, const Duration& dur) +{ + return dur / val; +} + +inline const Duration operator*(double val, const Duration& dur) +{ + return dur * val; +} + +inline const Duration operator/(double val, const Duration& dur) +{ + return dur / val; +} + +inline const Duration operator*(long double val, const Duration& dur) +{ + return dur * val; +} + +} // namespace kiwano + +#if defined(KGE_HAS_LITERALS) + +namespace kiwano +{ +inline namespace literals +{ +inline const kiwano::Duration operator"" _msec(long double val) +{ + return kiwano::time::Millisecond * val; +} + +inline const kiwano::Duration operator"" _msec(unsigned long long val) +{ + return kiwano::time::Millisecond * val; +} + +inline const kiwano::Duration operator"" _sec(long double val) +{ + return kiwano::time::Second * val; +} + +inline const kiwano::Duration operator"" _sec(unsigned long long val) +{ + return kiwano::time::Second * val; +} + +inline const kiwano::Duration operator"" _min(long double val) +{ + return kiwano::time::Minute * val; +} + +inline const kiwano::Duration operator"" _min(unsigned long long val) +{ + return kiwano::time::Minute * val; +} + +inline const kiwano::Duration operator"" _hour(long double val) +{ + return kiwano::time::Hour * val; +} + +inline const kiwano::Duration operator"" _hour(unsigned long long val) +{ + return kiwano::time::Hour * val; +} +} // namespace literals +} // namespace kiwano + +#endif diff --git a/src/kiwano/core/Time.cpp b/src/kiwano/core/Time.cpp index 091bf3a9..f340d06e 100644 --- a/src/kiwano/core/Time.cpp +++ b/src/kiwano/core/Time.cpp @@ -18,12 +18,8 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. -#include -#include -#include -#include +#include // std::chrono #include -#include namespace kiwano { @@ -180,353 +176,4 @@ ClockTime& ClockTime::operator-=(const Duration& other) return (*this); } -//------------------------------------------------------- -// Duration -//------------------------------------------------------- - -const Duration Duration::Ms = 1L; -const Duration Duration::Second = 1000 * Duration::Ms; -const Duration Duration::Minute = 60 * Duration::Second; -const Duration Duration::Hour = 60 * Duration::Minute; - -namespace -{ -const auto duration_regex = std::regex(R"(^[-+]?([0-9]*(\.[0-9]*)?(h|m|s|ms)+)+$)"); - -typedef std::unordered_map UnitMap; - -const auto unit_map = - UnitMap{ { "ms", Duration::Ms }, { "s", Duration::Second }, { "m", Duration::Minute }, { "h", Duration::Hour } }; - -} // namespace - -Duration::Duration() - : milliseconds_(0) -{ -} - -Duration::Duration(int64_t milliseconds) - : milliseconds_(milliseconds) -{ -} - -float Duration::GetSeconds() const -{ - auto sec = milliseconds_ / Second.milliseconds_; - auto ms = milliseconds_ % Second.milliseconds_; - return static_cast(sec + ms) / 1000.f; -} - -float Duration::GetMinutes() const -{ - auto min = milliseconds_ / Minute.milliseconds_; - auto ms = milliseconds_ % Minute.milliseconds_; - return static_cast(min + ms) / (60 * 1000.f); -} - -float Duration::GetHours() const -{ - auto hour = milliseconds_ / Hour.milliseconds_; - auto ms = milliseconds_ % Hour.milliseconds_; - return static_cast(hour + ms) / (60 * 60 * 1000.f); -} - -void Duration::Sleep() const -{ - using std::chrono::milliseconds; - using std::this_thread::sleep_for; - - if (milliseconds_) - { - sleep_for(milliseconds(milliseconds_)); - } -} - -String Duration::ToString() const -{ - if (IsZero()) - { - return String("0s"); - } - - StringStream stream; - - int64_t total_ms = milliseconds_; - if (total_ms < 0) - { - stream << "-"; - total_ms = -total_ms; - } - - int64_t hour = total_ms / Hour.milliseconds_; - int64_t min = total_ms / Minute.milliseconds_ - hour * 60; - int64_t sec = total_ms / Second.milliseconds_ - (hour * 60 * 60 + min * 60); - int64_t ms = total_ms % Second.milliseconds_; - - if (hour) - { - stream << hour << 'h' << min << 'm'; - } - else if (min) - { - stream << min << 'm'; - } - - if (ms != 0) - { - stream << float(sec) + float(ms) / 1000.f << 's'; - } - else if (sec != 0) - { - stream << sec << 's'; - } - return stream.str(); -} - -bool Duration::operator==(const Duration& other) const -{ - return milliseconds_ == other.milliseconds_; -} - -bool Duration::operator!=(const Duration& other) const -{ - return milliseconds_ != other.milliseconds_; -} - -bool Duration::operator>(const Duration& other) const -{ - return milliseconds_ > other.milliseconds_; -} - -bool Duration::operator>=(const Duration& other) const -{ - return milliseconds_ >= other.milliseconds_; -} - -bool Duration::operator<(const Duration& other) const -{ - return milliseconds_ < other.milliseconds_; -} - -bool Duration::operator<=(const Duration& other) const -{ - return milliseconds_ <= other.milliseconds_; -} - -float Duration::operator/(const Duration& other) const -{ - return static_cast(milliseconds_) / other.milliseconds_; -} - -const Duration Duration::operator+(const Duration& other) const -{ - return Duration(milliseconds_ + other.milliseconds_); -} - -const Duration Duration::operator-(const Duration& other) const -{ - return Duration(milliseconds_ - other.milliseconds_); -} - -const Duration Duration::operator-() const -{ - return Duration(-milliseconds_); -} - -const Duration Duration::operator*(int val) const -{ - return Duration(milliseconds_ * val); -} - -const Duration Duration::operator*(unsigned long long val) const -{ - return Duration(static_cast(milliseconds_ * val)); -} - -const Duration Duration::operator*(float val) const -{ - return Duration(static_cast(milliseconds_ * val)); -} - -const Duration Duration::operator*(double val) const -{ - return Duration(static_cast(milliseconds_ * val)); -} - -const Duration Duration::operator*(long double val) const -{ - return Duration(static_cast(milliseconds_ * val)); -} - -const Duration Duration::operator/(int val) const -{ - return Duration(milliseconds_ / val); -} - -const Duration Duration::operator/(float val) const -{ - return Duration(static_cast(milliseconds_ / val)); -} - -const Duration Duration::operator/(double val) const -{ - return Duration(static_cast(milliseconds_ / val)); -} - -Duration& Duration::operator+=(const Duration& other) -{ - milliseconds_ += other.milliseconds_; - return (*this); -} - -Duration& Duration::operator-=(const Duration& other) -{ - milliseconds_ -= other.milliseconds_; - return (*this); -} - -Duration& Duration::operator*=(int val) -{ - milliseconds_ *= val; - return (*this); -} - -Duration& Duration::operator/=(int val) -{ - milliseconds_ = static_cast(milliseconds_ / val); - return (*this); -} - -Duration& Duration::operator*=(float val) -{ - milliseconds_ = static_cast(milliseconds_ * val); - return (*this); -} - -Duration& Duration::operator/=(float val) -{ - milliseconds_ = static_cast(milliseconds_ / val); - return (*this); -} - -Duration& Duration::operator*=(double val) -{ - milliseconds_ = static_cast(milliseconds_ * val); - return (*this); -} - -Duration& Duration::operator/=(double val) -{ - milliseconds_ = static_cast(milliseconds_ / val); - return (*this); -} - -const Duration operator*(int val, const Duration& dur) -{ - return dur * val; -} - -const Duration operator/(int val, const Duration& dur) -{ - return dur / val; -} - -const Duration operator*(float val, const Duration& dur) -{ - return dur * val; -} - -const Duration operator/(float val, const Duration& dur) -{ - return dur / val; -} - -const Duration operator*(double val, const Duration& dur) -{ - return dur * val; -} - -const Duration operator/(double val, const Duration& dur) -{ - return dur / val; -} - -const Duration operator*(long double val, const Duration& dur) -{ - return dur * val; -} - -Duration Duration::Parse(const String& format) -{ - bool negative = false; - size_t len = format.length(); - size_t pos = 0; - Duration ret; - - if (!std::regex_match(format.c_str(), duration_regex)) - { - KGE_THROW("Duration::Parse failed, invalid duration"); - } - - if (format.empty() || format == "0") - { - return ret; - } - - // 符号位 - if (format[0] == '-' || format[0] == '+') - { - negative = (format[0] == '-'); - pos++; - } - - while (pos < len) - { - // 数值 - size_t i = pos; - for (; i < len; ++i) - { - wchar_t ch = format[i]; - if (!(ch == '.' || '0' <= ch && ch <= '9')) - { - break; - } - } - - String num_str = format.substr(pos, i - pos); - - pos = i; - - if (num_str.empty() || num_str == ".") - KGE_THROW("Duration::Parse failed, invalid duration"); - - // 单位 - for (; i < len; ++i) - { - wchar_t ch = format[i]; - if (ch == '.' || '0' <= ch && ch <= '9') - { - break; - } - } - - String unit_str = format.substr(pos, i - pos); - - pos = i; - - if (unit_map.find(unit_str) == unit_map.end()) - KGE_THROW("Duration::Parse failed, invalid duration"); - - double num = std::stod(num_str.c_str()); - Duration unit = unit_map.at(unit_str); - ret += unit * num; - } - - if (negative) - { - ret = -ret; - } - return ret; -} - } // namespace kiwano diff --git a/src/kiwano/core/Time.h b/src/kiwano/core/Time.h index 3d80185d..c34ba234 100644 --- a/src/kiwano/core/Time.h +++ b/src/kiwano/core/Time.h @@ -19,150 +19,12 @@ // THE SOFTWARE. #pragma once -#include +#include #include namespace kiwano { -/** - * \~chinese - * @brief 时间段 - * @par - * 时间段表示法: - * @code - * Duration::Ms * 50 // 50 毫秒 - * Duration::Second * 5 // 5 秒 - * Duration::Hour * 1.5 // 1.5 小时 - * Duration::Hour * 3 + Duration::Minute * 45 + Duration::Second * 15 // 3 小时 45 分 15秒 - * @endcode - * 在 VS2015 及更高版本可以使用 time literals: - * @code - * using namespace kiwano; - * 50_msec // 50 毫秒 - * 5_sec // 5 秒 - * 1.5_hour // 1.5 小时 - * 3_hour + 45_min + 15_sec // 3 小时 45 分 15 秒 - * @endcode - */ -struct KGE_API Duration -{ - /// \~chinese - /// @brief 构造时间段 - Duration(); - - /// \~chinese - /// @brief 构造时间段 - /// @param milliseconds 毫秒数 - Duration(int64_t milliseconds); - - /// \~chinese - /// @brief 获取毫秒数 - int64_t GetMilliseconds() const; - - /// \~chinese - /// @brief 获取秒数 - float GetSeconds() const; - - /// \~chinese - /// @brief 获取分钟数 - float GetMinutes() const; - - /// \~chinese - /// @brief 获取小时数 - float GetHours() const; - - /// \~chinese - /// @brief 时长是否是零 - /// @return 若时长是零,返回true - bool IsZero() const; - - /// \~chinese - /// @brief 设置毫秒数 - /// @param ms 毫秒数 - void SetMilliseconds(int64_t ms); - - /// \~chinese - /// @brief 设置秒数 - /// @param seconds 秒数 - void SetSeconds(float seconds); - - /// \~chinese - /// @brief 设置分钟数 - /// @param minutes 分钟数 - void SetMinutes(float minutes); - - /// \~chinese - /// @brief 设置小时数 - /// @param hours 小时数 - void SetHours(float hours); - - /// \~chinese - /// @brief 休眠 - void Sleep() const; - - /// \~chinese - /// @brief 转为字符串 - String ToString() const; - - /// \~chinese - /// @brief 解析时间段字符串 - /// @param str 时间段字符串 - /// @details - /// 时间段字符串允许是有符号的浮点数, 并且带有时间单位后缀 - /// 例如: "300ms", "-1.5h", "2h45m" - /// 允许的时间单位有 "ms", "s", "m", "h" - /// @return 解析出的时间段 - /// @throw kiwano::RuntimeError 传入一个不合法的格式时抛出 - static Duration Parse(const String& str); - - static const Duration Ms; ///< 毫秒 - static const Duration Second; ///< 秒 - static const Duration Minute; ///< 分钟 - static const Duration Hour; ///< 小时 - - bool operator==(const Duration&) const; - bool operator!=(const Duration&) const; - bool operator>(const Duration&) const; - bool operator>=(const Duration&) const; - bool operator<(const Duration&) const; - bool operator<=(const Duration&) const; - - float operator/(const Duration&) const; - - const Duration operator+(const Duration&) const; - const Duration operator-(const Duration&) const; - const Duration operator-() const; - const Duration operator*(int)const; - const Duration operator*(unsigned long long)const; - const Duration operator*(float)const; - const Duration operator*(double)const; - const Duration operator*(long double)const; - const Duration operator/(int) const; - const Duration operator/(float) const; - const Duration operator/(double) const; - - Duration& operator+=(const Duration&); - Duration& operator-=(const Duration&); - Duration& operator*=(int); - Duration& operator*=(float); - Duration& operator*=(double); - Duration& operator/=(int); - Duration& operator/=(float); - Duration& operator/=(double); - - friend const Duration operator*(int, const Duration&); - friend const Duration operator*(float, const Duration&); - friend const Duration operator*(double, const Duration&); - friend const Duration operator*(long double, const Duration&); - friend const Duration operator/(int, const Duration&); - friend const Duration operator/(float, const Duration&); - friend const Duration operator/(double, const Duration&); - -private: - int64_t milliseconds_; -}; - /** * \~chinese * @brief 时间 @@ -212,6 +74,11 @@ struct KGE_API ClockTime { ClockTime(); + /// \~chinese + /// @brief 是否是零时 + /// @return 若是零时,返回true + bool IsZero() const; + /// \~chinese /// @brief 获取当前时间戳 int64_t GetTimeStamp() const; @@ -247,89 +114,14 @@ private: int64_t ms_since_epoch_; }; -inline int64_t Duration::GetMilliseconds() const -{ - return milliseconds_; -} - -inline bool Duration::IsZero() const -{ - return milliseconds_ == 0LL; -} - -inline void Duration::SetMilliseconds(int64_t ms) -{ - milliseconds_ = ms; -} - -inline void Duration::SetSeconds(float seconds) -{ - milliseconds_ = static_cast(seconds * 1000.f); -} - -inline void Duration::SetMinutes(float minutes) -{ - milliseconds_ = static_cast(minutes * 60 * 1000.f); -} - -inline void Duration::SetHours(float hours) -{ - milliseconds_ = static_cast(hours * 60 * 60 * 1000.f); -} - inline bool Time::IsZero() const { return dur_ == 0; } +inline bool ClockTime::IsZero() const +{ + return ms_since_epoch_ == 0; +} + } // namespace kiwano - -#if defined(KGE_HAS_LITERALS) - -namespace kiwano -{ -inline namespace literals -{ -inline const kiwano::Duration operator"" _msec(long double val) -{ - return kiwano::Duration::Ms * val; -} - -inline const kiwano::Duration operator"" _msec(unsigned long long val) -{ - return kiwano::Duration::Ms * val; -} - -inline const kiwano::Duration operator"" _sec(long double val) -{ - return kiwano::Duration::Second * val; -} - -inline const kiwano::Duration operator"" _sec(unsigned long long val) -{ - return kiwano::Duration::Second * val; -} - -inline const kiwano::Duration operator"" _min(long double val) -{ - return kiwano::Duration::Minute * val; -} - -inline const kiwano::Duration operator"" _min(unsigned long long val) -{ - return kiwano::Duration::Minute * val; -} - -inline const kiwano::Duration operator"" _hour(long double val) -{ - return kiwano::Duration::Hour * val; -} - -inline const kiwano::Duration operator"" _hour(unsigned long long val) -{ - return kiwano::Duration::Hour * val; -} -} // namespace literals -} // namespace kiwano - -#endif