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