First commit
This commit is contained in:
189
src/runtime_methods/console.cpp
Normal file
189
src/runtime_methods/console.cpp
Normal file
@ -0,0 +1,189 @@
|
||||
#include "CrossLang.hpp"
|
||||
#include <iostream>
|
||||
|
||||
#if defined(GEKKO)
|
||||
#undef CROSSLANG_ENABLE_TERMIOS
|
||||
#endif
|
||||
|
||||
#ifdef CROSSLANG_ENABLE_TERMIOS
|
||||
#include <termios.h>
|
||||
#endif
|
||||
namespace Tesses::CrossLang {
|
||||
#ifdef CROSSLANG_ENABLE_TERMIOS
|
||||
struct termios orig_termios;
|
||||
static void disableRawMode()
|
||||
{
|
||||
tcsetattr(STDIN_FILENO, TCSAFLUSH, &orig_termios);
|
||||
}
|
||||
#endif
|
||||
TObject Console_getEcho(GCList& ls, std::vector<TObject> args)
|
||||
{
|
||||
#ifdef CROSSLANG_ENABLE_TERMIOS
|
||||
struct termios raw;
|
||||
tcgetattr(STDIN_FILENO, &raw);
|
||||
return (raw.c_lflag & ECHO) > 0;
|
||||
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
TObject Console_setEcho(GCList& ls, std::vector<TObject> args)
|
||||
{
|
||||
if(args.size() == 1 && std::holds_alternative<bool>(args[0]))
|
||||
{
|
||||
bool cooked = std::get<bool>(args[0]);
|
||||
#ifdef CROSSLANG_ENABLE_TERMIOS
|
||||
struct termios raw;
|
||||
tcgetattr(STDIN_FILENO, &raw);
|
||||
if(cooked)
|
||||
{
|
||||
raw.c_lflag |= ECHO;
|
||||
}
|
||||
else
|
||||
{
|
||||
raw.c_lflag &= ~(ECHO);
|
||||
}
|
||||
|
||||
tcsetattr(STDIN_FILENO, TCSAFLUSH, &raw);
|
||||
|
||||
#endif
|
||||
return cooked;
|
||||
}
|
||||
return Undefined();
|
||||
}
|
||||
TObject Console_getCanonical(GCList& ls, std::vector<TObject> args)
|
||||
{
|
||||
#ifdef CROSSLANG_ENABLE_TERMIOS
|
||||
struct termios raw;
|
||||
tcgetattr(STDIN_FILENO, &raw);
|
||||
return (raw.c_lflag & ICANON) > 0;
|
||||
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
TObject Console_setCanonical(GCList& ls, std::vector<TObject> args)
|
||||
{
|
||||
if(args.size() == 1 && std::holds_alternative<bool>(args[0]))
|
||||
{
|
||||
bool cooked = std::get<bool>(args[0]);
|
||||
#ifdef CROSSLANG_ENABLE_TERMIOS
|
||||
struct termios raw;
|
||||
tcgetattr(STDIN_FILENO, &raw);
|
||||
if(cooked)
|
||||
{
|
||||
raw.c_lflag |= ICANON;
|
||||
}
|
||||
else
|
||||
{
|
||||
raw.c_lflag &= ~(ICANON);
|
||||
}
|
||||
|
||||
tcsetattr(STDIN_FILENO, TCSAFLUSH, &raw);
|
||||
|
||||
#endif
|
||||
return cooked;
|
||||
}
|
||||
return Undefined();
|
||||
}
|
||||
TObject Console_getSignals(GCList& ls, std::vector<TObject> args)
|
||||
{
|
||||
#ifdef CROSSLANG_ENABLE_TERMIOS
|
||||
struct termios raw;
|
||||
tcgetattr(STDIN_FILENO, &raw);
|
||||
return (raw.c_lflag & ISIG) > 0;
|
||||
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
TObject Console_setSignals(GCList& ls, std::vector<TObject> args)
|
||||
{
|
||||
if(args.size() == 1 && std::holds_alternative<bool>(args[0]))
|
||||
{
|
||||
bool cooked = std::get<bool>(args[0]);
|
||||
#ifdef CROSSLANG_ENABLE_TERMIOS
|
||||
struct termios raw;
|
||||
tcgetattr(STDIN_FILENO, &raw);
|
||||
if(cooked)
|
||||
{
|
||||
raw.c_lflag |= ISIG;
|
||||
}
|
||||
else
|
||||
{
|
||||
raw.c_lflag &= ~(ISIG);
|
||||
}
|
||||
|
||||
tcsetattr(STDIN_FILENO, TCSAFLUSH, &raw);
|
||||
|
||||
#endif
|
||||
return cooked;
|
||||
}
|
||||
return Undefined();
|
||||
}
|
||||
|
||||
TObject Console_Read(GCList& ls, std::vector<TObject> args)
|
||||
{
|
||||
uint8_t byte;
|
||||
std::cin.read((char*)&byte,1);
|
||||
return std::cin.eof() ? (int64_t)-1 : (int64_t)byte;
|
||||
}
|
||||
TObject Console_ReadLine(GCList& ls, std::vector<TObject> args)
|
||||
{
|
||||
std::string str;
|
||||
std::getline(std::cin,str);
|
||||
return str;
|
||||
}
|
||||
TObject Console_Write(GCList& ls, std::vector<TObject> args)
|
||||
{
|
||||
if(args.size() < 1)
|
||||
{
|
||||
return Undefined();
|
||||
}
|
||||
std::cout << ToString(ls.GetGC(),args[0]);
|
||||
return Undefined();
|
||||
}
|
||||
TObject Console_Fatal(GCList& ls, std::vector<TObject> args)
|
||||
{
|
||||
if(args.size() < 1)
|
||||
{
|
||||
std::cout << "FATAL: <NO MESSAGE>" << std::endl;
|
||||
exit(1);
|
||||
}
|
||||
std::cout << "FATAL: " << ToString(ls.GetGC(),args[0]) << std::endl;
|
||||
exit(1);
|
||||
}
|
||||
TObject Console_WriteLine(GCList& ls, std::vector<TObject> args)
|
||||
{
|
||||
if(args.size() < 1)
|
||||
{
|
||||
std::cout << "\n";
|
||||
return Undefined();
|
||||
}
|
||||
std::cout << ToString(ls.GetGC(),args[0]) << "\n";
|
||||
return Undefined();
|
||||
}
|
||||
void TStd::RegisterConsole(GC* gc,TRootEnvironment* env)
|
||||
{
|
||||
env->permissions.canRegisterConsole=true;
|
||||
#ifdef CROSSLANG_ENABLE_TERMIOS
|
||||
tcgetattr(STDIN_FILENO, &orig_termios);
|
||||
atexit(disableRawMode);
|
||||
#endif
|
||||
GCList ls(gc);
|
||||
TDictionary* dict = TDictionary::Create(ls);
|
||||
dict->DeclareFunction(gc,"getEcho","Get whether terminal is echoing characters read",{},Console_getEcho);
|
||||
dict->DeclareFunction(gc,"setEcho","Set whether terminal is echoing characters read",{"flag"},Console_setEcho);
|
||||
dict->DeclareFunction(gc,"getCanonical","Get whether terminal is buffering line by line (true) or byte by byte (false)",{},Console_getCanonical);
|
||||
dict->DeclareFunction(gc,"setCanonical","Set whether terminal is buffering line by line (true) or byte by byte (false)",{"flag"},Console_setCanonical);
|
||||
dict->DeclareFunction(gc,"getSignals","Get whether terminal is sending signals for CTRL+C (true) or via read (false)",{},Console_getSignals);
|
||||
dict->DeclareFunction(gc,"setSignals","Set whether terminal is sending signals for CTRL+C (true) or via read (false)",{"flag"},Console_setSignals);
|
||||
|
||||
dict->DeclareFunction(gc,"Read", "Reads a byte from stdin",{},Console_Read);
|
||||
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,"Fatal","Stop the program with an optional error message",{"$text"},Console_Fatal);
|
||||
|
||||
gc->BarrierBegin();
|
||||
env->DeclareVariable("Console", dict);
|
||||
gc->BarrierEnd();
|
||||
}
|
||||
}
|
||||
811
src/runtime_methods/crypto.cpp
Normal file
811
src/runtime_methods/crypto.cpp
Normal file
@ -0,0 +1,811 @@
|
||||
#include "CrossLang.hpp"
|
||||
#if defined(CROSSLANG_ENABLE_MBED)
|
||||
#include <iostream>
|
||||
|
||||
#include <mbedtls/sha1.h>
|
||||
#include <mbedtls/sha256.h>
|
||||
#include <mbedtls/sha512.h>
|
||||
#include <mbedtls/base64.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
|
||||
|
||||
namespace Tesses::CrossLang
|
||||
{
|
||||
#if defined(CROSSLANG_ENABLE_MBED)
|
||||
static void my_debug(void *ctx, int level,
|
||||
const char *file, int line,
|
||||
const char *str)
|
||||
{
|
||||
((void) level);
|
||||
|
||||
fprintf(stderr, "%s:%04d: %s", file, line, str);
|
||||
fflush(stderr);
|
||||
}
|
||||
class TlsClientStream {
|
||||
GCList* ls;
|
||||
TCallable* read;
|
||||
TCallable* write;
|
||||
TCallable* close;
|
||||
TByteArray* readBuffer;
|
||||
TByteArray* writeBuffer;
|
||||
mbedtls_entropy_context entropy;
|
||||
mbedtls_ctr_drbg_context ctr_drbg;
|
||||
mbedtls_ssl_context ssl;
|
||||
mbedtls_ssl_config conf;
|
||||
mbedtls_x509_crt cachain;
|
||||
|
||||
|
||||
static int strm_send(void* ctx,const unsigned char* buf,size_t len)
|
||||
{
|
||||
TlsClientStream* strm = static_cast<TlsClientStream*>(ctx);
|
||||
strm->writeBuffer->data.resize(len);
|
||||
memcpy(strm->writeBuffer->data.data(),buf,len);
|
||||
|
||||
auto res = strm->write->Call(*strm->ls,{strm->writeBuffer});
|
||||
if(std::holds_alternative<int64_t>(res))
|
||||
{
|
||||
auto num = std::get<int64_t>(res);
|
||||
return (int)num;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
static int strm_recv(void* ctx,unsigned char* buf,size_t len)
|
||||
{
|
||||
TlsClientStream* strm = static_cast<TlsClientStream*>(ctx);
|
||||
strm->readBuffer->data.resize(len);
|
||||
|
||||
auto res = strm->read->Call(*strm->ls,{strm->readBuffer});
|
||||
if(std::holds_alternative<int64_t>(res))
|
||||
{
|
||||
auto num = std::get<int64_t>(res);
|
||||
if(num < 0) return (int)num;
|
||||
size_t read = (size_t)num;
|
||||
if(read > len) read = len;
|
||||
memcpy(buf,strm->readBuffer->data.data(), read);
|
||||
return read;
|
||||
}
|
||||
return -1;
|
||||
|
||||
//return (int)strm->Read((uint8_t*)buf,len);
|
||||
}
|
||||
public:
|
||||
void Close()
|
||||
{
|
||||
close->Call(*ls,{});
|
||||
}
|
||||
bool success=false;
|
||||
bool isDoneReading = false;
|
||||
int64_t Read(uint8_t* buffer, size_t len)
|
||||
{
|
||||
if(isDoneReading) return 0;
|
||||
int64_t r = (int64_t)mbedtls_ssl_read(&ssl,buffer,len);
|
||||
if(r == 0) isDoneReading=true;
|
||||
if(r == -30848)
|
||||
{
|
||||
isDoneReading = true;
|
||||
return 0;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
int64_t Write(uint8_t* buffer, size_t len)
|
||||
{
|
||||
return (int64_t)mbedtls_ssl_write(&ssl,buffer,len);
|
||||
}
|
||||
|
||||
TlsClientStream(GC* gc,std::string domain,std::string chain,bool verify, TCallable* read, TCallable* write, TCallable* close)
|
||||
{
|
||||
ls = new GCList(gc);
|
||||
ls->Add(read);
|
||||
ls->Add(write);
|
||||
ls->Add(close);
|
||||
this->read = read;
|
||||
this->write = write;
|
||||
this->close = close;
|
||||
readBuffer = TByteArray::Create(ls);
|
||||
writeBuffer = TByteArray::Create(ls);
|
||||
|
||||
mbedtls_ssl_init(&ssl);
|
||||
mbedtls_ssl_config_init(&conf);
|
||||
mbedtls_x509_crt_init(&cachain);
|
||||
mbedtls_ctr_drbg_init(&ctr_drbg);
|
||||
mbedtls_entropy_init(&entropy);
|
||||
|
||||
const char* pers = "CrossLangTLS";
|
||||
|
||||
int ret=0;
|
||||
|
||||
|
||||
|
||||
#if defined(MBEDTLS_USE_PSA_CRYPTO)
|
||||
psa_status_t status = psa_crypto_init();
|
||||
if (status != PSA_SUCCESS) {
|
||||
mbedtls_fprintf(stderr, "Failed to initialize PSA Crypto implementation: %d\n",
|
||||
(int) status);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
if ((ret = mbedtls_ctr_drbg_seed(&ctr_drbg, mbedtls_entropy_func, &entropy,
|
||||
(const unsigned char *) pers,
|
||||
strlen(pers))) != 0)
|
||||
{
|
||||
printf("FAILED mbedtls_ctr_drbg_seed\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if(ret != 0) { printf("FAILED mbedtls_x509_crt_parse cert %i\n",ret); return;}
|
||||
ret = mbedtls_x509_crt_parse(&cachain, (const unsigned char *) chain.c_str(),
|
||||
chain.size()+1);
|
||||
|
||||
if(ret != 0) {printf("FAILED mbedtls_x509_crt_parse chain %i\n",ret); return;}
|
||||
|
||||
|
||||
|
||||
if((ret = mbedtls_ssl_config_defaults(&conf,
|
||||
MBEDTLS_SSL_IS_CLIENT,
|
||||
MBEDTLS_SSL_TRANSPORT_STREAM,
|
||||
MBEDTLS_SSL_PRESET_DEFAULT)) != 0)
|
||||
{
|
||||
char buffer[100];
|
||||
mbedtls_strerror(ret,buffer,sizeof(buffer));
|
||||
printf("FAILED mbedtls_ssl_conf_defaults %s\n",buffer);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
mbedtls_ssl_conf_rng(&conf, mbedtls_ctr_drbg_random, &ctr_drbg);
|
||||
mbedtls_ssl_conf_dbg(&conf,my_debug,stdout);
|
||||
/* #if defined(MBEDTLS_SSL_CACHE_C)
|
||||
mbedtls_ssl_conf_session_cache(&conf, &cache,
|
||||
mbedtls_ssl_cache_get,
|
||||
mbedtls_ssl_cache_set);
|
||||
#endif*/
|
||||
mbedtls_ssl_conf_authmode(&conf, verify ? MBEDTLS_SSL_VERIFY_REQUIRED: MBEDTLS_SSL_VERIFY_OPTIONAL);
|
||||
mbedtls_ssl_conf_ca_chain(&conf, &cachain, NULL);
|
||||
|
||||
|
||||
mbedtls_ssl_set_bio(&ssl, static_cast<void*>(this),strm_send,strm_recv, NULL);
|
||||
if((ret=mbedtls_ssl_setup(&ssl,&conf) != 0))
|
||||
{
|
||||
printf("FAILED mbedtls_ssl_setup %i\n",ret);
|
||||
return;
|
||||
}
|
||||
if((ret=mbedtls_ssl_set_hostname(&ssl,domain.c_str()) != 0))
|
||||
{
|
||||
printf("FAILED mbedtls_ssl_set_hostname %i\n",ret);
|
||||
return;
|
||||
}
|
||||
if((ret = mbedtls_ssl_handshake(&ssl)) != 0)
|
||||
{
|
||||
char buffer[100];
|
||||
mbedtls_strerror(ret,buffer,sizeof(buffer));
|
||||
printf("FAILED mbedtls_ssl_handshake %s\n",buffer);
|
||||
return;
|
||||
}
|
||||
uint32_t flags;
|
||||
if ((flags = mbedtls_ssl_get_verify_result(&ssl)) != 0) {
|
||||
#if !defined(MBEDTLS_X509_REMOVE_INFO)
|
||||
char vrfy_buf[512];
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
#if !defined(MBEDTLS_X509_REMOVE_INFO)
|
||||
mbedtls_x509_crt_verify_info(vrfy_buf, sizeof(vrfy_buf), " ! ", flags);
|
||||
|
||||
|
||||
#endif
|
||||
if(verify)
|
||||
return;
|
||||
}
|
||||
|
||||
success=true;
|
||||
|
||||
}
|
||||
~TlsClientStream()
|
||||
{
|
||||
|
||||
mbedtls_ctr_drbg_free(&ctr_drbg);
|
||||
mbedtls_entropy_free(&entropy);
|
||||
mbedtls_ssl_config_free(&conf);
|
||||
|
||||
#if defined(MBEDTLS_USE_PSA_CRYPTO)
|
||||
mbedtls_psa_crypto_free();
|
||||
#endif /* MBEDTLS_USE_PSA_CRYPTO */
|
||||
|
||||
delete ls;
|
||||
}
|
||||
};
|
||||
|
||||
class TlsServerStream {
|
||||
GCList* ls;
|
||||
TCallable* read;
|
||||
TCallable* write;
|
||||
TCallable* close;
|
||||
TByteArray* readBuffer;
|
||||
TByteArray* writeBuffer;
|
||||
mbedtls_entropy_context entropy;
|
||||
mbedtls_ctr_drbg_context ctr_drbg;
|
||||
mbedtls_ssl_context ssl;
|
||||
mbedtls_ssl_config conf;
|
||||
mbedtls_x509_crt srvcert;
|
||||
mbedtls_x509_crt cachain;
|
||||
mbedtls_pk_context pkey;
|
||||
|
||||
|
||||
|
||||
static int strm_send(void* ctx,const unsigned char* buf,size_t len)
|
||||
{
|
||||
TlsServerStream* strm = static_cast<TlsServerStream*>(ctx);
|
||||
strm->writeBuffer->data.resize(len);
|
||||
memcpy(strm->writeBuffer->data.data(),buf,len);
|
||||
|
||||
auto res = strm->write->Call(*strm->ls,{strm->writeBuffer});
|
||||
if(std::holds_alternative<int64_t>(res))
|
||||
{
|
||||
auto num = std::get<int64_t>(res);
|
||||
|
||||
return (int)num;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
static int strm_recv(void* ctx,unsigned char* buf,size_t len)
|
||||
{
|
||||
TlsServerStream* strm = static_cast<TlsServerStream*>(ctx);
|
||||
strm->readBuffer->data.resize(len);
|
||||
|
||||
auto res = strm->read->Call(*strm->ls,{strm->readBuffer});
|
||||
if(std::holds_alternative<int64_t>(res))
|
||||
{
|
||||
auto num = std::get<int64_t>(res);
|
||||
if(num < 0) return num;
|
||||
size_t read = (size_t)num;
|
||||
if(read > len) read = len;
|
||||
memcpy(buf,strm->readBuffer->data.data(), read);
|
||||
return read;
|
||||
}
|
||||
return -1;
|
||||
|
||||
//return (int)strm->Read((uint8_t*)buf,len);
|
||||
}
|
||||
public:
|
||||
void Close()
|
||||
{
|
||||
close->Call(*ls,{});
|
||||
}
|
||||
bool success=false;
|
||||
bool isDoneReading =false;
|
||||
int64_t Read(uint8_t* buffer, size_t len)
|
||||
{
|
||||
if(isDoneReading) return 0;
|
||||
int64_t r = (int64_t)mbedtls_ssl_read(&ssl,buffer,len);
|
||||
if(r == 0) isDoneReading=true;
|
||||
if(r == -30848)
|
||||
{
|
||||
isDoneReading = true;
|
||||
return 0;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
int64_t Write(uint8_t* buffer, size_t len)
|
||||
{
|
||||
return mbedtls_ssl_write(&ssl,buffer,len);
|
||||
}
|
||||
|
||||
TlsServerStream(GC* gc,std::string cert, std::string chain, std::string privkey, TCallable* read, TCallable* write, TCallable* close)
|
||||
{
|
||||
ls = new GCList(gc);
|
||||
ls->Add(read);
|
||||
ls->Add(write);
|
||||
ls->Add(close);
|
||||
readBuffer = TByteArray::Create(ls);
|
||||
writeBuffer = TByteArray::Create(ls);
|
||||
this->read = read;
|
||||
this->write = write;
|
||||
this->close = close;
|
||||
|
||||
mbedtls_ssl_init(&ssl);
|
||||
mbedtls_ssl_config_init(&conf);
|
||||
mbedtls_x509_crt_init(&srvcert);
|
||||
mbedtls_x509_crt_init(&cachain);
|
||||
mbedtls_ctr_drbg_init(&ctr_drbg);
|
||||
mbedtls_entropy_init(&entropy);
|
||||
mbedtls_pk_init(&pkey);
|
||||
|
||||
const char* pers = "CrossLangTLS";
|
||||
int ret=0;
|
||||
|
||||
|
||||
|
||||
#if defined(MBEDTLS_USE_PSA_CRYPTO)
|
||||
psa_status_t status = psa_crypto_init();
|
||||
if (status != PSA_SUCCESS) {
|
||||
mbedtls_fprintf(stderr, "Failed to initialize PSA Crypto implementation: %d\n",
|
||||
(int) status);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
if ((ret = mbedtls_ctr_drbg_seed(&ctr_drbg, mbedtls_entropy_func, &entropy,
|
||||
(const unsigned char *) pers,
|
||||
strlen(pers))) != 0)
|
||||
{
|
||||
printf("FAILED mbedtls_ctr_drbg_seed\n");
|
||||
return;
|
||||
}
|
||||
ret = mbedtls_x509_crt_parse(&srvcert, (const unsigned char *) cert.c_str(),
|
||||
cert.size()+1);
|
||||
if(ret != 0) { printf("FAILED mbedtls_x509_crt_parse cert %i\n",ret); return;}
|
||||
ret = mbedtls_x509_crt_parse(&cachain, (const unsigned char *) chain.c_str(),
|
||||
chain.size()+1);
|
||||
|
||||
if(ret != 0) {printf("FAILED mbedtls_x509_crt_parse chain %i\n",ret); return;}
|
||||
|
||||
|
||||
ret = mbedtls_pk_parse_key(&pkey, (const unsigned char *) privkey.c_str(),
|
||||
privkey.size()+1, NULL, 0);
|
||||
if(ret != 0) {printf("FAILED mbedtls_pk_parse_key %i\n",ret); return;}
|
||||
if((ret = mbedtls_ssl_config_defaults(&conf,
|
||||
MBEDTLS_SSL_IS_SERVER,
|
||||
MBEDTLS_SSL_TRANSPORT_STREAM,
|
||||
MBEDTLS_SSL_PRESET_DEFAULT)) != 0)
|
||||
{
|
||||
char buffer[100];
|
||||
mbedtls_strerror(ret,buffer,sizeof(buffer));
|
||||
printf("FAILED mbedtls_ssl_conf_defaults %s\n",buffer);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
mbedtls_ssl_conf_rng(&conf, mbedtls_ctr_drbg_random, &ctr_drbg);
|
||||
|
||||
/* #if defined(MBEDTLS_SSL_CACHE_C)
|
||||
mbedtls_ssl_conf_session_cache(&conf, &cache,
|
||||
mbedtls_ssl_cache_get,
|
||||
mbedtls_ssl_cache_set);
|
||||
#endif*/
|
||||
mbedtls_ssl_conf_own_cert(&conf,&srvcert,&pkey);
|
||||
mbedtls_ssl_conf_ca_chain(&conf, &cachain, NULL);
|
||||
|
||||
mbedtls_ssl_set_bio(&ssl, static_cast<void*>(this),strm_send,strm_recv, NULL);
|
||||
|
||||
if((ret=mbedtls_ssl_setup(&ssl,&conf) != 0))
|
||||
{
|
||||
printf("FAILED mbedtls_ssl_setup %i\n",ret);
|
||||
return;
|
||||
}
|
||||
|
||||
if((ret = mbedtls_ssl_handshake(&ssl)) != 0)
|
||||
{
|
||||
char buffer[100];
|
||||
mbedtls_strerror(ret,buffer,sizeof(buffer));
|
||||
printf("FAILED mbedtls_ssl_handshake %s\n",buffer);
|
||||
return;
|
||||
}
|
||||
|
||||
success=true;
|
||||
|
||||
}
|
||||
~TlsServerStream()
|
||||
{
|
||||
mbedtls_x509_crt_free(&srvcert);
|
||||
mbedtls_pk_free(&pkey);
|
||||
|
||||
mbedtls_ctr_drbg_free(&ctr_drbg);
|
||||
mbedtls_entropy_free(&entropy);
|
||||
mbedtls_ssl_config_free(&conf);
|
||||
|
||||
#if defined(MBEDTLS_USE_PSA_CRYPTO)
|
||||
mbedtls_psa_crypto_free();
|
||||
#endif /* MBEDTLS_USE_PSA_CRYPTO */
|
||||
|
||||
delete ls;
|
||||
}
|
||||
};
|
||||
static TObject Crypto_TlsClient(GCList& ls, std::vector<TObject> args)
|
||||
{
|
||||
//TlsServerStream(GC* gc,std::string domain, std::string chain, bool verify, TCallable* read, TCallable* write, TCallable* close)
|
||||
if(args.size() == 6 && std::holds_alternative<std::string>(args[0]) && std::holds_alternative<std::string>(args[1]) && std::holds_alternative<bool>(args[2]) && std::holds_alternative<THeapObjectHolder>(args[3]) && std::holds_alternative<THeapObjectHolder>(args[4]) && std::holds_alternative<THeapObjectHolder>(args[5]))
|
||||
{
|
||||
std::string domain = std::get<std::string>(args[0]);
|
||||
std::string chain = std::get<std::string>(args[1]);
|
||||
bool verify = std::get<bool>(args[2]);
|
||||
TCallable* read = dynamic_cast<TCallable*>(std::get<THeapObjectHolder>(args[3]).obj);
|
||||
|
||||
TCallable* write = dynamic_cast<TCallable*>(std::get<THeapObjectHolder>(args[4]).obj);
|
||||
|
||||
TCallable* close = dynamic_cast<TCallable*>(std::get<THeapObjectHolder>(args[5]).obj);
|
||||
|
||||
if(read != nullptr && write != nullptr && close != nullptr)
|
||||
{
|
||||
auto serverStream = new TlsClientStream(ls.GetGC(),domain,chain,verify,read,write,close);
|
||||
if(!serverStream->success)
|
||||
{
|
||||
serverStream->Close();
|
||||
delete serverStream;
|
||||
return nullptr;
|
||||
}
|
||||
TNative* native = TNative::Create(ls,static_cast<void*>(serverStream),[](void* ptr)->void {
|
||||
if(ptr == nullptr) return;
|
||||
TlsClientStream* strm = static_cast<TlsClientStream*>(ptr);
|
||||
strm->Close();
|
||||
delete strm;
|
||||
});
|
||||
|
||||
TDictionary* dict = TDictionary::Create(ls);
|
||||
ls.GetGC()->BarrierBegin();
|
||||
dict->SetValue("_native",native);
|
||||
ls.GetGC()->BarrierEnd();
|
||||
dict->DeclareFunction(ls.GetGC(),"Read","Read data from Tls Connection",{"buffer","offset","length"},[native](GCList& ls2, std::vector<TObject> args2)->TObject {
|
||||
if(args2.size() == 3 && std::holds_alternative<THeapObjectHolder>(args2[0]) && std::holds_alternative<int64_t>(args2[1]) && std::holds_alternative<int64_t>(args2[2]))
|
||||
{
|
||||
auto byteArray = dynamic_cast<TByteArray*>(std::get<THeapObjectHolder>(args2[0]).obj);
|
||||
size_t offset = (size_t)std::get<int64_t>(args2[1]);
|
||||
size_t length = (size_t)std::get<int64_t>(args2[2]);
|
||||
|
||||
if(!native->GetDestroyed() && byteArray != nullptr && ((offset + length) <= byteArray->data.size()))
|
||||
{
|
||||
auto strm = static_cast<TlsClientStream*>(native->GetPointer());
|
||||
return strm->Read(byteArray->data.data()+offset, length);
|
||||
}
|
||||
}
|
||||
return Undefined();
|
||||
});
|
||||
dict->DeclareFunction(ls.GetGC(),"Write","Write data to Tls Connection",{"buffer","offset","length"},[native](GCList& ls2, std::vector<TObject> args2)->TObject {
|
||||
if(args2.size() == 3 && std::holds_alternative<THeapObjectHolder>(args2[0]) && std::holds_alternative<int64_t>(args2[1]) && std::holds_alternative<int64_t>(args2[2]))
|
||||
{
|
||||
auto byteArray = dynamic_cast<TByteArray*>(std::get<THeapObjectHolder>(args2[0]).obj);
|
||||
size_t offset = (size_t)std::get<int64_t>(args2[1]);
|
||||
size_t length = (size_t)std::get<int64_t>(args2[2]);
|
||||
|
||||
if(!native->GetDestroyed() && byteArray != nullptr && ((offset + length) <= byteArray->data.size()))
|
||||
{
|
||||
auto strm = static_cast<TlsClientStream*>(native->GetPointer());
|
||||
return strm->Write(byteArray->data.data()+offset, length);
|
||||
}
|
||||
}
|
||||
return Undefined();
|
||||
});
|
||||
dict->DeclareFunction(ls.GetGC(),"Close","Close Tls Connection",{},[native](GCList& ls2, std::vector<TObject> args2)->TObject {
|
||||
|
||||
if(!native->GetDestroyed())
|
||||
{
|
||||
native->Destroy();
|
||||
}
|
||||
|
||||
return Undefined();
|
||||
});
|
||||
return dict;
|
||||
}
|
||||
}
|
||||
return Undefined();
|
||||
}
|
||||
|
||||
static TObject Crypto_TlsServer(GCList& ls, std::vector<TObject> args)
|
||||
{
|
||||
//TlsServerStream(GC* gc,std::string cert, std::string chain, std::string privkey, TCallable* read, TCallable* write, TCallable* close)
|
||||
if(args.size() == 6 && std::holds_alternative<std::string>(args[0]) && std::holds_alternative<std::string>(args[1]) && std::holds_alternative<std::string>(args[2]) && std::holds_alternative<THeapObjectHolder>(args[3]) && std::holds_alternative<THeapObjectHolder>(args[4]) && std::holds_alternative<THeapObjectHolder>(args[5]))
|
||||
{
|
||||
std::string cert = std::get<std::string>(args[0]);
|
||||
std::string chain = std::get<std::string>(args[1]);
|
||||
std::string privkey = std::get<std::string>(args[2]);
|
||||
TCallable* read = dynamic_cast<TCallable*>(std::get<THeapObjectHolder>(args[3]).obj);
|
||||
|
||||
TCallable* write = dynamic_cast<TCallable*>(std::get<THeapObjectHolder>(args[4]).obj);
|
||||
|
||||
TCallable* close = dynamic_cast<TCallable*>(std::get<THeapObjectHolder>(args[5]).obj);
|
||||
|
||||
if(read != nullptr && write != nullptr && close != nullptr)
|
||||
{
|
||||
auto serverStream = new TlsServerStream(ls.GetGC(),cert,chain,privkey,read,write,close);
|
||||
if(!serverStream->success)
|
||||
{
|
||||
serverStream->Close();
|
||||
delete serverStream;
|
||||
return nullptr;
|
||||
}
|
||||
TNative* native = TNative::Create(ls,static_cast<void*>(serverStream),[](void* ptr)->void {
|
||||
if(ptr == nullptr) return;
|
||||
TlsServerStream* strm = static_cast<TlsServerStream*>(ptr);
|
||||
strm->Close();
|
||||
delete strm;
|
||||
});
|
||||
|
||||
TDictionary* dict = TDictionary::Create(ls);
|
||||
ls.GetGC()->BarrierBegin();
|
||||
dict->SetValue("_native",native);
|
||||
ls.GetGC()->BarrierEnd();
|
||||
dict->DeclareFunction(ls.GetGC(),"Read","Read data from Tls Connection",{"buffer","offset","length"},[native](GCList& ls2, std::vector<TObject> args2)->TObject {
|
||||
if(args2.size() == 3 && std::holds_alternative<THeapObjectHolder>(args2[0]) && std::holds_alternative<int64_t>(args2[1]) && std::holds_alternative<int64_t>(args2[2]))
|
||||
{
|
||||
auto byteArray = dynamic_cast<TByteArray*>(std::get<THeapObjectHolder>(args2[0]).obj);
|
||||
size_t offset = (size_t)std::get<int64_t>(args2[1]);
|
||||
size_t length = (size_t)std::get<int64_t>(args2[2]);
|
||||
if(!native->GetDestroyed() && byteArray != nullptr && ((offset + length) <= byteArray->data.size()))
|
||||
{
|
||||
auto strm = static_cast<TlsServerStream*>(native->GetPointer());
|
||||
return strm->Read(byteArray->data.data()+offset, length);
|
||||
}
|
||||
}
|
||||
return Undefined();
|
||||
});
|
||||
dict->DeclareFunction(ls.GetGC(),"Write","Write data to Tls Connection",{"buffer","offset","length"},[native](GCList& ls2, std::vector<TObject> args2)->TObject {
|
||||
if(args2.size() == 3 && std::holds_alternative<THeapObjectHolder>(args2[0]) && std::holds_alternative<int64_t>(args2[1]) && std::holds_alternative<int64_t>(args2[2]))
|
||||
{
|
||||
auto byteArray = dynamic_cast<TByteArray*>(std::get<THeapObjectHolder>(args2[0]).obj);
|
||||
size_t offset = (size_t)std::get<int64_t>(args2[1]);
|
||||
size_t length = (size_t)std::get<int64_t>(args2[2]);
|
||||
|
||||
|
||||
if(!native->GetDestroyed() && byteArray != nullptr && ((offset + length) <= byteArray->data.size()))
|
||||
{
|
||||
auto strm = static_cast<TlsServerStream*>(native->GetPointer());
|
||||
return strm->Write(byteArray->data.data()+offset, length);
|
||||
}
|
||||
}
|
||||
return Undefined();
|
||||
});
|
||||
dict->DeclareFunction(ls.GetGC(),"Close","Close Tls Connection",{},[native](GCList& ls2, std::vector<TObject> args2)->TObject {
|
||||
|
||||
if(!native->GetDestroyed())
|
||||
{
|
||||
native->Destroy();
|
||||
}
|
||||
|
||||
return Undefined();
|
||||
});
|
||||
return dict;
|
||||
}
|
||||
}
|
||||
return Undefined();
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
#endif
|
||||
void TStd::RegisterCrypto(GC* gc,TRootEnvironment* env)
|
||||
{
|
||||
|
||||
env->permissions.canRegisterCrypto=true;
|
||||
#if defined(CROSSLANG_ENABLE_MBED)
|
||||
|
||||
GCList ls(gc);
|
||||
TDictionary* dict = TDictionary::Create(ls);
|
||||
//dict->DeclareFunction(gc, "Decode","Deserialize Json",{"Json string"},Json_Decode);
|
||||
//dict->DeclareFunction(gc, "Encode","Serialize Json",{"any","$indent"},Json_Encode);
|
||||
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, "TlsClient", "Create TLS client for HTTPS client",{"domain","chain","verify","read","write","close"},Crypto_TlsClient);
|
||||
|
||||
dict->DeclareFunction(gc, "TlsServer", "Create TLS server for HTTPS server",{"cert","chain","privkey","read","write","close"},Crypto_TlsServer);
|
||||
gc->BarrierBegin();
|
||||
env->DeclareVariable("Crypto", dict);
|
||||
gc->BarrierEnd();
|
||||
dict = TDictionary::Create(ls);
|
||||
dict->DeclareFunction(gc, "Encode","Encode Base64",{"buffer","offset","count"},[](GCList& ls,std::vector<TObject> args)->TObject{
|
||||
TByteArray* bArray;
|
||||
int64_t offset;
|
||||
int64_t count;
|
||||
|
||||
if(!GetArgumentHeap<TByteArray*>(args,0,bArray))
|
||||
return nullptr;
|
||||
if(!GetArgument<int64_t>(args,1, offset))
|
||||
return nullptr;
|
||||
if(!GetArgument<int64_t>(args,2, count))
|
||||
return nullptr;
|
||||
|
||||
size_t off = (size_t)offset;
|
||||
size_t len = (size_t)count;
|
||||
|
||||
off = std::min(off, bArray->data.size());
|
||||
|
||||
len = std::min(len, bArray->data.size()-off);
|
||||
|
||||
size_t outLen = ((4 * len / 3) + 3) & ~3;
|
||||
|
||||
std::string str(outLen,'\0');
|
||||
|
||||
if(mbedtls_base64_encode((unsigned char*)str.data(),str.size(),&outLen,bArray->data.data(),bArray->data.size()) != 0)
|
||||
return nullptr;
|
||||
|
||||
str.resize(outLen);
|
||||
|
||||
return str;
|
||||
|
||||
//bArray->data.size();
|
||||
|
||||
//
|
||||
});
|
||||
|
||||
#endif
|
||||
}
|
||||
}
|
||||
51
src/runtime_methods/dictionary.cpp
Normal file
51
src/runtime_methods/dictionary.cpp
Normal file
@ -0,0 +1,51 @@
|
||||
#include "CrossLang.hpp"
|
||||
|
||||
namespace Tesses::CrossLang
|
||||
{
|
||||
|
||||
TObject Dictionary_Items(GCList& ls, std::vector<TObject> args)
|
||||
{
|
||||
|
||||
TDictionary* dict;
|
||||
|
||||
dict->items.begin();
|
||||
if(args.size() == 1 && std::holds_alternative<THeapObjectHolder>(args[0]))
|
||||
{
|
||||
auto item = dynamic_cast<TDictionary*>(std::get<THeapObjectHolder>(args[0]).obj);
|
||||
if(item != nullptr)
|
||||
{
|
||||
TDictionary* enumerableItem = TDictionary::Create(ls);
|
||||
ls.GetGC()->BarrierBegin();
|
||||
|
||||
auto fn = TExternalMethod::Create(ls,"Get Enumerator for Dictionary",{"dict"},[item](GCList& ls2, std::vector<TObject> args)->TObject {
|
||||
return TDictionaryEnumerator::Create(ls2,item);
|
||||
});
|
||||
fn->watch.push_back(item);
|
||||
|
||||
enumerableItem->SetValue("GetEnumerator", fn);
|
||||
|
||||
ls.GetGC()->BarrierEnd();
|
||||
|
||||
return enumerableItem;
|
||||
}
|
||||
}
|
||||
|
||||
return Undefined();
|
||||
}
|
||||
|
||||
void TStd::RegisterDictionary(GC* gc,TRootEnvironment* env)
|
||||
{
|
||||
|
||||
env->permissions.canRegisterDictionary=true;
|
||||
GCList ls(gc);
|
||||
TDictionary* dict = TDictionary::Create(ls);
|
||||
|
||||
|
||||
gc->BarrierBegin();
|
||||
|
||||
dict->DeclareFunction(gc, "Items","Get Dictionary Item Enumerable, for the each(item : Dictionary.Items(myDict)){item.Key; item.Value;}",{"dictionary"},Dictionary_Items);
|
||||
|
||||
env->DeclareVariable("Dictionary", dict);
|
||||
gc->BarrierEnd();
|
||||
}
|
||||
}
|
||||
147
src/runtime_methods/env.cpp
Normal file
147
src/runtime_methods/env.cpp
Normal file
@ -0,0 +1,147 @@
|
||||
#include "CrossLang.hpp"
|
||||
|
||||
#include "../sago/platform_folders.h"
|
||||
|
||||
namespace Tesses::CrossLang
|
||||
{
|
||||
static TObject Env_getPlatform(GCList& ls, std::vector<TObject> args)
|
||||
{
|
||||
#if defined(__SWITCH__)
|
||||
return "Nintendo Switch";
|
||||
#endif
|
||||
#if defined(GEKKO)
|
||||
#if defined(HW_RVL)
|
||||
return "Nintendo Wii";
|
||||
#endif
|
||||
return "Nintendo Gamecube";
|
||||
#endif
|
||||
#if defined(WIN32) || defined(_WIN32)
|
||||
return "Windows";
|
||||
#endif
|
||||
#if defined(linux)
|
||||
return "Linux";
|
||||
#endif
|
||||
|
||||
#ifdef __APPLE__
|
||||
#include "TargetConditionals.h"
|
||||
#if TARGET_OS_MAC
|
||||
return "MacOS";
|
||||
#endif
|
||||
#if TARGET_OS_IOS
|
||||
return "iOS";
|
||||
#endif
|
||||
#if TARGET_OS_TV
|
||||
return "Apple TV";
|
||||
#endif
|
||||
|
||||
#if TARGET_OS_WATCH
|
||||
return "Apple Watch";
|
||||
#endif
|
||||
|
||||
#if __EMSCRIPTEN__
|
||||
return "WebAssembly";
|
||||
#endif
|
||||
|
||||
return "Unknown Apple Device";
|
||||
#endif
|
||||
|
||||
return "Unknown";
|
||||
}
|
||||
static TObject Env_GetAt(GCList& ls, std::vector<TObject> args)
|
||||
{
|
||||
std::string key;
|
||||
if(GetArgument(args,0,key))
|
||||
{
|
||||
auto res = getenv(key.c_str());
|
||||
if(res == nullptr) return nullptr;
|
||||
std::string value = res;
|
||||
return value;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
static TObject Env_SetAt(GCList& ls, std::vector<TObject> args)
|
||||
{
|
||||
std::string key;
|
||||
std::string value;
|
||||
if(GetArgument(args,0,key))
|
||||
{
|
||||
if(GetArgument(args,1,value))
|
||||
setenv(key.c_str(), value.c_str(),1);
|
||||
else
|
||||
unsetenv(key.c_str());
|
||||
return value;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
static TObject Env_getDownloads(GCList& ls, std::vector<TObject> args)
|
||||
{
|
||||
return sago::getDownloadFolder();
|
||||
}
|
||||
static TObject Env_getMusic(GCList& ls, std::vector<TObject> args)
|
||||
{
|
||||
return sago::getMusicFolder();
|
||||
}
|
||||
static TObject Env_getPictures(GCList& ls, std::vector<TObject> args)
|
||||
{
|
||||
return sago::getMusicFolder();
|
||||
}
|
||||
static TObject Env_getVideos(GCList& ls, std::vector<TObject> args)
|
||||
{
|
||||
return sago::getVideoFolder();
|
||||
}
|
||||
static TObject Env_getDocuments(GCList& ls, std::vector<TObject> args)
|
||||
{
|
||||
return sago::getDocumentsFolder();
|
||||
}
|
||||
static TObject Env_getConfig(GCList& ls, std::vector<TObject> args)
|
||||
{
|
||||
return sago::getConfigHome();
|
||||
}
|
||||
|
||||
static TObject Env_getDesktop(GCList& ls, std::vector<TObject> args)
|
||||
{
|
||||
return sago::getDesktopFolder();
|
||||
}
|
||||
static TObject Env_getState(GCList& ls, std::vector<TObject> args)
|
||||
{
|
||||
return sago::getStateDir();
|
||||
}
|
||||
static TObject Env_getCache(GCList& ls, std::vector<TObject> args)
|
||||
{
|
||||
return sago::getCacheDir();
|
||||
}
|
||||
static TObject Env_getData(GCList& ls, std::vector<TObject> args)
|
||||
{
|
||||
return sago::getDataHome();
|
||||
}
|
||||
static TObject Env_getUser(GCList& ls, std::vector<TObject> args)
|
||||
{
|
||||
return sago::getHomeDir();
|
||||
}
|
||||
void TStd::RegisterEnv(GC* gc, TRootEnvironment* env)
|
||||
{
|
||||
|
||||
env->permissions.canRegisterEnv=true;
|
||||
GCList ls(gc);
|
||||
TDictionary* dict = TDictionary::Create(ls);
|
||||
dict->DeclareFunction(gc,"GetAt","Get environment variable", {"key"}, Env_GetAt);
|
||||
dict->DeclareFunction(gc,"SetAt","Set environment variable", {"key","value"}, Env_SetAt);
|
||||
|
||||
dict->DeclareFunction(gc,"getDesktop","Get downloads folder",{},Env_getDownloads);
|
||||
dict->DeclareFunction(gc,"getDownloads","Get downloads folder",{},Env_getDownloads);
|
||||
dict->DeclareFunction(gc,"getDocuments","Get documents folder",{},Env_getDocuments);
|
||||
dict->DeclareFunction(gc,"getMusic","Get music folder",{},Env_getMusic);
|
||||
dict->DeclareFunction(gc,"getPictures","Get pictures folder",{},Env_getPictures);
|
||||
dict->DeclareFunction(gc,"getVideos","Get videos folder",{},Env_getVideos);
|
||||
dict->DeclareFunction(gc,"getState","Get state folder",{},Env_getState);
|
||||
dict->DeclareFunction(gc,"getCache","Get cache folder",{},Env_getCache);
|
||||
dict->DeclareFunction(gc,"getConfig","Get config folder",{},Env_getConfig);
|
||||
dict->DeclareFunction(gc,"getData","Get data folder",{},Env_getData);
|
||||
dict->DeclareFunction(gc,"getUser","Get user folder",{},Env_getUser);
|
||||
dict->DeclareFunction(gc,"getPlatform","Get platform name",{},Env_getPlatform);
|
||||
|
||||
gc->BarrierBegin();
|
||||
env->SetVariable("Env", dict);
|
||||
gc->BarrierEnd();
|
||||
}
|
||||
}
|
||||
81
src/runtime_methods/io.cpp
Normal file
81
src/runtime_methods/io.cpp
Normal file
@ -0,0 +1,81 @@
|
||||
#include "CrossLang.hpp"
|
||||
|
||||
|
||||
|
||||
namespace Tesses::CrossLang
|
||||
{
|
||||
static TObject FS_SubdirFilesystem(GCList& ls, std::vector<TObject> args)
|
||||
{
|
||||
TVFSHeapObject* vfsho;
|
||||
|
||||
Tesses::Framework::Filesystem::VFSPath path;
|
||||
|
||||
if(GetArgumentHeap(args,0,vfsho) && GetArgumentAsPath(args,1,path))
|
||||
{
|
||||
return TVFSHeapObject::Create(ls,new Tesses::Framework::Filesystem::SubdirFilesystem(new TObjectVFS(ls.GetGC(),vfsho),path,true));
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
static TObject FS_MountableFilesystem(GCList& ls, std::vector<TObject> args)
|
||||
{
|
||||
TVFSHeapObject* vfsho;
|
||||
|
||||
if(GetArgumentHeap(args,0,vfsho))
|
||||
{
|
||||
return TVFSHeapObject::Create(ls,new Tesses::Framework::Filesystem::MountableFilesystem(new TObjectVFS(ls.GetGC(),vfsho),true));
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
static TObject FS_MemoryStream(GCList& ls, std::vector<TObject> args)
|
||||
{
|
||||
bool writable;
|
||||
if(GetArgument(args,0,writable))
|
||||
{
|
||||
return TStreamHeapObject::Create(ls,new Tesses::Framework::Streams::MemoryStream(writable));
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
static TObject FS_CreateFilesystem(GCList& ls, std::vector<TObject> args)
|
||||
{
|
||||
TDictionary* dict;
|
||||
if(GetArgumentHeap(args,0,dict))
|
||||
{
|
||||
return TVFSHeapObject::Create(ls, new TObjectVFS(ls.GetGC(),dict));
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
static TObject FS_CreateStream(GCList& ls, std::vector<TObject> args)
|
||||
{
|
||||
TDictionary* dict;
|
||||
if(GetArgumentHeap(args,0,dict))
|
||||
{
|
||||
return TStreamHeapObject::Create(ls, new TObjectStream(ls.GetGC(),dict));
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
void TStd::RegisterIO(GC* gc,TRootEnvironment* env,bool enableLocalFilesystem)
|
||||
{
|
||||
|
||||
env->permissions.canRegisterIO=true;
|
||||
env->permissions.canRegisterLocalFS = enableLocalFilesystem;
|
||||
GCList ls(gc);
|
||||
TDictionary* dict = TDictionary::Create(ls);
|
||||
|
||||
gc->BarrierBegin();
|
||||
if(enableLocalFilesystem)
|
||||
{
|
||||
TVFSHeapObject* vfs = TVFSHeapObject::Create(ls, new Tesses::Framework::Filesystem::LocalFilesystem());
|
||||
|
||||
dict->SetValue("Local", vfs);
|
||||
}
|
||||
|
||||
dict->DeclareFunction(gc, "MountableFilesystem","Create a mountable filesystem",{"root"}, FS_MountableFilesystem);
|
||||
dict->DeclareFunction(gc, "SubdirFilesystem","Create a subdir filesystem",{"fs","subdir"}, FS_SubdirFilesystem);
|
||||
dict->DeclareFunction(gc, "MemoryStream","Create a memory stream",{"writable"}, FS_MemoryStream);
|
||||
dict->DeclareFunction(gc, "CreateStream","Create stream", {"strm"},FS_CreateStream);
|
||||
dict->DeclareFunction(gc, "CreateFilesystem","Create filesystem", {"fs"},FS_CreateFilesystem);
|
||||
env->DeclareVariable("FS", dict);
|
||||
gc->BarrierEnd();
|
||||
}
|
||||
}
|
||||
147
src/runtime_methods/json.cpp
Normal file
147
src/runtime_methods/json.cpp
Normal file
@ -0,0 +1,147 @@
|
||||
/*
|
||||
|
||||
*/
|
||||
|
||||
#include "CrossLang.hpp"
|
||||
|
||||
#if defined(CROSSLANG_ENABLE_JSON)
|
||||
#include <jansson.h>
|
||||
#endif
|
||||
|
||||
namespace Tesses::CrossLang
|
||||
{
|
||||
|
||||
#if defined(CROSSLANG_ENABLE_JSON)
|
||||
static json_t* JsonSerialize(TObject v)
|
||||
{
|
||||
if(std::holds_alternative<std::nullptr_t>(v)) return json_null();
|
||||
if(std::holds_alternative<int64_t>(v)) return json_integer(std::get<int64_t>(v));
|
||||
if(std::holds_alternative<double>(v)) return json_real(std::get<double>(v));
|
||||
if(std::holds_alternative<bool>(v)) return json_boolean(std::get<bool>(v));
|
||||
if(std::holds_alternative<std::string>(v))
|
||||
{
|
||||
std::string txt = std::get<std::string>(v);
|
||||
return json_stringn(txt.c_str(),txt.size());
|
||||
}
|
||||
if(std::holds_alternative<THeapObjectHolder>(v))
|
||||
{
|
||||
auto obj = std::get<THeapObjectHolder>(v).obj;
|
||||
auto ls = dynamic_cast<TList*>(obj);
|
||||
auto dict = dynamic_cast<TDictionary*>(obj);
|
||||
|
||||
if(ls != nullptr)
|
||||
{
|
||||
json_t* items=json_array();
|
||||
for(int64_t i = 0; i < ls->Count(); i++)
|
||||
{
|
||||
json_array_append_new(items,JsonSerialize(ls->Get(i)));
|
||||
}
|
||||
return items;
|
||||
}
|
||||
|
||||
if(dict != nullptr)
|
||||
{
|
||||
json_t* obj = json_object();
|
||||
for(auto item : dict->items)
|
||||
{
|
||||
json_object_setn_new(obj, item.first.c_str(), item.first.size(),JsonSerialize(item.second));
|
||||
}
|
||||
return obj;
|
||||
}
|
||||
}
|
||||
|
||||
return json_null();
|
||||
}
|
||||
static TObject Json_Encode(GCList& ls2, std::vector<TObject> args)
|
||||
{
|
||||
if(args.size() >= 1)
|
||||
{
|
||||
bool indent = (args.size() == 2 && std::holds_alternative<bool>(args[1]) && std::get<bool>(args[1]));
|
||||
|
||||
auto json = JsonSerialize(args[0]);
|
||||
char* txt = json_dumps(json, indent ? JSON_INDENT(4) : 0);
|
||||
std::string str = txt;
|
||||
free(txt);
|
||||
json_decref(json);
|
||||
return str;
|
||||
}
|
||||
return "null";
|
||||
}
|
||||
static TObject JsonDeserialize(GCList& ls2,json_t* json)
|
||||
{
|
||||
if(json == nullptr) return nullptr;
|
||||
if(json_is_null(json)) return nullptr;
|
||||
if(json_is_true(json)) return true;
|
||||
if(json_is_false(json)) return false;
|
||||
if(json_is_integer(json)) return (int64_t)json_integer_value(json);
|
||||
if(json_is_real(json)) return json_real_value(json);
|
||||
if(json_is_string(json))
|
||||
{
|
||||
return std::string(json_string_value(json),json_string_length(json));
|
||||
}
|
||||
if(json_is_array(json))
|
||||
{
|
||||
TList* ls = TList::Create(ls2);
|
||||
json_t* item;
|
||||
size_t index;
|
||||
json_array_foreach(json,index, item)
|
||||
{
|
||||
auto itemRes = JsonDeserialize(ls2,item);
|
||||
ls2.GetGC()->BarrierBegin();
|
||||
ls->Add(itemRes);
|
||||
ls2.GetGC()->BarrierEnd();
|
||||
}
|
||||
return ls;
|
||||
}
|
||||
if(json_is_object(json))
|
||||
{
|
||||
|
||||
TDictionary* dict = TDictionary::Create(ls2);
|
||||
void* n;
|
||||
const char* key;
|
||||
size_t len;
|
||||
json_t* value;
|
||||
|
||||
json_object_keylen_foreach_safe(json,n,key,len,value)
|
||||
{
|
||||
auto itemRes = JsonDeserialize(ls2,value);
|
||||
ls2.GetGC()->BarrierBegin();
|
||||
dict->SetValue(std::string(key,len),itemRes);
|
||||
ls2.GetGC()->BarrierEnd();
|
||||
}
|
||||
return dict;
|
||||
}
|
||||
return Undefined();
|
||||
}
|
||||
static TObject Json_Decode(GCList& ls2,std::vector<TObject> args)
|
||||
{
|
||||
if(args.size() > 0 && std::holds_alternative<std::string>(args[0]))
|
||||
{
|
||||
std::string jsonText = std::get<std::string>(args[0]);
|
||||
json_t* json = json_loadb(jsonText.c_str(), jsonText.size(),0,NULL);
|
||||
|
||||
auto res = JsonDeserialize(ls2, json);
|
||||
json_decref(json);
|
||||
return res;
|
||||
}
|
||||
return Undefined();
|
||||
}
|
||||
#endif
|
||||
void TStd::RegisterJson(GC* gc,TRootEnvironment* env)
|
||||
{
|
||||
|
||||
env->permissions.canRegisterJSON=true;
|
||||
#if defined(CROSSLANG_ENABLE_JSON)
|
||||
GCList ls(gc);
|
||||
TDictionary* dict = TDictionary::Create(ls);
|
||||
dict->DeclareFunction(gc, "Decode","Deserialize Json",{"Json string"},Json_Decode);
|
||||
dict->DeclareFunction(gc, "Encode","Serialize Json",{"any","$indent"},Json_Encode);
|
||||
|
||||
|
||||
gc->BarrierBegin();
|
||||
env->DeclareVariable("Json", dict);
|
||||
gc->BarrierEnd();
|
||||
#endif
|
||||
}
|
||||
|
||||
}
|
||||
555
src/runtime_methods/net.cpp
Normal file
555
src/runtime_methods/net.cpp
Normal file
@ -0,0 +1,555 @@
|
||||
#include "CrossLang.hpp"
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netdb.h>
|
||||
#include <csignal>
|
||||
#include <arpa/inet.h>
|
||||
#include <iostream>
|
||||
#include <netinet/tcp.h>
|
||||
#include <unistd.h>
|
||||
#include <cstring>
|
||||
using namespace Tesses::Framework::Streams;
|
||||
using namespace Tesses::Framework::Http;
|
||||
namespace Tesses::CrossLang
|
||||
{
|
||||
TServerHeapObject* TServerHeapObject::Create(GCList& ls, Tesses::Framework::Http::IHttpServer* svr)
|
||||
{
|
||||
TServerHeapObject* ho = new TServerHeapObject();
|
||||
ls.Add(ho);
|
||||
auto gc = ls.GetGC();
|
||||
gc->Watch(ho);
|
||||
ho->server = svr;
|
||||
return ho;
|
||||
}
|
||||
TServerHeapObject* TServerHeapObject::Create(GCList* ls, Tesses::Framework::Http::IHttpServer* svr)
|
||||
{
|
||||
TServerHeapObject* ho = new TServerHeapObject();
|
||||
ls->Add(ho);
|
||||
auto gc = ls->GetGC();
|
||||
gc->Watch(ho);
|
||||
ho->server = svr;
|
||||
return ho;
|
||||
}
|
||||
|
||||
void TServerHeapObject::Close()
|
||||
{
|
||||
if(this->server != nullptr)
|
||||
{
|
||||
delete this->server;
|
||||
this->server = nullptr;
|
||||
}
|
||||
}
|
||||
TServerHeapObject::~TServerHeapObject()
|
||||
{
|
||||
if(this->server != nullptr)
|
||||
{
|
||||
delete this->server;
|
||||
}
|
||||
}
|
||||
static TDictionary* CreateDictionaryFromHttpDictionary(GCList& ls, Tesses::Framework::Http::HttpDictionary* dict0)
|
||||
{
|
||||
TDictionary* dict = TDictionary::Create(ls);
|
||||
|
||||
auto gc =ls.GetGC();
|
||||
//gc->BarrierBegin();
|
||||
|
||||
|
||||
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))
|
||||
{
|
||||
dict0->AddValue(key,value);
|
||||
}
|
||||
return nullptr;
|
||||
});
|
||||
|
||||
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))
|
||||
{
|
||||
dict0->SetValue(key,value);
|
||||
}
|
||||
return nullptr;
|
||||
});
|
||||
|
||||
dict->DeclareFunction(gc,"Clear","Clear items",{},[dict0](Tesses::CrossLang::GCList &ls2, std::vector<Tesses::CrossLang::TObject> args2)->TObject {
|
||||
dict0->Clear();
|
||||
return nullptr;
|
||||
});
|
||||
|
||||
dict->DeclareFunction(gc,"GetFirstBoolean","Get First boolean",{"key"},[dict0](Tesses::CrossLang::GCList &ls2, std::vector<Tesses::CrossLang::TObject> args2)->TObject {
|
||||
std::string key;
|
||||
if(GetArgument(args2,0,key))
|
||||
{
|
||||
return dict0->GetFirstBoolean(key);
|
||||
}
|
||||
return false;
|
||||
});
|
||||
dict->DeclareFunction(gc,"TryGetFirst","Try Get first string",{"key"},[dict0](Tesses::CrossLang::GCList &ls2, std::vector<Tesses::CrossLang::TObject> args2)->TObject {
|
||||
std::string key;
|
||||
std::string value;
|
||||
if(GetArgument(args2,0,key) && dict0->TryGetFirst(key,value))
|
||||
{
|
||||
return value;
|
||||
}
|
||||
return nullptr;
|
||||
});
|
||||
dict->DeclareFunction(gc,"TryGetFirstDouble","Try Get first double",{"key"},[dict0](Tesses::CrossLang::GCList &ls2, std::vector<Tesses::CrossLang::TObject> args2)->TObject {
|
||||
std::string key;
|
||||
double value;
|
||||
if(GetArgument(args2,0,key) && dict0->TryGetFirstDouble(key,value))
|
||||
{
|
||||
return value;
|
||||
}
|
||||
return nullptr;
|
||||
});
|
||||
dict->DeclareFunction(gc,"TryGetFirstInt","Try Get first integer",{"key"},[dict0](Tesses::CrossLang::GCList &ls2, std::vector<Tesses::CrossLang::TObject> args2)->TObject {
|
||||
std::string key;
|
||||
int64_t value;
|
||||
if(GetArgument(args2,0,key) && dict0->TryGetFirstInt(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);
|
||||
for(auto item : dict0->kvp)
|
||||
{
|
||||
for(auto i : item.second)
|
||||
{
|
||||
auto d = TDictionary::Create(ls2);
|
||||
ls2.GetGC()->BarrierBegin();
|
||||
d->SetValue("Key", item.first);
|
||||
d->SetValue("Value", i);
|
||||
ls->Add(d);
|
||||
ls2.GetGC()->BarrierEnd();
|
||||
}
|
||||
}
|
||||
return ls;
|
||||
});
|
||||
|
||||
return dict;
|
||||
}
|
||||
|
||||
static TDictionary* CreateDictionaryFromServerContext(GCList& ls,ServerContext* ctx)
|
||||
{
|
||||
TDictionary* dict = TDictionary::Create(ls);
|
||||
|
||||
auto gc =ls.GetGC();
|
||||
gc->BarrierBegin();
|
||||
dict->SetValue("native",TNative::Create(ls,ctx,[](void*)->void {}));
|
||||
dict->SetValue("Encrypted",ctx->encrypted);
|
||||
dict->SetValue("Method",ctx->method);
|
||||
dict->SetValue("IP",ctx->ip);
|
||||
dict->SetValue("Port",(int64_t)ctx->port);
|
||||
dict->SetValue("OriginalPath",ctx->originalPath);
|
||||
dict->SetValue("QueryParams",CreateDictionaryFromHttpDictionary(ls,&ctx->queryParams));
|
||||
dict->SetValue("RequestHeaders",CreateDictionaryFromHttpDictionary(ls,&ctx->requestHeaders));
|
||||
dict->SetValue("ResponseHeaders",CreateDictionaryFromHttpDictionary(ls,&ctx->responseHeaders));
|
||||
gc->BarrierEnd();
|
||||
|
||||
dict->DeclareFunction(gc,"GetStream","Get streams",{},[ctx](Tesses::CrossLang::GCList &ls2, std::vector<Tesses::CrossLang::TObject> args2)->TObject {
|
||||
return TStreamHeapObject::Create(ls2, &ctx->GetStream());
|
||||
});
|
||||
dict->DeclareFunction(gc,"OpenRequestStream","Open Request Stream",{},[ctx](Tesses::CrossLang::GCList &ls2, std::vector<Tesses::CrossLang::TObject> args2)->TObject {
|
||||
return TStreamHeapObject::Create(ls2, ctx->OpenRequestStream());
|
||||
});
|
||||
dict->DeclareFunction(gc,"OpenResponseStream","Open Response Stream",{},[ctx](Tesses::CrossLang::GCList &ls2, std::vector<Tesses::CrossLang::TObject> args2)->TObject {
|
||||
return TStreamHeapObject::Create(ls2, ctx->OpenResponseStream());
|
||||
});
|
||||
|
||||
dict->DeclareFunction(gc,"getNeedToParseFormData","Check if Need to parse form data",{},[ctx](Tesses::CrossLang::GCList &ls2, std::vector<Tesses::CrossLang::TObject> args2)->TObject{
|
||||
return ctx->NeedToParseFormData();
|
||||
});
|
||||
|
||||
/*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,"SendText","Send response text",{"text"},[ctx](Tesses::CrossLang::GCList &ls2, std::vector<Tesses::CrossLang::TObject> args2)->TObject{
|
||||
std::string text;
|
||||
if(GetArgument(args2,0,text))
|
||||
ctx->SendText(text);
|
||||
return nullptr;
|
||||
});
|
||||
dict->DeclareFunction(gc,"WithMimeType","Set mime type",{"mimeType"},[ctx,dict](Tesses::CrossLang::GCList &ls2, std::vector<Tesses::CrossLang::TObject> args2)->TObject{
|
||||
std::string text;
|
||||
if(GetArgument(args2,0,text))
|
||||
ctx->WithMimeType(text);
|
||||
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;
|
||||
if(GetArgument(args2,0,filename) && GetArgument(args2,1,isInline))
|
||||
ctx->WithContentDisposition(filename,isInline);
|
||||
return dict;
|
||||
});
|
||||
dict->DeclareFunction(gc,"WithHeader","Add header",{"key","value"},[ctx,dict](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))
|
||||
ctx->WithHeader(key,value);
|
||||
return dict;
|
||||
});
|
||||
dict->DeclareFunction(gc,"WithSingleHeader","Set header",{"key","value"},[ctx,dict](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))
|
||||
ctx->WithSingleHeader(key,value);
|
||||
return dict;
|
||||
});
|
||||
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))
|
||||
ctx->SendBytes(ba->data);
|
||||
return nullptr;
|
||||
});
|
||||
// dict->DeclareFunction(gc,"getUrlWithQuery","Get original path with query parameters",{},[ctx](Tesses::CrossLang::GCList &ls2, std::vector<Tesses::CrossLang::TObject> args2)->TObject {return ctx->GetUrlWithQuery();});
|
||||
|
||||
|
||||
//dict->DeclareFunction(gc,"getOriginalPathWithQuery","Get original path with query parameters",{},[ctx](Tesses::CrossLang::GCList &ls2, std::vector<Tesses::CrossLang::TObject> args2)->TObject {return ctx->GetOriginalPathWithQuery();});
|
||||
dict->DeclareFunction(gc,"getPath","Get path",{},[ctx](Tesses::CrossLang::GCList &ls2, std::vector<Tesses::CrossLang::TObject> args2)->TObject {return ctx->path;});
|
||||
dict->DeclareFunction(gc,"setPath","Set path",{},[ctx](Tesses::CrossLang::GCList &ls2, std::vector<Tesses::CrossLang::TObject> args2)->TObject {
|
||||
std::string str;
|
||||
if(GetArgument(args2,0,str))
|
||||
{
|
||||
ctx->path = str;
|
||||
return str;
|
||||
}
|
||||
return nullptr;
|
||||
});
|
||||
dict->DeclareFunction(gc,"getVersion","Get version",{},[ctx](Tesses::CrossLang::GCList &ls2, std::vector<Tesses::CrossLang::TObject> args2)->TObject {return ctx->version;});
|
||||
dict->DeclareFunction(gc,"setVersion","Set version",{},[ctx](Tesses::CrossLang::GCList &ls2, std::vector<Tesses::CrossLang::TObject> args2)->TObject {
|
||||
std::string str;
|
||||
if(GetArgument(args2,0,str))
|
||||
{
|
||||
ctx->version = str;
|
||||
return str;
|
||||
}
|
||||
return nullptr;
|
||||
});
|
||||
|
||||
dict->DeclareFunction(gc,"getStatusCode","Get status code",{},[ctx](Tesses::CrossLang::GCList &ls2, std::vector<Tesses::CrossLang::TObject> args2)->TObject {return (int64_t)ctx->statusCode;});
|
||||
dict->DeclareFunction(gc,"setStatusCode","Set status code",{},[ctx](Tesses::CrossLang::GCList &ls2, std::vector<Tesses::CrossLang::TObject> args2)->TObject {
|
||||
int64_t sc;
|
||||
if(GetArgument(args2,0,sc))
|
||||
{
|
||||
ctx->statusCode = (StatusCode)sc;
|
||||
return sc;
|
||||
}
|
||||
return nullptr;
|
||||
});
|
||||
|
||||
return dict;
|
||||
}
|
||||
|
||||
TObjectHttpServer::TObjectHttpServer(GC* gc,TObject obj)
|
||||
{
|
||||
this->ls=new GCList(gc);
|
||||
this->obj = obj;
|
||||
}
|
||||
|
||||
class TDictionaryHttpRequestBody : public HttpRequestBody
|
||||
{
|
||||
GC* gc;
|
||||
TDictionary* req;
|
||||
public:
|
||||
TDictionaryHttpRequestBody(GC* gc,TDictionary* req)
|
||||
{
|
||||
this->gc = gc;
|
||||
this->req = req;
|
||||
}
|
||||
|
||||
void HandleHeaders(HttpDictionary& dict)
|
||||
{
|
||||
GCList ls(gc);
|
||||
auto res=CreateDictionaryFromHttpDictionary(ls,&dict);
|
||||
req->CallMethod(ls,"HandleHeaders",{res});
|
||||
}
|
||||
void Write(Tesses::Framework::Streams::Stream* strm)
|
||||
{
|
||||
GCList ls(gc);
|
||||
auto res=TStreamHeapObject::Create(ls,strm);
|
||||
req->CallMethod(ls,"Write",{res});
|
||||
res->stream=nullptr;
|
||||
}
|
||||
|
||||
~TDictionaryHttpRequestBody()
|
||||
{
|
||||
GCList ls(gc);
|
||||
req->CallMethod(ls,"Close",{});
|
||||
}
|
||||
};
|
||||
|
||||
bool TObjectHttpServer::Handle(ServerContext& ctx)
|
||||
{
|
||||
TCallable* callable;
|
||||
TDictionary* dict;
|
||||
TServerHeapObject* server;
|
||||
if(GetObjectHeap<TCallable*>(this->obj,callable))
|
||||
{
|
||||
GCList ls2(this->ls->GetGC());
|
||||
auto res = CreateDictionaryFromServerContext(ls2,&ctx);
|
||||
bool result;
|
||||
auto out = callable->Call(ls2,{res});
|
||||
if(GetObject(out,result))
|
||||
{
|
||||
return result;
|
||||
}
|
||||
}
|
||||
else if(GetObjectHeap<TDictionary*>(this->obj,dict))
|
||||
{
|
||||
GCList ls2(this->ls->GetGC());
|
||||
auto res = CreateDictionaryFromServerContext(ls2,&ctx);
|
||||
bool result;
|
||||
auto out = dict->CallMethod(ls2,"Handle",{res});
|
||||
if(GetObject(out,result))
|
||||
{
|
||||
return result;
|
||||
}
|
||||
}
|
||||
else if(GetObjectHeap<TServerHeapObject*>(this->obj,server))
|
||||
{
|
||||
return server->server->Handle(ctx);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
TObjectHttpServer::~TObjectHttpServer()
|
||||
{
|
||||
delete ls;
|
||||
}
|
||||
|
||||
static TObject Net_UrlDecode(GCList& ls, std::vector<TObject> args)
|
||||
{
|
||||
if(args.size() == 1 && std::holds_alternative<std::string>(args[0]))
|
||||
{
|
||||
return HttpUtils::UrlDecode(std::get<std::string>(args[0]));
|
||||
}
|
||||
return Undefined();
|
||||
}
|
||||
static TObject Net_UrlEncode(GCList& ls, std::vector<TObject> args)
|
||||
{
|
||||
if(args.size() == 1 && std::holds_alternative<std::string>(args[0]))
|
||||
{
|
||||
return HttpUtils::UrlEncode(std::get<std::string>(args[0]));
|
||||
}
|
||||
return Undefined();
|
||||
}
|
||||
static TObject Net_UrlPathDecode(GCList& ls, std::vector<TObject> args)
|
||||
{
|
||||
if(args.size() == 1 && std::holds_alternative<std::string>(args[0]))
|
||||
{
|
||||
return HttpUtils::UrlPathDecode(std::get<std::string>(args[0]));
|
||||
}
|
||||
return Undefined();
|
||||
}
|
||||
static TObject Net_UrlPathEncode(GCList& ls, std::vector<TObject> args)
|
||||
{
|
||||
if(args.size() == 1 && std::holds_alternative<std::string>(args[0]))
|
||||
{
|
||||
return HttpUtils::UrlPathEncode(std::get<std::string>(args[0]));
|
||||
}
|
||||
return Undefined();
|
||||
}
|
||||
static TObject Net_NetworkStream(GCList& ls, std::vector<TObject> args)
|
||||
{
|
||||
bool ipv6;
|
||||
bool datagram;
|
||||
if(GetArgument(args,0,ipv6) && GetArgument(args,1,datagram))
|
||||
{
|
||||
return TStreamHeapObject::Create(ls,new NetworkStream(ipv6,datagram));
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
static TObject Net_Http_ListenSimpleWithLoop(GCList& ls, std::vector<TObject> args)
|
||||
{
|
||||
int64_t port;
|
||||
if(GetArgument(args,1,port))
|
||||
{
|
||||
TObjectHttpServer httpServer(ls.GetGC(),args[0]);
|
||||
uint16_t p = (uint16_t)port;
|
||||
HttpServer server(p,httpServer);
|
||||
server.StartAccepting();
|
||||
Tesses::Framework::TF_RunEventLoop();
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
static TObject Net_Http_MimeType(GCList& ls, std::vector<TObject> args)
|
||||
{
|
||||
Tesses::Framework::Filesystem::VFSPath p;
|
||||
if(GetArgumentAsPath(args,0,p))
|
||||
{
|
||||
std::filesystem::path p2 = p.GetFileName();
|
||||
return HttpUtils::MimeType(p2);
|
||||
}
|
||||
return "application/octet-stream";
|
||||
}
|
||||
|
||||
static TObject Net_Http_MakeRequest(GCList& ls, std::vector<TObject> args)
|
||||
{
|
||||
auto gc = ls.GetGC();
|
||||
std::string url;
|
||||
|
||||
if(GetArgument(args,0,url))
|
||||
{
|
||||
TDictionary* body1=nullptr;
|
||||
TNative* body2=nullptr;
|
||||
HttpRequest req;
|
||||
req.method = "GET";
|
||||
req.ignoreSSLErrors=false;
|
||||
req.followRedirects=false;
|
||||
req.trusted_root_cert_bundle="";
|
||||
req.url = url;
|
||||
req.body = nullptr;
|
||||
|
||||
TDictionary* options;
|
||||
if(GetArgumentHeap(args,1,options))
|
||||
{
|
||||
gc->BarrierBegin();
|
||||
auto _obj = options->GetValue("Method");
|
||||
GetObject(_obj,req.method);
|
||||
_obj = options->GetValue("IgnoreSSLErrors");
|
||||
GetObject(_obj,req.ignoreSSLErrors);
|
||||
_obj = options->GetValue("FollowRedirects");
|
||||
GetObject(_obj,req.followRedirects);
|
||||
_obj = options->GetValue("TrustedRootCertBundle");
|
||||
GetObject(_obj,req.trusted_root_cert_bundle);
|
||||
|
||||
_obj = options->GetValue("RequestHeaders");
|
||||
|
||||
TList* headers;
|
||||
|
||||
if(GetObjectHeap(_obj, headers))
|
||||
{
|
||||
for(int64_t index = 0; index < headers->Count();index ++)
|
||||
{
|
||||
_obj = headers->Get(index);
|
||||
TDictionary* dict;
|
||||
if(GetObjectHeap(_obj,dict))
|
||||
{
|
||||
std::string key={};
|
||||
std::string value={};
|
||||
_obj = dict->GetValue("Key");
|
||||
GetObject(_obj,key);
|
||||
_obj = dict->GetValue("Value");
|
||||
|
||||
req.requestHeaders.AddValue(key,value);
|
||||
}
|
||||
}
|
||||
}
|
||||
_obj = options->GetValue("Body");
|
||||
|
||||
|
||||
|
||||
if(GetObjectHeap(_obj, body1))
|
||||
{
|
||||
req.body = new TDictionaryHttpRequestBody(gc,body1);
|
||||
}
|
||||
else if(GetObjectHeap(_obj,body2) && !body2->GetDestroyed())
|
||||
{
|
||||
req.body = static_cast<HttpRequestBody*>(body2->GetPointer());
|
||||
}
|
||||
|
||||
|
||||
gc->BarrierEnd();
|
||||
}
|
||||
|
||||
|
||||
HttpResponse* resp = new HttpResponse(req);
|
||||
|
||||
if(req.body != nullptr)
|
||||
{
|
||||
if(body2 != nullptr)
|
||||
{
|
||||
body2->Destroy();
|
||||
}
|
||||
else if(body1 != nullptr)
|
||||
{
|
||||
delete req.body;
|
||||
}
|
||||
}
|
||||
|
||||
TDictionary* dict = TDictionary::Create(ls);
|
||||
gc->BarrierBegin();
|
||||
|
||||
TNative* nat = TNative::Create(ls,resp,[](void* ptr)->void{
|
||||
HttpResponse* resp0 = static_cast<HttpResponse*>(ptr);
|
||||
delete resp0;
|
||||
});
|
||||
|
||||
dict->SetValue("native", nat);
|
||||
|
||||
auto copyToStream = TExternalMethod::Create(ls,"Copy To a stream",{"stream"},[resp](GCList& ls, std::vector<TObject> args)->TObject{
|
||||
TStreamHeapObject* strm;
|
||||
if(GetArgumentHeap(args,0,strm))
|
||||
{
|
||||
resp->CopyToStream(strm->stream);
|
||||
}
|
||||
return nullptr;
|
||||
});
|
||||
|
||||
copyToStream->watch.push_back(dict);
|
||||
dict->SetValue("CopyToStream",copyToStream);
|
||||
|
||||
|
||||
auto readAsString = TExternalMethod::Create(ls,"Read as string",{},[resp](GCList& ls, std::vector<TObject> args)->TObject{
|
||||
return resp->ReadAsString();
|
||||
});
|
||||
|
||||
readAsString->watch.push_back(dict);
|
||||
dict->SetValue("ReadAsString",readAsString);
|
||||
|
||||
auto readAsStream = TExternalMethod::Create(ls,"Read as stream",{},[resp](GCList& ls, std::vector<TObject> args)->TObject{
|
||||
auto res = resp->ReadAsStream();
|
||||
return TStreamHeapObject::Create(ls, res);
|
||||
});
|
||||
|
||||
readAsStream->watch.push_back(dict);
|
||||
dict->SetValue("ReadAsStream",readAsStream);
|
||||
dict->SetValue("StatusCode",(int64_t)resp->statusCode);
|
||||
|
||||
dict->SetValue("Version",resp->version);
|
||||
|
||||
dict->SetValue("ResponseHeaders",CreateDictionaryFromHttpDictionary(ls,&resp->responseHeaders));
|
||||
|
||||
gc->BarrierEnd();
|
||||
return dict;
|
||||
}
|
||||
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void TStd::RegisterNet(GC* gc, TRootEnvironment* env)
|
||||
{
|
||||
|
||||
env->permissions.canRegisterNet=true;
|
||||
GCList ls(gc);
|
||||
TDictionary* dict = TDictionary::Create(ls);
|
||||
|
||||
TDictionary* http = TDictionary::Create(ls);
|
||||
http->DeclareFunction(gc, "UrlEncode","Url encode query param",{"param"}, Net_UrlEncode);
|
||||
http->DeclareFunction(gc, "UrlDecode","Url decode query param",{"param"}, Net_UrlDecode);
|
||||
http->DeclareFunction(gc, "UrlPathEncode","Url encode path",{"path"}, Net_UrlPathEncode);
|
||||
http->DeclareFunction(gc, "UrlPathDecode","Url decode path",{"path"}, Net_UrlPathDecode);
|
||||
http->DeclareFunction(gc, "MimeType","Get mimetype from extension",{"ext"},Net_Http_MimeType);
|
||||
|
||||
|
||||
//http->DeclareFunction(gc, "ProcessServer","Process HTTP server connection",{"networkstream","server","ip","port","encrypted"},, Net_ProcessServer);
|
||||
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);
|
||||
|
||||
dict->DeclareFunction(gc, "NetworkStream","Create a network stream",{"ipv6","datagram"},Net_NetworkStream);
|
||||
gc->BarrierBegin();
|
||||
dict->SetValue("Http", http);
|
||||
env->DeclareVariable("Net", dict);
|
||||
gc->BarrierEnd();
|
||||
}
|
||||
}
|
||||
17
src/runtime_methods/ogc.cpp
Normal file
17
src/runtime_methods/ogc.cpp
Normal file
@ -0,0 +1,17 @@
|
||||
#include "CrossLang.hpp"
|
||||
#if defined(GEKKO)
|
||||
#include <ogcsys.h>
|
||||
#include <gccore.h>
|
||||
#include <ogc/pad.h>
|
||||
#if defined(HW_RVL)
|
||||
#include <wiiuse/wpad.h>
|
||||
#endif
|
||||
#endif
|
||||
namespace Tesses::CrossLang
|
||||
{
|
||||
void TStd::RegisterOGC(GC* gc, TRootEnvironment* env)
|
||||
{
|
||||
|
||||
env->permissions.canRegisterOGC=true;
|
||||
}
|
||||
}
|
||||
82
src/runtime_methods/path.cpp
Normal file
82
src/runtime_methods/path.cpp
Normal file
@ -0,0 +1,82 @@
|
||||
#include "CrossLang.hpp"
|
||||
|
||||
|
||||
|
||||
namespace Tesses::CrossLang
|
||||
{
|
||||
bool GetObjectAsPath(TObject& obj, Tesses::Framework::Filesystem::VFSPath& path, bool allowString)
|
||||
{
|
||||
if(GetObject(obj,path)) return true;
|
||||
std::string str;
|
||||
if(allowString && GetObject<std::string>(obj,str))
|
||||
{
|
||||
path = Tesses::Framework::Filesystem::VFSPath(str);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
bool GetArgumentAsPath(std::vector<TObject>& args, size_t index, Tesses::Framework::Filesystem::VFSPath& path,bool allowString)
|
||||
{
|
||||
if(GetArgument(args,index,path)) return true;
|
||||
std::string str;
|
||||
if(allowString && GetArgument<std::string>(args,index,str))
|
||||
{
|
||||
path = Tesses::Framework::Filesystem::VFSPath(str);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static TObject Path_Root(GCList& ls, std::vector<TObject> args)
|
||||
{
|
||||
auto res = Tesses::Framework::Filesystem::VFSPath();\
|
||||
res.relative=false;
|
||||
return res;
|
||||
}
|
||||
static TObject Path_FromString(GCList& ls, std::vector<TObject> args)
|
||||
{
|
||||
std::string str;
|
||||
if(GetArgument(args,0,str))
|
||||
{
|
||||
return Tesses::Framework::Filesystem::VFSPath(str);
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
static TObject Path_Create(GCList& ls, std::vector<TObject> args)
|
||||
{
|
||||
TList* myls;
|
||||
bool relative;
|
||||
if(GetArgument(args,0,relative) && GetArgumentHeap(args,1,myls))
|
||||
{
|
||||
std::vector<std::string> items;
|
||||
for(int64_t i = 0; i < myls->Count(); i++)
|
||||
{
|
||||
std::string str;
|
||||
TObject o =myls->Get(i);
|
||||
if(GetObject<std::string>(o,str))
|
||||
{
|
||||
items.push_back(str);
|
||||
}
|
||||
}
|
||||
auto res = Tesses::Framework::Filesystem::VFSPath(items);
|
||||
res.relative = relative;
|
||||
return res;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
void TStd::RegisterPath(GC* gc,TRootEnvironment* env)
|
||||
{
|
||||
|
||||
env->permissions.canRegisterPath=true;
|
||||
GCList ls(gc);
|
||||
TDictionary* dict = TDictionary::Create(ls);
|
||||
|
||||
gc->BarrierBegin();
|
||||
dict->DeclareFunction(gc,"FromString","Create a Path from string",{"path"},Path_FromString);
|
||||
dict->DeclareFunction(gc,"Create","Create a Path from parts",{"relative","parts"},Path_Create);
|
||||
dict->DeclareFunction(gc,"Root","Create Absolute Root Path",{}, Path_Root);
|
||||
env->DeclareVariable("Path", dict);
|
||||
gc->BarrierEnd();
|
||||
}
|
||||
}
|
||||
26
src/runtime_methods/process.cpp
Normal file
26
src/runtime_methods/process.cpp
Normal file
@ -0,0 +1,26 @@
|
||||
#include "CrossLang.hpp"
|
||||
|
||||
#if defined(GEKKO)
|
||||
#undef CROSSLANG_ENABLE_PROCESS
|
||||
#endif
|
||||
|
||||
//#if defined(CROSSLANG_ENABLE_PROCESS)
|
||||
#include "subprocess.h"
|
||||
//#endif
|
||||
|
||||
namespace Tesses::CrossLang
|
||||
{
|
||||
//#if defined(CROSSLANG_ENABLE_PROCESS)
|
||||
static TObject Process_Start(GCList& ls, std::vector<TObject> args)
|
||||
{
|
||||
|
||||
//Process.Start({
|
||||
// FileName = "git",
|
||||
// Arguments = ["clone","https://gitea.site.tesses.net/tesses50/crosslang.git"],
|
||||
// Environment = []
|
||||
//})
|
||||
|
||||
|
||||
}
|
||||
//#endif
|
||||
}
|
||||
90
src/runtime_methods/sdl2.cpp
Normal file
90
src/runtime_methods/sdl2.cpp
Normal file
@ -0,0 +1,90 @@
|
||||
#include "CrossLang.hpp"
|
||||
#if defined(CROSSLANG_ENABLE_SDL2)
|
||||
#include <SDL2/SDL.h>
|
||||
#endif
|
||||
namespace Tesses::CrossLang
|
||||
{
|
||||
#if defined(CROSSLANG_ENABLE_SDL2)
|
||||
static TObject SDL2_RenderPresent(GCList& ls, std::vector<TObject> args)
|
||||
{
|
||||
TNative* renderer;
|
||||
if(GetArgumentHeap<TNative*>(args,0,renderer) && !renderer->GetDestroyed())
|
||||
{
|
||||
SDL_RenderPresent((SDL_Renderer*)renderer->GetPointer());
|
||||
}
|
||||
return Undefined();
|
||||
}
|
||||
static TObject SDL2_RenderClear(GCList& ls, std::vector<TObject> args)
|
||||
{
|
||||
TNative* renderer;
|
||||
if(GetArgumentHeap<TNative*>(args,0,renderer) && !renderer->GetDestroyed())
|
||||
{
|
||||
return SDL_RenderClear((SDL_Renderer*)renderer->GetPointer())==0;
|
||||
}
|
||||
return Undefined();
|
||||
}
|
||||
static TObject SDL2_SetRenderDrawColor(GCList& ls, std::vector<TObject> args)
|
||||
{
|
||||
TNative* renderer;
|
||||
int64_t r;
|
||||
int64_t g;
|
||||
int64_t b;
|
||||
int64_t a;
|
||||
if(GetArgumentHeap<TNative*>(args,0,renderer) && !renderer->GetDestroyed() && GetArgument<int64_t>(args,1,r) && GetArgument<int64_t>(args,2,g) && GetArgument<int64_t>(args,3,b) && GetArgument<int64_t>(args,4,a))
|
||||
{
|
||||
return SDL_SetRenderDrawColor((SDL_Renderer*)renderer->GetPointer(),(Uint8)r,(Uint8)g,(Uint8)b,(Uint8)a) == 0;
|
||||
}
|
||||
return Undefined();
|
||||
}
|
||||
|
||||
|
||||
static TObject SDL2_CreateRenderer(GCList& ls, std::vector<TObject> args)
|
||||
{
|
||||
TNative* window;
|
||||
int64_t index;
|
||||
int64_t flags;
|
||||
if(GetArgumentHeap<TNative*>(args,0,window) && !window->GetDestroyed() && GetArgument<int64_t>(args,1,index) && GetArgument<int64_t>(args,2,flags))
|
||||
{
|
||||
SDL_Renderer* _renderer= SDL_CreateRenderer((SDL_Window*)window->GetPointer(),(int)index, (Uint32)flags);
|
||||
if(_renderer == nullptr) return nullptr;
|
||||
return TNative::Create(ls,_renderer,[](void* _ptr)-> void{
|
||||
SDL_DestroyRenderer((SDL_Renderer*)_ptr);
|
||||
});
|
||||
}
|
||||
return Undefined();
|
||||
}
|
||||
static TObject SDL2_CreateWindow(GCList& ls, std::vector<TObject> args)
|
||||
{
|
||||
if(args.size() == 6 && std::holds_alternative<std::string>(args[0]) && std::holds_alternative<int64_t>(args[1]) && std::holds_alternative<int64_t>(args[2]) && std::holds_alternative<int64_t>(args[3]) && std::holds_alternative<int64_t>(args[4]) && std::holds_alternative<int64_t>(args[5]))
|
||||
{
|
||||
SDL_Window* window = SDL_CreateWindow(std::get<std::string>(args[0]).c_str(),(int)std::get<int64_t>(args[1]),(int)std::get<int64_t>(args[2]),(int)std::get<int64_t>(args[3]),(int)std::get<int64_t>(args[4]),(uint32_t)std::get<int64_t>(args[5]));
|
||||
if(window == nullptr) return nullptr;
|
||||
|
||||
return TNative::Create(ls,window,[](void* _ptr)->void {
|
||||
SDL_Window* win = (SDL_Window*)_ptr;
|
||||
if(win != nullptr) SDL_DestroyWindow(win);
|
||||
});
|
||||
}
|
||||
return Undefined();
|
||||
}
|
||||
#endif
|
||||
void TStd::RegisterSDL2(GC* gc, TRootEnvironment* env)
|
||||
{
|
||||
|
||||
env->permissions.canRegisterSDL2=true;
|
||||
#if defined(CROSSLANG_ENABLE_SDL2)
|
||||
GCList ls(gc);
|
||||
TDictionary* dict = TDictionary::Create(ls);
|
||||
|
||||
dict->DeclareFunction(gc, "RenderPresent","Present frame (you are finished with the frame)",{"renderer"},SDL2_RenderPresent);
|
||||
dict->DeclareFunction(gc, "RenderClear","Clear renderer with renderer draw color",{"renderer"},SDL2_RenderClear);
|
||||
dict->DeclareFunction(gc, "SetRenderDrawColor","Set SDL2 Renderer Draw Color",{"renderer","r","g","b","a"},SDL2_SetRenderDrawColor);
|
||||
dict->DeclareFunction(gc, "CreateWindow","Create a SDL2 Window",{"title","x","y","w","h","flags"},SDL2_CreateWindow);
|
||||
dict->DeclareFunction(gc, "CreateRenderer","Create a SDL2 Renderer",{"window",""},SDL2_CreateRenderer);
|
||||
|
||||
gc->BarrierBegin();
|
||||
env->DeclareVariable("SDL2", dict);
|
||||
gc->BarrierEnd();
|
||||
#endif
|
||||
}
|
||||
}
|
||||
139
src/runtime_methods/sqlite.cpp
Normal file
139
src/runtime_methods/sqlite.cpp
Normal file
@ -0,0 +1,139 @@
|
||||
#include "CrossLang.hpp"
|
||||
#if defined(CROSSLANG_ENABLE_SQLITE)
|
||||
#include "../sqlite/sqlite3.h"
|
||||
#endif
|
||||
#include <iostream>
|
||||
namespace Tesses::CrossLang {
|
||||
#if defined(CROSSLANG_ENABLE_SQLITE)
|
||||
static int sqlcollector(void* user, int count,char** vals, char** keys)
|
||||
{
|
||||
|
||||
std::pair<GCList*,TList*>* ls2 = static_cast<std::pair<GCList*,TList*>*>(user);
|
||||
TDictionary* dict = TDictionary::Create(ls2->first);
|
||||
for(int i = 0; i < count; i++)
|
||||
{
|
||||
std::string key = keys[i] == nullptr ? "" : keys[i];
|
||||
|
||||
if(vals[i] == nullptr)
|
||||
{
|
||||
dict->SetValue(key,nullptr);
|
||||
}
|
||||
else
|
||||
{
|
||||
dict->SetValue(key,vals[i]);
|
||||
}
|
||||
}
|
||||
ls2->second->Add(dict);
|
||||
|
||||
return 0;
|
||||
}
|
||||
TObject Sqlite_Open(GCList& ls, std::vector<TObject> args,TRootEnvironment* env)
|
||||
{
|
||||
Tesses::Framework::Filesystem::VFSPath p;
|
||||
if(GetArgumentAsPath(args,0,p))
|
||||
{
|
||||
if(env->permissions.sqlite3Scoped)
|
||||
{
|
||||
p = env->permissions.sqliteOffsetPath / p.CollapseRelativeParents();
|
||||
}
|
||||
std::string name = p.ToString();
|
||||
|
||||
sqlite3* sqlite;
|
||||
std::cout << name << std::endl;
|
||||
int rc =sqlite3_open(name.c_str(),&sqlite);
|
||||
if(rc)
|
||||
{
|
||||
std::string error = sqlite3_errmsg(sqlite);
|
||||
sqlite3_close(sqlite);
|
||||
return error;
|
||||
}
|
||||
return TNative::Create(ls,sqlite,[](void* a)->void {
|
||||
if(a != nullptr)
|
||||
sqlite3_close((sqlite3*)a);
|
||||
});
|
||||
}
|
||||
|
||||
return Undefined();
|
||||
|
||||
}
|
||||
TObject Sqlite_Exec(GCList& ls, std::vector<TObject> args)
|
||||
{
|
||||
if(args.size() == 2 && std::holds_alternative<THeapObjectHolder>(args[0]) && std::holds_alternative<std::string>(args[1]))
|
||||
{
|
||||
TNative* native = dynamic_cast<TNative*>(std::get<THeapObjectHolder>(args[0]).obj);
|
||||
std::string sqlStatement = std::get<std::string>(args[1]);
|
||||
if(native != nullptr && !native->GetDestroyed())
|
||||
{
|
||||
sqlite3* sql = (sqlite3*)native->GetPointer();
|
||||
TList* myLs = TList::Create(ls);
|
||||
std::pair<GCList*,TList*> result(&ls, myLs);
|
||||
char* err;
|
||||
int res = sqlite3_exec(sql,sqlStatement.c_str(),sqlcollector,&result,&err);
|
||||
if(res != SQLITE_OK)
|
||||
{
|
||||
std::string errstr = err == nullptr ? "" : err;
|
||||
sqlite3_free(err);
|
||||
return errstr;
|
||||
}
|
||||
|
||||
return myLs;
|
||||
}
|
||||
}
|
||||
|
||||
return Undefined();
|
||||
|
||||
}
|
||||
|
||||
TObject Sqlite_Escape(GCList& ls, std::vector<TObject> args)
|
||||
{
|
||||
if(args.size() == 1 && std::holds_alternative<std::string>(args[0]))
|
||||
{
|
||||
std::string srcStr = std::get<std::string>(args[0]);
|
||||
std::string myStr = "\'";
|
||||
for(auto c : srcStr)
|
||||
{
|
||||
if(c == '\'') myStr += "\'\'";
|
||||
else
|
||||
myStr += c;
|
||||
}
|
||||
myStr += '\'';
|
||||
return myStr;
|
||||
}
|
||||
return Undefined();
|
||||
}
|
||||
|
||||
TObject Sqlite_Close(GCList& ls, std::vector<TObject> args)
|
||||
{
|
||||
if(args.size() == 1 && std::holds_alternative<THeapObjectHolder>(args[0]))
|
||||
{
|
||||
TNative* native = dynamic_cast<TNative*>(std::get<THeapObjectHolder>(args[0]).obj);
|
||||
|
||||
if(native != nullptr && !native->GetDestroyed())
|
||||
{
|
||||
native->Destroy();
|
||||
}
|
||||
}
|
||||
return Undefined();
|
||||
}
|
||||
|
||||
#endif
|
||||
void TStd::RegisterSqlite(GC* gc,TRootEnvironment* env)
|
||||
{
|
||||
|
||||
env->permissions.canRegisterSqlite=true;
|
||||
#if defined(CROSSLANG_ENABLE_SQLITE)
|
||||
GCList ls(gc);
|
||||
TDictionary* dict = TDictionary::Create(ls);
|
||||
dict->DeclareFunction(gc,"Open","Opens the database (returns database handle or an error message as string or undefined)",{"filename"},[env](GCList& ls, std::vector<TObject> args)->TObject {
|
||||
return Sqlite_Open(ls,args,env);
|
||||
});
|
||||
dict->DeclareFunction(gc,"Exec","Execute sql (returns dictionary of columns key=value, an error message as string or undefined)",{"handle","sql"},Sqlite_Exec);
|
||||
dict->DeclareFunction(gc,"Close","Close sql database",{"handle"},Sqlite_Close);
|
||||
dict->DeclareFunction(gc,"Escape","Escape sql text",{"text"},Sqlite_Escape);
|
||||
|
||||
gc->BarrierBegin();
|
||||
env->DeclareVariable("Sqlite", dict);
|
||||
gc->BarrierEnd();
|
||||
#endif
|
||||
}
|
||||
}
|
||||
242
src/runtime_methods/std.cpp
Normal file
242
src/runtime_methods/std.cpp
Normal file
@ -0,0 +1,242 @@
|
||||
#include "CrossLang.hpp"
|
||||
|
||||
namespace Tesses::CrossLang
|
||||
{
|
||||
TObject TypeOf(GCList& ls, std::vector<TObject> args)
|
||||
{
|
||||
if(args.size() < 1) return "Undefined";
|
||||
if(std::holds_alternative<Undefined>(args[0])) return "Undefined";
|
||||
if(std::holds_alternative<std::nullptr_t>(args[0])) return "Null";
|
||||
if(std::holds_alternative<bool>(args[0])) return "Boolean";
|
||||
if(std::holds_alternative<int64_t>(args[0])) return "Long";
|
||||
if(std::holds_alternative<double>(args[0])) return "Double";
|
||||
if(std::holds_alternative<char>(args[0])) return "Char";
|
||||
if(std::holds_alternative<MethodInvoker>(args[0])) return "MethodInvoker";
|
||||
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<THeapObjectHolder>(args[0]))
|
||||
{
|
||||
auto obj = std::get<THeapObjectHolder>(args[0]).obj;
|
||||
auto dict = dynamic_cast<TDictionary*>(obj);
|
||||
auto list = dynamic_cast<TList*>(obj);
|
||||
auto argWrapper = dynamic_cast<TArgWrapper*>(obj);
|
||||
auto closure = dynamic_cast<TClosure*>(obj);
|
||||
auto externalMethod = dynamic_cast<TExternalMethod*>(obj);
|
||||
auto byteArray = dynamic_cast<TByteArray*>(obj);
|
||||
auto native = dynamic_cast<TNative*>(obj);
|
||||
auto vfs = dynamic_cast<TVFSHeapObject*>(obj);
|
||||
auto strm = dynamic_cast<TStreamHeapObject*>(obj);
|
||||
if(strm != nullptr)
|
||||
{
|
||||
auto netStrm = dynamic_cast<Tesses::Framework::Streams::NetworkStream*>(strm->stream);
|
||||
if(netStrm != nullptr)
|
||||
{
|
||||
return "NetworkStream";
|
||||
}
|
||||
|
||||
|
||||
return "Stream";
|
||||
}
|
||||
if(vfs != nullptr)
|
||||
{
|
||||
auto localVFS = dynamic_cast<Tesses::Framework::Filesystem::LocalFilesystem*>(vfs->vfs);
|
||||
|
||||
auto mountableVFS = dynamic_cast<Tesses::Framework::Filesystem::MountableFilesystem*>(vfs->vfs);
|
||||
|
||||
|
||||
auto subFS = dynamic_cast<Tesses::Framework::Filesystem::SubdirFilesystem*>(vfs->vfs);
|
||||
|
||||
if(localVFS != nullptr) return "LocalFilesystem";
|
||||
if(subFS != nullptr) return "SubdirFilesystem";
|
||||
if(mountableVFS != nullptr) return "MountableFilesystem";
|
||||
|
||||
return "VFS";
|
||||
}
|
||||
if(dict != nullptr) return "Dictionary";
|
||||
if(list != nullptr) return "List";
|
||||
if(argWrapper != nullptr) return "ArgWrapper";
|
||||
if(closure != nullptr) return "Closure";
|
||||
if(externalMethod != nullptr) return "ExternalMethod";
|
||||
if(byteArray != nullptr) return "ByteArray";
|
||||
if(native != nullptr) return "Native";
|
||||
|
||||
return "HeapObject";
|
||||
}
|
||||
|
||||
return "Object";
|
||||
}
|
||||
|
||||
TObject ByteArray(GCList& ls, std::vector<TObject> args)
|
||||
{
|
||||
auto res= TByteArray::Create(ls);
|
||||
if(args.size() == 1){
|
||||
|
||||
if(std::holds_alternative<int64_t>(args[0]))
|
||||
res->data.resize((size_t)std::get<int64_t>(args[0]));
|
||||
else if(std::holds_alternative<std::string>(args[0]))
|
||||
{
|
||||
std::string& txt = std::get<std::string>(args[0]);
|
||||
res->data.insert(res->data.end(), txt.begin(),txt.end());
|
||||
}
|
||||
|
||||
}
|
||||
return res;
|
||||
|
||||
}
|
||||
TObject ParseLong(GCList& ls, std::vector<TObject> args)
|
||||
{
|
||||
|
||||
if(args.size() >= 1)
|
||||
{
|
||||
int base = 10;
|
||||
|
||||
if(args.size() == 2 && std::holds_alternative<int64_t>(args[1]))
|
||||
{
|
||||
base = (int)std::get<int64_t>(args[1]);
|
||||
}
|
||||
|
||||
size_t pos;
|
||||
|
||||
|
||||
std::string str = ToString(ls.GetGC(),args[0]);
|
||||
|
||||
try {
|
||||
int64_t v = std::stoll(str,&pos,base);
|
||||
if(pos < str.size()) return nullptr;
|
||||
return v;
|
||||
}catch(std::exception& ex)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
}
|
||||
return nullptr;
|
||||
|
||||
}
|
||||
TObject ParseDouble(GCList& ls, std::vector<TObject> args)
|
||||
{
|
||||
|
||||
if(args.size() == 1)
|
||||
{
|
||||
|
||||
|
||||
size_t pos;
|
||||
|
||||
|
||||
std::string str = ToString(ls.GetGC(),args[0]);
|
||||
|
||||
try {
|
||||
double v = std::stod(str,&pos);
|
||||
if(pos < str.size()) return nullptr;
|
||||
return v;
|
||||
}catch(std::exception& ex)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
}
|
||||
return nullptr;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
static TObject Throw(GCList& ls, std::vector<TObject> args)
|
||||
{
|
||||
if(!args.empty())
|
||||
{
|
||||
VMByteCodeException bce(ls.GetGC(),args[0]);
|
||||
throw bce;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
static TObject Try(GCList& ls, std::vector<TObject> args)
|
||||
{
|
||||
TCallable* tryPart;
|
||||
TCallable* catchPart;
|
||||
if(GetArgumentHeap(args,0,tryPart) && GetArgumentHeap(args,1,catchPart))
|
||||
{
|
||||
try {
|
||||
tryPart->Call(ls,{});
|
||||
}
|
||||
catch(VMByteCodeException& ex)
|
||||
{
|
||||
catchPart->Call(ls,{ex.exception});
|
||||
}
|
||||
catch(std::exception& ex)
|
||||
{
|
||||
TDictionary* dict = TDictionary::Create(ls);
|
||||
auto gc = ls.GetGC();
|
||||
gc->BarrierBegin();
|
||||
dict->SetValue("Type","NativeException");
|
||||
dict->SetValue("Text",ex.what());
|
||||
gc->BarrierEnd();
|
||||
catchPart->Call(ls,{dict});
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
EnvironmentPermissions::EnvironmentPermissions()
|
||||
{
|
||||
this->canRegisterConsole=false;
|
||||
this->canRegisterCrypto=false;
|
||||
this->canRegisterDictionary=false;
|
||||
this->canRegisterEnv=false;
|
||||
this->canRegisterIO=false;
|
||||
this->canRegisterJSON=false;
|
||||
this->canRegisterLocalFS=false;
|
||||
this->canRegisterNet=false;
|
||||
this->canRegisterOGC=false;
|
||||
this->canRegisterPath=false;
|
||||
this->canRegisterRoot=false;
|
||||
this->canRegisterSDL2=false;
|
||||
this->canRegisterSqlite=false;
|
||||
this->canRegisterVM = false;
|
||||
this->locked=false;
|
||||
this->sqlite3Scoped=false;
|
||||
|
||||
}
|
||||
|
||||
void TStd::RegisterRoot(GC* gc, TRootEnvironment* env)
|
||||
{
|
||||
|
||||
env->permissions.canRegisterRoot=true;
|
||||
env->DeclareFunction(gc, "ParseLong","Parse Long from String",{"arg","$base"},ParseLong);
|
||||
|
||||
env->DeclareFunction(gc, "ParseDouble","Parse Double from String",{"arg"},ParseDouble);
|
||||
env->DeclareFunction(gc, "TypeOf","Get type of object",{"object"},TypeOf);
|
||||
env->DeclareFunction(gc, "Throw", "Throw an exception",{"object"},Throw);
|
||||
env->DeclareFunction(gc, "Try", "Handle exceptions",{"callbackToTry","callbackToCatch"},Try);
|
||||
env->DeclareFunction(gc, "Thread","Create thread",{"callback"},[](GCList& ls, std::vector<TObject> args)-> TObject
|
||||
{
|
||||
if(args.size() == 1 && std::holds_alternative<THeapObjectHolder>(args[0]))
|
||||
{
|
||||
auto cb = dynamic_cast<TCallable*>(std::get<THeapObjectHolder>(args[0]).obj);
|
||||
if(cb != nullptr)
|
||||
{
|
||||
return CreateThread(ls,cb,false);
|
||||
}
|
||||
}
|
||||
return Undefined();
|
||||
});
|
||||
env->DeclareFunction(gc,"ByteArray","Create bytearray, with optional either size (to size it) or string argument (to fill byte array)",{"$data"},ByteArray);
|
||||
|
||||
}
|
||||
void TStd::RegisterStd(GC* gc, TRootEnvironment* env)
|
||||
{
|
||||
RegisterEnv(gc, env);
|
||||
RegisterRoot(gc,env);
|
||||
RegisterPath(gc,env);
|
||||
RegisterConsole(gc, env);
|
||||
RegisterIO(gc, env);
|
||||
RegisterNet(gc, env);
|
||||
RegisterSqlite(gc, env);
|
||||
RegisterVM(gc, env);
|
||||
RegisterJson(gc, env);
|
||||
RegisterDictionary(gc, env);
|
||||
RegisterCrypto(gc,env);
|
||||
RegisterSDL2(gc, env);
|
||||
RegisterOGC(gc, env);
|
||||
env->permissions.locked=true;
|
||||
}
|
||||
}
|
||||
1203
src/runtime_methods/subprocess.h
Normal file
1203
src/runtime_methods/subprocess.h
Normal file
File diff suppressed because it is too large
Load Diff
211
src/runtime_methods/vm.cpp
Normal file
211
src/runtime_methods/vm.cpp
Normal file
@ -0,0 +1,211 @@
|
||||
|
||||
#include "CrossLang.hpp"
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
|
||||
namespace Tesses::CrossLang
|
||||
{
|
||||
static TObject VM_Eval(GCList& ls, std::vector<TObject> args)
|
||||
{
|
||||
std::string str;
|
||||
if(GetArgument(args,0,str))
|
||||
{
|
||||
if(current_function != nullptr)
|
||||
{
|
||||
return current_function->env->Eval(ls,str);
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
static TObject Failure(GCList& ls, std::string reason)
|
||||
{
|
||||
TDictionary* dict = TDictionary::Create(ls);
|
||||
ls.GetGC()->BarrierBegin();
|
||||
dict->SetValue("Success",false);
|
||||
dict->SetValue("Reason", reason);
|
||||
ls.GetGC()->BarrierEnd();
|
||||
return dict;
|
||||
}
|
||||
static TObject Success(GCList& ls)
|
||||
{
|
||||
TDictionary* dict = TDictionary::Create(ls);
|
||||
ls.GetGC()->BarrierBegin();
|
||||
dict->SetValue("Success",true);
|
||||
ls.GetGC()->BarrierEnd();
|
||||
return dict;
|
||||
}
|
||||
static TObject VM_getCurrentEnvironment(GCList& ls2,std::vector<TObject> args)
|
||||
{
|
||||
if(current_function != nullptr) return current_function->env;
|
||||
return Undefined();
|
||||
}
|
||||
static TObject VM_Compile(GCList& ls, std::vector<TObject> args)
|
||||
{
|
||||
try {
|
||||
TDictionary* dict;
|
||||
if(!GetArgumentHeap<TDictionary*>(args,0,dict)) return Undefined();
|
||||
/*
|
||||
VM.Compile
|
||||
{
|
||||
Name = "My name",
|
||||
Info = "",
|
||||
Sources = [],
|
||||
Version = "",
|
||||
Dependencies = [{Name="Name", Version}],
|
||||
ResourceDirectory = "",
|
||||
|
||||
}
|
||||
*/
|
||||
|
||||
std::string name = "Out";
|
||||
std::vector<std::pair<std::string,std::string>> sources;
|
||||
TVMVersion version(TVM_MAJOR,TVM_MINOR,TVM_PATCH,TVM_BUILD,TVM_VERSIONSTAGE);
|
||||
std::vector<std::pair<std::string,TVMVersion>> dependencies;
|
||||
std::string info;
|
||||
TVFSHeapObject* vfsHO =nullptr;
|
||||
|
||||
ls.GetGC()->BarrierBegin();
|
||||
TObject _name = dict->GetValue("Name");
|
||||
TObject _version = dict->GetValue("Version");
|
||||
TObject _sources = dict->GetValue("Sources");
|
||||
TObject _dependencies = dict->GetValue("Dependencies");
|
||||
TObject _info = dict->GetValue("Info");
|
||||
TObject _resourceFileSystem = dict->GetValue("ResourceFileSystem");
|
||||
|
||||
TObject _out = dict->GetValue("Output");
|
||||
TList* _depList; TList* srcLst;
|
||||
GetObject<std::string>(_name,name);
|
||||
GetObject<std::string>(_info,info);
|
||||
GetObjectHeap(_resourceFileSystem, vfsHO);
|
||||
std::string v2;
|
||||
if(GetObject<std::string>(_version,v2))
|
||||
TVMVersion::TryParse(v2, version);
|
||||
|
||||
if(GetObjectHeap<TList*>(_dependencies,_depList))
|
||||
{
|
||||
for(int64_t i = 0; i < _depList->Count(); i++)
|
||||
{
|
||||
TObject _dep = _depList->Get(i);
|
||||
TDictionary* _depD;
|
||||
if(GetObjectHeap<TDictionary*>(_dep, _depD))
|
||||
{
|
||||
TObject _name2 = _depD->GetValue("Name");
|
||||
TObject _version2 = _depD->GetValue("Version");
|
||||
std::string name2;
|
||||
std::string version2;
|
||||
TVMVersion version02;
|
||||
|
||||
if(GetObject<std::string>(_name2,name2) && GetObject<std::string>(_version2,version2) && TVMVersion::TryParse(version2,version02))
|
||||
{
|
||||
dependencies.push_back(std::pair<std::string,TVMVersion>(name2, version02));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
if(GetObjectHeap<TList*>(_sources,srcLst))
|
||||
{
|
||||
for(int64_t i = 0; i < srcLst->Count(); i++)
|
||||
{
|
||||
TObject _src = srcLst->Get(i);
|
||||
TDictionary* _srcD;
|
||||
if(GetObjectHeap<TDictionary*>(_src, _srcD))
|
||||
{
|
||||
TObject _sourceTxt = _srcD->GetValue("Source");
|
||||
TObject _filename = _srcD->GetValue("FileName");
|
||||
|
||||
|
||||
std::string srctxt = "";
|
||||
std::string filename = "memory_" + std::to_string(i) + ".tcross";
|
||||
bool fromFile = false;
|
||||
|
||||
GetObject<std::string>(_sourceTxt,srctxt);
|
||||
GetObject<std::string>(_filename,filename);
|
||||
|
||||
|
||||
sources.push_back(std::pair<std::string,std::string>(srctxt,filename));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
ls.GetGC()->BarrierEnd();
|
||||
|
||||
std::vector<LexToken> tokens;
|
||||
for(auto source : sources)
|
||||
{
|
||||
std::stringstream strm(source.first);
|
||||
|
||||
int res = Lex(source.second, strm, tokens);
|
||||
if(res != 0)
|
||||
{
|
||||
return Failure(ls, "Lex error in file \"" + source.second + "\":" + std::to_string(res));
|
||||
}
|
||||
}
|
||||
Parser parser(tokens);
|
||||
SyntaxNode n = parser.ParseRoot();
|
||||
CodeGen gen;
|
||||
gen.GenRoot(n);
|
||||
gen.dependencies = dependencies;
|
||||
gen.info = info;
|
||||
gen.name = name;
|
||||
gen.version = version;
|
||||
std::string outpath;
|
||||
TStreamHeapObject* stream;
|
||||
if(GetObjectHeap<TStreamHeapObject*>(_out, stream))
|
||||
{
|
||||
gen.Save(vfsHO != nullptr ? vfsHO->vfs : nullptr, stream->stream);
|
||||
}
|
||||
|
||||
|
||||
|
||||
return Success(ls);
|
||||
} catch(std::exception& ex)
|
||||
{
|
||||
return Failure(ls, ex.what());
|
||||
}
|
||||
}
|
||||
void TStd::RegisterVM(GC* gc,TRootEnvironment* env)
|
||||
{
|
||||
|
||||
env->permissions.canRegisterVM=true;
|
||||
GCList ls(gc);
|
||||
TDictionary* dict = TDictionary::Create(ls);
|
||||
dict->DeclareFunction(gc, "getRootEnvironmentAsDictionary","Get root environment as a dictionary",{},[env](GCList& ls, std::vector<TObject> args)-> TObject{
|
||||
return env->GetDictionary();
|
||||
});
|
||||
dict->DeclareFunction(gc, "getRootEnvironment","Get root environment, for reflection purposes",{},[env](GCList& ls2,std::vector<TObject> args)->TObject {return env;});
|
||||
dict->DeclareFunction(gc, "getCurrentEnvironment","Get current environment, for reflection purposes",{},VM_getCurrentEnvironment);
|
||||
dict->DeclareFunction(gc, "CreateEnvironment","Create root environment",{"$dict"},[](GCList& ls,std::vector<TObject> args)->TObject{
|
||||
TDictionary* dict;
|
||||
if(GetArgumentHeap(args,0,dict))
|
||||
{
|
||||
return TRootEnvironment::Create(ls,dict);
|
||||
}
|
||||
else
|
||||
{
|
||||
return TRootEnvironment::Create(ls,TDictionary::Create(ls));
|
||||
}
|
||||
});
|
||||
dict->DeclareFunction(gc, "LoadExecutable", "Load a crossvm executable",{"stream"},[](GCList& ls,std::vector<TObject> args)->TObject{
|
||||
TStreamHeapObject* strm;
|
||||
if(GetArgumentHeap(args,0,strm))
|
||||
{
|
||||
TFile* f =TFile::Create(ls);
|
||||
f->Load(ls.GetGC(),strm->stream);
|
||||
return f;
|
||||
}
|
||||
return nullptr;
|
||||
});
|
||||
dict->DeclareFunction(gc, "Eval", "Eval source code",{"source"}, VM_Eval);
|
||||
dict->DeclareFunction(gc, "Compile", "Compile Source",{"dict"},VM_Compile);
|
||||
|
||||
|
||||
|
||||
gc->BarrierBegin();
|
||||
env->DeclareVariable("VM", dict);
|
||||
gc->BarrierEnd();
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user