Add html expression, console error and streams
This commit is contained in:
@ -161,6 +161,38 @@ namespace Tesses::CrossLang {
|
||||
std::cout << ToString(ls.GetGC(),args[0]) << "\n";
|
||||
return Undefined();
|
||||
}
|
||||
TObject Console_Error(GCList& ls, std::vector<TObject> args)
|
||||
{
|
||||
if(args.size() < 1)
|
||||
{
|
||||
return Undefined();
|
||||
}
|
||||
std::cerr << ToString(ls.GetGC(),args[0]);
|
||||
return Undefined();
|
||||
}
|
||||
TObject Console_ErrorLine(GCList& ls, std::vector<TObject> args)
|
||||
{
|
||||
if(args.size() < 1)
|
||||
{
|
||||
std::cout << "\n";
|
||||
return Undefined();
|
||||
}
|
||||
std::cerr << ToString(ls.GetGC(),args[0]) << "\n";
|
||||
return Undefined();
|
||||
}
|
||||
TObject Console_getIn(GCList& ls, std::vector<TObject> args)
|
||||
{
|
||||
return TStreamHeapObject::Create(ls, new Tesses::Framework::Streams::FileStream(stdin,false,"r",false));
|
||||
}
|
||||
|
||||
TObject Console_getOut(GCList& ls, std::vector<TObject> args)
|
||||
{
|
||||
return TStreamHeapObject::Create(ls, new Tesses::Framework::Streams::FileStream(stdout,false,"w",false));
|
||||
}
|
||||
TObject Console_getError(GCList& ls, std::vector<TObject> args)
|
||||
{
|
||||
return TStreamHeapObject::Create(ls, new Tesses::Framework::Streams::FileStream(stderr,false,"w",false));
|
||||
}
|
||||
void TStd::RegisterConsole(GC* gc,TRootEnvironment* env)
|
||||
{
|
||||
env->permissions.canRegisterConsole=true;
|
||||
@ -181,8 +213,12 @@ namespace Tesses::CrossLang {
|
||||
dict->DeclareFunction(gc,"ReadLine","Reads line from stdin",{},Console_ReadLine);
|
||||
dict->DeclareFunction(gc,"Write","Write text \"text\" to stdout",{"text"},Console_Write);
|
||||
dict->DeclareFunction(gc,"WriteLine","Write text \"text\" to stdout with new line",{"text"},Console_WriteLine);
|
||||
dict->DeclareFunction(gc,"Error", "Write text \"error\" to stderr",{"error"},Console_Error);
|
||||
dict->DeclareFunction(gc,"ErrorLine","Write text \"error\" to stderr",{"error"},Console_ErrorLine);
|
||||
dict->DeclareFunction(gc,"Fatal","Stop the program with an optional error message",{"$text"},Console_Fatal);
|
||||
|
||||
dict->DeclareFunction(gc,"getIn","Get stdin Stream",{},Console_getIn);
|
||||
dict->DeclareFunction(gc,"getOut","Get stdout Stream",{},Console_getOut);
|
||||
dict->DeclareFunction(gc,"getError", "Get stderr Stream",{},Console_getError);
|
||||
gc->BarrierBegin();
|
||||
env->DeclareVariable("Console", dict);
|
||||
gc->BarrierEnd();
|
||||
|
||||
@ -1,59 +1,27 @@
|
||||
#include "CrossLang.hpp"
|
||||
|
||||
#include <TessesFramework/TessesFrameworkFeatures.h>
|
||||
#if defined(TESSESFRAMEWORK_ENABLE_MBED)
|
||||
#include <iostream>
|
||||
|
||||
#include <mbedtls/sha1.h>
|
||||
#include <mbedtls/sha256.h>
|
||||
#include <mbedtls/sha512.h>
|
||||
#include <mbedtls/base64.h>
|
||||
#include <mbedtls/pkcs5.h>
|
||||
#include <mbedtls/entropy.h>
|
||||
#include <mbedtls/ctr_drbg.h>
|
||||
#include <mbedtls/x509.h>
|
||||
#include <mbedtls/ssl.h>
|
||||
#include <mbedtls/net_sockets.h>
|
||||
#include <mbedtls/error.h>
|
||||
#include <cstring>
|
||||
#endif
|
||||
using namespace Tesses::Framework::Crypto;
|
||||
|
||||
namespace Tesses::CrossLang
|
||||
{
|
||||
#if defined(TESSESFRAMEWORK_ENABLE_MBED)
|
||||
static TObject Crypto_RandomBytes(GCList& ls, std::vector<TObject> args)
|
||||
static TObject Crypto_RandomBytes(GCList& ls, std::vector<TObject> args)
|
||||
{
|
||||
int64_t size;
|
||||
std::string personalStr;
|
||||
if(GetArgument(args,0,size) && GetArgument(args,1,personalStr))
|
||||
{
|
||||
mbedtls_entropy_context entropy;
|
||||
mbedtls_ctr_drbg_context ctr_drbg;
|
||||
|
||||
mbedtls_entropy_init(&entropy);
|
||||
mbedtls_ctr_drbg_init(&ctr_drbg);
|
||||
|
||||
int ret = mbedtls_ctr_drbg_seed(&ctr_drbg, mbedtls_entropy_func, &entropy, (const unsigned char *) personalStr.c_str(), personalStr.size());
|
||||
if(ret != 0)
|
||||
{
|
||||
mbedtls_ctr_drbg_free(&ctr_drbg);
|
||||
mbedtls_entropy_free(&entropy);
|
||||
return nullptr;
|
||||
}
|
||||
std::vector<uint8_t> bytes;
|
||||
bytes.resize((size_t)size);
|
||||
ret = mbedtls_ctr_drbg_random(&ctr_drbg, bytes.data(),bytes.size());
|
||||
if (ret != 0)
|
||||
if(RandomBytes(bytes,personalStr))
|
||||
{
|
||||
mbedtls_ctr_drbg_free(&ctr_drbg);
|
||||
mbedtls_entropy_free(&entropy);
|
||||
return nullptr;
|
||||
}
|
||||
mbedtls_ctr_drbg_free(&ctr_drbg);
|
||||
mbedtls_entropy_free(&entropy);
|
||||
TByteArray* ba = TByteArray::Create(ls);
|
||||
ba->data = bytes;
|
||||
return ba;
|
||||
auto ba = TByteArray::Create(ls);
|
||||
ba->data = bytes;
|
||||
return ba;
|
||||
}
|
||||
return nullptr;
|
||||
|
||||
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
@ -66,228 +34,45 @@ namespace Tesses::CrossLang
|
||||
int64_t shanum;
|
||||
if(GetArgument(args,0,pass) && GetArgumentHeap(args,1, bArraySalt) && GetArgument(args,2, itterations) && GetArgument(args,3,keylength) && GetArgument(args,4,shanum))
|
||||
{
|
||||
mbedtls_md_context_t ctx;
|
||||
mbedtls_md_init(&ctx);
|
||||
const mbedtls_md_info_t* info = NULL;
|
||||
ShaVersion version = VERSION_SHA384;
|
||||
|
||||
switch(shanum)
|
||||
{
|
||||
case 1:
|
||||
info = mbedtls_md_info_from_type(MBEDTLS_MD_SHA1);
|
||||
version = VERSION_SHA1;
|
||||
break;
|
||||
case 224:
|
||||
info = mbedtls_md_info_from_type(MBEDTLS_MD_SHA224);
|
||||
version = VERSION_SHA224;
|
||||
break;
|
||||
case 256:
|
||||
info = mbedtls_md_info_from_type(MBEDTLS_MD_SHA256);
|
||||
version = VERSION_SHA256;
|
||||
break;
|
||||
default:
|
||||
case 384:
|
||||
info = mbedtls_md_info_from_type(MBEDTLS_MD_SHA384);
|
||||
version = VERSION_SHA384;
|
||||
break;
|
||||
case 512:
|
||||
info = mbedtls_md_info_from_type(MBEDTLS_MD_SHA512);
|
||||
version = VERSION_SHA512;
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
mbedtls_md_setup(&ctx, info, 1);
|
||||
|
||||
std::vector<uint8_t> key;
|
||||
key.resize((size_t)keylength);
|
||||
|
||||
if(mbedtls_pkcs5_pbkdf2_hmac(&ctx, (const unsigned char*)pass.c_str(), pass.size(), bArraySalt->data.data(), bArraySalt->data.size(), (int)itterations,(uint32_t)key.size(),key.data()) == 0)
|
||||
|
||||
if(PBKDF2(key,pass,bArraySalt->data,(long)itterations,version))
|
||||
{
|
||||
auto ba = TByteArray::Create(ls);
|
||||
TByteArray* ba = TByteArray::Create(ls);
|
||||
ba->data = key;
|
||||
mbedtls_md_free(&ctx);
|
||||
return ba;
|
||||
}
|
||||
|
||||
mbedtls_md_free(&ctx);
|
||||
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
||||
static TObject Crypto_Sha1(GCList& ls, std::vector<TObject> args)
|
||||
{
|
||||
|
||||
TDictionary* dict = TDictionary::Create(ls);
|
||||
mbedtls_sha1_context* ctx = new mbedtls_sha1_context();
|
||||
mbedtls_sha1_init(ctx);
|
||||
mbedtls_sha1_starts(ctx);
|
||||
|
||||
TNative* native = TNative::Create(ls,ctx,[](void* _ctx)->void{
|
||||
if(_ctx == nullptr) return;
|
||||
mbedtls_sha1_context* ctx = (mbedtls_sha1_context*)_ctx;
|
||||
mbedtls_sha1_free(ctx);
|
||||
delete ctx;
|
||||
});
|
||||
ls.GetGC()->BarrierBegin();
|
||||
dict->SetValue("_native",native);
|
||||
ls.GetGC()->BarrierEnd();
|
||||
|
||||
dict->DeclareFunction(ls.GetGC(),"Update","Write more bytes",{"buffer","offset","size"},[native](GCList& ls2,std::vector<TObject> args2)->TObject{
|
||||
if(!native->GetDestroyed() && args2.size() == 3 && std::holds_alternative<THeapObjectHolder>(args2[0]) && std::holds_alternative<int64_t>(args2[1]) && std::holds_alternative<int64_t>(args2[2]))
|
||||
{
|
||||
auto buffer = dynamic_cast<TByteArray*>(std::get<THeapObjectHolder>(args2[0]).obj);
|
||||
auto offset = (size_t)std::get<int64_t>(args2[1]);
|
||||
auto len = (size_t)std::get<int64_t>(args2[2]);
|
||||
if(buffer != nullptr && (len+offset) < buffer->data.size())
|
||||
{
|
||||
|
||||
mbedtls_sha1_update((mbedtls_sha1_context*)native->GetPointer(),buffer->data.data() + offset, len);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
});
|
||||
|
||||
dict->DeclareFunction(ls.GetGC(),"Finish","Get hash",{},[native](GCList& ls2,std::vector<TObject> args2)->TObject{
|
||||
if(!native->GetDestroyed())
|
||||
{
|
||||
TByteArray* ba = TByteArray::Create(ls2);
|
||||
ba->data.resize(20);
|
||||
|
||||
mbedtls_sha1_finish((mbedtls_sha1_context*)native->GetPointer(),ba->data.data());
|
||||
|
||||
return ba;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
|
||||
|
||||
/*
|
||||
|
||||
|
||||
mbedtls_sha1_update(&ctx, (const unsigned char*)"Demi Lovato", 11);
|
||||
unsigned char sha1[20];
|
||||
mbedtls_sha1_finish(&ctx,sha1);
|
||||
|
||||
for(int i = 0;i<20;i++)
|
||||
{
|
||||
printf("%02x", sha1[i]);
|
||||
}
|
||||
printf("\n");
|
||||
|
||||
mbedtls_sha1_free(&ctx);*/
|
||||
|
||||
return dict;
|
||||
}
|
||||
static TObject Crypto_Sha256(GCList& ls, std::vector<TObject> args)
|
||||
{
|
||||
|
||||
bool is224=false;
|
||||
|
||||
if(args.size() == 1 && std::holds_alternative<bool>(args[0]))
|
||||
{
|
||||
is224 = std::get<bool>(args[1]);
|
||||
}
|
||||
|
||||
TDictionary* dict = TDictionary::Create(ls);
|
||||
mbedtls_sha256_context* ctx = new mbedtls_sha256_context();
|
||||
mbedtls_sha256_init(ctx);
|
||||
mbedtls_sha256_starts(ctx,is224 ? 1 : 0);
|
||||
|
||||
|
||||
TNative* native = TNative::Create(ls,ctx,[](void* _ctx)->void{
|
||||
if(_ctx == nullptr) return;
|
||||
mbedtls_sha256_context* ctx = (mbedtls_sha256_context*)_ctx;
|
||||
mbedtls_sha256_free(ctx);
|
||||
delete ctx;
|
||||
});
|
||||
ls.GetGC()->BarrierBegin();
|
||||
dict->SetValue("_native",native);
|
||||
ls.GetGC()->BarrierEnd();
|
||||
|
||||
dict->DeclareFunction(ls.GetGC(),"Update","Write more bytes",{"buffer","offset","size"},[native](GCList& ls2,std::vector<TObject> args2)->TObject{
|
||||
if(!native->GetDestroyed() && args2.size() == 3 && std::holds_alternative<THeapObjectHolder>(args2[0]) && std::holds_alternative<int64_t>(args2[1]) && std::holds_alternative<int64_t>(args2[2]))
|
||||
{
|
||||
auto buffer = dynamic_cast<TByteArray*>(std::get<THeapObjectHolder>(args2[0]).obj);
|
||||
auto offset = (size_t)std::get<int64_t>(args2[1]);
|
||||
auto len = (size_t)std::get<int64_t>(args2[2]);
|
||||
if(buffer != nullptr && (len+offset) < buffer->data.size())
|
||||
{
|
||||
|
||||
mbedtls_sha256_update((mbedtls_sha256_context*)native->GetPointer(),buffer->data.data() + offset, len);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
});
|
||||
|
||||
dict->DeclareFunction(ls.GetGC(),"Finish","Get hash",{},[native](GCList& ls2,std::vector<TObject> args2)->TObject{
|
||||
if(!native->GetDestroyed())
|
||||
{
|
||||
TByteArray* ba = TByteArray::Create(ls2);
|
||||
ba->data.resize(32);
|
||||
|
||||
mbedtls_sha256_finish((mbedtls_sha256_context*)native->GetPointer(),ba->data.data());
|
||||
|
||||
return ba;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
|
||||
|
||||
|
||||
return dict;
|
||||
}
|
||||
static TObject Crypto_Sha512(GCList& ls, std::vector<TObject> args)
|
||||
{
|
||||
|
||||
bool is384=false;
|
||||
|
||||
if(args.size() == 1 && std::holds_alternative<bool>(args[0]))
|
||||
{
|
||||
is384 = std::get<bool>(args[1]);
|
||||
}
|
||||
|
||||
TDictionary* dict = TDictionary::Create(ls);
|
||||
mbedtls_sha512_context* ctx = new mbedtls_sha512_context();
|
||||
mbedtls_sha512_init(ctx);
|
||||
mbedtls_sha512_starts(ctx,is384 ? 1 : 0);
|
||||
|
||||
TNative* native = TNative::Create(ls,ctx,[](void* _ctx)->void{
|
||||
if(_ctx == nullptr) return;
|
||||
mbedtls_sha512_context* ctx = (mbedtls_sha512_context*)_ctx;
|
||||
mbedtls_sha512_free(ctx);
|
||||
delete ctx;
|
||||
});
|
||||
ls.GetGC()->BarrierBegin();
|
||||
dict->SetValue("_native",native);
|
||||
ls.GetGC()->BarrierEnd();
|
||||
|
||||
dict->DeclareFunction(ls.GetGC(),"Update","Write more bytes",{"buffer","offset","size"},[native](GCList& ls2,std::vector<TObject> args2)->TObject{
|
||||
if(!native->GetDestroyed() && args2.size() == 3 && std::holds_alternative<THeapObjectHolder>(args2[0]) && std::holds_alternative<int64_t>(args2[1]) && std::holds_alternative<int64_t>(args2[2]))
|
||||
{
|
||||
auto buffer = dynamic_cast<TByteArray*>(std::get<THeapObjectHolder>(args2[0]).obj);
|
||||
auto offset = (size_t)std::get<int64_t>(args2[1]);
|
||||
auto len = (size_t)std::get<int64_t>(args2[2]);
|
||||
if(buffer != nullptr && (len+offset) < buffer->data.size())
|
||||
{
|
||||
|
||||
mbedtls_sha512_update((mbedtls_sha512_context*)native->GetPointer(),buffer->data.data() + offset, len);
|
||||
}
|
||||
}
|
||||
return Undefined();
|
||||
});
|
||||
|
||||
dict->DeclareFunction(ls.GetGC(),"Finish","Get hash",{},[native](GCList& ls2,std::vector<TObject> args2)->TObject{
|
||||
if(!native->GetDestroyed())
|
||||
{
|
||||
TByteArray* ba = TByteArray::Create(ls2);
|
||||
ba->data.resize(64);
|
||||
|
||||
mbedtls_sha512_finish((mbedtls_sha512_context*)native->GetPointer(),ba->data.data());
|
||||
|
||||
return ba;
|
||||
}
|
||||
return Undefined();
|
||||
});
|
||||
|
||||
|
||||
|
||||
return dict;
|
||||
}
|
||||
static TObject Crypto_Base64Encode(GCList& ls, std::vector<TObject> args)
|
||||
{
|
||||
TByteArray* byteArray;
|
||||
@ -313,26 +98,22 @@ namespace Tesses::CrossLang
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
#endif
|
||||
void TStd::RegisterCrypto(GC* gc,TRootEnvironment* env)
|
||||
{
|
||||
|
||||
env->permissions.canRegisterCrypto=true;
|
||||
#if defined(TESSESFRAMEWORK_ENABLE_MBED)
|
||||
|
||||
if(!HaveCrypto()) return;
|
||||
GCList ls(gc);
|
||||
TDictionary* dict = TDictionary::Create(ls);
|
||||
dict->DeclareFunction(gc, "PBKDF2","Hash passwords with PBKDF2",{"pass","salt","itterations","keylen","shanum"},Crypto_PBKDF2);
|
||||
dict->DeclareFunction(gc, "RandomBytes","Create bytearray but with random bytes in it instead of zeros (this uses mbedtls by the way)",{"byteCount","personalString"},Crypto_RandomBytes);
|
||||
dict->DeclareFunction(gc, "Sha1","Sha1 Algorithm (needed for WebSocket handshake/BitTorrent etc) (don't use unless you have no other choice)",{},Crypto_Sha1);
|
||||
dict->DeclareFunction(gc, "Sha256","Sha256 Algorithm",{"$is224"},Crypto_Sha256);
|
||||
dict->DeclareFunction(gc, "Sha512","Sha512 Algorithm",{"$is384"},Crypto_Sha512);
|
||||
|
||||
dict->DeclareFunction(gc, "Base64Encode","Base64 encode",{"data"},Crypto_Base64Encode);
|
||||
dict->DeclareFunction(gc, "Base64Decode","Base64 decode",{"str"},Crypto_Base64Decode);
|
||||
gc->BarrierBegin();
|
||||
env->DeclareVariable("Crypto", dict);
|
||||
gc->BarrierEnd();
|
||||
|
||||
#endif
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@ -46,7 +46,8 @@ namespace Tesses::CrossLang
|
||||
using namespace Tesses::Framework::Filesystem;
|
||||
using namespace Tesses::Framework::Http;
|
||||
LocalFilesystem lfs;
|
||||
if(!realPath.relative) return realPath;
|
||||
if(!realPath.relative) return realPath.MakeAbsolute();
|
||||
if(lfs.FileExists(realPath)) return realPath.MakeAbsolute();
|
||||
const char* path = std::getenv("PATH");
|
||||
#if defined(_WIN32)
|
||||
const char* pathext = std::getenv("PATHEXT");
|
||||
@ -61,7 +62,7 @@ namespace Tesses::CrossLang
|
||||
if(lfs.FileExists(newPath)) return newPath;
|
||||
}
|
||||
}
|
||||
return realPath.RelativeCurrentDirectory();
|
||||
return realPath;
|
||||
#else
|
||||
|
||||
auto pathParts = HttpUtils::SplitString(path,":");
|
||||
@ -70,7 +71,7 @@ namespace Tesses::CrossLang
|
||||
auto newPath = lfs.SystemToVFSPath(item) / realPath;
|
||||
if(lfs.FileExists(newPath)) return newPath;
|
||||
}
|
||||
return realPath.RelativeCurrentDirectory();
|
||||
return realPath.MakeAbsolute();
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@ -239,6 +239,15 @@ namespace Tesses::CrossLang
|
||||
ctx->WithSingleHeader(key,value);
|
||||
return dict;
|
||||
});
|
||||
|
||||
dict->DeclareFunction(gc,"SendStream","Send stream",{"strm"},[ctx,dict](Tesses::CrossLang::GCList &ls2, std::vector<Tesses::CrossLang::TObject> args2)->TObject{
|
||||
TStreamHeapObject* strmHeapObj;
|
||||
if(GetArgumentHeap(args2,0,strmHeapObj))
|
||||
{
|
||||
ctx->SendStream(strmHeapObj->stream);
|
||||
}
|
||||
return nullptr;
|
||||
});
|
||||
dict->DeclareFunction(gc,"SendBytes","Send bytes",{"ba"},[ctx,dict](Tesses::CrossLang::GCList &ls2, std::vector<Tesses::CrossLang::TObject> args2)->TObject{
|
||||
TByteArray* ba;
|
||||
if(GetArgumentHeap(args2,0,ba))
|
||||
|
||||
@ -468,6 +468,14 @@ namespace Tesses::CrossLang
|
||||
return TVMVersion(ba->data.data()+o);
|
||||
}
|
||||
return nullptr;
|
||||
})),
|
||||
TDItem("FromLong", TExternalMethod::Create(ls, "Create from long",{"longBasedVersion"},[](GCList& ls, std::vector<TObject> args)->TObject {
|
||||
int64_t num;
|
||||
if(GetArgument(args,0,num))
|
||||
{
|
||||
return TVMVersion((uint64_t)num);
|
||||
}
|
||||
return nullptr;
|
||||
}))
|
||||
}));
|
||||
env->DeclareVariable("InvokeMethod",MethodInvoker());
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
|
||||
#include "CrossLang.hpp"
|
||||
#if defined(CROSSLANG_ENABLE_TIME)
|
||||
#if defined(_WIN32)
|
||||
#include <windows.h>
|
||||
|
||||
@ -10,10 +11,12 @@
|
||||
#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)
|
||||
@ -135,6 +138,53 @@ namespace Tesses::CrossLang
|
||||
|
||||
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;
|
||||
@ -166,9 +216,10 @@ namespace Tesses::CrossLang
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
#endif
|
||||
void TStd::RegisterTime(GC* gc,TRootEnvironment* env)
|
||||
{
|
||||
|
||||
#if defined(CROSSLANG_ENABLE_TIME)
|
||||
|
||||
|
||||
env->permissions.canRegisterTime=true;
|
||||
@ -178,7 +229,9 @@ namespace Tesses::CrossLang
|
||||
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));
|
||||
@ -190,5 +243,6 @@ namespace Tesses::CrossLang
|
||||
env->DeclareVariable("Time", dict);
|
||||
|
||||
gc->BarrierEnd();
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@ -317,6 +317,7 @@ namespace Tesses::CrossLang
|
||||
dict->DeclareFunction(gc, "getRuntimeVersion","Get the runtime version",{},[](GCList& ls,std::vector<TObject> args)->TObject {
|
||||
return TVMVersion(TVM_MAJOR,TVM_MINOR,TVM_PATCH,TVM_BUILD,TVM_VERSIONSTAGE);
|
||||
});
|
||||
|
||||
gc->BarrierBegin();
|
||||
env->DeclareVariable("VM", dict);
|
||||
gc->BarrierEnd();
|
||||
|
||||
Reference in New Issue
Block a user