Files
crosslang/src/vm/bc/executemethod2.cpp

3988 lines
166 KiB
C++

#include "CrossLang.hpp"
#include "TessesFramework/Serialization/BitConverter.hpp"
#include "TessesFramework/Streams/ByteReader.hpp"
#include "TessesFramework/Streams/ByteWriter.hpp"
#include "TessesFramework/Uuid.hpp"
#include <cstddef>
#include <cstdint>
#include <exception>
#include <iostream>
#include <cmath>
#include <cstring>
#include <sstream>
#include <variant>
namespace Tesses::CrossLang {
extern bool IHttpServer_Handle(std::shared_ptr<Tesses::Framework::Http::IHttpServer> svr,std::vector<TObject>& args);
bool InterperterThread::ExecuteMethod2(std::shared_ptr<GC> gc, TObject instance, std::string key, std::vector<TObject> args)
{
std::vector<CallStackEntry*>& cse=this->call_stack_entries;
if(!cse.empty())
{
GCList ls(gc);
std::regex regex;
TVMVersion version;
if(std::holds_alternative<std::nullptr_t>(instance))
{
if(key == "ToString")
{
cse.back()->Push(gc,"null");
return false;
}
cse.back()->Push(gc,Undefined());
return false;
}else if(std::holds_alternative<Undefined>(instance))
{
if(key == "ToString")
{
cse.back()->Push(gc,"undefined");
return false;
}
cse.back()->Push(gc,Undefined());
return false;
}
else
if(GetObject(instance, version))
{
if(key == "ToString")
{
cse.back()->Push(gc, version.ToString());
return false;
}
if(key == "ToByteArray")
{
TByteArray* ba = TByteArray::Create(ls);
ba->data.resize(5);
version.ToArray(ba->data.data());
cse.back()->Push(gc,ba);
return false;
}
cse.back()->Push(gc, Undefined());
return false;
}
else if(GetObject(instance,regex))
{
if(key == "Search")
{
std::string str;
if(GetArgument(args,0,str))
{
std::smatch m;
if(std::regex_search(str,m,regex))
{
auto myLs = TList::Create(ls);
gc->BarrierBegin();
for(auto item : m)
{
auto itm = TDictionary::Create(ls);
itm->SetValue("Offset", (int64_t)(item.first-str.begin()));
itm->SetValue("Length",(int64_t)item.length());
itm->SetValue("Matched",item.matched);
itm->SetValue("Text",item.str());
myLs->Add(itm);
}
cse.back()->Push(gc, myLs);
gc->BarrierEnd();
return false;
}
}
}
cse.back()->Push(gc, nullptr);
return false;
}
else if(std::holds_alternative<bool>(instance))
{
bool flag = std::get<bool>(instance);
if(key == "ToString")
{
cse.back()->Push(gc, flag ? "true" : "false");
return false;
}
else if(key == "ToLong")
{
cse.back()->Push(gc, flag ? (int64_t)1 : (int64_t)0);
return false;
}
cse.back()->Push(gc, Undefined());
return false;
}
else if(std::holds_alternative<char>(instance))
{
char c = std::get<char>(instance);
if(key == "ToString")
{
cse.back()->Push(gc, std::string{c});
return false;
}
else if(key == "ToLong")
{
uint8_t uc = (uint8_t)c;
cse.back()->Push(gc, (int64_t)uc);
return false;
}
else if(key == "IsAscii")
{
bool isAscii = c >= 0;
cse.back()->Push(gc, isAscii);
return false;
}
if(key == "IsLetter")
{
bool isLetter = (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z');
cse.back()->Push(gc, isLetter);
return false;
}
if(key == "IsDigit")
{
bool isDigit = (c >= '0' && c <= '9');
cse.back()->Push(gc, isDigit);
return false;
}
if(key == "IsLetterOrDigit")
{
bool isDigit = (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || (c >= '0' && c <= '9');
cse.back()->Push(gc, isDigit);
return false;
}
if(key == "ToLower")
{
if(c >= 'A' && c <= 'Z')
cse.back()->Push(gc, (char)tolower(c));
else
cse.back()->Push(gc, c);
return false;
}
if(key == "ToUpper")
{
if(c >= 'a' && c <= 'z')
cse.back()->Push(gc, (char)toupper(c));
else
cse.back()->Push(gc, c);
return false;
}
cse.back()->Push(gc, Undefined());
return false;
}
else if(std::holds_alternative<double>(instance))
{
double number = std::get<double>(instance);
if(key == "ToString")
{
cse.back()->Push(gc, std::to_string(number));
return false;
}
if(key == "ToLong")
{
cse.back()->Push(gc, (int64_t)number);
return false;
}
if(key == "ToLongBits")
{
cse.back()->Push(gc, *(int64_t*)&number);
return false;
}
if(key == "Floor")
{
cse.back()->Push(gc,floor(number));
return false;
}
if(key == "Ceiling")
{
cse.back()->Push(gc,ceil(number));
return false;
}
if(key == "Abs")
{
cse.back()->Push(gc,fabs(number));
return false;
}
if(key == "Pow")
{
if(args.size() != 1)
{
throw VMException("Double.Pow must only accept one argument");
}
if(!std::holds_alternative<double>(args[0]))
{
throw VMException("Double.Pow must only accept a double");
}
cse.back()->Push(gc,pow(number, std::get<double>(args[0])));
return false;
}
if(key == "Atan2")
{
if(args.size() != 1)
{
throw VMException("Double.Atan2 must only accept one argument");
}
if(!std::holds_alternative<double>(args[0]))
{
throw VMException("Double.Atan2 must only accept a double");
}
cse.back()->Push(gc,atan2(number, std::get<double>(args[0])));
return false;
}
if(key == "Atan")
{
cse.back()->Push(gc,tan(number));
return false;
}
if(key == "Tan")
{
cse.back()->Push(gc,tan(number));
return false;
}
if(key == "Tanh")
{
cse.back()->Push(gc,tanh(number));
return false;
}
if(key == "Asin")
{
cse.back()->Push(gc,asin(number));
return false;
}
if(key == "Sin")
{
cse.back()->Push(gc,sin(number));
return false;
}
if(key == "Sinh")
{
cse.back()->Push(gc,sinh(number));
return false;
}
if(key == "Acos")
{
cse.back()->Push(gc,acos(number));
return false;
}
if(key == "Cos")
{
cse.back()->Push(gc,cos(number));
return false;
}
if(key == "Cosh")
{
cse.back()->Push(gc,cosh(number));
return false;
}
if(key == "Log")
{
cse.back()->Push(gc,log(number));
return false;
}
if(key == "Log10")
{
cse.back()->Push(gc,log10(number));
return false;
}
if(key == "Sqrt")
{
cse.back()->Push(gc,sqrt(number));
return false;
}
cse.back()->Push(gc, Undefined());
return false;
}
else if(std::holds_alternative<int64_t>(instance))
{
int64_t number = std::get<int64_t>(instance);
if(key == "ToHexString")
{
int64_t width = 1;
if(!GetArgument(args,0,width)) width=1;
size_t _width = (size_t)width;
std::stringstream strm;
if(_width > 1)
strm << std::setfill('0') << std::setw((int)_width) << std::hex << number;
else
strm << std::hex << number;
cse.back()->Push(gc,strm.str());
return false;
}
if(key == "ToString")
{
cse.back()->Push(gc, std::to_string(number));
return false;
}
if(key == "ToChar")
{
uint8_t c = (uint8_t)number;
cse.back()->Push(gc, (char)c);
return false;
}
if(key == "Abs")
{
if(number < 0)
cse.back()->Push(gc, -number);
else
cse.back()->Push(gc, number);
return false;
}
if(key == "ToDouble")
{
cse.back()->Push(gc,(double)number);
return false;
}
if(key == "ToDoubleBits")
{
cse.back()->Push(gc,*(double*)&number);
return false;
}
cse.back()->Push(gc, Undefined());
return false;
}
else if(std::holds_alternative<Tesses::Framework::Filesystem::VFSPath>(instance))
{
auto path = std::get<Tesses::Framework::Filesystem::VFSPath>(instance);
if(key == "GetEnumerator")
{
TList* _ls = TList::Create(ls);
for(auto item : path.path)
{
_ls->Add(item);
}
cse.back()->Push(gc, TListEnumerator::Create(ls,_ls));
return false;
}
if(key == "ToString")
{
cse.back()->Push(gc, path.ToString());
return false;
}
if(key == "GetAt")
{
int64_t index;
if(GetArgument(args,0,index))
{
size_t idx = (size_t)idx;
if(idx < path.path.size())
cse.back()->Push(gc, path.path[idx]);
else
cse.back()->Push(gc, nullptr);
return false;
}
}
if(key == "Count" || key == "Length")
{
cse.back()->Push(gc, (int64_t)path.path.size());
return false;
}
if(key == "GetParent")
{
cse.back()->Push(gc, path.GetParent());
return false;
}
if(key == "GetFileName")
{
cse.back()->Push(gc, path.GetFileName());
return false;
}
if(key == "GetExtension")
{
cse.back()->Push(gc, path.GetExtension());
return false;
}
if(cse.back()->env->GetRootEnvironment()->permissions.localfs && key == "MakeAbsolute")
{
Tesses::Framework::Filesystem::VFSPath p;
if(GetArgumentAsPath(args,0,p))
{
cse.back()->Push(gc,path.MakeAbsolute(p));
return false;
}
else
{
cse.back()->Push(gc,path.MakeAbsolute(cse.back()->env->GetRootEnvironment()->permissions.localfs->GetWorking()));
return false;
}
}
if(cse.back()->env->GetRootEnvironment()->permissions.localfs && key == "MakeRelative")
{
Tesses::Framework::Filesystem::VFSPath p;
if(GetArgumentAsPath(args,0,p))
{
cse.back()->Push(gc,path.MakeRelative(p));
return false;
}
else
{
cse.back()->Push(gc,path.MakeRelative(cse.back()->env->GetRootEnvironment()->permissions.localfs->GetWorking()));
return false;
}
}
if(key == "ChangeExtension")
{
Tesses::Framework::Filesystem::VFSPath newPath = path;
std::string ext;
if(GetArgument(args,0, ext))
{
newPath.ChangeExtension(ext);
}
else
{
newPath.RemoveExtension();
}
cse.back()->Push(gc, newPath);
return false;
}
if(key == "CollapseRelativeParents")
{
cse.back()->Push(gc, path.CollapseRelativeParents());
return false;
}
if(key == "IsRelative")
{
cse.back()->Push(gc, path.relative);
return false;
//Path.FromString();
}
}
else if(std::holds_alternative<std::string>(instance))
{
std::string str = std::get<std::string>(instance);
if(key == "ToLower")
{
for(size_t i = 0; i < str.size(); i++)
{
if(str[i] >= 'A' && str[i] <= 'Z')
{
str[i] = 'a' + (str[i] - 'A');
}
}
cse.back()->Push(gc, str);
return false;
}
if(key == "ToUpper")
{
for(size_t i = 0; i < str.size(); i++)
{
if(str[i] >= 'a' && str[i] <= 'z')
{
str[i] = 'A' + (str[i] - 'a');
}
}
cse.back()->Push(gc, str);
return false;
}
if(key == "PadLeft")
{
int64_t pad;
char padChar=' ';
if(args.size() == 0 || args.size() > 2)
{
throw VMException("String.PadLeft must only accept 1 or 2 arguments");
}
if(GetArgument(args,0, pad))
{
if((size_t)pad < str.size()) {
cse.back()->Push(gc, str);
return false;
}
GetArgument(args,1, padChar);
size_t diff = (size_t)pad - str.size();
str.insert(str.begin(),diff, padChar);
cse.back()->Push(gc, str);
return false;
}
else throw VMException("String.PadLeft must have a long for width");
}
if(key == "PadRight")
{
int64_t pad;
char padChar=' ';
if(args.size() == 0 || args.size() > 2)
{
throw VMException("String.PadRight must only accept 1 or 2 arguments");
}
if(GetArgument(args,0, pad))
{
if((size_t)pad < str.size()) {
cse.back()->Push(gc, str);
return false;
}
GetArgument(args,1, padChar);
size_t diff = (size_t)pad - str.size();
str.insert(str.end(),diff, padChar);
cse.back()->Push(gc, str);
return false;
}
else throw VMException("String.PadRight must have a long for width");
}
if(key == "Contains")
{
std::string str2;
char c;
if(GetArgument(args,0,str2))
{
int64_t index = 0;
GetArgument(args,1,index);
auto res = str.find(str2,(std::size_t)index);
cse.back()->Push(gc, res != std::string::npos);
return false;
}
else if(GetArgument<char>(args,0,c))
{
int64_t index = 0;
GetArgument(args,1,index);
auto res = str.find_first_of(c,(std::size_t)index);
cse.back()->Push(gc, res != std::string::npos);
return false;
}
cse.back()->Push(gc,nullptr);
return false;
}
if(key == "IndexOf")
{
std::string str2;
char c;
if(GetArgument(args,0,str2))
{
int64_t index = 0;
GetArgument(args,1,index);
auto res = str.find(str2,(std::size_t)index);
if(res == std::string::npos)
cse.back()->Push(gc, (int64_t)-1);
else
cse.back()->Push(gc, (int64_t)res);
return false;
}
else if(GetArgument<char>(args,0,c))
{
int64_t index = 0;
GetArgument(args,1,index);
auto res = str.find_first_of(c,(std::size_t)index);
if(res == std::string::npos)
cse.back()->Push(gc, (int64_t)-1);
else
cse.back()->Push(gc, (int64_t)res);
return false;
}
cse.back()->Push(gc,nullptr);
return false;
}
if(key == "LastIndexOf")
{
std::string str2;
char c;
if(GetArgument(args,0,str2))
{
int64_t index = str.size();
GetArgument(args,1,index);
auto res = str.rfind(str2,(std::size_t)index);
if(res == std::string::npos)
cse.back()->Push(gc, (int64_t)-1);
else
cse.back()->Push(gc, (int64_t)res);
return false;
}
else if(GetArgument<char>(args,0,c))
{
int64_t index = str.size();
GetArgument(args,1,index);
auto res = str.find_last_of(c,(std::size_t)index);
if(res == std::string::npos)
cse.back()->Push(gc, (int64_t)-1);
else
cse.back()->Push(gc, (int64_t)res);
return false;
}
cse.back()->Push(gc,nullptr);
return false;
}
if(key == "GetEnumerator")
{
cse.back()->Push(gc, TStringEnumerator::Create(ls,str));
return false;
}
if(key == "Substring")
{
if(args.size() >=1 && std::holds_alternative<int64_t>(args[0]))
{
size_t offset = (size_t)std::get<int64_t>(args[0]);
size_t count = std::string::npos;
if(args.size() == 2 && std::holds_alternative<int64_t>(args[1]))
{
count = (size_t)std::get<int64_t>(args[1]);
}
cse.back()->Push(gc, str.substr(offset,count));
return false;
}
}
if(key == "Remove")
{
if(args.size() >=1 && std::holds_alternative<int64_t>(args[0]))
{
size_t offset = (size_t)std::get<int64_t>(args[0]);
size_t count = std::string::npos;
if(args.size() == 2 && std::holds_alternative<int64_t>(args[1]))
{
count = (size_t)std::get<int64_t>(args[1]);
}
cse.back()->Push(gc, str.erase(offset,count));
return false;
}
}
if(key == "TrimStart")
{
if(args.size() >= 0)
{
char c = (args.size() == 1 && std::holds_alternative<char>(args[0])) ? std::get<char>(args[0]) : ' ';
size_t i = 0;
for(; i < str.size();i++)
{
if(str[i] != c) break;
}
cse.back()->Push(gc,(!str.empty() && i < str.size()) ? str.substr(i) : "");
return false;
}
}
if(key == "TrimEnd")
{
if(args.size() >= 0)
{
char c = (args.size() == 1 && std::holds_alternative<char>(args[0])) ? std::get<char>(args[0]) : ' ';
size_t i = str.size()-1;
for(; i >= 0;i--)
{
if(str[i] != c) break;
}
cse.back()->Push(gc, (!str.empty() && i < str.size()) ? str.substr(0,i+1) : "");
return false;
}
}
if(key == "EndsWith")
{
std::string v;
if(GetArgument(args,0,v))
{
if(str.size() < v.size()) {
cse.back()->Push(gc,false);
return false;
}
size_t _end = str.size()-v.size();
for(size_t i = 0; i < v.size(); i++)
{
if(v[i] != str[i+_end])
{
cse.back()->Push(gc,false);
return false;
}
}
cse.back()->Push(gc,true);
return false;
}
cse.back()->Push(gc,false);
return false;
}
if(key == "StartsWith")
{
std::string v;
if(GetArgument(args,0,v))
{
if(str.size() < v.size()) {
cse.back()->Push(gc,false);
return false;
}
for(size_t i = 0; i < v.size(); i++)
{
if(v[i] != str[i])
{
cse.back()->Push(gc,false);
return false;
}
}
cse.back()->Push(gc,true);
return false;
}
cse.back()->Push(gc,false);
return false;
}
if(key == "Escape")
{
bool quote;
if(!GetArgument(args,0,quote)) quote=false;
cse.back()->Push(gc, EscapeString(str, quote));
return false;
}
if(key == "Replace")
{
std::string oldStr;
std::string newStr;
std::string _str={};
if(GetArgument(args,0,oldStr) && GetArgument(args,1,newStr))
{
_str = Tesses::Framework::Http::HttpUtils::Replace(str, oldStr,newStr);
}
cse.back()->Push(gc,_str);
return false;
}
if(key == "Split")
{
std::string delimiter;
bool removeEmpty=false;
size_t count=std::string::npos;
if(args.size() < 1 || args.size() > 3) throw VMException("String.Split must only accept 1-3 arguments");
if(!std::holds_alternative<std::string>(args[0])) throw VMException("String.Split first arg must be a string");
else
delimiter = std::get<std::string>(args[0]);
if(args.size() > 1 && !std::holds_alternative<bool>(args[1])) throw VMException("String.Split second arg must be a bool");
else if(args.size() > 1)
removeEmpty = std::get<bool>(args[1]);
if(args.size() > 2 && !std::holds_alternative<int64_t>(args[2])) throw VMException("String.Split third arg must be a int64_t");
else if(args.size() > 2)
count = (size_t)std::get<int64_t>(args[2]);
auto res = Tesses::Framework::Http::HttpUtils::SplitString(str, delimiter,count);
TList* mls = TList::Create(ls);
for(auto item : res)
{
if(!removeEmpty || !item.empty()) mls->Add(item);
}
cse.back()->Push(gc,mls);
return false;
// SplitString()
}
if(key == "GetAt")
{
if(args.size() != 1)
{
throw VMException("String.GetAt must only accept one argument");
}
if(!std::holds_alternative<int64_t>(args[0]))
{
throw VMException("String.GetAt must only accept a long");
}
size_t index = (size_t)std::get<int64_t>(args[0]);
size_t sz = str.size();
if(index >= 0 && index < sz)
{
cse.back()->Push(gc, str[index]);
return false;
}
}
if(key == "Count" || key == "Length")
{
int64_t len = (int64_t)str.size();
if(len < 0) len = 0;
cse.back()->Push(gc, len);
return false;
}
if(key == "ToString")
{
cse.back()->Push(gc, str);
return false;
}
cse.back()->Push(gc, Undefined());
return false;
}
else if(std::holds_alternative<std::shared_ptr<Tesses::Framework::Date::TimeSpan>>(instance))
{
auto& time = std::get<std::shared_ptr<Tesses::Framework::Date::TimeSpan>>(instance);
if(key == "ToString")
{
bool slim = false;
GetArgument(args,0,slim);
cse.back()->Push(gc, time->ToString(slim));
return false;
}
cse.back()->Push(gc, Undefined());
return false;
}
else if(std::holds_alternative<std::shared_ptr<Tesses::Framework::Date::DateTime>>(instance))
{
auto& date = std::get<std::shared_ptr<Tesses::Framework::Date::DateTime>>(instance);
if(key == "ToString")
{
std::string fmt;
if(GetArgument(args,0,fmt))
{
cse.back()->Push(gc, date->ToString(fmt));
}
else
{
cse.back()->Push(gc, date->ToString());
}
return false;
}
if(key == "ToHttpDate")
{
cse.back()->Push(gc, date->ToHttpDate());
return false;
}
if(key == "ToEpoch")
{
cse.back()->Push(gc, date->ToEpoch());
return false;
}
if(key == "ToLocal")
{
cse.back()->Push(gc, std::make_shared<Tesses::Framework::Date::DateTime>(date->ToLocal()));
return false;
}
if(key == "ToUTC")
{
cse.back()->Push(gc, std::make_shared<Tesses::Framework::Date::DateTime>(date->ToUTC()));
return false;
}
cse.back()->Push(gc, nullptr);
return false;
}
else if(std::holds_alternative<std::shared_ptr<Tesses::Framework::TextStreams::TextReader>>(instance))
{
auto textReader = std::get<std::shared_ptr<Tesses::Framework::TextStreams::TextReader>>(instance);
if(key == "Rewind")
{
cse.back()->Push(gc,textReader->Rewind());
return false;
}
if(key == "ReadBlock")
{
int64_t sz;
if(GetArgument(args,0,sz))
{
std::string block;
if(textReader->ReadBlock(block,(size_t)sz))
{
cse.back()->Push(gc, block);
return false;
}
}
cse.back()->Push(gc, nullptr);
return false;
}
if(key == "ReadChar")
{
cse.back()->Push(gc,(int64_t)textReader->ReadChar());
return false;
}
if(key == "ReadLine")
{
std::string line;
if(textReader->ReadLine(line))
{
cse.back()->Push(gc, line);
return false;
}
cse.back()->Push(gc, nullptr);
return false;
}
if(key == "ReadLineHttp")
{
std::string line;
if(textReader->ReadLineHttp(line))
{
cse.back()->Push(gc, line);
return false;
}
cse.back()->Push(gc, nullptr);
return false;
}
if(key == "ReadAllLines")
{
std::vector<std::string> lines;
textReader->ReadAllLines(lines);
gc->BarrierBegin();
TList* list = TList::Create(ls);
for(auto& item : lines) list->Add(item);
gc->BarrierEnd();
return list;
}
if(key == "ReadToEnd")
{
std::string text;
textReader->ReadToEnd(text);
cse.back()->Push(gc,text);
return false;
}
if(key == "CopyTo")
{
std::shared_ptr<Tesses::Framework::TextStreams::TextWriter> writer;
if(GetArgument(args,0,writer))
{
textReader->CopyTo(*writer);
}
}
cse.back()->Push(gc, Undefined());
return false;
}
else if(std::holds_alternative<std::shared_ptr<Tesses::Framework::TextStreams::TextWriter>>(instance))
{
auto textWriter=std::get<std::shared_ptr<Tesses::Framework::TextStreams::TextWriter>>(instance);
if(key == "Write")
{
if(args.size()>0)
textWriter->Write(ToString(gc,args[0]));
}
if(key == "WriteLine")
{
if(args.size()>0)
textWriter->WriteLine(ToString(gc,args[0]));
}
if(key == "WriteData")
{
if(args.size()>0)
{
auto s=ToString(gc,args[0]);
textWriter->WriteData(s.c_str(),s.size());
}
}
cse.back()->Push(gc, nullptr);
return false;
}
else if(std::holds_alternative<std::shared_ptr<Tesses::Framework::Streams::ByteReader>>(instance))
{
auto& br = std::get<std::shared_ptr<Tesses::Framework::Streams::ByteReader>>(instance);
if(key == "ReadS8")
{
cse.back()->Push(gc,(int64_t)br->ReadI8());
return false;
}
if(key == "ReadU8")
{
cse.back()->Push(gc,(int64_t)br->ReadU8());
return false;
}
if(key == "ReadS16BE")
{
cse.back()->Push(gc,(int64_t)br->ReadI16BE());
return false;
}
if(key == "ReadS16LE")
{
cse.back()->Push(gc,(int64_t)br->ReadI16LE());
return false;
}
if(key == "ReadU16BE")
{
cse.back()->Push(gc,(int64_t)br->ReadU16BE());
return false;
}
if(key == "ReadU16LE")
{
cse.back()->Push(gc,(int64_t)br->ReadU16LE());
return false;
}
if(key == "ReadS32BE")
{
cse.back()->Push(gc,(int64_t)br->ReadI32BE());
return false;
}
if(key == "ReadS32LE")
{
cse.back()->Push(gc,(int64_t)br->ReadI32LE());
return false;
}
if(key == "ReadU32BE")
{
cse.back()->Push(gc,(int64_t)br->ReadU32BE());
return false;
}
if(key == "ReadU32LE")
{
cse.back()->Push(gc,(int64_t)br->ReadU32LE());
return false;
}
if(key == "ReadS64BE")
{
cse.back()->Push(gc,br->ReadI64BE());
return false;
}
if(key == "ReadS64LE")
{
cse.back()->Push(gc,br->ReadI64LE());
return false;
}
if(key == "ReadU16BE")
{
uint64_t value = br->ReadU64BE();
int64_t value2 = 0;
memcpy(&value2,&value,sizeof(uint64_t));
cse.back()->Push(gc,value2);
return false;
}
if(key == "ReadU64LE")
{
uint64_t value = br->ReadU64LE();
int64_t value2 = 0;
memcpy(&value2,&value,sizeof(uint64_t));
cse.back()->Push(gc,value2);
return false;
}
if(key == "ReadF32BE")
{
cse.back()->Push(gc,(double)br->ReadF32BE());
return false;
}
if(key == "ReadF32LE")
{
cse.back()->Push(gc,(double)br->ReadF32LE());
return false;
}
if(key == "ReadF64BE")
{
cse.back()->Push(gc,br->ReadF64BE());
return false;
}
if(key == "ReadF64LE")
{
cse.back()->Push(gc,br->ReadF64LE());
return false;
}
if(key == "ReadUuid")
{
cse.back()->Push(gc, br->ReadUuid());
return false;
}
cse.back()->Push(gc, Undefined());
return false;
}
else if(std::holds_alternative<std::shared_ptr<Tesses::Framework::Streams::ByteWriter>>(instance))
{
auto& bw = std::get<std::shared_ptr<Tesses::Framework::Streams::ByteWriter>>(instance);
int64_t number;
double numberDbl;
Tesses::Framework::Uuid uuid;
if(GetArgument(args,0,number))
{
if(key == "WriteS8")
{
bw->WriteI8((int8_t)number);
}
else if(key == "WriteU8")
{
bw->WriteI8((uint8_t)number);
}
else if(key == "WriteS16BE")
{
bw->WriteI16BE((int16_t)number);
}
else if(key == "WriteS16LE")
{
bw->WriteI16LE((int16_t)number);
}
else if(key == "WriteU16BE")
{
bw->WriteU16BE((uint16_t)number);
}
else if(key == "WriteU16LE")
{
bw->WriteU16LE((uint16_t)number);
}
else if(key == "WriteS32BE")
{
bw->WriteI32BE((int32_t)number);
}
else if(key == "WriteS32LE")
{
bw->WriteI32LE((int32_t)number);
}
else if(key == "WriteU32BE")
{
bw->WriteU32BE((uint32_t)number);
}
else if(key == "WriteU32LE")
{
bw->WriteU32LE((uint32_t)number);
}
else if(key == "WriteS64BE")
{
bw->WriteI64BE(number);
}
else if(key == "WriteS64LE")
{
bw->WriteI64LE(number);
}
else if(key == "WriteU64BE")
{
uint64_t number2 = 0;
memcpy(&number2,&number, sizeof(uint64_t));
bw->WriteU64BE(number2);
}
else if(key == "WriteU64LE")
{
uint64_t number2 = 0;
memcpy(&number2,&number, sizeof(uint64_t));
bw->WriteU64LE(number2);
}
}
else if(GetArgument(args,0,numberDbl))
{
if(key == "WriteF32BE")
{
bw->WriteF32BE((float)numberDbl);
}
else if(key == "WriteF32LE")
{
bw->WriteF32LE((float)numberDbl);
}
else if(key == "WriteF64BE")
{
bw->WriteF64BE(numberDbl);
}
else if(key == "WriteF64LE")
{
bw->WriteF64LE(numberDbl);
}
}
else if(GetArgument(args,0,uuid))
{
if(key == "WriteUuid")
{
bw->WriteUuid(uuid);
}
}
cse.back()->Push(gc,Undefined());
return false;
}
else if(std::holds_alternative<std::shared_ptr<Tesses::Framework::Http::ServerSentEvents>>(instance))
{
auto& sse = std::get<std::shared_ptr<Tesses::Framework::Http::ServerSentEvents>>(instance);
if(sse != nullptr)
{
std::string text;
std::string text2;
if(key == "SendComment" && GetArgument(args, 0, text))
{
sse->SendComment(text);
}
else if(key == "SendCustomEvent" && GetArgument(args, 0, text) && GetArgument(args,1,text2)) {
sse->SendCustomEvent(text,text2);
}
else if(key == "SendCustomEvent" && GetArgument(args, 0, text)) {
if(GetArgument(args,1,text2))
sse->SendData(text,text2);
else
sse->SendData(text);
}
else if(key == "SendId" && GetArgument(args, 0, text))
{
sse->SendId(text);
}
else if(key == "SendRetry")
{
std::shared_ptr<Tesses::Framework::Date::TimeSpan> ts;
int64_t num;
if(GetArgument(args,0,ts) && ts)
{
sse->SendRetry(*ts);
}
else if(GetArgument(args,0,num))
{
sse->SendRetry((uint32_t)num);
}
}
}
cse.back()->Push(gc, Undefined());
return false;
}
else if(std::holds_alternative<std::shared_ptr<Tesses::Framework::Streams::Stream>>(instance))
{
auto& strm = std::get<std::shared_ptr<Tesses::Framework::Streams::Stream>>(instance);
if(strm != nullptr)
{
auto memStrm = std::dynamic_pointer_cast<Tesses::Framework::Streams::MemoryStream>(strm);
auto netStrm = std::dynamic_pointer_cast<Tesses::Framework::Streams::NetworkStream>(strm);
auto mystrm = std::dynamic_pointer_cast<TObjectStream>(strm);
if(mystrm != nullptr)
{
TDictionary* dict2;
if(GetObjectHeap(mystrm->obj, dict2))
{
gc->BarrierBegin();
auto o = dict2->GetValue(key);
gc->BarrierEnd();
return InvokeMethod(ls,o,dict2,args);
}
}
if(memStrm != nullptr)
{
if(key == "GetBytes")
{
auto res = TByteArray::Create(ls);
res->data = memStrm->GetBuffer();
cse.back()->Push(gc, res);
return false;
}
}
if(netStrm != nullptr)
{
if(key == "SetMulticastMembership")
{
std::string ma;
std::string ifaceIP = "0.0.0.0";
if(GetArgument(args,0,ma))
{
GetArgument(args,1,ifaceIP);
netStrm->SetMulticastMembership(ma,ifaceIP);
}
cse.back()->Push(gc, Undefined());
return false;
}
if(key == "GetPort")
{
cse.back()->Push(gc, (int64_t)netStrm->GetPort());
return false;
}
if(key == "Bind")
{
std::string ip;
int64_t port;
if(GetArgument(args,0,ip) && GetArgument(args,1,port))
netStrm->Bind(ip,(uint16_t)port);
cse.back()->Push(gc, nullptr);
return false;
}
if(key == "Accept")
{
std::string ip;
uint16_t port;
auto strm = netStrm->Accept(ip,port);
TDictionary* dict = TDictionary::Create(ls);
gc->BarrierBegin();
dict->SetValue("IP",ip);
dict->SetValue("Port",(int64_t)port);
dict->SetValue("Stream", strm);
gc->BarrierEnd();
cse.back()->Push(gc, dict);
return false;
}
if(key == "Listen")
{
int64_t backlog;
if(GetArgument(args,0,backlog))
{
netStrm->Listen((int32_t)backlog);
}
else
{
netStrm->Listen(10);
}
cse.back()->Push(gc, nullptr);
return false;
}
if(key == "ReadFrom")
{
TByteArray* data;
int64_t offset;
int64_t length;
if(GetArgumentHeap<TByteArray*>(args, 0, data) && GetArgument<int64_t>(args, 1, offset) && GetArgument<int64_t>(args,2,length))
{
size_t off = (size_t)offset;
size_t len = (size_t)length;
std::string ip={};
uint16_t port=0;
if(off < len)
len = netStrm->ReadFrom(data->data.data()+off,std::min(len,std::min(data->data.size() - off, data->data.size())),ip,port);
else
len = 0;
TDictionary* dict = TDictionary::Create(ls);
gc->BarrierBegin();
dict->SetValue("IP",ip);
dict->SetValue("Port",(int64_t)port);
dict->SetValue("Read", (int64_t)len);
gc->BarrierEnd();
cse.back()->Push(gc, dict);
return false;
}
cse.back()->Push(gc, nullptr);
return false;
}
if(key == "WriteTo")
{
TByteArray* data;
int64_t offset;
int64_t length;
std::string ip;
int64_t port;
if(GetArgumentHeap<TByteArray*>(args, 0, data) && GetArgument<int64_t>(args, 1, offset) && GetArgument<int64_t>(args,2,length) && GetArgument(args,3,ip) && GetArgument(args,4,port))
{
size_t off = (size_t)offset;
size_t len = (size_t)length;
if(off < len)
len = netStrm->WriteTo(data->data.data()+off,std::min(len, std::min(data->data.size() - off, data->data.size())), ip, (int64_t)port);
else
len = 0;
cse.back()->Push(gc, (int64_t)len);
return false;
}
cse.back()->Push(gc, nullptr);
return false;
}
}
if(key == "Read")
{
TByteArray* data;
int64_t offset;
int64_t length;
if(GetArgumentHeap<TByteArray*>(args, 0, data) && GetArgument<int64_t>(args, 1, offset) && GetArgument<int64_t>(args,2,length))
{
size_t off = (size_t)offset;
size_t len = (size_t)length;
if(off < len)
len = strm->Read(data->data.data()+off,std::min(len,std::min(data->data.size() - off, data->data.size())));
else
len = 0;
cse.back()->Push(gc, (int64_t)len);
return false;
}
cse.back()->Push(gc, nullptr);
return false;
}
if(key == "Write")
{
TByteArray* data;
int64_t offset;
int64_t length;
if(GetArgumentHeap<TByteArray*>(args, 0, data) && GetArgument<int64_t>(args, 1, offset) && GetArgument<int64_t>(args,2,length))
{
size_t off = (size_t)offset;
size_t len = (size_t)length;
if(off < len)
len = strm->Write(data->data.data()+off,std::min(len, std::min(data->data.size() - off, data->data.size())));
else
len = 0;
cse.back()->Push(gc, (int64_t)len);
return false;
}
cse.back()->Push(gc, nullptr);
return false;
}
if(key == "ReadBlock")
{
TByteArray* data;
int64_t offset;
int64_t length;
if(GetArgumentHeap<TByteArray*>(args, 0, data) && GetArgument<int64_t>(args, 1, offset) && GetArgument<int64_t>(args,2,length))
{
size_t off = (size_t)offset;
size_t len = (size_t)length;
if(off < len)
len = strm->ReadBlock(data->data.data()+off,std::min(len, std::min(data->data.size() - off, data->data.size())));
else
len = 0;
cse.back()->Push(gc, (int64_t)len);
return false;
}
cse.back()->Push(gc, nullptr);
return false;
}
if(key == "WriteText")
{
std::string text;
if(GetArgument(args,0,text))
{
strm->WriteBlock((const uint8_t*)text.data(), text.size());
}
cse.back()->Push(gc, nullptr);
return false;
}
if(key == "WriteBlock")
{
TByteArray* data;
int64_t offset;
int64_t length;
if(GetArgumentHeap<TByteArray*>(args, 0, data) && GetArgument<int64_t>(args, 1, offset) && GetArgument<int64_t>(args,2,length))
{
size_t off = (size_t)offset;
size_t len = (size_t)length;
if(off < len)
strm->WriteBlock(data->data.data()+off,std::min(len,std::min(data->data.size() - off, data->data.size())));
}
cse.back()->Push(gc, nullptr);
return false;
}
if(key == "CopyTo")
{
std::shared_ptr<Tesses::Framework::Streams::Stream> data;
int64_t buffSize;
if(GetArgument(args,0,data))
{
if(!GetArgument<int64_t>(args,1,buffSize)) buffSize=1024;
strm->CopyTo(data,(size_t)buffSize);
}
cse.back()->Push(gc, nullptr);
return false;
}
if(key == "CopyToLimit")
{
std::shared_ptr<Tesses::Framework::Streams::Stream> data;
int64_t cnt;
int64_t buffSize;
if(GetArgument(args,0,data) && GetArgument(args,1,cnt))
{
if(!GetArgument<int64_t>(args,2,buffSize)) buffSize=1024;
strm->CopyToLimit(data,(uint64_t)cnt,(size_t)buffSize);
}
cse.back()->Push(gc, nullptr);
return false;
}
if(key == "Flush")
{
strm->Flush();
cse.back()->Push(gc, nullptr);
return false;
}
if(key == "Close")
{
strm->Close();
cse.back()->Push(gc, nullptr);
return false;
}
if(key == "Seek")
{
int64_t pos,whence;
if(!GetArgument<int64_t>(args,0,pos)) pos=0;
if(!GetArgument<int64_t>(args,1,whence)) whence=0;
strm->Seek(pos, whence == 0 ? Tesses::Framework::Streams::SeekOrigin::Begin : whence == 1 ? Tesses::Framework::Streams::SeekOrigin::Current : Tesses::Framework::Streams::SeekOrigin::End);
cse.back()->Push(gc, nullptr);
return false;
}
cse.back()->Push(gc, nullptr);
return false;
}
}
else if(std::holds_alternative<std::shared_ptr<Tesses::Framework::Http::IHttpServer>>(instance))
{
auto svr = std::get<std::shared_ptr<Tesses::Framework::Http::IHttpServer>>(instance);
if(svr != nullptr)
{
auto mountable = std::dynamic_pointer_cast<Tesses::Framework::Http::MountableServer>(svr);
auto routable = std::dynamic_pointer_cast<Tesses::Framework::Http::RouteServer>(svr);
if(mountable != nullptr)
{
if(key == "Mount")
{
Tesses::Framework::Filesystem::VFSPath p;
if(args.size() > 1 && GetArgumentAsPath(args,0,p))
{
std::shared_ptr<Tesses::Framework::Http::IHttpServer> svr2=ToHttpServer(gc,args[1]);
if(svr2)
mountable->Mount(p.ToString(), svr2);
cse.back()->Push(gc,nullptr);
return false;
}
}
if(key == "Unmount")
{
Tesses::Framework::Filesystem::VFSPath p;
if(GetArgumentAsPath(args,0,p))
{
mountable->Unmount(p.ToString());
cse.back()->Push(gc,nullptr);
return false;
}
}
}
if(routable != nullptr)
{
if(key == "Add")
{
std::string method;
std::string pattern;
TCallable* callable;
if(GetArgument(args,0,method) && GetArgument(args,1,pattern) && GetArgumentHeap(args,2,callable))
{
routable->Add(method,pattern, callable->ToRouteServerRequestHandler(gc));
}
}
else if(key == "Delete")
{
std::string pattern;
TCallable* callable;
if(GetArgument(args,0,pattern) && GetArgumentHeap(args,1,callable))
{
routable->Delete(pattern, callable->ToRouteServerRequestHandler(gc));
}
}
else if(key == "Get")
{
std::string pattern;
TCallable* callable;
if(GetArgument(args,0,pattern) && GetArgumentHeap(args,1,callable))
{
routable->Get(pattern, callable->ToRouteServerRequestHandler(gc));
}
}
else if(key == "Options")
{
std::string pattern;
TCallable* callable;
if(GetArgument(args,0,pattern) && GetArgumentHeap(args,1,callable))
{
routable->Options(pattern, callable->ToRouteServerRequestHandler(gc));
}
}
else if(key == "Patch")
{
std::string pattern;
TCallable* callable;
if(GetArgument(args,0,pattern) && GetArgumentHeap(args,1,callable))
{
routable->Patch(pattern, callable->ToRouteServerRequestHandler(gc));
}
}
else if(key == "Post")
{
std::string pattern;
TCallable* callable;
if(GetArgument(args,0,pattern) && GetArgumentHeap(args,1,callable))
{
routable->Post(pattern, callable->ToRouteServerRequestHandler(gc));
}
}
else if(key == "Put")
{
std::string pattern;
TCallable* callable;
if(GetArgument(args,0,pattern) && GetArgumentHeap(args,1,callable))
{
routable->Put(pattern, callable->ToRouteServerRequestHandler(gc));
}
}
else if(key == "Trace")
{
std::string pattern;
TCallable* callable;
if(GetArgument(args,0,pattern) && GetArgumentHeap(args,1,callable))
{
routable->Trace(pattern, callable->ToRouteServerRequestHandler(gc));
}
}
}
if(key == "Handle")
{
cse.back()->Push(gc,IHttpServer_Handle(svr,args));
return false;
}
cse.back()->Push(gc,Undefined());
return false;
}
}
else if(std::holds_alternative<std::shared_ptr<Tesses::Framework::Filesystem::VFS>>(instance))
{
auto vfs = std::get<std::shared_ptr<Tesses::Framework::Filesystem::VFS>>(instance);
if(vfs != nullptr)
{
auto myvfs = std::dynamic_pointer_cast<TObjectVFS>(vfs);
auto mountable = std::dynamic_pointer_cast<Tesses::Framework::Filesystem::MountableFilesystem>(vfs);
if(myvfs != nullptr)
{
TDictionary* dict2;
if(GetObjectHeap(myvfs->obj, dict2))
{
gc->BarrierBegin();
auto o = dict2->GetValue(key);
gc->BarrierEnd();
return InvokeMethod(ls,o,dict2,args);
}
}
if(mountable != nullptr)
{
if(key == "Unmount")
{
Tesses::Framework::Filesystem::VFSPath path;
if(GetArgumentAsPath(args,0,path))
{
mountable->Unmount(path);
}
cse.back()->Push(gc, nullptr);
return false;
}
if(key == "Mount")
{
Tesses::Framework::Filesystem::VFSPath path;
std::shared_ptr<Tesses::Framework::Filesystem::VFS> vfs2;
if(GetArgumentAsPath(args,0,path) && GetArgument(args,1,vfs2))
{
//mountable->Mount(path, , true);
mountable->Mount(path, vfs2);
}
cse.back()->Push(gc, nullptr);
return false;
}
}
if(key == "Close")
{
vfs->Close();
cse.back()->Push(gc,nullptr);
return false;
}
if(key == "EnumeratePaths")
{
Tesses::Framework::Filesystem::VFSPath dir;
if(GetArgumentAsPath(args,0,dir))
{
auto tem = TExternalMethod::Create(ls,"Get the enumerator",{},[vfs,dir](GCList& ls, std::vector<TObject> args)->TObject{
return TVFSPathEnumerator::Create(ls,vfs->EnumeratePaths(dir));
});
auto d1=TDictionary::Create(ls);
gc->BarrierBegin();
tem->watch.push_back(vfs);
d1->SetValue("GetEnumerator", tem);
gc->BarrierEnd();
cse.back()->Push(gc,d1);
return false;
}
cse.back()->Push(gc, nullptr);
return false;
}
if(key == "MoveDirectory")
{
Tesses::Framework::Filesystem::VFSPath existingFile;
Tesses::Framework::Filesystem::VFSPath symlinkFile;
if(GetArgumentAsPath(args,0,existingFile) && GetArgumentAsPath(args,1,symlinkFile))
{
vfs->MoveDirectory(existingFile,symlinkFile);
return false;
}
cse.back()->Push(gc, nullptr);
return false;
}
if(key == "SetDate")
{
Tesses::Framework::Filesystem::VFSPath path;
std::shared_ptr<Tesses::Framework::Date::DateTime> lastWrite;
std::shared_ptr<Tesses::Framework::Date::DateTime> lastAccess;
if(GetArgumentAsPath(args,0,path) && GetArgument(args,1,lastWrite) && GetArgument(args,2,lastAccess))
{
vfs->SetDate(path,*lastWrite, *lastAccess);
}
cse.back()->Push(gc, nullptr);
return false;
}
if(key == "GetDate")
{
Tesses::Framework::Filesystem::VFSPath path;
if(GetArgumentAsPath(args,0,path))
{
Tesses::Framework::Date::DateTime lastWrite;
Tesses::Framework::Date::DateTime lastAccess;
vfs->GetDate(path,lastWrite,lastAccess);
auto dict = TDictionary::Create(ls);
ls.GetGC()->BarrierBegin();
dict->SetValue("LastWrite", std::make_shared<Tesses::Framework::Date::DateTime>(lastWrite));
dict->SetValue("LastAccess", std::make_shared<Tesses::Framework::Date::DateTime>(lastAccess));
ls.GetGC()->BarrierEnd();
cse.back()->Push(gc, dict);
return false;
}
cse.back()->Push(gc, nullptr);
return false;
}
if(key == "MoveFile")
{
Tesses::Framework::Filesystem::VFSPath existingFile;
Tesses::Framework::Filesystem::VFSPath symlinkFile;
if(GetArgumentAsPath(args,0,existingFile) && GetArgumentAsPath(args,1,symlinkFile))
{
vfs->MoveFile(existingFile,symlinkFile);
return false;
}
cse.back()->Push(gc, nullptr);
return false;
}
if(key == "CreateHardlink")
{
Tesses::Framework::Filesystem::VFSPath existingFile;
Tesses::Framework::Filesystem::VFSPath symlinkFile;
if(GetArgumentAsPath(args,0,existingFile) && GetArgumentAsPath(args,1,symlinkFile))
{
vfs->CreateHardlink(existingFile,symlinkFile);
return false;
}
cse.back()->Push(gc, nullptr);
return false;
}
if(key == "CreateSymlink")
{
Tesses::Framework::Filesystem::VFSPath existingFile;
Tesses::Framework::Filesystem::VFSPath symlinkFile;
if(GetArgumentAsPath(args,0,existingFile) && GetArgumentAsPath(args,1,symlinkFile))
{
vfs->CreateSymlink(existingFile,symlinkFile);
return false;
}
cse.back()->Push(gc, nullptr);
return false;
}
if(key == "RegularFileExists")
{
Tesses::Framework::Filesystem::VFSPath filename;
if(GetArgumentAsPath(args,0,filename))
{
cse.back()->Push(gc,vfs->RegularFileExists(filename));
return false;
}
cse.back()->Push(gc, nullptr);
return false;
}
if(key == "SpecialFileExists")
{
Tesses::Framework::Filesystem::VFSPath filename;
if(GetArgumentAsPath(args,0,filename))
{
cse.back()->Push(gc,vfs->SpecialFileExists(filename));
return false;
}
cse.back()->Push(gc, nullptr);
return false;
}
if(key == "FIFOFileExists")
{
Tesses::Framework::Filesystem::VFSPath filename;
if(GetArgumentAsPath(args,0,filename))
{
cse.back()->Push(gc,vfs->FIFOFileExists(filename));
return false;
}
cse.back()->Push(gc, nullptr);
return false;
}
if(key == "SocketFileExists")
{
Tesses::Framework::Filesystem::VFSPath filename;
if(GetArgumentAsPath(args,0,filename))
{
cse.back()->Push(gc,vfs->SocketFileExists(filename));
return false;
}
cse.back()->Push(gc, nullptr);
return false;
}
if(key == "BlockDeviceExists")
{
Tesses::Framework::Filesystem::VFSPath filename;
if(GetArgumentAsPath(args,0,filename))
{
cse.back()->Push(gc,vfs->BlockDeviceExists(filename));
return false;
}
cse.back()->Push(gc, nullptr);
return false;
}
if(key == "CharacterDeviceExists")
{
Tesses::Framework::Filesystem::VFSPath filename;
if(GetArgumentAsPath(args,0,filename))
{
cse.back()->Push(gc,vfs->CharacterDeviceExists(filename));
return false;
}
cse.back()->Push(gc, nullptr);
return false;
}
if(key == "SymlinkExists")
{
Tesses::Framework::Filesystem::VFSPath filename;
if(GetArgumentAsPath(args,0,filename))
{
cse.back()->Push(gc,vfs->SymlinkExists(filename));
return false;
}
cse.back()->Push(gc, nullptr);
return false;
}
if(key == "DirectoryExists")
{
Tesses::Framework::Filesystem::VFSPath filename;
if(GetArgumentAsPath(args,0,filename))
{
cse.back()->Push(gc,vfs->DirectoryExists(filename));
return false;
}
cse.back()->Push(gc, nullptr);
return false;
}
if(key == "FileExists")
{
Tesses::Framework::Filesystem::VFSPath filename;
if(GetArgumentAsPath(args,0,filename))
{
cse.back()->Push(gc,vfs->FileExists(filename));
return false;
}
cse.back()->Push(gc, nullptr);
return false;
}
if(key == "ReadLink")
{
Tesses::Framework::Filesystem::VFSPath filename;
if(GetArgumentAsPath(args,0,filename))
{
cse.back()->Push(gc,vfs->ReadLink(filename));
return false;
}
cse.back()->Push(gc, nullptr);
return false;
}
if(key == "VFSPathToSystem")
{
Tesses::Framework::Filesystem::VFSPath filename;
if(GetArgumentAsPath(args,0,filename))
{
cse.back()->Push(gc,vfs->VFSPathToSystem(filename));
return false;
}
cse.back()->Push(gc, nullptr);
return false;
}
if(key == "SystemToVFSPath")
{
std::string filename;
if(GetArgument(args,0,filename))
{
cse.back()->Push(gc,vfs->SystemToVFSPath(filename));
return false;
}
cse.back()->Push(gc, nullptr);
return false;
}
if(key == "DeleteFile")
{
Tesses::Framework::Filesystem::VFSPath filename;
if(GetArgumentAsPath(args,0,filename))
{
vfs->DeleteFile(filename);
}
cse.back()->Push(gc, nullptr);
return false;
}
if(key == "Lock")
{
Tesses::Framework::Filesystem::VFSPath filename;
if(GetArgumentAsPath(args,0,filename))
{
vfs->Lock(filename);
}
cse.back()->Push(gc, nullptr);
return false;
}
if(key == "Unlock")
{
Tesses::Framework::Filesystem::VFSPath filename;
if(GetArgumentAsPath(args,0,filename))
{
vfs->Unlock(filename);
}
cse.back()->Push(gc, nullptr);
return false;
}
if(key == "DeleteDirectoryRecurse")
{
Tesses::Framework::Filesystem::VFSPath dirname;
if(GetArgumentAsPath(args,0,dirname))
{
vfs->DeleteDirectoryRecurse(dirname);
}
cse.back()->Push(gc, nullptr);
return false;
}
if(key == "DeleteDirectory")
{
Tesses::Framework::Filesystem::VFSPath dirname;
if(GetArgumentAsPath(args,0,dirname))
{
vfs->DeleteDirectory(dirname);
}
cse.back()->Push(gc, nullptr);
return false;
}
if(key == "CreateDirectory")
{
Tesses::Framework::Filesystem::VFSPath dirname;
if(GetArgumentAsPath(args,0,dirname))
{
vfs->CreateDirectory(dirname);
}
cse.back()->Push(gc, nullptr);
return false;
}
if(key == "OpenFile")
{
Tesses::Framework::Filesystem::VFSPath path;
std::string mode;
if(GetArgumentAsPath(args,0,path) && GetArgument(args,1,mode))
{
auto res = vfs->OpenFile(path,mode);
cse.back()->Push(gc, res);
return false;
}
cse.back()->Push(gc, nullptr);
return false;
}
if(key == "Chmod")
{
Tesses::Framework::Filesystem::VFSPath path;
int64_t mode;
if(GetArgumentAsPath(args,0,path) && GetArgument(args,1,mode))
{
vfs->Chmod(path,(uint32_t)mode);
}
cse.back()->Push(gc, nullptr);
return false;
}
if(key == "Stat")
{
Tesses::Framework::Filesystem::VFSPath path;
if(GetArgumentAsPath(args,0,path))
{
Tesses::Framework::Filesystem::StatData data;
if(vfs->Stat(path,data))
{
cse.back()->Push(gc, TDictionary::Create(ls,{
TDItem("BlockCount", (int64_t)data.BlockCount),
TDItem("BlockSize", (int64_t)data.BlockSize),
TDItem("Device", (int64_t)data.Device),
TDItem("DeviceId", (int64_t)data.DeviceId),
TDItem("GroupId", (int64_t)data.GroupId),
TDItem("HardLinks", (int64_t)data.HardLinks),
TDItem("Inode", (int64_t)data.Inode),
TDItem("LastAccess", std::make_shared<Tesses::Framework::Date::DateTime>(data.LastAccess)),
TDItem("LastModified", std::make_shared<Tesses::Framework::Date::DateTime>(data.LastModified)),
TDItem("LastStatus", std::make_shared<Tesses::Framework::Date::DateTime>(data.LastStatus)),
TDItem("Mode", (int64_t)data.Mode),
TDItem("Size", (int64_t)data.Size),
TDItem("UserId", (int64_t)data.UserId)
}));
return false;
}
}
cse.back()->Push(gc, nullptr);
return false;
}
if(key == "StatVFS")
{
Tesses::Framework::Filesystem::VFSPath path;
if(GetArgumentAsPath(args,0,path))
{
Tesses::Framework::Filesystem::StatVFSData data;
if(vfs->StatVFS(path,data))
{
cse.back()->Push(gc, TDictionary::Create(ls,{
TDItem("BlockSize", (int64_t)data.BlockSize),
TDItem("FragmentSize",(int64_t)data.FragmentSize),
TDItem("Blocks",(int64_t)data.Blocks),
TDItem("BlocksFree",(int64_t)data.BlocksFree),
TDItem("BlocksAvailable", (int64_t)data.BlocksAvailable),
TDItem("TotalInodes", (int64_t)data.TotalInodes),
TDItem("FreeInodes",(int64_t)data.FreeInodes),
TDItem("AvailableInodes",(int64_t)data.AvailableInodes),
TDItem("Id",(int64_t)data.Id),
TDItem("Flags",(int64_t)data.Flags),
TDItem("MaxNameLength",(int64_t)data.MaxNameLength)
}));
return false;
}
}
cse.back()->Push(gc, nullptr);
return false;
}
cse.back()->Push(gc, nullptr);
return false;
}
}
else if(std::holds_alternative<Tesses::Framework::Uuid>(instance))
{
auto& obj = std::get<Tesses::Framework::Uuid>(instance);
if(key == "ToBytes")
{
TByteArray* ba = TByteArray::Create(ls);
ba->data.resize(16);
Tesses::Framework::Serialization::BitConverter::FromUuid(ba->data[0], obj);
cse.back()->Push(gc, ba);
return false;
}
if(key == "ToString")
{
int64_t arg;
if(GetArgument(args,0,arg))
{
cse.back()->Push(gc, obj.ToString((Framework::UuidStringifyConfig)arg));
return false;
}
cse.back()->Push(gc, obj.ToString(Framework::UuidStringifyConfig::LowercaseNoCurly));
return false;
}
cse.back()->Push(gc, Undefined());
return false;
}
else if(std::holds_alternative<THeapObjectHolder>(instance))
{
auto obj = std::get<THeapObjectHolder>(instance).obj;
auto list = dynamic_cast<TList*>(obj);
auto dynList = dynamic_cast<TDynamicList*>(obj);
auto bArray = dynamic_cast<TByteArray*>(obj);
auto dict = dynamic_cast<TDictionary*>(obj);
auto dynDict = dynamic_cast<TDynamicDictionary*>(obj);
auto ittr = dynamic_cast<TEnumerator*>(obj);
auto env = dynamic_cast<TEnvironment*>(obj);
auto subEnv = dynamic_cast<TSubEnvironment*>(obj);
auto rootEnv = dynamic_cast<TRootEnvironment*>(obj);
auto callable = dynamic_cast<TCallable*>(obj);
auto callstackEntry = dynamic_cast<CallStackEntry*>(obj);
auto natObj = dynamic_cast<TNativeObject*>(obj);
auto cls = dynamic_cast<TClassObject*>(obj);
auto aArray=dynamic_cast<TAssociativeArray*>(obj);
auto ttask = dynamic_cast<TTask*>(obj);
auto file = dynamic_cast<TFile*>(obj);
auto queryable = dynamic_cast<TQueryable*>(obj);
if(queryable != nullptr)
{
if(key == "Skip")
{
int64_t count;
if(GetArgument(args,0,count))
{
cse.back()->Push(gc, queryable->Skip(ls,count));
return false;
}
}
if(key == "Take")
{
int64_t count;
if(GetArgument(args,0,count))
{
cse.back()->Push(gc, queryable->Take(ls,count));
return false;
}
}
if(key == "SkipWhile")
{
TCallable* callable;
if(GetArgumentHeap(args, 0, callable))
{
cse.back()->Push(gc, queryable->SkipWhile(ls,callable));
return false;
}
}
if(key == "TakeWhile")
{
TCallable* callable;
if(GetArgumentHeap(args, 0, callable))
{
cse.back()->Push(gc, queryable->TakeWhile(ls,callable));
return false;
}
}
if(key == "Select")
{
TCallable* callable;
if(GetArgumentHeap(args, 0, callable))
{
cse.back()->Push(gc, queryable->Select(ls,callable));
return false;
}
}
if(key == "Where")
{
TCallable* callable;
if(GetArgumentHeap(args, 0, callable))
{
cse.back()->Push(gc, queryable->Where(ls,callable));
return false;
}
}
if(key == "ToList")
{
cse.back()->Push(gc, queryable->ToList(ls));
return false;
}
if(key == "ForEach")
{
TCallable* call;
if(GetArgumentHeap(args,0,call))
{
queryable->ForEach(gc, call);
}
cse.back()->Push(gc, Undefined());
return false;
}
if(key == "Count")
{
TCallable* call;
if(GetArgumentHeap(args,0,call))
{
cse.back()->Push(gc, queryable->Count(gc, call));
return false;
}
else {
cse.back()->Push(gc, queryable->Count(gc));
return false;
}
}
if(key == "Contains")
{
if(!args.empty())
{
cse.back()->Push(gc, queryable->Contains(gc, args[0]));
return false;
}
}
if(key == "All")
{
TCallable* call;
if(GetArgumentHeap(args,0,call))
{
cse.back()->Push(gc, queryable->All(gc, call));
return false;
}
}
if(key == "Any")
{
TCallable* call;
if(GetArgumentHeap(args,0,call))
{
cse.back()->Push(gc, queryable->Any(gc, call));
return false;
}
}
if(key == "GetEnumerator")
{
cse.back()->Push(gc, queryable->GetEnumerator(ls));
return false;
}
cse.back()->Push(gc, Undefined());
return false;
}
if(file != nullptr)
{
if(key == "MetadataDecode")
{
int64_t index;
if(GetArgument(args,0, index) && (size_t)index < file->metadata.size())
{
cse.back()->Push(gc,file->MetadataDecode(ls,(size_t)index));
return false;
}
}
if(key == "MetadataName")
{
int64_t index;
if(GetArgument(args,0, index) && (size_t)index < file->metadata.size())
{
cse.back()->Push(gc,file->metadata.at((size_t)index).first);
return false;
}
}
cse.back()->Push(gc,Undefined());
return false;
}
if(ttask != nullptr)
{
if(key == "ContinueWith")
{
TCallable* callable2;
if(GetArgumentHeap(args,0,callable2))
{
cse.back()->Push(gc,ttask->ContinueWith(ls,callable2));
return false;
}
}
if(key == "Wait")
{
cse.back()->Push(gc,ttask->Wait());
return false;
}
cse.back()->Push(gc,Undefined());
return false;
}
if(natObj != nullptr)
{
cse.back()->Push(gc, natObj->CallMethod(ls,key,args));
return false;
}
if(callstackEntry != nullptr)
{
if(key == "Resume")
{
gc->BarrierBegin();
cse.push_back(callstackEntry);
gc->BarrierEnd();
return true;
}
if(key == "Push")
{
if(!args.empty())
callstackEntry->Push(gc, args[0]);
else
callstackEntry->Push(gc,Undefined());
return false;
}
if(key == "Pop")
{
cse.back()->Push(gc, callstackEntry->Pop(ls));
return false;
}
}
if(rootEnv != nullptr)
{
//TStd::RegisterCrypto
//TStd::RegisterDictionary
//TStd::RegisterEnv
//TStd::RegisterIO
//TStd::RegisterJson
//TStd::RegisterNet
//TStd::RegisterOGC
//TStd::RegisterPath
//TStd::RegisterRoot
//TStd::RegisterSqlite
//TStd::RegisterVM
auto myEnv = cse.back()->env->GetRootEnvironment();
if(key == "RegisterOnError")
{
TCallable* callable;
if(!rootEnv->permissions.locked && GetArgumentHeap(args,0,callable))
{
gc->BarrierBegin();
rootEnv->RegisterOnError(callable);
gc->BarrierEnd();
}
}
if(key == "SetCustomConsole")
{
TDictionary* dict;
if(!rootEnv->permissions.locked && GetArgumentHeap(args,0, dict))
{
gc->BarrierBegin();
rootEnv->permissions.customConsole = dict;
gc->BarrierEnd();
}
else if(!rootEnv->permissions.locked && myEnv->permissions.customConsole == nullptr)
{
gc->BarrierBegin();
rootEnv->permissions.customConsole=nullptr;
gc->BarrierEnd();
}
}
if(key == "RegisterEverything")
{
if(rootEnv->permissions.locked)
{
cse.back()->Push(gc,nullptr);
return false;
}
if(myEnv->permissions.canRegisterEverything)
{
std::shared_ptr<Tesses::Framework::Filesystem::VFS> vfs;
if(GetArgument(args,0, vfs))
{
auto rfs = std::dynamic_pointer_cast<Tesses::Framework::Filesystem::RelativeFilesystem>(vfs);
if(rfs)
{
TStd::RegisterStd(gc,rootEnv, rfs);
cse.back()->Push(gc,nullptr);
return false;
}
}
if(myEnv->permissions.localfs)
TStd::RegisterStd(gc, rootEnv, std::make_shared<Tesses::Framework::Filesystem::RelativeFilesystem>(myEnv->permissions.localfs->GetVFS(),myEnv->permissions.localfs->GetWorking()));
else
TStd::RegisterStd(gc, rootEnv, nullptr);
cse.back()->Push(gc,nullptr);
return false;
}
else
{
if(myEnv->permissions.canRegisterConsole && !rootEnv->permissions.locked)
TStd::RegisterConsole(gc, rootEnv);
if(myEnv->permissions.canRegisterCrypto && !rootEnv->permissions.locked)
TStd::RegisterCrypto(gc, rootEnv);
if(myEnv->permissions.canRegisterDictionary && !rootEnv->permissions.locked)
TStd::RegisterDictionary(gc, rootEnv);
if(myEnv->permissions.canRegisterEnv && !rootEnv->permissions.locked)
TStd::RegisterEnv(gc, rootEnv);
if(myEnv->permissions.canRegisterIO && !rootEnv->permissions.locked)
{
if(myEnv->permissions.localfs)
{
TStd::RegisterIO(gc, rootEnv, std::make_shared<Tesses::Framework::Filesystem::RelativeFilesystem>(myEnv->permissions.localfs->GetVFS(),myEnv->permissions.localfs->GetWorking()));
}
else {
TStd::RegisterIO(gc, rootEnv, nullptr);
}
}
if(myEnv->permissions.canRegisterJSON && !rootEnv->permissions.locked)
TStd::RegisterJson(gc, rootEnv);
if(myEnv->permissions.canRegisterNet && !rootEnv->permissions.locked)
TStd::RegisterNet(gc, rootEnv);
if(myEnv->permissions.canRegisterOGC && !rootEnv->permissions.locked)
TStd::RegisterOGC(gc, rootEnv);
if(myEnv->permissions.canRegisterPath && !rootEnv->permissions.locked)
TStd::RegisterPath(gc, rootEnv);
if(myEnv->permissions.canRegisterRoot && !rootEnv->permissions.locked)
TStd::RegisterRoot(gc, rootEnv);
if(myEnv->permissions.canRegisterSqlite && !rootEnv->permissions.locked)
TStd::RegisterSqlite(gc, rootEnv);
if(myEnv->permissions.canRegisterVM && !rootEnv->permissions.locked)
TStd::RegisterVM(gc, rootEnv);
if(myEnv->permissions.canRegisterProcess && !rootEnv->permissions.locked)
TStd::RegisterProcess(gc, rootEnv);
}
cse.back()->Push(gc,nullptr);
return false;
}
if(key == "RegisterClass")
{
if((myEnv->permissions.canRegisterEverything || myEnv->permissions.canRegisterClass) && !rootEnv->permissions.locked)
TStd::RegisterClass(gc, rootEnv);
cse.back()->Push(gc,nullptr);
return false;
}
if(key == "RegisterConsole")
{
if((myEnv->permissions.canRegisterEverything || myEnv->permissions.canRegisterConsole) && !rootEnv->permissions.locked)
TStd::RegisterConsole(gc, rootEnv);
cse.back()->Push(gc,nullptr);
return false;
}
if(key == "RegisterProcess")
{
if((myEnv->permissions.canRegisterEverything || myEnv->permissions.canRegisterProcess) && !rootEnv->permissions.locked)
TStd::RegisterProcess(gc, rootEnv);
cse.back()->Push(gc,nullptr);
return false;
}
if(key == "RegisterCrypto")
{
if((myEnv->permissions.canRegisterEverything || myEnv->permissions.canRegisterCrypto) && !rootEnv->permissions.locked)
TStd::RegisterCrypto(gc, rootEnv);
cse.back()->Push(gc,nullptr);
return false;
}
if(key == "RegisterDictionary")
{
if((myEnv->permissions.canRegisterEverything || myEnv->permissions.canRegisterDictionary) && !rootEnv->permissions.locked)
TStd::RegisterDictionary(gc, rootEnv);
cse.back()->Push(gc,nullptr);
return false;
}
if(key == "RegisterEnv")
{
if((myEnv->permissions.canRegisterEverything || myEnv->permissions.canRegisterEnv) && !rootEnv->permissions.locked)
TStd::RegisterDictionary(gc, rootEnv);
cse.back()->Push(gc,nullptr);
return false;
}
if(key == "RegisterIO")
{
std::shared_ptr<Tesses::Framework::Filesystem::VFS> vfs;
bool r;
if(GetArgument(args,0,r))
{
if((myEnv->permissions.canRegisterEverything || myEnv->permissions.canRegisterIO) && !rootEnv->permissions.locked)
{
if(myEnv->permissions.localfs)
{
TStd::RegisterIO(gc, rootEnv, std::make_shared<Tesses::Framework::Filesystem::RelativeFilesystem>(myEnv->permissions.localfs->GetVFS(),myEnv->permissions.localfs->GetWorking()));
}
else {
TStd::RegisterIO(gc, rootEnv, nullptr);
}
}
}
if(GetArgument(args,0,vfs))
{
auto rfs = std::dynamic_pointer_cast<Tesses::Framework::Filesystem::RelativeFilesystem>(vfs);
if(rfs && (myEnv->permissions.canRegisterEverything || myEnv->permissions.canRegisterIO) && !rootEnv->permissions.locked)
{
TStd::RegisterIO(gc, rootEnv, rfs);
}
}
cse.back()->Push(gc,nullptr);
return false;
}
if(key == "RegisterJson")
{
if((myEnv->permissions.canRegisterEverything || myEnv->permissions.canRegisterJSON) && !rootEnv->permissions.locked)
TStd::RegisterJson(gc, rootEnv);
cse.back()->Push(gc,nullptr);
return false;
}
if(key == "RegisterNet")
{
if((myEnv->permissions.canRegisterEverything || myEnv->permissions.canRegisterNet) && !rootEnv->permissions.locked)
TStd::RegisterNet(gc, rootEnv);
cse.back()->Push(gc,nullptr);
return false;
}
if(key == "RegisterOGC")
{
if((myEnv->permissions.canRegisterEverything || myEnv->permissions.canRegisterOGC) && !rootEnv->permissions.locked)
TStd::RegisterOGC(gc, rootEnv);
cse.back()->Push(gc,nullptr);
return false;
}
if(key == "RegisterPath")
{
if((myEnv->permissions.canRegisterEverything || myEnv->permissions.canRegisterPath) && !rootEnv->permissions.locked)
TStd::RegisterPath(gc, rootEnv);
cse.back()->Push(gc,nullptr);
return false;
}
if(key == "RegisterRoot")
{
if((myEnv->permissions.canRegisterEverything || myEnv->permissions.canRegisterRoot) && !rootEnv->permissions.locked)
TStd::RegisterRoot(gc, rootEnv);
cse.back()->Push(gc,nullptr);
return false;
}
if(key == "RegisterSqlite")
{
if((myEnv->permissions.canRegisterEverything || myEnv->permissions.canRegisterSqlite) && !rootEnv->permissions.locked)
TStd::RegisterSqlite(gc, rootEnv);
cse.back()->Push(gc,nullptr);
return false;
}
if(key == "SetSqliteRoot")
{
Tesses::Framework::Filesystem::VFSPath p;
if(!rootEnv->permissions.locked)
{
if(GetArgumentAsPath(args,0,p))
{
if(myEnv->permissions.sqlite3Scoped)
{
rootEnv->permissions.sqliteOffsetPath = myEnv->permissions.sqliteOffsetPath / p.CollapseRelativeParents();
rootEnv->permissions.sqlite3Scoped = true;
}
else
{
rootEnv->permissions.sqliteOffsetPath = p;
rootEnv->permissions.sqlite3Scoped = true;
}
}
else {
if(myEnv->permissions.sqlite3Scoped)
{
rootEnv->permissions.sqliteOffsetPath = myEnv->permissions.sqliteOffsetPath;
rootEnv->permissions.sqlite3Scoped = true;
}
else
{
rootEnv->permissions.sqlite3Scoped = false;
}
}
}
cse.back()->Push(gc,nullptr);
return false;
}
if(key == "RegisterVM")
{
if((myEnv->permissions.canRegisterEverything || myEnv->permissions.canRegisterVM) && !rootEnv->permissions.locked)
TStd::RegisterVM(gc, rootEnv);
cse.back()->Push(gc,nullptr);
return false;
}
if(key == "LockRegister")
{
if(!rootEnv->permissions.locked)
{
rootEnv->permissions.locked=true;
}
cse.back()->Push(gc,nullptr);
return false;
}
if(key == "GetDictionary")
{
cse.back()->Push(gc,rootEnv->GetDictionary());
return false;
}
if(key == "LoadFileWithDependencies")
{
std::shared_ptr<Tesses::Framework::Filesystem::VFS> vfs0;
TFile* f;
Tesses::Framework::Filesystem::VFSPath p;
if(GetArgument(args,0,vfs0) )
{
if(GetArgumentHeap(args,1,f))
{
rootEnv->LoadFileWithDependencies(gc,vfs0,f);
}
else if(GetArgumentAsPath(args,1,p))
{
rootEnv->LoadFileWithDependencies(gc,vfs0,p);
}
}
cse.back()->Push(gc,nullptr);
return false;
}
}
if(subEnv != nullptr)
{
if(key == "GetDictionary")
{
cse.back()->Push(gc,subEnv->GetDictionary());
return false;
}
}
if(env != nullptr)
{
if(key == "Eval")
{
std::string str;
if(GetArgument(args,0,str))
{
cse.back()->Push(gc,env->Eval(ls,str));
return false;
}
cse.back()->Push(gc,nullptr);
return false;
}
if(key == "GetRootEnvironment")
{
cse.back()->Push(gc,env->GetRootEnvironment());
return false;
}
if(key == "GetSubEnvironment")
{
cse.back()->Push(gc,env->GetSubEnvironment(ls));
return false;
}
if(key == "GetParentEnvironment")
{
cse.back()->Push(gc,env->GetParentEnvironment());
return false;
}
if(key == "GetVariable")
{
std::string key;
gc->BarrierBegin();
if(GetArgument(args,0,key))
cse.back()->Push(gc,env->GetVariable(key));
gc->BarrierEnd();
return false;
}
if(key == "SetVariable")
{
std::string key;
gc->BarrierBegin();
if(args.size() > 1 && GetArgument(args,0,key))
{
if(env->HasConstForSet(key))
{
gc->BarrierEnd();
ThrowConstError(key);
}
env->SetVariable(key,args[1]);
}
gc->BarrierEnd();
cse.back()->Push(gc,nullptr);
return false;
}
if(key == "DeclareVariable")
{
std::string key;
gc->BarrierBegin();
if(args.size() > 1 && GetArgument(args,0,key))
{
if(env->HasConstForDeclare(key))
{
gc->BarrierEnd();
ThrowConstError(key);
}
env->DeclareVariable(key,args[1]);
}
gc->BarrierEnd();
cse.back()->Push(gc,nullptr);
return false;
}
if(key == "DeclareConstVariable")
{
std::string key;
gc->BarrierBegin();
if(args.size() > 1 && GetArgument(args,0,key))
{
if(env->HasConstForDeclare(key))
{
gc->BarrierEnd();
ThrowConstError(key);
}
env->DeclareConstVariable(key,args[1]);
}
gc->BarrierEnd();
cse.back()->Push(gc,nullptr);
return false;
}
if(key == "LoadFile")
{
TFile* f;
if(GetArgumentHeap(args,0,f))
{
env->LoadFile(gc,f);
}
cse.back()->Push(gc,nullptr);
return false;
}
cse.back()->Push(gc,nullptr);
return false;
}
if(ittr != nullptr)
{
if(key == "MoveNext")
{
cse.back()->Push(gc, ittr->MoveNext(gc));
return false;
}
cse.back()->Push(gc, nullptr);
return false;
}
else if(bArray != nullptr)
{
if(key == "Count" || key == "Length")
{
int64_t len = (int64_t)bArray->data.size();
if(len < 0) len = 0;
cse.back()->Push(gc, len);
return false;
}
if(key == "ToString")
{
cse.back()->Push(gc,std::string(bArray->data.begin(),bArray->data.end()));
return false;
}
if(key == "GetAt")
{
if(args.size() != 1)
{
throw VMException("ByteArray.GetAt must only accept one argument");
}
if(!std::holds_alternative<int64_t>(args[0]))
{
throw VMException("ByteArray.GetAt must only accept a long");
}
size_t index = (size_t)std::get<int64_t>(args[0]);
size_t sz = bArray->data.size();
if(index >= 0 && index < sz)
{
cse.back()->Push(gc, (int64_t)bArray->data[index]);
return false;
}
}
if(key == "SetAt")
{
if(args.size() != 2)
{
throw VMException("ByteArray.SetAt must only accept two arguments");
}
if(!std::holds_alternative<int64_t>(args[0]))
{
throw VMException("ByteArray.SetAt first argument must only accept a long");
}
uint8_t v = 0;
if(std::holds_alternative<int64_t>(args[1]))
{
v = (uint8_t)(std::get<int64_t>(args[1]) & 0xFF);
}
size_t index = (size_t)std::get<int64_t>(args[0]);
size_t sz = bArray->data.size();
if(index >= 0 && index < sz)
{
bArray->data[index]=v;
return false;
}
}
if(key == "ToCHeaderFile")
{
std::string name = "NONAME";
GetArgument(args,0,name);
cse.back()->Push(gc, Tesses::Framework::Text::GenerateCHeaderFile(bArray->data,name));
return false;
}
if(key == "CopyTo")
{
//CopyTo(destBuff, offsetSrc, offsetDest, length)
if(args.size() != 4)
{
throw VMException("ByteArray.CopyTo must only accept 4 arguments");
}
TByteArray* bArray2;
int64_t offsetSrc;
int64_t offsetDest;
int64_t count;
if(!GetArgumentHeap<TByteArray*>(args,0,bArray2))
{
throw VMException("ByteArray.CopyTo first argument must be a ByteArray");
}
if(!GetArgument<int64_t>(args,1, offsetSrc))
{
throw VMException("ByteArray.CopyTo second argument must be a Long (offsetSrc)");
}
if(!GetArgument<int64_t>(args,2, offsetDest))
{
throw VMException("ByteArray.CopyTo third argument must be a Long (offsetDest)");
}
if(!GetArgument<int64_t>(args,3,count))
{
throw VMException("ByteArray.CopyTo fourth argument must be a Long (length)");
}
size_t offsrc = (size_t)offsetSrc;
size_t offdest = (size_t)offsetDest;
size_t len = (size_t)count;
if(offsrc > bArray->data.size())
{
offsrc = bArray->data.size();
}
if(offdest > bArray2->data.size())
{
offdest = bArray2->data.size();
}
len = std::min<size_t>(std::min<size_t>(bArray->data.size()-offsrc,bArray2->data.size()-offdest),len);
if(len > 0)
memcpy(bArray2->data.data()+offdest,bArray->data.data()+offsrc,len);
cse.back()->Push(gc,bArray2);
return false;
}
if(key == "Insert")
{
if(args.size() != 4)
{
throw VMException("ByteArray.Insert must only accept 4 arguments");
}
//Insert(offsetDest, buffer, offsetSrc, length)
TByteArray* bArray2;
int64_t offsetSrc;
int64_t offsetDest;
int64_t count;
if(!GetArgumentHeap<TByteArray*>(args,1,bArray2))
{
throw VMException("ByteArray.Insert second argument must be a ByteArray");
}
if(!GetArgument<int64_t>(args,0, offsetSrc))
{
throw VMException("ByteArray.Insert first argument must be a Long (offsetSrc)");
}
if(!GetArgument<int64_t>(args,2, offsetDest))
{
throw VMException("ByteArray.Insert third argument must be a Long (offsetDest)");
}
if(!GetArgument<int64_t>(args,3,count))
{
throw VMException("ByteArray.Insert fourth argument must be a Long (length)");
}
size_t offsrc = (size_t)offsetSrc;
size_t offdest = (size_t)offsetDest;
size_t len = (size_t)count;
if(offsrc > bArray->data.size())
{
offsrc = bArray->data.size();
}
if(offdest > bArray->data.size())
{
offdest = bArray->data.size();
}
len = std::min(len,bArray2->data.size()-offsrc);
bArray->data.insert(bArray->data.begin()+offdest,bArray2->data.begin()+offsrc,bArray2->data.begin()+offsrc+len);
cse.back()->Push(gc, bArray);
return false;
}
if(key == "Append")
{
if(args.size() != 3)
{
throw VMException("ByteArray.Append must only accept 3 arguments");
}
TByteArray* bArray2;
int64_t offset;
int64_t count;
if(!GetArgumentHeap<TByteArray*>(args,0,bArray2))
{
throw VMException("ByteArray.Append first argument must be a ByteArray");
}
if(!GetArgument<int64_t>(args,1, offset))
{
throw VMException("ByteArray.Append second argument must be a Long (offset)");
}
if(!GetArgument<int64_t>(args,2,count))
{
throw VMException("ByteArray.Append third argument must be a Long (length)");
}
size_t off = (size_t)offset;
size_t len = (size_t)count;
if(off > bArray->data.size())
{
off = bArray->data.size();
}
len = std::min<size_t>(bArray->data.size() - off,len);
bArray->data.insert(bArray->data.end(),bArray2->data.begin()+off,bArray2->data.begin()+off+len);
cse.back()->Push(gc,bArray);
return false;
}
if(key == "Resize")
{
if(args.size() != 1)
{
throw VMException("ByteArray.Resize must only accept one argument");
}
if(!std::holds_alternative<int64_t>(args[0]))
{
throw VMException("ByteArray.Resize must only accept a long");
}
size_t len = (size_t)std::get<int64_t>(args[0]);
if(len >= 0)
{
bArray->data.resize(len);
}
cse.back()->Push(gc, bArray);
return false;
}
if(key == "SetU16BE")
{
int64_t index;
int64_t value;
if(GetArgument(args,0,index) && GetArgument(args,1, value) && (size_t)index < bArray->data.size() && (size_t)index + 2 <= bArray->data.size())
{
uint16_t number = (uint16_t)value;
BitConverter::FromUint16BE(bArray->data[(size_t)index],number);
cse.back()->Push(gc, (int64_t)value);
return false;
}
}
if(key == "SetU32BE")
{
int64_t index;
int64_t value;
if(GetArgument(args,0,index) && GetArgument(args,1, value) && (size_t)index < bArray->data.size() && (size_t)index + 4 <= bArray->data.size())
{
uint32_t number = (uint32_t)value;
BitConverter::FromUint32BE(bArray->data[(size_t)index],number);
cse.back()->Push(gc, (int64_t)value);
return false;
}
}
if(key == "SetU64BE")
{
int64_t index;
int64_t value;
if(GetArgument(args,0,index) && GetArgument(args,1, value) && (size_t)index < bArray->data.size() && (size_t)index + 8 <= bArray->data.size())
{
uint64_t number=0;
memcpy(&number, &value,sizeof(int64_t));
BitConverter::FromUint64BE(bArray->data[(size_t)index],number);
cse.back()->Push(gc, value);
return false;
}
}
if(key == "SetU16LE")
{
int64_t index;
int64_t value;
if(GetArgument(args,0,index) && GetArgument(args,1, value) && (size_t)index < bArray->data.size() && (size_t)index + 2 <= bArray->data.size())
{
uint16_t number = (uint16_t)value;
BitConverter::FromUint16LE(bArray->data[(size_t)index],number);
cse.back()->Push(gc, (int64_t)value);
return false;
}
}
if(key == "SetU32LE")
{
int64_t index;
int64_t value;
if(GetArgument(args,0,index) && GetArgument(args,1, value) && (size_t)index < bArray->data.size() && (size_t)index + 4 <= bArray->data.size())
{
uint32_t number = (uint32_t)value;
BitConverter::FromUint32LE(bArray->data[(size_t)index],number);
cse.back()->Push(gc, (int64_t)value);
return false;
}
}
if(key == "SetU64LE")
{
int64_t index;
int64_t value;
if(GetArgument(args,0,index) && GetArgument(args,1, value) && (size_t)index < bArray->data.size() && (size_t)index + 8 <= bArray->data.size())
{
uint64_t number=0;
memcpy(&number, &value,sizeof(int64_t));
BitConverter::FromUint64LE(bArray->data[(size_t)index],number);
cse.back()->Push(gc, value);
return false;
}
}
if(key == "SetU16BE")
{
int64_t index;
int64_t value;
if(GetArgument(args,0,index) && GetArgument(args,1, value) && (size_t)index < bArray->data.size() && (size_t)index + 2 <= bArray->data.size())
{
BitConverter::FromSint16BE(bArray->data[(size_t)index],(int16_t)value);
cse.back()->Push(gc, (int64_t)(int16_t)value);
return false;
}
}
if(key == "SetS32BE")
{
int64_t index;
int64_t value;
if(GetArgument(args,0,index) && GetArgument(args,1, value) && (size_t)index < bArray->data.size() && (size_t)index + 4 <= bArray->data.size())
{
BitConverter::FromSint32BE(bArray->data[(size_t)index],(int32_t)value);
cse.back()->Push(gc,(int64_t)(int32_t) value);
return false;
}
}
if(key == "SetS64BE")
{
int64_t index;
int64_t value;
if(GetArgument(args,0,index) && GetArgument(args,1, value) && (size_t)index < bArray->data.size() && (size_t)index + 8 <= bArray->data.size())
{
BitConverter::FromSint64BE(bArray->data[(size_t)index],value);
cse.back()->Push(gc, value);
return false;
}
}
if(key == "SetS16LE")
{
int64_t index;
int64_t value;
if(GetArgument(args,0,index) && GetArgument(args,1, value) && (size_t)index < bArray->data.size() && (size_t)index + 2 <= bArray->data.size())
{
BitConverter::FromSint16LE(bArray->data[(size_t)index],(int16_t)value);
cse.back()->Push(gc,(int64_t)(int16_t) value);
return false;
}
}
if(key == "SetS32LE")
{
int64_t index;
int64_t value;
if(GetArgument(args,0,index) && GetArgument(args,1, value) && (size_t)index < bArray->data.size() && (size_t)index + 4 <= bArray->data.size())
{
BitConverter::FromSint32LE(bArray->data[(size_t)index],(int32_t)value);
cse.back()->Push(gc, (int64_t)(int32_t)value);
return false;
}
}
if(key == "SetS64LE")
{
int64_t index;
int64_t value;
if(GetArgument(args,0,index) && GetArgument(args,1, value) && (size_t)index < bArray->data.size() && (size_t)index + 8 <= bArray->data.size())
{
BitConverter::FromSint64LE(bArray->data[(size_t)index],value);
cse.back()->Push(gc, value);
return false;
}
}
if(key == "SetF32LE")
{
int64_t index;
double value;
if(GetArgument(args,0,index) && GetArgument(args,1, value) && (size_t)index < bArray->data.size() && (size_t)index + 4 <= bArray->data.size())
{
BitConverter::FromFloatLE(bArray->data[(size_t)index],(float)value);
cse.back()->Push(gc, (double)(float)value);
return false;
}
}
if(key == "SetF64LE")
{
int64_t index;
double value;
if(GetArgument(args,0,index) && GetArgument(args,1, value) && (size_t)index < bArray->data.size() && (size_t)index + 8 <= bArray->data.size())
{
BitConverter::FromDoubleLE(bArray->data[(size_t)index],value);
cse.back()->Push(gc, value);
return false;
}
}
if(key == "SetF32BE")
{
int64_t index;
double value;
if(GetArgument(args,0,index) && GetArgument(args,1, value) && (size_t)index < bArray->data.size() && (size_t)index + 4 <= bArray->data.size())
{
BitConverter::FromFloatBE(bArray->data[(size_t)index],(float)value);
cse.back()->Push(gc, (double)(float)value);
return false;
}
}
if(key == "SetF64BE")
{
int64_t index;
double value;
if(GetArgument(args,0,index) && GetArgument(args,1, value) && (size_t)index < bArray->data.size() && (size_t)index + 8 <= bArray->data.size())
{
BitConverter::FromDoubleBE(bArray->data[(size_t)index],value);
cse.back()->Push(gc, value);
return false;
}
}
if(key == "SetUuid")
{
int64_t index;
Tesses::Framework::Uuid value;
if(GetArgument(args,0,index) && GetArgument(args,1, value) && (size_t)index < bArray->data.size() && (size_t)index + 16 <= bArray->data.size())
{
BitConverter::FromUuid(bArray->data[(size_t)index],value);
cse.back()->Push(gc, value);
return false;
}
}
if(key == "GetU16BE")
{
int64_t index;
if(GetArgument(args,0,index) && (size_t)index < bArray->data.size() && (size_t)index + 2 <= bArray->data.size())
{
int64_t value = (int64_t)BitConverter::ToUint16BE(bArray->data[(size_t)index]);
cse.back()->Push(gc, value);
return false;
}
}
if(key == "GetU32BE")
{
int64_t index;
if(GetArgument(args,0,index) && (size_t)index < bArray->data.size() && (size_t)index + 4 <= bArray->data.size())
{
int64_t value = (int64_t)BitConverter::ToUint32BE(bArray->data[(size_t)index]);
cse.back()->Push(gc, value);
return false;
}
}
if(key == "GetU64BE")
{
int64_t index;
if(GetArgument(args,0,index) && (size_t)index < bArray->data.size() && (size_t)index + 8 <= bArray->data.size())
{
uint64_t value = BitConverter::ToUint64BE(bArray->data[(size_t)index]);
int64_t value2 = 0;
memcpy(&value2, &value, sizeof(uint64_t));
cse.back()->Push(gc, value2);
return false;
}
}
if(key == "GetU16LE")
{
int64_t index;
if(GetArgument(args,0,index) && (size_t)index < bArray->data.size() && (size_t)index + 2 <= bArray->data.size())
{
int64_t value = (int64_t)BitConverter::ToUint16LE(bArray->data[(size_t)index]);
cse.back()->Push(gc, value);
return false;
}
}
if(key == "GetU32LE")
{
int64_t index;
if(GetArgument(args,0,index) && (size_t)index < bArray->data.size() && (size_t)index + 4 <= bArray->data.size())
{
int64_t value = (int64_t)BitConverter::ToUint32LE(bArray->data[(size_t)index]);
cse.back()->Push(gc, value);
return false;
}
}
if(key == "GetU64LE")
{
int64_t index;
if(GetArgument(args,0,index) && (size_t)index < bArray->data.size() && (size_t)index + 8 <= bArray->data.size())
{
uint64_t value = BitConverter::ToUint64LE(bArray->data[(size_t)index]);
int64_t value2 = 0;
memcpy(&value2, &value, sizeof(uint64_t));
cse.back()->Push(gc, value2);
return false;
}
}
if(key == "GetS16BE")
{
int64_t index;
if(GetArgument(args,0,index) && (size_t)index < bArray->data.size() && (size_t)index + 2 <= bArray->data.size())
{
int64_t value = (int64_t)BitConverter::ToSint16BE(bArray->data[(size_t)index]);
cse.back()->Push(gc, value);
return false;
}
}
if(key == "GetS32BE")
{
int64_t index;
if(GetArgument(args,0,index) && (size_t)index < bArray->data.size() && (size_t)index + 4 <= bArray->data.size())
{
int64_t value = (int64_t)BitConverter::ToSint32BE(bArray->data[(size_t)index]);
cse.back()->Push(gc, value);
return false;
}
}
if(key == "GetS64BE")
{
int64_t index;
if(GetArgument(args,0,index) && (size_t)index < bArray->data.size() && (size_t)index + 8 <= bArray->data.size())
{
int64_t value = BitConverter::ToSint64BE(bArray->data[(size_t)index]);
cse.back()->Push(gc, value);
return false;
}
}
if(key == "GetS16LE")
{
int64_t index;
if(GetArgument(args,0,index) && (size_t)index < bArray->data.size() && (size_t)index + 2 <= bArray->data.size())
{
int64_t value = (int64_t)BitConverter::ToSint16LE(bArray->data[(size_t)index]);
cse.back()->Push(gc, value);
return false;
}
}
if(key == "GetS32LE")
{
int64_t index;
if(GetArgument(args,0,index) && (size_t)index < bArray->data.size() && (size_t)index + 4 <= bArray->data.size())
{
int64_t value = (int64_t)BitConverter::ToSint32LE(bArray->data[(size_t)index]);
cse.back()->Push(gc, value);
return false;
}
}
if(key == "GetS64LE")
{
int64_t index;
if(GetArgument(args,0,index) && (size_t)index < bArray->data.size() && (size_t)index + 8 <= bArray->data.size())
{
int64_t value = BitConverter::ToSint64LE(bArray->data[(size_t)index]);
cse.back()->Push(gc, value);
return false;
}
}
if(key == "GetF32LE")
{
int64_t index;
if(GetArgument(args,0,index) && (size_t)index < bArray->data.size() && (size_t)index + 4 <= bArray->data.size())
{
double value = (double)BitConverter::ToFloatLE(bArray->data[(size_t)index]);
cse.back()->Push(gc, value);
return false;
}
}
if(key == "GetF64LE")
{
int64_t index;
if(GetArgument(args,0,index) && (size_t)index < bArray->data.size() && (size_t)index + 8 <= bArray->data.size())
{
uint64_t value = BitConverter::ToDoubleLE(bArray->data[(size_t)index]);
cse.back()->Push(gc, value);
return false;
}
}
if(key == "GetF32BE")
{
int64_t index;
if(GetArgument(args,0,index) && (size_t)index < bArray->data.size() && (size_t)index + 4 <= bArray->data.size())
{
double value = (double)BitConverter::ToFloatBE(bArray->data[(size_t)index]);
cse.back()->Push(gc, value);
return false;
}
}
if(key == "GetF64BE")
{
int64_t index;
if(GetArgument(args,0,index) && (size_t)index < bArray->data.size() && (size_t)index + 8 <= bArray->data.size())
{
uint64_t value = BitConverter::ToDoubleBE(bArray->data[(size_t)index]);
cse.back()->Push(gc, value);
return false;
}
}
if(key == "GetUuid")
{
int64_t index;
if(GetArgument(args,0,index) && (size_t)index < bArray->data.size() && (size_t)index + 16 <= bArray->data.size())
{
auto value = BitConverter::ToUuid(bArray->data[(size_t)index]);
cse.back()->Push(gc, value);
return false;
}
}
cse.back()->Push(gc, Undefined());
return false;
}
else if(aArray != nullptr)
{
if(key == "ToString")
{
cse.back()->Push(gc,ToString(gc,aArray));
return false;
}
else if(key == "GetAt")
{
if(args.size() != 1)
{
throw VMException("AArray.GetAt must only accept one argument");
}
cse.back()->Push(gc, aArray->Get(gc,args[0]));
return false;
}
else if(key == "SetAt")
{
if(args.size() != 2)
{
throw VMException("AArray.SetAt must only accept two arguments");
}
aArray->Set(gc,args[0],args[1]);
cse.back()->Push(gc, args[1]);
return false;
}
else if(key == "GetKey")
{
if(args.size() != 1)
{
throw VMException("AArray.GetKey must only accept one argument");
}
if(!std::holds_alternative<int64_t>(args[0]))
{
throw VMException("AArray.GetKey must only accept a long");
}
gc->BarrierBegin();
auto res = aArray->GetKey(std::get<int64_t>(args[0]));
gc->BarrierEnd();
cse.back()->Push(gc, res);
return false;
}
else if(key == "GetValue")
{
if(args.size() != 1)
{
throw VMException("AArray.GetValue must only accept one argument");
}
if(!std::holds_alternative<int64_t>(args[0]))
{
throw VMException("AArray.GetValue must only accept a long");
}
gc->BarrierBegin();
auto res = aArray->GetValue(std::get<int64_t>(args[0]));
gc->BarrierEnd();
cse.back()->Push(gc, res);
return false;
}
else if(key == "SetKey")
{
if(args.size() != 2)
{
throw VMException("AArray.SetKey must only accept two arguments");
}
if(!std::holds_alternative<int64_t>(args[0]))
{
throw VMException("AArray.SetKey first argument must only accept a long");
}
gc->BarrierBegin();
aArray->SetKey(std::get<int64_t>(args[0]),args[1]);
gc->BarrierEnd();
cse.back()->Push(gc, args[1]);
return false;
}
else if(key == "SetValue")
{
if(args.size() != 2)
{
throw VMException("AArray.SetValue must only accept two arguments");
}
if(!std::holds_alternative<int64_t>(args[0]))
{
throw VMException("AArray.SetValue first argument must only accept a long");
}
gc->BarrierBegin();
aArray->SetValue(std::get<int64_t>(args[0]),args[1]);
gc->BarrierEnd();
cse.back()->Push(gc, args[1]);
return false;
}
else if(key == "Count" || key == "Length")
{
gc->BarrierBegin();
cse.back()->Push(gc, aArray->Count());
gc->BarrierEnd();
return false;
}
else if(key == "GetEnumerator")
{
cse.back()->Push(gc,TAssociativeArrayEnumerator::Create(ls,aArray));
return false;
}
cse.back()->Push(gc,Undefined());
return false;
}
else if(list != nullptr)
{
if(key == "GetEnumerator")
{
cse.back()->Push(gc, TListEnumerator::Create(ls,list));
return false;
}
else if(key == "ToString")
{
cse.back()->Push(gc,Json_Encode(list));
return false;
}
else if(key == "Insert")
{
if(args.size() != 2)
{
throw VMException("List.Insert must only accept two arguments");
}
int64_t index;
if(!GetArgument(args,0,index))
{
throw VMException("List.Insert first argument must be Long");
}
gc->BarrierBegin();
list->Insert(index,args[1]);
gc->BarrierEnd();
cse.back()->Push(gc, Undefined());
return false;
}
else if(key == "Add")
{
if(args.size() != 1)
{
throw VMException("List.Add must only accept one argument");
}
gc->BarrierBegin();
list->Add(args[0]);
gc->BarrierEnd();
cse.back()->Push(gc, Undefined());
return false;
}
else if(key == "Contains")
{
if(args.size() != 1)
{
throw VMException("List.Contains must only accept one argument");
}
gc->BarrierBegin();
for(int64_t i = 0; i < list->Count(); i++)
{
auto item = list->Get(i);
gc->BarrierEnd();
if(Equals(gc,args[0],item))
{
cse.back()->Push(gc, true);
return false;
}
gc->BarrierBegin();
}
gc->BarrierEnd();
cse.back()->Push(gc, false);
return false;
}
else if(key == "IndexOf")
{
//IndexOf(obj, $idx)
if(args.size() < 1 || args.size() > 2)
{
throw VMException("List.IndexOf must either have one or two arguments");
}
int64_t i=0;
GetArgument(args,1,i);
gc->BarrierBegin();
for(; i < list->Count(); i++)
{
auto item = list->Get(i);
gc->BarrierEnd();
if(Equals(gc,args[0],item))
{
cse.back()->Push(gc,i);
return false;
}
gc->BarrierBegin();
}
gc->BarrierEnd();
cse.back()->Push(gc,(int64_t)-1);
return false;
}
else if(key == "RemoveAllEqual")
{
if(args.size() != 1)
{
throw VMException("List.RemoveAllEqual must only accept one argument");
}
gc->BarrierBegin();
for(int64_t i = 0; i < list->Count(); i++)
{
auto item = list->Get(i);
gc->BarrierEnd();
if(Equals(gc,args[0],item))
{
gc->BarrierBegin();
list->RemoveAt(i);
i--;
}else gc->BarrierBegin();
}
gc->BarrierEnd();
cse.back()->Push(gc, Undefined());
return false;
}
else if(key == "Remove")
{
if(args.size() != 1)
{
throw VMException("List.Remove must only accept one argument");
}
gc->BarrierBegin();
for(int64_t i = 0; i < list->Count(); i++)
{
auto item = list->Get(i);
gc->BarrierEnd();
if(Equals(gc,args[0],item))
{
gc->BarrierBegin();
list->RemoveAt(i);
gc->BarrierEnd();
break;
}
gc->BarrierBegin();
}
gc->BarrierEnd();
cse.back()->Push(gc, Undefined());
return false;
}
else if(key == "RemoveAt")
{
if(args.size() != 1)
{
throw VMException("List.RemoveAt must only accept one argument");
}
if(!std::holds_alternative<int64_t>(args[0]))
{
throw VMException("List.RemoveAt must only accept a long");
}
gc->BarrierBegin();
list->RemoveAt(std::get<int64_t>(args[0]));
gc->BarrierEnd();
cse.back()->Push(gc, Undefined());
return false;
}
else if(key == "Clear")
{
gc->BarrierBegin();
list->Clear();
gc->BarrierEnd();
cse.back()->Push(gc, Undefined());
return false;
}
else if(key == "GetAt")
{
if(args.size() != 1)
{
throw VMException("List.GetAt must only accept one argument");
}
if(!std::holds_alternative<int64_t>(args[0]))
{
throw VMException("List.GetAt must only accept a long");
}
int64_t index = std::get<int64_t>(args[0]);
if(index >= 0 && index < list->Count())
{
cse.back()->Push(gc, list->Get(index));
return false;
}
}
else if(key == "SetAt")
{
if(args.size() != 2)
{
throw VMException("List.SetAt must only accept two arguments");
}
if(!std::holds_alternative<int64_t>(args[0]))
{
throw VMException("List.SetAt first argument must only accept a long");
}
int64_t index = std::get<int64_t>(args[0]);
if(index >= 0 && index < list->Count())
{
list->Set(index,args[1]);
return false;
}
}
else if(key == "Count" || key == "Length")
{
gc->BarrierBegin();
cse.back()->Push(gc, list->Count());
gc->BarrierEnd();
return false;
}
cse.back()->Push(gc, Undefined());
return false;
}
else if(dynList != nullptr)
{
if(key == "GetEnumerator")
{
cse.back()->Push(gc, TDynamicListEnumerator::Create(ls, dynList));
return false;
}
else if(key == "ToString")
{
cse.back()->Push(gc, dynList->ToString(ls));
return false;
}
else if(key == "Insert")
{
if(args.size() != 2)
{
throw VMException("List.Insert must only accept two arguments");
}
int64_t index;
if(!GetArgument(args,0,index))
{
throw VMException("List.Insert first argument must be Long");
}
cse.back()->Push(gc, dynList->Insert(ls,index,args[0]));
return false;
}
if(key == "Add")
{
if(args.size() != 1)
{
throw VMException("List.Add must only accept one argument");
}
cse.back()->Push(gc,dynList->Add(ls,args[0]));
return false;
}
if(key == "RemoveAllEqual")
{
if(args.size() != 1)
{
throw VMException("List.RemoveAllEqual must only accept one argument");
}
cse.back()->Push(gc,dynList->RemoveAllEqual(ls, args[0]));
return false;
}
if(key == "Remove")
{
if(args.size() != 1)
{
throw VMException("List.Remove must only accept one argument");
}
cse.back()->Push(gc,dynList->Remove(ls, args[0]));
return false;
}
if(key == "RemoveAt")
{
if(args.size() != 1)
{
throw VMException("List.RemoveAt must only accept one argument");
}
if(!std::holds_alternative<int64_t>(args[0]))
{
throw VMException("List.RemoveAt must only accept a long");
}
cse.back()->Push(gc,dynList->RemoveAt(ls,std::get<int64_t>(args[0])));
return false;
}
if(key == "Clear")
{
cse.back()->Push(gc, dynList->Clear(ls));
return false;
}
if(key == "GetAt")
{
if(args.size() != 1)
{
throw VMException("List.GetAt must only accept one argument");
}
if(!std::holds_alternative<int64_t>(args[0]))
{
throw VMException("List.GetAt must only accept a long");
}
int64_t index = std::get<int64_t>(args[0]);
if(index >= 0)
{
cse.back()->Push(gc, dynList->GetAt(ls,index));
return false;
}
}
if(key == "SetAt")
{
if(args.size() != 2)
{
throw VMException("List.SetAt must only accept two arguments");
}
if(!std::holds_alternative<int64_t>(args[0]))
{
throw VMException("List.SetAt first argument must only accept a long");
}
int64_t index = std::get<int64_t>(args[0]);
if(index >= 0)
{
cse.back()->Push(gc,dynList->SetAt(ls,index,args[1]));
return false;
}
}
if(key == "Count" || key == "Length")
{
cse.back()->Push(gc, dynList->Count(ls));
return false;
}
cse.back()->Push(gc, Undefined());
return false;
}
else if(cls != nullptr)
{
gc->BarrierBegin();
auto obj=cls->GetValue(cse.back()->callable->className,key);
gc->BarrierEnd();
TClosure* clos;
TCallable* callable;
if(GetObjectHeap(obj,clos))
{
this->AddCallStackEntry(ls,clos,args);
return true;
}
else if(GetObjectHeap(obj,callable))
{
cse.back()->Push(gc,callable->Call(ls,args));
return false;
}
cse.back()->Push(gc,Undefined());
return false;
}
else if(dict != nullptr)
{
if(key == "ToString" && !dict->MethodExists(ls, key) && args.empty())
{
cse.back()->Push(gc,Json_Encode(dict));
return false;
}
gc->BarrierBegin();
auto o = dict->GetValue(key);
gc->BarrierEnd();
return InvokeMethod(ls,o,dict,args);
}
else if(dynDict != nullptr)
{
cse.back()->Push(gc,dynDict->CallMethod(ls, key, args));
return false;
}
else if(callable != nullptr)
{
if(key == "Call")
{
TList* argls;
if(GetArgumentHeap(args,0,argls))
{
TClosure* clo = dynamic_cast<TClosure*>(callable);
if(clo != nullptr)
{
AddCallStackEntry(ls,clo,argls->items);
return true;
}
else
{
cse.back()->Push(gc,callable->Call(ls, argls->items));
return false;
}
}
}
cse.back()->Push(gc,nullptr);
return false;
}
else
{
cse.back()->Push(gc, Undefined());
}
}
else
{
cse.back()->Push(gc,Undefined());
}
}
return false;
}
}