Move date to tessesframework
This commit is contained in:
@ -124,7 +124,7 @@ src/runtime_methods/ogc.cpp
|
||||
src/runtime_methods/path.cpp
|
||||
src/runtime_methods/env.cpp
|
||||
src/runtime_methods/process.cpp
|
||||
src/runtime_methods/time.cpp
|
||||
src/types/datetime.cpp
|
||||
src/types/ittr.cpp
|
||||
src/types/closure.cpp
|
||||
src/types/dictionary.cpp
|
||||
|
||||
@ -1348,11 +1348,21 @@ class Parser {
|
||||
class MethodInvoker {
|
||||
|
||||
};
|
||||
|
||||
class TDateTime {
|
||||
Tesses::Framework::Date::DateTime* dt;
|
||||
public:
|
||||
TDateTime();
|
||||
TDateTime(Tesses::Framework::Date::DateTime t);
|
||||
TDateTime(const TDateTime& dt);
|
||||
Tesses::Framework::Date::DateTime& GetDate();
|
||||
~TDateTime();
|
||||
};
|
||||
/**
|
||||
* @brief A script object
|
||||
*
|
||||
*/
|
||||
using TObject = std::variant<int64_t,double,char,bool,std::string,std::regex,Tesses::Framework::Filesystem::VFSPath,std::nullptr_t,Undefined,MethodInvoker,THeapObjectHolder,TVMVersion>;
|
||||
using TObject = std::variant<int64_t,double,char,bool,std::string,std::regex,Tesses::Framework::Filesystem::VFSPath,std::nullptr_t,Undefined,MethodInvoker,THeapObjectHolder,TVMVersion,TDateTime>;
|
||||
class TRootEnvironment;
|
||||
class GC;
|
||||
class GC {
|
||||
@ -1500,7 +1510,6 @@ class GC {
|
||||
|
||||
};
|
||||
using TDItem = std::pair<std::string, TObject>;
|
||||
|
||||
class TDictionary : public THeapObject
|
||||
{
|
||||
public:
|
||||
@ -1609,7 +1618,6 @@ class GC {
|
||||
bool canRegisterPath;
|
||||
bool canRegisterOGC;
|
||||
bool canRegisterEnv;
|
||||
bool canRegisterTime;
|
||||
bool sqlite3Scoped;
|
||||
bool locked;
|
||||
};
|
||||
@ -1660,7 +1668,6 @@ class GC {
|
||||
static void RegisterOGC(GC* gc, TRootEnvironment* env);
|
||||
static void RegisterEnv(GC* gc, TRootEnvironment* env);
|
||||
static void RegisterProcess(GC* gc, TRootEnvironment* env);
|
||||
static void RegisterTime(GC* gc, TRootEnvironment* env);
|
||||
|
||||
};
|
||||
|
||||
@ -1863,8 +1870,8 @@ class GC {
|
||||
Tesses::Framework::Filesystem::VFSPath ReadLink(Tesses::Framework::Filesystem::VFSPath path);
|
||||
std::string VFSPathToSystem(Tesses::Framework::Filesystem::VFSPath path);
|
||||
Tesses::Framework::Filesystem::VFSPath SystemToVFSPath(std::string path);
|
||||
void GetDate(Tesses::Framework::Filesystem::VFSPath path, time_t& lastWrite, time_t& lastAccess);
|
||||
void SetDate(Tesses::Framework::Filesystem::VFSPath path, time_t lastWrite, time_t lastAccess);
|
||||
void GetDate(Tesses::Framework::Filesystem::VFSPath path, Tesses::Framework::Date::DateTime& lastWrite, Tesses::Framework::Date::DateTime& lastAccess);
|
||||
void SetDate(Tesses::Framework::Filesystem::VFSPath path, Tesses::Framework::Date::DateTime lastWrite, Tesses::Framework::Date::DateTime lastAccess);
|
||||
~TObjectVFS();
|
||||
};
|
||||
|
||||
|
||||
@ -1,34 +0,0 @@
|
||||
#ifndef CHRONO_IO_H
|
||||
#define CHRONO_IO_H
|
||||
|
||||
// The MIT License (MIT)
|
||||
//
|
||||
// Copyright (c) 2016, 2017 Howard Hinnant
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
//
|
||||
// Our apologies. When the previous paragraph was written, lowercase had not yet
|
||||
// been invented (that would involve another several millennia of evolution).
|
||||
// We did not mean to shout.
|
||||
|
||||
// This functionality has moved to "date.h"
|
||||
|
||||
#include "date.h"
|
||||
|
||||
#endif // CHRONO_IO_H
|
||||
File diff suppressed because it is too large
Load Diff
@ -1,50 +0,0 @@
|
||||
//
|
||||
// ios.h
|
||||
// DateTimeLib
|
||||
//
|
||||
// The MIT License (MIT)
|
||||
//
|
||||
// Copyright (c) 2016 Alexander Kormanovsky
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
|
||||
#ifndef ios_hpp
|
||||
#define ios_hpp
|
||||
|
||||
#if __APPLE__
|
||||
# include <TargetConditionals.h>
|
||||
# if TARGET_OS_IPHONE
|
||||
# include <string>
|
||||
|
||||
namespace date
|
||||
{
|
||||
namespace iOSUtils
|
||||
{
|
||||
|
||||
std::string get_tzdata_path();
|
||||
std::string get_current_timezone();
|
||||
|
||||
} // namespace iOSUtils
|
||||
} // namespace date
|
||||
|
||||
# endif // TARGET_OS_IPHONE
|
||||
#else // !__APPLE__
|
||||
# define TARGET_OS_IPHONE 0
|
||||
#endif // !__APPLE__
|
||||
#endif // ios_hpp
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -1,952 +0,0 @@
|
||||
#ifndef PTZ_H
|
||||
#define PTZ_H
|
||||
|
||||
// The MIT License (MIT)
|
||||
//
|
||||
// Copyright (c) 2017 Howard Hinnant
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
|
||||
// This header allows Posix-style time zones as specified for TZ here:
|
||||
// http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap08.html#tag_08_03
|
||||
//
|
||||
// Posix::time_zone can be constructed with a posix-style string and then used in
|
||||
// a zoned_time like so:
|
||||
//
|
||||
// zoned_time<system_clock::duration, Posix::time_zone> zt{"EST5EDT,M3.2.0,M11.1.0",
|
||||
// system_clock::now()};
|
||||
// or:
|
||||
//
|
||||
// Posix::time_zone tz{"EST5EDT,M3.2.0,M11.1.0"};
|
||||
// zoned_time<system_clock::duration, Posix::time_zone> zt{tz, system_clock::now()};
|
||||
//
|
||||
// In C++17 CTAD simplifies this to:
|
||||
//
|
||||
// Posix::time_zone tz{"EST5EDT,M3.2.0,M11.1.0"};
|
||||
// zoned_time zt{tz, system_clock::now()};
|
||||
//
|
||||
// Extension to the Posix rules to allow a constant daylight saving offset:
|
||||
//
|
||||
// If the rule set is missing (everything starting with ','), then
|
||||
// there must be exactly one abbreviation (std or daylight) with
|
||||
// length 3 or greater, and that will be used as the constant offset. If
|
||||
// there are two, the std abbreviation is silently set to "", and the
|
||||
// result is constant daylight saving. If there are zero abbreviations
|
||||
// with no rule set, an exception is thrown.
|
||||
//
|
||||
// Example:
|
||||
// "EST5" yields a constant offset of -5h with 0h save and "EST abbreviation.
|
||||
// "5EDT" yields a constant offset of -4h with 1h save and "EDT" abbreviation.
|
||||
// "EST5EDT" and "5EDT4" are both equal to "5EDT".
|
||||
//
|
||||
// Note, Posix-style time zones are not recommended for all of the reasons described here:
|
||||
// https://stackoverflow.com/tags/timezone/info
|
||||
//
|
||||
// They are provided here as a non-trivial custom time zone example, and if you really
|
||||
// have to have Posix time zones, you're welcome to use this one.
|
||||
|
||||
#include "date/tz.h"
|
||||
#include <algorithm>
|
||||
#include <cctype>
|
||||
#include <ostream>
|
||||
#include <string>
|
||||
|
||||
namespace Posix
|
||||
{
|
||||
|
||||
namespace detail
|
||||
{
|
||||
|
||||
#if HAS_STRING_VIEW
|
||||
|
||||
using string_t = std::string_view;
|
||||
|
||||
#else // !HAS_STRING_VIEW
|
||||
|
||||
using string_t = std::string;
|
||||
|
||||
#endif // !HAS_STRING_VIEW
|
||||
|
||||
class rule;
|
||||
|
||||
void throw_invalid(const string_t& s, unsigned i, const string_t& message);
|
||||
unsigned read_date(const string_t& s, unsigned i, rule& r);
|
||||
unsigned read_name(const string_t& s, unsigned i, std::string& name);
|
||||
unsigned read_signed_time(const string_t& s, unsigned i, std::chrono::seconds& t);
|
||||
unsigned read_unsigned_time(const string_t& s, unsigned i, std::chrono::seconds& t);
|
||||
unsigned read_unsigned(const string_t& s, unsigned i, unsigned limit, unsigned& u,
|
||||
const string_t& message = string_t{});
|
||||
|
||||
class rule
|
||||
{
|
||||
enum {off, J, M, N};
|
||||
|
||||
date::month m_;
|
||||
date::weekday wd_;
|
||||
unsigned short n_ : 14;
|
||||
unsigned short mode_ : 2;
|
||||
std::chrono::duration<std::int32_t> time_ = std::chrono::hours{2};
|
||||
|
||||
public:
|
||||
rule() : mode_(off) {}
|
||||
|
||||
bool ok() const {return mode_ != off;}
|
||||
date::local_seconds operator()(date::year y) const;
|
||||
std::string to_string() const;
|
||||
|
||||
friend std::ostream& operator<<(std::ostream& os, const rule& r);
|
||||
friend unsigned read_date(const string_t& s, unsigned i, rule& r);
|
||||
friend bool operator==(const rule& x, const rule& y);
|
||||
};
|
||||
|
||||
inline
|
||||
bool
|
||||
operator==(const rule& x, const rule& y)
|
||||
{
|
||||
if (x.mode_ != y.mode_)
|
||||
return false;
|
||||
switch (x.mode_)
|
||||
{
|
||||
case rule::J:
|
||||
case rule::N:
|
||||
return x.n_ == y.n_;
|
||||
case rule::M:
|
||||
return x.m_ == y.m_ && x.n_ == y.n_ && x.wd_ == y.wd_;
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
inline
|
||||
bool
|
||||
operator!=(const rule& x, const rule& y)
|
||||
{
|
||||
return !(x == y);
|
||||
}
|
||||
|
||||
inline
|
||||
date::local_seconds
|
||||
rule::operator()(date::year y) const
|
||||
{
|
||||
using date::local_days;
|
||||
using date::January;
|
||||
using date::days;
|
||||
using date::last;
|
||||
using sec = std::chrono::seconds;
|
||||
date::local_seconds t;
|
||||
switch (mode_)
|
||||
{
|
||||
case J:
|
||||
t = local_days{y/January/0} + days{n_ + (y.is_leap() && n_ > 59)} + sec{time_};
|
||||
break;
|
||||
case M:
|
||||
t = (n_ == 5 ? local_days{y/m_/wd_[last]} : local_days{y/m_/wd_[n_]}) + sec{time_};
|
||||
break;
|
||||
case N:
|
||||
t = local_days{y/January/1} + days{n_} + sec{time_};
|
||||
break;
|
||||
default:
|
||||
assert(!"rule called with bad mode");
|
||||
}
|
||||
return t;
|
||||
}
|
||||
|
||||
inline
|
||||
std::string
|
||||
rule::to_string() const
|
||||
{
|
||||
using namespace std::chrono;
|
||||
auto print_offset = [](seconds off)
|
||||
{
|
||||
std::string nm;
|
||||
if (off != hours{2})
|
||||
{
|
||||
date::hh_mm_ss<seconds> offset{off};
|
||||
nm = '/';
|
||||
nm += std::to_string(offset.hours().count());
|
||||
if (offset.minutes() != minutes{0} || offset.seconds() != seconds{0})
|
||||
{
|
||||
nm += ':';
|
||||
if (offset.minutes() < minutes{10})
|
||||
nm += '0';
|
||||
nm += std::to_string(offset.minutes().count());
|
||||
if (offset.seconds() != seconds{0})
|
||||
{
|
||||
nm += ':';
|
||||
if (offset.seconds() < seconds{10})
|
||||
nm += '0';
|
||||
nm += std::to_string(offset.seconds().count());
|
||||
}
|
||||
}
|
||||
}
|
||||
return nm;
|
||||
};
|
||||
|
||||
std::string nm;
|
||||
switch (mode_)
|
||||
{
|
||||
case rule::J:
|
||||
nm = 'J';
|
||||
nm += std::to_string(n_);
|
||||
break;
|
||||
case rule::M:
|
||||
nm = 'M';
|
||||
nm += std::to_string(static_cast<unsigned>(m_));
|
||||
nm += '.';
|
||||
nm += std::to_string(n_);
|
||||
nm += '.';
|
||||
nm += std::to_string(wd_.c_encoding());
|
||||
break;
|
||||
case rule::N:
|
||||
nm = std::to_string(n_);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
nm += print_offset(time_);
|
||||
return nm;
|
||||
}
|
||||
|
||||
inline
|
||||
std::ostream&
|
||||
operator<<(std::ostream& os, const rule& r)
|
||||
{
|
||||
switch (r.mode_)
|
||||
{
|
||||
case rule::J:
|
||||
os << 'J' << r.n_ << date::format(" %T", r.time_);
|
||||
break;
|
||||
case rule::M:
|
||||
if (r.n_ == 5)
|
||||
os << r.m_/r.wd_[date::last];
|
||||
else
|
||||
os << r.m_/r.wd_[r.n_];
|
||||
os << date::format(" %T", r.time_);
|
||||
break;
|
||||
case rule::N:
|
||||
os << r.n_ << date::format(" %T", r.time_);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return os;
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
|
||||
class time_zone
|
||||
{
|
||||
std::string std_abbrev_;
|
||||
std::string dst_abbrev_ = {};
|
||||
std::chrono::seconds offset_;
|
||||
std::chrono::seconds save_ = std::chrono::hours{1};
|
||||
detail::rule start_rule_;
|
||||
detail::rule end_rule_;
|
||||
|
||||
public:
|
||||
explicit time_zone(const detail::string_t& name);
|
||||
|
||||
template <class Duration>
|
||||
date::sys_info get_info(date::sys_time<Duration> st) const;
|
||||
template <class Duration>
|
||||
date::local_info get_info(date::local_time<Duration> tp) const;
|
||||
|
||||
template <class Duration>
|
||||
date::sys_time<typename std::common_type<Duration, std::chrono::seconds>::type>
|
||||
to_sys(date::local_time<Duration> tp) const;
|
||||
|
||||
template <class Duration>
|
||||
date::sys_time<typename std::common_type<Duration, std::chrono::seconds>::type>
|
||||
to_sys(date::local_time<Duration> tp, date::choose z) const;
|
||||
|
||||
template <class Duration>
|
||||
date::local_time<typename std::common_type<Duration, std::chrono::seconds>::type>
|
||||
to_local(date::sys_time<Duration> tp) const;
|
||||
|
||||
friend std::ostream& operator<<(std::ostream& os, const time_zone& z);
|
||||
|
||||
const time_zone* operator->() const {return this;}
|
||||
|
||||
std::string name() const;
|
||||
|
||||
friend bool operator==(const time_zone& x, const time_zone& y);
|
||||
|
||||
private:
|
||||
date::sys_seconds get_start(date::year y) const;
|
||||
date::sys_seconds get_prev_start(date::year y) const;
|
||||
date::sys_seconds get_next_start(date::year y) const;
|
||||
date::sys_seconds get_end(date::year y) const;
|
||||
date::sys_seconds get_prev_end(date::year y) const;
|
||||
date::sys_seconds get_next_end(date::year y) const;
|
||||
date::sys_info contant_offset() const;
|
||||
};
|
||||
|
||||
inline
|
||||
date::sys_seconds
|
||||
time_zone::get_start(date::year y) const
|
||||
{
|
||||
return date::sys_seconds{(start_rule_(y) - offset_).time_since_epoch()};
|
||||
}
|
||||
|
||||
inline
|
||||
date::sys_seconds
|
||||
time_zone::get_prev_start(date::year y) const
|
||||
{
|
||||
return date::sys_seconds{(start_rule_(--y) - offset_).time_since_epoch()};
|
||||
}
|
||||
|
||||
inline
|
||||
date::sys_seconds
|
||||
time_zone::get_next_start(date::year y) const
|
||||
{
|
||||
return date::sys_seconds{(start_rule_(++y) - offset_).time_since_epoch()};
|
||||
}
|
||||
|
||||
inline
|
||||
date::sys_seconds
|
||||
time_zone::get_end(date::year y) const
|
||||
{
|
||||
return date::sys_seconds{(end_rule_(y) - (offset_ + save_)).time_since_epoch()};
|
||||
}
|
||||
|
||||
inline
|
||||
date::sys_seconds
|
||||
time_zone::get_prev_end(date::year y) const
|
||||
{
|
||||
return date::sys_seconds{(end_rule_(--y) - (offset_ + save_)).time_since_epoch()};
|
||||
}
|
||||
|
||||
inline
|
||||
date::sys_seconds
|
||||
time_zone::get_next_end(date::year y) const
|
||||
{
|
||||
return date::sys_seconds{(end_rule_(++y) - (offset_ + save_)).time_since_epoch()};
|
||||
}
|
||||
|
||||
inline
|
||||
date::sys_info
|
||||
time_zone::contant_offset() const
|
||||
{
|
||||
using date::year;
|
||||
using date::sys_info;
|
||||
using date::sys_days;
|
||||
using date::January;
|
||||
using date::December;
|
||||
using date::last;
|
||||
using date::days;
|
||||
using std::chrono::minutes;
|
||||
sys_info r;
|
||||
r.begin = sys_days{year::min()/January/1};
|
||||
r.end = sys_days{year::max()/December/last} + days{1} - std::chrono::seconds{1};
|
||||
if (std_abbrev_.size() > 0)
|
||||
{
|
||||
r.abbrev = std_abbrev_;
|
||||
r.offset = offset_;
|
||||
r.save = {};
|
||||
}
|
||||
else
|
||||
{
|
||||
r.abbrev = dst_abbrev_;
|
||||
r.offset = offset_ + save_;
|
||||
r.save = date::ceil<minutes>(save_);
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
inline
|
||||
time_zone::time_zone(const detail::string_t& s)
|
||||
{
|
||||
using detail::read_name;
|
||||
using detail::read_signed_time;
|
||||
using detail::throw_invalid;
|
||||
auto i = read_name(s, 0, std_abbrev_);
|
||||
auto std_name_i = i;
|
||||
auto abbrev_name_i = i;
|
||||
i = read_signed_time(s, i, offset_);
|
||||
offset_ = -offset_;
|
||||
if (i != s.size())
|
||||
{
|
||||
i = read_name(s, i, dst_abbrev_);
|
||||
abbrev_name_i = i;
|
||||
if (i != s.size())
|
||||
{
|
||||
if (s[i] != ',')
|
||||
{
|
||||
i = read_signed_time(s, i, save_);
|
||||
save_ = -save_ - offset_;
|
||||
}
|
||||
if (i != s.size())
|
||||
{
|
||||
if (s[i] != ',')
|
||||
throw_invalid(s, i, "Expecting end of string or ',' to start rule");
|
||||
++i;
|
||||
i = read_date(s, i, start_rule_);
|
||||
if (i == s.size() || s[i] != ',')
|
||||
throw_invalid(s, i, "Expecting ',' and then the ending rule");
|
||||
++i;
|
||||
i = read_date(s, i, end_rule_);
|
||||
if (i != s.size())
|
||||
throw_invalid(s, i, "Found unexpected trailing characters");
|
||||
}
|
||||
}
|
||||
}
|
||||
if (start_rule_.ok())
|
||||
{
|
||||
if (std_abbrev_.size() < 3)
|
||||
throw_invalid(s, std_name_i, "Zone with rules must have a std"
|
||||
" abbreviation of length 3 or greater");
|
||||
if (dst_abbrev_.size() < 3)
|
||||
throw_invalid(s, abbrev_name_i, "Zone with rules must have a daylight"
|
||||
" abbreviation of length 3 or greater");
|
||||
}
|
||||
else
|
||||
{
|
||||
if (dst_abbrev_.size() >= 3)
|
||||
{
|
||||
std_abbrev_.clear();
|
||||
}
|
||||
else if (std_abbrev_.size() < 3)
|
||||
{
|
||||
throw_invalid(s, std_name_i, "Zone must have at least one abbreviation"
|
||||
" of length 3 or greater");
|
||||
}
|
||||
else
|
||||
{
|
||||
dst_abbrev_.clear();
|
||||
save_ = {};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <class Duration>
|
||||
date::sys_info
|
||||
time_zone::get_info(date::sys_time<Duration> st) const
|
||||
{
|
||||
using date::sys_info;
|
||||
using date::year_month_day;
|
||||
using date::sys_days;
|
||||
using date::floor;
|
||||
using date::ceil;
|
||||
using date::days;
|
||||
using date::year;
|
||||
using date::January;
|
||||
using date::December;
|
||||
using date::last;
|
||||
using std::chrono::minutes;
|
||||
sys_info r{};
|
||||
r.offset = offset_;
|
||||
if (start_rule_.ok())
|
||||
{
|
||||
auto y = year_month_day{floor<days>(st)}.year();
|
||||
if (st >= get_next_start(y))
|
||||
++y;
|
||||
else if (st < get_prev_end(y))
|
||||
--y;
|
||||
auto start = get_start(y);
|
||||
auto end = get_end(y);
|
||||
if (start <= end) // (northern hemisphere)
|
||||
{
|
||||
if (start <= st && st < end)
|
||||
{
|
||||
r.begin = start;
|
||||
r.end = end;
|
||||
r.offset += save_;
|
||||
r.save = ceil<minutes>(save_);
|
||||
r.abbrev = dst_abbrev_;
|
||||
}
|
||||
else if (st < start)
|
||||
{
|
||||
r.begin = get_prev_end(y);
|
||||
r.end = start;
|
||||
r.abbrev = std_abbrev_;
|
||||
}
|
||||
else // st >= end
|
||||
{
|
||||
r.begin = end;
|
||||
r.end = get_next_start(y);
|
||||
r.abbrev = std_abbrev_;
|
||||
}
|
||||
}
|
||||
else // end < start (southern hemisphere)
|
||||
{
|
||||
if (end <= st && st < start)
|
||||
{
|
||||
r.begin = end;
|
||||
r.end = start;
|
||||
r.abbrev = std_abbrev_;
|
||||
}
|
||||
else if (st < end)
|
||||
{
|
||||
r.begin = get_prev_start(y);
|
||||
r.end = end;
|
||||
r.offset += save_;
|
||||
r.save = ceil<minutes>(save_);
|
||||
r.abbrev = dst_abbrev_;
|
||||
}
|
||||
else // st >= start
|
||||
{
|
||||
r.begin = start;
|
||||
r.end = get_next_end(y);
|
||||
r.offset += save_;
|
||||
r.save = ceil<minutes>(save_);
|
||||
r.abbrev = dst_abbrev_;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
r = contant_offset();
|
||||
using seconds = std::chrono::seconds;
|
||||
assert(r.begin <= floor<seconds>(st) && floor<seconds>(st) <= r.end);
|
||||
return r;
|
||||
}
|
||||
|
||||
template <class Duration>
|
||||
date::local_info
|
||||
time_zone::get_info(date::local_time<Duration> tp) const
|
||||
{
|
||||
using date::local_info;
|
||||
using date::year_month_day;
|
||||
using date::days;
|
||||
using date::sys_days;
|
||||
using date::sys_seconds;
|
||||
using date::year;
|
||||
using date::ceil;
|
||||
using date::January;
|
||||
using date::December;
|
||||
using date::last;
|
||||
using std::chrono::seconds;
|
||||
using std::chrono::minutes;
|
||||
local_info r{};
|
||||
using date::floor;
|
||||
if (start_rule_.ok())
|
||||
{
|
||||
auto y = year_month_day{floor<days>(tp)}.year();
|
||||
auto start = get_start(y);
|
||||
auto end = get_end(y);
|
||||
auto utcs = sys_seconds{floor<seconds>(tp - offset_).time_since_epoch()};
|
||||
auto utcd = sys_seconds{floor<seconds>(tp - (offset_ + save_)).time_since_epoch()};
|
||||
auto northern = start <= end;
|
||||
if ((utcs < start) != (utcd < start))
|
||||
{
|
||||
if (northern)
|
||||
r.first.begin = get_prev_end(y);
|
||||
else
|
||||
r.first.begin = end;
|
||||
r.first.end = start;
|
||||
r.first.offset = offset_;
|
||||
r.first.abbrev = std_abbrev_;
|
||||
r.second.begin = start;
|
||||
if (northern)
|
||||
r.second.end = end;
|
||||
else
|
||||
r.second.end = get_next_end(y);
|
||||
r.second.abbrev = dst_abbrev_;
|
||||
r.second.offset = offset_ + save_;
|
||||
r.second.save = ceil<minutes>(save_);
|
||||
r.result = save_ > seconds{0} ? local_info::nonexistent
|
||||
: local_info::ambiguous;
|
||||
}
|
||||
else if ((utcs < end) != (utcd < end))
|
||||
{
|
||||
if (northern)
|
||||
r.first.begin = start;
|
||||
else
|
||||
r.first.begin = get_prev_start(y);
|
||||
r.first.end = end;
|
||||
r.first.offset = offset_ + save_;
|
||||
r.first.save = ceil<minutes>(save_);
|
||||
r.first.abbrev = dst_abbrev_;
|
||||
r.second.begin = end;
|
||||
if (northern)
|
||||
r.second.end = get_next_start(y);
|
||||
else
|
||||
r.second.end = start;
|
||||
r.second.abbrev = std_abbrev_;
|
||||
r.second.offset = offset_;
|
||||
r.result = save_ > seconds{0} ? local_info::ambiguous
|
||||
: local_info::nonexistent;
|
||||
}
|
||||
else
|
||||
r.first = get_info(utcs);
|
||||
}
|
||||
else
|
||||
r.first = contant_offset();
|
||||
return r;
|
||||
}
|
||||
|
||||
template <class Duration>
|
||||
date::sys_time<typename std::common_type<Duration, std::chrono::seconds>::type>
|
||||
time_zone::to_sys(date::local_time<Duration> tp) const
|
||||
{
|
||||
using date::local_info;
|
||||
using date::sys_time;
|
||||
using date::ambiguous_local_time;
|
||||
using date::nonexistent_local_time;
|
||||
auto i = get_info(tp);
|
||||
if (i.result == local_info::nonexistent)
|
||||
throw nonexistent_local_time(tp, i);
|
||||
else if (i.result == local_info::ambiguous)
|
||||
throw ambiguous_local_time(tp, i);
|
||||
return sys_time<Duration>{tp.time_since_epoch()} - i.first.offset;
|
||||
}
|
||||
|
||||
template <class Duration>
|
||||
date::sys_time<typename std::common_type<Duration, std::chrono::seconds>::type>
|
||||
time_zone::to_sys(date::local_time<Duration> tp, date::choose z) const
|
||||
{
|
||||
using date::local_info;
|
||||
using date::sys_time;
|
||||
using date::choose;
|
||||
auto i = get_info(tp);
|
||||
if (i.result == local_info::nonexistent)
|
||||
{
|
||||
return i.first.end;
|
||||
}
|
||||
else if (i.result == local_info::ambiguous)
|
||||
{
|
||||
if (z == choose::latest)
|
||||
return sys_time<Duration>{tp.time_since_epoch()} - i.second.offset;
|
||||
}
|
||||
return sys_time<Duration>{tp.time_since_epoch()} - i.first.offset;
|
||||
}
|
||||
|
||||
template <class Duration>
|
||||
date::local_time<typename std::common_type<Duration, std::chrono::seconds>::type>
|
||||
time_zone::to_local(date::sys_time<Duration> tp) const
|
||||
{
|
||||
using date::local_time;
|
||||
using std::chrono::seconds;
|
||||
using LT = local_time<typename std::common_type<Duration, seconds>::type>;
|
||||
auto i = get_info(tp);
|
||||
return LT{(tp + i.offset).time_since_epoch()};
|
||||
}
|
||||
|
||||
inline
|
||||
std::ostream&
|
||||
operator<<(std::ostream& os, const time_zone& z)
|
||||
{
|
||||
using date::operator<<;
|
||||
os << '{';
|
||||
os << z.std_abbrev_ << ", " << z.dst_abbrev_ << date::format(", %T, ", z.offset_)
|
||||
<< date::format("%T, [", z.save_) << z.start_rule_ << ", " << z.end_rule_ << ")}";
|
||||
return os;
|
||||
}
|
||||
|
||||
inline
|
||||
std::string
|
||||
time_zone::name() const
|
||||
{
|
||||
using namespace date;
|
||||
using namespace std::chrono;
|
||||
auto print_abbrev = [](std::string const& nm)
|
||||
{
|
||||
if (std::any_of(nm.begin(), nm.end(),
|
||||
[](char c)
|
||||
{
|
||||
return !std::isalpha(c);
|
||||
}))
|
||||
{
|
||||
return '<' + nm + '>';
|
||||
}
|
||||
return nm;
|
||||
};
|
||||
auto print_offset = [](seconds off)
|
||||
{
|
||||
std::string nm;
|
||||
date::hh_mm_ss<seconds> offset{-off};
|
||||
if (offset.is_negative())
|
||||
nm += '-';
|
||||
nm += std::to_string(offset.hours().count());
|
||||
if (offset.minutes() != minutes{0} || offset.seconds() != seconds{0})
|
||||
{
|
||||
nm += ':';
|
||||
if (offset.minutes() < minutes{10})
|
||||
nm += '0';
|
||||
nm += std::to_string(offset.minutes().count());
|
||||
if (offset.seconds() != seconds{0})
|
||||
{
|
||||
nm += ':';
|
||||
if (offset.seconds() < seconds{10})
|
||||
nm += '0';
|
||||
nm += std::to_string(offset.seconds().count());
|
||||
}
|
||||
}
|
||||
return nm;
|
||||
};
|
||||
auto nm = print_abbrev(std_abbrev_);
|
||||
nm += print_offset(offset_);
|
||||
if (!dst_abbrev_.empty())
|
||||
{
|
||||
nm += print_abbrev(dst_abbrev_);
|
||||
if (save_ != hours{1})
|
||||
nm += print_offset(offset_+save_);
|
||||
if (start_rule_.ok())
|
||||
{
|
||||
nm += ',';
|
||||
nm += start_rule_.to_string();
|
||||
nm += ',';
|
||||
nm += end_rule_.to_string();
|
||||
}
|
||||
}
|
||||
return nm;
|
||||
}
|
||||
|
||||
inline
|
||||
bool
|
||||
operator==(const time_zone& x, const time_zone& y)
|
||||
{
|
||||
return x.std_abbrev_ == y.std_abbrev_ &&
|
||||
x.dst_abbrev_ == y. dst_abbrev_ &&
|
||||
x.offset_ == y.offset_ &&
|
||||
x.save_ == y.save_ &&
|
||||
x.start_rule_ == y.start_rule_ &&
|
||||
x.end_rule_ == y.end_rule_;
|
||||
}
|
||||
|
||||
inline
|
||||
bool
|
||||
operator!=(const time_zone& x, const time_zone& y)
|
||||
{
|
||||
return !(x == y);
|
||||
}
|
||||
|
||||
namespace detail
|
||||
{
|
||||
|
||||
inline
|
||||
void
|
||||
throw_invalid(const string_t& s, unsigned i, const string_t& message)
|
||||
{
|
||||
throw std::runtime_error(std::string("Invalid time_zone initializer.\n") +
|
||||
std::string(message) + ":\n" +
|
||||
std::string(s) + '\n' +
|
||||
"\x1b[1;32m" +
|
||||
std::string(i, '~') + '^' +
|
||||
std::string(i < s.size() ? s.size()-i-1 : 0, '~') +
|
||||
"\x1b[0m");
|
||||
}
|
||||
|
||||
inline
|
||||
unsigned
|
||||
read_date(const string_t& s, unsigned i, rule& r)
|
||||
{
|
||||
using date::month;
|
||||
using date::weekday;
|
||||
if (i == s.size())
|
||||
throw_invalid(s, i, "Expected rule but found end of string");
|
||||
if (s[i] == 'J')
|
||||
{
|
||||
++i;
|
||||
unsigned n;
|
||||
i = read_unsigned(s, i, 3, n, "Expected to find the Julian day [1, 365]");
|
||||
if (!(1 <= n && n <= 365))
|
||||
throw_invalid(s, i-1, "Expected Julian day to be in the range [1, 365]");
|
||||
r.mode_ = rule::J;
|
||||
r.n_ = n;
|
||||
}
|
||||
else if (s[i] == 'M')
|
||||
{
|
||||
++i;
|
||||
unsigned m;
|
||||
i = read_unsigned(s, i, 2, m, "Expected to find month [1, 12]");
|
||||
if (!(1 <= m && m <= 12))
|
||||
throw_invalid(s, i-1, "Expected month to be in the range [1, 12]");
|
||||
if (i == s.size() || s[i] != '.')
|
||||
throw_invalid(s, i, "Expected '.' after month");
|
||||
++i;
|
||||
unsigned n;
|
||||
i = read_unsigned(s, i, 1, n, "Expected to find week number [1, 5]");
|
||||
if (!(1 <= n && n <= 5))
|
||||
throw_invalid(s, i-1, "Expected week number to be in the range [1, 5]");
|
||||
if (i == s.size() || s[i] != '.')
|
||||
throw_invalid(s, i, "Expected '.' after weekday index");
|
||||
++i;
|
||||
unsigned wd;
|
||||
i = read_unsigned(s, i, 1, wd, "Expected to find day of week [0, 6]");
|
||||
if (wd > 6)
|
||||
throw_invalid(s, i-1, "Expected day of week to be in the range [0, 6]");
|
||||
r.mode_ = rule::M;
|
||||
r.m_ = month{m};
|
||||
r.wd_ = weekday{wd};
|
||||
r.n_ = n;
|
||||
}
|
||||
else if (std::isdigit(s[i]))
|
||||
{
|
||||
unsigned n;
|
||||
i = read_unsigned(s, i, 3, n);
|
||||
if (n > 365)
|
||||
throw_invalid(s, i-1, "Expected Julian day to be in the range [0, 365]");
|
||||
r.mode_ = rule::N;
|
||||
r.n_ = n;
|
||||
}
|
||||
else
|
||||
throw_invalid(s, i, "Expected 'J', 'M', or a digit to start rule");
|
||||
if (i != s.size() && s[i] == '/')
|
||||
{
|
||||
++i;
|
||||
std::chrono::seconds t;
|
||||
i = read_unsigned_time(s, i, t);
|
||||
r.time_ = t;
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
inline
|
||||
unsigned
|
||||
read_name(const string_t& s, unsigned i, std::string& name)
|
||||
{
|
||||
if (i == s.size())
|
||||
throw_invalid(s, i, "Expected a name but found end of string");
|
||||
if (s[i] == '<')
|
||||
{
|
||||
++i;
|
||||
while (true)
|
||||
{
|
||||
if (i == s.size())
|
||||
throw_invalid(s, i,
|
||||
"Expected to find closing '>', but found end of string");
|
||||
if (s[i] == '>')
|
||||
break;
|
||||
name.push_back(s[i]);
|
||||
++i;
|
||||
}
|
||||
++i;
|
||||
}
|
||||
else
|
||||
{
|
||||
while (i != s.size() && std::isalpha(s[i]))
|
||||
{
|
||||
name.push_back(s[i]);
|
||||
++i;
|
||||
}
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
inline
|
||||
unsigned
|
||||
read_signed_time(const string_t& s, unsigned i,
|
||||
std::chrono::seconds& t)
|
||||
{
|
||||
if (i == s.size())
|
||||
throw_invalid(s, i, "Expected to read signed time, but found end of string");
|
||||
bool negative = false;
|
||||
if (s[i] == '-')
|
||||
{
|
||||
negative = true;
|
||||
++i;
|
||||
}
|
||||
else if (s[i] == '+')
|
||||
++i;
|
||||
i = read_unsigned_time(s, i, t);
|
||||
if (negative)
|
||||
t = -t;
|
||||
return i;
|
||||
}
|
||||
|
||||
inline
|
||||
unsigned
|
||||
read_unsigned_time(const string_t& s, unsigned i, std::chrono::seconds& t)
|
||||
{
|
||||
using std::chrono::seconds;
|
||||
using std::chrono::minutes;
|
||||
using std::chrono::hours;
|
||||
if (i == s.size())
|
||||
throw_invalid(s, i, "Expected to read unsigned time, but found end of string");
|
||||
unsigned x;
|
||||
i = read_unsigned(s, i, 2, x, "Expected to find hours [0, 24]");
|
||||
if (x > 24)
|
||||
throw_invalid(s, i-1, "Expected hours to be in the range [0, 24]");
|
||||
t = hours{x};
|
||||
if (i != s.size() && s[i] == ':')
|
||||
{
|
||||
++i;
|
||||
i = read_unsigned(s, i, 2, x, "Expected to find minutes [0, 59]");
|
||||
if (x > 59)
|
||||
throw_invalid(s, i-1, "Expected minutes to be in the range [0, 59]");
|
||||
t += minutes{x};
|
||||
if (i != s.size() && s[i] == ':')
|
||||
{
|
||||
++i;
|
||||
i = read_unsigned(s, i, 2, x, "Expected to find seconds [0, 59]");
|
||||
if (x > 59)
|
||||
throw_invalid(s, i-1, "Expected seconds to be in the range [0, 59]");
|
||||
t += seconds{x};
|
||||
}
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
inline
|
||||
unsigned
|
||||
read_unsigned(const string_t& s, unsigned i, unsigned limit, unsigned& u,
|
||||
const string_t& message)
|
||||
{
|
||||
if (i == s.size() || !std::isdigit(s[i]))
|
||||
throw_invalid(s, i, message);
|
||||
u = static_cast<unsigned>(s[i] - '0');
|
||||
unsigned count = 1;
|
||||
for (++i; count < limit && i != s.size() && std::isdigit(s[i]); ++i, ++count)
|
||||
u = u * 10 + static_cast<unsigned>(s[i] - '0');
|
||||
return i;
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
|
||||
} // namespace Posix
|
||||
|
||||
namespace date
|
||||
{
|
||||
|
||||
template <>
|
||||
struct zoned_traits<Posix::time_zone>
|
||||
{
|
||||
|
||||
#if HAS_STRING_VIEW
|
||||
|
||||
static
|
||||
Posix::time_zone
|
||||
locate_zone(std::string_view name)
|
||||
{
|
||||
return Posix::time_zone{name};
|
||||
}
|
||||
|
||||
#else // !HAS_STRING_VIEW
|
||||
|
||||
static
|
||||
Posix::time_zone
|
||||
locate_zone(const std::string& name)
|
||||
{
|
||||
return Posix::time_zone{name};
|
||||
}
|
||||
|
||||
static
|
||||
Posix::time_zone
|
||||
locate_zone(const char* name)
|
||||
{
|
||||
return Posix::time_zone{name};
|
||||
}
|
||||
|
||||
#endif // !HAS_STRING_VIEW
|
||||
|
||||
};
|
||||
|
||||
} // namespace date
|
||||
|
||||
#endif // PTZ_H
|
||||
File diff suppressed because it is too large
Load Diff
@ -83,9 +83,19 @@ namespace Tesses::CrossLang
|
||||
dict->DeclareFunction(gc,"AddValue","Add item",{"key","value"},[dict0](Tesses::CrossLang::GCList &ls2, std::vector<Tesses::CrossLang::TObject> args2)->TObject {
|
||||
std::string key;
|
||||
std::string value;
|
||||
if(GetArgument(args2,0,key) && GetArgument(args2,1,value))
|
||||
int64_t i64;
|
||||
double d64;
|
||||
TDateTime da;
|
||||
if(GetArgument(args2,0,key) )
|
||||
{
|
||||
dict0->AddValue(key,value);
|
||||
if(GetArgument(args2,1,value))
|
||||
dict0->AddValue(key,value);
|
||||
else if(GetArgument(args2,1,i64))
|
||||
dict0->AddValue(key,i64);
|
||||
else if(GetArgument(args2,1,d64))
|
||||
dict0->AddValue(key, d64);
|
||||
else if(GetArgument(args2,1,da))
|
||||
dict0->AddValue(key, da.GetDate());
|
||||
}
|
||||
return nullptr;
|
||||
});
|
||||
@ -93,9 +103,19 @@ namespace Tesses::CrossLang
|
||||
dict->DeclareFunction(gc,"SetValue","Set item",{"key","value"},[dict0](Tesses::CrossLang::GCList &ls2, std::vector<Tesses::CrossLang::TObject> args2)->TObject {
|
||||
std::string key;
|
||||
std::string value;
|
||||
if(GetArgument(args2,0,key) && GetArgument(args2,1,value))
|
||||
int64_t i64;
|
||||
double d64;
|
||||
TDateTime da;
|
||||
if(GetArgument(args2,0,key) )
|
||||
{
|
||||
dict0->SetValue(key,value);
|
||||
if(GetArgument(args2,1,value))
|
||||
dict0->SetValue(key,value);
|
||||
else if(GetArgument(args2,1,i64))
|
||||
dict0->SetValue(key,i64);
|
||||
else if(GetArgument(args2,1,d64))
|
||||
dict0->SetValue(key, d64);
|
||||
else if(GetArgument(args2,1,da))
|
||||
dict0->SetValue(key, da.GetDate());
|
||||
}
|
||||
return nullptr;
|
||||
});
|
||||
@ -140,6 +160,15 @@ namespace Tesses::CrossLang
|
||||
}
|
||||
return nullptr;
|
||||
});
|
||||
dict->DeclareFunction(gc,"TryGetFirstDate","Try Get first date",{"key"},[dict0](Tesses::CrossLang::GCList &ls2, std::vector<Tesses::CrossLang::TObject> args2)->TObject {
|
||||
std::string key;
|
||||
Tesses::Framework::Date::DateTime value;
|
||||
if(GetArgument(args2,0,key) && dict0->TryGetFirstDate(key,value))
|
||||
{
|
||||
return value;
|
||||
}
|
||||
return nullptr;
|
||||
});
|
||||
|
||||
dict->DeclareFunction(gc, "ToList","To List",{}, [dict0](Tesses::CrossLang::GCList &ls2, std::vector<Tesses::CrossLang::TObject> args2)->TObject {
|
||||
TList* ls = TList::Create(ls2);
|
||||
@ -205,6 +234,16 @@ namespace Tesses::CrossLang
|
||||
dict->DeclareFunction(gc,"ReadString","Read string from request",{},[ctx](Tesses::CrossLang::GCList &ls2, std::vector<Tesses::CrossLang::TObject> args2)->TObject{
|
||||
return ctx->ReadString();
|
||||
});
|
||||
dict->DeclareFunction(gc, "ReadJson","Read json from request",{},[ctx](Tesses::CrossLang::GCList &ls2, std::vector<Tesses::CrossLang::TObject> args2)->TObject{
|
||||
return Json_Decode(ls2,ctx->ReadString());
|
||||
});
|
||||
dict->DeclareFunction(gc,"SendJson","Send object as json",{"object"},[ctx](Tesses::CrossLang::GCList& ls2, std::vector<TObject> args2)->TObject{
|
||||
if(args2.size() > 0)
|
||||
{
|
||||
ctx->WithMimeType("application/json").SendText(Json_Encode(args2[0]));
|
||||
}
|
||||
return nullptr;
|
||||
});
|
||||
|
||||
dict->DeclareFunction(gc,"SendText","Send response text",{"text"},[ctx](Tesses::CrossLang::GCList &ls2, std::vector<Tesses::CrossLang::TObject> args2)->TObject{
|
||||
std::string text;
|
||||
@ -218,6 +257,12 @@ namespace Tesses::CrossLang
|
||||
ctx->WithMimeType(text);
|
||||
return dict;
|
||||
});
|
||||
dict->DeclareFunction(gc,"WithLastModified","Set last modified date",{"date"},[ctx,dict](Tesses::CrossLang::GCList &ls2, std::vector<Tesses::CrossLang::TObject> args2)->TObject{
|
||||
TDateTime da;
|
||||
if(GetArgument(args2,0,da))
|
||||
ctx->WithLastModified(da.GetDate());
|
||||
return dict;
|
||||
});
|
||||
dict->DeclareFunction(gc,"WithContentDisposition","Set content disposition",{"filename","inline"},[ctx,dict](Tesses::CrossLang::GCList &ls2, std::vector<Tesses::CrossLang::TObject> args2)->TObject{
|
||||
std::string filename;
|
||||
bool isInline;
|
||||
@ -491,6 +536,21 @@ namespace Tesses::CrossLang
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
static TObject Net_Http_ListenOnUnusedPort(GCList& ls, std::vector<TObject> args)
|
||||
{
|
||||
if(args.size() > 0)
|
||||
{
|
||||
TObjectHttpServer httpServer(ls.GetGC(),args[0]);
|
||||
|
||||
|
||||
uint16_t port=0;
|
||||
HttpServer server(port,httpServer, false);
|
||||
std::cout << "Port: " << server.GetPort() << std::endl;
|
||||
server.StartAccepting();
|
||||
Tesses::Framework::TF_RunEventLoop();
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
static TObject Net_Http_MimeType(GCList& ls, std::vector<TObject> args)
|
||||
{
|
||||
Tesses::Framework::Filesystem::VFSPath p;
|
||||
@ -818,6 +878,7 @@ namespace Tesses::CrossLang
|
||||
});
|
||||
http->DeclareFunction(gc, "MakeRequest", "Create an http request", {"url","$extra"}, Net_Http_MakeRequest);
|
||||
http->DeclareFunction(gc, "ListenSimpleWithLoop", "Listen (creates application loop)", {"server","port"},Net_Http_ListenSimpleWithLoop);
|
||||
http->DeclareFunction(gc, "ListenOnUnusedPort","Listen on unused localhost port and print Port: theport",{"server"},Net_Http_ListenOnUnusedPort);
|
||||
//FileServer svr()
|
||||
http->DeclareFunction(gc, "FileServer","Create a file server",{"path","allowlisting","spa"}, [](GCList& ls, std::vector<TObject> args)->TObject{
|
||||
|
||||
@ -842,6 +903,21 @@ namespace Tesses::CrossLang
|
||||
});
|
||||
dict->DeclareFunction(gc, "NetworkStream","Create a network stream",{"ipv6","datagram"},Net_NetworkStream);
|
||||
smtp->DeclareFunction(gc, "Send","Send email via smtp server",{"messageStruct"},Net_Smtp_Send);
|
||||
dict->DeclareFunction(gc, "getIPAddresses","Get the ip addresses of this machine",{"$ipv6"},[](GCList& ls, std::vector<TObject> args)->TObject{
|
||||
TList* a = TList::Create(ls);
|
||||
bool ipv6=false;
|
||||
GetArgument(args,0,ipv6);
|
||||
ls.GetGC()->BarrierBegin();
|
||||
for(auto item : Tesses::Framework::Streams::NetworkStream::GetIPs(ipv6))
|
||||
{
|
||||
a->Add(TDictionary::Create(ls,{
|
||||
TDItem("Interface", item.first),
|
||||
TDItem("Address", item.second)
|
||||
}));
|
||||
}
|
||||
ls.GetGC()->BarrierEnd();;
|
||||
return a;
|
||||
});
|
||||
gc->BarrierBegin();
|
||||
dict->SetValue("Http", http);
|
||||
dict->SetValue("Smtp", smtp);
|
||||
|
||||
@ -2,10 +2,28 @@
|
||||
#if defined(CROSSLANG_ENABLE_SHARED)
|
||||
#if defined(_WIN32)
|
||||
#include <windows.h>
|
||||
|
||||
#include <time.h>
|
||||
#undef min
|
||||
#undef max
|
||||
#else
|
||||
#include <dlfcn.h>
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
#else
|
||||
#if defined(_WIN32)
|
||||
#include <windows.h>
|
||||
|
||||
#include <time.h>
|
||||
#undef min
|
||||
#undef max
|
||||
#else
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
namespace Tesses::CrossLang
|
||||
{
|
||||
#if defined(CROSSLANG_ENABLE_SHARED)
|
||||
@ -118,6 +136,13 @@ namespace Tesses::CrossLang
|
||||
TVFSHeapObject* vfs;
|
||||
return GetArgumentHeap(args,0,vfs);
|
||||
}
|
||||
|
||||
static TObject TypeIsDateTime(GCList& ls, std::vector<TObject> args)
|
||||
{
|
||||
if(args.empty()) return nullptr;
|
||||
TDateTime* dt;
|
||||
return GetArgumentHeap(args,0,dt);
|
||||
}
|
||||
static TObject New_SubdirFilesystem(GCList& ls, std::vector<TObject> args)
|
||||
{
|
||||
TVFSHeapObject* vfsho;
|
||||
@ -172,6 +197,38 @@ namespace Tesses::CrossLang
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
static TObject New_DateTime(GCList& ls, std::vector<TObject> args)
|
||||
{
|
||||
int64_t year;
|
||||
if(GetArgument(args,0,year))
|
||||
{
|
||||
if(args.size()==1)
|
||||
{
|
||||
Tesses::Framework::Date::DateTime dt(year);
|
||||
return dt;
|
||||
}
|
||||
else
|
||||
{
|
||||
int64_t month=1;
|
||||
int64_t day=1;
|
||||
int64_t hour=0;
|
||||
int64_t minute=0;
|
||||
int64_t second=0;
|
||||
bool isLocal=true;
|
||||
GetArgument(args,1,month);
|
||||
GetArgument(args,2,day);
|
||||
GetArgument(args,3,hour);
|
||||
GetArgument(args,4,minute);
|
||||
GetArgument(args,5,second);
|
||||
GetArgument(args,6,isLocal);
|
||||
|
||||
|
||||
Tesses::Framework::Date::DateTime dt((int)year,(int)month,(int)day,(int)hour,(int)minute,(int)second,isLocal);
|
||||
return dt;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
static TObject TypeOf(GCList& ls, std::vector<TObject> args)
|
||||
{
|
||||
@ -187,6 +244,7 @@ namespace Tesses::CrossLang
|
||||
if(std::holds_alternative<std::string>(args[0])) return "String";
|
||||
|
||||
if(std::holds_alternative<Tesses::Framework::Filesystem::VFSPath>(args[0])) return "Path";
|
||||
if(std::holds_alternative<TDateTime>(args[0])) return "DateTime";
|
||||
if(std::holds_alternative<THeapObjectHolder>(args[0]))
|
||||
{
|
||||
auto obj = std::get<THeapObjectHolder>(args[0]).obj;
|
||||
@ -208,6 +266,7 @@ namespace Tesses::CrossLang
|
||||
auto subEnv = dynamic_cast<TSubEnvironment*>(obj);
|
||||
auto env = dynamic_cast<TEnvironment*>(obj);
|
||||
|
||||
|
||||
if(rootEnv != nullptr) return "RootEnvironment";
|
||||
if(subEnv != nullptr) return "SubEnvironment";
|
||||
if(env != nullptr) return "Environment";
|
||||
@ -390,13 +449,70 @@ namespace Tesses::CrossLang
|
||||
return Undefined();
|
||||
}
|
||||
|
||||
|
||||
static TObject DateTime_Sleep(GCList& ls, std::vector<TObject> args)
|
||||
{
|
||||
int64_t msec;
|
||||
if(GetArgument(args,0,msec))
|
||||
{
|
||||
#if defined(_WIN32)
|
||||
Sleep((int)msec);
|
||||
#else
|
||||
usleep(1000*msec);
|
||||
#endif
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
static TObject DateTime_getNow(GCList& ls, std::vector<TObject> args)
|
||||
{
|
||||
|
||||
return Tesses::Framework::Date::DateTime::Now();
|
||||
}
|
||||
static TObject DateTime_getNowUTC(GCList& ls, std::vector<TObject> args)
|
||||
{
|
||||
return Tesses::Framework::Date::DateTime::NowUTC();
|
||||
}
|
||||
static TObject DateTime_getNowEpoch(GCList& ls, std::vector<TObject> args)
|
||||
{
|
||||
|
||||
return (int64_t)time(NULL);
|
||||
}
|
||||
static TObject DateTime_TryParseHttpDate(GCList& ls, std::vector<TObject> args)
|
||||
{
|
||||
std::string d;
|
||||
Tesses::Framework::Date::DateTime dt;
|
||||
if(GetArgument(args,0,d) && Tesses::Framework::Date::DateTime::TryParseHttpDate(d,dt))
|
||||
{
|
||||
return dt;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
void TStd::RegisterRoot(GC* gc, TRootEnvironment* env)
|
||||
{
|
||||
GCList ls(gc);
|
||||
|
||||
env->permissions.canRegisterRoot=true;
|
||||
|
||||
TDictionary* date = TDictionary::Create(ls);
|
||||
date->DeclareFunction(gc, "Sleep","Sleep for a specified amount of milliseconds (multiply seconds by 1000 to get milliseconds)", {"ms"},DateTime_Sleep);
|
||||
date->DeclareFunction(gc, "getNow", "Get the current time",{},DateTime_getNow);
|
||||
date->DeclareFunction(gc, "getNowUTC","Get the current time in UTC",{},DateTime_getNowUTC);
|
||||
date->DeclareFunction(gc, "getNowEpoch","Get the time_t time now",{},DateTime_getNowEpoch);
|
||||
date->DeclareFunction(gc, "TryParseHttpDate","Parse the http date",{},DateTime_TryParseHttpDate);
|
||||
|
||||
|
||||
gc->BarrierBegin();
|
||||
|
||||
date->SetValue("Zone", Tesses::Framework::Date::GetTimeZone());
|
||||
date->SetValue("SupportsDaylightSavings",Tesses::Framework::Date::TimeZoneSupportDST());
|
||||
|
||||
env->DeclareVariable("DateTime", date);
|
||||
|
||||
gc->BarrierEnd();
|
||||
TDictionary* newTypes = TDictionary::Create(ls);
|
||||
|
||||
newTypes->DeclareFunction(gc, "DateTime","Create a DateTime object, if only one arg is provided year is epoch, isLocal defaults to true unless epoch",{"year","$month","$day","$hour","$minute","$second","$isLocal"},New_DateTime);
|
||||
|
||||
newTypes->DeclareFunction(gc, "MountableFilesystem","Create a mountable filesystem",{"root"}, New_MountableFilesystem);
|
||||
newTypes->DeclareFunction(gc, "SubdirFilesystem","Create a subdir filesystem",{"fs","subdir"}, New_SubdirFilesystem);
|
||||
newTypes->DeclareFunction(gc, "MemoryStream","Create a memory stream",{"writable"}, New_MemoryStream);
|
||||
@ -444,6 +560,7 @@ namespace Tesses::CrossLang
|
||||
env->DeclareFunction(gc, "TypeIsList","Get whether object is a list or dynamic list",{"object"},TypeIsList);
|
||||
env->DeclareFunction(gc, "TypeIsStream","Get whether object is a stream",{"object"},TypeIsStream);
|
||||
env->DeclareFunction(gc, "TypeIsVFS","Get whether object is a virtual filesystem",{"object"},TypeIsVFS);
|
||||
env->DeclareFunction(gc, "TypeIsDateTime","Get whether object is a DateTime",{"object"},TypeIsDateTime);
|
||||
|
||||
|
||||
newTypes->DeclareFunction(gc, "Regex", "Create regex object",{"regex"},[](GCList& ls,std::vector<TObject> args)->TObject {
|
||||
@ -569,7 +686,6 @@ namespace Tesses::CrossLang
|
||||
RegisterCrypto(gc,env);
|
||||
RegisterOGC(gc, env);
|
||||
RegisterProcess(gc,env);
|
||||
RegisterTime(gc, env);
|
||||
|
||||
gc->RegisterEverything(env);
|
||||
|
||||
|
||||
@ -1,248 +0,0 @@
|
||||
|
||||
#include "CrossLang.hpp"
|
||||
#if defined(CROSSLANG_ENABLE_TIME)
|
||||
#if defined(_WIN32)
|
||||
#include <windows.h>
|
||||
|
||||
#include <time.h>
|
||||
#undef min
|
||||
#undef max
|
||||
#else
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
#include "../HowardHinnant_date/date.h"
|
||||
#endif
|
||||
|
||||
|
||||
namespace Tesses::CrossLang
|
||||
{
|
||||
#if defined(CROSSLANG_ENABLE_TIME)
|
||||
static int64_t ToLocalTime(int64_t local)
|
||||
{
|
||||
#if defined(__SWITCH__) || defined(_WIN32)
|
||||
local -= _timezone;
|
||||
if(_daylight)
|
||||
#else
|
||||
local -= timezone;
|
||||
if(daylight)
|
||||
#endif
|
||||
{
|
||||
auto epoch = date::sys_days{date::January/1/1970};
|
||||
epoch += date::days(local/86400);
|
||||
|
||||
bool isDST = false;
|
||||
|
||||
date::year_month_day ymd(epoch);
|
||||
|
||||
auto month = (uint32_t)ymd.month();
|
||||
|
||||
if(month > 3 && month < 11)
|
||||
{
|
||||
isDST=true;
|
||||
}
|
||||
else if(month == 3)
|
||||
{
|
||||
auto day = (uint32_t)ymd.day();
|
||||
if(day > 14) isDST=true;
|
||||
else if(day >= 8 && day <= 14)
|
||||
{
|
||||
date::year_month_weekday ymw(epoch);
|
||||
auto dow=ymw.weekday().c_encoding();
|
||||
auto secondSunday = day - dow;
|
||||
if(secondSunday < 8) secondSunday+=7;
|
||||
|
||||
if(day > secondSunday) isDST=true;
|
||||
else if(day == secondSunday)
|
||||
{
|
||||
std::chrono::duration<int64_t> local_epoch_time(local);
|
||||
date::hh_mm_ss hms(local_epoch_time%86400);
|
||||
if(hms.hours().count() >= 2) isDST=true;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(month == 11)
|
||||
{
|
||||
auto day = (uint32_t)ymd.day();
|
||||
if(day >= 1 && day <= 7)
|
||||
{
|
||||
date::year_month_weekday ymw(epoch);
|
||||
auto dow=ymw.weekday().c_encoding();
|
||||
int32_t firstSunday = (int32_t)day - (int32_t)dow;
|
||||
if(firstSunday < 1) firstSunday+=7;
|
||||
|
||||
if(day < firstSunday) isDST=true;
|
||||
else if(day == firstSunday)
|
||||
{
|
||||
std::chrono::duration<int64_t> local_epoch_time(local);
|
||||
date::hh_mm_ss hms(local_epoch_time%86400);
|
||||
if(hms.hours().count() <=1) isDST=true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(isDST) local += 3600;
|
||||
}
|
||||
return local;
|
||||
}
|
||||
static TObject Time_getNow(GCList& ls, std::vector<TObject> args)
|
||||
{
|
||||
time_t t = time(NULL);
|
||||
return (time_t)t;
|
||||
}
|
||||
static TObject Time_Sleep(GCList& ls, std::vector<TObject> args)
|
||||
{
|
||||
int64_t msec;
|
||||
if(GetArgument(args,0,msec))
|
||||
{
|
||||
#if defined(_WIN32)
|
||||
Sleep((int)msec);
|
||||
#else
|
||||
usleep(1000*msec);
|
||||
#endif
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
static TObject Time_LocalTime(GCList& ls, std::vector<TObject> args)
|
||||
{
|
||||
//THIS code isn't the best but should work
|
||||
int64_t local;
|
||||
if(GetArgument(args,0,local))
|
||||
{
|
||||
local = ToLocalTime(local);
|
||||
|
||||
std::chrono::duration<int64_t> local_epoch_time(local);
|
||||
date::hh_mm_ss hms(local_epoch_time%86400);
|
||||
auto epoch = date::sys_days{date::January/1/1970};
|
||||
epoch += date::days(local/86400);
|
||||
|
||||
|
||||
|
||||
//date::days<int64_t> sys_days_since_epoch = date::days<int64_t>(gmt);
|
||||
|
||||
|
||||
// Convert sys_days to year_month_day
|
||||
date::year_month_day ymd = date::year_month_day(epoch);
|
||||
|
||||
TDictionary* dict = TDictionary::Create(ls);
|
||||
ls.GetGC()->BarrierBegin();
|
||||
dict->SetValue("Hour",hms.hours().count());
|
||||
dict->SetValue("Minute",hms.minutes().count());
|
||||
dict->SetValue("Second",hms.seconds().count());
|
||||
|
||||
dict->SetValue("Day",(int64_t)(uint32_t)ymd.day());
|
||||
dict->SetValue("Month",(int64_t)(uint32_t)ymd.month());
|
||||
dict->SetValue("Year",(int64_t)(int32_t)ymd.year());
|
||||
ls.GetGC()->BarrierEnd();
|
||||
return dict;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
static TObject Time_LocalUsSlashDate(GCList& ls, std::vector<TObject> args)
|
||||
{
|
||||
|
||||
//THIS code isn't the best but should work
|
||||
int64_t local;
|
||||
if(GetArgument(args,0,local))
|
||||
{
|
||||
local = ToLocalTime(local);
|
||||
|
||||
std::chrono::duration<int64_t> local_epoch_time(local);
|
||||
date::hh_mm_ss hms(local_epoch_time%86400);
|
||||
auto epoch = date::sys_days{date::January/1/1970};
|
||||
epoch += date::days(local/86400);
|
||||
|
||||
|
||||
|
||||
//date::days<int64_t> sys_days_since_epoch = date::days<int64_t>(gmt);
|
||||
|
||||
|
||||
// Convert sys_days to year_month_day
|
||||
date::year_month_day ymd = date::year_month_day(epoch);
|
||||
|
||||
return std::to_string((uint32_t)ymd.month()) + "/" + std::to_string((uint32_t)ymd.day()) + "/" + std::to_string((int)ymd.year());
|
||||
}
|
||||
return "";
|
||||
}
|
||||
static TObject Time_UTCUsSlashDate(GCList& ls,std::vector<TObject> args)
|
||||
{
|
||||
int64_t gmt;
|
||||
if(GetArgument(args,0,gmt))
|
||||
{
|
||||
|
||||
std::chrono::duration<int64_t> epoch_time(gmt);
|
||||
date::hh_mm_ss hms(epoch_time%86400);
|
||||
auto epoch = date::sys_days{date::January/1/1970};
|
||||
epoch += date::days(gmt/86400);
|
||||
|
||||
|
||||
//date::days<int64_t> sys_days_since_epoch = date::days<int64_t>(gmt);
|
||||
|
||||
|
||||
// Convert sys_days to year_month_day
|
||||
date::year_month_day ymd = date::year_month_day(epoch);
|
||||
return std::to_string((uint32_t)ymd.month()) + "/" + std::to_string((uint32_t)ymd.day()) + "/" + std::to_string((int)ymd.year());
|
||||
}
|
||||
return "";
|
||||
}
|
||||
static TObject Time_GMTTime(GCList& ls, std::vector<TObject> args)
|
||||
{
|
||||
int64_t gmt;
|
||||
if(GetArgument(args,0,gmt))
|
||||
{
|
||||
std::chrono::duration<int64_t> epoch_time(gmt);
|
||||
date::hh_mm_ss hms(epoch_time%86400);
|
||||
auto epoch = date::sys_days{date::January/1/1970};
|
||||
epoch += date::days(gmt/86400);
|
||||
|
||||
|
||||
//date::days<int64_t> sys_days_since_epoch = date::days<int64_t>(gmt);
|
||||
|
||||
|
||||
// Convert sys_days to year_month_day
|
||||
date::year_month_day ymd = date::year_month_day(epoch);
|
||||
|
||||
TDictionary* dict = TDictionary::Create(ls);
|
||||
ls.GetGC()->BarrierBegin();
|
||||
dict->SetValue("Hour",hms.hours().count());
|
||||
dict->SetValue("Minute",hms.minutes().count());
|
||||
dict->SetValue("Second",hms.seconds().count());
|
||||
|
||||
dict->SetValue("Day",(int64_t)(uint32_t)ymd.day());
|
||||
dict->SetValue("Month",(int64_t)(uint32_t)ymd.month());
|
||||
dict->SetValue("Year",(int64_t)(int32_t)ymd.year());
|
||||
ls.GetGC()->BarrierEnd();
|
||||
return dict;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
#endif
|
||||
void TStd::RegisterTime(GC* gc,TRootEnvironment* env)
|
||||
{
|
||||
#if defined(CROSSLANG_ENABLE_TIME)
|
||||
|
||||
|
||||
env->permissions.canRegisterTime=true;
|
||||
GCList ls(gc);
|
||||
TDictionary* dict = TDictionary::Create(ls);
|
||||
dict->DeclareFunction(gc, "GetLocalTime", "Get local time from epoch value",{"epoch"},Time_LocalTime);
|
||||
dict->DeclareFunction(gc, "GetGMTTime","Get the GMT time from epoch value",{"epoch"},Time_GMTTime);
|
||||
dict->DeclareFunction(gc, "getNow","Get the time right now, returns C's time(NULL) return value",{},Time_getNow);
|
||||
dict->DeclareFunction(gc, "Sleep","Sleep for a specified amount of milliseconds (multiply seconds by 1000 to get milliseconds)", {"ms"},Time_Sleep);
|
||||
dict->DeclareFunction(gc, "UTCUsSlashDate","Get a utc date like 8/20/1992 from epoch value",{"epoch"},Time_UTCUsSlashDate);
|
||||
dict->DeclareFunction(gc, "LocalUsSlashDate","Get a local date like 8/20/1992 from epoch value",{"epoch"},Time_LocalUsSlashDate);
|
||||
|
||||
gc->BarrierBegin();
|
||||
#if defined(__SWITCH__) || defined(_WIN32)
|
||||
dict->SetValue("Zone", (int64_t)-(_timezone));
|
||||
dict->SetValue("SupportsDaylightSavings",(int64_t)_daylight);
|
||||
#else
|
||||
dict->SetValue("Zone", (int64_t)-(timezone));
|
||||
dict->SetValue("SupportsDaylightSavings",(int64_t)daylight);
|
||||
#endif
|
||||
env->DeclareVariable("Time", dict);
|
||||
|
||||
gc->BarrierEnd();
|
||||
#endif
|
||||
}
|
||||
}
|
||||
23
src/types/datetime.cpp
Normal file
23
src/types/datetime.cpp
Normal file
@ -0,0 +1,23 @@
|
||||
#include "CrossLang.hpp"
|
||||
namespace Tesses::CrossLang {
|
||||
TDateTime::TDateTime()
|
||||
{
|
||||
this->dt=new Tesses::Framework::Date::DateTime();
|
||||
}
|
||||
TDateTime::TDateTime(Tesses::Framework::Date::DateTime t)
|
||||
{
|
||||
this->dt = new Tesses::Framework::Date::DateTime(t);
|
||||
}
|
||||
TDateTime::TDateTime(const TDateTime& dt)
|
||||
{
|
||||
this->dt = new Tesses::Framework::Date::DateTime(*dt.dt);
|
||||
}
|
||||
Tesses::Framework::Date::DateTime& TDateTime::GetDate()
|
||||
{
|
||||
return *this->dt;
|
||||
}
|
||||
TDateTime::~TDateTime()
|
||||
{
|
||||
delete this->dt;
|
||||
}
|
||||
}
|
||||
@ -556,7 +556,7 @@ namespace Tesses::CrossLang {
|
||||
}
|
||||
return Tesses::Framework::Filesystem::VFSPath();
|
||||
}
|
||||
void TObjectVFS::GetDate(Tesses::Framework::Filesystem::VFSPath path, time_t& lastWrite, time_t& lastAccess)
|
||||
void TObjectVFS::GetDate(Tesses::Framework::Filesystem::VFSPath path, Tesses::Framework::Date::DateTime& lastWrite, Tesses::Framework::Date::DateTime& lastAccess)
|
||||
{
|
||||
|
||||
TVFSHeapObject* vfs;
|
||||
@ -573,17 +573,20 @@ namespace Tesses::CrossLang {
|
||||
{
|
||||
this->ls->GetGC()->BarrierBegin();
|
||||
res = dict->GetValue("LastWrite");
|
||||
int64_t v;
|
||||
if(GetObject(res,v)) lastWrite=(time_t)v;
|
||||
TDateTime d;
|
||||
if(GetObject(res,d))
|
||||
lastWrite =d.GetDate();
|
||||
|
||||
res = dict->GetValue("LastAccess");
|
||||
if(GetObject(res,v)) lastAccess=(time_t)v;
|
||||
|
||||
if(GetObject(res,d))
|
||||
lastWrite =d.GetDate();
|
||||
|
||||
this->ls->GetGC()->BarrierEnd();
|
||||
}
|
||||
}
|
||||
}
|
||||
void TObjectVFS::SetDate(Tesses::Framework::Filesystem::VFSPath path, time_t lastWrite, time_t lastAccess)
|
||||
void TObjectVFS::SetDate(Tesses::Framework::Filesystem::VFSPath path, Tesses::Framework::Date::DateTime lastWrite, Tesses::Framework::Date::DateTime lastAccess)
|
||||
{
|
||||
|
||||
TVFSHeapObject* vfs;
|
||||
@ -595,7 +598,7 @@ namespace Tesses::CrossLang {
|
||||
if(GetObjectHeap(this->obj, dict))
|
||||
{
|
||||
GCList ls(this->ls->GetGC());
|
||||
dict->CallMethod(ls, "SetDate",{path,(int64_t)lastWrite,(int64_t)lastAccess});
|
||||
dict->CallMethod(ls, "SetDate",{path,lastWrite,lastAccess});
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
183
src/vm/vm.cpp
183
src/vm/vm.cpp
@ -42,6 +42,12 @@ namespace Tesses::CrossLang {
|
||||
{
|
||||
return std::get<char>(obj) != 0;
|
||||
}
|
||||
else if(std::holds_alternative<TDateTime>(obj))
|
||||
{
|
||||
auto& dt = std::get<TDateTime>(obj).GetDate();
|
||||
return !(dt.Year() == 1970 && dt.Month() == 1 && dt.Day() == 1 && dt.Hour() == 0 && dt.Minute() == 0 && dt.Second() == 0 && !dt.IsLocal());
|
||||
|
||||
}
|
||||
else if(std::holds_alternative<THeapObjectHolder>(obj))
|
||||
{
|
||||
auto o = std::get<THeapObjectHolder>(obj).obj;
|
||||
@ -50,6 +56,8 @@ namespace Tesses::CrossLang {
|
||||
auto ba = dynamic_cast<TByteArray*>(o);
|
||||
auto nat = dynamic_cast<TNative*>(o);
|
||||
auto thrd = dynamic_cast<ThreadHandle*>(o);
|
||||
auto dt = dynamic_cast<TDateTime*>(o);
|
||||
|
||||
if(ls != nullptr)
|
||||
{
|
||||
return ls->Count() != 0;
|
||||
@ -130,6 +138,10 @@ namespace Tesses::CrossLang {
|
||||
{
|
||||
return std::get<int64_t>(left) == std::get<char>(right);
|
||||
}
|
||||
else if(std::holds_alternative<TDateTime>(left) && std::holds_alternative<TDateTime>(right))
|
||||
{
|
||||
return std::get<TDateTime>(left).GetDate().ToEpoch() == std::get<TDateTime>(right).GetDate().ToEpoch();
|
||||
}
|
||||
else if(std::holds_alternative<TVMVersion>(left) && std::holds_alternative<TVMVersion>(right))
|
||||
{
|
||||
auto lver= std::get<TVMVersion>(left);
|
||||
@ -692,6 +704,7 @@ namespace Tesses::CrossLang {
|
||||
cse.back()->Push(gc,dynDict->CallMethod(ls,"operator!",{}));
|
||||
return false;
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
cse.back()->Push(gc, !ToBool(left));
|
||||
@ -796,12 +809,17 @@ namespace Tesses::CrossLang {
|
||||
{
|
||||
cse.back()->Push(gc, std::get<std::string>(left) < std::get<std::string>(right));
|
||||
}
|
||||
else if(std::holds_alternative<TDateTime>(left) && std::holds_alternative<TDateTime>(right))
|
||||
{
|
||||
cse.back()->Push(gc, std::get<TDateTime>(left).GetDate().ToEpoch() < std::get<TDateTime>(right).GetDate().ToEpoch());
|
||||
}
|
||||
else if(std::holds_alternative<THeapObjectHolder>(left))
|
||||
{
|
||||
auto obj = std::get<THeapObjectHolder>(left).obj;
|
||||
auto dict = dynamic_cast<TDictionary*>(obj);
|
||||
|
||||
auto dynDict = dynamic_cast<TDynamicDictionary*>(obj);
|
||||
|
||||
if(dict != nullptr)
|
||||
{
|
||||
gc->BarrierBegin();
|
||||
@ -875,12 +893,17 @@ namespace Tesses::CrossLang {
|
||||
{
|
||||
cse.back()->Push(gc, std::get<std::string>(left) > std::get<std::string>(right));
|
||||
}
|
||||
else if(std::holds_alternative<TDateTime>(left) && std::holds_alternative<TDateTime>(right))
|
||||
{
|
||||
cse.back()->Push(gc, std::get<TDateTime>(left).GetDate().ToEpoch() > std::get<TDateTime>(right).GetDate().ToEpoch());
|
||||
}
|
||||
else if(std::holds_alternative<THeapObjectHolder>(left))
|
||||
{
|
||||
auto obj = std::get<THeapObjectHolder>(left).obj;
|
||||
auto dict = dynamic_cast<TDictionary*>(obj);
|
||||
|
||||
auto dynDict = dynamic_cast<TDynamicDictionary*>(obj);
|
||||
|
||||
if(dict != nullptr)
|
||||
{
|
||||
gc->BarrierBegin();
|
||||
@ -953,12 +976,17 @@ namespace Tesses::CrossLang {
|
||||
{
|
||||
cse.back()->Push(gc, std::get<std::string>(left) <= std::get<std::string>(right));
|
||||
}
|
||||
else if(std::holds_alternative<TDateTime>(left) && std::holds_alternative<TDateTime>(right))
|
||||
{
|
||||
cse.back()->Push(gc, std::get<TDateTime>(left).GetDate().ToEpoch() <= std::get<TDateTime>(right).GetDate().ToEpoch());
|
||||
}
|
||||
else if(std::holds_alternative<THeapObjectHolder>(left))
|
||||
{
|
||||
auto obj = std::get<THeapObjectHolder>(left).obj;
|
||||
auto dict = dynamic_cast<TDictionary*>(obj);
|
||||
|
||||
auto dynDict = dynamic_cast<TDynamicDictionary*>(obj);
|
||||
|
||||
if(dict != nullptr)
|
||||
{
|
||||
gc->BarrierBegin();
|
||||
@ -971,6 +999,7 @@ namespace Tesses::CrossLang {
|
||||
cse.back()->Push(gc,dynDict->CallMethod(ls,"operator<=",{right}));
|
||||
return false;
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
cse.back()->Push(gc,Undefined());
|
||||
@ -1032,12 +1061,17 @@ namespace Tesses::CrossLang {
|
||||
{
|
||||
cse.back()->Push(gc, std::get<std::string>(left) >= std::get<std::string>(right));
|
||||
}
|
||||
else if(std::holds_alternative<TDateTime>(left) && std::holds_alternative<TDateTime>(right))
|
||||
{
|
||||
cse.back()->Push(gc, std::get<TDateTime>(left).GetDate().ToEpoch() >= std::get<TDateTime>(right).GetDate().ToEpoch());
|
||||
}
|
||||
else if(std::holds_alternative<THeapObjectHolder>(left))
|
||||
{
|
||||
auto obj = std::get<THeapObjectHolder>(left).obj;
|
||||
auto dict = dynamic_cast<TDictionary*>(obj);
|
||||
|
||||
auto dynDict = dynamic_cast<TDynamicDictionary*>(obj);
|
||||
|
||||
if(dict != nullptr)
|
||||
{
|
||||
gc->BarrierBegin();
|
||||
@ -1050,6 +1084,7 @@ namespace Tesses::CrossLang {
|
||||
cse.back()->Push(gc,dynDict->CallMethod(ls,"operator>=",{right}));
|
||||
return false;
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
cse.back()->Push(gc,Undefined());
|
||||
@ -1128,6 +1163,10 @@ namespace Tesses::CrossLang {
|
||||
auto r = lver.CompareTo(rver);
|
||||
cse.back()->Push(gc, r == 0);
|
||||
}
|
||||
else if(std::holds_alternative<TDateTime>(left) && std::holds_alternative<TDateTime>(right))
|
||||
{
|
||||
cse.back()->Push(gc, std::get<TDateTime>(left).GetDate().ToEpoch() == std::get<TDateTime>(right).GetDate().ToEpoch());
|
||||
}
|
||||
else if(std::holds_alternative<THeapObjectHolder>(left))
|
||||
{
|
||||
auto obj = std::get<THeapObjectHolder>(left).obj;
|
||||
@ -1135,6 +1174,8 @@ namespace Tesses::CrossLang {
|
||||
|
||||
auto dynDict = dynamic_cast<TDynamicDictionary*>(obj);
|
||||
auto native = dynamic_cast<TNative*>(obj);
|
||||
|
||||
|
||||
if(dict != nullptr)
|
||||
{
|
||||
gc->BarrierBegin();
|
||||
@ -1154,6 +1195,7 @@ namespace Tesses::CrossLang {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
else if(native != nullptr && std::holds_alternative<std::nullptr_t>(right)){
|
||||
cse.back()->Push(gc, native->GetDestroyed());
|
||||
return false;
|
||||
@ -1260,6 +1302,10 @@ namespace Tesses::CrossLang {
|
||||
auto r = lver.CompareTo(rver);
|
||||
cse.back()->Push(gc, r != 0);
|
||||
}
|
||||
else if(std::holds_alternative<TDateTime>(left) && std::holds_alternative<TDateTime>(right))
|
||||
{
|
||||
cse.back()->Push(gc, std::get<TDateTime>(left).GetDate().ToEpoch() != std::get<TDateTime>(right).GetDate().ToEpoch());
|
||||
}
|
||||
else if(std::holds_alternative<THeapObjectHolder>(left))
|
||||
{
|
||||
auto obj = std::get<THeapObjectHolder>(left).obj;
|
||||
@ -1286,6 +1332,7 @@ namespace Tesses::CrossLang {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
else if(native != nullptr && std::holds_alternative<std::nullptr_t>(right)){
|
||||
cse.back()->Push(gc, !native->GetDestroyed());
|
||||
return false;
|
||||
@ -2369,14 +2416,7 @@ namespace Tesses::CrossLang {
|
||||
std::string _str={};
|
||||
if(GetArgument(args,0,oldStr) && GetArgument(args,1,newStr))
|
||||
{
|
||||
bool first=true;
|
||||
|
||||
for(auto txt : Tesses::Framework::Http::HttpUtils::SplitString(str,oldStr))
|
||||
{
|
||||
if(!first) _str.append(newStr);
|
||||
first=false;
|
||||
_str.append(txt);
|
||||
}
|
||||
_str = Tesses::Framework::Http::HttpUtils::Replace(str, oldStr,newStr);
|
||||
|
||||
|
||||
}
|
||||
@ -2449,6 +2489,48 @@ namespace Tesses::CrossLang {
|
||||
cse.back()->Push(gc, Undefined());
|
||||
return false;
|
||||
}
|
||||
else if(std::holds_alternative<TDateTime>(instance))
|
||||
{
|
||||
auto& date = std::get<TDateTime>(instance).GetDate();
|
||||
|
||||
|
||||
if(key == "ToString")
|
||||
{
|
||||
std::string fmt;
|
||||
if(GetArgument(args,0,fmt))
|
||||
{
|
||||
cse.back()->Push(gc, date.ToString(fmt));
|
||||
}
|
||||
else
|
||||
{
|
||||
cse.back()->Push(gc, date.ToString());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
if(key == "ToHttpDate")
|
||||
{
|
||||
cse.back()->Push(gc, date.ToHttpDate());
|
||||
return false;
|
||||
}
|
||||
if(key == "ToEpoch")
|
||||
{
|
||||
cse.back()->Push(gc, date.ToEpoch());
|
||||
return false;
|
||||
}
|
||||
if(key == "ToLocal")
|
||||
{
|
||||
cse.back()->Push(gc, date.ToLocal());
|
||||
return false;
|
||||
}
|
||||
if(key == "ToUTC")
|
||||
{
|
||||
cse.back()->Push(gc, date.ToUTC());
|
||||
return false;
|
||||
}
|
||||
cse.back()->Push(gc, nullptr);
|
||||
return false;
|
||||
|
||||
}
|
||||
else if(std::holds_alternative<THeapObjectHolder>(instance))
|
||||
{
|
||||
auto obj = std::get<THeapObjectHolder>(instance).obj;
|
||||
@ -2465,6 +2547,7 @@ namespace Tesses::CrossLang {
|
||||
auto callable = dynamic_cast<TCallable*>(obj);
|
||||
auto callstackEntry = dynamic_cast<CallStackEntry*>(obj);
|
||||
|
||||
|
||||
auto svr = dynamic_cast<TServerHeapObject*>(obj);
|
||||
|
||||
if(callstackEntry != nullptr)
|
||||
@ -2721,13 +2804,7 @@ namespace Tesses::CrossLang {
|
||||
cse.back()->Push(gc,nullptr);
|
||||
return false;
|
||||
}
|
||||
if(key == "RegisterTime")
|
||||
{
|
||||
if((myEnv->permissions.canRegisterEverything || myEnv->permissions.canRegisterTime) && !rootEnv->permissions.locked)
|
||||
TStd::RegisterTime(gc, rootEnv);
|
||||
cse.back()->Push(gc,nullptr);
|
||||
return false;
|
||||
}
|
||||
|
||||
if(key == "SetSqliteRoot")
|
||||
{
|
||||
Tesses::Framework::Filesystem::VFSPath p;
|
||||
@ -2974,11 +3051,11 @@ namespace Tesses::CrossLang {
|
||||
if(key == "SetDate")
|
||||
{
|
||||
Tesses::Framework::Filesystem::VFSPath path;
|
||||
int64_t lastWrite;
|
||||
int64_t lastAccess;
|
||||
TDateTime lastWrite;
|
||||
TDateTime lastAccess;
|
||||
if(GetArgumentAsPath(args,0,path) && GetArgument(args,1,lastWrite) && GetArgument(args,2,lastAccess))
|
||||
{
|
||||
vfs->vfs->SetDate(path,(time_t)lastWrite,(time_t)lastAccess);
|
||||
vfs->vfs->SetDate(path,lastWrite.GetDate(), lastAccess.GetDate());
|
||||
}
|
||||
cse.back()->Push(gc, nullptr);
|
||||
return false;
|
||||
@ -2988,13 +3065,15 @@ namespace Tesses::CrossLang {
|
||||
Tesses::Framework::Filesystem::VFSPath path;
|
||||
if(GetArgumentAsPath(args,0,path))
|
||||
{
|
||||
time_t lastWrite;
|
||||
time_t lastAccess;
|
||||
Tesses::Framework::Date::DateTime lastWrite;
|
||||
Tesses::Framework::Date::DateTime lastAccess;
|
||||
vfs->vfs->GetDate(path,lastWrite,lastAccess);
|
||||
|
||||
auto dict = TDictionary::Create(ls);
|
||||
ls.GetGC()->BarrierBegin();
|
||||
dict->SetValue("LastWrite", (int64_t)lastWrite);
|
||||
dict->SetValue("LastAccess", (int64_t)lastAccess);
|
||||
|
||||
dict->SetValue("LastWrite", TDateTime(lastWrite));
|
||||
dict->SetValue("LastAccess", TDateTime(lastAccess));
|
||||
ls.GetGC()->BarrierEnd();
|
||||
|
||||
cse.back()->Push(gc, dict);
|
||||
@ -3244,6 +3323,7 @@ namespace Tesses::CrossLang {
|
||||
{
|
||||
auto memStrm = dynamic_cast<Tesses::Framework::Streams::MemoryStream*>(strm->stream);
|
||||
auto netStrm = dynamic_cast<Tesses::Framework::Streams::NetworkStream*>(strm->stream);
|
||||
|
||||
auto mystrm = dynamic_cast<TObjectStream*>(strm->stream);
|
||||
|
||||
if(mystrm != nullptr)
|
||||
@ -3271,6 +3351,11 @@ namespace Tesses::CrossLang {
|
||||
}
|
||||
if(netStrm != nullptr)
|
||||
{
|
||||
if(key == "GetPort")
|
||||
{
|
||||
cse.back()->Push(gc, netStrm->GetPort());
|
||||
return false;
|
||||
}
|
||||
if(key == "Bind")
|
||||
{
|
||||
std::string ip;
|
||||
@ -3522,6 +3607,7 @@ namespace Tesses::CrossLang {
|
||||
cse.back()->Push(gc, nullptr);
|
||||
return false;
|
||||
}
|
||||
|
||||
else if(bArray != nullptr)
|
||||
{
|
||||
if(key == "Count" || key == "Length")
|
||||
@ -4098,6 +4184,53 @@ namespace Tesses::CrossLang {
|
||||
stk->Push(gc, Undefined());
|
||||
return false;
|
||||
}
|
||||
if(std::holds_alternative<TDateTime>(instance))
|
||||
{
|
||||
auto& date = std::get<TDateTime>(instance).GetDate();
|
||||
if(key == "IsLocal")
|
||||
{
|
||||
stk->Push(gc, date.IsLocal());
|
||||
return false;
|
||||
}
|
||||
if(key == "Year")
|
||||
{
|
||||
stk->Push(gc, (int64_t)date.Year());
|
||||
return false;
|
||||
}
|
||||
if(key == "Month")
|
||||
{
|
||||
stk->Push(gc, (int64_t)date.Month());
|
||||
return false;
|
||||
}
|
||||
if(key == "Day")
|
||||
{
|
||||
stk->Push(gc, (int64_t)date.Day());
|
||||
return false;
|
||||
}
|
||||
if(key == "Hour")
|
||||
{
|
||||
stk->Push(gc, (int64_t)date.Hour());
|
||||
return false;
|
||||
}
|
||||
if(key == "Minute")
|
||||
{
|
||||
stk->Push(gc, (int64_t)date.Minute());
|
||||
return false;
|
||||
}
|
||||
if(key == "Second")
|
||||
{
|
||||
stk->Push(gc, (int64_t)date.Second());
|
||||
return false;
|
||||
}
|
||||
if(key == "DayOfWeek")
|
||||
{
|
||||
stk->Push(gc, (int64_t)date.DayOfWeek());
|
||||
return false;
|
||||
}
|
||||
|
||||
stk->Push(gc, Undefined());
|
||||
return false;
|
||||
}
|
||||
if(std::holds_alternative<THeapObjectHolder>(instance))
|
||||
{
|
||||
auto obj = std::get<THeapObjectHolder>(instance).obj;
|
||||
@ -5791,13 +5924,17 @@ namespace Tesses::CrossLang {
|
||||
{
|
||||
return std::get<bool>(o) ? "true" : "false";
|
||||
}
|
||||
|
||||
if(std::holds_alternative<TDateTime>(o))
|
||||
{
|
||||
return std::get<TDateTime>(o).GetDate().ToString();
|
||||
}
|
||||
if(std::holds_alternative<THeapObjectHolder>(o))
|
||||
{
|
||||
auto obj = std::get<THeapObjectHolder>(o).obj;
|
||||
auto dict = dynamic_cast<TDictionary*>(obj);
|
||||
auto list = dynamic_cast<TList*>(obj);
|
||||
auto bArray = dynamic_cast<TByteArray*>(obj);
|
||||
|
||||
if(dict != nullptr)
|
||||
{
|
||||
GCList ls(gc);
|
||||
|
||||
Reference in New Issue
Block a user