-
-
Notifications
You must be signed in to change notification settings - Fork 67
Expand file tree
/
Copy pathtime.cpp
More file actions
121 lines (97 loc) · 4.79 KB
/
time.cpp
File metadata and controls
121 lines (97 loc) · 4.79 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
#include <pl.hpp>
#include <pl/core/token.hpp>
#include <pl/core/log_console.hpp>
#include <pl/core/evaluator.hpp>
#include <pl/patterns/pattern.hpp>
#include <ctime>
#include <fmt/format.h>
#include <fmt/chrono.h>
namespace pl::lib::libstd::time {
static u128 packTMValue(const std::tm &tm, std::endian endian = std::endian::native) {
std::tm tmCopy = tm;
tmCopy.tm_year = hlp::changeEndianess(tm.tm_year, 2, endian);
tmCopy.tm_yday = hlp::changeEndianess(tm.tm_yday, 2, endian);
u128 result =
(u128(tm.tm_sec) << 0) |
(u128(tm.tm_min) << 8) |
(u128(tm.tm_hour) << 16) |
(u128(tm.tm_mday) << 24) |
(u128(tm.tm_mon) << 32) |
(u128(tmCopy.tm_year) << 40) |
(u128(tm.tm_wday) << 56) |
(u128(tmCopy.tm_yday) << 64) |
(u128(tm.tm_isdst) << 80);
return hlp::changeEndianess(result, 16, endian);
}
static tm unpackTMValue(u128 value, std::endian endian = std::endian::native) {
value = hlp::changeEndianess(value, 16, endian);
tm tm = { };
tm.tm_sec = (int)(value >> 0) & 0xFF;
tm.tm_min = (int)(value >> 8) & 0xFF;
tm.tm_hour = (int)(value >> 16) & 0xFF;
tm.tm_mday = (int)(value >> 24) & 0xFF;
tm.tm_mon = (int)(value >> 32) & 0xFF;
tm.tm_year = (int)(value >> 40) & 0xFFFF;
tm.tm_year = hlp::changeEndianess(tm.tm_year, 2, endian);
tm.tm_wday = (int)(value >> 56) & 0xFF;
tm.tm_yday = (int)(value >> 64) & 0xFFFF;
tm.tm_yday = hlp::changeEndianess(tm.tm_yday, 2, endian);
tm.tm_isdst = (int)(value >> 80) & 0xFF;
return tm;
}
void registerFunctions(pl::PatternLanguage &runtime) {
using FunctionParameterCount = pl::api::FunctionParameterCount;
using namespace pl::core;
api::Namespace nsStdTime = { "builtin", "std", "time" };
{
/* epoch() */
runtime.addFunction(nsStdTime, "epoch", FunctionParameterCount::exactly(0), [](Evaluator *, auto params) -> std::optional<Token::Literal> {
wolv::util::unused(params);
return { u128(std::time(nullptr)) };
});
/* to_local(time) */
runtime.addFunction(nsStdTime, "to_local", FunctionParameterCount::exactly(1), [](Evaluator *ctx, auto params) -> std::optional<Token::Literal> {
auto time = time_t(params[0].toUnsigned());
try {
auto localTime = std::localtime(&time);
if (localTime == nullptr) return u128(0);
return { packTMValue(*localTime, ctx->getDefaultEndian()) };
} catch (const fmt::format_error&) {
return u128(0);
}
});
/* to_utc(time) */
runtime.addFunction(nsStdTime, "to_utc", FunctionParameterCount::exactly(1), [](Evaluator *ctx, auto params) -> std::optional<Token::Literal> {
auto time = time_t(params[0].toUnsigned());
try {
auto gmTime = std::gmtime(&time);
if (gmTime == nullptr) return u128(0);
return { packTMValue(*gmTime, ctx->getDefaultEndian()) };
} catch (const fmt::format_error&) {
return u128(0);
}
});
/* to_epoch(structured_time) */
runtime.addFunction(nsStdTime, "to_epoch", FunctionParameterCount::exactly(1), [](Evaluator *ctx, auto params) -> std::optional<Token::Literal> {
u128 structuredTime = params[0].toUnsigned();
tm time = unpackTMValue(structuredTime, ctx->getDefaultEndian());
return { u128(std::mktime(&time)) };
});
/* format(format_string, structured_time) */
runtime.addFunction(nsStdTime, "format", FunctionParameterCount::exactly(2), [](Evaluator *ctx, auto params) -> std::optional<Token::Literal> {
auto formatString = params[0].toString(false);
u128 structuredTime = params[1].toUnsigned();
auto time = unpackTMValue(structuredTime, ctx->getDefaultEndian());
if (time.tm_sec < 0 || time.tm_sec > 61 ||
time.tm_min < 0 || time.tm_min > 59 ||
time.tm_hour < 0 || time.tm_hour > 23 ||
time.tm_mday < 1 || time.tm_mday > 31 ||
time.tm_mon < 0 || time.tm_mon > 11 ||
time.tm_wday < 0 || time.tm_wday > 6 ||
time.tm_yday < 0 || time.tm_yday > 365)
return std::string("Invalid");
return { fmt::format(fmt::runtime(fmt::format("{{:{}}}", formatString)), time) };
});
}
}
}