Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions lib/include/pl/pattern_language.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@

#include <wolv/io/fs.hpp>
#include <wolv/container/interval_tree.hpp>
#include <wolv/utils/date_time_format.hpp>

namespace pl {

Expand Down Expand Up @@ -134,6 +135,16 @@ namespace pl {
*/
void abort();

/**
* @brief Get locale (currently only used for date/time formatting)
*/
const wolv::util::Locale& getLocale() const;

/**
* @brief Set locale (currently only used for date/time formatting)
*/
void setLocale(const wolv::util::Locale &lc);

/**
* @brief Sets the data source for the pattern language
* @param baseAddress Base address of the data source
Expand Down Expand Up @@ -416,6 +427,7 @@ namespace pl {

private:
Internals m_internals;
wolv::util::Locale m_locale;
std::vector<core::err::CompileError> m_compileErrors;
std::optional<core::err::PatternLanguageError> m_currError;
std::map<std::string, std::string> m_defines;
Expand Down
112 changes: 98 additions & 14 deletions lib/source/pl/lib/std/time.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,17 @@
#include <pl/core/log_console.hpp>
#include <pl/core/evaluator.hpp>
#include <pl/patterns/pattern.hpp>
#include <wolv/utils/date_time_format.hpp>

#include <ctime>
#include <fmt/format.h>
#include <fmt/chrono.h>

namespace pl::lib::libstd::time {

const std::string s_invalid = "Invalid";
const std::string s_canNotFormat = "Can not format";

static u128 packTMValue(const std::tm &tm, pl::PatternLanguage &runtime) {
auto endian = runtime.getInternals().evaluator->getDefaultEndian();
std::tm tmCopy = tm;
Expand Down Expand Up @@ -65,29 +69,21 @@ namespace pl::lib::libstd::time {
/* to_local(time) */
runtime.addFunction(nsStdTime, "to_local", FunctionParameterCount::exactly(1), [&runtime](Evaluator *, auto params) -> std::optional<Token::Literal> {
auto time = time_t(params[0].toUnsigned());
auto localTime = std::localtime(&time);

try {
auto localTime = std::localtime(&time);
if (localTime == nullptr) return u128(0);
if (localTime == nullptr) return u128(0);

return { packTMValue(*localTime, runtime) };
} catch (const fmt::format_error&) {
return u128(0);
}
return { packTMValue(*localTime, runtime) };
});

/* to_utc(time) */
runtime.addFunction(nsStdTime, "to_utc", FunctionParameterCount::exactly(1), [&runtime](Evaluator *, auto params) -> std::optional<Token::Literal> {
auto time = time_t(params[0].toUnsigned());
auto gmTime = std::gmtime(&time);

try {
auto gmTime = std::gmtime(&time);
if (gmTime == nullptr) return u128(0);
if (gmTime == nullptr) return u128(0);

return { packTMValue(*gmTime, runtime) };
} catch (const fmt::format_error&) {
return u128(0);
}
return { packTMValue(*gmTime, runtime) };
});

/* to_epoch(structured_time) */
Expand Down Expand Up @@ -117,6 +113,94 @@ namespace pl::lib::libstd::time {

return { fmt::format(fmt::runtime(fmt::format("{{:{}}}", formatString)), time) };
});

/* format_tt(time_t) */
runtime.addFunction(nsStdTime, "format_tt", FunctionParameterCount::exactly(1), [&runtime](Evaluator *, auto params) -> std::optional<Token::Literal> {
auto tt = params[0].toUnsigned();
const wolv::util::Locale &lc = runtime.getLocale();

using wolv::util::DTOpts;
auto optval = wolv::util::formatTT(lc, tt, DTOpts::TT64 | DTOpts::DandT);
if (!optval) {
return s_canNotFormat;
}

return optval;
});

/* format_dos_date(time_t) */
runtime.addFunction(nsStdTime, "format_dos_date", FunctionParameterCount::exactly(1), [&runtime](Evaluator *, auto params) -> std::optional<Token::Literal> {
auto p = params[0].toUnsigned();

struct DOSDate {
u16 day : 5;
u16 month : 4;
u16 year : 7;
};

DOSDate dd;
std::memcpy(&dd, &p, sizeof(dd));
if ( (dd.day<1 || dd.day>31) || (dd.month<1 || dd.month>12) ) {
return s_invalid;
}

std::tm tm{};
tm.tm_year = dd.year + 80;
tm.tm_mon = dd.month - 1;
tm.tm_mday = dd.day;

#if defined(OS_WINDOWS)
time_t tt = _mkgmtime(&tm);
#else
time_t tt = timegm(&tm);
#endif
if (tt == -1) {
return s_canNotFormat;
}

const wolv::util::Locale &lc = runtime.getLocale();

using wolv::util::DTOpts;
auto optval = wolv::util::formatTT(lc, tt, DTOpts::TT64 | DTOpts::D);
if (!optval) {
return s_canNotFormat;
}

return *optval;
});

/* format_dos_time(time_t) */
runtime.addFunction(nsStdTime, "format_dos_time", FunctionParameterCount::exactly(1), [&runtime](Evaluator *, auto params) -> std::optional<Token::Literal> {
auto p = params[0].toUnsigned();

struct DOSTime {
u16 seconds : 5;
u16 minutes : 6;
u16 hours : 5;
};

DOSTime dt;
std::memcpy(&dt, &p, sizeof(dt));

if ( (dt.hours<0 || dt.hours>23) ||
(dt.minutes<0 || dt.minutes>59) ||
(dt.seconds<0 || dt.seconds>29) )
{
return s_invalid;
}

time_t tt = dt.hours*60*60 + dt.minutes*60 + dt.seconds*2;

const wolv::util::Locale &lc = runtime.getLocale();

using wolv::util::DTOpts;
auto optval = wolv::util::formatTT(lc, tt, DTOpts::TT64 | DTOpts::T);
if (!optval) {
return s_canNotFormat;
}

return *optval;
});
}
}

Expand Down
8 changes: 8 additions & 0 deletions lib/source/pl/pattern_language.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -380,6 +380,14 @@ namespace pl {
this->m_aborted = true;
}

const wolv::util::Locale& PatternLanguage::getLocale() const {
return m_locale;
}

void PatternLanguage::setLocale(const wolv::util::Locale &lc) {
m_locale = lc;
}

void PatternLanguage::setIncludePaths(const std::vector<std::fs::path>& paths) {
this->m_fileResolver.setIncludePaths(paths);
}
Expand Down
Loading