update Duration
This commit is contained in:
parent
4be1d7eccb
commit
21c476c56f
|
|
@ -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",
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@
|
|||
<ClInclude Include="..\..\src\kiwano\core\Cloneable.h" />
|
||||
<ClInclude Include="..\..\src\kiwano\core\Common.h" />
|
||||
<ClInclude Include="..\..\src\kiwano\core\Defer.h" />
|
||||
<ClInclude Include="..\..\src\kiwano\core\Duration.h" />
|
||||
<ClInclude Include="..\..\src\kiwano\core\Exception.h" />
|
||||
<ClInclude Include="..\..\src\kiwano\core\Flag.h" />
|
||||
<ClInclude Include="..\..\src\kiwano\core\Function.h" />
|
||||
|
|
@ -139,6 +140,7 @@
|
|||
<ClCompile Include="..\..\src\kiwano\base\ObjectBase.cpp" />
|
||||
<ClCompile Include="..\..\src\kiwano\base\RefObject.cpp" />
|
||||
<ClCompile Include="..\..\src\kiwano\core\Allocator.cpp" />
|
||||
<ClCompile Include="..\..\src\kiwano\core\Duration.cpp" />
|
||||
<ClCompile Include="..\..\src\kiwano\core\Exception.cpp" />
|
||||
<ClCompile Include="..\..\src\kiwano\core\Library.cpp" />
|
||||
<ClCompile Include="..\..\src\kiwano\core\Resource.cpp" />
|
||||
|
|
|
|||
|
|
@ -132,6 +132,9 @@
|
|||
<ClInclude Include="..\..\src\kiwano\core\Time.h">
|
||||
<Filter>core</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\kiwano\core\Duration.h">
|
||||
<Filter>core</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\kiwano\render\Brush.h">
|
||||
<Filter>render</Filter>
|
||||
</ClInclude>
|
||||
|
|
@ -599,6 +602,9 @@
|
|||
<ClCompile Include="..\..\src\kiwano\render\NativeObject.cpp">
|
||||
<Filter>render</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\kiwano\core\Duration.cpp">
|
||||
<Filter>core</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="suppress_warning.ruleset" />
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 <regex> // std::regex
|
||||
#include <unordered_map> // std::unordered_map
|
||||
#include <chrono> // std::chrono::milliseconds
|
||||
#include <thread> // std::this_thread::sleep_for
|
||||
#include <kiwano/core/Duration.h>
|
||||
#include <kiwano/utils/Logger.h> // 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<String, Duration> 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<float>(sec + ms) / 1000.f;
|
||||
}
|
||||
|
||||
float Duration::GetMinutes() const
|
||||
{
|
||||
auto min = milliseconds_ / time::Minute.milliseconds_;
|
||||
auto ms = milliseconds_ % time::Minute.milliseconds_;
|
||||
return static_cast<float>(min + ms) / (60 * 1000.f);
|
||||
}
|
||||
|
||||
float Duration::GetHours() const
|
||||
{
|
||||
auto hour = milliseconds_ / time::Hour.milliseconds_;
|
||||
auto ms = milliseconds_ % time::Hour.milliseconds_;
|
||||
return static_cast<float>(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
|
||||
|
|
@ -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 <kiwano/core/Common.h>
|
||||
|
||||
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<int64_t>(seconds * 1000.f);
|
||||
}
|
||||
|
||||
inline void Duration::SetMinutes(float minutes)
|
||||
{
|
||||
milliseconds_ = static_cast<int64_t>(minutes * 60 * 1000.f);
|
||||
}
|
||||
|
||||
inline void Duration::SetHours(float hours)
|
||||
{
|
||||
milliseconds_ = static_cast<int64_t>(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<float>(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<int64_t>(milliseconds_ * val));
|
||||
}
|
||||
|
||||
inline const Duration Duration::operator*(float val) const
|
||||
{
|
||||
return Duration(static_cast<int64_t>(milliseconds_ * val));
|
||||
}
|
||||
|
||||
inline const Duration Duration::operator*(double val) const
|
||||
{
|
||||
return Duration(static_cast<int64_t>(milliseconds_ * val));
|
||||
}
|
||||
|
||||
inline const Duration Duration::operator*(long double val) const
|
||||
{
|
||||
return Duration(static_cast<int64_t>(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<int64_t>(milliseconds_ / val));
|
||||
}
|
||||
|
||||
inline const Duration Duration::operator/(double val) const
|
||||
{
|
||||
return Duration(static_cast<int64_t>(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<int64_t>(milliseconds_ / val);
|
||||
return (*this);
|
||||
}
|
||||
|
||||
inline Duration& Duration::operator*=(float val)
|
||||
{
|
||||
milliseconds_ = static_cast<int64_t>(milliseconds_ * val);
|
||||
return (*this);
|
||||
}
|
||||
|
||||
inline Duration& Duration::operator/=(float val)
|
||||
{
|
||||
milliseconds_ = static_cast<int64_t>(milliseconds_ / val);
|
||||
return (*this);
|
||||
}
|
||||
|
||||
inline Duration& Duration::operator*=(double val)
|
||||
{
|
||||
milliseconds_ = static_cast<int64_t>(milliseconds_ * val);
|
||||
return (*this);
|
||||
}
|
||||
|
||||
inline Duration& Duration::operator/=(double val)
|
||||
{
|
||||
milliseconds_ = static_cast<int64_t>(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
|
||||
|
|
@ -18,12 +18,8 @@
|
|||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
#include <regex>
|
||||
#include <unordered_map>
|
||||
#include <chrono>
|
||||
#include <thread>
|
||||
#include <chrono> // std::chrono
|
||||
#include <kiwano/core/Time.h>
|
||||
#include <kiwano/utils/Logger.h>
|
||||
|
||||
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<String, Duration> 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<float>(sec + ms) / 1000.f;
|
||||
}
|
||||
|
||||
float Duration::GetMinutes() const
|
||||
{
|
||||
auto min = milliseconds_ / Minute.milliseconds_;
|
||||
auto ms = milliseconds_ % Minute.milliseconds_;
|
||||
return static_cast<float>(min + ms) / (60 * 1000.f);
|
||||
}
|
||||
|
||||
float Duration::GetHours() const
|
||||
{
|
||||
auto hour = milliseconds_ / Hour.milliseconds_;
|
||||
auto ms = milliseconds_ % Hour.milliseconds_;
|
||||
return static_cast<float>(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<float>(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<int64_t>(milliseconds_ * val));
|
||||
}
|
||||
|
||||
const Duration Duration::operator*(float val) const
|
||||
{
|
||||
return Duration(static_cast<int64_t>(milliseconds_ * val));
|
||||
}
|
||||
|
||||
const Duration Duration::operator*(double val) const
|
||||
{
|
||||
return Duration(static_cast<int64_t>(milliseconds_ * val));
|
||||
}
|
||||
|
||||
const Duration Duration::operator*(long double val) const
|
||||
{
|
||||
return Duration(static_cast<int64_t>(milliseconds_ * val));
|
||||
}
|
||||
|
||||
const Duration Duration::operator/(int val) const
|
||||
{
|
||||
return Duration(milliseconds_ / val);
|
||||
}
|
||||
|
||||
const Duration Duration::operator/(float val) const
|
||||
{
|
||||
return Duration(static_cast<int64_t>(milliseconds_ / val));
|
||||
}
|
||||
|
||||
const Duration Duration::operator/(double val) const
|
||||
{
|
||||
return Duration(static_cast<int64_t>(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<int64_t>(milliseconds_ / val);
|
||||
return (*this);
|
||||
}
|
||||
|
||||
Duration& Duration::operator*=(float val)
|
||||
{
|
||||
milliseconds_ = static_cast<int64_t>(milliseconds_ * val);
|
||||
return (*this);
|
||||
}
|
||||
|
||||
Duration& Duration::operator/=(float val)
|
||||
{
|
||||
milliseconds_ = static_cast<int64_t>(milliseconds_ / val);
|
||||
return (*this);
|
||||
}
|
||||
|
||||
Duration& Duration::operator*=(double val)
|
||||
{
|
||||
milliseconds_ = static_cast<int64_t>(milliseconds_ * val);
|
||||
return (*this);
|
||||
}
|
||||
|
||||
Duration& Duration::operator/=(double val)
|
||||
{
|
||||
milliseconds_ = static_cast<int64_t>(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
|
||||
|
|
|
|||
|
|
@ -19,150 +19,12 @@
|
|||
// THE SOFTWARE.
|
||||
|
||||
#pragma once
|
||||
#include <kiwano/core/Common.h>
|
||||
#include <kiwano/core/Duration.h>
|
||||
#include <ctime>
|
||||
|
||||
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<int64_t>(seconds * 1000.f);
|
||||
}
|
||||
|
||||
inline void Duration::SetMinutes(float minutes)
|
||||
{
|
||||
milliseconds_ = static_cast<int64_t>(minutes * 60 * 1000.f);
|
||||
}
|
||||
|
||||
inline void Duration::SetHours(float hours)
|
||||
{
|
||||
milliseconds_ = static_cast<int64_t>(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
|
||||
|
|
|
|||
Loading…
Reference in New Issue