1
0
mirror of https://github.com/borgesdan/xn65 synced 2024-12-29 21:54:47 +01:00

Implementa TimeSpan

This commit is contained in:
Danilo Borges Santos 2024-12-14 16:57:20 -03:00
parent a1e79518f4
commit 51e359f980
4 changed files with 363 additions and 1 deletions

View File

@ -318,6 +318,36 @@ namespace csharp {
HRresult = HResults::HR_COR_E_UNAUTHORIZEDACCESS;
}
};
//The exception that is thrown for errors in an arithmetic, casting, or conversion operation.
class ArithmeticException : public SystemException {
public:
ArithmeticException(OptionalString const& message = std::nullopt, std::source_location const& source = std::source_location::current())
: ArithmeticException(message, nullptr, source)
{
}
ArithmeticException(OptionalString const& message, std::shared_ptr<Exception> const& innerException, std::source_location const& source = std::source_location::current())
: SystemException(message.value_or(SR::Arg_ArithmeticException), innerException, source)
{
HRresult = HResults::HR_COR_E_ARITHMETIC;
}
};
//The exception that is thrown for errors in an arithmetic, casting, or conversion operation.
class OverflowException : public ArithmeticException {
public:
OverflowException(OptionalString const& message = std::nullopt, std::source_location const& source = std::source_location::current())
: OverflowException(message, nullptr, source)
{
}
OverflowException(OptionalString const& message, std::shared_ptr<Exception> const& innerException, std::source_location const& source = std::source_location::current())
: ArithmeticException(message.value_or(SR::Arg_OverflowException), innerException, source)
{
HRresult = HResults::HR_COR_E_OVERFLOW;
}
};
}
#endif

View File

@ -59,6 +59,18 @@ namespace csharp {
= "BinaryReader encountered an invalid string length.";
inline static const std::string Argument_StreamNotWritable
= "Stream was not writable.";
inline static const std::string Overflow_TimeSpanTooLong
= "TimeSpan overflowed because the duration is too long.";
inline static const std::string Arg_ArithmeticException
= "Overflow or underflow in the arithmetic operation.";
inline static const std::string Arg_OverflowException
= "Arithmetic operation resulted in an overflow.";
inline static const std::string Arg_CannotBeNaN
= "TimeSpan does not accept floating point Not-a-Number values.";
inline static const std::string Overflow_NegateTwosCompNum
= "Negating the minimum value of a twos complement number is invalid.";
inline static const std::string Overflow_Duration
= "The duration cannot be returned for TimeSpan.MinValue because the absolute value of TimeSpan.MinValue exceeds the value of TimeSpan.MaxValue.";
};
};

320
includes/csharp/time.hpp Normal file
View File

@ -0,0 +1,320 @@
#ifndef CSHARP_TIME_HPP
#define CSHARP_TIME_HPP
#include <cstdint>
#include <limits>
#include <cmath>
#include "exception.hpp"
#include "sr.hpp"
namespace csharp {
struct TimeSpan {
constexpr TimeSpan() = default;
constexpr TimeSpan(int64_t ticks) : _ticks(ticks) {}
constexpr TimeSpan(int32_t hours, int32_t minutes, int32_t seconds)
{
_ticks = TimeToTicks(hours, minutes, seconds);
}
constexpr TimeSpan(int32_t days, int32_t hours, int32_t minutes, int32_t seconds)
: TimeSpan(days, hours, minutes, seconds, 0)
{
}
constexpr TimeSpan(int32_t days, int32_t hours, int32_t minutes, int32_t seconds, int32_t milliseconds)
: TimeSpan(days, hours, minutes, seconds, milliseconds, 0)
{
}
constexpr TimeSpan(int32_t days, int32_t hours, int32_t minutes, int32_t seconds, int32_t milliseconds, int32_t microseconds)
{
const auto totalMicroseconds = (days * MicrosecondsPerDay)
+ (hours * MicrosecondsPerHour)
+ (minutes * MicrosecondsPerMinute)
+ (seconds * MicrosecondsPerSecond)
+ (milliseconds * MicrosecondsPerMillisecond)
+ microseconds;
if ((totalMicroseconds > MaxMicroseconds) || (totalMicroseconds < MinMicroseconds))
{
throw ArgumentOutOfRangeException(SR::Overflow_TimeSpanTooLong);
}
_ticks = totalMicroseconds * TicksPerMicrosecond;
}
static constexpr int64_t NanosecondsPerTick = 100;
static constexpr int64_t TicksPerMicrosecond = 10;
static constexpr int64_t TicksPerMillisecond = TicksPerMicrosecond * 1000;
static constexpr int64_t TicksPerSecond = TicksPerMillisecond * 1000;
static constexpr int64_t TicksPerMinute = TicksPerSecond * 60;
static constexpr int64_t TicksPerHour = TicksPerMinute * 60;
static constexpr int64_t TicksPerDay = TicksPerHour * 24;
static constexpr int64_t MicrosecondsPerMillisecond = TicksPerMillisecond / TicksPerMicrosecond;
static constexpr int64_t MicrosecondsPerSecond = TicksPerSecond / TicksPerMicrosecond;
static constexpr int64_t MicrosecondsPerMinute = TicksPerMinute / TicksPerMicrosecond;
static constexpr int64_t MicrosecondsPerHour = TicksPerHour / TicksPerMicrosecond;
static constexpr int64_t MicrosecondsPerDay = TicksPerDay / TicksPerMicrosecond;
static constexpr int64_t MillisecondsPerSecond = TicksPerSecond / TicksPerMillisecond;
static constexpr int64_t MillisecondsPerMinute = TicksPerMinute / TicksPerMillisecond;
static constexpr int64_t MillisecondsPerHour = TicksPerHour / TicksPerMillisecond;
static constexpr int64_t MillisecondsPerDay = TicksPerDay / TicksPerMillisecond;
static constexpr int64_t SecondsPerMinute = TicksPerMinute / TicksPerSecond;
static constexpr int64_t SecondsPerHour = TicksPerHour / TicksPerSecond;
static constexpr int64_t SecondsPerDay = TicksPerDay / TicksPerSecond;
static constexpr int64_t MinutesPerHour = TicksPerHour / TicksPerMinute;
static constexpr int64_t MinutesPerDay = TicksPerDay / TicksPerMinute;
static constexpr int32_t HoursPerDay = static_cast<int32_t>(TicksPerDay / TicksPerHour);
static constexpr int64_t MinTicks = (std::numeric_limits<int64_t>::min)();
static constexpr int64_t MaxTicks = (std::numeric_limits<int64_t>::max)();
static constexpr int64_t MinMicroseconds = MinTicks / TicksPerMicrosecond;
static constexpr int64_t MaxMicroseconds = MaxTicks / TicksPerMicrosecond;
static constexpr int64_t MinMilliseconds = MinTicks / TicksPerMillisecond;
static constexpr int64_t MaxMilliseconds = MaxTicks / TicksPerMillisecond;
static constexpr int64_t MinSeconds = MinTicks / TicksPerSecond;
static constexpr int64_t MaxSeconds = MaxTicks / TicksPerSecond;
static constexpr int64_t MinMinutes = MinTicks / TicksPerMinute;
static constexpr int64_t MaxMinutes = MaxTicks / TicksPerMinute;
static constexpr int64_t MinHours = MinTicks / TicksPerHour;
static constexpr int64_t MaxHours = MaxTicks / TicksPerHour;
static constexpr int64_t MinDays = MinTicks / TicksPerDay;
static constexpr int64_t MaxDays = MaxTicks / TicksPerDay;
static constexpr int64_t TicksPerTenthSecond = TicksPerMillisecond * 100;
static constexpr TimeSpan Zero() { return TimeSpan(0); }
static constexpr TimeSpan MaxValue() { return TimeSpan(MaxTicks); }
static constexpr TimeSpan MinValue() { return TimeSpan(MinTicks); }
constexpr int64_t Ticks() const { return _ticks; }
constexpr int32_t Days() const { return static_cast<int32_t>(_ticks / TicksPerDay); }
constexpr int32_t Hours() const { return static_cast<int32_t>(_ticks / TicksPerHour % HoursPerDay); }
constexpr int32_t Milliseconds() const { return static_cast<int32_t>(_ticks / TicksPerMillisecond % MillisecondsPerSecond); }
constexpr int32_t Microseconds() const { return static_cast<int32_t>(_ticks / TicksPerMicrosecond % MicrosecondsPerMillisecond); }
constexpr int32_t Nanoseconds() const { return static_cast<int32_t>(_ticks % TicksPerMicrosecond * NanosecondsPerTick); }
constexpr int32_t Minutes() const { return static_cast<int32_t>(_ticks / TicksPerMinute % MinutesPerHour); }
constexpr int32_t Seconds() const { return static_cast<int32_t>(_ticks / TicksPerSecond % SecondsPerMinute); }
constexpr double TotalDays() const { return static_cast<double>(_ticks) / TicksPerDay; }
constexpr double TotalHours() const { return static_cast<double>(_ticks) / TicksPerHour; }
constexpr double TotalMilliseconds() const
{
const double temp = static_cast<double>(_ticks) / TicksPerMillisecond;
if (temp > MaxMilliseconds)
{
return MaxMilliseconds;
}
if (temp < MinMilliseconds)
{
return MinMilliseconds;
}
return temp;
}
constexpr double TotalMicroseconds() const { return static_cast<double>(_ticks) / TicksPerMicrosecond; }
constexpr double TotalNanoseconds() const { return static_cast<double>(_ticks) * NanosecondsPerTick; }
constexpr double TotalMinutes() const { return static_cast<double>(_ticks) / TicksPerMinute; }
constexpr double TotalSeconds() const { return static_cast<double>(_ticks) / TicksPerSecond; }
constexpr TimeSpan Add(TimeSpan const& ts) const { return *this + ts; }
static constexpr TimeSpan FromDays(double value) {
return Interval(value, TicksPerDay);
}
constexpr TimeSpan Duration() const {
if (_ticks == MinTicks)
{
throw OverflowException(SR::Overflow_Duration);
}
return TimeSpan(_ticks >= 0 ? _ticks : -_ticks);
}
constexpr static int64_t TimeToTicks(int32_t hour, int32_t minute, int32_t second) {
const auto totalSeconds = (hour * SecondsPerHour)
+ (minute * SecondsPerMinute)
+ second;
if ((totalSeconds > MaxSeconds) || (totalSeconds < MinSeconds))
{
throw ArgumentOutOfRangeException(SR::Overflow_TimeSpanTooLong);
}
return totalSeconds * TicksPerSecond;
}
static constexpr TimeSpan FromDays(int32_t days) {
return FromUnits(days, TicksPerDay, MinDays, MaxDays);
}
static constexpr TimeSpan FromHours(int32_t hours) {
return FromUnits(hours, TicksPerHour, MinHours, MaxHours);
}
static constexpr TimeSpan FromMinutes(int32_t minutes) {
return FromUnits(minutes, TicksPerMinute, MinMinutes, MaxMinutes);
}
static constexpr TimeSpan FromSeconds(int32_t seconds) {
return FromUnits(seconds, TicksPerSecond, MinSeconds, MaxSeconds);
}
static constexpr TimeSpan FromMicroseconds(int32_t microseconds) {
return FromUnits(microseconds, TicksPerMicrosecond, MinMicroseconds, MaxMicroseconds);
}
static constexpr TimeSpan FromHours(double value) {
return Interval(value, TicksPerHour);
}
static constexpr TimeSpan FromMilliseconds(double value) {
return Interval(value, TicksPerMillisecond);
}
static constexpr TimeSpan FromMicroseconds(double value) {
return Interval(value, TicksPerMicrosecond);
}
static constexpr TimeSpan FromMinutes(double value) {
return Interval(value, TicksPerMinute);
}
constexpr TimeSpan Negate() const {
return -(*this);
}
static constexpr TimeSpan FromSeconds(double value) {
return Interval(value, TicksPerSecond);
}
constexpr TimeSpan Subtract(TimeSpan const& ts) const {
return *this - ts;
}
TimeSpan Multiply(double factor) const {
return *this * factor;
}
TimeSpan Divide(double divisor) const {
return *this / divisor;
}
double Divide(TimeSpan const& ts) const {
return *this / ts;
}
static constexpr TimeSpan FromTicks(int64_t value) {
return TimeSpan(value);
}
constexpr TimeSpan operator-() const {
if (_ticks == MinTicks)
{
throw OverflowException(SR::Overflow_NegateTwosCompNum);
}
return TimeSpan(_ticks);
}
friend constexpr TimeSpan operator-(TimeSpan const& t1, TimeSpan const t2) {
const auto result = t1._ticks - t2._ticks;
const auto t1Sign = t1._ticks >> 63;
if ((t1Sign != (t2._ticks >> 63)) && (t1Sign != (result >> 63)))
{
throw OverflowException(SR::Overflow_TimeSpanTooLong);
}
return TimeSpan(result);
}
constexpr TimeSpan operator+() const {
return *this;
}
friend constexpr TimeSpan operator+(TimeSpan const& t1, TimeSpan const t2) {
long result = t1._ticks + t2._ticks;
long t1Sign = t1._ticks >> 63;
if ((t1Sign == (t2._ticks >> 63)) && (t1Sign != (result >> 63)))
{
throw OverflowException(SR::Overflow_TimeSpanTooLong);
}
return TimeSpan(result);
}
friend TimeSpan operator*(TimeSpan const& timeSpan, double factor) {
const auto ticks = std::round(timeSpan.Ticks() * factor);
return IntervalFromDoubleTicks(ticks);
}
friend TimeSpan operator*(double factor, TimeSpan const& timeSpan) {
return timeSpan * factor;
}
friend TimeSpan operator/(TimeSpan const& timeSpan, double divisor) {
const auto ticks = std::round(timeSpan.Ticks() / divisor);
return IntervalFromDoubleTicks(ticks);
}
friend double operator/(TimeSpan const& t1, TimeSpan const t2) {
return t1.Ticks() / static_cast<double>(t2.Ticks());
}
constexpr bool operator==(TimeSpan const& other) const {
return _ticks == other._ticks;
}
constexpr bool operator<(TimeSpan const& other) const {
return _ticks < other._ticks;
}
constexpr bool operator<=(TimeSpan const& other) const {
return _ticks <= other._ticks;
}
constexpr bool operator>(TimeSpan const& other) const {
return _ticks > other._ticks;
}
constexpr bool operator>=(TimeSpan const& other) const {
return _ticks >= other._ticks;
}
private:
static constexpr TimeSpan FromUnits(int64_t units, int64_t ticksPerUnit, int64_t minUnits, int64_t maxUnits) {
if (units > maxUnits || units < minUnits)
{
throw ArgumentOutOfRangeException(SR::Overflow_TimeSpanTooLong);
}
return TimeSpan::FromTicks(units * ticksPerUnit);
}
static constexpr TimeSpan Interval(double value, double scale) {
return IntervalFromDoubleTicks(value * scale);
}
static constexpr TimeSpan IntervalFromDoubleTicks(double ticks) {
if ((ticks > MaxTicks) || (ticks < MinTicks))
{
throw OverflowException(SR::Overflow_TimeSpanTooLong);
}
if (ticks == MaxTicks)
{
return MaxValue();
}
return TimeSpan(static_cast<int64_t>(ticks));
}
private:
int64_t _ticks{ 0 };
};
}
#endif

View File

@ -5,7 +5,7 @@
# Add source to this project's executable.
add_library (CSharp++ STATIC
"exception.cpp"
"io/stream.cpp" "io/binary.cpp")
"io/stream.cpp" "io/binary.cpp" )
if (CMAKE_VERSION VERSION_GREATER 3.12)
set_property(TARGET CSharp++ PROPERTY CXX_STANDARD 20)