mirror of
https://onedev.site.tesses.net/crosslang
synced 2026-02-08 17:15:45 +00:00
Add embeddir finally and embedstrm
This commit is contained in:
@@ -154,6 +154,7 @@ src/runtime_methods/path.cpp
|
||||
src/runtime_methods/env.cpp
|
||||
src/runtime_methods/process.cpp
|
||||
src/runtime_methods/helpers.cpp
|
||||
src/types/embed.cpp
|
||||
src/types/async.cpp
|
||||
src/types/associativearray.cpp
|
||||
src/types/any.cpp
|
||||
|
||||
@@ -662,7 +662,9 @@ typedef enum {
|
||||
JMPIFCONTINUE,
|
||||
JMPIFDEFINED,
|
||||
DECLARECONSTVARIABLE,
|
||||
LINEINFO
|
||||
LINEINFO,
|
||||
PUSHRESOURCESTREAM,
|
||||
PUSHRESOUURCEDIR
|
||||
} Instruction;
|
||||
/**
|
||||
* @brief Base type for bytecode instruction
|
||||
@@ -762,6 +764,13 @@ class EmbedInstruction : public ByteCodeInstruction {
|
||||
size_t Size();
|
||||
void Write(std::vector<uint8_t>& data);
|
||||
};
|
||||
class EmbedStreamInstruction : public ByteCodeInstruction {
|
||||
public:
|
||||
uint32_t n;
|
||||
EmbedStreamInstruction(uint32_t n);
|
||||
size_t Size();
|
||||
void Write(std::vector<uint8_t>& data);
|
||||
};
|
||||
|
||||
class ClosureInstruction : public ByteCodeInstruction {
|
||||
public:
|
||||
@@ -867,6 +876,7 @@ class CodeGen {
|
||||
void GenNode(std::vector<ByteCodeInstruction*>& instructions, SyntaxNode n,int32_t scope, int32_t contscope, int32_t brkscope, int32_t contI, int32_t brkI);
|
||||
void GenPop(std::vector<ByteCodeInstruction*>& instrs,SyntaxNode n);
|
||||
public:
|
||||
std::shared_ptr<Tesses::Framework::Filesystem::VFS> embedFS;
|
||||
std::vector<std::pair<std::string, TVMVersion>> dependencies;
|
||||
std::vector<std::pair<std::string, TVMVersion>> tools;
|
||||
TVMVersion version;
|
||||
@@ -874,7 +884,7 @@ class CodeGen {
|
||||
std::string info;
|
||||
std::string icon;
|
||||
void GenRoot(SyntaxNode n);
|
||||
void Save(std::shared_ptr<Tesses::Framework::Filesystem::VFS> embedFS,std::shared_ptr<Tesses::Framework::Streams::Stream> output);
|
||||
void Save(std::shared_ptr<Tesses::Framework::Streams::Stream> output);
|
||||
~CodeGen();
|
||||
};
|
||||
/**
|
||||
@@ -883,10 +893,20 @@ class CodeGen {
|
||||
*/
|
||||
constexpr std::string_view HtmlRootExpression = "htmlRootExpression";
|
||||
/**
|
||||
* @brief an intrinsic function that embeads a resource from the filename based on the constant string argument
|
||||
* @brief an intrinsic function that embeds a resource from the filename based on the constant string argument
|
||||
*
|
||||
*/
|
||||
constexpr std::string_view EmbedExpression = "embedExpression";
|
||||
/**
|
||||
* @brief an intrinsic function that embeds a resource as a stream from the filename based on the constant string argument
|
||||
*
|
||||
*/
|
||||
constexpr std::string_view EmbedStreamExpression = "embedStreamExpression";
|
||||
/**
|
||||
* @brief an intrinsic function that embeds a resource directory from the directory name based on the constant string argument
|
||||
*
|
||||
*/
|
||||
constexpr std::string_view EmbedDirectoryExpression = "embedDirectoryExpression";
|
||||
/**
|
||||
* @brief Negative operator -EXPR
|
||||
*
|
||||
@@ -2061,6 +2081,8 @@ class GC {
|
||||
~TObjectStream();
|
||||
};
|
||||
|
||||
|
||||
|
||||
class TObjectHttpServer : public Tesses::Framework::Http::IHttpServer
|
||||
{
|
||||
public:
|
||||
@@ -2279,6 +2301,8 @@ class GC {
|
||||
bool JumpIfBreak(GC* gc);
|
||||
bool JumpIfContinue(GC* gc);
|
||||
bool LineInfo(GC* gc);
|
||||
bool PushResourceStream(GC* gc);
|
||||
bool PushResourceDirectory(GC* gc);
|
||||
public:
|
||||
static InterperterThread* Create(GCList* ls);
|
||||
static InterperterThread* Create(GCList& ls);
|
||||
@@ -2543,4 +2567,39 @@ class GC {
|
||||
|
||||
|
||||
std::shared_ptr<Tesses::Framework::Http::IHttpServer> ToHttpServer(GC* gc,TObject obj);
|
||||
|
||||
class EmbedStream : public Tesses::Framework::Streams::Stream
|
||||
{
|
||||
size_t offset;
|
||||
MarkedTObject file;
|
||||
uint32_t resource;
|
||||
|
||||
public:
|
||||
EmbedStream(GC* gc, TFile* file, uint32_t resource);
|
||||
bool CanRead();
|
||||
bool CanSeek();
|
||||
bool EndOfStream();
|
||||
size_t Read(uint8_t* buff, size_t len);
|
||||
int64_t GetPosition();
|
||||
int64_t GetLength();
|
||||
void Seek(int64_t pos, Tesses::Framework::Streams::SeekOrigin whence);
|
||||
};
|
||||
|
||||
class EmbedDirectory : public Tesses::Framework::Filesystem::VFS
|
||||
{
|
||||
MarkedTObject dir;
|
||||
TObject getEntry(Tesses::Framework::Filesystem::VFSPath path);
|
||||
public:
|
||||
EmbedDirectory(GC* gc, TDictionary* dict);
|
||||
std::shared_ptr<Tesses::Framework::Streams::Stream> OpenFile(Tesses::Framework::Filesystem::VFSPath path, std::string mode);
|
||||
void CreateDirectory(Tesses::Framework::Filesystem::VFSPath path);
|
||||
void DeleteDirectory(Tesses::Framework::Filesystem::VFSPath path);
|
||||
bool RegularFileExists(Tesses::Framework::Filesystem::VFSPath path);
|
||||
bool DirectoryExists(Tesses::Framework::Filesystem::VFSPath path);
|
||||
void DeleteFile(Tesses::Framework::Filesystem::VFSPath path);
|
||||
Tesses::Framework::Filesystem::VFSPathEnumerator EnumeratePaths(Tesses::Framework::Filesystem::VFSPath path);
|
||||
void MoveFile(Tesses::Framework::Filesystem::VFSPath src, Tesses::Framework::Filesystem::VFSPath dest);
|
||||
std::string VFSPathToSystem(Tesses::Framework::Filesystem::VFSPath path);
|
||||
Tesses::Framework::Filesystem::VFSPath SystemToVFSPath(std::string path);
|
||||
};
|
||||
};
|
||||
|
||||
@@ -83,6 +83,18 @@ namespace Tesses::CrossLang {
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
class PushResourceStreamChunkInstruction : public ChunkInstruction {
|
||||
public:
|
||||
PushResourceStreamChunkInstruction(std::string v) : value(v)
|
||||
{}
|
||||
std::string value;
|
||||
size_t Size()
|
||||
{
|
||||
return 5;
|
||||
}
|
||||
};
|
||||
|
||||
class LabelChunkInstruction : public ChunkInstruction {
|
||||
public:
|
||||
LabelChunkInstruction(std::string lbl) : lbl(lbl)
|
||||
@@ -285,6 +297,10 @@ namespace Tesses::CrossLang {
|
||||
{
|
||||
instrs.push_back(std::make_shared<SimpleChunkInstruction>(LINEINFO));
|
||||
}
|
||||
else if(name == "embeddir")
|
||||
{
|
||||
instrs.push_back(std::make_shared<SimpleChunkInstruction>(PUSHRESOUURCEDIR));
|
||||
}
|
||||
else if(name == "pushclosure")
|
||||
{
|
||||
auto closure = std::make_shared<ClosureChunkInstruction>(true);
|
||||
@@ -325,6 +341,14 @@ namespace Tesses::CrossLang {
|
||||
instrs.push_back(std::make_shared<PushResourceChunkInstruction>(str));
|
||||
}
|
||||
}
|
||||
else if(name == "embedstrm")
|
||||
{
|
||||
if(i < tokens.size() && tokens[i].type == LexTokenType::String)
|
||||
{
|
||||
std::string str = tokens[i++].text;
|
||||
instrs.push_back(std::make_shared<PushResourceStreamChunkInstruction>(str));
|
||||
}
|
||||
}
|
||||
else if(name == "push")
|
||||
{
|
||||
if(IsSym("."))
|
||||
@@ -1031,6 +1055,7 @@ namespace Tesses::CrossLang {
|
||||
auto chr = std::dynamic_pointer_cast<PushCharChunkInstruction>(item);
|
||||
auto chk = std::dynamic_pointer_cast<ClosureChunkInstruction>(item);
|
||||
auto reso = std::dynamic_pointer_cast<PushResourceChunkInstruction>(item);
|
||||
auto resos = std::dynamic_pointer_cast<PushResourceStreamChunkInstruction>(item);
|
||||
auto jmp = std::dynamic_pointer_cast<JumpStyleChunkInstruction>(item);
|
||||
auto scopeend = std::dynamic_pointer_cast<ScopeEndTimesChunkInstruction>(item);
|
||||
if(lbl)
|
||||
@@ -1066,6 +1091,10 @@ namespace Tesses::CrossLang {
|
||||
{
|
||||
chunks[chunkId].second.push_back(std::make_shared<EmbedInstruction>(GetResource(reso->value)));
|
||||
}
|
||||
if(resos)
|
||||
{
|
||||
chunks[chunkId].second.push_back(std::make_shared<EmbedStreamInstruction>(GetResource(reso->value)));
|
||||
}
|
||||
if(jmp)
|
||||
{
|
||||
chunks[chunkId].second.push_back(std::make_shared<JumpStyleInstruction>(jmp->instr,jmp->lbl));
|
||||
|
||||
@@ -223,6 +223,7 @@ namespace Tesses::CrossLang {
|
||||
{
|
||||
switch(code[i++])
|
||||
{
|
||||
case PUSHRESOURCESTREAM:
|
||||
case PUSHRESOURCE:
|
||||
case PUSHSTRING:
|
||||
case SCOPEENDTIMES:
|
||||
@@ -381,6 +382,9 @@ namespace Tesses::CrossLang {
|
||||
case APPENDDICT:
|
||||
buffer.append("appenddict");
|
||||
break;
|
||||
case PUSHRESOUURCEDIR:
|
||||
buffer.append("embeddir");
|
||||
break;
|
||||
case PUSHRESOURCE:
|
||||
{
|
||||
uint32_t clId = (uint32_t)code[i++] << 24;
|
||||
@@ -391,6 +395,16 @@ namespace Tesses::CrossLang {
|
||||
buffer.append(EscapeString(name + "-" + version.ToString()+"_"+ std::to_string(clId) + ".bin",true));
|
||||
}
|
||||
break;
|
||||
case PUSHRESOURCESTREAM:
|
||||
{
|
||||
uint32_t clId = (uint32_t)code[i++] << 24;
|
||||
clId |= (uint32_t)code[i++] << 16;
|
||||
clId |= (uint32_t)code[i++] << 8;
|
||||
clId |= (uint32_t)code[i++];
|
||||
buffer.append("embedstrm ");
|
||||
buffer.append(EscapeString(name + "-" + version.ToString()+"_"+ std::to_string(clId) + ".bin",true));
|
||||
}
|
||||
break;
|
||||
case PUSHLONG:
|
||||
{
|
||||
uint64_t number = (uint64_t)code[i++] << 56;
|
||||
|
||||
@@ -34,7 +34,7 @@ namespace Tesses::CrossLang
|
||||
}
|
||||
|
||||
|
||||
void CodeGen::Save(std::shared_ptr<Tesses::Framework::Filesystem::VFS> vfs, std::shared_ptr<Tesses::Framework::Streams::Stream> stream)
|
||||
void CodeGen::Save(std::shared_ptr<Tesses::Framework::Streams::Stream> stream)
|
||||
{
|
||||
TVMVersion runtime_version(TVM_MAJOR,TVM_MINOR,TVM_PATCH,TVM_BUILD,TVM_VERSIONSTAGE);
|
||||
uint8_t buffer[18];
|
||||
@@ -235,7 +235,7 @@ namespace Tesses::CrossLang
|
||||
{
|
||||
memcpy(buffer,"RESO",4);
|
||||
Write(stream,buffer,4);
|
||||
WriteInt(stream,reso->GetLength(vfs));
|
||||
WriteInt(stream,reso->GetLength(embedFS));
|
||||
reso->Write(stream);
|
||||
}
|
||||
if(!this->icon.empty())
|
||||
@@ -354,6 +354,21 @@ namespace Tesses::CrossLang
|
||||
BitConverter::FromUint32BE(buff[0],this->n);
|
||||
instr.insert(instr.end(),buff.begin(),buff.end());
|
||||
}
|
||||
EmbedStreamInstruction::EmbedStreamInstruction(uint32_t s)
|
||||
{
|
||||
this->n = s;
|
||||
}
|
||||
size_t EmbedStreamInstruction::Size()
|
||||
{
|
||||
return 5;
|
||||
}
|
||||
void EmbedStreamInstruction::Write(std::vector<uint8_t>& instr)
|
||||
{
|
||||
instr.push_back(PUSHRESOURCESTREAM);
|
||||
std::array<uint8_t,4> buff;
|
||||
BitConverter::FromUint32BE(buff[0],this->n);
|
||||
instr.insert(instr.end(),buff.begin(),buff.end());
|
||||
}
|
||||
ClosureInstruction::ClosureInstruction(uint32_t s,bool hasScope)
|
||||
{
|
||||
this->n = s;
|
||||
@@ -1365,6 +1380,49 @@ namespace Tesses::CrossLang
|
||||
instructions.push_back(new EmbedInstruction(GetResource(std::make_shared<ResourceFile>(filename))));
|
||||
|
||||
}
|
||||
else if(adv.nodeName == EmbedStreamExpression && adv.nodes.size() == 1 && std::holds_alternative<std::string>(adv.nodes[0]))
|
||||
{
|
||||
std::string filename = std::get<std::string>(adv.nodes[0]);
|
||||
instructions.push_back(new EmbedStreamInstruction(GetResource(std::make_shared<ResourceFile>(filename))));
|
||||
|
||||
}
|
||||
else if(adv.nodeName == EmbedDirectoryExpression && adv.nodes.size() == 1 && std::holds_alternative<std::string>(adv.nodes[0]))
|
||||
{
|
||||
std::string filename = std::get<std::string>(adv.nodes[0]);
|
||||
std::function<void(Tesses::Framework::Filesystem::VFSPath path)> embedDir;
|
||||
embedDir = [&](Tesses::Framework::Filesystem::VFSPath path)-> void {
|
||||
instructions.push_back(new SimpleInstruction(CREATEDICTIONARY));
|
||||
|
||||
if(embedFS != nullptr && embedFS->DirectoryExists(path))
|
||||
for(auto& item : embedFS->EnumeratePaths(path))
|
||||
{
|
||||
GenNode(instructions,item.GetFileName(),scope,contscope,brkscope,contI,brkI);
|
||||
if(embedFS->DirectoryExists(item))
|
||||
{
|
||||
embedDir(item);
|
||||
}
|
||||
else if(embedFS->RegularFileExists(item))
|
||||
{
|
||||
auto ce = AdvancedSyntaxNode::Create(ClosureExpression,true,{
|
||||
AdvancedSyntaxNode::Create(ParenthesesExpression,true,{}),
|
||||
AdvancedSyntaxNode::Create(ReturnStatement,false,{
|
||||
AdvancedSyntaxNode::Create(EmbedStreamExpression,true,{item.ToString()})
|
||||
})
|
||||
});
|
||||
GenNode(instructions,ce,scope,contscope,brkscope,contI,brkI);
|
||||
}
|
||||
else {
|
||||
instructions.push_back(new SimpleInstruction(PUSHUNDEFINED));
|
||||
}
|
||||
|
||||
instructions.push_back(new SimpleInstruction(APPENDDICT));
|
||||
}
|
||||
};
|
||||
embedDir(filename);
|
||||
//
|
||||
//instructions.push_back(new EmbedStreamInstruction(GetResource(std::make_shared<ResourceFile>(filename))));
|
||||
instructions.push_back(new SimpleInstruction(PUSHRESOUURCEDIR));
|
||||
}
|
||||
else if(adv.nodeName == HtmlRootExpression)
|
||||
{
|
||||
scope++;
|
||||
|
||||
@@ -922,7 +922,7 @@ namespace Tesses::CrossLang
|
||||
|
||||
auto ms = std::make_shared<Tesses::Framework::Streams::MemoryStream>(true);
|
||||
|
||||
gen.Save(nullptr,ms);
|
||||
gen.Save(ms);
|
||||
|
||||
ms->Seek(0, Tesses::Framework::Streams::SeekOrigin::Begin);
|
||||
|
||||
@@ -963,6 +963,26 @@ namespace Tesses::CrossLang
|
||||
EnsureSymbol(")");
|
||||
node = AdvancedSyntaxNode::Create(EmbedExpression, true,{embed.text});
|
||||
}
|
||||
else if(IsIdentifier("embedstrm"))
|
||||
{
|
||||
EnsureSymbol("(");
|
||||
if(i >= tokens.size()) throw std::out_of_range("End of file");
|
||||
auto embed = tokens[i];
|
||||
i++;
|
||||
if(embed.type != LexTokenType::String) throw SyntaxException(embed.lineInfo, "Expected an string for embed got a " + LexTokenType_ToString(embed.type) + " \"" + embed.text + "\"");
|
||||
EnsureSymbol(")");
|
||||
node = AdvancedSyntaxNode::Create(EmbedStreamExpression, true,{embed.text});
|
||||
}
|
||||
else if(IsIdentifier("embeddir"))
|
||||
{
|
||||
EnsureSymbol("(");
|
||||
if(i >= tokens.size()) throw std::out_of_range("End of file");
|
||||
auto embed = tokens[i];
|
||||
i++;
|
||||
if(embed.type != LexTokenType::String) throw SyntaxException(embed.lineInfo, "Expected an string for embed got a " + LexTokenType_ToString(embed.type) + " \"" + embed.text + "\"");
|
||||
EnsureSymbol(")");
|
||||
node = AdvancedSyntaxNode::Create(EmbedDirectoryExpression, true,{embed.text});
|
||||
}
|
||||
else if(tokens[i].type == LexTokenType::Identifier)
|
||||
{
|
||||
auto token=tokens[i];
|
||||
|
||||
@@ -256,6 +256,10 @@ int main(int argc, char** argv)
|
||||
Parser parser(tokens,gc,env);
|
||||
parser.debug = debug;
|
||||
CodeGen gen;
|
||||
|
||||
auto sfs = std::make_shared<SubdirFilesystem>(LocalFS,LocalFS->SystemToVFSPath(resourceDir.string()));
|
||||
gen.embedFS = sfs;
|
||||
|
||||
gen.GenRoot(parser.ParseRoot());
|
||||
gen.name = name;
|
||||
gen.version = version;
|
||||
@@ -275,9 +279,7 @@ int main(int argc, char** argv)
|
||||
{
|
||||
auto strm = std::make_shared<Tesses::Framework::Streams::FileStream>(outputDir / (name + "-" + version.ToString() + ".crvm"),"wb");
|
||||
|
||||
auto sfs = std::make_shared<SubdirFilesystem>(LocalFS,LocalFS->SystemToVFSPath(resourceDir.string()));
|
||||
|
||||
gen.Save(sfs,strm);
|
||||
gen.Save(strm);
|
||||
}
|
||||
if(gc != nullptr)
|
||||
{
|
||||
|
||||
@@ -24,13 +24,14 @@ int main(int argc, char** argv)
|
||||
Parser parser(tokens);
|
||||
|
||||
CodeGen gen;
|
||||
|
||||
auto sfs = std::make_shared<SubdirFilesystem>(LocalFS,VFSPath("."));
|
||||
gen.embedFS = sfs;
|
||||
gen.GenRoot(parser.ParseRoot());
|
||||
std::vector<uint8_t> data;
|
||||
{
|
||||
auto sfs = std::make_shared<SubdirFilesystem>(LocalFS,VFSPath("."));
|
||||
|
||||
auto strm2 = std::make_shared<Tesses::Framework::Streams::MemoryStream>(true);
|
||||
gen.Save(sfs,strm2);
|
||||
gen.Save(strm2);
|
||||
|
||||
|
||||
{
|
||||
@@ -78,11 +79,12 @@ int main(int argc, char** argv)
|
||||
Parser parser(tokens);
|
||||
|
||||
CodeGen gen;
|
||||
gen.GenRoot(parser.ParseRoot());
|
||||
|
||||
auto sfs = std::make_shared<SubdirFilesystem>(LocalFS,VFSPath("."));
|
||||
gen.embedFS = sfs;
|
||||
gen.GenRoot(parser.ParseRoot());
|
||||
|
||||
gen.Save(sfs, strm2);
|
||||
gen.Save(strm2);
|
||||
|
||||
}
|
||||
else if(source == "exit")
|
||||
@@ -98,11 +100,13 @@ int main(int argc, char** argv)
|
||||
Parser parser(tokens);
|
||||
|
||||
CodeGen gen;
|
||||
gen.GenRoot(parser.ParseRoot());
|
||||
|
||||
auto sfs = std::make_shared<SubdirFilesystem>(LocalFS,VFSPath("."));
|
||||
gen.embedFS = sfs;
|
||||
|
||||
gen.Save(sfs,strm2);
|
||||
gen.GenRoot(parser.ParseRoot());
|
||||
|
||||
gen.Save(strm2);
|
||||
}
|
||||
|
||||
{
|
||||
|
||||
@@ -264,6 +264,7 @@ namespace Tesses::CrossLang
|
||||
parser.debug = debug;
|
||||
SyntaxNode n = parser.ParseRoot();
|
||||
CodeGen gen;
|
||||
gen.embedFS = vfs;
|
||||
gen.GenRoot(n);
|
||||
gen.dependencies = dependencies;
|
||||
gen.tools = tools;
|
||||
@@ -275,7 +276,7 @@ namespace Tesses::CrossLang
|
||||
std::shared_ptr<Tesses::Framework::Streams::Stream> stream;
|
||||
if(GetObject(_out, stream))
|
||||
{
|
||||
gen.Save(vfs, stream);
|
||||
gen.Save(stream);
|
||||
}
|
||||
|
||||
|
||||
|
||||
228
src/types/embed.cpp
Normal file
228
src/types/embed.cpp
Normal file
@@ -0,0 +1,228 @@
|
||||
#include "CrossLang.hpp"
|
||||
|
||||
namespace Tesses::CrossLang {
|
||||
|
||||
EmbedStream::EmbedStream(GC* gc, TFile* file, uint32_t resource)
|
||||
{
|
||||
this->offset = 0;
|
||||
this->resource = resource;
|
||||
this->file = CreateMarkedTObject(gc,file);
|
||||
}
|
||||
bool EmbedStream::CanRead()
|
||||
{
|
||||
TFile* file;
|
||||
if(GetObjectHeap(this->file->GetObject(),file))
|
||||
{
|
||||
if(this->resource >= file->resources.size()) return false;
|
||||
if(this->offset >= file->resources[this->resource].size()) return false;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
bool EmbedStream::CanSeek()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
bool EmbedStream::EndOfStream()
|
||||
{
|
||||
return !CanRead();
|
||||
}
|
||||
size_t EmbedStream::Read(uint8_t* buff, size_t len)
|
||||
{
|
||||
TFile* file;
|
||||
|
||||
if(GetObjectHeap(this->file->GetObject(),file))
|
||||
{
|
||||
if(this->resource >= file->resources.size()) return 0;
|
||||
auto flen = file->resources[this->resource].size();
|
||||
if(this->offset >= flen) return 0;
|
||||
|
||||
len = std::min(len, std::min(
|
||||
flen,
|
||||
flen - this->offset
|
||||
));
|
||||
|
||||
memcpy(buff,file->resources[this->resource].data() + this->offset,len);
|
||||
this->offset += len;
|
||||
return len;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
int64_t EmbedStream::GetPosition()
|
||||
{
|
||||
return (int64_t)this->offset;
|
||||
}
|
||||
int64_t EmbedStream::GetLength()
|
||||
{
|
||||
TFile* file;
|
||||
|
||||
if(GetObjectHeap(this->file->GetObject(),file))
|
||||
{
|
||||
if(this->resource >= file->resources.size()) return 0;
|
||||
return (int64_t)file->resources[this->resource].size();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
void EmbedStream::Seek(int64_t pos, Tesses::Framework::Streams::SeekOrigin whence)
|
||||
{
|
||||
switch(whence)
|
||||
{
|
||||
case Tesses::Framework::Streams::SeekOrigin::Begin:
|
||||
this->offset = (uint32_t)pos;
|
||||
break;
|
||||
case Tesses::Framework::Streams::SeekOrigin::Current:
|
||||
{
|
||||
int64_t cur = this->offset;
|
||||
cur += pos;
|
||||
this->offset = (uint32_t)cur;
|
||||
}
|
||||
break;
|
||||
case Tesses::Framework::Streams::SeekOrigin::End:
|
||||
{
|
||||
TFile* file;
|
||||
|
||||
if(GetObjectHeap(this->file->GetObject(),file))
|
||||
{
|
||||
if(this->resource >= file->resources.size()) return;
|
||||
int64_t cur = (int64_t)file->resources[this->resource].size();
|
||||
cur += pos;
|
||||
this->offset = (uint32_t)cur;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
TObject EmbedDirectory::getEntry(Tesses::Framework::Filesystem::VFSPath path)
|
||||
{
|
||||
path = path.CollapseRelativeParents();
|
||||
auto curEntry = this->dir->GetObject();
|
||||
for(auto item : path.path)
|
||||
{
|
||||
TDictionary* dict;
|
||||
if(GetObjectHeap(curEntry,dict) && dict->HasValue(item))
|
||||
{
|
||||
curEntry = dict->GetValue(item);
|
||||
continue; //don't want to return undefined now do we
|
||||
}
|
||||
return Undefined();
|
||||
}
|
||||
return curEntry;
|
||||
}
|
||||
|
||||
std::shared_ptr<Tesses::Framework::Streams::Stream> EmbedDirectory::OpenFile(Tesses::Framework::Filesystem::VFSPath path, std::string mode)
|
||||
{
|
||||
if(mode != "r" && mode != "rb") return nullptr;
|
||||
|
||||
auto ent = getEntry(path);
|
||||
TCallable* call;
|
||||
if(GetObjectHeap(ent,call))
|
||||
{
|
||||
GCList ls(this->dir->GetGC());
|
||||
auto fileO = call->Call(ls,{});
|
||||
std::shared_ptr<Tesses::Framework::Streams::Stream> strm;
|
||||
if(GetObject(fileO,strm)) return strm;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
bool EmbedDirectory::RegularFileExists(Tesses::Framework::Filesystem::VFSPath path)
|
||||
{
|
||||
auto ent = getEntry(path);
|
||||
TCallable* call;
|
||||
return GetObjectHeap(ent,call);
|
||||
}
|
||||
bool EmbedDirectory::DirectoryExists(Tesses::Framework::Filesystem::VFSPath path)
|
||||
{
|
||||
auto ent = getEntry(path);
|
||||
TDictionary* dict;
|
||||
return GetObjectHeap(ent,dict);
|
||||
}
|
||||
|
||||
class DICT_DIRENUM
|
||||
{
|
||||
GCList ls;
|
||||
TDictionary* dict;
|
||||
std::map<std::string, Tesses::CrossLang::TObject>::iterator current;
|
||||
bool hasStarted = false;
|
||||
public:
|
||||
std::string GetCurrent()
|
||||
{
|
||||
return this->current->first;
|
||||
}
|
||||
DICT_DIRENUM(GC* gc, TDictionary* dict) : ls(gc), dict(dict)
|
||||
{
|
||||
ls.Add(dict);
|
||||
}
|
||||
bool MoveNext()
|
||||
{
|
||||
if(!this->hasStarted)
|
||||
{
|
||||
this->hasStarted=true;
|
||||
this->current = this->dict->items.begin();
|
||||
return !this->dict->items.empty();
|
||||
}
|
||||
else
|
||||
{
|
||||
this->current++;
|
||||
return this->current != this->dict->items.end();
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
Tesses::Framework::Filesystem::VFSPathEnumerator EmbedDirectory::EnumeratePaths(Tesses::Framework::Filesystem::VFSPath path)
|
||||
{
|
||||
auto ent = getEntry(path);
|
||||
TDictionary* dict;
|
||||
if(GetObjectHeap(ent,dict))
|
||||
{
|
||||
DICT_DIRENUM* dir2 = new DICT_DIRENUM(this->dir->GetGC(), dict);
|
||||
|
||||
Tesses::Framework::Filesystem::VFSPathEnumerator er(
|
||||
[dir2,path](Tesses::Framework::Filesystem::VFSPath& path2)->bool {
|
||||
if(dir2->MoveNext())
|
||||
{
|
||||
path2 = path / dir2->GetCurrent();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
},
|
||||
[dir2]()->void {
|
||||
delete dir2;
|
||||
}
|
||||
);
|
||||
|
||||
return er;
|
||||
}
|
||||
return Tesses::Framework::Filesystem::VFSPathEnumerator();
|
||||
}
|
||||
|
||||
EmbedDirectory::EmbedDirectory(GC* gc, TDictionary* dict)
|
||||
{
|
||||
this->dir = CreateMarkedTObject(gc, dict);
|
||||
}
|
||||
void EmbedDirectory::CreateDirectory(Tesses::Framework::Filesystem::VFSPath path)
|
||||
{
|
||||
//DO NOTHING
|
||||
}
|
||||
void EmbedDirectory::DeleteDirectory(Tesses::Framework::Filesystem::VFSPath path)
|
||||
{
|
||||
|
||||
}
|
||||
void EmbedDirectory::DeleteFile(Tesses::Framework::Filesystem::VFSPath path)
|
||||
{
|
||||
|
||||
}
|
||||
void EmbedDirectory::MoveFile(Tesses::Framework::Filesystem::VFSPath src, Tesses::Framework::Filesystem::VFSPath dest)
|
||||
{
|
||||
|
||||
}
|
||||
std::string EmbedDirectory::VFSPathToSystem(Tesses::Framework::Filesystem::VFSPath path)
|
||||
{
|
||||
return path.ToString();
|
||||
}
|
||||
Tesses::Framework::Filesystem::VFSPath EmbedDirectory::SystemToVFSPath(std::string path)
|
||||
{
|
||||
return path;
|
||||
}
|
||||
}
|
||||
@@ -123,7 +123,7 @@ namespace Tesses::CrossLang {
|
||||
CodeGen gen;
|
||||
gen.GenRoot(n);
|
||||
auto ms = std::make_shared<Tesses::Framework::Streams::MemoryStream>(true);
|
||||
gen.Save(nullptr, ms);
|
||||
gen.Save(ms);
|
||||
ms->Seek(0,Tesses::Framework::Streams::SeekOrigin::Begin);
|
||||
TFile* f = TFile::Create(ls);
|
||||
f->Load(ls.GetGC(),ms);
|
||||
|
||||
@@ -6971,7 +6971,35 @@ namespace Tesses::CrossLang {
|
||||
}
|
||||
return false;
|
||||
}
|
||||
bool InterperterThread::PushResourceStream(GC* gc)
|
||||
{
|
||||
std::vector<CallStackEntry*>& cse=this->call_stack_entries;
|
||||
if(!cse.empty())
|
||||
{
|
||||
auto stk = cse.back();
|
||||
std::vector<uint8_t>& code = stk->callable->closure->code;
|
||||
if(stk->ip + 4 <= code.size())
|
||||
{
|
||||
uint32_t n=BitConverter::ToUint32BE(code[stk->ip]);
|
||||
if(n >= stk->callable->file->resources.size())
|
||||
throw VMException("Can't read resource.");
|
||||
stk->ip = stk->ip + 4;
|
||||
|
||||
gc->BarrierBegin();
|
||||
GCList ls(gc);
|
||||
// TByteArray* arr = TByteArray::Create(ls);
|
||||
// arr->data = stk->callable->file->resources[n];
|
||||
stk->Push(gc, std::make_shared<EmbedStream>(gc,stk->callable->file,n));
|
||||
|
||||
gc->BarrierEnd();
|
||||
}
|
||||
else
|
||||
{
|
||||
throw VMException("Can't read chunk.");
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool InterperterThread::PushResource(GC* gc)
|
||||
{
|
||||
@@ -7016,6 +7044,21 @@ namespace Tesses::CrossLang {
|
||||
}
|
||||
return false;
|
||||
}
|
||||
bool InterperterThread::PushResourceDirectory(GC* gc)
|
||||
{
|
||||
std::vector<CallStackEntry*>& cse=this->call_stack_entries;
|
||||
GCList ls(gc);
|
||||
auto _res2 = cse.back()->Pop(ls);
|
||||
TDictionary* dict;
|
||||
if(GetObjectHeap(_res2, dict))
|
||||
{
|
||||
cse.back()->Push(gc, std::make_shared<EmbedDirectory>(gc,dict));
|
||||
}
|
||||
else {
|
||||
cse.back()->Push(gc, Undefined());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
bool InterperterThread::JumpIfDefined(GC* gc)
|
||||
{
|
||||
|
||||
|
||||
@@ -64,9 +64,9 @@ static opcode opcodes[256]={
|
||||
&InterperterThread::JumpIfContinue,
|
||||
&InterperterThread::JumpIfDefined,
|
||||
&InterperterThread::DeclareConstVariable,
|
||||
&InterperterThread::LineInfo,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::LineInfo,
|
||||
&InterperterThread::PushResourceStream,
|
||||
&InterperterThread::PushResourceDirectory,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
|
||||
Reference in New Issue
Block a user