#include "CrossLang.hpp" #include "TessesFramework/Serialization/BitConverter.hpp" #include "TessesFramework/Streams/ByteReader.hpp" #include "TessesFramework/Streams/ByteWriter.hpp" #include "TessesFramework/Uuid.hpp" #include #include #include #include #include #include #include #include namespace Tesses::CrossLang { extern bool IHttpServer_Handle(std::shared_ptr svr,std::vector& args); bool InterperterThread::ExecuteMethod2(std::shared_ptr gc, TObject instance, std::string key, std::vector args) { std::vector& cse=this->call_stack_entries; if(!cse.empty()) { GCList ls(gc); std::regex regex; TVMVersion version; if(std::holds_alternative(instance)) { if(key == "ToString") { cse.back()->Push(gc,"null"); return false; } cse.back()->Push(gc,Undefined()); return false; }else if(std::holds_alternative(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(instance)) { bool flag = std::get(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(instance)) { char c = std::get(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(instance)) { double number = std::get(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(args[0])) { throw VMException("Double.Pow must only accept a double"); } cse.back()->Push(gc,pow(number, std::get(args[0]))); return false; } if(key == "Atan2") { if(args.size() != 1) { throw VMException("Double.Atan2 must only accept one argument"); } if(!std::holds_alternative(args[0])) { throw VMException("Double.Atan2 must only accept a double"); } cse.back()->Push(gc,atan2(number, std::get(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(instance)) { int64_t number = std::get(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(instance)) { auto path = std::get(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(instance)) { std::string str = std::get(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(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(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(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(args[0])) { size_t offset = (size_t)std::get(args[0]); size_t count = std::string::npos; if(args.size() == 2 && std::holds_alternative(args[1])) { count = (size_t)std::get(args[1]); } cse.back()->Push(gc, str.substr(offset,count)); return false; } } if(key == "Remove") { if(args.size() >=1 && std::holds_alternative(args[0])) { size_t offset = (size_t)std::get(args[0]); size_t count = std::string::npos; if(args.size() == 2 && std::holds_alternative(args[1])) { count = (size_t)std::get(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(args[0])) ? std::get(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(args[0])) ? std::get(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(args[0])) throw VMException("String.Split first arg must be a string"); else delimiter = std::get(args[0]); if(args.size() > 1 && !std::holds_alternative(args[1])) throw VMException("String.Split second arg must be a bool"); else if(args.size() > 1) removeEmpty = std::get(args[1]); if(args.size() > 2 && !std::holds_alternative(args[2])) throw VMException("String.Split third arg must be a int64_t"); else if(args.size() > 2) count = (size_t)std::get(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(args[0])) { throw VMException("String.GetAt must only accept a long"); } size_t index = (size_t)std::get(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>(instance)) { auto& time = std::get>(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>(instance)) { auto& date = std::get>(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(date->ToLocal())); return false; } if(key == "ToUTC") { cse.back()->Push(gc, std::make_shared(date->ToUTC())); return false; } cse.back()->Push(gc, nullptr); return false; } else if(std::holds_alternative>(instance)) { auto textReader = std::get>(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 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 writer; if(GetArgument(args,0,writer)) { textReader->CopyTo(*writer); } } cse.back()->Push(gc, Undefined()); return false; } else if(std::holds_alternative>(instance)) { auto textWriter=std::get>(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>(instance)) { auto& br = std::get>(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>(instance)) { auto& bw = std::get>(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>(instance)) { auto& sse = std::get>(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 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>(instance)) { auto& strm = std::get>(instance); if(strm != nullptr) { auto memStrm = std::dynamic_pointer_cast(strm); auto netStrm = std::dynamic_pointer_cast(strm); auto mystrm = std::dynamic_pointer_cast(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(args, 0, data) && GetArgument(args, 1, offset) && GetArgument(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(args, 0, data) && GetArgument(args, 1, offset) && GetArgument(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(args, 0, data) && GetArgument(args, 1, offset) && GetArgument(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(args, 0, data) && GetArgument(args, 1, offset) && GetArgument(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(args, 0, data) && GetArgument(args, 1, offset) && GetArgument(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(args, 0, data) && GetArgument(args, 1, offset) && GetArgument(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 data; int64_t buffSize; if(GetArgument(args,0,data)) { if(!GetArgument(args,1,buffSize)) buffSize=1024; strm->CopyTo(data,(size_t)buffSize); } cse.back()->Push(gc, nullptr); return false; } if(key == "CopyToLimit") { std::shared_ptr data; int64_t cnt; int64_t buffSize; if(GetArgument(args,0,data) && GetArgument(args,1,cnt)) { if(!GetArgument(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(args,0,pos)) pos=0; if(!GetArgument(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>(instance)) { auto svr = std::get>(instance); if(svr != nullptr) { auto mountable = std::dynamic_pointer_cast(svr); auto routable = std::dynamic_pointer_cast(svr); if(mountable != nullptr) { if(key == "Mount") { Tesses::Framework::Filesystem::VFSPath p; if(args.size() > 1 && GetArgumentAsPath(args,0,p)) { std::shared_ptr 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>(instance)) { auto vfs = std::get>(instance); if(vfs != nullptr) { auto myvfs = std::dynamic_pointer_cast(vfs); auto mountable = std::dynamic_pointer_cast(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 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 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 lastWrite; std::shared_ptr 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(lastWrite)); dict->SetValue("LastAccess", std::make_shared(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(data.LastAccess)), TDItem("LastModified", std::make_shared(data.LastModified)), TDItem("LastStatus", std::make_shared(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(instance)) { auto& obj = std::get(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(instance)) { auto obj = std::get(instance).obj; auto list = dynamic_cast(obj); auto dynList = dynamic_cast(obj); auto bArray = dynamic_cast(obj); auto dict = dynamic_cast(obj); auto dynDict = dynamic_cast(obj); auto ittr = dynamic_cast(obj); auto env = dynamic_cast(obj); auto subEnv = dynamic_cast(obj); auto rootEnv = dynamic_cast(obj); auto callable = dynamic_cast(obj); auto callstackEntry = dynamic_cast(obj); auto natObj = dynamic_cast(obj); auto cls = dynamic_cast(obj); auto aArray=dynamic_cast(obj); auto ttask = dynamic_cast(obj); auto file = dynamic_cast(obj); auto queryable = dynamic_cast(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 vfs; if(GetArgument(args,0, vfs)) { auto rfs = std::dynamic_pointer_cast(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(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(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 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(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(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 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(args[0])) { throw VMException("ByteArray.GetAt must only accept a long"); } size_t index = (size_t)std::get(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(args[0])) { throw VMException("ByteArray.SetAt first argument must only accept a long"); } uint8_t v = 0; if(std::holds_alternative(args[1])) { v = (uint8_t)(std::get(args[1]) & 0xFF); } size_t index = (size_t)std::get(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(args,0,bArray2)) { throw VMException("ByteArray.CopyTo first argument must be a ByteArray"); } if(!GetArgument(args,1, offsetSrc)) { throw VMException("ByteArray.CopyTo second argument must be a Long (offsetSrc)"); } if(!GetArgument(args,2, offsetDest)) { throw VMException("ByteArray.CopyTo third argument must be a Long (offsetDest)"); } if(!GetArgument(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(std::min(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(args,1,bArray2)) { throw VMException("ByteArray.Insert second argument must be a ByteArray"); } if(!GetArgument(args,0, offsetSrc)) { throw VMException("ByteArray.Insert first argument must be a Long (offsetSrc)"); } if(!GetArgument(args,2, offsetDest)) { throw VMException("ByteArray.Insert third argument must be a Long (offsetDest)"); } if(!GetArgument(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(args,0,bArray2)) { throw VMException("ByteArray.Append first argument must be a ByteArray"); } if(!GetArgument(args,1, offset)) { throw VMException("ByteArray.Append second argument must be a Long (offset)"); } if(!GetArgument(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(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(args[0])) { throw VMException("ByteArray.Resize must only accept a long"); } size_t len = (size_t)std::get(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(args[0])) { throw VMException("AArray.GetKey must only accept a long"); } gc->BarrierBegin(); auto res = aArray->GetKey(std::get(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(args[0])) { throw VMException("AArray.GetValue must only accept a long"); } gc->BarrierBegin(); auto res = aArray->GetValue(std::get(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(args[0])) { throw VMException("AArray.SetKey first argument must only accept a long"); } gc->BarrierBegin(); aArray->SetKey(std::get(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(args[0])) { throw VMException("AArray.SetValue first argument must only accept a long"); } gc->BarrierBegin(); aArray->SetValue(std::get(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(args[0])) { throw VMException("List.RemoveAt must only accept a long"); } gc->BarrierBegin(); list->RemoveAt(std::get(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(args[0])) { throw VMException("List.GetAt must only accept a long"); } int64_t index = std::get(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(args[0])) { throw VMException("List.SetAt first argument must only accept a long"); } int64_t index = std::get(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(args[0])) { throw VMException("List.RemoveAt must only accept a long"); } cse.back()->Push(gc,dynList->RemoveAt(ls,std::get(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(args[0])) { throw VMException("List.GetAt must only accept a long"); } int64_t index = std::get(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(args[0])) { throw VMException("List.SetAt first argument must only accept a long"); } int64_t index = std::get(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(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; } }