update Duration

This commit is contained in:
liuhaibo.2020 2020-10-09 20:54:43 +08:00 committed by Nomango
parent 4be1d7eccb
commit 21c476c56f
8 changed files with 649 additions and 576 deletions

View File

@ -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",

View File

@ -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" />

View File

@ -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" />

View File

@ -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();
}

View File

@ -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

433
src/kiwano/core/Duration.h Normal file
View File

@ -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

View File

@ -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

View File

@ -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