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

3694 lines
153 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 <cmath>
#include <cstddef>
#include <cstdint>
#include <cstring>
#include <exception>
#include <iostream>
#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;
}
} // namespace Tesses::CrossLang