diff options
author | Anton Samokhvalov <pg83@yandex.ru> | 2022-02-10 16:45:17 +0300 |
---|---|---|
committer | Daniil Cherednik <dcherednik@yandex-team.ru> | 2022-02-10 16:45:17 +0300 |
commit | d3a398281c6fd1d3672036cb2d63f842d2cb28c5 (patch) | |
tree | dd4bd3ca0f36b817e96812825ffaf10d645803f2 /util/datetime | |
parent | 72cb13b4aff9bc9cf22e49251bc8fd143f82538f (diff) | |
download | ydb-d3a398281c6fd1d3672036cb2d63f842d2cb28c5.tar.gz |
Restoring authorship annotation for Anton Samokhvalov <pg83@yandex.ru>. Commit 2 of 2.
Diffstat (limited to 'util/datetime')
-rw-r--r-- | util/datetime/base.cpp | 198 | ||||
-rw-r--r-- | util/datetime/base.h | 268 | ||||
-rw-r--r-- | util/datetime/base_ut.cpp | 424 | ||||
-rw-r--r-- | util/datetime/constants.cpp | 2 | ||||
-rw-r--r-- | util/datetime/cputimer.cpp | 42 | ||||
-rw-r--r-- | util/datetime/cputimer.h | 66 | ||||
-rw-r--r-- | util/datetime/parser.h | 26 | ||||
-rw-r--r-- | util/datetime/parser.rl6 | 24 | ||||
-rw-r--r-- | util/datetime/parser_ut.cpp | 80 | ||||
-rw-r--r-- | util/datetime/strptime.cpp | 872 | ||||
-rw-r--r-- | util/datetime/systime.cpp | 70 | ||||
-rw-r--r-- | util/datetime/systime.h | 54 | ||||
-rw-r--r-- | util/datetime/uptime.cpp | 8 | ||||
-rw-r--r-- | util/datetime/ut/ya.make | 6 |
14 files changed, 1070 insertions, 1070 deletions
diff --git a/util/datetime/base.cpp b/util/datetime/base.cpp index b9e84b29b6..38ecc3ab96 100644 --- a/util/datetime/base.cpp +++ b/util/datetime/base.cpp @@ -1,72 +1,72 @@ -#include "base.h" +#include "base.h" #include <util/string/cast.h> -#include <util/stream/output.h> -#include <util/stream/mem.h> +#include <util/stream/output.h> +#include <util/stream/mem.h> #include <util/system/compat.h> -#include <util/memory/tempbuf.h> +#include <util/memory/tempbuf.h> #include <util/generic/string.h> #include <util/generic/strbuf.h> -#include <util/generic/yexception.h> +#include <util/generic/yexception.h> TString Strftime(const char* format, const struct tm* tm) { - size_t size = Max<size_t>(strlen(format) * 2 + 1, 107); + size_t size = Max<size_t>(strlen(format) * 2 + 1, 107); for (;;) { - TTempBuf buf(size); + TTempBuf buf(size); int r = strftime(buf.Data(), buf.Size(), format, tm); - if (r != 0) { + if (r != 0) { return TString(buf.Data(), r); - } + } size *= 2; } } -template <> -TDuration FromStringImpl<TDuration, char>(const char* s, size_t len) { +template <> +TDuration FromStringImpl<TDuration, char>(const char* s, size_t len) { return TDuration::Parse(TStringBuf(s, len)); -} - -template <> +} + +template <> bool TryFromStringImpl<TDuration, char>(const char* s, size_t len, TDuration& result) { return TDuration::TryParse(TStringBuf(s, len), result); } -namespace { - template <size_t N> - struct TPad { - int I; - }; - - template <size_t N> - inline TPad<N> Pad(int i) { - return {i}; - } - +namespace { + template <size_t N> + struct TPad { + int I; + }; + + template <size_t N> + inline TPad<N> Pad(int i) { + return {i}; + } + inline IOutputStream& operator<<(IOutputStream& o, const TPad<2>& p) { - if (p.I < 10) { - if (p.I >= 0) { - o << '0'; - } - } - - return o << p.I; - } - + if (p.I < 10) { + if (p.I >= 0) { + o << '0'; + } + } + + return o << p.I; + } + inline IOutputStream& operator<<(IOutputStream& o, const TPad<4>& p) { - if (p.I < 1000) { - if (p.I >= 0) { - if (p.I < 10) { - o << '0' << '0' << '0'; - } else if (p.I < 100) { - o << '0' << '0'; - } else { - o << '0'; - } - } - } - - return o << p.I; - } + if (p.I < 1000) { + if (p.I >= 0) { + if (p.I < 10) { + o << '0' << '0' << '0'; + } else if (p.I < 100) { + o << '0' << '0'; + } else { + o << '0'; + } + } + } + + return o << p.I; + } inline IOutputStream& operator<<(IOutputStream& o, const TPad<6>& p) { if (p.I < 100000) { @@ -94,7 +94,7 @@ namespace { void WriteTmToStream(IOutputStream& os, const struct tm& theTm) { os << Pad<4>(theTm.tm_year + 1900) << '-' << Pad<2>(theTm.tm_mon + 1) << '-' << Pad<2>(theTm.tm_mday) << 'T' - << Pad<2>(theTm.tm_hour) << ':' << Pad<2>(theTm.tm_min) << ':' << Pad<2>(theTm.tm_sec); + << Pad<2>(theTm.tm_hour) << ':' << Pad<2>(theTm.tm_min) << ':' << Pad<2>(theTm.tm_sec); } template <bool PrintUpToSeconds, bool iso> @@ -131,8 +131,8 @@ namespace { os << Pad<2>(utcOffsetInMinutes % 60); } } -} - +} + template <> void Out<TDuration>(IOutputStream& os, TTypeTraits<TDuration>::TFuncParam duration) { os << duration.Seconds(); @@ -154,22 +154,22 @@ void Out<TInstant>(IOutputStream& os, TTypeTraits<TInstant>::TFuncParam instant) } template <> -void Out<::NPrivate::TPrintableLocalTime<false, false>>(IOutputStream& os, TTypeTraits<::NPrivate::TPrintableLocalTime<false, false>>::TFuncParam localTime) { +void Out<::NPrivate::TPrintableLocalTime<false, false>>(IOutputStream& os, TTypeTraits<::NPrivate::TPrintableLocalTime<false, false>>::TFuncParam localTime) { WritePrintableLocalTimeToStream(os, localTime); } template <> -void Out<::NPrivate::TPrintableLocalTime<false, true>>(IOutputStream& os, TTypeTraits<::NPrivate::TPrintableLocalTime<false, true>>::TFuncParam localTime) { +void Out<::NPrivate::TPrintableLocalTime<false, true>>(IOutputStream& os, TTypeTraits<::NPrivate::TPrintableLocalTime<false, true>>::TFuncParam localTime) { WritePrintableLocalTimeToStream(os, localTime); } template <> -void Out<::NPrivate::TPrintableLocalTime<true, false>>(IOutputStream& os, TTypeTraits<::NPrivate::TPrintableLocalTime<true, false>>::TFuncParam localTime) { +void Out<::NPrivate::TPrintableLocalTime<true, false>>(IOutputStream& os, TTypeTraits<::NPrivate::TPrintableLocalTime<true, false>>::TFuncParam localTime) { WritePrintableLocalTimeToStream(os, localTime); } template <> -void Out<::NPrivate::TPrintableLocalTime<true, true>>(IOutputStream& os, TTypeTraits<::NPrivate::TPrintableLocalTime<true, true>>::TFuncParam localTime) { +void Out<::NPrivate::TPrintableLocalTime<true, true>>(IOutputStream& os, TTypeTraits<::NPrivate::TPrintableLocalTime<true, true>>::TFuncParam localTime) { WritePrintableLocalTimeToStream(os, localTime); } @@ -188,9 +188,9 @@ TString TInstant::ToRfc822String() const { TString TInstant::ToStringUpToSeconds() const { char buf[64]; auto len = FormatDate8601(buf, sizeof(buf), TimeT()); - if (!len) { + if (!len) { ythrow yexception() << "TInstant::ToStringUpToSeconds: year does not fit into an integer"; - } + } return TString(buf, len); } @@ -246,16 +246,16 @@ void Sleep(TDuration duration) { NanoSleep(duration.NanoSeconds()); } -void sprint_gm_date(char* buf, time_t when, long* sec) { - struct tm theTm; - ::Zero(theTm); - GmTimeR(&when, &theTm); +void sprint_gm_date(char* buf, time_t when, long* sec) { + struct tm theTm; + ::Zero(theTm); + GmTimeR(&when, &theTm); DateToString(buf, theTm); - if (sec) { - *sec = seconds(theTm); - } -} - + if (sec) { + *sec = seconds(theTm); + } +} + void DateToString(char* buf, const struct tm& theTm) { Y_ENSURE(0 <= theTm.tm_year + 1900 && theTm.tm_year + 1900 <= 9999, "invalid year " + ToString(theTm.tm_year + 1900) + ", year should be in range [0, 9999]"); @@ -299,38 +299,38 @@ TString YearToString(time_t when) { return YearToString(theTm); } -bool sscan_date(const char* date, struct tm& theTm) { - int year, mon, mday; - if (sscanf(date, "%4d%2d%2d", &year, &mon, &mday) != 3) { - return false; - } - theTm.tm_year = year - 1900; - theTm.tm_mon = mon - 1; - theTm.tm_mday = mday; - return true; -} - -size_t FormatDate8601(char* buf, size_t len, time_t when) { - struct tm theTm; - struct tm* ret = GmTimeR(&when, &theTm); - - if (ret) { - TMemoryOutput out(buf, len); - +bool sscan_date(const char* date, struct tm& theTm) { + int year, mon, mday; + if (sscanf(date, "%4d%2d%2d", &year, &mon, &mday) != 3) { + return false; + } + theTm.tm_year = year - 1900; + theTm.tm_mon = mon - 1; + theTm.tm_mday = mday; + return true; +} + +size_t FormatDate8601(char* buf, size_t len, time_t when) { + struct tm theTm; + struct tm* ret = GmTimeR(&when, &theTm); + + if (ret) { + TMemoryOutput out(buf, len); + WriteTmToStream(out, theTm); out << 'Z'; - - return out.Buf() - buf; - } - - return 0; -} - -void SleepUntil(TInstant instant) { - TInstant now = TInstant::Now(); - if (instant <= now) { - return; - } - TDuration duration = instant - now; - Sleep(duration); -} + + return out.Buf() - buf; + } + + return 0; +} + +void SleepUntil(TInstant instant) { + TInstant now = TInstant::Now(); + if (instant <= now) { + return; + } + TDuration duration = instant - now; + Sleep(duration); +} diff --git a/util/datetime/base.h b/util/datetime/base.h index 3c13e29f10..5e902b8f63 100644 --- a/util/datetime/base.h +++ b/util/datetime/base.h @@ -1,7 +1,7 @@ #pragma once -#include "systime.h" - +#include "systime.h" + #include <util/str_stl.h> #include <util/system/platform.h> #include <util/system/datetime.h> @@ -9,7 +9,7 @@ #include <util/generic/strbuf.h> #include <util/generic/ylimits.h> #include <util/generic/utility.h> -#include <util/generic/typetraits.h> +#include <util/generic/typetraits.h> #include <util/generic/yexception.h> #include <chrono> @@ -18,20 +18,20 @@ #include <compare> #endif -#include <ctime> -#include <cstdio> +#include <ctime> +#include <cstdio> #include <ratio> - -#include <time.h> - + +#include <time.h> + #ifdef _MSC_VER - #pragma warning(push) - #pragma warning(disable : 4244) // conversion from 'time_t' to 'long', possible loss of data -#endif // _MSC_VER + #pragma warning(push) + #pragma warning(disable : 4244) // conversion from 'time_t' to 'long', possible loss of data +#endif // _MSC_VER // Microseconds since epoch class TInstant; - + // Duration is microseconds. Could be used to store timeouts, for example. class TDuration; @@ -43,21 +43,21 @@ static inline TInstant Now() noexcept; class TDateTimeParseException: public yexception { }; -const int DATE_BUF_LEN = 4 + 2 + 2 + 1; // [YYYYMMDD*] +const int DATE_BUF_LEN = 4 + 2 + 2 + 1; // [YYYYMMDD*] constexpr long seconds(const struct tm& theTm) { - return 60 * (60 * theTm.tm_hour + theTm.tm_min) + theTm.tm_sec; + return 60 * (60 * theTm.tm_hour + theTm.tm_min) + theTm.tm_sec; } void sprint_gm_date(char* buf, time_t when, long* sec = nullptr); -bool sscan_date(const char* date, struct tm& theTm); +bool sscan_date(const char* date, struct tm& theTm); -const int DATE_8601_LEN = 21; // strlen("YYYY-MM-DDThh:mm:ssZ") = 20 + '\0' +const int DATE_8601_LEN = 21; // strlen("YYYY-MM-DDThh:mm:ssZ") = 20 + '\0' -size_t FormatDate8601(char* buf, size_t len, time_t when); +size_t FormatDate8601(char* buf, size_t len, time_t when); -inline void sprint_date8601(char* buf, time_t when) { - buf[FormatDate8601(buf, 64, when)] = 0; +inline void sprint_date8601(char* buf, time_t when) { + buf[FormatDate8601(buf, 64, when)] = 0; } bool ParseISO8601DateTimeDeprecated(const char* date, time_t& utcTime); @@ -79,9 +79,9 @@ bool ParseX509ValidityDateTime(const char* date, time_t& utcTime); bool ParseX509ValidityDateTime(const char* date, size_t dateLen, time_t& utcTime); constexpr long TVdiff(timeval r1, timeval r2) { - return (1000000 * (r2.tv_sec - r1.tv_sec) + (r2.tv_usec - r1.tv_usec)); -} - + return (1000000 * (r2.tv_sec - r1.tv_sec) + (r2.tv_usec - r1.tv_usec)); +} + TString Strftime(const char* format, const struct tm* tm); // Use functions below instead of sprint_date (check IGNIETFERRO-892 for details) @@ -100,7 +100,7 @@ public: protected: constexpr TTimeBase(const TValue& value) noexcept - : Value_(value) + : Value_(value) { } @@ -111,12 +111,12 @@ public: } constexpr TTimeBase(const struct timeval& tv) noexcept - : Value_(tv.tv_sec * (ui64)1000000 + tv.tv_usec) + : Value_(tv.tv_sec * (ui64)1000000 + tv.tv_usec) { } constexpr TValue GetValue() const noexcept { - return Value_; + return Value_; } constexpr double SecondsFloat() const noexcept { @@ -128,25 +128,25 @@ public: } constexpr TValue MicroSeconds() const noexcept { - return Value_; + return Value_; } - + constexpr TValue MilliSeconds() const noexcept { return MicroSeconds() / 1000; } - + constexpr TValue Seconds() const noexcept { return MilliSeconds() / 1000; } - + constexpr TValue Minutes() const noexcept { return Seconds() / 60; } - + constexpr TValue Hours() const noexcept { return Minutes() / 60; } - + constexpr TValue Days() const noexcept { return Hours() / 24; } @@ -154,19 +154,19 @@ public: constexpr TValue NanoSeconds() const noexcept { return MicroSeconds() >= (Max<TValue>() / (TValue)1000) ? Max<TValue>() : MicroSeconds() * (TValue)1000; } - + constexpr ui32 MicroSecondsOfSecond() const noexcept { - return MicroSeconds() % (TValue)1000000; + return MicroSeconds() % (TValue)1000000; } - + constexpr ui32 MilliSecondsOfSecond() const noexcept { - return MicroSecondsOfSecond() / (TValue)1000; + return MicroSecondsOfSecond() / (TValue)1000; } constexpr ui32 NanoSecondsOfSecond() const noexcept { - return MicroSecondsOfSecond() * (TValue)1000; - } - + return MicroSecondsOfSecond() * (TValue)1000; + } + constexpr explicit operator bool() const noexcept { return Value_; } @@ -190,17 +190,17 @@ namespace NDateTimeHelpers { struct TPrecisionHelper<double> { using THighPrecision = double; }; -} +} class TDuration: public TTimeBase<TDuration> { using TBase = TTimeBase<TDuration>; - + private: /** * private construct from microseconds */ constexpr explicit TDuration(TValue value) noexcept - : TBase(value) + : TBase(value) { } @@ -267,13 +267,13 @@ public: /* noexcept(false) as conversion from T might throw, for example FromString("abc") */ template <typename T> static constexpr TDuration MilliSeconds(T ms) noexcept(false) { - return MicroSeconds((ui64)(typename NDateTimeHelpers::TPrecisionHelper<T>::THighPrecision(ms) * 1000)); + return MicroSeconds((ui64)(typename NDateTimeHelpers::TPrecisionHelper<T>::THighPrecision(ms) * 1000)); } using TBase::Days; using TBase::Hours; - using TBase::MicroSeconds; - using TBase::MilliSeconds; + using TBase::MicroSeconds; + using TBase::MilliSeconds; using TBase::Minutes; using TBase::Seconds; @@ -282,11 +282,11 @@ public: constexpr TInstant ToDeadLine(TInstant now) const; static constexpr TDuration Max() noexcept { - return TDuration(::Max<TValue>()); + return TDuration(::Max<TValue>()); } static constexpr TDuration Zero() noexcept { - return TDuration(); + return TDuration(); } /* noexcept(false) as conversion from T might throw, for example FromString("abc") */ @@ -298,48 +298,48 @@ public: static constexpr TDuration Minutes(ui64 m) noexcept { return Seconds(m * 60); } - + static constexpr TDuration Hours(ui64 h) noexcept { return Minutes(h * 60); } - + static constexpr TDuration Days(ui64 d) noexcept { return Hours(d * 24); } /// parses strings like 10s, 15ms, 15.05s, 20us, or just 25 (s). See parser_ut.cpp for details static TDuration Parse(const TStringBuf input); - + static bool TryParse(const TStringBuf input, TDuration& result); // note global Out method is defined for TDuration, so it could be written to IOutputStream as text - - template <class T> + + template <class T> inline TDuration& operator+=(const T& t) noexcept { - return (*this = (*this + t)); - } - - template <class T> + return (*this = (*this + t)); + } + + template <class T> inline TDuration& operator-=(const T& t) noexcept { - return (*this = (*this - t)); - } - - template <class T> + return (*this = (*this - t)); + } + + template <class T> inline TDuration& operator*=(const T& t) noexcept { - return (*this = (*this * t)); - } - - template <class T> + return (*this = (*this * t)); + } + + template <class T> inline TDuration& operator/=(const T& t) noexcept { - return (*this = (*this / t)); - } + return (*this = (*this / t)); + } TString ToString() const; }; Y_DECLARE_PODTYPE(TDuration); - -template <> + +template <> struct THash<TDuration> { size_t operator()(const TDuration& key) const { return THash<TDuration::TValue>()(key.GetValue()); @@ -349,13 +349,13 @@ struct THash<TDuration> { /// TInstant and TDuration are guaranteed to have same precision class TInstant: public TTimeBase<TInstant> { using TBase = TTimeBase<TInstant>; - + private: /** * private construct from microseconds since epoch */ constexpr explicit TInstant(TValue value) noexcept - : TBase(value) + : TBase(value) { } @@ -373,39 +373,39 @@ public: } static inline TInstant Now() { - return TInstant::MicroSeconds(::MicroSeconds()); + return TInstant::MicroSeconds(::MicroSeconds()); } using TBase::Days; using TBase::Hours; - using TBase::MicroSeconds; - using TBase::MilliSeconds; + using TBase::MicroSeconds; + using TBase::MilliSeconds; using TBase::Minutes; using TBase::Seconds; static constexpr TInstant Max() noexcept { - return TInstant(::Max<TValue>()); + return TInstant(::Max<TValue>()); } static constexpr TInstant Zero() noexcept { - return TInstant(); + return TInstant(); } /// us since epoch static constexpr TInstant MicroSeconds(ui64 us) noexcept { return TInstant(us); } - + /// ms since epoch static constexpr TInstant MilliSeconds(ui64 ms) noexcept { return MicroSeconds(ms * 1000); } - + /// seconds since epoch static constexpr TInstant Seconds(ui64 s) noexcept { return MilliSeconds(s * 1000); } - + /// minutes since epoch static constexpr TInstant Minutes(ui64 m) noexcept { return Seconds(m * 60); @@ -422,7 +422,7 @@ public: } constexpr time_t TimeT() const noexcept { - return (time_t)Seconds(); + return (time_t)Seconds(); } inline struct timeval TimeVal() const noexcept { @@ -437,7 +437,7 @@ public: time_t clock = Seconds(); return localtime_r(&clock, tm); } - + inline struct tm* GmTime(struct tm* tm) const noexcept { time_t clock = Seconds(); return GmTimeR(&clock, tm); @@ -510,12 +510,12 @@ public: /// See #TryParseIso8601. static TInstant ParseIso8601(TStringBuf); /// See #TryParseRfc822. - static TInstant ParseRfc822(TStringBuf); + static TInstant ParseRfc822(TStringBuf); /// See #TryParseHttp. static TInstant ParseHttp(TStringBuf); /// See #TryParseX509. static TInstant ParseX509Validity(TStringBuf); - + /// ISO 8601 Representation of Dates and Times /// /// @link https://www.iso.org/standard/40874.html Description of format. @@ -546,20 +546,20 @@ public: static bool TryParseHttpDeprecated(TStringBuf input, TInstant& instant); static bool TryParseX509Deprecated(TStringBuf input, TInstant& instant); - template <class T> + template <class T> inline TInstant& operator+=(const T& t) noexcept { - return (*this = (*this + t)); - } - - template <class T> + return (*this = (*this + t)); + } + + template <class T> inline TInstant& operator-=(const T& t) noexcept { - return (*this = (*this - t)); - } + return (*this = (*this - t)); + } }; Y_DECLARE_PODTYPE(TInstant); - -template <> + +template <> struct THash<TInstant> { size_t operator()(const TInstant& key) const { return THash<TInstant::TValue>()(key.GetValue()); @@ -601,72 +601,72 @@ namespace NPrivate { ::NPrivate::TPrintableLocalTime<true, false> FormatLocalUpToSeconds(TInstant instant); ///@} -template <class S> +template <class S> static constexpr bool operator<(const TTimeBase<S>& l, const TTimeBase<S>& r) noexcept { - return l.GetValue() < r.GetValue(); -} - -template <class S> + return l.GetValue() < r.GetValue(); +} + +template <class S> static constexpr bool operator<=(const TTimeBase<S>& l, const TTimeBase<S>& r) noexcept { - return l.GetValue() <= r.GetValue(); -} - -template <class S> + return l.GetValue() <= r.GetValue(); +} + +template <class S> static constexpr bool operator==(const TTimeBase<S>& l, const TTimeBase<S>& r) noexcept { - return l.GetValue() == r.GetValue(); -} - -template <class S> + return l.GetValue() == r.GetValue(); +} + +template <class S> static constexpr bool operator!=(const TTimeBase<S>& l, const TTimeBase<S>& r) noexcept { - return l.GetValue() != r.GetValue(); -} - -template <class S> + return l.GetValue() != r.GetValue(); +} + +template <class S> static constexpr bool operator>(const TTimeBase<S>& l, const TTimeBase<S>& r) noexcept { - return l.GetValue() > r.GetValue(); -} - -template <class S> + return l.GetValue() > r.GetValue(); +} + +template <class S> static constexpr bool operator>=(const TTimeBase<S>& l, const TTimeBase<S>& r) noexcept { - return l.GetValue() >= r.GetValue(); -} - + return l.GetValue() >= r.GetValue(); +} + namespace NDateTimeHelpers { template <typename T> static constexpr T SumWithSaturation(T a, T b) { static_assert(!std::numeric_limits<T>::is_signed, "expect !std::numeric_limits<T>::is_signed"); - + return Max<T>() - a < b ? Max<T>() : a + b; } template <typename T> static constexpr T DiffWithSaturation(T a, T b) { static_assert(!std::numeric_limits<T>::is_signed, "expect !std::numeric_limits<T>::is_signed"); - + return a < b ? 0 : a - b; } } constexpr TDuration operator-(const TInstant& l, const TInstant& r) noexcept { return TDuration::FromValue(::NDateTimeHelpers::DiffWithSaturation(l.GetValue(), r.GetValue())); -} - +} + constexpr TInstant operator+(const TInstant& i, const TDuration& d) noexcept { return TInstant::FromValue(::NDateTimeHelpers::SumWithSaturation(i.GetValue(), d.GetValue())); -} - +} + constexpr TInstant operator-(const TInstant& i, const TDuration& d) noexcept { return TInstant::FromValue(::NDateTimeHelpers::DiffWithSaturation(i.GetValue(), d.GetValue())); -} - +} + constexpr TDuration operator-(const TDuration& l, const TDuration& r) noexcept { return TDuration::FromValue(::NDateTimeHelpers::DiffWithSaturation(l.GetValue(), r.GetValue())); -} - +} + constexpr TDuration operator+(const TDuration& l, const TDuration& r) noexcept { return TDuration::FromValue(::NDateTimeHelpers::SumWithSaturation(l.GetValue(), r.GetValue())); -} - +} + template <typename T, typename TRatio> constexpr bool operator==(const TDuration& l, const std::chrono::duration<T, TRatio>& r) noexcept { return r.count() >= 0 && l == TDuration(r); @@ -771,13 +771,13 @@ constexpr TInstant operator-(const TInstant& l, const std::chrono::duration<T, T return l + (-r); } -template <class T> +template <class T> inline TDuration operator*(TDuration d, T t) noexcept { Y_ASSERT(t >= T()); Y_ASSERT(t == T() || Max<TDuration::TValue>() / t >= d.GetValue()); return TDuration::FromValue(d.GetValue() * t); -} - +} + template <> inline TDuration operator*(TDuration d, double t) noexcept { Y_ASSERT(t >= 0 && MaxFloor<TDuration::TValue>() >= d.GetValue() * t); @@ -797,8 +797,8 @@ inline TDuration operator*(T t, TDuration d) noexcept { template <class T, std::enable_if_t<!std::is_same<TDuration, T>::value, int> = 0> constexpr TDuration operator/(const TDuration& d, const T& t) noexcept { return TDuration::FromValue(d.GetValue() / t); -} - +} + constexpr double operator/(const TDuration& x, const TDuration& y) noexcept { return static_cast<double>(x.GetValue()) / static_cast<double>(y.GetValue()); } @@ -808,16 +808,16 @@ inline TInstant TDuration::ToDeadLine() const { } constexpr TInstant TDuration::ToDeadLine(TInstant now) const { - return now + *this; + return now + *this; } void Sleep(TDuration duration); -void SleepUntil(TInstant instant); +void SleepUntil(TInstant instant); static inline TInstant Now() noexcept { return TInstant::Now(); } #ifdef _MSC_VER - #pragma warning(pop) + #pragma warning(pop) #endif // _MSC_VER diff --git a/util/datetime/base_ut.cpp b/util/datetime/base_ut.cpp index 19e4111ed1..afc3f802eb 100644 --- a/util/datetime/base_ut.cpp +++ b/util/datetime/base_ut.cpp @@ -1,17 +1,17 @@ -#include "base.h" - +#include "base.h" + #include <library/cpp/testing/unittest/registar.h> #include <util/generic/utility.h> #include <util/generic/ylimits.h> #include <util/generic/ymath.h> -#include <util/string/cast.h> +#include <util/string/cast.h> #include <util/stream/output.h> #include <util/system/compat.h> -#include <util/random/random.h> +#include <util/random/random.h> + +#include <limits.h> -#include <limits.h> - using namespace std::chrono_literals; struct TTestTime { @@ -21,31 +21,31 @@ struct TTestTime { const long SprintSecs_ = 15921; struct tm Tm_; TTestTime() { - Tm_.tm_sec = 21; - Tm_.tm_min = 25; - Tm_.tm_hour = 4; - Tm_.tm_mday = 19; - Tm_.tm_mon = 3; - Tm_.tm_year = 101; - Tm_.tm_wday = 4; - Tm_.tm_yday = 108; + Tm_.tm_sec = 21; + Tm_.tm_min = 25; + Tm_.tm_hour = 4; + Tm_.tm_mday = 19; + Tm_.tm_mon = 3; + Tm_.tm_year = 101; + Tm_.tm_wday = 4; + Tm_.tm_yday = 108; } }; -namespace { - inline void OldDate8601(char* buf, time_t when) { - struct tm theTm; - struct tm* ret = nullptr; - - ret = GmTimeR(&when, &theTm); - - if (ret) { - sprintf(buf, "%04d-%02d-%02dT%02d:%02d:%02dZ", theTm.tm_year + 1900, theTm.tm_mon + 1, theTm.tm_mday, theTm.tm_hour, theTm.tm_min, theTm.tm_sec); - } else { - *buf = '\0'; - } - } -} +namespace { + inline void OldDate8601(char* buf, time_t when) { + struct tm theTm; + struct tm* ret = nullptr; + + ret = GmTimeR(&when, &theTm); + + if (ret) { + sprintf(buf, "%04d-%02d-%02dT%02d:%02d:%02dZ", theTm.tm_year + 1900, theTm.tm_mon + 1, theTm.tm_mday, theTm.tm_hour, theTm.tm_min, theTm.tm_sec); + } else { + *buf = '\0'; + } + } +} Y_UNIT_TEST_SUITE(TestSprintDate) { Y_UNIT_TEST(Year9999) { @@ -148,78 +148,78 @@ Y_UNIT_TEST_SUITE(TestSprintDate) { UNIT_ASSERT_VALUES_EQUAL(expectedYear, YearToString(timestamp)); } -} - -Y_UNIT_TEST_SUITE(TDateTimeTest) { - Y_UNIT_TEST(Test8601) { - char buf1[100]; - char buf2[100]; - - for (size_t i = 0; i < 1000000; ++i) { - const time_t t = RandomNumber<ui32>(); - - OldDate8601(buf1, t); - sprint_date8601(buf2, t); - - UNIT_ASSERT_VALUES_EQUAL(TStringBuf(buf1), TStringBuf(buf2)); - } - } - - inline bool CompareTM(const struct tm& a, const struct tm& b) { - return ( - a.tm_sec == b.tm_sec && - a.tm_min == b.tm_min && - a.tm_hour == b.tm_hour && - a.tm_mday == b.tm_mday && - a.tm_mon == b.tm_mon && - a.tm_year == b.tm_year && - a.tm_wday == b.tm_wday && - a.tm_yday == b.tm_yday); - } - - static inline TString Str(const struct tm& a) { - return TStringBuilder() << "(" - << a.tm_sec << ", " - << a.tm_min << ", " - << a.tm_hour << ", " - << a.tm_mday << ", " - << a.tm_mon << ", " - << a.tm_year << ", " - << a.tm_wday << ", " +} + +Y_UNIT_TEST_SUITE(TDateTimeTest) { + Y_UNIT_TEST(Test8601) { + char buf1[100]; + char buf2[100]; + + for (size_t i = 0; i < 1000000; ++i) { + const time_t t = RandomNumber<ui32>(); + + OldDate8601(buf1, t); + sprint_date8601(buf2, t); + + UNIT_ASSERT_VALUES_EQUAL(TStringBuf(buf1), TStringBuf(buf2)); + } + } + + inline bool CompareTM(const struct tm& a, const struct tm& b) { + return ( + a.tm_sec == b.tm_sec && + a.tm_min == b.tm_min && + a.tm_hour == b.tm_hour && + a.tm_mday == b.tm_mday && + a.tm_mon == b.tm_mon && + a.tm_year == b.tm_year && + a.tm_wday == b.tm_wday && + a.tm_yday == b.tm_yday); + } + + static inline TString Str(const struct tm& a) { + return TStringBuilder() << "(" + << a.tm_sec << ", " + << a.tm_min << ", " + << a.tm_hour << ", " + << a.tm_mday << ", " + << a.tm_mon << ", " + << a.tm_year << ", " + << a.tm_wday << ", " #if !defined(_musl_) && !defined(_win_) - << a.tm_yday -#endif - << ")"; - } - - Y_UNIT_TEST(TestBasicFuncs) { - ui64 mlsecB = millisec(); - ui64 mcrsecB = MicroSeconds(); - struct timeval tvB; - gettimeofday(&tvB, nullptr); - - usleep(100000); - - ui64 mlsecA = millisec(); - ui64 mcrsecA = MicroSeconds(); - struct timeval tvA; - gettimeofday(&tvA, nullptr); - - UNIT_ASSERT(mlsecB + 90 < mlsecA); - UNIT_ASSERT((mcrsecB + 90000 < mcrsecA)); - //UNIT_ASSERT(ToMicroSeconds(&tvB) + 90000 < ToMicroSeconds(&tvA)); - //UNIT_ASSERT(TVdiff(tvB, tvA) == long(ToMicroSeconds(&tvA) - ToMicroSeconds(&tvB))); - } - - Y_UNIT_TEST(TestCompatFuncs) { - struct tm t; - struct tm* tret = nullptr; - TTestTime e; - tret = gmtime_r(&e.T_, &t); - UNIT_ASSERT(tret == &t); - UNIT_ASSERT(CompareTM(e.Tm_, t)); - - /* + << a.tm_yday +#endif + << ")"; + } + + Y_UNIT_TEST(TestBasicFuncs) { + ui64 mlsecB = millisec(); + ui64 mcrsecB = MicroSeconds(); + struct timeval tvB; + gettimeofday(&tvB, nullptr); + + usleep(100000); + + ui64 mlsecA = millisec(); + ui64 mcrsecA = MicroSeconds(); + struct timeval tvA; + gettimeofday(&tvA, nullptr); + + UNIT_ASSERT(mlsecB + 90 < mlsecA); + UNIT_ASSERT((mcrsecB + 90000 < mcrsecA)); + //UNIT_ASSERT(ToMicroSeconds(&tvB) + 90000 < ToMicroSeconds(&tvA)); + //UNIT_ASSERT(TVdiff(tvB, tvA) == long(ToMicroSeconds(&tvA) - ToMicroSeconds(&tvB))); + } + + Y_UNIT_TEST(TestCompatFuncs) { + struct tm t; + struct tm* tret = nullptr; + TTestTime e; + tret = gmtime_r(&e.T_, &t); + UNIT_ASSERT(tret == &t); + UNIT_ASSERT(CompareTM(e.Tm_, t)); + + /* * strptime seems to be broken on Mac OS X: * * struct tm t; @@ -232,111 +232,111 @@ Y_UNIT_TEST_SUITE(TDateTimeTest) { * So this test fails on Mac OS X. */ - struct tm t2; - Zero(t2); - char* ret = strptime(e.Date_, "%a %b %d %H:%M:%S %Y\n ", &t2); - UNIT_ASSERT(ret == e.Date_ + strlen(e.Date_)); - UNIT_ASSERT_VALUES_EQUAL(Str(e.Tm_), Str(t2)); - time_t t3 = timegm(&t); - UNIT_ASSERT(t3 == e.T_); - } - - Y_UNIT_TEST(TestSprintSscan) { - char buf[256]; - long secs; - TTestTime e; - - sprint_gm_date(buf, e.T_, &secs); - UNIT_ASSERT(strcmp(buf, e.SprintDate_) == 0); - UNIT_ASSERT(secs == e.SprintSecs_); - - struct tm t; - Zero(t); - bool ret = sscan_date(buf, t); - UNIT_ASSERT(ret); - UNIT_ASSERT( - t.tm_year == e.Tm_.tm_year && - t.tm_mon == e.Tm_.tm_mon && - t.tm_mday == e.Tm_.tm_mday); - - buf[0] = 'a'; - ret = sscan_date(buf, t); - UNIT_ASSERT(!ret); - } - - Y_UNIT_TEST(TestNow) { - i64 seconds = Seconds(); - i64 milliseconds = millisec(); - i64 microseconds = MicroSeconds(); - UNIT_ASSERT(Abs(seconds - milliseconds / 1000) <= 1); - UNIT_ASSERT(Abs(milliseconds - microseconds / 1000) < 100); - UNIT_ASSERT(seconds > 1243008607); // > time when test was written - } - - Y_UNIT_TEST(TestStrftime) { - struct tm tm; - Zero(tm); - tm.tm_year = 109; - tm.tm_mon = 4; - tm.tm_mday = 29; - UNIT_ASSERT_STRINGS_EQUAL("2009-05-29", Strftime("%Y-%m-%d", &tm)); - } - - Y_UNIT_TEST(TestNanoSleep) { - NanoSleep(0); - NanoSleep(1); - NanoSleep(1000); - NanoSleep(1000000); - } - - static bool TimeZoneEq(const char* zone0, const char* zone1) { - if (strcmp(zone0, "GMT") == 0) { - zone0 = "UTC"; - } - if (strcmp(zone1, "GMT") == 0) { - zone1 = "UTC"; - } - return strcmp(zone0, zone1) == 0; - } - - static bool CompareTMFull(const tm* t0, const tm* t1) { - return t0 && t1 && - CompareTM(*t0, *t1) && - (t0->tm_isdst == t1->tm_isdst) + struct tm t2; + Zero(t2); + char* ret = strptime(e.Date_, "%a %b %d %H:%M:%S %Y\n ", &t2); + UNIT_ASSERT(ret == e.Date_ + strlen(e.Date_)); + UNIT_ASSERT_VALUES_EQUAL(Str(e.Tm_), Str(t2)); + time_t t3 = timegm(&t); + UNIT_ASSERT(t3 == e.T_); + } + + Y_UNIT_TEST(TestSprintSscan) { + char buf[256]; + long secs; + TTestTime e; + + sprint_gm_date(buf, e.T_, &secs); + UNIT_ASSERT(strcmp(buf, e.SprintDate_) == 0); + UNIT_ASSERT(secs == e.SprintSecs_); + + struct tm t; + Zero(t); + bool ret = sscan_date(buf, t); + UNIT_ASSERT(ret); + UNIT_ASSERT( + t.tm_year == e.Tm_.tm_year && + t.tm_mon == e.Tm_.tm_mon && + t.tm_mday == e.Tm_.tm_mday); + + buf[0] = 'a'; + ret = sscan_date(buf, t); + UNIT_ASSERT(!ret); + } + + Y_UNIT_TEST(TestNow) { + i64 seconds = Seconds(); + i64 milliseconds = millisec(); + i64 microseconds = MicroSeconds(); + UNIT_ASSERT(Abs(seconds - milliseconds / 1000) <= 1); + UNIT_ASSERT(Abs(milliseconds - microseconds / 1000) < 100); + UNIT_ASSERT(seconds > 1243008607); // > time when test was written + } + + Y_UNIT_TEST(TestStrftime) { + struct tm tm; + Zero(tm); + tm.tm_year = 109; + tm.tm_mon = 4; + tm.tm_mday = 29; + UNIT_ASSERT_STRINGS_EQUAL("2009-05-29", Strftime("%Y-%m-%d", &tm)); + } + + Y_UNIT_TEST(TestNanoSleep) { + NanoSleep(0); + NanoSleep(1); + NanoSleep(1000); + NanoSleep(1000000); + } + + static bool TimeZoneEq(const char* zone0, const char* zone1) { + if (strcmp(zone0, "GMT") == 0) { + zone0 = "UTC"; + } + if (strcmp(zone1, "GMT") == 0) { + zone1 = "UTC"; + } + return strcmp(zone0, zone1) == 0; + } + + static bool CompareTMFull(const tm* t0, const tm* t1) { + return t0 && t1 && + CompareTM(*t0, *t1) && + (t0->tm_isdst == t1->tm_isdst) #ifndef _win_ - && (t0->tm_gmtoff == t1->tm_gmtoff) && - TimeZoneEq(t0->tm_zone, t1->tm_zone) + && (t0->tm_gmtoff == t1->tm_gmtoff) && + TimeZoneEq(t0->tm_zone, t1->tm_zone) #endif // _win_ - && true; - } - - Y_UNIT_TEST(TestGmTimeR) { - time_t starttime = static_cast<time_t>(Max<i64>(-12244089600LL, Min<time_t>())); // 1-Jan-1582 - time_t finishtime = static_cast<time_t>(Min<i64>(0xFFFFFFFF * 20, Max<time_t>())); - time_t step = (finishtime - starttime) / 25; - struct tm tms0, tms1; - struct tm* ptm0 = nullptr; - struct tm* ptm1 = nullptr; - for (time_t t = starttime; t < finishtime; t += step) { - ptm0 = GmTimeR(&t, &tms0); - UNIT_ASSERT_EQUAL(ptm0, &tms0); + && true; + } + + Y_UNIT_TEST(TestGmTimeR) { + time_t starttime = static_cast<time_t>(Max<i64>(-12244089600LL, Min<time_t>())); // 1-Jan-1582 + time_t finishtime = static_cast<time_t>(Min<i64>(0xFFFFFFFF * 20, Max<time_t>())); + time_t step = (finishtime - starttime) / 25; + struct tm tms0, tms1; + struct tm* ptm0 = nullptr; + struct tm* ptm1 = nullptr; + for (time_t t = starttime; t < finishtime; t += step) { + ptm0 = GmTimeR(&t, &tms0); + UNIT_ASSERT_EQUAL(ptm0, &tms0); #ifdef _win_ - if (tms0.tm_year + 1900 > 3000) { - // Windows: _MAX__TIME64_T == 23:59:59. 12/31/3000 UTC - continue; - } + if (tms0.tm_year + 1900 > 3000) { + // Windows: _MAX__TIME64_T == 23:59:59. 12/31/3000 UTC + continue; + } #endif - ptm1 = gmtime_r(&t, &tms1); - if (!ptm1) { - continue; - } - UNIT_ASSERT_EQUAL(ptm1, &tms1); - UNIT_ASSERT(CompareTMFull(ptm0, ptm1)); - } + ptm1 = gmtime_r(&t, &tms1); + if (!ptm1) { + continue; + } + UNIT_ASSERT_EQUAL(ptm1, &tms1); + UNIT_ASSERT(CompareTMFull(ptm0, ptm1)); + } } -} +} Y_UNIT_TEST_SUITE(DateTimeTest) { Y_UNIT_TEST(TestDurationFromFloat) { @@ -346,15 +346,15 @@ Y_UNIT_TEST_SUITE(DateTimeTest) { Y_UNIT_TEST(TestSecondsLargeValue) { unsigned int seconds = UINT_MAX; - UNIT_ASSERT_VALUES_EQUAL(((ui64)seconds) * 1000000, TDuration::Seconds(seconds).MicroSeconds()); + UNIT_ASSERT_VALUES_EQUAL(((ui64)seconds) * 1000000, TDuration::Seconds(seconds).MicroSeconds()); } Y_UNIT_TEST(TestToString) { -#define CHECK_CONVERTIBLE(v) \ - do { \ - UNIT_ASSERT_VALUES_EQUAL(v, ToString(TDuration::Parse(v))); \ - UNIT_ASSERT_VALUES_EQUAL(v, TDuration::Parse(v).ToString()); \ - } while (0) +#define CHECK_CONVERTIBLE(v) \ + do { \ + UNIT_ASSERT_VALUES_EQUAL(v, ToString(TDuration::Parse(v))); \ + UNIT_ASSERT_VALUES_EQUAL(v, TDuration::Parse(v).ToString()); \ + } while (0) #if 0 CHECK_CONVERTIBLE("10s"); @@ -377,12 +377,12 @@ Y_UNIT_TEST_SUITE(DateTimeTest) { const TDuration::TValue MicroSeconds; const bool Parseable; } tests[] = { - {"0", 0, true}, - {"1", 1000000, true}, - {"2s", 2000000, true}, - {"3ms", 3000, true}, - {"x3ms", 0, false}, - }; + {"0", 0, true}, + {"1", 1000000, true}, + {"2s", 2000000, true}, + {"3ms", 3000, true}, + {"x3ms", 0, false}, + }; for (const T* t = tests; t != std::end(tests); ++t) { // FromString @@ -525,9 +525,9 @@ Y_UNIT_TEST_SUITE(DateTimeTest) { time_t newTimestamp = TimeGM(&time); UNIT_ASSERT_VALUES_EQUAL_C( - newTimestamp, - timestamp, - "incorrect date " << (1900 + time.tm_year) << "-" << (time.tm_mon + 1) << "-" << time.tm_mday); + newTimestamp, + timestamp, + "incorrect date " << (1900 + time.tm_year) << "-" << (time.tm_mon + 1) << "-" << time.tm_mday); } } diff --git a/util/datetime/constants.cpp b/util/datetime/constants.cpp index ef981d5eaf..04a2aa68f2 100644 --- a/util/datetime/constants.cpp +++ b/util/datetime/constants.cpp @@ -1 +1 @@ -#include "constants.h" +#include "constants.h" diff --git a/util/datetime/cputimer.cpp b/util/datetime/cputimer.cpp index 837879833c..516d372c37 100644 --- a/util/datetime/cputimer.cpp +++ b/util/datetime/cputimer.cpp @@ -1,23 +1,23 @@ #include "cputimer.h" - + #include <util/system/defaults.h> #include <util/system/hp_timer.h> #include <util/string/printf.h> -#include <util/stream/output.h> +#include <util/stream/output.h> #include <util/generic/singleton.h> #if defined(_unix_) - #include <unistd.h> - #include <sched.h> - #include <sys/types.h> - #include <sys/resource.h> - #include <sys/param.h> + #include <unistd.h> + #include <sched.h> + #include <sys/types.h> + #include <sys/resource.h> + #include <sys/param.h> #elif defined(_win_) - #include <util/system/winint.h> + #include <util/system/winint.h> #endif TTimer::TTimer(const TStringBuf message) { - static const int SMALL_DURATION_CHAR_LENGTH = 9; // strlen("0.123456s") + static const int SMALL_DURATION_CHAR_LENGTH = 9; // strlen("0.123456s") Message_.Reserve(message.length() + SMALL_DURATION_CHAR_LENGTH + 1); // +"\n" Message_ << message; // Do not measure the allocations above. @@ -33,11 +33,11 @@ TTimer::~TTimer() { static ui64 ManuallySetCyclesPerSecond = 0; static ui64 GetCyclesPerSecond() { - if (ManuallySetCyclesPerSecond != 0) { + if (ManuallySetCyclesPerSecond != 0) { return ManuallySetCyclesPerSecond; - } else { + } else { return NHPTimer::GetCyclesPerSecond(); - } + } } void SetCyclesPerSecond(ui64 cycles) { @@ -78,17 +78,17 @@ TString FormatCycles(ui64 cycles) { } TFormattedPrecisionTimer::TFormattedPrecisionTimer(const char* message, IOutputStream* out) - : Message(message) - , Out(out) + : Message(message) + , Out(out) { Start = GetCycleCount(); } -TFormattedPrecisionTimer::~TFormattedPrecisionTimer() { - const ui64 end = GetCycleCount(); - const ui64 diff = end - Start; - - *Out << Message << ": " << diff << " ticks " << FormatCycles(diff) << Endl; +TFormattedPrecisionTimer::~TFormattedPrecisionTimer() { + const ui64 end = GetCycleCount(); + const ui64 diff = end - Start; + + *Out << Message << ": " << diff << " ticks " << FormatCycles(diff) << Endl; } TFuncTimer::TFuncTimer(const char* func) @@ -119,11 +119,11 @@ double TTimeLogger::ElapsedTime() const { return time(nullptr) - Begin; } -void TTimeLogger::SetOK() { +void TTimeLogger::SetOK() { OK = true; } -TTimeLogger::~TTimeLogger() { +TTimeLogger::~TTimeLogger() { time_t tim = time(nullptr); ui64 endCycles = GetCycleCount(); if (Verbose) { diff --git a/util/datetime/cputimer.h b/util/datetime/cputimer.h index c6d2b6a933..7d38d5bdb3 100644 --- a/util/datetime/cputimer.h +++ b/util/datetime/cputimer.h @@ -1,54 +1,54 @@ #pragma once -#include "base.h" - +#include "base.h" + #include <util/system/rusage.h> #include <util/generic/string.h> #include <util/stream/str.h> - + class TTimer { private: TInstant Start_; TStringStream Message_; - + public: TTimer(const TStringBuf message = TStringBuf(" took: ")); ~TTimer(); }; -class TSimpleTimer { +class TSimpleTimer { TInstant T; - + public: - TSimpleTimer() { + TSimpleTimer() { Reset(); } TDuration Get() const { return TInstant::Now() - T; } - void Reset() { + void Reset() { T = TInstant::Now(); } }; -class TProfileTimer { +class TProfileTimer { TDuration T; - + public: - TProfileTimer() { + TProfileTimer() { Reset(); } TDuration Get() const { return TRusage::Get().Utime - T; } - TDuration Step() { + TDuration Step() { TRusage r; r.Fill(); TDuration d = r.Utime - T; T = r.Utime; return d; } - void Reset() { + void Reset() { T = TRusage::Get().Utime; } }; @@ -62,7 +62,7 @@ void SetCyclesPerSecond(ui64 cycles); TDuration CyclesToDuration(ui64 cycles); ui64 DurationToCycles(TDuration duration); -class TPrecisionTimer { +class TPrecisionTimer { private: ui64 Start = 0; @@ -74,7 +74,7 @@ public: TString FormatCycles(ui64 cycles); -class TFormattedPrecisionTimer { +class TFormattedPrecisionTimer { private: ui64 Start; const char* Message; @@ -85,29 +85,29 @@ public: ~TFormattedPrecisionTimer(); }; -class TFuncTimer { -public: +class TFuncTimer { +public: TFuncTimer(const char* func); ~TFuncTimer(); - -private: + +private: const TInstant Start_; - const char* Func_; -}; - -class TFakeTimer { -public: + const char* Func_; +}; + +class TFakeTimer { +public: inline TFakeTimer(const char* = nullptr) noexcept { - } -}; - -#if defined(WITH_DEBUG) - #define TDebugTimer TFuncTimer -#else - #define TDebugTimer TFakeTimer + } +}; + +#if defined(WITH_DEBUG) + #define TDebugTimer TFuncTimer +#else + #define TDebugTimer TFakeTimer #endif - -class TTimeLogger { + +class TTimeLogger { private: TString Message; bool Verbose; diff --git a/util/datetime/parser.h b/util/datetime/parser.h index 8b19aa5c66..f0c1b4a0c7 100644 --- a/util/datetime/parser.h +++ b/util/datetime/parser.h @@ -99,10 +99,10 @@ public: const TDateTimeFields& GetDateTimeFields() const { return DateTimeFields; } - + protected: TDateTimeFields DateTimeFields; - int cs; //for ragel + int cs; //for ragel int Sign; int I; int Dc; @@ -111,8 +111,8 @@ protected: TDateTimeParserBase() : DateTimeFields() , cs(0) - , Sign(0) - , I(0xDEADBEEF) // to guarantee unittest break if ragel code is incorrect + , Sign(0) + , I(0xDEADBEEF) // to guarantee unittest break if ragel code is incorrect , Dc(0xDEADBEEF) { } @@ -124,10 +124,10 @@ protected: } }; -#define DECLARE_PARSER(CLASS) \ - struct CLASS: public TDateTimeParserBase { \ - CLASS(); \ - bool ParsePart(const char* input, size_t len); \ +#define DECLARE_PARSER(CLASS) \ + struct CLASS: public TDateTimeParserBase { \ + CLASS(); \ + bool ParsePart(const char* input, size_t len); \ TInstant GetResult(TInstant defaultValue) const; \ }; @@ -278,11 +278,11 @@ protected: } }; -#define DECLARE_PARSER(CLASS) \ - struct CLASS: public TDateTimeParserBaseDeprecated { \ - CLASS(); \ - bool ParsePart(const char* input, size_t len); \ - TInstant GetResult(TInstant defaultValue) const; \ +#define DECLARE_PARSER(CLASS) \ + struct CLASS: public TDateTimeParserBaseDeprecated { \ + CLASS(); \ + bool ParsePart(const char* input, size_t len); \ + TInstant GetResult(TInstant defaultValue) const; \ }; DECLARE_PARSER(TIso8601DateTimeParserDeprecated) diff --git a/util/datetime/parser.rl6 b/util/datetime/parser.rl6 index 0fb3656a35..931f09eae1 100644 --- a/util/datetime/parser.rl6 +++ b/util/datetime/parser.rl6 @@ -1,11 +1,11 @@ -#include <cstdio> -#include <cstdlib> -#include <cstring> -#include <cctype> -#include <ctime> -#include <numeric> - -#include <util/datetime/parser.h> +#include <cstdio> +#include <cstdlib> +#include <cstring> +#include <cctype> +#include <ctime> +#include <numeric> + +#include <util/datetime/parser.h> #include <util/generic/ymath.h> @@ -30,9 +30,9 @@ int = (digit+) $update_int; int1 = digit - >clear_int + >clear_int $update_int; - + int2 = (digit digit) >clear_int $update_int; @@ -48,7 +48,7 @@ int4 = (digit digit digit digit) int12 = (digit digit?) >clear_int $update_int; - + int24 = ( digit digit ( digit digit )? ) >clear_int $update_int; @@ -170,7 +170,7 @@ TRfc822DateTimeParserDeprecated::TRfc822DateTimeParserDeprecated() { bool TRfc822DateTimeParserDeprecated::ParsePart(const char* input, size_t len) { const char* p = input; const char* pe = input + len; - + %% write exec; return cs != %%{ write error; }%%; } diff --git a/util/datetime/parser_ut.cpp b/util/datetime/parser_ut.cpp index 3d9b9b0b3c..61364af997 100644 --- a/util/datetime/parser_ut.cpp +++ b/util/datetime/parser_ut.cpp @@ -1,5 +1,5 @@ -#include "parser.h" - +#include "parser.h" + #include <library/cpp/testing/unittest/registar.h> static const time_t SECONDS_PER_HOUR = 3600; @@ -11,10 +11,10 @@ Y_UNIT_TEST_SUITE(TDateTimeParseTest) { time_t t = 0; // predefined time zones - + r = ParseRFC822DateTime("Fri, 4 Mar 2005 19:34:45 UT", t); - UNIT_ASSERT(r); - UNIT_ASSERT_EQUAL(t, (time_t)1109964885); + UNIT_ASSERT(r); + UNIT_ASSERT_EQUAL(t, (time_t)1109964885); r = ParseRFC822DateTime("Fri, 4 Mar 2005 19:34:45 GMT", t); UNIT_ASSERT(r); @@ -50,57 +50,57 @@ Y_UNIT_TEST_SUITE(TDateTimeParseTest) { // optinal century r = ParseRFC822DateTime("Fri, 4 Mar 05 19:34:45 UT", t); - UNIT_ASSERT(r); - UNIT_ASSERT_EQUAL(t, (time_t)1109964885); - + UNIT_ASSERT(r); + UNIT_ASSERT_EQUAL(t, (time_t)1109964885); + // + optional day of week r = ParseRFC822DateTime("4 Mar 05 19:34:45 UT", t); UNIT_ASSERT(r); UNIT_ASSERT_EQUAL(t, (time_t)1109964885); - + // + optional seconds r = ParseRFC822DateTime("4 Mar 05 19:34 UT", t); UNIT_ASSERT(r); UNIT_ASSERT_EQUAL(t, (time_t)1109964840); // local differential hour+min - + r = ParseRFC822DateTime("Fri, 4 Mar 2005 19:34:45 +0300", t); - UNIT_ASSERT(r); - UNIT_ASSERT_EQUAL(t, (time_t)1109954085); + UNIT_ASSERT(r); + UNIT_ASSERT_EQUAL(t, (time_t)1109954085); r = ParseRFC822DateTime("Fri, 4 Mar 05 19:34:45 +0300", t); - UNIT_ASSERT(r); - UNIT_ASSERT_EQUAL(t, (time_t)1109954085); - + UNIT_ASSERT(r); + UNIT_ASSERT_EQUAL(t, (time_t)1109954085); + r = ParseRFC822DateTime("21 Apr 1999 23:40:00 +0400", t); - UNIT_ASSERT(r); - UNIT_ASSERT_EQUAL(t, (time_t)924723600); - + UNIT_ASSERT(r); + UNIT_ASSERT_EQUAL(t, (time_t)924723600); + r = ParseRFC822DateTime("21 Apr 99 23:40 +0400", t); - UNIT_ASSERT(r); - UNIT_ASSERT_EQUAL(t, (time_t)924723600); + UNIT_ASSERT(r); + UNIT_ASSERT_EQUAL(t, (time_t)924723600); r = ParseRFC822DateTime("Fri, 4 Mar 2005 19:34:45 -0300", t); UNIT_ASSERT(r); UNIT_ASSERT_EQUAL(t, (time_t)1109964885 + 3 * SECONDS_PER_HOUR); - + r = ParseRFC822DateTime("Fri, 4 Mar 2005 19:34 -0300", t); UNIT_ASSERT(r); UNIT_ASSERT_EQUAL(t, (time_t)1109964840 + 3 * SECONDS_PER_HOUR); - + r = ParseRFC822DateTime("Fri, 4 Mar 05 19:34:45 -0330", t); UNIT_ASSERT(r); UNIT_ASSERT_EQUAL(t, (time_t)1109964885 + 3 * SECONDS_PER_HOUR + 30 * SECONDS_PER_MINUTE); - + r = ParseRFC822DateTime("Fri, 4 Mar 05 19:34 -0330", t); UNIT_ASSERT(r); UNIT_ASSERT_EQUAL(t, (time_t)1109964840 + 3 * SECONDS_PER_HOUR + 30 * SECONDS_PER_MINUTE); - + r = ParseRFC822DateTime("4 Mar 2005 19:34:45 -1030", t); UNIT_ASSERT(r); UNIT_ASSERT_EQUAL(t, (time_t)1109964885 + 10 * SECONDS_PER_HOUR + 30 * SECONDS_PER_MINUTE); - + r = ParseRFC822DateTime("4 Mar 2005 19:34 -1030", t); UNIT_ASSERT(r); UNIT_ASSERT_EQUAL(t, (time_t)1109964840 + 10 * SECONDS_PER_HOUR + 30 * SECONDS_PER_MINUTE); @@ -128,7 +128,7 @@ Y_UNIT_TEST_SUITE(TDateTimeParseTest) { UNIT_ASSERT_EQUAL(t, (time_t)1234567890); } - time_t GetOffset(char militaryZone) { + time_t GetOffset(char militaryZone) { char ch = (char)toupper(militaryZone); if (ch == 'Z') { return 0; @@ -148,7 +148,7 @@ Y_UNIT_TEST_SUITE(TDateTimeParseTest) { char text[] = "Fri, 4 Mar 2005 19:34:45 A"; const size_t zoneCharIndex = strlen(text) - 1; - for (char militaryZone = firstChar; militaryZone <= lastChar; ++militaryZone) { + for (char militaryZone = firstChar; militaryZone <= lastChar; ++militaryZone) { time_t t = 0; const time_t offset = GetOffset(militaryZone); // the last character is replaced with next zone symbol @@ -169,7 +169,7 @@ Y_UNIT_TEST_SUITE(TDateTimeParseTest) { Y_UNIT_TEST(TestRfc822IncorrectDates) { bool r = true; time_t t = 0; - + t = 12345; r = ParseRFC822DateTime("", t); UNIT_ASSERT(!r); @@ -182,19 +182,19 @@ Y_UNIT_TEST_SUITE(TDateTimeParseTest) { t = 54321; r = ParseRFC822DateTime("Fri, 4 Mar 2005 19:34:45 UTC", t); - UNIT_ASSERT(!r); + UNIT_ASSERT(!r); UNIT_ASSERT_EQUAL(t, (time_t)54321); // TODO: check semantic validity of parsed date (30 Feb, 88:90 etc.). // The following tests MUST fail (they don't now) // r = ParseRFC822DateTime("45 Mar 2005 19:34:45 UT", t); - // UNIT_ASSERT_EQUAL(r, false); + // UNIT_ASSERT_EQUAL(r, false); // r = ParseRFC822DateTime("29 Feb 2005 19:34:45 +0300", t); - // UNIT_ASSERT_EQUAL(r, false); + // UNIT_ASSERT_EQUAL(r, false); // r = ParseRFC822DateTime("31 Apr 2004 19:34:45 +0300", t); - // UNIT_ASSERT_EQUAL(r, false); + // UNIT_ASSERT_EQUAL(r, false); r = ParseRFC822DateTime("17 Nov 2008 19:34:45", t); // no specified time zone UNIT_ASSERT(!r); @@ -265,7 +265,7 @@ Y_UNIT_TEST_SUITE(TDateTimeParseTest) { p = TRfc822DateTimeParser(); const char* part3 = "Fri, 4 Mar 05 19:34:46 +0300"; UNIT_ASSERT(p.ParsePart(part3, strlen(part3))); - UNIT_ASSERT_VALUES_EQUAL(TInstant::Seconds(1109954086), p.GetResult(TInstant::Zero())); + UNIT_ASSERT_VALUES_EQUAL(TInstant::Seconds(1109954086), p.GetResult(TInstant::Zero())); } Y_UNIT_TEST(TestIso8601Partial) { @@ -278,7 +278,7 @@ Y_UNIT_TEST_SUITE(TDateTimeParseTest) { p = TIso8601DateTimeParser(); const char* part3 = "1990-03-15T15:16:18+0732"; UNIT_ASSERT(p.ParsePart(part3, strlen(part3))); - UNIT_ASSERT_VALUES_EQUAL(TInstant::Seconds(637487058), p.GetResult(TInstant::Zero())); + UNIT_ASSERT_VALUES_EQUAL(TInstant::Seconds(637487058), p.GetResult(TInstant::Zero())); } Y_UNIT_TEST(TestIso8601Correct) { @@ -355,7 +355,7 @@ Y_UNIT_TEST_SUITE(TDateTimeParseTest) { ret = ParseISO8601DateTime("2009-02-14 02:31:30+03:00", t); UNIT_ASSERT(ret); UNIT_ASSERT_VALUES_EQUAL(t, 1234567890); - + ret = ParseISO8601DateTime("2010-03-28T04:27:00.000-07:00", t); UNIT_ASSERT(ret); UNIT_ASSERT_VALUES_EQUAL(t, 1269775620); @@ -409,16 +409,16 @@ Y_UNIT_TEST_SUITE(TDateTimeParseTest) { Y_UNIT_TEST(TestIso8601Fractions) { UNIT_ASSERT_VALUES_EQUAL( TInstant::ParseIso8601("2009-09-19 03:37:08.1+04:00"), - TInstant::Seconds(1253317028) + TDuration::MilliSeconds(100)); + TInstant::Seconds(1253317028) + TDuration::MilliSeconds(100)); UNIT_ASSERT_VALUES_EQUAL( TInstant::ParseIso8601("2009-09-19 03:37:03.926+04:00"), - TInstant::Seconds(1253317023) + TDuration::MilliSeconds(926)); + TInstant::Seconds(1253317023) + TDuration::MilliSeconds(926)); UNIT_ASSERT_VALUES_EQUAL( TInstant::ParseIso8601("2009-09-19 03:37:03.92622+04:00"), - TInstant::Seconds(1253317023) + TDuration::MicroSeconds(926220)); + TInstant::Seconds(1253317023) + TDuration::MicroSeconds(926220)); UNIT_ASSERT_VALUES_EQUAL( TInstant::ParseIso8601("2009-09-19 03:37:03.012331+04:00"), - TInstant::Seconds(1253317023) + TDuration::MicroSeconds(12331)); + TInstant::Seconds(1253317023) + TDuration::MicroSeconds(12331)); } Y_UNIT_TEST(TestIso8601FractionsBelowMicro) { @@ -572,7 +572,7 @@ Y_UNIT_TEST_SUITE(TDateTimeParseTest) { Y_UNIT_TEST_SUITE(TDurationParseTest) { Y_UNIT_TEST(TestParse) { - UNIT_ASSERT_VALUES_EQUAL(TDuration::Seconds(60 * 60 * 24 * 7), TDuration::Parse("1w")); + UNIT_ASSERT_VALUES_EQUAL(TDuration::Seconds(60 * 60 * 24 * 7), TDuration::Parse("1w")); UNIT_ASSERT_VALUES_EQUAL(TDuration::Seconds(60), TDuration::Parse("1m")); UNIT_ASSERT_VALUES_EQUAL(TDuration::Seconds(90), TDuration::Parse("1.5m")); UNIT_ASSERT_VALUES_EQUAL(TDuration::Seconds(102), TDuration::Parse("1.7m")); diff --git a/util/datetime/strptime.cpp b/util/datetime/strptime.cpp index 6da3dc5a67..f0d4ec333e 100644 --- a/util/datetime/strptime.cpp +++ b/util/datetime/strptime.cpp @@ -57,40 +57,40 @@ #include <util/system/compat.h> #include "systime.h" #ifdef _win32_ - #ifndef lint - #ifndef NOID + #ifndef lint + #ifndef NOID static char copyright[] = - "@(#) Copyright (c) 1994 Powerdog Industries. All rights reserved."; + "@(#) Copyright (c) 1994 Powerdog Industries. All rights reserved."; static char sccsid[] = "@(#)strptime.c 0.1 (Powerdog) 94/03/27"; - #endif /* !defined NOID */ - #endif /* not lint */ - //__FBSDID("$FreeBSD: src/lib/libc/stdtime/strptime.c,v 1.35 2003/11/17 04:19:15 nectar Exp $"); - - //#include "namespace.h" - #include <time.h> - #include <ctype.h> - #include <errno.h> - #include <stdlib.h> - #include <string.h> + #endif /* !defined NOID */ + #endif /* not lint */ + //__FBSDID("$FreeBSD: src/lib/libc/stdtime/strptime.c,v 1.35 2003/11/17 04:19:15 nectar Exp $"); + + //#include "namespace.h" + #include <time.h> + #include <ctype.h> + #include <errno.h> + #include <stdlib.h> + #include <string.h> //#include <pthread.h> //#include "un-namespace.h" //#include "libc_private.h" // ******************* #include "timelocal.h" ********************* struct lc_time_T { - const char* mon[12]; - const char* month[12]; - const char* wday[7]; - const char* weekday[7]; - const char* X_fmt; - const char* x_fmt; - const char* c_fmt; - const char* am; - const char* pm; - const char* date_fmt; - const char* alt_month[12]; - const char* md_order; - const char* ampm_fmt; + const char* mon[12]; + const char* month[12]; + const char* wday[7]; + const char* weekday[7]; + const char* X_fmt; + const char* x_fmt; + const char* c_fmt; + const char* am; + const char* pm; + const char* date_fmt; + const char* alt_month[12]; + const char* md_order; + const char* ampm_fmt; }; // ******************* timelocal.c ****************** @@ -99,86 +99,86 @@ struct lc_time_T { * Copyright (c) 1997 FreeBSD Inc. * All rights reserved. */ -static const struct lc_time_T _C_time_locale = { - {"Jan", "Feb", "Mar", "Apr", "May", "Jun", - "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"}, - {"January", "February", "March", "April", "May", "June", - "July", "August", "September", "October", "November", "December"}, - {"Sun", "Mon", "Tue", "Wed", - "Thu", "Fri", "Sat"}, - {"Sunday", "Monday", "Tuesday", "Wednesday", - "Thursday", "Friday", "Saturday"}, - - /* X_fmt */ - "%H:%M:%S", - - /* +static const struct lc_time_T _C_time_locale = { + {"Jan", "Feb", "Mar", "Apr", "May", "Jun", + "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"}, + {"January", "February", "March", "April", "May", "June", + "July", "August", "September", "October", "November", "December"}, + {"Sun", "Mon", "Tue", "Wed", + "Thu", "Fri", "Sat"}, + {"Sunday", "Monday", "Tuesday", "Wednesday", + "Thursday", "Friday", "Saturday"}, + + /* X_fmt */ + "%H:%M:%S", + + /* * x_fmt * Since the C language standard calls for * "date, using locale's date format," anything goes. * Using just numbers (as here) makes Quakers happier; * it's also compatible with SVR4. */ - "%m/%d/%y", + "%m/%d/%y", - /* + /* * c_fmt */ - "%a %b %e %H:%M:%S %Y", + "%a %b %e %H:%M:%S %Y", - /* am */ - "AM", + /* am */ + "AM", - /* pm */ - "PM", + /* pm */ + "PM", - /* date_fmt */ - "%a %b %e %H:%M:%S %Z %Y", + /* date_fmt */ + "%a %b %e %H:%M:%S %Z %Y", - /* alt_month + /* alt_month * Standalone months forms for %OB */ - { - "January", "February", "March", "April", "May", "June", - "July", "August", "September", "October", "November", "December"}, + { + "January", "February", "March", "April", "May", "June", + "July", "August", "September", "October", "November", "December"}, - /* md_order + /* md_order * Month / day order in dates */ - "md", + "md", - /* ampm_fmt + /* ampm_fmt * To determine 12-hour clock format time (empty, if N/A) */ - "%I:%M:%S %p"}; + "%I:%M:%S %p"}; -struct lc_time_T* +struct lc_time_T* __get_current_time_locale(void) { - return /*(_time_using_locale + return /*(_time_using_locale ? &_time_locale - :*/ - (struct lc_time_T*)&_C_time_locale /*)*/; + :*/ + (struct lc_time_T*)&_C_time_locale /*)*/; } // ******************* strptime.c ******************* -static char* _strptime(const char*, const char*, struct tm*, int*); +static char* _strptime(const char*, const char*, struct tm*, int*); - #define asizeof(a) (sizeof(a) / sizeof((a)[0])) + #define asizeof(a) (sizeof(a) / sizeof((a)[0])) - #if defined(_MSC_VER) && (_MSC_VER >= 1900) - #define tzname _tzname - #endif - -static char* -_strptime(const char* buf, const char* fmt, struct tm* tm, int* GMTp) + #if defined(_MSC_VER) && (_MSC_VER >= 1900) + #define tzname _tzname + #endif + +static char* +_strptime(const char* buf, const char* fmt, struct tm* tm, int* GMTp) { - char c; - const char* ptr; - int i; + char c; + const char* ptr; + int i; size_t len = 0; int Ealternative, Oalternative; - struct lc_time_T* tptr = __get_current_time_locale(); + struct lc_time_T* tptr = __get_current_time_locale(); ptr = fmt; while (*ptr != 0) { @@ -198,149 +198,149 @@ _strptime(const char* buf, const char* fmt, struct tm* tm, int* GMTp) Ealternative = 0; Oalternative = 0; - label: + label: c = *ptr++; switch (c) { - case 0: - case '%': - if (*buf++ != '%') - return 0; - break; - - case '+': - buf = _strptime(buf, tptr->date_fmt, tm, GMTp); - if (buf == 0) - return 0; - break; - - case 'C': - if (!isdigit((unsigned char)*buf)) - return 0; - - /* XXX This will break for 3-digit centuries. */ - len = 2; - for (i = 0; len && *buf != 0 && isdigit((unsigned char)*buf); buf++) { - i *= 10; - i += *buf - '0'; - --len; - } - if (i < 19) - return 0; - - tm->tm_year = i * 100 - 1900; - break; - - case 'c': - buf = _strptime(buf, tptr->c_fmt, tm, GMTp); - if (buf == 0) - return 0; + case 0: + case '%': + if (*buf++ != '%') + return 0; + break; + + case '+': + buf = _strptime(buf, tptr->date_fmt, tm, GMTp); + if (buf == 0) + return 0; + break; + + case 'C': + if (!isdigit((unsigned char)*buf)) + return 0; + + /* XXX This will break for 3-digit centuries. */ + len = 2; + for (i = 0; len && *buf != 0 && isdigit((unsigned char)*buf); buf++) { + i *= 10; + i += *buf - '0'; + --len; + } + if (i < 19) + return 0; + + tm->tm_year = i * 100 - 1900; + break; + + case 'c': + buf = _strptime(buf, tptr->c_fmt, tm, GMTp); + if (buf == 0) + return 0; + break; + + case 'D': + buf = _strptime(buf, "%m/%d/%y", tm, GMTp); + if (buf == 0) + return 0; + break; + + case 'E': + if (Ealternative || Oalternative) + break; + ++Ealternative; + goto label; + + case 'O': + if (Ealternative || Oalternative) + break; + ++Oalternative; + goto label; + + case 'F': + buf = _strptime(buf, "%Y-%m-%d", tm, GMTp); + if (buf == 0) + return 0; + break; + + case 'R': + buf = _strptime(buf, "%H:%M", tm, GMTp); + if (buf == 0) + return 0; + break; + + case 'r': + buf = _strptime(buf, tptr->ampm_fmt, tm, GMTp); + if (buf == 0) + return 0; break; - case 'D': - buf = _strptime(buf, "%m/%d/%y", tm, GMTp); - if (buf == 0) - return 0; + case 'T': + buf = _strptime(buf, "%H:%M:%S", tm, GMTp); + if (buf == 0) + return 0; + break; + + case 'X': + buf = _strptime(buf, tptr->X_fmt, tm, GMTp); + if (buf == 0) + return 0; + break; + + case 'x': + buf = _strptime(buf, tptr->x_fmt, tm, GMTp); + if (buf == 0) + return 0; break; - case 'E': - if (Ealternative || Oalternative) - break; - ++Ealternative; - goto label; - - case 'O': - if (Ealternative || Oalternative) - break; - ++Oalternative; - goto label; - - case 'F': - buf = _strptime(buf, "%Y-%m-%d", tm, GMTp); - if (buf == 0) - return 0; - break; - - case 'R': - buf = _strptime(buf, "%H:%M", tm, GMTp); - if (buf == 0) - return 0; - break; - - case 'r': - buf = _strptime(buf, tptr->ampm_fmt, tm, GMTp); - if (buf == 0) - return 0; - break; - - case 'T': - buf = _strptime(buf, "%H:%M:%S", tm, GMTp); - if (buf == 0) - return 0; - break; - - case 'X': - buf = _strptime(buf, tptr->X_fmt, tm, GMTp); - if (buf == 0) - return 0; - break; - - case 'x': - buf = _strptime(buf, tptr->x_fmt, tm, GMTp); - if (buf == 0) - return 0; - break; - - case 'j': - if (!isdigit((unsigned char)*buf)) - return 0; - - len = 3; - for (i = 0; len && *buf != 0 && isdigit((unsigned char)*buf); buf++) { - i *= 10; - i += *buf - '0'; - --len; - } - if (i < 1 || i > 366) - return 0; - - tm->tm_yday = i - 1; + case 'j': + if (!isdigit((unsigned char)*buf)) + return 0; + + len = 3; + for (i = 0; len && *buf != 0 && isdigit((unsigned char)*buf); buf++) { + i *= 10; + i += *buf - '0'; + --len; + } + if (i < 1 || i > 366) + return 0; + + tm->tm_yday = i - 1; break; - case 'M': - case 'S': - if (*buf == 0 || isspace((unsigned char)*buf)) - break; + case 'M': + case 'S': + if (*buf == 0 || isspace((unsigned char)*buf)) + break; - if (!isdigit((unsigned char)*buf)) + if (!isdigit((unsigned char)*buf)) return 0; - len = 2; - for (i = 0; len && *buf != 0 && isdigit((unsigned char)*buf); buf++) { - i *= 10; - i += *buf - '0'; - --len; - } - - if (c == 'M') { - if (i > 59) - return 0; - tm->tm_min = i; - } else { - if (i > 60) - return 0; - tm->tm_sec = i; - } - - if (*buf != 0 && isspace((unsigned char)*buf)) - while (*ptr != 0 && !isspace((unsigned char)*ptr)) - ++ptr; - break; - - case 'H': - case 'I': - case 'k': - case 'l': - /* + len = 2; + for (i = 0; len && *buf != 0 && isdigit((unsigned char)*buf); buf++) { + i *= 10; + i += *buf - '0'; + --len; + } + + if (c == 'M') { + if (i > 59) + return 0; + tm->tm_min = i; + } else { + if (i > 60) + return 0; + tm->tm_sec = i; + } + + if (*buf != 0 && isspace((unsigned char)*buf)) + while (*ptr != 0 && !isspace((unsigned char)*ptr)) + ++ptr; + break; + + case 'H': + case 'I': + case 'k': + case 'l': + /* * Of these, %l is the only specifier explicitly * documented as not being zero-padded. However, * there is no harm in allowing zero-padding. @@ -348,117 +348,117 @@ _strptime(const char* buf, const char* fmt, struct tm* tm, int* GMTp) * XXX The %l specifier may gobble one too many * digits if used incorrectly. */ - if (!isdigit((unsigned char)*buf)) - return 0; - - len = 2; - for (i = 0; len && *buf != 0 && isdigit((unsigned char)*buf); buf++) { - i *= 10; - i += *buf - '0'; - --len; - } - if (c == 'H' || c == 'k') { - if (i > 23) - return 0; - } else if (i > 12) + if (!isdigit((unsigned char)*buf)) return 0; - tm->tm_hour = i; + len = 2; + for (i = 0; len && *buf != 0 && isdigit((unsigned char)*buf); buf++) { + i *= 10; + i += *buf - '0'; + --len; + } + if (c == 'H' || c == 'k') { + if (i > 23) + return 0; + } else if (i > 12) + return 0; - if (*buf != 0 && isspace((unsigned char)*buf)) - while (*ptr != 0 && !isspace((unsigned char)*ptr)) - ++ptr; - break; + tm->tm_hour = i; - case 'p': - /* + if (*buf != 0 && isspace((unsigned char)*buf)) + while (*ptr != 0 && !isspace((unsigned char)*ptr)) + ++ptr; + break; + + case 'p': + /* * XXX This is bogus if parsed before hour-related * specifiers. */ - len = strlen(tptr->am); - if (strnicmp(buf, tptr->am, len) == 0) { - if (tm->tm_hour > 12) - return 0; - if (tm->tm_hour == 12) - tm->tm_hour = 0; - buf += len; - break; - } - - len = strlen(tptr->pm); - if (strnicmp(buf, tptr->pm, len) == 0) { - if (tm->tm_hour > 12) - return 0; - if (tm->tm_hour != 12) - tm->tm_hour += 12; - buf += len; - break; - } - - return 0; - - case 'A': - case 'a': - for (i = 0; i < asizeof(tptr->weekday); i++) { - len = strlen(tptr->weekday[i]); - if (strnicmp(buf, tptr->weekday[i], - len) == 0) - break; - len = strlen(tptr->wday[i]); - if (strnicmp(buf, tptr->wday[i], - len) == 0) - break; - } - if (i == asizeof(tptr->weekday)) + len = strlen(tptr->am); + if (strnicmp(buf, tptr->am, len) == 0) { + if (tm->tm_hour > 12) + return 0; + if (tm->tm_hour == 12) + tm->tm_hour = 0; + buf += len; + break; + } + + len = strlen(tptr->pm); + if (strnicmp(buf, tptr->pm, len) == 0) { + if (tm->tm_hour > 12) + return 0; + if (tm->tm_hour != 12) + tm->tm_hour += 12; + buf += len; + break; + } + + return 0; + + case 'A': + case 'a': + for (i = 0; i < asizeof(tptr->weekday); i++) { + len = strlen(tptr->weekday[i]); + if (strnicmp(buf, tptr->weekday[i], + len) == 0) + break; + len = strlen(tptr->wday[i]); + if (strnicmp(buf, tptr->wday[i], + len) == 0) + break; + } + if (i == asizeof(tptr->weekday)) return 0; - tm->tm_wday = i; + tm->tm_wday = i; buf += len; break; - case 'U': - case 'W': - /* + case 'U': + case 'W': + /* * XXX This is bogus, as we can not assume any valid * information present in the tm structure at this * point to calculate a real value, so just check the * range for now. */ - if (!isdigit((unsigned char)*buf)) - return 0; - - len = 2; - for (i = 0; len && *buf != 0 && isdigit((unsigned char)*buf); buf++) { - i *= 10; - i += *buf - '0'; - --len; - } - if (i > 53) - return 0; - - if (*buf != 0 && isspace((unsigned char)*buf)) - while (*ptr != 0 && !isspace((unsigned char)*ptr)) - ++ptr; - break; - - case 'w': - if (!isdigit((unsigned char)*buf)) - return 0; - - i = *buf - '0'; - if (i > 6) - return 0; - - tm->tm_wday = i; - - if (*buf != 0 && isspace((unsigned char)*buf)) - while (*ptr != 0 && !isspace((unsigned char)*ptr)) - ++ptr; - break; - - case 'd': - case 'e': - /* + if (!isdigit((unsigned char)*buf)) + return 0; + + len = 2; + for (i = 0; len && *buf != 0 && isdigit((unsigned char)*buf); buf++) { + i *= 10; + i += *buf - '0'; + --len; + } + if (i > 53) + return 0; + + if (*buf != 0 && isspace((unsigned char)*buf)) + while (*ptr != 0 && !isspace((unsigned char)*ptr)) + ++ptr; + break; + + case 'w': + if (!isdigit((unsigned char)*buf)) + return 0; + + i = *buf - '0'; + if (i > 6) + return 0; + + tm->tm_wday = i; + + if (*buf != 0 && isspace((unsigned char)*buf)) + while (*ptr != 0 && !isspace((unsigned char)*ptr)) + ++ptr; + break; + + case 'd': + case 'e': + /* * The %e specifier is explicitly documented as not * being zero-padded but there is no harm in allowing * such padding. @@ -466,153 +466,153 @@ _strptime(const char* buf, const char* fmt, struct tm* tm, int* GMTp) * XXX The %e specifier may gobble one too many * digits if used incorrectly. */ - if (!isdigit((unsigned char)*buf)) - return 0; - - len = 2; - for (i = 0; len && *buf != 0 && isdigit((unsigned char)*buf); buf++) { - i *= 10; - i += *buf - '0'; - --len; - } - if (i > 31) - return 0; - - tm->tm_mday = i; - - if (*buf != 0 && isspace((unsigned char)*buf)) - while (*ptr != 0 && !isspace((unsigned char)*ptr)) - ++ptr; - break; - - case 'B': - case 'b': - case 'h': - for (i = 0; i < asizeof(tptr->month); i++) { - if (Oalternative) { - if (c == 'B') { - len = strlen(tptr->alt_month[i]); - if (strnicmp(buf, - tptr->alt_month[i], - len) == 0) - break; - } - } else { - len = strlen(tptr->month[i]); - if (strnicmp(buf, tptr->month[i], - len) == 0) + if (!isdigit((unsigned char)*buf)) + return 0; + + len = 2; + for (i = 0; len && *buf != 0 && isdigit((unsigned char)*buf); buf++) { + i *= 10; + i += *buf - '0'; + --len; + } + if (i > 31) + return 0; + + tm->tm_mday = i; + + if (*buf != 0 && isspace((unsigned char)*buf)) + while (*ptr != 0 && !isspace((unsigned char)*ptr)) + ++ptr; + break; + + case 'B': + case 'b': + case 'h': + for (i = 0; i < asizeof(tptr->month); i++) { + if (Oalternative) { + if (c == 'B') { + len = strlen(tptr->alt_month[i]); + if (strnicmp(buf, + tptr->alt_month[i], + len) == 0) + break; + } + } else { + len = strlen(tptr->month[i]); + if (strnicmp(buf, tptr->month[i], + len) == 0) + break; + len = strlen(tptr->mon[i]); + if (strnicmp(buf, tptr->mon[i], + len) == 0) break; - len = strlen(tptr->mon[i]); - if (strnicmp(buf, tptr->mon[i], - len) == 0) - break; } } - if (i == asizeof(tptr->month)) - return 0; - - tm->tm_mon = i; - buf += len; - break; - - case 'm': - if (!isdigit((unsigned char)*buf)) - return 0; - - len = 2; - for (i = 0; len && *buf != 0 && isdigit((unsigned char)*buf); buf++) { - i *= 10; - i += *buf - '0'; - --len; - } - if (i < 1 || i > 12) - return 0; - - tm->tm_mon = i - 1; - - if (*buf != 0 && isspace((unsigned char)*buf)) - while (*ptr != 0 && !isspace((unsigned char)*ptr)) - ++ptr; - break; - - case 's': { - char* cp; - int sverrno; - long n; - time_t t; - - sverrno = errno; - errno = 0; - n = strtol(buf, &cp, 10); - if (errno == ERANGE || (long)(t = n) != n) { - errno = sverrno; - return 0; - } + if (i == asizeof(tptr->month)) + return 0; + + tm->tm_mon = i; + buf += len; + break; + + case 'm': + if (!isdigit((unsigned char)*buf)) + return 0; + + len = 2; + for (i = 0; len && *buf != 0 && isdigit((unsigned char)*buf); buf++) { + i *= 10; + i += *buf - '0'; + --len; + } + if (i < 1 || i > 12) + return 0; + + tm->tm_mon = i - 1; + + if (*buf != 0 && isspace((unsigned char)*buf)) + while (*ptr != 0 && !isspace((unsigned char)*ptr)) + ++ptr; + break; + + case 's': { + char* cp; + int sverrno; + long n; + time_t t; + + sverrno = errno; + errno = 0; + n = strtol(buf, &cp, 10); + if (errno == ERANGE || (long)(t = n) != n) { + errno = sverrno; + return 0; + } errno = sverrno; - buf = cp; - GmTimeR(&t, tm); - *GMTp = 1; - } break; - - case 'Y': - case 'y': - if (*buf == 0 || isspace((unsigned char)*buf)) - break; - - if (!isdigit((unsigned char)*buf)) - return 0; - - len = (c == 'Y') ? 4 : 2; - for (i = 0; len && *buf != 0 && isdigit((unsigned char)*buf); buf++) { - i *= 10; - i += *buf - '0'; - --len; - } - if (c == 'Y') - i -= 1900; - if (c == 'y' && i < 69) - i += 100; - if (i < 0) - return 0; - - tm->tm_year = i; - - if (*buf != 0 && isspace((unsigned char)*buf)) - while (*ptr != 0 && !isspace((unsigned char)*ptr)) - ++ptr; - break; - - case 'Z': { - const char* cp; - char* zonestr; - - for (cp = buf; *cp && isupper((unsigned char)*cp); ++cp) { /*empty*/ + buf = cp; + GmTimeR(&t, tm); + *GMTp = 1; + } break; + + case 'Y': + case 'y': + if (*buf == 0 || isspace((unsigned char)*buf)) + break; + + if (!isdigit((unsigned char)*buf)) + return 0; + + len = (c == 'Y') ? 4 : 2; + for (i = 0; len && *buf != 0 && isdigit((unsigned char)*buf); buf++) { + i *= 10; + i += *buf - '0'; + --len; + } + if (c == 'Y') + i -= 1900; + if (c == 'y' && i < 69) + i += 100; + if (i < 0) + return 0; + + tm->tm_year = i; + + if (*buf != 0 && isspace((unsigned char)*buf)) + while (*ptr != 0 && !isspace((unsigned char)*ptr)) + ++ptr; + break; + + case 'Z': { + const char* cp; + char* zonestr; + + for (cp = buf; *cp && isupper((unsigned char)*cp); ++cp) { /*empty*/ + } + if (cp - buf) { + zonestr = (char*)alloca(cp - buf + 1); + strncpy(zonestr, buf, cp - buf); + zonestr[cp - buf] = '\0'; + tzset(); + if (0 == strcmp(zonestr, "GMT")) { + *GMTp = 1; + } else if (0 == strcmp(zonestr, tzname[0])) { + tm->tm_isdst = 0; + } else if (0 == strcmp(zonestr, tzname[1])) { + tm->tm_isdst = 1; + } else { + return 0; + } + buf += cp - buf; } - if (cp - buf) { - zonestr = (char*)alloca(cp - buf + 1); - strncpy(zonestr, buf, cp - buf); - zonestr[cp - buf] = '\0'; - tzset(); - if (0 == strcmp(zonestr, "GMT")) { - *GMTp = 1; - } else if (0 == strcmp(zonestr, tzname[0])) { - tm->tm_isdst = 0; - } else if (0 == strcmp(zonestr, tzname[1])) { - tm->tm_isdst = 1; - } else { - return 0; - } - buf += cp - buf; - } - } break; + } break; } } - return (char*)buf; + return (char*)buf; } -char* strptime(const char* buf, const char* fmt, struct tm* tm) +char* strptime(const char* buf, const char* fmt, struct tm* tm) { - char* ret; + char* ret; int gmt; gmt = 0; diff --git a/util/datetime/systime.cpp b/util/datetime/systime.cpp index 4c328ec4d0..6ee7e8fc6e 100644 --- a/util/datetime/systime.cpp +++ b/util/datetime/systime.cpp @@ -1,29 +1,29 @@ #include "systime.h" -#include <util/system/yassert.h> -#include <util/system/defaults.h> - +#include <util/system/yassert.h> +#include <util/system/defaults.h> + #ifdef _win_ -void FileTimeToTimeval(const FILETIME* ft, timeval* tv) { +void FileTimeToTimeval(const FILETIME* ft, timeval* tv) { const i64 NANOINTERVAL = LL(116444736000000000); // Number of 100 nanosecond units from 1/1/1601 to 1/1/1970 - union { - ui64 ft_scalar; - FILETIME ft_struct; - } nt_time; + union { + ui64 ft_scalar; + FILETIME ft_struct; + } nt_time; nt_time.ft_struct = *ft; tv->tv_sec = (long)((nt_time.ft_scalar - NANOINTERVAL) / LL(10000000)); tv->tv_usec = (i32)((nt_time.ft_scalar / LL(10)) % LL(1000000)); } -int gettimeofday(timeval* tp, void*) { +int gettimeofday(timeval* tp, void*) { FILETIME ft; GetSystemTimeAsFileTime(&ft); FileTimeToTimeval(&ft, tp); return 0; } -tm* localtime_r(const time_t* clock, tm* result) { +tm* localtime_r(const time_t* clock, tm* result) { tzset(); tm* res = localtime(clock); if (res) { @@ -33,11 +33,11 @@ tm* localtime_r(const time_t* clock, tm* result) { return 0; } -tm* gmtime_r(const time_t* clock, tm* result) { +tm* gmtime_r(const time_t* clock, tm* result) { return gmtime_s(result, clock) == 0 ? result : 0; } -char* ctime_r(const time_t* clock, char* buf) { +char* ctime_r(const time_t* clock, char* buf) { char* res = ctime(clock); if (res) { memcpy(buf, res, 26); @@ -48,12 +48,12 @@ char* ctime_r(const time_t* clock, char* buf) { #endif /* _win_ */ -#define YEAR0 1900 -#define EPOCH_YR 1970 -#define SECS_DAY (24L * 60L * 60L) -#define LEAPYEAR(year) (!((year) % 4) && (((year) % 100) || !((year) % 400))) -#define YEARSIZE(year) (LEAPYEAR(year) ? 366 : 365) -#define FOURCENTURIES (400 * 365 + 100 - 3) +#define YEAR0 1900 +#define EPOCH_YR 1970 +#define SECS_DAY (24L * 60L * 60L) +#define LEAPYEAR(year) (!((year) % 4) && (((year) % 100) || !((year) % 400))) +#define YEARSIZE(year) (LEAPYEAR(year) ? 366 : 365) +#define FOURCENTURIES (400 * 365 + 100 - 3) //! Inverse of gmtime: converts struct tm to time_t, assuming the data //! in tm is UTC rather than local timezone. This implementation @@ -63,32 +63,32 @@ char* ctime_r(const time_t* clock, char* buf) { //! Subject: A more robust timegm - msg#00010 time_t TimeGM(const struct tm* t) { static const unsigned short int month_to_days[][13] = { - {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334}, - {0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335}}; + {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334}, + {0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335}}; // Only handles years after 1970 - if (t->tm_year < 70) { - return (time_t)-1; - } + if (t->tm_year < 70) { + return (time_t)-1; + } int days = 365 * (t->tm_year - 70); // Take into account the leap days between 1970 and YEAR-1 days += (t->tm_year - 1 - 68) / 4 - ((t->tm_year - 1) / 100) + ((t->tm_year - 1 + 300) / 400); - if (t->tm_mon < 0 || t->tm_mon >= 12) { - return (time_t)-1; - } - days += month_to_days[LEAPYEAR(1900 + t->tm_year)][t->tm_mon]; + if (t->tm_mon < 0 || t->tm_mon >= 12) { + return (time_t)-1; + } + days += month_to_days[LEAPYEAR(1900 + t->tm_year)][t->tm_mon]; days += t->tm_mday - 1; unsigned long secs = days * 86400ul + t->tm_hour * 3600 + t->tm_min * 60 + t->tm_sec; - return (time_t)secs; + return (time_t)secs; } -struct tm* GmTimeR(const time_t* timer, struct tm* tmbuf) { +struct tm* GmTimeR(const time_t* timer, struct tm* tmbuf) { static const int _ytab[2][12] = { {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}, - {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}}; + {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}}; i64 time = static_cast<i64>(*timer); @@ -101,8 +101,8 @@ struct tm* GmTimeR(const time_t* timer, struct tm* tmbuf) { year -= shift * 400; } - dayclock = (ui64)time % SECS_DAY; - dayno = (ui64)time / SECS_DAY; + dayclock = (ui64)time % SECS_DAY; + dayno = (ui64)time / SECS_DAY; year += 400 * (dayno / FOURCENTURIES); dayno = dayno % FOURCENTURIES; @@ -111,14 +111,14 @@ struct tm* GmTimeR(const time_t* timer, struct tm* tmbuf) { tmbuf->tm_min = (dayclock % 3600) / 60; tmbuf->tm_hour = dayclock / 3600; tmbuf->tm_wday = (dayno + 4) % 7; // Day 0 was a thursday - while (dayno >= (ui64)YEARSIZE(year)) { + while (dayno >= (ui64)YEARSIZE(year)) { dayno -= YEARSIZE(year); ++year; } tmbuf->tm_year = year - YEAR0; tmbuf->tm_yday = dayno; tmbuf->tm_mon = 0; - while (dayno >= (ui64)_ytab[LEAPYEAR(year)][tmbuf->tm_mon]) { + while (dayno >= (ui64)_ytab[LEAPYEAR(year)][tmbuf->tm_mon]) { dayno -= _ytab[LEAPYEAR(year)][tmbuf->tm_mon]; ++tmbuf->tm_mon; } @@ -126,7 +126,7 @@ struct tm* GmTimeR(const time_t* timer, struct tm* tmbuf) { tmbuf->tm_isdst = 0; #ifndef _win_ tmbuf->tm_gmtoff = 0; - tmbuf->tm_zone = (char*)"UTC"; + tmbuf->tm_zone = (char*)"UTC"; #endif return tmbuf; diff --git a/util/datetime/systime.h b/util/datetime/systime.h index 6e6ea58928..491d36e802 100644 --- a/util/datetime/systime.h +++ b/util/datetime/systime.h @@ -1,47 +1,47 @@ #pragma once -#include <util/system/platform.h> +#include <util/system/platform.h> #include <util/generic/string.h> - + #include <ctime> - + // timegm and gmtime_r versions that don't need access to filesystem or a big stack time_t TimeGM(const struct tm* t); -struct tm* GmTimeR(const time_t* timer, struct tm* tmbuf); +struct tm* GmTimeR(const time_t* timer, struct tm* tmbuf); // safe version of ctime, convinient version of ctime_r TString CTimeR(const time_t* timer); #ifdef _win_ - #include <util/system/winint.h> - #include <winsock2.h> + #include <util/system/winint.h> + #include <winsock2.h> -void FileTimeToTimeval(const FILETIME* ft, struct timeval* tv); +void FileTimeToTimeval(const FILETIME* ft, struct timeval* tv); -// obtains the current time, expressed as seconds and microseconds since 00:00 UTC, January 1, 1970 -int gettimeofday(struct timeval* tp, void*); +// obtains the current time, expressed as seconds and microseconds since 00:00 UTC, January 1, 1970 +int gettimeofday(struct timeval* tp, void*); -// thou should not mix these with non-_r functions -tm* localtime_r(const time_t* clock, tm* result); -tm* gmtime_r(const time_t* clock, tm* result); -char* ctime_r(const time_t* clock, char* buf); +// thou should not mix these with non-_r functions +tm* localtime_r(const time_t* clock, tm* result); +tm* gmtime_r(const time_t* clock, tm* result); +char* ctime_r(const time_t* clock, char* buf); -inline time_t timegm(struct tm* t) { - return TimeGM(t); -} +inline time_t timegm(struct tm* t) { + return TimeGM(t); +} -char* strptime(const char* buf, const char* fmt, struct tm* tm); // strptime.cpp +char* strptime(const char* buf, const char* fmt, struct tm* tm); // strptime.cpp #else - #include <sys/time.h> + #include <sys/time.h> #endif #ifndef timersub - #define timersub(tvp, uvp, vvp) \ - do { \ - (vvp)->tv_sec = (tvp)->tv_sec - (uvp)->tv_sec; \ - (vvp)->tv_usec = (tvp)->tv_usec - (uvp)->tv_usec; \ - if ((vvp)->tv_usec < 0) { \ - (vvp)->tv_sec--; \ - (vvp)->tv_usec += 1000000; \ - } \ - } while (0) + #define timersub(tvp, uvp, vvp) \ + do { \ + (vvp)->tv_sec = (tvp)->tv_sec - (uvp)->tv_sec; \ + (vvp)->tv_usec = (tvp)->tv_usec - (uvp)->tv_usec; \ + if ((vvp)->tv_usec < 0) { \ + (vvp)->tv_sec--; \ + (vvp)->tv_usec += 1000000; \ + } \ + } while (0) #endif diff --git a/util/datetime/uptime.cpp b/util/datetime/uptime.cpp index f87fd7af38..12476a94bf 100644 --- a/util/datetime/uptime.cpp +++ b/util/datetime/uptime.cpp @@ -1,12 +1,12 @@ #include "uptime.h" #if defined(_win_) - #include <util/system/winint.h> + #include <util/system/winint.h> #elif defined(_linux_) - #include <util/stream/file.h> - #include <util/string/cast.h> + #include <util/stream/file.h> + #include <util/string/cast.h> #elif defined(_darwin_) - #include <sys/sysctl.h> + #include <sys/sysctl.h> #endif #if defined(_darwin_) diff --git a/util/datetime/ut/ya.make b/util/datetime/ut/ya.make index f5a26938ba..c2bc714059 100644 --- a/util/datetime/ut/ya.make +++ b/util/datetime/ut/ya.make @@ -1,12 +1,12 @@ -UNITTEST_FOR(util) +UNITTEST_FOR(util) OWNER(g:util) SUBSCRIBER(g:util-subscribers) SRCS( - datetime/base_ut.cpp + datetime/base_ut.cpp datetime/parser_deprecated_ut.cpp - datetime/parser_ut.cpp + datetime/parser_ut.cpp datetime/uptime_ut.cpp ) |