Fix for tessesframework migration
This commit is contained in:
@ -15,11 +15,7 @@ option(CROSSLANG_ENABLE_SHARED "Enable Tesses CrossLang shared libraries" ON)
|
|||||||
option(CROSSLANG_ENABLE_BINARIES "Enable Tesses CrossLang binaries" ON)
|
option(CROSSLANG_ENABLE_BINARIES "Enable Tesses CrossLang binaries" ON)
|
||||||
option(CROSSLANG_INSTALL_DEVELOPMENT "Enable Tesses CrossLang development files" ON)
|
option(CROSSLANG_INSTALL_DEVELOPMENT "Enable Tesses CrossLang development files" ON)
|
||||||
option(CROSSLANG_ENABLE_THREADING "Enable Tesses CrossLang threading" ON)
|
option(CROSSLANG_ENABLE_THREADING "Enable Tesses CrossLang threading" ON)
|
||||||
option(CROSSLANG_ENABLE_SQLITE "Enable sqlite (Embedded database, supports Wii)" ON)
|
|
||||||
option(CROSSLANG_ENABLE_PROCESS "Enable process" ON)
|
|
||||||
option(CROSSLANG_ENABLE_TERMIOS "Enable termios (For changing terminal options)" ON)
|
option(CROSSLANG_ENABLE_TERMIOS "Enable termios (For changing terminal options)" ON)
|
||||||
option(CROSSLANG_ENABLE_PLATFORM_FOLDERS "Enable platform folders" ON)
|
|
||||||
option(CROSSLANG_ENABLE_TIME "Enable Time" ON)
|
|
||||||
option(CROSSLANG_SHARED_EXECUTABLES "Link with libcrosslang_shared" ON)
|
option(CROSSLANG_SHARED_EXECUTABLES "Link with libcrosslang_shared" ON)
|
||||||
option(CROSSLANG_FETCHCONTENT "Use fetchcontent" ON)
|
option(CROSSLANG_FETCHCONTENT "Use fetchcontent" ON)
|
||||||
option(CROSSLANG_ENABLE_CONFIG_ENVVAR "Allow setting config directory via the environment variable CROSSLANG_CONFIG" ON)
|
option(CROSSLANG_ENABLE_CONFIG_ENVVAR "Allow setting config directory via the environment variable CROSSLANG_CONFIG" ON)
|
||||||
@ -144,6 +140,7 @@ src/runtime_methods/path.cpp
|
|||||||
src/runtime_methods/env.cpp
|
src/runtime_methods/env.cpp
|
||||||
src/runtime_methods/process.cpp
|
src/runtime_methods/process.cpp
|
||||||
src/runtime_methods/sdl2.cpp
|
src/runtime_methods/sdl2.cpp
|
||||||
|
src/types/async.cpp
|
||||||
src/types/associativearray.cpp
|
src/types/associativearray.cpp
|
||||||
src/types/any.cpp
|
src/types/any.cpp
|
||||||
src/types/datetime.cpp
|
src/types/datetime.cpp
|
||||||
@ -168,12 +165,6 @@ src/archive.cpp
|
|||||||
src/markedtobject.cpp
|
src/markedtobject.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
if(CROSSLANG_ENABLE_PLATFORM_FOLDERS)
|
|
||||||
list(APPEND CROSSLANG_SOURCE src/sago/platform_folders.cpp)
|
|
||||||
endif()
|
|
||||||
if(CROSSLANG_ENABLE_SQLITE)
|
|
||||||
list(APPEND CROSSLANG_SOURCE src/sqlite/sqlite3.c src/sqlite/vfs.c)
|
|
||||||
endif()
|
|
||||||
if(CROSSLANG_OFFLINE_SHELL_PACKAGE STREQUAL "")
|
if(CROSSLANG_OFFLINE_SHELL_PACKAGE STREQUAL "")
|
||||||
|
|
||||||
else()
|
else()
|
||||||
|
|||||||
@ -64,7 +64,6 @@ namespace Tesses::CrossLang {
|
|||||||
*/
|
*/
|
||||||
std::string EscapeString(std::string text,bool quote);
|
std::string EscapeString(std::string text,bool quote);
|
||||||
|
|
||||||
Tesses::Framework::Filesystem::VFSPath GetRealExecutablePath(Tesses::Framework::Filesystem::VFSPath realPath);
|
|
||||||
/**
|
/**
|
||||||
* @brief Get the config folder used by crosslang
|
* @brief Get the config folder used by crosslang
|
||||||
*
|
*
|
||||||
@ -841,7 +840,7 @@ class CharInstruction : public ByteCodeInstruction {
|
|||||||
void Write(std::vector<uint8_t>& data);
|
void Write(std::vector<uint8_t>& data);
|
||||||
};
|
};
|
||||||
|
|
||||||
using SyntaxNode = std::variant<int64_t, double, std::string, char, bool, std::nullptr_t, Undefined, AdvancedSyntaxNode>;
|
using SyntaxNode = std::variant<int64_t, double, std::string, char, bool, std::nullptr_t, Undefined,std::vector<uint8_t>, AdvancedSyntaxNode>;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -860,6 +859,35 @@ struct CodeGenClass {
|
|||||||
std::vector<CodeGenClassEntry> entries;
|
std::vector<CodeGenClassEntry> entries;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class ResourceBase {
|
||||||
|
public:
|
||||||
|
virtual uint32_t GetLength(Tesses::Framework::Filesystem::VFS* embedFS)=0;
|
||||||
|
virtual void Write(Tesses::Framework::Streams::Stream* output)=0;
|
||||||
|
virtual ~ResourceBase();
|
||||||
|
virtual bool IsEqual(ResourceBase* base);
|
||||||
|
};
|
||||||
|
|
||||||
|
class ResourceFile : public ResourceBase
|
||||||
|
{
|
||||||
|
Tesses::Framework::Streams::Stream* strm=nullptr;
|
||||||
|
public:
|
||||||
|
ResourceFile();
|
||||||
|
ResourceFile(std::string file);
|
||||||
|
std::string file;
|
||||||
|
uint32_t GetLength(Tesses::Framework::Filesystem::VFS* embedFS);
|
||||||
|
void Write(Tesses::Framework::Streams::Stream* output);
|
||||||
|
bool IsEqual(ResourceBase* base);
|
||||||
|
~ResourceFile();
|
||||||
|
};
|
||||||
|
|
||||||
|
class ResourceByteArray : public ResourceBase
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
std::vector<uint8_t> data;
|
||||||
|
uint32_t GetLength(Tesses::Framework::Filesystem::VFS* embedFS);
|
||||||
|
void Write(Tesses::Framework::Streams::Stream* output);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
class CodeGen {
|
class CodeGen {
|
||||||
uint32_t id;
|
uint32_t id;
|
||||||
@ -871,9 +899,9 @@ class CodeGen {
|
|||||||
SyntaxNode StringifyListOfVars(SyntaxNode n);
|
SyntaxNode StringifyListOfVars(SyntaxNode n);
|
||||||
|
|
||||||
uint32_t GetString(std::string str);
|
uint32_t GetString(std::string str);
|
||||||
uint32_t GetResource(std::string res);
|
uint32_t GetResource(std::shared_ptr<ResourceBase> resource);
|
||||||
std::vector<std::string> strs;
|
std::vector<std::string> strs;
|
||||||
std::vector<std::string> res;
|
std::vector<std::shared_ptr<ResourceBase>> res;
|
||||||
|
|
||||||
std::vector<std::pair<std::vector<uint32_t>, std::vector<ByteCodeInstruction*>>> chunks;
|
std::vector<std::pair<std::vector<uint32_t>, std::vector<ByteCodeInstruction*>>> chunks;
|
||||||
std::vector<std::pair<std::vector<uint32_t>,uint32_t>> funcs;
|
std::vector<std::pair<std::vector<uint32_t>,uint32_t>> funcs;
|
||||||
@ -1242,6 +1270,10 @@ constexpr std::string_view RootPathExpression = "rootPathExpression";
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
constexpr std::string_view RelativePathExpression = "relativePathExpression";
|
constexpr std::string_view RelativePathExpression = "relativePathExpression";
|
||||||
|
/**
|
||||||
|
* @brief await expression for async/await
|
||||||
|
*/
|
||||||
|
constexpr std::string_view AwaitExpression = "awaitExpression";
|
||||||
/**
|
/**
|
||||||
* @brief Advanced AST node
|
* @brief Advanced AST node
|
||||||
*
|
*
|
||||||
@ -1279,6 +1311,8 @@ class AdvancedSyntaxNode {
|
|||||||
SyntaxNode Deserialize(std::string astData);
|
SyntaxNode Deserialize(std::string astData);
|
||||||
|
|
||||||
std::string Serialize(SyntaxNode node);
|
std::string Serialize(SyntaxNode node);
|
||||||
|
class GC;
|
||||||
|
class TRootEnvironment;
|
||||||
/**
|
/**
|
||||||
* @brief Token Parser
|
* @brief Token Parser
|
||||||
*
|
*
|
||||||
@ -1313,13 +1347,17 @@ class Parser {
|
|||||||
SyntaxNode ParseValue();
|
SyntaxNode ParseValue();
|
||||||
SyntaxNode ParseUnary();
|
SyntaxNode ParseUnary();
|
||||||
void ParseHtml(std::vector<SyntaxNode>& nodes,std::string var);
|
void ParseHtml(std::vector<SyntaxNode>& nodes,std::string var);
|
||||||
|
GC* gc;
|
||||||
|
TRootEnvironment* env;
|
||||||
public:
|
public:
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Construct a new Parser object
|
* @brief Construct a new Parser object
|
||||||
*
|
*
|
||||||
* @param tokens the tokens from lexer
|
* @param tokens the tokens from lexer
|
||||||
*/
|
*/
|
||||||
Parser(std::vector<LexToken> tokens);
|
Parser(std::vector<LexToken> tokens);
|
||||||
|
Parser(std::vector<LexToken> tokens, GC* gc, TRootEnvironment* env);
|
||||||
/**
|
/**
|
||||||
* @brief Turn tokens into abstract syntax tree
|
* @brief Turn tokens into abstract syntax tree
|
||||||
*
|
*
|
||||||
@ -1349,6 +1387,7 @@ class Parser {
|
|||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
class THeapObjectHolder
|
class THeapObjectHolder
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@ -1370,6 +1409,7 @@ class Parser {
|
|||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
class TDateTime {
|
class TDateTime {
|
||||||
Tesses::Framework::Date::DateTime* dt;
|
Tesses::Framework::Date::DateTime* dt;
|
||||||
public:
|
public:
|
||||||
@ -1400,8 +1440,11 @@ class GC {
|
|||||||
volatile std::atomic<bool> running;
|
volatile std::atomic<bool> running;
|
||||||
std::vector<THeapObject*> roots;
|
std::vector<THeapObject*> roots;
|
||||||
std::vector<THeapObject*> objects;
|
std::vector<THeapObject*> objects;
|
||||||
|
|
||||||
|
Tesses::Framework::Lazy<Tesses::Framework::Threading::ThreadPool*>* tpool;
|
||||||
std::vector<std::function<void(GC* gc, TRootEnvironment* env)>> register_everything;
|
std::vector<std::function<void(GC* gc, TRootEnvironment* env)>> register_everything;
|
||||||
public:
|
public:
|
||||||
|
Tesses::Framework::Threading::ThreadPool* GetPool();
|
||||||
bool UsingNullThreads();
|
bool UsingNullThreads();
|
||||||
GC();
|
GC();
|
||||||
void Start();
|
void Start();
|
||||||
@ -2172,6 +2215,36 @@ class GC {
|
|||||||
|
|
||||||
TObject Resume(GCList& ls);
|
TObject Resume(GCList& ls);
|
||||||
};
|
};
|
||||||
|
class TTask : public THeapObject
|
||||||
|
{
|
||||||
|
TCallable* cont=nullptr;
|
||||||
|
std::exception_ptr ex=nullptr;
|
||||||
|
GC* gc;
|
||||||
|
TObject obj=Undefined();
|
||||||
|
bool isCompleted=false;
|
||||||
|
TTask(GC* gc);
|
||||||
|
public:
|
||||||
|
static TTask* Create(GCList& ls);
|
||||||
|
bool IsCompleted();
|
||||||
|
|
||||||
|
void ContinueWith(TCallable* callable);
|
||||||
|
TTask* ContinueWith(GCList& ls,TCallable* callable);
|
||||||
|
|
||||||
|
|
||||||
|
void SetFailed(std::exception_ptr ex);
|
||||||
|
void SetSucceeded(TObject v);
|
||||||
|
|
||||||
|
TObject Wait();
|
||||||
|
void Mark();
|
||||||
|
|
||||||
|
static TTask* FromClosure(GCList& ls, TClosure* closure);
|
||||||
|
|
||||||
|
static TTask* FromCallStackEntry(GCList& ls, CallStackEntry* ent);
|
||||||
|
|
||||||
|
static TTask* Run(GCList& ls, TCallable* callable);
|
||||||
|
|
||||||
|
static TTask* FromResult(GCList& ls, TObject v);
|
||||||
|
};
|
||||||
extern thread_local CallStackEntry* current_function;
|
extern thread_local CallStackEntry* current_function;
|
||||||
|
|
||||||
class InterperterThread : public THeapObject
|
class InterperterThread : public THeapObject
|
||||||
|
|||||||
@ -57,7 +57,7 @@ namespace Tesses::CrossLang
|
|||||||
}
|
}
|
||||||
if(!this->icon.empty())
|
if(!this->icon.empty())
|
||||||
{
|
{
|
||||||
this->GetResource(this->icon);
|
this->GetResource(std::make_shared<ResourceFile>(this->icon));
|
||||||
|
|
||||||
}
|
}
|
||||||
for(auto& res : this->res)
|
for(auto& res : this->res)
|
||||||
@ -234,38 +234,15 @@ namespace Tesses::CrossLang
|
|||||||
{
|
{
|
||||||
memcpy(buffer,"RESO",4);
|
memcpy(buffer,"RESO",4);
|
||||||
Write(stream,buffer,4);
|
Write(stream,buffer,4);
|
||||||
|
WriteInt(stream,reso->GetLength(vfs));
|
||||||
if(vfs == nullptr)
|
reso->Write(stream);
|
||||||
{
|
|
||||||
WriteInt(stream,0);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
auto f = vfs->OpenFile(reso,"rb");
|
|
||||||
if(f != NULL)
|
|
||||||
{
|
|
||||||
|
|
||||||
uint32_t len = (uint32_t)f->GetLength();
|
|
||||||
|
|
||||||
WriteInt(stream,len);
|
|
||||||
uint8_t buff[1024];
|
|
||||||
size_t read;
|
|
||||||
do {
|
|
||||||
read = f->Read(buff,1024);
|
|
||||||
Write(stream,buff,read);
|
|
||||||
} while(read > 0);
|
|
||||||
delete f;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
WriteInt(stream,0);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if(!this->icon.empty())
|
if(!this->icon.empty())
|
||||||
{
|
{
|
||||||
memcpy(buffer,"ICON",4);
|
memcpy(buffer,"ICON",4);
|
||||||
Write(stream,buffer,4);
|
Write(stream,buffer,4);
|
||||||
WriteInt(stream,4);
|
WriteInt(stream,4);
|
||||||
WriteInt(stream,this->GetResource(this->icon));
|
WriteInt(stream,this->GetResource(std::make_shared<ResourceFile>(this->icon)));
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -448,14 +425,14 @@ namespace Tesses::CrossLang
|
|||||||
this->strs.push_back(str);
|
this->strs.push_back(str);
|
||||||
return strI;
|
return strI;
|
||||||
}
|
}
|
||||||
uint32_t CodeGen::GetResource(std::string res)
|
uint32_t CodeGen::GetResource(std::shared_ptr<ResourceBase> resource)
|
||||||
{
|
{
|
||||||
for(uint32_t i = 0; i < (uint32_t)this->res.size();i++)
|
for(uint32_t i = 0; i < (uint32_t)this->res.size();i++)
|
||||||
{
|
{
|
||||||
if(this->res[i] == res) return i;
|
if(this->res[i]->IsEqual(resource.get())) return i;
|
||||||
}
|
}
|
||||||
uint32_t resI = (uint32_t)this->res.size();
|
uint32_t resI = (uint32_t)this->res.size();
|
||||||
this->res.push_back(res);
|
this->res.push_back(resource);
|
||||||
return resI;
|
return resI;
|
||||||
}
|
}
|
||||||
#define ONE_EXPR(EXPRESSION, INSTRUCTION) if(adv.nodeName == EXPRESSION && adv.nodes.size() == 1) {GenNode(instructions,adv.nodes[0],scope,contscope,brkscope,contI,brkI);instructions.push_back(new SimpleInstruction(INSTRUCTION));}
|
#define ONE_EXPR(EXPRESSION, INSTRUCTION) if(adv.nodeName == EXPRESSION && adv.nodes.size() == 1) {GenNode(instructions,adv.nodes[0],scope,contscope,brkscope,contI,brkI);instructions.push_back(new SimpleInstruction(INSTRUCTION));}
|
||||||
@ -516,6 +493,12 @@ namespace Tesses::CrossLang
|
|||||||
{
|
{
|
||||||
instructions.push_back(new DoubleInstruction(std::get<double>(n)));
|
instructions.push_back(new DoubleInstruction(std::get<double>(n)));
|
||||||
}
|
}
|
||||||
|
else if(std::holds_alternative<std::vector<uint8_t>>(n))
|
||||||
|
{
|
||||||
|
ResourceByteArray ba;
|
||||||
|
ba.data = std::get<std::vector<uint8_t>>(n);
|
||||||
|
instructions.push_back(new EmbedInstruction(GetResource(std::make_shared<ResourceByteArray>(ba))));
|
||||||
|
}
|
||||||
else if(std::holds_alternative<AdvancedSyntaxNode>(n))
|
else if(std::holds_alternative<AdvancedSyntaxNode>(n))
|
||||||
{
|
{
|
||||||
auto adv = std::get<AdvancedSyntaxNode>(n);
|
auto adv = std::get<AdvancedSyntaxNode>(n);
|
||||||
@ -1337,7 +1320,7 @@ namespace Tesses::CrossLang
|
|||||||
else if(adv.nodeName == EmbedExpression && adv.nodes.size() == 1 && std::holds_alternative<std::string>(adv.nodes[0]))
|
else if(adv.nodeName == EmbedExpression && adv.nodes.size() == 1 && std::holds_alternative<std::string>(adv.nodes[0]))
|
||||||
{
|
{
|
||||||
std::string filename = std::get<std::string>(adv.nodes[0]);
|
std::string filename = std::get<std::string>(adv.nodes[0]);
|
||||||
instructions.push_back(new EmbedInstruction(GetResource(filename)));
|
instructions.push_back(new EmbedInstruction(GetResource(std::make_shared<ResourceFile>(filename))));
|
||||||
|
|
||||||
}
|
}
|
||||||
else if(adv.nodeName == HtmlRootExpression)
|
else if(adv.nodeName == HtmlRootExpression)
|
||||||
@ -1520,20 +1503,6 @@ namespace Tesses::CrossLang
|
|||||||
this->chunks[fnindex] = std::pair<std::vector<uint32_t>,std::vector<ByteCodeInstruction*>>(args, fnInstructions);
|
this->chunks[fnindex] = std::pair<std::vector<uint32_t>,std::vector<ByteCodeInstruction*>>(args, fnInstructions);
|
||||||
instructions.push_back(new ClosureInstruction((uint32_t)fnindex));
|
instructions.push_back(new ClosureInstruction((uint32_t)fnindex));
|
||||||
}
|
}
|
||||||
else if(adv.nodeName == EnumerableStatement && adv.nodes.size() == 2 && std::holds_alternative<AdvancedSyntaxNode>(adv.nodes[0]))
|
|
||||||
{
|
|
||||||
SyntaxNode n = AdvancedSyntaxNode::Create(FunctionStatement,false,{
|
|
||||||
adv.nodes[0],
|
|
||||||
AdvancedSyntaxNode::Create(ReturnStatement,false,{
|
|
||||||
AdvancedSyntaxNode::Create(FunctionCallExpression,true,{
|
|
||||||
AdvancedSyntaxNode::Create(GetVariableExpression,true,{"YieldEmumerable"}),
|
|
||||||
AdvancedSyntaxNode::Create(ClosureExpression,true,{AdvancedSyntaxNode::Create(ParenthesesExpression,true,{}), adv.nodes[1]})
|
|
||||||
})
|
|
||||||
})
|
|
||||||
});
|
|
||||||
GenNode(instructions,n,scope,contscope,brkscope,contI,brkI);
|
|
||||||
|
|
||||||
}
|
|
||||||
else if(adv.nodeName == FunctionStatement && adv.nodes.size() == 2 && std::holds_alternative<AdvancedSyntaxNode>(adv.nodes[0]))
|
else if(adv.nodeName == FunctionStatement && adv.nodes.size() == 2 && std::holds_alternative<AdvancedSyntaxNode>(adv.nodes[0]))
|
||||||
{
|
{
|
||||||
//func NAME(ARGS) {}
|
//func NAME(ARGS) {}
|
||||||
@ -1763,4 +1732,58 @@ namespace Tesses::CrossLang
|
|||||||
instrs.push_back(new SimpleInstruction(POP));
|
instrs.push_back(new SimpleInstruction(POP));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ResourceBase::~ResourceBase()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ResourceBase::IsEqual(ResourceBase* base)
|
||||||
|
{
|
||||||
|
return this == base;
|
||||||
|
}
|
||||||
|
|
||||||
|
ResourceFile::ResourceFile()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
ResourceFile::ResourceFile(std::string f)
|
||||||
|
{
|
||||||
|
this->file = f;
|
||||||
|
}
|
||||||
|
ResourceFile::~ResourceFile()
|
||||||
|
{
|
||||||
|
delete this->strm;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t ResourceFile::GetLength(Tesses::Framework::Filesystem::VFS* embedFS)
|
||||||
|
{
|
||||||
|
if(embedFS == nullptr) return 0;
|
||||||
|
if(strm != nullptr) return strm->GetLength();
|
||||||
|
this->strm = embedFS->OpenFile(this->file,"rb");
|
||||||
|
if(strm != nullptr) return this->strm->GetLength();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
bool ResourceFile::IsEqual(ResourceBase* base)
|
||||||
|
{
|
||||||
|
auto res = dynamic_cast<ResourceFile*>(base);
|
||||||
|
if(res != nullptr) return this->file == res->file;
|
||||||
|
return ResourceBase::IsEqual(base);
|
||||||
|
}
|
||||||
|
void ResourceFile::Write(Tesses::Framework::Streams::Stream* output)
|
||||||
|
{
|
||||||
|
if(this->strm != nullptr)
|
||||||
|
this->strm->CopyTo(output);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t ResourceByteArray::GetLength(Tesses::Framework::Filesystem::VFS* embedFS)
|
||||||
|
{
|
||||||
|
return (uint32_t)this->data.size();
|
||||||
|
}
|
||||||
|
void ResourceByteArray::Write(Tesses::Framework::Streams::Stream* output)
|
||||||
|
{
|
||||||
|
output->WriteBlock(this->data.data(),this->data.size());
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -3,6 +3,65 @@
|
|||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
namespace Tesses::CrossLang
|
namespace Tesses::CrossLang
|
||||||
{
|
{
|
||||||
|
SyntaxNode TObject2SyntaxNode(TObject o)
|
||||||
|
{
|
||||||
|
if(std::holds_alternative<Undefined>(o)) return Undefined();
|
||||||
|
if(std::holds_alternative<std::nullptr_t>(o)) return nullptr;
|
||||||
|
if(std::holds_alternative<std::string>(o)) return std::get<std::string>(o);
|
||||||
|
if(std::holds_alternative<int64_t>(o)) return std::get<int64_t>(o);
|
||||||
|
if(std::holds_alternative<double>(o)) return std::get<double>(o);
|
||||||
|
if(std::holds_alternative<char>(o)) return std::get<char>(o);
|
||||||
|
if(std::holds_alternative<bool>(o)) return std::get<bool>(o);
|
||||||
|
TList* list;
|
||||||
|
TDictionary* dict;
|
||||||
|
TByteArray* byteArray;
|
||||||
|
|
||||||
|
|
||||||
|
if(GetObjectHeap(o,list))
|
||||||
|
{
|
||||||
|
if(list->Count() == 0) return AdvancedSyntaxNode::Create(ArrayExpression, true, {});
|
||||||
|
|
||||||
|
SyntaxNode node = TObject2SyntaxNode(list->Get(0));
|
||||||
|
|
||||||
|
for(int64_t i = 1; i < list->Count(); i++)
|
||||||
|
node = AdvancedSyntaxNode::Create(CommaExpression,true,{node,TObject2SyntaxNode(list->Get(i))});
|
||||||
|
|
||||||
|
return AdvancedSyntaxNode::Create(ArrayExpression, true, {node});
|
||||||
|
}
|
||||||
|
if(GetObjectHeap(o,dict))
|
||||||
|
{
|
||||||
|
bool has=false;
|
||||||
|
SyntaxNode node=nullptr;
|
||||||
|
|
||||||
|
for(auto item : dict->items)
|
||||||
|
{
|
||||||
|
if(has)
|
||||||
|
{
|
||||||
|
node = AdvancedSyntaxNode::Create(CommaExpression,true, {node,AdvancedSyntaxNode::Create(AssignExpression,true,{
|
||||||
|
AdvancedSyntaxNode::Create(GetVariableExpression,true,{TObject2SyntaxNode(item.first)}),
|
||||||
|
TObject2SyntaxNode(item.second)
|
||||||
|
})});
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
node = AdvancedSyntaxNode::Create(AssignExpression,true,{
|
||||||
|
AdvancedSyntaxNode::Create(GetVariableExpression,true,{TObject2SyntaxNode(item.first)}),
|
||||||
|
TObject2SyntaxNode(item.second)
|
||||||
|
});
|
||||||
|
has=true;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(has) return AdvancedSyntaxNode::Create(DictionaryExpression,true,{node});
|
||||||
|
return AdvancedSyntaxNode::Create(DictionaryExpression,true,{});
|
||||||
|
}
|
||||||
|
if(GetObjectHeap(o,byteArray)) {
|
||||||
|
return byteArray->data;
|
||||||
|
}
|
||||||
|
return Undefined();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
std::string LexTokenType_ToString(LexTokenType t)
|
std::string LexTokenType_ToString(LexTokenType t)
|
||||||
{
|
{
|
||||||
switch(t)
|
switch(t)
|
||||||
@ -103,10 +162,16 @@ namespace Tesses::CrossLang
|
|||||||
}
|
}
|
||||||
throw std::out_of_range("End of file");
|
throw std::out_of_range("End of file");
|
||||||
}
|
}
|
||||||
Parser::Parser(std::vector<LexToken> tokens)
|
Parser::Parser(std::vector<LexToken> tokens) : Parser(tokens,nullptr,nullptr)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
Parser::Parser(std::vector<LexToken> tokens, GC* gc, TRootEnvironment* env)
|
||||||
{
|
{
|
||||||
this->i = 0;
|
this->i = 0;
|
||||||
this->tokens = tokens;
|
this->tokens = tokens;
|
||||||
|
this->gc = gc;
|
||||||
|
this->env = env;
|
||||||
}
|
}
|
||||||
void Parser::ParseHtml(std::vector<SyntaxNode>& nodes,std::string var)
|
void Parser::ParseHtml(std::vector<SyntaxNode>& nodes,std::string var)
|
||||||
{
|
{
|
||||||
@ -625,6 +690,42 @@ namespace Tesses::CrossLang
|
|||||||
node = AdvancedSyntaxNode::Create(DeclareExpression,true,{variable.text});
|
node = AdvancedSyntaxNode::Create(DeclareExpression,true,{variable.text});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if(IsIdentifier("comptime"))
|
||||||
|
{
|
||||||
|
SyntaxNode n = nullptr;
|
||||||
|
if(IsSymbol("{",false))
|
||||||
|
{
|
||||||
|
n = ParseNode();
|
||||||
|
if(std::holds_alternative<AdvancedSyntaxNode>(n))
|
||||||
|
{
|
||||||
|
std::get<AdvancedSyntaxNode>(n).nodeName = NodeList;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
n = AdvancedSyntaxNode::Create(ReturnStatement,false,{ParseExpression()});
|
||||||
|
}
|
||||||
|
if(gc != nullptr && env != nullptr)
|
||||||
|
{
|
||||||
|
GCList ls(gc);
|
||||||
|
|
||||||
|
CodeGen gen;
|
||||||
|
gen.GenRoot(n);
|
||||||
|
|
||||||
|
Tesses::Framework::Streams::MemoryStream ms(true);
|
||||||
|
|
||||||
|
gen.Save(nullptr,&ms);
|
||||||
|
|
||||||
|
ms.Seek(0, Tesses::Framework::Streams::SeekOrigin::Begin);
|
||||||
|
|
||||||
|
TFile* f = TFile::Create(ls);
|
||||||
|
f->Load(gc,&ms);
|
||||||
|
|
||||||
|
node = TObject2SyntaxNode(env->LoadFile(gc,f));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
node = Undefined();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
else if(IsIdentifier("operator"))
|
else if(IsIdentifier("operator"))
|
||||||
{
|
{
|
||||||
if(i >= tokens.size()) throw std::out_of_range("End of file");
|
if(i >= tokens.size()) throw std::out_of_range("End of file");
|
||||||
@ -823,6 +924,69 @@ namespace Tesses::CrossLang
|
|||||||
{
|
{
|
||||||
return AdvancedSyntaxNode::Create(PrefixDecrementExpression,true,{ParseUnary()});
|
return AdvancedSyntaxNode::Create(PrefixDecrementExpression,true,{ParseUnary()});
|
||||||
}
|
}
|
||||||
|
else if(IsIdentifier("await"))
|
||||||
|
{
|
||||||
|
return AdvancedSyntaxNode::Create(YieldStatement,true,{ParseValue()});
|
||||||
|
}
|
||||||
|
else if(IsIdentifier("async"))
|
||||||
|
{
|
||||||
|
auto tkn = this->tkn;
|
||||||
|
auto v = ParseValue();
|
||||||
|
if(std::holds_alternative<AdvancedSyntaxNode>(v))
|
||||||
|
{
|
||||||
|
auto asn = std::get<AdvancedSyntaxNode>(v);
|
||||||
|
if(asn.nodeName != ClosureExpression)
|
||||||
|
throw SyntaxException(tkn.lineInfo,"async must be used only with a closure");
|
||||||
|
if(asn.nodes.size() != 2)
|
||||||
|
throw SyntaxException(tkn.lineInfo,"invalid closure");
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
return AdvancedSyntaxNode::Create(ClosureExpression,true,{
|
||||||
|
asn.nodes[0],
|
||||||
|
AdvancedSyntaxNode::Create(ReturnStatement,false,{
|
||||||
|
AdvancedSyntaxNode::Create(FunctionCallExpression,true,{
|
||||||
|
AdvancedSyntaxNode::Create(GetFieldExpression,true,{AdvancedSyntaxNode::Create(GetVariableExpression,true,{"Task"}),"AsyncClosure"}),
|
||||||
|
AdvancedSyntaxNode::Create(ClosureExpression,true,{AdvancedSyntaxNode::Create(ParenthesesExpression,true,{}), asn.nodes[1]})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
throw SyntaxException(tkn.lineInfo,"async must be used only with a closure, not a simple value");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(IsIdentifier("enumerable"))
|
||||||
|
{
|
||||||
|
|
||||||
|
auto tkn = this->tkn;
|
||||||
|
auto v = ParseValue();
|
||||||
|
if(std::holds_alternative<AdvancedSyntaxNode>(v))
|
||||||
|
{
|
||||||
|
auto asn = std::get<AdvancedSyntaxNode>(v);
|
||||||
|
if(asn.nodeName != ClosureExpression)
|
||||||
|
throw SyntaxException(tkn.lineInfo,"enumerable must be used only with a closure");
|
||||||
|
if(asn.nodes.size() != 2)
|
||||||
|
throw SyntaxException(tkn.lineInfo,"invalid closure");
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
return AdvancedSyntaxNode::Create(ClosureExpression,true,{
|
||||||
|
asn.nodes[0],
|
||||||
|
AdvancedSyntaxNode::Create(ReturnStatement,false,{
|
||||||
|
AdvancedSyntaxNode::Create(FunctionCallExpression,true,{
|
||||||
|
AdvancedSyntaxNode::Create(GetVariableExpression,true,{"YieldEmumerable"}),
|
||||||
|
AdvancedSyntaxNode::Create(ClosureExpression,true,{AdvancedSyntaxNode::Create(ParenthesesExpression,true,{}), asn.nodes[1]})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
throw SyntaxException(tkn.lineInfo,"enumerable must be used only with a closure, not a simple value");
|
||||||
|
}
|
||||||
|
}
|
||||||
else if(IsSymbol("/"))
|
else if(IsSymbol("/"))
|
||||||
{
|
{
|
||||||
if(this->i < this->tokens.size() && (this->tokens[this->i].type == LexTokenType::String || this->tokens[this->i].type == LexTokenType::Identifier))
|
if(this->i < this->tokens.size() && (this->tokens[this->i].type == LexTokenType::String || this->tokens[this->i].type == LexTokenType::Identifier))
|
||||||
@ -1124,6 +1288,67 @@ namespace Tesses::CrossLang
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
if(IsIdentifier("async"))
|
||||||
|
{
|
||||||
|
auto nameAndArgs = ParseExpression();
|
||||||
|
|
||||||
|
if(IsSymbol("{",false))
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
name_and_methods.push_back(AdvancedSyntaxNode::Create(MethodStatement,false,{documentation,myTkn.text,nameAndArgs,
|
||||||
|
AdvancedSyntaxNode::Create(ReturnStatement,false,{
|
||||||
|
AdvancedSyntaxNode::Create(FunctionCallExpression,true,{
|
||||||
|
AdvancedSyntaxNode::Create(GetFieldExpression,true,{AdvancedSyntaxNode::Create(GetVariableExpression,true,{"Task"}),"AsyncClosure"}),
|
||||||
|
AdvancedSyntaxNode::Create(ClosureExpression,true,{AdvancedSyntaxNode::Create(ParenthesesExpression,true,{}), ParseNode()})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}));
|
||||||
|
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
auto v = ParseExpression();
|
||||||
|
EnsureSymbol(";");
|
||||||
|
|
||||||
|
name_and_methods.push_back(AdvancedSyntaxNode::Create(MethodStatement,false,{documentation,myTkn.text,nameAndArgs,
|
||||||
|
AdvancedSyntaxNode::Create(ReturnStatement,false,{
|
||||||
|
AdvancedSyntaxNode::Create(FunctionCallExpression,true,{
|
||||||
|
AdvancedSyntaxNode::Create(GetFieldExpression,true,{AdvancedSyntaxNode::Create(GetVariableExpression,true,{"Task"}),"AsyncClosure"}),
|
||||||
|
AdvancedSyntaxNode::Create(ClosureExpression,true,{AdvancedSyntaxNode::Create(ParenthesesExpression,true,{}), AdvancedSyntaxNode::Create(ReturnStatement,false,{v})})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}));
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(IsIdentifier("enumerable"))
|
||||||
|
{
|
||||||
|
auto nameAndArgs = ParseExpression();
|
||||||
|
|
||||||
|
if(IsSymbol("{",false))
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
name_and_methods.push_back(AdvancedSyntaxNode::Create(MethodStatement,false,{documentation,myTkn.text,nameAndArgs,
|
||||||
|
AdvancedSyntaxNode::Create(ReturnStatement,false,{
|
||||||
|
AdvancedSyntaxNode::Create(FunctionCallExpression,true,{
|
||||||
|
AdvancedSyntaxNode::Create(GetVariableExpression,true,{"YieldEmumerable"}),
|
||||||
|
AdvancedSyntaxNode::Create(ClosureExpression,true,{AdvancedSyntaxNode::Create(ParenthesesExpression,true,{}), ParseNode()})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}));
|
||||||
|
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw SyntaxException(tokens[i].lineInfo, "expected the symbol \"{\" on enumerable but got the symbol or other token \"" + tokens[i].text + "\"");
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
auto nameAndArgs = ParseExpression();
|
auto nameAndArgs = ParseExpression();
|
||||||
|
|
||||||
if(IsSymbol("{",false))
|
if(IsSymbol("{",false))
|
||||||
@ -1140,6 +1365,7 @@ namespace Tesses::CrossLang
|
|||||||
name_and_methods.push_back(AdvancedSyntaxNode::Create(MethodStatement,false,{documentation,myTkn.text,nameAndArgs,AdvancedSyntaxNode::Create(ReturnStatement,false,{v})}));
|
name_and_methods.push_back(AdvancedSyntaxNode::Create(MethodStatement,false,{documentation,myTkn.text,nameAndArgs,AdvancedSyntaxNode::Create(ReturnStatement,false,{v})}));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1150,21 +1376,66 @@ namespace Tesses::CrossLang
|
|||||||
}
|
}
|
||||||
else throw std::out_of_range("End of file");
|
else throw std::out_of_range("End of file");
|
||||||
}
|
}
|
||||||
if(IsIdentifier("enumerable"))
|
|
||||||
|
if(IsIdentifier("enumerable",false) && i+1<tokens.size() && tokens[i+1].text == "func" && i+1<tokens.size() && tokens[i+1].type == LexTokenType::Identifier)
|
||||||
{
|
{
|
||||||
|
i+=2;
|
||||||
auto nameAndArgs = ParseExpression();
|
auto nameAndArgs = ParseExpression();
|
||||||
|
|
||||||
if(IsSymbol("{",false))
|
if(IsSymbol("{",false))
|
||||||
{
|
{
|
||||||
return AdvancedSyntaxNode::Create(EnumerableStatement,false,{nameAndArgs,ParseNode()});
|
return AdvancedSyntaxNode::Create(FunctionStatement,false,{
|
||||||
|
nameAndArgs,
|
||||||
|
AdvancedSyntaxNode::Create(ReturnStatement,false,{
|
||||||
|
AdvancedSyntaxNode::Create(FunctionCallExpression,true,{
|
||||||
|
AdvancedSyntaxNode::Create(GetVariableExpression,true,{"YieldEmumerable"}),
|
||||||
|
AdvancedSyntaxNode::Create(ClosureExpression,true,{AdvancedSyntaxNode::Create(ParenthesesExpression,true,{}), ParseNode()})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
});
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
throw SyntaxException(tokens[i].lineInfo, "expected the symbol \"{\" on enumerable but got the symbol or other token \"" + tokens[i].text + "\"");
|
throw SyntaxException(tokens[i].lineInfo, "expected the symbol \"{\" on enumerable but got the symbol or other token \"" + tokens[i].text + "\"");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if(IsIdentifier("async",false) && i+1<tokens.size() && tokens[i+1].text == "func" && tokens[i+1].type == LexTokenType::Identifier)
|
||||||
|
{
|
||||||
|
i+=2;
|
||||||
|
//async func
|
||||||
|
auto nameAndArgs = ParseExpression();
|
||||||
|
|
||||||
|
if(IsSymbol("{",false))
|
||||||
|
{
|
||||||
|
return AdvancedSyntaxNode::Create(FunctionStatement,false,{
|
||||||
|
nameAndArgs,
|
||||||
|
AdvancedSyntaxNode::Create(ReturnStatement,false,{
|
||||||
|
AdvancedSyntaxNode::Create(FunctionCallExpression,true,{
|
||||||
|
AdvancedSyntaxNode::Create(GetFieldExpression,true,{AdvancedSyntaxNode::Create(GetVariableExpression,true,{"Task"}),"AsyncClosure"}),
|
||||||
|
AdvancedSyntaxNode::Create(ClosureExpression,true,{AdvancedSyntaxNode::Create(ParenthesesExpression,true,{}), ParseNode()})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
auto v = ParseExpression();
|
||||||
|
|
||||||
|
EnsureSymbol(";");
|
||||||
|
return AdvancedSyntaxNode::Create(FunctionStatement,false,{
|
||||||
|
nameAndArgs,
|
||||||
|
AdvancedSyntaxNode::Create(ReturnStatement,false,{
|
||||||
|
AdvancedSyntaxNode::Create(FunctionCallExpression,true,{
|
||||||
|
AdvancedSyntaxNode::Create(GetFieldExpression,true,{AdvancedSyntaxNode::Create(GetVariableExpression,true,{"Task"}),"AsyncClosure"}),
|
||||||
|
AdvancedSyntaxNode::Create(ClosureExpression,true,{AdvancedSyntaxNode::Create(ParenthesesExpression,true,{}), AdvancedSyntaxNode::Create(ReturnStatement,false,{v})})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
if(IsIdentifier("func"))
|
if(IsIdentifier("func"))
|
||||||
{
|
{
|
||||||
|
|
||||||
auto nameAndArgs = ParseExpression();
|
auto nameAndArgs = ParseExpression();
|
||||||
|
|
||||||
if(IsSymbol("{",false))
|
if(IsSymbol("{",false))
|
||||||
|
|||||||
@ -58,7 +58,7 @@ int main(int argc, char** argv)
|
|||||||
|
|
||||||
Tesses::Framework::Filesystem::LocalFilesystem fs;
|
Tesses::Framework::Filesystem::LocalFilesystem fs;
|
||||||
|
|
||||||
auto p = GetRealExecutablePath(fs.SystemToVFSPath(argv[0])).GetParent().GetParent() / "share" / "Tesses" / "CrossLang" / "Tesses.CrossLang.ShellPackage-1.0.0.0-prod.crvm";
|
auto p = Tesses::Framework::Platform::Environment::GetRealExecutablePath(fs.SystemToVFSPath(argv[0])).GetParent().GetParent() / "share" / "Tesses" / "CrossLang" / "Tesses.CrossLang.ShellPackage-1.0.0.0-prod.crvm";
|
||||||
|
|
||||||
if(argc > 1 && strcmp(argv[1],"update-shell") == 0)
|
if(argc > 1 && strcmp(argv[1],"update-shell") == 0)
|
||||||
{
|
{
|
||||||
|
|||||||
@ -17,6 +17,7 @@ void Help(const char* filename)
|
|||||||
printf(" -n: Set name (MyAppOrLibName defaults to out)\n");
|
printf(" -n: Set name (MyAppOrLibName defaults to out)\n");
|
||||||
printf(" -r: Set resource directory (RESDIR defaults to res)\n");
|
printf(" -r: Set resource directory (RESDIR defaults to res)\n");
|
||||||
printf(" -h, --help: Prints help\n");
|
printf(" -h, --help: Prints help\n");
|
||||||
|
printf(" -e: Set comptime permissions defaults to none, none for no support, \"secure\" for sane without file access, \"secure_file\" for sane with file access to current directory and sub directories, \"full\" has full runtime.\n");
|
||||||
printf("Options except for help have flag with arg like this: -F ARG\n");
|
printf("Options except for help have flag with arg like this: -F ARG\n");
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
@ -43,9 +44,12 @@ int main(int argc, char** argv)
|
|||||||
std::string name="out";
|
std::string name="out";
|
||||||
std::string info="{}";
|
std::string info="{}";
|
||||||
std::string icon="";
|
std::string icon="";
|
||||||
|
std::string comptime="none";
|
||||||
TVMVersion version;
|
TVMVersion version;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
for(int i = 1; i < argc; i++)
|
for(int i = 1; i < argc; i++)
|
||||||
{
|
{
|
||||||
if(strcmp(argv[i],"--help") == 0 || strcmp(argv[i],"-h")==0)
|
if(strcmp(argv[i],"--help") == 0 || strcmp(argv[i],"-h")==0)
|
||||||
@ -68,6 +72,15 @@ int main(int argc, char** argv)
|
|||||||
resourceDir = argv[i];
|
resourceDir = argv[i];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if(strcmp(argv[i], "-e") == 0)
|
||||||
|
{
|
||||||
|
i++;
|
||||||
|
if(i < argc)
|
||||||
|
{
|
||||||
|
comptime = argv[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
else if(strcmp(argv[i], "-i") == 0)
|
else if(strcmp(argv[i], "-i") == 0)
|
||||||
{
|
{
|
||||||
i++;
|
i++;
|
||||||
@ -193,7 +206,48 @@ int main(int argc, char** argv)
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Parser parser(tokens);
|
GC* gc=nullptr;
|
||||||
|
GCList* ls=nullptr;
|
||||||
|
TRootEnvironment* env=nullptr;
|
||||||
|
if(comptime != "none")
|
||||||
|
{
|
||||||
|
gc = new GC();
|
||||||
|
gc->Start();
|
||||||
|
ls = new GCList(gc);
|
||||||
|
env = TRootEnvironment::Create(ls,TDictionary::Create(ls));
|
||||||
|
|
||||||
|
if(comptime == "secure")
|
||||||
|
{
|
||||||
|
TStd::RegisterConsole(gc,env);
|
||||||
|
TStd::RegisterClass(gc,env);
|
||||||
|
TStd::RegisterCrypto(gc,env);
|
||||||
|
TStd::RegisterDictionary(gc,env);
|
||||||
|
TStd::RegisterJson(gc,env);
|
||||||
|
TStd::RegisterRoot(gc,env);
|
||||||
|
TStd::RegisterIO(gc,env,false);
|
||||||
|
env->permissions.locked=true;
|
||||||
|
}
|
||||||
|
else if(comptime == "secure_file")
|
||||||
|
{
|
||||||
|
TStd::RegisterConsole(gc,env);
|
||||||
|
TStd::RegisterClass(gc,env);
|
||||||
|
TStd::RegisterCrypto(gc,env);
|
||||||
|
TStd::RegisterDictionary(gc,env);
|
||||||
|
TStd::RegisterJson(gc,env);
|
||||||
|
TStd::RegisterRoot(gc,env);
|
||||||
|
TStd::RegisterIO(gc,env,false);
|
||||||
|
env->permissions.locked=true;
|
||||||
|
auto fs = env->EnsureDictionary(gc,"FS");
|
||||||
|
fs->SetValue("Local",TVFSHeapObject::Create(ls, new SubdirFilesystem(new Tesses::Framework::Filesystem::LocalFilesystem(),Tesses::Framework::Filesystem::VFSPath::GetAbsoluteCurrentDirectory(),true)));
|
||||||
|
}
|
||||||
|
else if(comptime == "full")
|
||||||
|
{
|
||||||
|
TStd::RegisterStd(gc,env);
|
||||||
|
env->permissions.locked=true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Parser parser(tokens,gc,env);
|
||||||
|
|
||||||
CodeGen gen;
|
CodeGen gen;
|
||||||
gen.GenRoot(parser.ParseRoot());
|
gen.GenRoot(parser.ParseRoot());
|
||||||
@ -220,5 +274,10 @@ int main(int argc, char** argv)
|
|||||||
|
|
||||||
gen.Save(&sfs,&strm);
|
gen.Save(&sfs,&strm);
|
||||||
}
|
}
|
||||||
|
if(gc != nullptr)
|
||||||
|
{
|
||||||
|
delete ls;
|
||||||
|
delete gc;
|
||||||
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -8,7 +8,7 @@ using namespace Tesses::CrossLang;
|
|||||||
using namespace Tesses::Framework::Filesystem;
|
using namespace Tesses::Framework::Filesystem;
|
||||||
int main(int argc, char** argv)
|
int main(int argc, char** argv)
|
||||||
{
|
{
|
||||||
TF_Init();
|
TF_InitWithConsole();
|
||||||
GC gc;
|
GC gc;
|
||||||
gc.Start();
|
gc.Start();
|
||||||
GCList ls(gc);
|
GCList ls(gc);
|
||||||
|
|||||||
@ -9,7 +9,7 @@
|
|||||||
int main(int argc,char** argv)
|
int main(int argc,char** argv)
|
||||||
{
|
{
|
||||||
std::string p = argv[0];
|
std::string p = argv[0];
|
||||||
auto emptyThumb =Tesses::CrossLang::GetRealExecutablePath(p).GetParent().GetParent() / "share" / "icons" / "crosslang.png";
|
auto emptyThumb =Tesses::Framework::Platform::Environment::GetRealExecutablePath(p).GetParent().GetParent() / "share" / "icons" / "crosslang.png";
|
||||||
|
|
||||||
if(argc < 3)
|
if(argc < 3)
|
||||||
{
|
{
|
||||||
|
|||||||
@ -1,80 +1,25 @@
|
|||||||
#include "CrossLang.hpp"
|
#include "CrossLang.hpp"
|
||||||
#if defined(CROSSLANG_ENABLE_PLATFORM_FOLDERS)
|
|
||||||
#include "../sago/platform_folders.h"
|
|
||||||
#endif
|
|
||||||
#if defined(_WIN32)
|
#if defined(_WIN32)
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
namespace Tesses::CrossLang
|
namespace Tesses::CrossLang
|
||||||
{
|
{
|
||||||
|
using namespace Tesses::Framework::Platform::Environment;
|
||||||
#if defined(_WIN32)
|
#if defined(_WIN32)
|
||||||
static char EnvPathSeperator=';';
|
static char EnvPathSeperator=';';
|
||||||
#else
|
#else
|
||||||
static char EnvPathSeperator=':';
|
static char EnvPathSeperator=':';
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static std::string GetHomeFolder()
|
|
||||||
{
|
|
||||||
#if defined(CROSSLANG_ENABLE_PLATFORM_FOLDERS)
|
|
||||||
return sago::getHomeDir();
|
|
||||||
#elif defined(__EMSCRIPTEN__)
|
|
||||||
return "/home/web_user";
|
|
||||||
#else
|
|
||||||
return "/CrossLangProfile";
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
Tesses::Framework::Filesystem::VFSPath GetCrossLangConfigDir()
|
Tesses::Framework::Filesystem::VFSPath GetCrossLangConfigDir()
|
||||||
{
|
{
|
||||||
#if defined(CROSSLANG_ENABLE_CONFIG_ENVVAR)
|
|
||||||
char* conf = std::getenv("CROSSLANG_CONFIG");
|
return SpecialFolders::GetConfig() / "Tesses" / "CrossLang";
|
||||||
if(conf != NULL)
|
|
||||||
{
|
|
||||||
return std::string(conf);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
Tesses::Framework::Filesystem::VFSPath p;
|
|
||||||
#if defined(CROSSLANG_ENABLE_PLATFORM_FOLDERS)
|
|
||||||
p=sago::getConfigHome();
|
|
||||||
#else
|
|
||||||
p = GetHomeFolder() + "/Config";
|
|
||||||
#endif
|
|
||||||
return p / "Tesses" / "CrossLang";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Tesses::Framework::Filesystem::VFSPath GetRealExecutablePath(Tesses::Framework::Filesystem::VFSPath realPath)
|
|
||||||
{
|
|
||||||
using namespace Tesses::Framework::Filesystem;
|
|
||||||
using namespace Tesses::Framework::Http;
|
|
||||||
LocalFilesystem lfs;
|
|
||||||
if(!realPath.relative) return realPath.MakeAbsolute();
|
|
||||||
if(lfs.FileExists(realPath)) return realPath.MakeAbsolute();
|
|
||||||
const char* path = std::getenv("PATH");
|
|
||||||
#if defined(_WIN32)
|
|
||||||
const char* pathext = std::getenv("PATHEXT");
|
|
||||||
auto pext = HttpUtils::SplitString(pathext,";");
|
|
||||||
pext.push_back({});
|
|
||||||
auto pathParts = HttpUtils::SplitString(path,";");
|
|
||||||
for(auto item : pathParts)
|
|
||||||
{
|
|
||||||
for(auto item2 : pext)
|
|
||||||
{
|
|
||||||
auto newPath = (lfs.SystemToVFSPath(item) / realPath) + item2;
|
|
||||||
if(lfs.FileExists(newPath)) return newPath;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return realPath;
|
|
||||||
#else
|
|
||||||
|
|
||||||
auto pathParts = HttpUtils::SplitString(path,":");
|
|
||||||
for(auto item : pathParts)
|
|
||||||
{
|
|
||||||
auto newPath = lfs.SystemToVFSPath(item) / realPath;
|
|
||||||
if(lfs.FileExists(newPath)) return newPath;
|
|
||||||
}
|
|
||||||
return realPath.MakeAbsolute();
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static TObject Env_getCrossLangConfig(GCList& ls, std::vector<TObject> args)
|
static TObject Env_getCrossLangConfig(GCList& ls, std::vector<TObject> args)
|
||||||
@ -83,56 +28,16 @@ namespace Tesses::CrossLang
|
|||||||
}
|
}
|
||||||
static TObject Env_getPlatform(GCList& ls, std::vector<TObject> args)
|
static TObject Env_getPlatform(GCList& ls, std::vector<TObject> args)
|
||||||
{
|
{
|
||||||
#if defined(__SWITCH__)
|
return Tesses::Framework::Platform::Environment::GetPlatform();
|
||||||
return "Nintendo Switch";
|
|
||||||
#endif
|
|
||||||
#if defined(GEKKO)
|
|
||||||
#if defined(HW_RVL)
|
|
||||||
return "Nintendo Wii";
|
|
||||||
#endif
|
|
||||||
return "Nintendo Gamecube";
|
|
||||||
#endif
|
|
||||||
#if defined(WIN32) || defined(_WIN32)
|
|
||||||
return "Windows";
|
|
||||||
#endif
|
|
||||||
#if defined(linux)
|
|
||||||
return "Linux";
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef __APPLE__
|
|
||||||
#include "TargetConditionals.h"
|
|
||||||
#if TARGET_OS_MAC
|
|
||||||
return "MacOS";
|
|
||||||
#endif
|
|
||||||
#if TARGET_OS_IOS
|
|
||||||
return "iOS";
|
|
||||||
#endif
|
|
||||||
#if TARGET_OS_TV
|
|
||||||
return "Apple TV";
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if TARGET_OS_WATCH
|
|
||||||
return "Apple Watch";
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if __EMSCRIPTEN__
|
|
||||||
return "WebAssembly";
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return "Unknown Apple Device";
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return "Unknown";
|
|
||||||
}
|
}
|
||||||
static TObject Env_GetAt(GCList& ls, std::vector<TObject> args)
|
static TObject Env_GetAt(GCList& ls, std::vector<TObject> args)
|
||||||
{
|
{
|
||||||
std::string key;
|
std::string key;
|
||||||
if(GetArgument(args,0,key))
|
if(GetArgument(args,0,key))
|
||||||
{
|
{
|
||||||
auto res = std::getenv(key.c_str());
|
auto v = GetVariable(key);
|
||||||
if(res == nullptr) return nullptr;
|
if(v) return v.value();
|
||||||
std::string value = res;
|
|
||||||
return value;
|
|
||||||
}
|
}
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
@ -143,108 +48,62 @@ namespace Tesses::CrossLang
|
|||||||
if(GetArgument(args,0,key))
|
if(GetArgument(args,0,key))
|
||||||
{
|
{
|
||||||
if(GetArgument(args,1,value))
|
if(GetArgument(args,1,value))
|
||||||
#if defined(_WIN32)
|
|
||||||
SetEnvironmentVariable(key.c_str(),value.c_str());
|
|
||||||
#else
|
|
||||||
setenv(key.c_str(), value.c_str(),1);
|
|
||||||
#endif
|
|
||||||
else
|
|
||||||
#if defined(_WIN32)
|
|
||||||
{
|
{
|
||||||
|
SetVariable(key,value);
|
||||||
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
unsetenv(key.c_str());
|
|
||||||
#endif
|
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
SetVariable(key,std::nullopt);
|
||||||
|
}
|
||||||
|
}
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
static TObject Env_getDownloads(GCList& ls, std::vector<TObject> args)
|
static TObject Env_getDownloads(GCList& ls, std::vector<TObject> args)
|
||||||
{
|
{
|
||||||
#if defined(CROSSLANG_ENABLE_PLATFORM_FOLDERS)
|
return SpecialFolders::GetDownloads();
|
||||||
return sago::getDownloadFolder();
|
|
||||||
#else
|
|
||||||
return GetHomeFolder() + "/Downloads";
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
static TObject Env_getMusic(GCList& ls, std::vector<TObject> args)
|
static TObject Env_getMusic(GCList& ls, std::vector<TObject> args)
|
||||||
{
|
{
|
||||||
|
return SpecialFolders::GetMusic();
|
||||||
#if defined(CROSSLANG_ENABLE_PLATFORM_FOLDERS)
|
|
||||||
return sago::getMusicFolder();
|
|
||||||
#else
|
|
||||||
return GetHomeFolder() + "/Music";
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
static TObject Env_getPictures(GCList& ls, std::vector<TObject> args)
|
static TObject Env_getPictures(GCList& ls, std::vector<TObject> args)
|
||||||
{
|
{
|
||||||
#if defined(CROSSLANG_ENABLE_PLATFORM_FOLDERS)
|
return SpecialFolders::GetPictures();
|
||||||
return sago::getPicturesFolder();
|
|
||||||
#else
|
|
||||||
return GetHomeFolder() + "/Pictures";
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
static TObject Env_getVideos(GCList& ls, std::vector<TObject> args)
|
static TObject Env_getVideos(GCList& ls, std::vector<TObject> args)
|
||||||
{
|
{
|
||||||
#if defined(CROSSLANG_ENABLE_PLATFORM_FOLDERS)
|
return SpecialFolders::GetVideos();
|
||||||
return sago::getVideoFolder();
|
|
||||||
#else
|
|
||||||
return GetHomeFolder() + "/Videos";
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
static TObject Env_getDocuments(GCList& ls, std::vector<TObject> args)
|
static TObject Env_getDocuments(GCList& ls, std::vector<TObject> args)
|
||||||
{
|
{
|
||||||
#if defined(CROSSLANG_ENABLE_PLATFORM_FOLDERS)
|
return SpecialFolders::GetDocuments();
|
||||||
return sago::getDocumentsFolder();
|
|
||||||
#else
|
|
||||||
return GetHomeFolder() + "/Documents";
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
static TObject Env_getConfig(GCList& ls, std::vector<TObject> args)
|
static TObject Env_getConfig(GCList& ls, std::vector<TObject> args)
|
||||||
{
|
{
|
||||||
#if defined(CROSSLANG_ENABLE_PLATFORM_FOLDERS)
|
return SpecialFolders::GetConfig();
|
||||||
return sago::getConfigHome();
|
|
||||||
#else
|
|
||||||
return GetHomeFolder() + "/Config";
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static TObject Env_getDesktop(GCList& ls, std::vector<TObject> args)
|
static TObject Env_getDesktop(GCList& ls, std::vector<TObject> args)
|
||||||
{
|
{
|
||||||
#if defined(CROSSLANG_ENABLE_PLATFORM_FOLDERS)
|
return SpecialFolders::GetDesktop();
|
||||||
return sago::getDesktopFolder();
|
|
||||||
#else
|
|
||||||
return GetHomeFolder() + "/Desktop";
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
static TObject Env_getState(GCList& ls, std::vector<TObject> args)
|
static TObject Env_getState(GCList& ls, std::vector<TObject> args)
|
||||||
{
|
{
|
||||||
#if defined(CROSSLANG_ENABLE_PLATFORM_FOLDERS)
|
return SpecialFolders::GetState();
|
||||||
return sago::getStateDir();
|
|
||||||
#else
|
|
||||||
return GetHomeFolder() + "/State";
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
static TObject Env_getCache(GCList& ls, std::vector<TObject> args)
|
static TObject Env_getCache(GCList& ls, std::vector<TObject> args)
|
||||||
{
|
{
|
||||||
#if defined(CROSSLANG_ENABLE_PLATFORM_FOLDERS)
|
return SpecialFolders::GetCache();
|
||||||
return sago::getCacheDir();
|
|
||||||
#else
|
|
||||||
return GetHomeFolder() + "/Cache";
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
static TObject Env_getData(GCList& ls, std::vector<TObject> args)
|
static TObject Env_getData(GCList& ls, std::vector<TObject> args)
|
||||||
{
|
{
|
||||||
#if defined(CROSSLANG_ENABLE_PLATFORM_FOLDERS)
|
return SpecialFolders::GetData();
|
||||||
return sago::getDataHome();
|
|
||||||
#else
|
|
||||||
return GetHomeFolder() + "/Data";
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
static TObject Env_getUser(GCList& ls, std::vector<TObject> args)
|
static TObject Env_getUser(GCList& ls, std::vector<TObject> args)
|
||||||
{
|
{
|
||||||
return GetHomeFolder();
|
return SpecialFolders::GetHomeFolder();
|
||||||
}
|
}
|
||||||
static TObject Env_GetRealExecutablePath(GCList& ls, std::vector<TObject> args)
|
static TObject Env_GetRealExecutablePath(GCList& ls, std::vector<TObject> args)
|
||||||
{
|
{
|
||||||
|
|||||||
@ -230,10 +230,17 @@ namespace Tesses::CrossLang
|
|||||||
dict->DeclareFunction(gc,"getNeedToParseFormData","Check if Need to parse form data",{},[ctx](Tesses::CrossLang::GCList &ls2, std::vector<Tesses::CrossLang::TObject> args2)->TObject{
|
dict->DeclareFunction(gc,"getNeedToParseFormData","Check if Need to parse form data",{},[ctx](Tesses::CrossLang::GCList &ls2, std::vector<Tesses::CrossLang::TObject> args2)->TObject{
|
||||||
return ctx->NeedToParseFormData();
|
return ctx->NeedToParseFormData();
|
||||||
});
|
});
|
||||||
|
|
||||||
dict->DeclareFunction(gc,"ReadString","Read string from request",{},[ctx](Tesses::CrossLang::GCList &ls2, std::vector<Tesses::CrossLang::TObject> args2)->TObject{
|
dict->DeclareFunction(gc,"ReadString","Read string from request",{},[ctx](Tesses::CrossLang::GCList &ls2, std::vector<Tesses::CrossLang::TObject> args2)->TObject{
|
||||||
return ctx->ReadString();
|
return ctx->ReadString();
|
||||||
});
|
});
|
||||||
|
dict->DeclareFunction(gc,"ReadStream","Read request to stream",{},[ctx](Tesses::CrossLang::GCList& ls2, std::vector<TObject> args)->TObject {
|
||||||
|
Tesses::CrossLang::TStreamHeapObject* strm;
|
||||||
|
if(GetArgumentHeap(args,0,strm))
|
||||||
|
{
|
||||||
|
ctx->ReadStream(strm->stream);
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
});
|
||||||
dict->DeclareFunction(gc, "ReadJson","Read json from request",{},[ctx](Tesses::CrossLang::GCList &ls2, std::vector<Tesses::CrossLang::TObject> args2)->TObject{
|
dict->DeclareFunction(gc, "ReadJson","Read json from request",{},[ctx](Tesses::CrossLang::GCList &ls2, std::vector<Tesses::CrossLang::TObject> args2)->TObject{
|
||||||
return Json_Decode(ls2,ctx->ReadString());
|
return Json_Decode(ls2,ctx->ReadString());
|
||||||
});
|
});
|
||||||
@ -615,6 +622,7 @@ namespace Tesses::CrossLang
|
|||||||
_obj = dict->GetValue("Key");
|
_obj = dict->GetValue("Key");
|
||||||
GetObject(_obj,key);
|
GetObject(_obj,key);
|
||||||
_obj = dict->GetValue("Value");
|
_obj = dict->GetValue("Value");
|
||||||
|
GetObject(_obj,value);
|
||||||
|
|
||||||
req.requestHeaders.AddValue(key,value);
|
req.requestHeaders.AddValue(key,value);
|
||||||
}
|
}
|
||||||
@ -863,7 +871,7 @@ namespace Tesses::CrossLang
|
|||||||
_obj = dict->GetValue("Key");
|
_obj = dict->GetValue("Key");
|
||||||
GetObject(_obj,key);
|
GetObject(_obj,key);
|
||||||
_obj = dict->GetValue("Value");
|
_obj = dict->GetValue("Value");
|
||||||
|
GetObject(_obj,value);
|
||||||
hdict.AddValue(key,value);
|
hdict.AddValue(key,value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -17,7 +17,8 @@ namespace Tesses::CrossLang
|
|||||||
//Process.Start({
|
//Process.Start({
|
||||||
// FileName = "git",
|
// FileName = "git",
|
||||||
// Arguments = ["clone","https://gitea.site.tesses.net/tesses50/crosslang.git"],
|
// Arguments = ["clone","https://gitea.site.tesses.net/tesses50/crosslang.git"],
|
||||||
// Environment = []
|
// Environment = [],
|
||||||
|
// InheritParentEnvironment=true
|
||||||
//})
|
//})
|
||||||
|
|
||||||
TDictionary* dict;
|
TDictionary* dict;
|
||||||
|
|||||||
@ -12,6 +12,9 @@
|
|||||||
#include <TessesFramework/SDL2/Views/LabelView.hpp>
|
#include <TessesFramework/SDL2/Views/LabelView.hpp>
|
||||||
#include <TessesFramework/SDL2/Views/ProgressView.hpp>
|
#include <TessesFramework/SDL2/Views/ProgressView.hpp>
|
||||||
#include <TessesFramework/SDL2/Views/TextListView.hpp>
|
#include <TessesFramework/SDL2/Views/TextListView.hpp>
|
||||||
|
#include <TessesFramework/SDL2/Views/ScrollableTextListView.hpp>
|
||||||
|
#include <TessesFramework/SDL2/Views/DropDownView.hpp>
|
||||||
|
#include <TessesFramework/SDL2/Views/EditTextView.hpp>
|
||||||
using namespace Tesses::Framework::SDL2;
|
using namespace Tesses::Framework::SDL2;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -756,6 +759,7 @@ namespace Tesses::CrossLang
|
|||||||
{
|
{
|
||||||
this->view = view;
|
this->view = view;
|
||||||
}
|
}
|
||||||
|
static TObject FindViewById(GCList& ls,View* v, std::string id);
|
||||||
TObject FindViewById(GCList& ls,std::string id);
|
TObject FindViewById(GCList& ls,std::string id);
|
||||||
|
|
||||||
|
|
||||||
@ -816,19 +820,52 @@ namespace Tesses::CrossLang
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class GUI_EditTextView : public GUI_View {
|
||||||
|
public:
|
||||||
|
GUI_EditTextView(Views::EditTextView* view) : GUI_View(view)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
GUI_EditTextView(std::string hint) : GUI_View(new Views::EditTextView(hint))
|
||||||
|
{
|
||||||
|
|
||||||
class GUI_Window : public GUI_ContainerView {
|
}
|
||||||
|
std::string TypeName()
|
||||||
|
{
|
||||||
|
return "GUI.EditTextView";
|
||||||
|
}
|
||||||
|
virtual TObject CallMethod(GCList& ls, std::string key, std::vector<TObject> args)
|
||||||
|
{
|
||||||
|
auto edit = dynamic_cast<Views::EditTextView*>(this->view);
|
||||||
|
if(edit == nullptr) return GUI_View::CallMethod(ls,key,args);
|
||||||
|
if(key == "getHint")
|
||||||
|
{
|
||||||
|
return edit->GetHint();
|
||||||
|
}
|
||||||
|
if(key == "setHint")
|
||||||
|
{
|
||||||
|
std::string str;
|
||||||
|
if(GetArgument(args,0,str))
|
||||||
|
{
|
||||||
|
edit->SetHint(str);
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return GUI_View::CallMethod(ls,key,args);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class GUI_Window : public TNativeObject {
|
||||||
Tesses::Framework::SDL2::GUIPalette Default()
|
Tesses::Framework::SDL2::GUIPalette Default()
|
||||||
{
|
{
|
||||||
return Tesses::Framework::SDL2::GUIPalette(true,{.r=192,.g=255,.b=0,.a=255});
|
return Tesses::Framework::SDL2::GUIPalette(true,{.r=192,.g=255,.b=0,.a=255});
|
||||||
}
|
}
|
||||||
public:
|
public:
|
||||||
|
GUIWindow* window;
|
||||||
//"title","width","height","flags","$pallete"
|
//"title","width","height","flags","$pallete"
|
||||||
GUI_Window(std::string title, int width, int height, Uint32 flags, Tesses::Framework::SDL2::GUIPalette* palette)
|
GUI_Window(std::string title, int width, int height, Uint32 flags, Tesses::Framework::SDL2::GUIPalette* palette)
|
||||||
{
|
{
|
||||||
this->view = new Tesses::Framework::SDL2::GUIWindow(title,width,height,flags,palette != nullptr ? *palette : Default());
|
this->window = new Tesses::Framework::SDL2::GUIWindow(title,width,height,flags,palette != nullptr ? *palette : Default());
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string TypeName()
|
std::string TypeName()
|
||||||
@ -838,19 +875,46 @@ namespace Tesses::CrossLang
|
|||||||
|
|
||||||
TObject CallMethod(GCList& ls, std::string key, std::vector<TObject> args)
|
TObject CallMethod(GCList& ls, std::string key, std::vector<TObject> args)
|
||||||
{
|
{
|
||||||
auto win = dynamic_cast<GUIWindow*>(this->view);
|
|
||||||
if(win != nullptr)
|
if(window)
|
||||||
{
|
{
|
||||||
if(key == "setView")
|
if(key == "setView")
|
||||||
{
|
{
|
||||||
GUI_View* v;
|
GUI_View* v;
|
||||||
if(GetArgumentHeap(args,0,v))
|
if(GetArgumentHeap(args,0,v))
|
||||||
{
|
{
|
||||||
win->SetView(v->view,true);
|
window->SetView(v->view,true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(key == "FindViewById")
|
||||||
|
{
|
||||||
|
std::string id;
|
||||||
|
if(GetArgument(args,0,id))
|
||||||
|
{
|
||||||
|
if(id == window->GetId()) return this;
|
||||||
|
else {
|
||||||
|
auto v=window->GetViewAt(0);
|
||||||
|
if(v != nullptr)
|
||||||
|
return GUI_View::FindViewById(ls,v,id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
if(key == "getText")
|
||||||
|
{
|
||||||
|
return this->window->GetText();
|
||||||
|
}
|
||||||
|
if(key == "setText")
|
||||||
|
{
|
||||||
|
std::string str;
|
||||||
|
if(GetArgument(args,0,str))
|
||||||
|
{
|
||||||
|
this->window->SetText(str);
|
||||||
|
return str;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return GUI_ContainerView::CallMethod(ls,key,args);
|
return Undefined();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -1012,12 +1076,21 @@ namespace Tesses::CrossLang
|
|||||||
};
|
};
|
||||||
TObject GUI_View::FindViewById(GCList& ls,std::string id)
|
TObject GUI_View::FindViewById(GCList& ls,std::string id)
|
||||||
{
|
{
|
||||||
auto view = this->view->FindViewById(id);
|
return FindViewById(ls,view,id);
|
||||||
|
}
|
||||||
|
TObject GUI_View::FindViewById(GCList& ls,View* curView,std::string id)
|
||||||
|
{
|
||||||
|
auto view = curView->FindViewById(id);
|
||||||
auto buttonView = dynamic_cast<Views::ButtonView*>(view);
|
auto buttonView = dynamic_cast<Views::ButtonView*>(view);
|
||||||
|
auto editTextView = dynamic_cast<Views::EditTextView*>(view);
|
||||||
if(buttonView != nullptr)
|
if(buttonView != nullptr)
|
||||||
{
|
{
|
||||||
return TNativeObject::Create<GUI_ButtonView>(ls,buttonView);
|
return TNativeObject::Create<GUI_ButtonView>(ls,buttonView);
|
||||||
}
|
}
|
||||||
|
if(editTextView != nullptr)
|
||||||
|
{
|
||||||
|
return TNativeObject::Create<GUI_EditTextView>(ls,editTextView);
|
||||||
|
}
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
static TObject SDL2_getEvents(GCList& ls, std::vector<TObject> args)
|
static TObject SDL2_getEvents(GCList& ls, std::vector<TObject> args)
|
||||||
@ -1039,7 +1112,7 @@ namespace Tesses::CrossLang
|
|||||||
std::string jsonText = ToString(ls.GetGC(),args[0]);
|
std::string jsonText = ToString(ls.GetGC(),args[0]);
|
||||||
GUI_Window* window = TNativeObject::Create<GUI_Window>(ls,std::string("Unnamed Window"),320,240,flags,nullptr);
|
GUI_Window* window = TNativeObject::Create<GUI_Window>(ls,std::string("Unnamed Window"),320,240,flags,nullptr);
|
||||||
|
|
||||||
dynamic_cast<GUIWindow*>(window->view)->SetView(Tesses::Framework::Serialization::Json::Json::Decode(jsonText));
|
window->window->SetView(Tesses::Framework::Serialization::Json::Json::Decode(jsonText));
|
||||||
return window;
|
return window;
|
||||||
}
|
}
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|||||||
@ -1,32 +1,84 @@
|
|||||||
#include "CrossLang.hpp"
|
#include "CrossLang.hpp"
|
||||||
#if defined(CROSSLANG_ENABLE_SQLITE)
|
#include <TessesFramework/TessesFrameworkFeatures.h>
|
||||||
#include "../sqlite/sqlite3.h"
|
|
||||||
#endif
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
namespace Tesses::CrossLang {
|
namespace Tesses::CrossLang {
|
||||||
#if defined(CROSSLANG_ENABLE_SQLITE)
|
#if defined(TESSESFRAMEWORK_ENABLE_SQLITE)
|
||||||
static int sqlcollector(void* user, int count,char** vals, char** keys)
|
using namespace Tesses::Framework::Serialization;
|
||||||
|
class SQLiteObject : public TNativeObject
|
||||||
{
|
{
|
||||||
|
public:
|
||||||
std::pair<GCList*,TList*>* ls2 = static_cast<std::pair<GCList*,TList*>*>(user);
|
SQLiteDatabase* db;
|
||||||
TDictionary* dict = TDictionary::Create(ls2->first);
|
SQLiteObject(Tesses::Framework::Filesystem::VFSPath path)
|
||||||
for(int i = 0; i < count; i++)
|
|
||||||
{
|
{
|
||||||
std::string key = keys[i] == nullptr ? "" : keys[i];
|
db=new SQLiteDatabase(path);
|
||||||
|
|
||||||
if(vals[i] == nullptr)
|
|
||||||
{
|
|
||||||
dict->SetValue(key,nullptr);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string TypeName()
|
||||||
|
{
|
||||||
|
return "SQLiteDatabase";
|
||||||
|
}
|
||||||
|
void Close()
|
||||||
|
{
|
||||||
|
if(this->db == nullptr) return;
|
||||||
|
delete this->db;
|
||||||
|
this->db = nullptr;
|
||||||
|
|
||||||
|
}
|
||||||
|
bool ToBool()
|
||||||
|
{
|
||||||
|
return this->db != nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
TObject CallMethod(GCList& ls,std::string name, std::vector<TObject> args)
|
||||||
|
{
|
||||||
|
if(name == "Close") this->Close();
|
||||||
|
if(name == "Escape") {
|
||||||
|
std::string str;
|
||||||
|
if(GetArgument(args,0,str))
|
||||||
|
{
|
||||||
|
return SQLiteDatabase::Escape(str); //here for completeness
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(name == "Exec")
|
||||||
|
{
|
||||||
|
std::string arg;
|
||||||
|
if(GetArgument(args,0,arg))
|
||||||
|
{
|
||||||
|
if(this->db == nullptr) return nullptr;
|
||||||
|
std::vector<std::vector<std::pair<std::string, std::optional<std::string>>>> res;
|
||||||
|
this->db->Exec(arg,res);
|
||||||
|
|
||||||
|
TList* list = TList::Create(ls);
|
||||||
|
|
||||||
|
for(auto& item : res)
|
||||||
|
{
|
||||||
|
TDictionary* dict = TDictionary::Create(ls);
|
||||||
|
for(auto& item2 : item)
|
||||||
|
{
|
||||||
|
if(item2.second)
|
||||||
|
dict->SetValue(item2.first,item2.second.value());
|
||||||
else
|
else
|
||||||
{
|
dict->SetValue(item2.first,nullptr);
|
||||||
dict->SetValue(key,vals[i]);
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
ls2->second->Add(dict);
|
|
||||||
|
|
||||||
return 0;
|
list->Add(dict);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Undefined();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
~SQLiteObject()
|
||||||
|
{
|
||||||
|
if(this->db != nullptr)
|
||||||
|
delete this->db;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
TObject Sqlite_Open(GCList& ls, std::vector<TObject> args,TRootEnvironment* env)
|
TObject Sqlite_Open(GCList& ls, std::vector<TObject> args,TRootEnvironment* env)
|
||||||
{
|
{
|
||||||
Tesses::Framework::Filesystem::VFSPath p;
|
Tesses::Framework::Filesystem::VFSPath p;
|
||||||
@ -36,20 +88,8 @@ namespace Tesses::CrossLang {
|
|||||||
{
|
{
|
||||||
p = env->permissions.sqliteOffsetPath / p.CollapseRelativeParents();
|
p = env->permissions.sqliteOffsetPath / p.CollapseRelativeParents();
|
||||||
}
|
}
|
||||||
std::string name = p.ToString();
|
|
||||||
|
|
||||||
sqlite3* sqlite;
|
return TNativeObject::Create<SQLiteObject>(ls,p);
|
||||||
int rc =sqlite3_open(name.c_str(),&sqlite);
|
|
||||||
if(rc)
|
|
||||||
{
|
|
||||||
std::string error = sqlite3_errmsg(sqlite);
|
|
||||||
sqlite3_close(sqlite);
|
|
||||||
return error;
|
|
||||||
}
|
|
||||||
return TNative::Create(ls,sqlite,[](void* a)->void {
|
|
||||||
if(a != nullptr)
|
|
||||||
sqlite3_close((sqlite3*)a);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return Undefined();
|
return Undefined();
|
||||||
@ -57,26 +97,11 @@ namespace Tesses::CrossLang {
|
|||||||
}
|
}
|
||||||
TObject Sqlite_Exec(GCList& ls, std::vector<TObject> args)
|
TObject Sqlite_Exec(GCList& ls, std::vector<TObject> args)
|
||||||
{
|
{
|
||||||
if(args.size() == 2 && std::holds_alternative<THeapObjectHolder>(args[0]) && std::holds_alternative<std::string>(args[1]))
|
SQLiteObject* sql;
|
||||||
|
std::string cmd;
|
||||||
|
if(GetArgumentHeap(args,0,sql) && GetArgument(args,1,cmd))
|
||||||
{
|
{
|
||||||
TNative* native = dynamic_cast<TNative*>(std::get<THeapObjectHolder>(args[0]).obj);
|
return sql->CallMethod(ls,"Exec",{cmd});
|
||||||
std::string sqlStatement = std::get<std::string>(args[1]);
|
|
||||||
if(native != nullptr && !native->GetDestroyed())
|
|
||||||
{
|
|
||||||
sqlite3* sql = (sqlite3*)native->GetPointer();
|
|
||||||
TList* myLs = TList::Create(ls);
|
|
||||||
std::pair<GCList*,TList*> result(&ls, myLs);
|
|
||||||
char* err;
|
|
||||||
int res = sqlite3_exec(sql,sqlStatement.c_str(),sqlcollector,&result,&err);
|
|
||||||
if(res != SQLITE_OK)
|
|
||||||
{
|
|
||||||
std::string errstr = err == nullptr ? "" : err;
|
|
||||||
sqlite3_free(err);
|
|
||||||
return errstr;
|
|
||||||
}
|
|
||||||
|
|
||||||
return myLs;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return Undefined();
|
return Undefined();
|
||||||
@ -85,32 +110,21 @@ namespace Tesses::CrossLang {
|
|||||||
|
|
||||||
TObject Sqlite_Escape(GCList& ls, std::vector<TObject> args)
|
TObject Sqlite_Escape(GCList& ls, std::vector<TObject> args)
|
||||||
{
|
{
|
||||||
if(args.size() == 1 && std::holds_alternative<std::string>(args[0]))
|
std::string str;
|
||||||
|
if(GetArgument(args,0,str))
|
||||||
{
|
{
|
||||||
std::string srcStr = std::get<std::string>(args[0]);
|
return SQLiteDatabase::Escape(str);
|
||||||
std::string myStr = "\'";
|
|
||||||
for(auto c : srcStr)
|
|
||||||
{
|
|
||||||
if(c == '\'') myStr += "\'\'";
|
|
||||||
else
|
|
||||||
myStr += c;
|
|
||||||
}
|
|
||||||
myStr += '\'';
|
|
||||||
return myStr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return Undefined();
|
return Undefined();
|
||||||
}
|
}
|
||||||
|
|
||||||
TObject Sqlite_Close(GCList& ls, std::vector<TObject> args)
|
TObject Sqlite_Close(GCList& ls, std::vector<TObject> args)
|
||||||
{
|
{
|
||||||
if(args.size() == 1 && std::holds_alternative<THeapObjectHolder>(args[0]))
|
SQLiteObject* sql;
|
||||||
|
if(GetArgumentHeap(args,0,sql))
|
||||||
{
|
{
|
||||||
TNative* native = dynamic_cast<TNative*>(std::get<THeapObjectHolder>(args[0]).obj);
|
sql->Close();
|
||||||
|
|
||||||
if(native != nullptr && !native->GetDestroyed())
|
|
||||||
{
|
|
||||||
native->Destroy();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return Undefined();
|
return Undefined();
|
||||||
}
|
}
|
||||||
@ -120,7 +134,7 @@ namespace Tesses::CrossLang {
|
|||||||
{
|
{
|
||||||
|
|
||||||
env->permissions.canRegisterSqlite=true;
|
env->permissions.canRegisterSqlite=true;
|
||||||
#if defined(CROSSLANG_ENABLE_SQLITE)
|
#if defined(TESSESFRAMEWORK_ENABLE_SQLITE)
|
||||||
GCList ls(gc);
|
GCList ls(gc);
|
||||||
TDictionary* dict = TDictionary::Create(ls);
|
TDictionary* dict = TDictionary::Create(ls);
|
||||||
dict->DeclareFunction(gc,"Open","Opens the database (returns database handle or an error message as string or undefined)",{"filename"},[env](GCList& ls, std::vector<TObject> args)->TObject {
|
dict->DeclareFunction(gc,"Open","Opens the database (returns database handle or an error message as string or undefined)",{"filename"},[env](GCList& ls, std::vector<TObject> args)->TObject {
|
||||||
|
|||||||
@ -859,9 +859,11 @@ namespace Tesses::CrossLang
|
|||||||
{
|
{
|
||||||
GCList ls(gc);
|
GCList ls(gc);
|
||||||
|
|
||||||
|
gc->BarrierBegin();
|
||||||
|
|
||||||
env->permissions.canRegisterRoot=true;
|
env->permissions.canRegisterRoot=true;
|
||||||
|
|
||||||
TDictionary* date = TDictionary::Create(ls);
|
auto date =env->EnsureDictionary(gc,"DateTime");
|
||||||
date->DeclareFunction(gc, "Sleep","Sleep for a specified amount of milliseconds (multiply seconds by 1000 to get milliseconds)", {"ms"},DateTime_Sleep);
|
date->DeclareFunction(gc, "Sleep","Sleep for a specified amount of milliseconds (multiply seconds by 1000 to get milliseconds)", {"ms"},DateTime_Sleep);
|
||||||
date->DeclareFunction(gc, "getNow", "Get the current time",{},DateTime_getNow);
|
date->DeclareFunction(gc, "getNow", "Get the current time",{},DateTime_getNow);
|
||||||
date->DeclareFunction(gc, "getNowUTC","Get the current time in UTC",{},DateTime_getNowUTC);
|
date->DeclareFunction(gc, "getNowUTC","Get the current time in UTC",{},DateTime_getNowUTC);
|
||||||
@ -869,14 +871,27 @@ namespace Tesses::CrossLang
|
|||||||
date->DeclareFunction(gc, "TryParseHttpDate","Parse the http date",{},DateTime_TryParseHttpDate);
|
date->DeclareFunction(gc, "TryParseHttpDate","Parse the http date",{},DateTime_TryParseHttpDate);
|
||||||
|
|
||||||
|
|
||||||
gc->BarrierBegin();
|
|
||||||
|
|
||||||
date->SetValue("Zone", (int64_t)Tesses::Framework::Date::GetTimeZone());
|
date->SetValue("Zone", (int64_t)Tesses::Framework::Date::GetTimeZone());
|
||||||
date->SetValue("SupportsDaylightSavings",Tesses::Framework::Date::TimeZoneSupportDST());
|
date->SetValue("SupportsDaylightSavings",Tesses::Framework::Date::TimeZoneSupportDST());
|
||||||
|
|
||||||
env->DeclareVariable("DateTime", date);
|
auto task = env->EnsureDictionary(gc,"Task");
|
||||||
|
|
||||||
|
task->DeclareFunction(gc,"AsyncClosure","Create async closure (internal for compiler to generate calls to)",{"closure"},[](GCList& ls, std::vector<TObject> args)->TObject {
|
||||||
|
TClosure* closure;
|
||||||
|
if(GetArgumentHeap(args,0,closure))
|
||||||
|
return TTask::FromClosure(ls,closure);
|
||||||
|
return nullptr;
|
||||||
|
});
|
||||||
|
|
||||||
|
task->DeclareFunction(gc,"Run","Run code async",{"callable"},[](GCList& ls, std::vector<TObject> args)->TObject {
|
||||||
|
TCallable* closure;
|
||||||
|
if(GetArgumentHeap(args,0,closure))
|
||||||
|
return TTask::Run(ls,closure);
|
||||||
|
return nullptr;
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
gc->BarrierEnd();
|
|
||||||
TDictionary* newTypes = env->EnsureDictionary(gc, "New");
|
TDictionary* newTypes = env->EnsureDictionary(gc, "New");
|
||||||
|
|
||||||
newTypes->DeclareFunction(gc, "DateTime","Create a DateTime object, if only one arg is provided year is epoch, isLocal defaults to true unless epoch",{"year","$month","$day","$hour","$minute","$second","$isLocal"},New_DateTime);
|
newTypes->DeclareFunction(gc, "DateTime","Create a DateTime object, if only one arg is provided year is epoch, isLocal defaults to true unless epoch",{"year","$month","$day","$hour","$minute","$second","$isLocal"},New_DateTime);
|
||||||
@ -1018,7 +1033,7 @@ namespace Tesses::CrossLang
|
|||||||
return TAssociativeArray::Create(ls);
|
return TAssociativeArray::Create(ls);
|
||||||
});
|
});
|
||||||
newTypes->DeclareFunction(gc,"ByteArray","Create bytearray, with optional either size (to size it) or string argument (to fill byte array)",{"$data"},ByteArray);
|
newTypes->DeclareFunction(gc,"ByteArray","Create bytearray, with optional either size (to size it) or string argument (to fill byte array)",{"$data"},ByteArray);
|
||||||
gc->BarrierBegin();
|
|
||||||
env->DeclareVariable("Version", TDictionary::Create(ls,{
|
env->DeclareVariable("Version", TDictionary::Create(ls,{
|
||||||
TDItem("Parse",TExternalMethod::Create(ls,"Parse version from string",{"versionStr"},[](GCList& ls, std::vector<TObject> args)->TObject{
|
TDItem("Parse",TExternalMethod::Create(ls,"Parse version from string",{"versionStr"},[](GCList& ls, std::vector<TObject> args)->TObject{
|
||||||
std::string str;
|
std::string str;
|
||||||
@ -1057,6 +1072,8 @@ namespace Tesses::CrossLang
|
|||||||
}));
|
}));
|
||||||
env->DeclareVariable("InvokeMethod",MethodInvoker());
|
env->DeclareVariable("InvokeMethod",MethodInvoker());
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
gc->BarrierEnd();
|
gc->BarrierEnd();
|
||||||
}
|
}
|
||||||
void TStd::RegisterStd(GC* gc, TRootEnvironment* env)
|
void TStd::RegisterStd(GC* gc, TRootEnvironment* env)
|
||||||
|
|||||||
@ -242,15 +242,18 @@ namespace Tesses::CrossLang
|
|||||||
TObject _tools = dict->GetValue("Tools");
|
TObject _tools = dict->GetValue("Tools");
|
||||||
TObject _info = dict->GetValue("Info");
|
TObject _info = dict->GetValue("Info");
|
||||||
TObject _icon = dict->GetValue("Icon");
|
TObject _icon = dict->GetValue("Icon");
|
||||||
|
TObject _comptime = dict->GetValue("CompTime");
|
||||||
TObject _resourceFileSystem = dict->GetValue("ResourceFileSystem");
|
TObject _resourceFileSystem = dict->GetValue("ResourceFileSystem");
|
||||||
|
|
||||||
TObject _out = dict->GetValue("Output");
|
TObject _out = dict->GetValue("Output");
|
||||||
TList* _toolList;
|
TList* _toolList;
|
||||||
TList* _depList; TList* srcLst;
|
TList* _depList; TList* srcLst;
|
||||||
|
TRootEnvironment* comptimeEnv=nullptr;
|
||||||
GetObject<std::string>(_name,name);
|
GetObject<std::string>(_name,name);
|
||||||
GetObject<std::string>(_info,info);
|
GetObject<std::string>(_info,info);
|
||||||
GetObject<std::string>(_icon,icon);
|
GetObject<std::string>(_icon,icon);
|
||||||
GetObjectHeap(_resourceFileSystem, vfsHO);
|
GetObjectHeap(_resourceFileSystem, vfsHO);
|
||||||
|
GetObjectHeap(_comptime,comptimeEnv);
|
||||||
std::string v2;
|
std::string v2;
|
||||||
if(GetObject<std::string>(_version,v2))
|
if(GetObject<std::string>(_version,v2))
|
||||||
TVMVersion::TryParse(v2, version);
|
TVMVersion::TryParse(v2, version);
|
||||||
@ -348,7 +351,7 @@ namespace Tesses::CrossLang
|
|||||||
return Failure(ls, "Lex error in file \"" + source.second + "\":" + std::to_string(res));
|
return Failure(ls, "Lex error in file \"" + source.second + "\":" + std::to_string(res));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Parser parser(tokens);
|
Parser parser(tokens,ls.GetGC(),comptimeEnv);
|
||||||
SyntaxNode n = parser.ParseRoot();
|
SyntaxNode n = parser.ParseRoot();
|
||||||
CodeGen gen;
|
CodeGen gen;
|
||||||
gen.GenRoot(n);
|
gen.GenRoot(n);
|
||||||
|
|||||||
@ -1,472 +0,0 @@
|
|||||||
/*
|
|
||||||
Its is under the MIT license, to encourage reuse by cut-and-paste.
|
|
||||||
|
|
||||||
The original files are hosted here: https://github.com/sago007/PlatformFolders
|
|
||||||
|
|
||||||
Copyright (c) 2015-2016 Poul Sander
|
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person
|
|
||||||
obtaining a copy of this software and associated documentation files
|
|
||||||
(the "Software"), to deal in the Software without restriction,
|
|
||||||
including without limitation the rights to use, copy, modify, merge,
|
|
||||||
publish, distribute, sublicense, and/or sell copies of the Software,
|
|
||||||
and to permit persons to whom the Software is furnished to do so,
|
|
||||||
subject to the following conditions:
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be
|
|
||||||
included in all copies or substantial portions of the Software.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
||||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
||||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
||||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
|
||||||
BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
|
||||||
ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
|
||||||
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
SOFTWARE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
Modified by Mike Nolan for this project
|
|
||||||
I modified it to return home directory and conditionally compile for systems that are not GEKKO / NX etc
|
|
||||||
*/
|
|
||||||
|
|
||||||
#if !defined(SAGO_DISABLE)
|
|
||||||
#include "platform_folders.h"
|
|
||||||
#include <iostream>
|
|
||||||
#include <stdexcept>
|
|
||||||
#include <cstdio>
|
|
||||||
#include <cstdlib>
|
|
||||||
|
|
||||||
#ifndef _WIN32
|
|
||||||
|
|
||||||
#include <pwd.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Retrives the effective user's home dir.
|
|
||||||
* If the user is running as root we ignore the HOME environment. It works badly with sudo.
|
|
||||||
* Writing to $HOME as root implies security concerns that a multiplatform program cannot be assumed to handle.
|
|
||||||
* @return The home directory. HOME environment is respected for non-root users if it exists.
|
|
||||||
*/
|
|
||||||
static std::string getHome() {
|
|
||||||
std::string res;
|
|
||||||
int uid = getuid();
|
|
||||||
const char* homeEnv = std::getenv("HOME");
|
|
||||||
if ( uid != 0 && homeEnv) {
|
|
||||||
//We only acknowlegde HOME if not root.
|
|
||||||
res = homeEnv;
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
struct passwd* pw = nullptr;
|
|
||||||
struct passwd pwd;
|
|
||||||
long bufsize = sysconf(_SC_GETPW_R_SIZE_MAX);
|
|
||||||
if (bufsize < 0) {
|
|
||||||
bufsize = 16384;
|
|
||||||
}
|
|
||||||
std::vector<char> buffer;
|
|
||||||
buffer.resize(bufsize);
|
|
||||||
int error_code = getpwuid_r(uid, &pwd, buffer.data(), buffer.size(), &pw);
|
|
||||||
if (error_code) {
|
|
||||||
throw std::runtime_error("Unable to get passwd struct.");
|
|
||||||
}
|
|
||||||
const char* tempRes = pw->pw_dir;
|
|
||||||
if (!tempRes) {
|
|
||||||
throw std::runtime_error("User has no home directory");
|
|
||||||
}
|
|
||||||
res = tempRes;
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef _WIN32
|
|
||||||
// Make sure we don't bring in all the extra junk with windows.h
|
|
||||||
#ifndef WIN32_LEAN_AND_MEAN
|
|
||||||
#define WIN32_LEAN_AND_MEAN
|
|
||||||
#endif
|
|
||||||
// stringapiset.h depends on this
|
|
||||||
#include <windows.h>
|
|
||||||
// For SUCCEEDED macro
|
|
||||||
#include <winerror.h>
|
|
||||||
// For WideCharToMultiByte
|
|
||||||
#include <stringapiset.h>
|
|
||||||
// For SHGetFolderPathW and various CSIDL "magic numbers"
|
|
||||||
#include <shlobj.h>
|
|
||||||
|
|
||||||
namespace sago {
|
|
||||||
namespace internal {
|
|
||||||
|
|
||||||
std::string win32_utf16_to_utf8(const wchar_t* wstr) {
|
|
||||||
std::string res;
|
|
||||||
// If the 6th parameter is 0 then WideCharToMultiByte returns the number of bytes needed to store the result.
|
|
||||||
int actualSize = WideCharToMultiByte(CP_UTF8, 0, wstr, -1, nullptr, 0, nullptr, nullptr);
|
|
||||||
if (actualSize > 0) {
|
|
||||||
//If the converted UTF-8 string could not be in the initial buffer. Allocate one that can hold it.
|
|
||||||
std::vector<char> buffer(actualSize);
|
|
||||||
actualSize = WideCharToMultiByte(CP_UTF8, 0, wstr, -1, &buffer[0], static_cast<int>(buffer.size()), nullptr, nullptr);
|
|
||||||
res = buffer.data();
|
|
||||||
}
|
|
||||||
if (actualSize == 0) {
|
|
||||||
// WideCharToMultiByte return 0 for errors.
|
|
||||||
throw std::runtime_error("UTF16 to UTF8 failed with error code: " + std::to_string(GetLastError()));
|
|
||||||
}
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namesapce internal
|
|
||||||
} // namespace sago
|
|
||||||
|
|
||||||
class FreeCoTaskMemory {
|
|
||||||
LPWSTR pointer = NULL;
|
|
||||||
public:
|
|
||||||
explicit FreeCoTaskMemory(LPWSTR pointer) : pointer(pointer) {};
|
|
||||||
~FreeCoTaskMemory() {
|
|
||||||
CoTaskMemFree(pointer);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
static std::string GetKnownWindowsFolder(REFKNOWNFOLDERID folderId, const char* errorMsg) {
|
|
||||||
LPWSTR wszPath = NULL;
|
|
||||||
HRESULT hr;
|
|
||||||
hr = SHGetKnownFolderPath(folderId, KF_FLAG_CREATE, NULL, &wszPath);
|
|
||||||
FreeCoTaskMemory scopeBoundMemory(wszPath);
|
|
||||||
|
|
||||||
if (!SUCCEEDED(hr)) {
|
|
||||||
throw std::runtime_error(errorMsg);
|
|
||||||
}
|
|
||||||
return sago::internal::win32_utf16_to_utf8(wszPath);
|
|
||||||
}
|
|
||||||
|
|
||||||
static std::string GetAppData() {
|
|
||||||
return GetKnownWindowsFolder(FOLDERID_RoamingAppData, "RoamingAppData could not be found");
|
|
||||||
}
|
|
||||||
|
|
||||||
static std::string GetAppDataCommon() {
|
|
||||||
return GetKnownWindowsFolder(FOLDERID_ProgramData, "ProgramData could not be found");
|
|
||||||
}
|
|
||||||
|
|
||||||
static std::string GetAppDataLocal() {
|
|
||||||
return GetKnownWindowsFolder(FOLDERID_LocalAppData, "LocalAppData could not be found");
|
|
||||||
}
|
|
||||||
#elif defined(__APPLE__)
|
|
||||||
#else
|
|
||||||
#include <map>
|
|
||||||
#include <fstream>
|
|
||||||
#include <sys/types.h>
|
|
||||||
// For strlen and strtok
|
|
||||||
#include <cstring>
|
|
||||||
#include <sstream>
|
|
||||||
//Typically Linux. For easy reading the comments will just say Linux but should work with most *nixes
|
|
||||||
|
|
||||||
static void throwOnRelative(const char* envName, const char* envValue) {
|
|
||||||
if (envValue[0] != '/') {
|
|
||||||
char buffer[200];
|
|
||||||
std::snprintf(buffer, sizeof(buffer), "Environment \"%s\" does not start with an '/'. XDG specifies that the value must be absolute. The current value is: \"%s\"", envName, envValue);
|
|
||||||
throw std::runtime_error(buffer);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static std::string getLinuxFolderDefault(const char* envName, const char* defaultRelativePath) {
|
|
||||||
std::string res;
|
|
||||||
const char* tempRes = std::getenv(envName);
|
|
||||||
if (tempRes) {
|
|
||||||
throwOnRelative(envName, tempRes);
|
|
||||||
res = tempRes;
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
res = getHome() + "/" + defaultRelativePath;
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void appendExtraFolders(const char* envName, const char* defaultValue, std::vector<std::string>& folders) {
|
|
||||||
const char* envValue = std::getenv(envName);
|
|
||||||
if (!envValue) {
|
|
||||||
envValue = defaultValue;
|
|
||||||
}
|
|
||||||
sago::internal::appendExtraFoldersTokenizer(envName, envValue, folders);
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
namespace sago {
|
|
||||||
|
|
||||||
#if !defined(_WIN32) && !defined(__APPLE__)
|
|
||||||
namespace internal {
|
|
||||||
void appendExtraFoldersTokenizer(const char* envName, const char* envValue, std::vector<std::string>& folders) {
|
|
||||||
std::stringstream ss(envValue);
|
|
||||||
std::string value;
|
|
||||||
while (std::getline(ss, value, ':')) {
|
|
||||||
if (value[0] == '/') {
|
|
||||||
folders.push_back(value);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
//Unless the system is wrongly configured this should never happen... But of course some systems will be incorectly configured.
|
|
||||||
//The XDG documentation indicates that the folder should be ignored but that the program should continue.
|
|
||||||
std::cerr << "Skipping path \"" << value << "\" in \"" << envName << "\" because it does not start with a \"/\"\n";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
std::string getDataHome() {
|
|
||||||
#ifdef _WIN32
|
|
||||||
return GetAppData();
|
|
||||||
#elif defined(__APPLE__)
|
|
||||||
return getHome()+"/Library/Application Support";
|
|
||||||
#else
|
|
||||||
return getLinuxFolderDefault("XDG_DATA_HOME", ".local/share");
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
std::string getHomeDir()
|
|
||||||
{
|
|
||||||
#if defined(_WIN32)
|
|
||||||
|
|
||||||
return GetKnownWindowsFolder(FOLDERID_Profile, "Profile could not be found");
|
|
||||||
#else
|
|
||||||
return getHome();
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
std::string getConfigHome() {
|
|
||||||
#ifdef _WIN32
|
|
||||||
return GetAppData();
|
|
||||||
#elif defined(__APPLE__)
|
|
||||||
return getHome()+"/Library/Application Support";
|
|
||||||
#else
|
|
||||||
return getLinuxFolderDefault("XDG_CONFIG_HOME", ".config");
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string getCacheDir() {
|
|
||||||
#ifdef _WIN32
|
|
||||||
return GetAppDataLocal();
|
|
||||||
#elif defined(__APPLE__)
|
|
||||||
return getHome()+"/Library/Caches";
|
|
||||||
#else
|
|
||||||
return getLinuxFolderDefault("XDG_CACHE_HOME", ".cache");
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string getStateDir() {
|
|
||||||
#ifdef _WIN32
|
|
||||||
return GetAppDataLocal();
|
|
||||||
#elif defined(__APPLE__)
|
|
||||||
return getHome()+"/Library/Application Support";
|
|
||||||
#else
|
|
||||||
return getLinuxFolderDefault("XDG_STATE_HOME", ".local/state");
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
void appendAdditionalDataDirectories(std::vector<std::string>& homes) {
|
|
||||||
#ifdef _WIN32
|
|
||||||
homes.push_back(GetAppDataCommon());
|
|
||||||
#elif !defined(__APPLE__)
|
|
||||||
appendExtraFolders("XDG_DATA_DIRS", "/usr/local/share/:/usr/share/", homes);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
void appendAdditionalConfigDirectories(std::vector<std::string>& homes) {
|
|
||||||
#ifdef _WIN32
|
|
||||||
homes.push_back(GetAppDataCommon());
|
|
||||||
#elif !defined(__APPLE__)
|
|
||||||
appendExtraFolders("XDG_CONFIG_DIRS", "/etc/xdg", homes);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
#if !defined(_WIN32) && !defined(__APPLE__)
|
|
||||||
struct PlatformFolders::PlatformFoldersData {
|
|
||||||
std::map<std::string, std::string> folders;
|
|
||||||
};
|
|
||||||
|
|
||||||
static void PlatformFoldersAddFromFile(const std::string& filename, std::map<std::string, std::string>& folders) {
|
|
||||||
std::ifstream infile(filename.c_str());
|
|
||||||
std::string line;
|
|
||||||
while (std::getline(infile, line)) {
|
|
||||||
if (line.length() == 0 || line.at(0) == '#' || line.substr(0, 4) != "XDG_" || line.find("_DIR") == std::string::npos) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
std::size_t splitPos = line.find('=');
|
|
||||||
std::string key = line.substr(0, splitPos);
|
|
||||||
std::size_t valueStart = line.find('"', splitPos);
|
|
||||||
std::size_t valueEnd = line.find('"', valueStart+1);
|
|
||||||
std::string value = line.substr(valueStart+1, valueEnd - valueStart - 1);
|
|
||||||
folders[key] = value;
|
|
||||||
}
|
|
||||||
catch (std::exception& e) {
|
|
||||||
std::cerr << "WARNING: Failed to process \"" << line << "\" from \"" << filename << "\". Error: "<< e.what() << "\n";
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void PlatformFoldersFillData(std::map<std::string, std::string>& folders) {
|
|
||||||
folders["XDG_DOCUMENTS_DIR"] = "$HOME/Documents";
|
|
||||||
folders["XDG_DESKTOP_DIR"] = "$HOME/Desktop";
|
|
||||||
folders["XDG_DOWNLOAD_DIR"] = "$HOME/Downloads";
|
|
||||||
folders["XDG_MUSIC_DIR"] = "$HOME/Music";
|
|
||||||
folders["XDG_PICTURES_DIR"] = "$HOME/Pictures";
|
|
||||||
folders["XDG_PUBLICSHARE_DIR"] = "$HOME/Public";
|
|
||||||
folders["XDG_TEMPLATES_DIR"] = "$HOME/.Templates";
|
|
||||||
folders["XDG_VIDEOS_DIR"] = "$HOME/Videos";
|
|
||||||
PlatformFoldersAddFromFile( getConfigHome()+"/user-dirs.dirs", folders);
|
|
||||||
for (std::map<std::string, std::string>::iterator itr = folders.begin() ; itr != folders.end() ; ++itr ) {
|
|
||||||
std::string& value = itr->second;
|
|
||||||
if (value.compare(0, 5, "$HOME") == 0) {
|
|
||||||
value = getHome() + value.substr(5, std::string::npos);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
PlatformFolders::PlatformFolders() {
|
|
||||||
#if !defined(_WIN32) && !defined(__APPLE__)
|
|
||||||
this->data = new PlatformFolders::PlatformFoldersData();
|
|
||||||
try {
|
|
||||||
PlatformFoldersFillData(data->folders);
|
|
||||||
}
|
|
||||||
catch (...) {
|
|
||||||
delete this->data;
|
|
||||||
throw;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
PlatformFolders::~PlatformFolders() {
|
|
||||||
#if !defined(_WIN32) && !defined(__APPLE__)
|
|
||||||
delete this->data;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string PlatformFolders::getDocumentsFolder() const {
|
|
||||||
#ifdef _WIN32
|
|
||||||
return GetKnownWindowsFolder(FOLDERID_Documents, "Failed to find My Documents folder");
|
|
||||||
#elif defined(__APPLE__)
|
|
||||||
return getHome()+"/Documents";
|
|
||||||
#else
|
|
||||||
return data->folders["XDG_DOCUMENTS_DIR"];
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string PlatformFolders::getDesktopFolder() const {
|
|
||||||
#ifdef _WIN32
|
|
||||||
return GetKnownWindowsFolder(FOLDERID_Desktop, "Failed to find Desktop folder");
|
|
||||||
#elif defined(__APPLE__)
|
|
||||||
return getHome()+"/Desktop";
|
|
||||||
#else
|
|
||||||
return data->folders["XDG_DESKTOP_DIR"];
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string PlatformFolders::getPicturesFolder() const {
|
|
||||||
#ifdef _WIN32
|
|
||||||
return GetKnownWindowsFolder(FOLDERID_Pictures, "Failed to find My Pictures folder");
|
|
||||||
#elif defined(__APPLE__)
|
|
||||||
return getHome()+"/Pictures";
|
|
||||||
#else
|
|
||||||
return data->folders["XDG_PICTURES_DIR"];
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string PlatformFolders::getPublicFolder() const {
|
|
||||||
#ifdef _WIN32
|
|
||||||
return GetKnownWindowsFolder(FOLDERID_Public, "Failed to find the Public folder");
|
|
||||||
#elif defined(__APPLE__)
|
|
||||||
return getHome()+"/Public";
|
|
||||||
#else
|
|
||||||
return data->folders["XDG_PUBLICSHARE_DIR"];
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string PlatformFolders::getDownloadFolder1() const {
|
|
||||||
#ifdef _WIN32
|
|
||||||
return GetKnownWindowsFolder(FOLDERID_Downloads, "Failed to find My Downloads folder");
|
|
||||||
#elif defined(__APPLE__)
|
|
||||||
return getHome()+"/Downloads";
|
|
||||||
#else
|
|
||||||
return data->folders["XDG_DOWNLOAD_DIR"];
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string PlatformFolders::getMusicFolder() const {
|
|
||||||
#ifdef _WIN32
|
|
||||||
return GetKnownWindowsFolder(FOLDERID_Music, "Failed to find My Music folder");
|
|
||||||
#elif defined(__APPLE__)
|
|
||||||
return getHome()+"/Music";
|
|
||||||
#else
|
|
||||||
return data->folders["XDG_MUSIC_DIR"];
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string PlatformFolders::getVideoFolder() const {
|
|
||||||
#ifdef _WIN32
|
|
||||||
return GetKnownWindowsFolder(FOLDERID_Videos, "Failed to find My Video folder");
|
|
||||||
#elif defined(__APPLE__)
|
|
||||||
return getHome()+"/Movies";
|
|
||||||
#else
|
|
||||||
return data->folders["XDG_VIDEOS_DIR"];
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string PlatformFolders::getSaveGamesFolder1() const {
|
|
||||||
#ifdef _WIN32
|
|
||||||
//A dedicated Save Games folder was not introduced until Vista. For XP and older save games are most often saved in a normal folder named "My Games".
|
|
||||||
//Data that should not be user accessible should be placed under GetDataHome() instead
|
|
||||||
return GetKnownWindowsFolder(FOLDERID_Documents, "Failed to find My Documents folder")+"\\My Games";
|
|
||||||
#elif defined(__APPLE__)
|
|
||||||
return getHome()+"/Library/Application Support";
|
|
||||||
#else
|
|
||||||
return getDataHome();
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string getDesktopFolder() {
|
|
||||||
return PlatformFolders().getDesktopFolder();
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string getDocumentsFolder() {
|
|
||||||
return PlatformFolders().getDocumentsFolder();
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string getDownloadFolder() {
|
|
||||||
return PlatformFolders().getDownloadFolder1();
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string getDownloadFolder1() {
|
|
||||||
return getDownloadFolder();
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string getPicturesFolder() {
|
|
||||||
return PlatformFolders().getPicturesFolder();
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string getPublicFolder() {
|
|
||||||
return PlatformFolders().getPublicFolder();
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string getMusicFolder() {
|
|
||||||
return PlatformFolders().getMusicFolder();
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string getVideoFolder() {
|
|
||||||
return PlatformFolders().getVideoFolder();
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string getSaveGamesFolder1() {
|
|
||||||
return PlatformFolders().getSaveGamesFolder1();
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string getSaveGamesFolder2() {
|
|
||||||
#ifdef _WIN32
|
|
||||||
return GetKnownWindowsFolder(FOLDERID_SavedGames, "Failed to find Saved Games folder");
|
|
||||||
#else
|
|
||||||
return PlatformFolders().getSaveGamesFolder1();
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
} //namespace sago
|
|
||||||
#endif
|
|
||||||
@ -1,305 +0,0 @@
|
|||||||
/*
|
|
||||||
Its is under the MIT license, to encourage reuse by cut-and-paste.
|
|
||||||
|
|
||||||
The original files are hosted here: https://github.com/sago007/PlatformFolders
|
|
||||||
|
|
||||||
Copyright (c) 2015 Poul Sander
|
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person
|
|
||||||
obtaining a copy of this software and associated documentation files
|
|
||||||
(the "Software"), to deal in the Software without restriction,
|
|
||||||
including without limitation the rights to use, copy, modify, merge,
|
|
||||||
publish, distribute, sublicense, and/or sell copies of the Software,
|
|
||||||
and to permit persons to whom the Software is furnished to do so,
|
|
||||||
subject to the following conditions:
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be
|
|
||||||
included in all copies or substantial portions of the Software.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
||||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
||||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
||||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
|
||||||
BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
|
||||||
ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
|
||||||
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
SOFTWARE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
Modified by Mike Nolan for this project
|
|
||||||
I modified it to return home directory and conditionally compile for systems that are not GEKKO / NX etc
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#ifndef SAGO_PLATFORM_FOLDERS_H
|
|
||||||
#define SAGO_PLATFORM_FOLDERS_H
|
|
||||||
|
|
||||||
#if defined(GEKKO) || defined(__SWITCH__) || defined(__EMSCRIPTEN__)
|
|
||||||
#define SAGO_DISABLE
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#if !defined(SAGO_DISABLE)
|
|
||||||
|
|
||||||
#include <vector>
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The namespace I use for common function. Nothing special about it.
|
|
||||||
*/
|
|
||||||
namespace sago {
|
|
||||||
|
|
||||||
#ifndef DOXYGEN_SHOULD_SKIP_THIS
|
|
||||||
namespace internal {
|
|
||||||
#if !defined(_WIN32) && !defined(__APPLE__)
|
|
||||||
void appendExtraFoldersTokenizer(const char* envName, const char* envValue, std::vector<std::string>& folders);
|
|
||||||
#endif
|
|
||||||
#ifdef _WIN32
|
|
||||||
std::string win32_utf16_to_utf8(const wchar_t* wstr);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
#endif //DOXYGEN_SHOULD_SKIP_THIS
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Retrives the base folder for storing data files.
|
|
||||||
* You must add the program name yourself like this:
|
|
||||||
* @code{.cpp}
|
|
||||||
* string data_home = getDataHome()+"/My Program Name/";
|
|
||||||
* @endcode
|
|
||||||
* On Windows this defaults to %APPDATA% (Roaming profile)
|
|
||||||
* On Linux this defaults to ~/.local/share but can be configured by the user
|
|
||||||
* @return The base folder for storing program data.
|
|
||||||
*/
|
|
||||||
std::string getDataHome();
|
|
||||||
|
|
||||||
std::string getHomeDir();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Retrives the base folder for storing config files.
|
|
||||||
* You must add the program name yourself like this:
|
|
||||||
* @code{.cpp}
|
|
||||||
* string data_home = getConfigHome()+"/My Program Name/";
|
|
||||||
* @endcode
|
|
||||||
* On Windows this defaults to %APPDATA% (Roaming profile)
|
|
||||||
* On Linux this defaults to ~/.config but can be configured by the user
|
|
||||||
* @return The base folder for storing config data.
|
|
||||||
*/
|
|
||||||
std::string getConfigHome();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Retrives the base folder for storing cache files.
|
|
||||||
* You must add the program name yourself like this:
|
|
||||||
* @code{.cpp}
|
|
||||||
* string data_home = getCacheDir()+"/My Program Name/cache/";
|
|
||||||
* @endcode
|
|
||||||
* On Windows this defaults to %APPDATALOCAL%
|
|
||||||
* On Linux this defaults to ~/.cache but can be configured by the user
|
|
||||||
* Note that it is recommended to append "cache" after the program name to prevent conflicting with "StateDir" under Windows
|
|
||||||
* @return The base folder for storing data that do not need to be backed up and might be deleted.
|
|
||||||
*/
|
|
||||||
std::string getCacheDir();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Retrives the base folder used for state files.
|
|
||||||
* You must add the program name yourself like this:
|
|
||||||
* @code{.cpp}
|
|
||||||
* string data_home = getStateDir()+"/My Program Name/";
|
|
||||||
* @endcode
|
|
||||||
* On Windows this defaults to %APPDATALOCAL%
|
|
||||||
* On Linux this defaults to ~/.local/state but can be configured by the user
|
|
||||||
* On OS X this is the same as getDataHome()
|
|
||||||
* @return The base folder for storing data that do not need to be backed up but should not be reguarly deleted either.
|
|
||||||
*/
|
|
||||||
std::string getStateDir();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This will append extra folders that your program should be looking for data files in.
|
|
||||||
* This does not normally include the path returned by GetDataHome().
|
|
||||||
* If you want all the folders you should do something like:
|
|
||||||
* @code{.cpp}
|
|
||||||
* vector<string> folders;
|
|
||||||
* folders.push_back(getDataHome());
|
|
||||||
* appendAdditionalDataDirectories(folders);
|
|
||||||
* for (string s& : folders) {
|
|
||||||
* s+="/My Program Name/";
|
|
||||||
* }
|
|
||||||
* @endcode
|
|
||||||
* You must apply "/My Program Name/" to all the strings.
|
|
||||||
* The string at the lowest index has the highest priority.
|
|
||||||
* @param homes A vector that extra folders will be appended to.
|
|
||||||
*/
|
|
||||||
void appendAdditionalDataDirectories(std::vector<std::string>& homes);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This will append extra folders that your program should be looking for config files in.
|
|
||||||
* This does not normally include the path returned by GetConfigHome().
|
|
||||||
* If you want all the folders you should do something like:
|
|
||||||
* @code{.cpp}
|
|
||||||
* std::vector<std::string> folders;
|
|
||||||
* folders.push_back(sago::getConfigHome());
|
|
||||||
* sago::appendAdditionalConfigDirectories(folders);
|
|
||||||
* for (std::string s& : folders) {
|
|
||||||
* s+="/My Program Name/";
|
|
||||||
* }
|
|
||||||
* @endcode
|
|
||||||
* You must apply "/My Program Name/" to all the strings.
|
|
||||||
* The string at the lowest index has the highest priority.
|
|
||||||
* @param homes A vector that extra folders will be appended to.
|
|
||||||
*/
|
|
||||||
void appendAdditionalConfigDirectories(std::vector<std::string>& homes);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The folder that represents the desktop.
|
|
||||||
* Normally you should try not to use this folder.
|
|
||||||
* @return Absolute path to the user's desktop
|
|
||||||
*/
|
|
||||||
std::string getDesktopFolder();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The folder to store user documents to
|
|
||||||
* @return Absolute path to the "Documents" folder
|
|
||||||
*/
|
|
||||||
std::string getDocumentsFolder();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The folder where files are downloaded.
|
|
||||||
* @return Absolute path to the folder where files are downloaded to.
|
|
||||||
*/
|
|
||||||
std::string getDownloadFolder();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The folder where files are downloaded.
|
|
||||||
* @note This is provided for backward compatibility. Use getDownloadFolder instead.
|
|
||||||
* @return Absolute path to the folder where files are downloaded to.
|
|
||||||
*/
|
|
||||||
std::string getDownloadFolder1();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The folder for storing the user's pictures.
|
|
||||||
* @return Absolute path to the "Picture" folder
|
|
||||||
*/
|
|
||||||
std::string getPicturesFolder();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This returns the folder that can be used for sharing files with other users on the same system.
|
|
||||||
* @return Absolute path to the "Public" folder
|
|
||||||
*/
|
|
||||||
std::string getPublicFolder();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The folder where music is stored
|
|
||||||
* @return Absolute path to the music folder
|
|
||||||
*/
|
|
||||||
std::string getMusicFolder();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The folder where video is stored
|
|
||||||
* @return Absolute path to the video folder
|
|
||||||
*/
|
|
||||||
std::string getVideoFolder();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A base folder for storing saved games.
|
|
||||||
* You must add the program name to it like this:
|
|
||||||
* @code{.cpp}
|
|
||||||
* string saved_games_folder = sago::getSaveGamesFolder1()+"/My Program Name/";
|
|
||||||
* @endcode
|
|
||||||
* @note Windows: This is an XP compatible version and returns the path to "My Games" in Documents. Vista and later has an official folder.
|
|
||||||
* @note Linux: XDF does not define a folder for saved games. This will just return the same as GetDataHome()
|
|
||||||
* @return The folder base folder for storing save games.
|
|
||||||
*/
|
|
||||||
std::string getSaveGamesFolder1();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A base folder for storing saved games.
|
|
||||||
* You must add the program name to it like this:
|
|
||||||
* @code{.cpp}
|
|
||||||
* string saved_games_folder = sago::getSaveGamesFolder2()+"/My Program Name/";
|
|
||||||
* @endcode
|
|
||||||
* @note PlatformFolders provide different folders to for saved games as not all operating systems has support for Saved Games yet.
|
|
||||||
* It is recommended to pick the highest number (currently getSaveGamesFolder2) at the time your product enters production and stick with it
|
|
||||||
* @note Windows: This returns the "Saved Games" folder. This folder exist in Vista and later
|
|
||||||
* @note Linux: XDF does not define a folder for saved games. This will just return the same as GetDataHome()
|
|
||||||
* @return The folder base folder for storing save games.
|
|
||||||
*/
|
|
||||||
std::string getSaveGamesFolder2();
|
|
||||||
|
|
||||||
#ifndef DOXYGEN_SHOULD_SKIP_THIS
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This class contains methods for finding the system depended special folders.
|
|
||||||
* For Windows these folders are either by convention or given by CSIDL.
|
|
||||||
* For Linux XDG convention is used.
|
|
||||||
* The Linux version has very little error checking and assumes that the config is correct
|
|
||||||
*/
|
|
||||||
class PlatformFolders {
|
|
||||||
public:
|
|
||||||
PlatformFolders();
|
|
||||||
~PlatformFolders();
|
|
||||||
/**
|
|
||||||
* The folder that represents the desktop.
|
|
||||||
* Normally you should try not to use this folder.
|
|
||||||
* @return Absolute path to the user's desktop
|
|
||||||
*/
|
|
||||||
std::string getDesktopFolder() const;
|
|
||||||
/**
|
|
||||||
* The folder to store user documents to
|
|
||||||
* @return Absolute path to the "Documents" folder
|
|
||||||
*/
|
|
||||||
std::string getDocumentsFolder() const;
|
|
||||||
/**
|
|
||||||
* The folder for storing the user's pictures.
|
|
||||||
* @return Absolute path to the "Picture" folder
|
|
||||||
*/
|
|
||||||
std::string getPicturesFolder() const;
|
|
||||||
/**
|
|
||||||
* Use sago::getPublicFolder() instead!
|
|
||||||
*/
|
|
||||||
std::string getPublicFolder() const;
|
|
||||||
/**
|
|
||||||
* The folder where files are downloaded.
|
|
||||||
* @note Windows: This version is XP compatible and returns the Desktop. Vista and later has a dedicated folder.
|
|
||||||
* @return Absolute path to the folder where files are downloaded to.
|
|
||||||
*/
|
|
||||||
std::string getDownloadFolder1() const;
|
|
||||||
/**
|
|
||||||
* The folder where music is stored
|
|
||||||
* @return Absolute path to the music folder
|
|
||||||
*/
|
|
||||||
std::string getMusicFolder() const;
|
|
||||||
/**
|
|
||||||
* The folder where video is stored
|
|
||||||
* @return Absolute path to the video folder
|
|
||||||
*/
|
|
||||||
std::string getVideoFolder() const;
|
|
||||||
/**
|
|
||||||
* The base folder for storing saved games.
|
|
||||||
* You must add the program name to it like this:
|
|
||||||
* @code{.cpp}
|
|
||||||
* PlatformFolders pf;
|
|
||||||
* string saved_games_folder = pf.getSaveGamesFolder1()+"/My Program Name/";
|
|
||||||
* @endcode
|
|
||||||
* @note Windows: This is an XP compatible version and returns the path to "My Games" in Documents. Vista and later has an official folder.
|
|
||||||
* @note Linux: XDF does not define a folder for saved games. This will just return the same as GetDataHome()
|
|
||||||
* @return The folder base folder for storing save games.
|
|
||||||
*/
|
|
||||||
std::string getSaveGamesFolder1() const;
|
|
||||||
private:
|
|
||||||
PlatformFolders(const PlatformFolders&);
|
|
||||||
PlatformFolders& operator=(const PlatformFolders&);
|
|
||||||
#if !defined(_WIN32) && !defined(__APPLE__)
|
|
||||||
struct PlatformFoldersData;
|
|
||||||
PlatformFoldersData* data;
|
|
||||||
#endif
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // skip doxygen
|
|
||||||
|
|
||||||
|
|
||||||
} //namespace sago
|
|
||||||
#endif
|
|
||||||
#endif /* PLATFORM_FOLDERS_H */
|
|
||||||
257688
src/sqlite/sqlite3.c
257688
src/sqlite/sqlite3.c
File diff suppressed because it is too large
Load Diff
13431
src/sqlite/sqlite3.h
13431
src/sqlite/sqlite3.h
File diff suppressed because it is too large
Load Diff
@ -1,719 +0,0 @@
|
|||||||
/*
|
|
||||||
** 2006 June 7
|
|
||||||
**
|
|
||||||
** The author disclaims copyright to this source code. In place of
|
|
||||||
** a legal notice, here is a blessing:
|
|
||||||
**
|
|
||||||
** May you do good and not evil.
|
|
||||||
** May you find forgiveness for yourself and forgive others.
|
|
||||||
** May you share freely, never taking more than you give.
|
|
||||||
**
|
|
||||||
*************************************************************************
|
|
||||||
** This header file defines the SQLite interface for use by
|
|
||||||
** shared libraries that want to be imported as extensions into
|
|
||||||
** an SQLite instance. Shared libraries that intend to be loaded
|
|
||||||
** as extensions by SQLite should #include this file instead of
|
|
||||||
** sqlite3.h.
|
|
||||||
*/
|
|
||||||
#ifndef SQLITE3EXT_H
|
|
||||||
#define SQLITE3EXT_H
|
|
||||||
#include "sqlite3.h"
|
|
||||||
|
|
||||||
/*
|
|
||||||
** The following structure holds pointers to all of the SQLite API
|
|
||||||
** routines.
|
|
||||||
**
|
|
||||||
** WARNING: In order to maintain backwards compatibility, add new
|
|
||||||
** interfaces to the end of this structure only. If you insert new
|
|
||||||
** interfaces in the middle of this structure, then older different
|
|
||||||
** versions of SQLite will not be able to load each other's shared
|
|
||||||
** libraries!
|
|
||||||
*/
|
|
||||||
struct sqlite3_api_routines {
|
|
||||||
void * (*aggregate_context)(sqlite3_context*,int nBytes);
|
|
||||||
int (*aggregate_count)(sqlite3_context*);
|
|
||||||
int (*bind_blob)(sqlite3_stmt*,int,const void*,int n,void(*)(void*));
|
|
||||||
int (*bind_double)(sqlite3_stmt*,int,double);
|
|
||||||
int (*bind_int)(sqlite3_stmt*,int,int);
|
|
||||||
int (*bind_int64)(sqlite3_stmt*,int,sqlite_int64);
|
|
||||||
int (*bind_null)(sqlite3_stmt*,int);
|
|
||||||
int (*bind_parameter_count)(sqlite3_stmt*);
|
|
||||||
int (*bind_parameter_index)(sqlite3_stmt*,const char*zName);
|
|
||||||
const char * (*bind_parameter_name)(sqlite3_stmt*,int);
|
|
||||||
int (*bind_text)(sqlite3_stmt*,int,const char*,int n,void(*)(void*));
|
|
||||||
int (*bind_text16)(sqlite3_stmt*,int,const void*,int,void(*)(void*));
|
|
||||||
int (*bind_value)(sqlite3_stmt*,int,const sqlite3_value*);
|
|
||||||
int (*busy_handler)(sqlite3*,int(*)(void*,int),void*);
|
|
||||||
int (*busy_timeout)(sqlite3*,int ms);
|
|
||||||
int (*changes)(sqlite3*);
|
|
||||||
int (*close)(sqlite3*);
|
|
||||||
int (*collation_needed)(sqlite3*,void*,void(*)(void*,sqlite3*,
|
|
||||||
int eTextRep,const char*));
|
|
||||||
int (*collation_needed16)(sqlite3*,void*,void(*)(void*,sqlite3*,
|
|
||||||
int eTextRep,const void*));
|
|
||||||
const void * (*column_blob)(sqlite3_stmt*,int iCol);
|
|
||||||
int (*column_bytes)(sqlite3_stmt*,int iCol);
|
|
||||||
int (*column_bytes16)(sqlite3_stmt*,int iCol);
|
|
||||||
int (*column_count)(sqlite3_stmt*pStmt);
|
|
||||||
const char * (*column_database_name)(sqlite3_stmt*,int);
|
|
||||||
const void * (*column_database_name16)(sqlite3_stmt*,int);
|
|
||||||
const char * (*column_decltype)(sqlite3_stmt*,int i);
|
|
||||||
const void * (*column_decltype16)(sqlite3_stmt*,int);
|
|
||||||
double (*column_double)(sqlite3_stmt*,int iCol);
|
|
||||||
int (*column_int)(sqlite3_stmt*,int iCol);
|
|
||||||
sqlite_int64 (*column_int64)(sqlite3_stmt*,int iCol);
|
|
||||||
const char * (*column_name)(sqlite3_stmt*,int);
|
|
||||||
const void * (*column_name16)(sqlite3_stmt*,int);
|
|
||||||
const char * (*column_origin_name)(sqlite3_stmt*,int);
|
|
||||||
const void * (*column_origin_name16)(sqlite3_stmt*,int);
|
|
||||||
const char * (*column_table_name)(sqlite3_stmt*,int);
|
|
||||||
const void * (*column_table_name16)(sqlite3_stmt*,int);
|
|
||||||
const unsigned char * (*column_text)(sqlite3_stmt*,int iCol);
|
|
||||||
const void * (*column_text16)(sqlite3_stmt*,int iCol);
|
|
||||||
int (*column_type)(sqlite3_stmt*,int iCol);
|
|
||||||
sqlite3_value* (*column_value)(sqlite3_stmt*,int iCol);
|
|
||||||
void * (*commit_hook)(sqlite3*,int(*)(void*),void*);
|
|
||||||
int (*complete)(const char*sql);
|
|
||||||
int (*complete16)(const void*sql);
|
|
||||||
int (*create_collation)(sqlite3*,const char*,int,void*,
|
|
||||||
int(*)(void*,int,const void*,int,const void*));
|
|
||||||
int (*create_collation16)(sqlite3*,const void*,int,void*,
|
|
||||||
int(*)(void*,int,const void*,int,const void*));
|
|
||||||
int (*create_function)(sqlite3*,const char*,int,int,void*,
|
|
||||||
void (*xFunc)(sqlite3_context*,int,sqlite3_value**),
|
|
||||||
void (*xStep)(sqlite3_context*,int,sqlite3_value**),
|
|
||||||
void (*xFinal)(sqlite3_context*));
|
|
||||||
int (*create_function16)(sqlite3*,const void*,int,int,void*,
|
|
||||||
void (*xFunc)(sqlite3_context*,int,sqlite3_value**),
|
|
||||||
void (*xStep)(sqlite3_context*,int,sqlite3_value**),
|
|
||||||
void (*xFinal)(sqlite3_context*));
|
|
||||||
int (*create_module)(sqlite3*,const char*,const sqlite3_module*,void*);
|
|
||||||
int (*data_count)(sqlite3_stmt*pStmt);
|
|
||||||
sqlite3 * (*db_handle)(sqlite3_stmt*);
|
|
||||||
int (*declare_vtab)(sqlite3*,const char*);
|
|
||||||
int (*enable_shared_cache)(int);
|
|
||||||
int (*errcode)(sqlite3*db);
|
|
||||||
const char * (*errmsg)(sqlite3*);
|
|
||||||
const void * (*errmsg16)(sqlite3*);
|
|
||||||
int (*exec)(sqlite3*,const char*,sqlite3_callback,void*,char**);
|
|
||||||
int (*expired)(sqlite3_stmt*);
|
|
||||||
int (*finalize)(sqlite3_stmt*pStmt);
|
|
||||||
void (*free)(void*);
|
|
||||||
void (*free_table)(char**result);
|
|
||||||
int (*get_autocommit)(sqlite3*);
|
|
||||||
void * (*get_auxdata)(sqlite3_context*,int);
|
|
||||||
int (*get_table)(sqlite3*,const char*,char***,int*,int*,char**);
|
|
||||||
int (*global_recover)(void);
|
|
||||||
void (*interruptx)(sqlite3*);
|
|
||||||
sqlite_int64 (*last_insert_rowid)(sqlite3*);
|
|
||||||
const char * (*libversion)(void);
|
|
||||||
int (*libversion_number)(void);
|
|
||||||
void *(*malloc)(int);
|
|
||||||
char * (*mprintf)(const char*,...);
|
|
||||||
int (*open)(const char*,sqlite3**);
|
|
||||||
int (*open16)(const void*,sqlite3**);
|
|
||||||
int (*prepare)(sqlite3*,const char*,int,sqlite3_stmt**,const char**);
|
|
||||||
int (*prepare16)(sqlite3*,const void*,int,sqlite3_stmt**,const void**);
|
|
||||||
void * (*profile)(sqlite3*,void(*)(void*,const char*,sqlite_uint64),void*);
|
|
||||||
void (*progress_handler)(sqlite3*,int,int(*)(void*),void*);
|
|
||||||
void *(*realloc)(void*,int);
|
|
||||||
int (*reset)(sqlite3_stmt*pStmt);
|
|
||||||
void (*result_blob)(sqlite3_context*,const void*,int,void(*)(void*));
|
|
||||||
void (*result_double)(sqlite3_context*,double);
|
|
||||||
void (*result_error)(sqlite3_context*,const char*,int);
|
|
||||||
void (*result_error16)(sqlite3_context*,const void*,int);
|
|
||||||
void (*result_int)(sqlite3_context*,int);
|
|
||||||
void (*result_int64)(sqlite3_context*,sqlite_int64);
|
|
||||||
void (*result_null)(sqlite3_context*);
|
|
||||||
void (*result_text)(sqlite3_context*,const char*,int,void(*)(void*));
|
|
||||||
void (*result_text16)(sqlite3_context*,const void*,int,void(*)(void*));
|
|
||||||
void (*result_text16be)(sqlite3_context*,const void*,int,void(*)(void*));
|
|
||||||
void (*result_text16le)(sqlite3_context*,const void*,int,void(*)(void*));
|
|
||||||
void (*result_value)(sqlite3_context*,sqlite3_value*);
|
|
||||||
void * (*rollback_hook)(sqlite3*,void(*)(void*),void*);
|
|
||||||
int (*set_authorizer)(sqlite3*,int(*)(void*,int,const char*,const char*,
|
|
||||||
const char*,const char*),void*);
|
|
||||||
void (*set_auxdata)(sqlite3_context*,int,void*,void (*)(void*));
|
|
||||||
char * (*xsnprintf)(int,char*,const char*,...);
|
|
||||||
int (*step)(sqlite3_stmt*);
|
|
||||||
int (*table_column_metadata)(sqlite3*,const char*,const char*,const char*,
|
|
||||||
char const**,char const**,int*,int*,int*);
|
|
||||||
void (*thread_cleanup)(void);
|
|
||||||
int (*total_changes)(sqlite3*);
|
|
||||||
void * (*trace)(sqlite3*,void(*xTrace)(void*,const char*),void*);
|
|
||||||
int (*transfer_bindings)(sqlite3_stmt*,sqlite3_stmt*);
|
|
||||||
void * (*update_hook)(sqlite3*,void(*)(void*,int ,char const*,char const*,
|
|
||||||
sqlite_int64),void*);
|
|
||||||
void * (*user_data)(sqlite3_context*);
|
|
||||||
const void * (*value_blob)(sqlite3_value*);
|
|
||||||
int (*value_bytes)(sqlite3_value*);
|
|
||||||
int (*value_bytes16)(sqlite3_value*);
|
|
||||||
double (*value_double)(sqlite3_value*);
|
|
||||||
int (*value_int)(sqlite3_value*);
|
|
||||||
sqlite_int64 (*value_int64)(sqlite3_value*);
|
|
||||||
int (*value_numeric_type)(sqlite3_value*);
|
|
||||||
const unsigned char * (*value_text)(sqlite3_value*);
|
|
||||||
const void * (*value_text16)(sqlite3_value*);
|
|
||||||
const void * (*value_text16be)(sqlite3_value*);
|
|
||||||
const void * (*value_text16le)(sqlite3_value*);
|
|
||||||
int (*value_type)(sqlite3_value*);
|
|
||||||
char *(*vmprintf)(const char*,va_list);
|
|
||||||
/* Added ??? */
|
|
||||||
int (*overload_function)(sqlite3*, const char *zFuncName, int nArg);
|
|
||||||
/* Added by 3.3.13 */
|
|
||||||
int (*prepare_v2)(sqlite3*,const char*,int,sqlite3_stmt**,const char**);
|
|
||||||
int (*prepare16_v2)(sqlite3*,const void*,int,sqlite3_stmt**,const void**);
|
|
||||||
int (*clear_bindings)(sqlite3_stmt*);
|
|
||||||
/* Added by 3.4.1 */
|
|
||||||
int (*create_module_v2)(sqlite3*,const char*,const sqlite3_module*,void*,
|
|
||||||
void (*xDestroy)(void *));
|
|
||||||
/* Added by 3.5.0 */
|
|
||||||
int (*bind_zeroblob)(sqlite3_stmt*,int,int);
|
|
||||||
int (*blob_bytes)(sqlite3_blob*);
|
|
||||||
int (*blob_close)(sqlite3_blob*);
|
|
||||||
int (*blob_open)(sqlite3*,const char*,const char*,const char*,sqlite3_int64,
|
|
||||||
int,sqlite3_blob**);
|
|
||||||
int (*blob_read)(sqlite3_blob*,void*,int,int);
|
|
||||||
int (*blob_write)(sqlite3_blob*,const void*,int,int);
|
|
||||||
int (*create_collation_v2)(sqlite3*,const char*,int,void*,
|
|
||||||
int(*)(void*,int,const void*,int,const void*),
|
|
||||||
void(*)(void*));
|
|
||||||
int (*file_control)(sqlite3*,const char*,int,void*);
|
|
||||||
sqlite3_int64 (*memory_highwater)(int);
|
|
||||||
sqlite3_int64 (*memory_used)(void);
|
|
||||||
sqlite3_mutex *(*mutex_alloc)(int);
|
|
||||||
void (*mutex_enter)(sqlite3_mutex*);
|
|
||||||
void (*mutex_free)(sqlite3_mutex*);
|
|
||||||
void (*mutex_leave)(sqlite3_mutex*);
|
|
||||||
int (*mutex_try)(sqlite3_mutex*);
|
|
||||||
int (*open_v2)(const char*,sqlite3**,int,const char*);
|
|
||||||
int (*release_memory)(int);
|
|
||||||
void (*result_error_nomem)(sqlite3_context*);
|
|
||||||
void (*result_error_toobig)(sqlite3_context*);
|
|
||||||
int (*sleep)(int);
|
|
||||||
void (*soft_heap_limit)(int);
|
|
||||||
sqlite3_vfs *(*vfs_find)(const char*);
|
|
||||||
int (*vfs_register)(sqlite3_vfs*,int);
|
|
||||||
int (*vfs_unregister)(sqlite3_vfs*);
|
|
||||||
int (*xthreadsafe)(void);
|
|
||||||
void (*result_zeroblob)(sqlite3_context*,int);
|
|
||||||
void (*result_error_code)(sqlite3_context*,int);
|
|
||||||
int (*test_control)(int, ...);
|
|
||||||
void (*randomness)(int,void*);
|
|
||||||
sqlite3 *(*context_db_handle)(sqlite3_context*);
|
|
||||||
int (*extended_result_codes)(sqlite3*,int);
|
|
||||||
int (*limit)(sqlite3*,int,int);
|
|
||||||
sqlite3_stmt *(*next_stmt)(sqlite3*,sqlite3_stmt*);
|
|
||||||
const char *(*sql)(sqlite3_stmt*);
|
|
||||||
int (*status)(int,int*,int*,int);
|
|
||||||
int (*backup_finish)(sqlite3_backup*);
|
|
||||||
sqlite3_backup *(*backup_init)(sqlite3*,const char*,sqlite3*,const char*);
|
|
||||||
int (*backup_pagecount)(sqlite3_backup*);
|
|
||||||
int (*backup_remaining)(sqlite3_backup*);
|
|
||||||
int (*backup_step)(sqlite3_backup*,int);
|
|
||||||
const char *(*compileoption_get)(int);
|
|
||||||
int (*compileoption_used)(const char*);
|
|
||||||
int (*create_function_v2)(sqlite3*,const char*,int,int,void*,
|
|
||||||
void (*xFunc)(sqlite3_context*,int,sqlite3_value**),
|
|
||||||
void (*xStep)(sqlite3_context*,int,sqlite3_value**),
|
|
||||||
void (*xFinal)(sqlite3_context*),
|
|
||||||
void(*xDestroy)(void*));
|
|
||||||
int (*db_config)(sqlite3*,int,...);
|
|
||||||
sqlite3_mutex *(*db_mutex)(sqlite3*);
|
|
||||||
int (*db_status)(sqlite3*,int,int*,int*,int);
|
|
||||||
int (*extended_errcode)(sqlite3*);
|
|
||||||
void (*log)(int,const char*,...);
|
|
||||||
sqlite3_int64 (*soft_heap_limit64)(sqlite3_int64);
|
|
||||||
const char *(*sourceid)(void);
|
|
||||||
int (*stmt_status)(sqlite3_stmt*,int,int);
|
|
||||||
int (*strnicmp)(const char*,const char*,int);
|
|
||||||
int (*unlock_notify)(sqlite3*,void(*)(void**,int),void*);
|
|
||||||
int (*wal_autocheckpoint)(sqlite3*,int);
|
|
||||||
int (*wal_checkpoint)(sqlite3*,const char*);
|
|
||||||
void *(*wal_hook)(sqlite3*,int(*)(void*,sqlite3*,const char*,int),void*);
|
|
||||||
int (*blob_reopen)(sqlite3_blob*,sqlite3_int64);
|
|
||||||
int (*vtab_config)(sqlite3*,int op,...);
|
|
||||||
int (*vtab_on_conflict)(sqlite3*);
|
|
||||||
/* Version 3.7.16 and later */
|
|
||||||
int (*close_v2)(sqlite3*);
|
|
||||||
const char *(*db_filename)(sqlite3*,const char*);
|
|
||||||
int (*db_readonly)(sqlite3*,const char*);
|
|
||||||
int (*db_release_memory)(sqlite3*);
|
|
||||||
const char *(*errstr)(int);
|
|
||||||
int (*stmt_busy)(sqlite3_stmt*);
|
|
||||||
int (*stmt_readonly)(sqlite3_stmt*);
|
|
||||||
int (*stricmp)(const char*,const char*);
|
|
||||||
int (*uri_boolean)(const char*,const char*,int);
|
|
||||||
sqlite3_int64 (*uri_int64)(const char*,const char*,sqlite3_int64);
|
|
||||||
const char *(*uri_parameter)(const char*,const char*);
|
|
||||||
char *(*xvsnprintf)(int,char*,const char*,va_list);
|
|
||||||
int (*wal_checkpoint_v2)(sqlite3*,const char*,int,int*,int*);
|
|
||||||
/* Version 3.8.7 and later */
|
|
||||||
int (*auto_extension)(void(*)(void));
|
|
||||||
int (*bind_blob64)(sqlite3_stmt*,int,const void*,sqlite3_uint64,
|
|
||||||
void(*)(void*));
|
|
||||||
int (*bind_text64)(sqlite3_stmt*,int,const char*,sqlite3_uint64,
|
|
||||||
void(*)(void*),unsigned char);
|
|
||||||
int (*cancel_auto_extension)(void(*)(void));
|
|
||||||
int (*load_extension)(sqlite3*,const char*,const char*,char**);
|
|
||||||
void *(*malloc64)(sqlite3_uint64);
|
|
||||||
sqlite3_uint64 (*msize)(void*);
|
|
||||||
void *(*realloc64)(void*,sqlite3_uint64);
|
|
||||||
void (*reset_auto_extension)(void);
|
|
||||||
void (*result_blob64)(sqlite3_context*,const void*,sqlite3_uint64,
|
|
||||||
void(*)(void*));
|
|
||||||
void (*result_text64)(sqlite3_context*,const char*,sqlite3_uint64,
|
|
||||||
void(*)(void*), unsigned char);
|
|
||||||
int (*strglob)(const char*,const char*);
|
|
||||||
/* Version 3.8.11 and later */
|
|
||||||
sqlite3_value *(*value_dup)(const sqlite3_value*);
|
|
||||||
void (*value_free)(sqlite3_value*);
|
|
||||||
int (*result_zeroblob64)(sqlite3_context*,sqlite3_uint64);
|
|
||||||
int (*bind_zeroblob64)(sqlite3_stmt*, int, sqlite3_uint64);
|
|
||||||
/* Version 3.9.0 and later */
|
|
||||||
unsigned int (*value_subtype)(sqlite3_value*);
|
|
||||||
void (*result_subtype)(sqlite3_context*,unsigned int);
|
|
||||||
/* Version 3.10.0 and later */
|
|
||||||
int (*status64)(int,sqlite3_int64*,sqlite3_int64*,int);
|
|
||||||
int (*strlike)(const char*,const char*,unsigned int);
|
|
||||||
int (*db_cacheflush)(sqlite3*);
|
|
||||||
/* Version 3.12.0 and later */
|
|
||||||
int (*system_errno)(sqlite3*);
|
|
||||||
/* Version 3.14.0 and later */
|
|
||||||
int (*trace_v2)(sqlite3*,unsigned,int(*)(unsigned,void*,void*,void*),void*);
|
|
||||||
char *(*expanded_sql)(sqlite3_stmt*);
|
|
||||||
/* Version 3.18.0 and later */
|
|
||||||
void (*set_last_insert_rowid)(sqlite3*,sqlite3_int64);
|
|
||||||
/* Version 3.20.0 and later */
|
|
||||||
int (*prepare_v3)(sqlite3*,const char*,int,unsigned int,
|
|
||||||
sqlite3_stmt**,const char**);
|
|
||||||
int (*prepare16_v3)(sqlite3*,const void*,int,unsigned int,
|
|
||||||
sqlite3_stmt**,const void**);
|
|
||||||
int (*bind_pointer)(sqlite3_stmt*,int,void*,const char*,void(*)(void*));
|
|
||||||
void (*result_pointer)(sqlite3_context*,void*,const char*,void(*)(void*));
|
|
||||||
void *(*value_pointer)(sqlite3_value*,const char*);
|
|
||||||
int (*vtab_nochange)(sqlite3_context*);
|
|
||||||
int (*value_nochange)(sqlite3_value*);
|
|
||||||
const char *(*vtab_collation)(sqlite3_index_info*,int);
|
|
||||||
/* Version 3.24.0 and later */
|
|
||||||
int (*keyword_count)(void);
|
|
||||||
int (*keyword_name)(int,const char**,int*);
|
|
||||||
int (*keyword_check)(const char*,int);
|
|
||||||
sqlite3_str *(*str_new)(sqlite3*);
|
|
||||||
char *(*str_finish)(sqlite3_str*);
|
|
||||||
void (*str_appendf)(sqlite3_str*, const char *zFormat, ...);
|
|
||||||
void (*str_vappendf)(sqlite3_str*, const char *zFormat, va_list);
|
|
||||||
void (*str_append)(sqlite3_str*, const char *zIn, int N);
|
|
||||||
void (*str_appendall)(sqlite3_str*, const char *zIn);
|
|
||||||
void (*str_appendchar)(sqlite3_str*, int N, char C);
|
|
||||||
void (*str_reset)(sqlite3_str*);
|
|
||||||
int (*str_errcode)(sqlite3_str*);
|
|
||||||
int (*str_length)(sqlite3_str*);
|
|
||||||
char *(*str_value)(sqlite3_str*);
|
|
||||||
/* Version 3.25.0 and later */
|
|
||||||
int (*create_window_function)(sqlite3*,const char*,int,int,void*,
|
|
||||||
void (*xStep)(sqlite3_context*,int,sqlite3_value**),
|
|
||||||
void (*xFinal)(sqlite3_context*),
|
|
||||||
void (*xValue)(sqlite3_context*),
|
|
||||||
void (*xInv)(sqlite3_context*,int,sqlite3_value**),
|
|
||||||
void(*xDestroy)(void*));
|
|
||||||
/* Version 3.26.0 and later */
|
|
||||||
const char *(*normalized_sql)(sqlite3_stmt*);
|
|
||||||
/* Version 3.28.0 and later */
|
|
||||||
int (*stmt_isexplain)(sqlite3_stmt*);
|
|
||||||
int (*value_frombind)(sqlite3_value*);
|
|
||||||
/* Version 3.30.0 and later */
|
|
||||||
int (*drop_modules)(sqlite3*,const char**);
|
|
||||||
/* Version 3.31.0 and later */
|
|
||||||
sqlite3_int64 (*hard_heap_limit64)(sqlite3_int64);
|
|
||||||
const char *(*uri_key)(const char*,int);
|
|
||||||
const char *(*filename_database)(const char*);
|
|
||||||
const char *(*filename_journal)(const char*);
|
|
||||||
const char *(*filename_wal)(const char*);
|
|
||||||
/* Version 3.32.0 and later */
|
|
||||||
const char *(*create_filename)(const char*,const char*,const char*,
|
|
||||||
int,const char**);
|
|
||||||
void (*free_filename)(const char*);
|
|
||||||
sqlite3_file *(*database_file_object)(const char*);
|
|
||||||
/* Version 3.34.0 and later */
|
|
||||||
int (*txn_state)(sqlite3*,const char*);
|
|
||||||
/* Version 3.36.1 and later */
|
|
||||||
sqlite3_int64 (*changes64)(sqlite3*);
|
|
||||||
sqlite3_int64 (*total_changes64)(sqlite3*);
|
|
||||||
/* Version 3.37.0 and later */
|
|
||||||
int (*autovacuum_pages)(sqlite3*,
|
|
||||||
unsigned int(*)(void*,const char*,unsigned int,unsigned int,unsigned int),
|
|
||||||
void*, void(*)(void*));
|
|
||||||
/* Version 3.38.0 and later */
|
|
||||||
int (*error_offset)(sqlite3*);
|
|
||||||
int (*vtab_rhs_value)(sqlite3_index_info*,int,sqlite3_value**);
|
|
||||||
int (*vtab_distinct)(sqlite3_index_info*);
|
|
||||||
int (*vtab_in)(sqlite3_index_info*,int,int);
|
|
||||||
int (*vtab_in_first)(sqlite3_value*,sqlite3_value**);
|
|
||||||
int (*vtab_in_next)(sqlite3_value*,sqlite3_value**);
|
|
||||||
/* Version 3.39.0 and later */
|
|
||||||
int (*deserialize)(sqlite3*,const char*,unsigned char*,
|
|
||||||
sqlite3_int64,sqlite3_int64,unsigned);
|
|
||||||
unsigned char *(*serialize)(sqlite3*,const char *,sqlite3_int64*,
|
|
||||||
unsigned int);
|
|
||||||
const char *(*db_name)(sqlite3*,int);
|
|
||||||
/* Version 3.40.0 and later */
|
|
||||||
int (*value_encoding)(sqlite3_value*);
|
|
||||||
/* Version 3.41.0 and later */
|
|
||||||
int (*is_interrupted)(sqlite3*);
|
|
||||||
/* Version 3.43.0 and later */
|
|
||||||
int (*stmt_explain)(sqlite3_stmt*,int);
|
|
||||||
/* Version 3.44.0 and later */
|
|
||||||
void *(*get_clientdata)(sqlite3*,const char*);
|
|
||||||
int (*set_clientdata)(sqlite3*, const char*, void*, void(*)(void*));
|
|
||||||
};
|
|
||||||
|
|
||||||
/*
|
|
||||||
** This is the function signature used for all extension entry points. It
|
|
||||||
** is also defined in the file "loadext.c".
|
|
||||||
*/
|
|
||||||
typedef int (*sqlite3_loadext_entry)(
|
|
||||||
sqlite3 *db, /* Handle to the database. */
|
|
||||||
char **pzErrMsg, /* Used to set error string on failure. */
|
|
||||||
const sqlite3_api_routines *pThunk /* Extension API function pointers. */
|
|
||||||
);
|
|
||||||
|
|
||||||
/*
|
|
||||||
** The following macros redefine the API routines so that they are
|
|
||||||
** redirected through the global sqlite3_api structure.
|
|
||||||
**
|
|
||||||
** This header file is also used by the loadext.c source file
|
|
||||||
** (part of the main SQLite library - not an extension) so that
|
|
||||||
** it can get access to the sqlite3_api_routines structure
|
|
||||||
** definition. But the main library does not want to redefine
|
|
||||||
** the API. So the redefinition macros are only valid if the
|
|
||||||
** SQLITE_CORE macros is undefined.
|
|
||||||
*/
|
|
||||||
#if !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION)
|
|
||||||
#define sqlite3_aggregate_context sqlite3_api->aggregate_context
|
|
||||||
#ifndef SQLITE_OMIT_DEPRECATED
|
|
||||||
#define sqlite3_aggregate_count sqlite3_api->aggregate_count
|
|
||||||
#endif
|
|
||||||
#define sqlite3_bind_blob sqlite3_api->bind_blob
|
|
||||||
#define sqlite3_bind_double sqlite3_api->bind_double
|
|
||||||
#define sqlite3_bind_int sqlite3_api->bind_int
|
|
||||||
#define sqlite3_bind_int64 sqlite3_api->bind_int64
|
|
||||||
#define sqlite3_bind_null sqlite3_api->bind_null
|
|
||||||
#define sqlite3_bind_parameter_count sqlite3_api->bind_parameter_count
|
|
||||||
#define sqlite3_bind_parameter_index sqlite3_api->bind_parameter_index
|
|
||||||
#define sqlite3_bind_parameter_name sqlite3_api->bind_parameter_name
|
|
||||||
#define sqlite3_bind_text sqlite3_api->bind_text
|
|
||||||
#define sqlite3_bind_text16 sqlite3_api->bind_text16
|
|
||||||
#define sqlite3_bind_value sqlite3_api->bind_value
|
|
||||||
#define sqlite3_busy_handler sqlite3_api->busy_handler
|
|
||||||
#define sqlite3_busy_timeout sqlite3_api->busy_timeout
|
|
||||||
#define sqlite3_changes sqlite3_api->changes
|
|
||||||
#define sqlite3_close sqlite3_api->close
|
|
||||||
#define sqlite3_collation_needed sqlite3_api->collation_needed
|
|
||||||
#define sqlite3_collation_needed16 sqlite3_api->collation_needed16
|
|
||||||
#define sqlite3_column_blob sqlite3_api->column_blob
|
|
||||||
#define sqlite3_column_bytes sqlite3_api->column_bytes
|
|
||||||
#define sqlite3_column_bytes16 sqlite3_api->column_bytes16
|
|
||||||
#define sqlite3_column_count sqlite3_api->column_count
|
|
||||||
#define sqlite3_column_database_name sqlite3_api->column_database_name
|
|
||||||
#define sqlite3_column_database_name16 sqlite3_api->column_database_name16
|
|
||||||
#define sqlite3_column_decltype sqlite3_api->column_decltype
|
|
||||||
#define sqlite3_column_decltype16 sqlite3_api->column_decltype16
|
|
||||||
#define sqlite3_column_double sqlite3_api->column_double
|
|
||||||
#define sqlite3_column_int sqlite3_api->column_int
|
|
||||||
#define sqlite3_column_int64 sqlite3_api->column_int64
|
|
||||||
#define sqlite3_column_name sqlite3_api->column_name
|
|
||||||
#define sqlite3_column_name16 sqlite3_api->column_name16
|
|
||||||
#define sqlite3_column_origin_name sqlite3_api->column_origin_name
|
|
||||||
#define sqlite3_column_origin_name16 sqlite3_api->column_origin_name16
|
|
||||||
#define sqlite3_column_table_name sqlite3_api->column_table_name
|
|
||||||
#define sqlite3_column_table_name16 sqlite3_api->column_table_name16
|
|
||||||
#define sqlite3_column_text sqlite3_api->column_text
|
|
||||||
#define sqlite3_column_text16 sqlite3_api->column_text16
|
|
||||||
#define sqlite3_column_type sqlite3_api->column_type
|
|
||||||
#define sqlite3_column_value sqlite3_api->column_value
|
|
||||||
#define sqlite3_commit_hook sqlite3_api->commit_hook
|
|
||||||
#define sqlite3_complete sqlite3_api->complete
|
|
||||||
#define sqlite3_complete16 sqlite3_api->complete16
|
|
||||||
#define sqlite3_create_collation sqlite3_api->create_collation
|
|
||||||
#define sqlite3_create_collation16 sqlite3_api->create_collation16
|
|
||||||
#define sqlite3_create_function sqlite3_api->create_function
|
|
||||||
#define sqlite3_create_function16 sqlite3_api->create_function16
|
|
||||||
#define sqlite3_create_module sqlite3_api->create_module
|
|
||||||
#define sqlite3_create_module_v2 sqlite3_api->create_module_v2
|
|
||||||
#define sqlite3_data_count sqlite3_api->data_count
|
|
||||||
#define sqlite3_db_handle sqlite3_api->db_handle
|
|
||||||
#define sqlite3_declare_vtab sqlite3_api->declare_vtab
|
|
||||||
#define sqlite3_enable_shared_cache sqlite3_api->enable_shared_cache
|
|
||||||
#define sqlite3_errcode sqlite3_api->errcode
|
|
||||||
#define sqlite3_errmsg sqlite3_api->errmsg
|
|
||||||
#define sqlite3_errmsg16 sqlite3_api->errmsg16
|
|
||||||
#define sqlite3_exec sqlite3_api->exec
|
|
||||||
#ifndef SQLITE_OMIT_DEPRECATED
|
|
||||||
#define sqlite3_expired sqlite3_api->expired
|
|
||||||
#endif
|
|
||||||
#define sqlite3_finalize sqlite3_api->finalize
|
|
||||||
#define sqlite3_free sqlite3_api->free
|
|
||||||
#define sqlite3_free_table sqlite3_api->free_table
|
|
||||||
#define sqlite3_get_autocommit sqlite3_api->get_autocommit
|
|
||||||
#define sqlite3_get_auxdata sqlite3_api->get_auxdata
|
|
||||||
#define sqlite3_get_table sqlite3_api->get_table
|
|
||||||
#ifndef SQLITE_OMIT_DEPRECATED
|
|
||||||
#define sqlite3_global_recover sqlite3_api->global_recover
|
|
||||||
#endif
|
|
||||||
#define sqlite3_interrupt sqlite3_api->interruptx
|
|
||||||
#define sqlite3_last_insert_rowid sqlite3_api->last_insert_rowid
|
|
||||||
#define sqlite3_libversion sqlite3_api->libversion
|
|
||||||
#define sqlite3_libversion_number sqlite3_api->libversion_number
|
|
||||||
#define sqlite3_malloc sqlite3_api->malloc
|
|
||||||
#define sqlite3_mprintf sqlite3_api->mprintf
|
|
||||||
#define sqlite3_open sqlite3_api->open
|
|
||||||
#define sqlite3_open16 sqlite3_api->open16
|
|
||||||
#define sqlite3_prepare sqlite3_api->prepare
|
|
||||||
#define sqlite3_prepare16 sqlite3_api->prepare16
|
|
||||||
#define sqlite3_prepare_v2 sqlite3_api->prepare_v2
|
|
||||||
#define sqlite3_prepare16_v2 sqlite3_api->prepare16_v2
|
|
||||||
#define sqlite3_profile sqlite3_api->profile
|
|
||||||
#define sqlite3_progress_handler sqlite3_api->progress_handler
|
|
||||||
#define sqlite3_realloc sqlite3_api->realloc
|
|
||||||
#define sqlite3_reset sqlite3_api->reset
|
|
||||||
#define sqlite3_result_blob sqlite3_api->result_blob
|
|
||||||
#define sqlite3_result_double sqlite3_api->result_double
|
|
||||||
#define sqlite3_result_error sqlite3_api->result_error
|
|
||||||
#define sqlite3_result_error16 sqlite3_api->result_error16
|
|
||||||
#define sqlite3_result_int sqlite3_api->result_int
|
|
||||||
#define sqlite3_result_int64 sqlite3_api->result_int64
|
|
||||||
#define sqlite3_result_null sqlite3_api->result_null
|
|
||||||
#define sqlite3_result_text sqlite3_api->result_text
|
|
||||||
#define sqlite3_result_text16 sqlite3_api->result_text16
|
|
||||||
#define sqlite3_result_text16be sqlite3_api->result_text16be
|
|
||||||
#define sqlite3_result_text16le sqlite3_api->result_text16le
|
|
||||||
#define sqlite3_result_value sqlite3_api->result_value
|
|
||||||
#define sqlite3_rollback_hook sqlite3_api->rollback_hook
|
|
||||||
#define sqlite3_set_authorizer sqlite3_api->set_authorizer
|
|
||||||
#define sqlite3_set_auxdata sqlite3_api->set_auxdata
|
|
||||||
#define sqlite3_snprintf sqlite3_api->xsnprintf
|
|
||||||
#define sqlite3_step sqlite3_api->step
|
|
||||||
#define sqlite3_table_column_metadata sqlite3_api->table_column_metadata
|
|
||||||
#define sqlite3_thread_cleanup sqlite3_api->thread_cleanup
|
|
||||||
#define sqlite3_total_changes sqlite3_api->total_changes
|
|
||||||
#define sqlite3_trace sqlite3_api->trace
|
|
||||||
#ifndef SQLITE_OMIT_DEPRECATED
|
|
||||||
#define sqlite3_transfer_bindings sqlite3_api->transfer_bindings
|
|
||||||
#endif
|
|
||||||
#define sqlite3_update_hook sqlite3_api->update_hook
|
|
||||||
#define sqlite3_user_data sqlite3_api->user_data
|
|
||||||
#define sqlite3_value_blob sqlite3_api->value_blob
|
|
||||||
#define sqlite3_value_bytes sqlite3_api->value_bytes
|
|
||||||
#define sqlite3_value_bytes16 sqlite3_api->value_bytes16
|
|
||||||
#define sqlite3_value_double sqlite3_api->value_double
|
|
||||||
#define sqlite3_value_int sqlite3_api->value_int
|
|
||||||
#define sqlite3_value_int64 sqlite3_api->value_int64
|
|
||||||
#define sqlite3_value_numeric_type sqlite3_api->value_numeric_type
|
|
||||||
#define sqlite3_value_text sqlite3_api->value_text
|
|
||||||
#define sqlite3_value_text16 sqlite3_api->value_text16
|
|
||||||
#define sqlite3_value_text16be sqlite3_api->value_text16be
|
|
||||||
#define sqlite3_value_text16le sqlite3_api->value_text16le
|
|
||||||
#define sqlite3_value_type sqlite3_api->value_type
|
|
||||||
#define sqlite3_vmprintf sqlite3_api->vmprintf
|
|
||||||
#define sqlite3_vsnprintf sqlite3_api->xvsnprintf
|
|
||||||
#define sqlite3_overload_function sqlite3_api->overload_function
|
|
||||||
#define sqlite3_prepare_v2 sqlite3_api->prepare_v2
|
|
||||||
#define sqlite3_prepare16_v2 sqlite3_api->prepare16_v2
|
|
||||||
#define sqlite3_clear_bindings sqlite3_api->clear_bindings
|
|
||||||
#define sqlite3_bind_zeroblob sqlite3_api->bind_zeroblob
|
|
||||||
#define sqlite3_blob_bytes sqlite3_api->blob_bytes
|
|
||||||
#define sqlite3_blob_close sqlite3_api->blob_close
|
|
||||||
#define sqlite3_blob_open sqlite3_api->blob_open
|
|
||||||
#define sqlite3_blob_read sqlite3_api->blob_read
|
|
||||||
#define sqlite3_blob_write sqlite3_api->blob_write
|
|
||||||
#define sqlite3_create_collation_v2 sqlite3_api->create_collation_v2
|
|
||||||
#define sqlite3_file_control sqlite3_api->file_control
|
|
||||||
#define sqlite3_memory_highwater sqlite3_api->memory_highwater
|
|
||||||
#define sqlite3_memory_used sqlite3_api->memory_used
|
|
||||||
#define sqlite3_mutex_alloc sqlite3_api->mutex_alloc
|
|
||||||
#define sqlite3_mutex_enter sqlite3_api->mutex_enter
|
|
||||||
#define sqlite3_mutex_free sqlite3_api->mutex_free
|
|
||||||
#define sqlite3_mutex_leave sqlite3_api->mutex_leave
|
|
||||||
#define sqlite3_mutex_try sqlite3_api->mutex_try
|
|
||||||
#define sqlite3_open_v2 sqlite3_api->open_v2
|
|
||||||
#define sqlite3_release_memory sqlite3_api->release_memory
|
|
||||||
#define sqlite3_result_error_nomem sqlite3_api->result_error_nomem
|
|
||||||
#define sqlite3_result_error_toobig sqlite3_api->result_error_toobig
|
|
||||||
#define sqlite3_sleep sqlite3_api->sleep
|
|
||||||
#define sqlite3_soft_heap_limit sqlite3_api->soft_heap_limit
|
|
||||||
#define sqlite3_vfs_find sqlite3_api->vfs_find
|
|
||||||
#define sqlite3_vfs_register sqlite3_api->vfs_register
|
|
||||||
#define sqlite3_vfs_unregister sqlite3_api->vfs_unregister
|
|
||||||
#define sqlite3_threadsafe sqlite3_api->xthreadsafe
|
|
||||||
#define sqlite3_result_zeroblob sqlite3_api->result_zeroblob
|
|
||||||
#define sqlite3_result_error_code sqlite3_api->result_error_code
|
|
||||||
#define sqlite3_test_control sqlite3_api->test_control
|
|
||||||
#define sqlite3_randomness sqlite3_api->randomness
|
|
||||||
#define sqlite3_context_db_handle sqlite3_api->context_db_handle
|
|
||||||
#define sqlite3_extended_result_codes sqlite3_api->extended_result_codes
|
|
||||||
#define sqlite3_limit sqlite3_api->limit
|
|
||||||
#define sqlite3_next_stmt sqlite3_api->next_stmt
|
|
||||||
#define sqlite3_sql sqlite3_api->sql
|
|
||||||
#define sqlite3_status sqlite3_api->status
|
|
||||||
#define sqlite3_backup_finish sqlite3_api->backup_finish
|
|
||||||
#define sqlite3_backup_init sqlite3_api->backup_init
|
|
||||||
#define sqlite3_backup_pagecount sqlite3_api->backup_pagecount
|
|
||||||
#define sqlite3_backup_remaining sqlite3_api->backup_remaining
|
|
||||||
#define sqlite3_backup_step sqlite3_api->backup_step
|
|
||||||
#define sqlite3_compileoption_get sqlite3_api->compileoption_get
|
|
||||||
#define sqlite3_compileoption_used sqlite3_api->compileoption_used
|
|
||||||
#define sqlite3_create_function_v2 sqlite3_api->create_function_v2
|
|
||||||
#define sqlite3_db_config sqlite3_api->db_config
|
|
||||||
#define sqlite3_db_mutex sqlite3_api->db_mutex
|
|
||||||
#define sqlite3_db_status sqlite3_api->db_status
|
|
||||||
#define sqlite3_extended_errcode sqlite3_api->extended_errcode
|
|
||||||
#define sqlite3_log sqlite3_api->log
|
|
||||||
#define sqlite3_soft_heap_limit64 sqlite3_api->soft_heap_limit64
|
|
||||||
#define sqlite3_sourceid sqlite3_api->sourceid
|
|
||||||
#define sqlite3_stmt_status sqlite3_api->stmt_status
|
|
||||||
#define sqlite3_strnicmp sqlite3_api->strnicmp
|
|
||||||
#define sqlite3_unlock_notify sqlite3_api->unlock_notify
|
|
||||||
#define sqlite3_wal_autocheckpoint sqlite3_api->wal_autocheckpoint
|
|
||||||
#define sqlite3_wal_checkpoint sqlite3_api->wal_checkpoint
|
|
||||||
#define sqlite3_wal_hook sqlite3_api->wal_hook
|
|
||||||
#define sqlite3_blob_reopen sqlite3_api->blob_reopen
|
|
||||||
#define sqlite3_vtab_config sqlite3_api->vtab_config
|
|
||||||
#define sqlite3_vtab_on_conflict sqlite3_api->vtab_on_conflict
|
|
||||||
/* Version 3.7.16 and later */
|
|
||||||
#define sqlite3_close_v2 sqlite3_api->close_v2
|
|
||||||
#define sqlite3_db_filename sqlite3_api->db_filename
|
|
||||||
#define sqlite3_db_readonly sqlite3_api->db_readonly
|
|
||||||
#define sqlite3_db_release_memory sqlite3_api->db_release_memory
|
|
||||||
#define sqlite3_errstr sqlite3_api->errstr
|
|
||||||
#define sqlite3_stmt_busy sqlite3_api->stmt_busy
|
|
||||||
#define sqlite3_stmt_readonly sqlite3_api->stmt_readonly
|
|
||||||
#define sqlite3_stricmp sqlite3_api->stricmp
|
|
||||||
#define sqlite3_uri_boolean sqlite3_api->uri_boolean
|
|
||||||
#define sqlite3_uri_int64 sqlite3_api->uri_int64
|
|
||||||
#define sqlite3_uri_parameter sqlite3_api->uri_parameter
|
|
||||||
#define sqlite3_uri_vsnprintf sqlite3_api->xvsnprintf
|
|
||||||
#define sqlite3_wal_checkpoint_v2 sqlite3_api->wal_checkpoint_v2
|
|
||||||
/* Version 3.8.7 and later */
|
|
||||||
#define sqlite3_auto_extension sqlite3_api->auto_extension
|
|
||||||
#define sqlite3_bind_blob64 sqlite3_api->bind_blob64
|
|
||||||
#define sqlite3_bind_text64 sqlite3_api->bind_text64
|
|
||||||
#define sqlite3_cancel_auto_extension sqlite3_api->cancel_auto_extension
|
|
||||||
#define sqlite3_load_extension sqlite3_api->load_extension
|
|
||||||
#define sqlite3_malloc64 sqlite3_api->malloc64
|
|
||||||
#define sqlite3_msize sqlite3_api->msize
|
|
||||||
#define sqlite3_realloc64 sqlite3_api->realloc64
|
|
||||||
#define sqlite3_reset_auto_extension sqlite3_api->reset_auto_extension
|
|
||||||
#define sqlite3_result_blob64 sqlite3_api->result_blob64
|
|
||||||
#define sqlite3_result_text64 sqlite3_api->result_text64
|
|
||||||
#define sqlite3_strglob sqlite3_api->strglob
|
|
||||||
/* Version 3.8.11 and later */
|
|
||||||
#define sqlite3_value_dup sqlite3_api->value_dup
|
|
||||||
#define sqlite3_value_free sqlite3_api->value_free
|
|
||||||
#define sqlite3_result_zeroblob64 sqlite3_api->result_zeroblob64
|
|
||||||
#define sqlite3_bind_zeroblob64 sqlite3_api->bind_zeroblob64
|
|
||||||
/* Version 3.9.0 and later */
|
|
||||||
#define sqlite3_value_subtype sqlite3_api->value_subtype
|
|
||||||
#define sqlite3_result_subtype sqlite3_api->result_subtype
|
|
||||||
/* Version 3.10.0 and later */
|
|
||||||
#define sqlite3_status64 sqlite3_api->status64
|
|
||||||
#define sqlite3_strlike sqlite3_api->strlike
|
|
||||||
#define sqlite3_db_cacheflush sqlite3_api->db_cacheflush
|
|
||||||
/* Version 3.12.0 and later */
|
|
||||||
#define sqlite3_system_errno sqlite3_api->system_errno
|
|
||||||
/* Version 3.14.0 and later */
|
|
||||||
#define sqlite3_trace_v2 sqlite3_api->trace_v2
|
|
||||||
#define sqlite3_expanded_sql sqlite3_api->expanded_sql
|
|
||||||
/* Version 3.18.0 and later */
|
|
||||||
#define sqlite3_set_last_insert_rowid sqlite3_api->set_last_insert_rowid
|
|
||||||
/* Version 3.20.0 and later */
|
|
||||||
#define sqlite3_prepare_v3 sqlite3_api->prepare_v3
|
|
||||||
#define sqlite3_prepare16_v3 sqlite3_api->prepare16_v3
|
|
||||||
#define sqlite3_bind_pointer sqlite3_api->bind_pointer
|
|
||||||
#define sqlite3_result_pointer sqlite3_api->result_pointer
|
|
||||||
#define sqlite3_value_pointer sqlite3_api->value_pointer
|
|
||||||
/* Version 3.22.0 and later */
|
|
||||||
#define sqlite3_vtab_nochange sqlite3_api->vtab_nochange
|
|
||||||
#define sqlite3_value_nochange sqlite3_api->value_nochange
|
|
||||||
#define sqlite3_vtab_collation sqlite3_api->vtab_collation
|
|
||||||
/* Version 3.24.0 and later */
|
|
||||||
#define sqlite3_keyword_count sqlite3_api->keyword_count
|
|
||||||
#define sqlite3_keyword_name sqlite3_api->keyword_name
|
|
||||||
#define sqlite3_keyword_check sqlite3_api->keyword_check
|
|
||||||
#define sqlite3_str_new sqlite3_api->str_new
|
|
||||||
#define sqlite3_str_finish sqlite3_api->str_finish
|
|
||||||
#define sqlite3_str_appendf sqlite3_api->str_appendf
|
|
||||||
#define sqlite3_str_vappendf sqlite3_api->str_vappendf
|
|
||||||
#define sqlite3_str_append sqlite3_api->str_append
|
|
||||||
#define sqlite3_str_appendall sqlite3_api->str_appendall
|
|
||||||
#define sqlite3_str_appendchar sqlite3_api->str_appendchar
|
|
||||||
#define sqlite3_str_reset sqlite3_api->str_reset
|
|
||||||
#define sqlite3_str_errcode sqlite3_api->str_errcode
|
|
||||||
#define sqlite3_str_length sqlite3_api->str_length
|
|
||||||
#define sqlite3_str_value sqlite3_api->str_value
|
|
||||||
/* Version 3.25.0 and later */
|
|
||||||
#define sqlite3_create_window_function sqlite3_api->create_window_function
|
|
||||||
/* Version 3.26.0 and later */
|
|
||||||
#define sqlite3_normalized_sql sqlite3_api->normalized_sql
|
|
||||||
/* Version 3.28.0 and later */
|
|
||||||
#define sqlite3_stmt_isexplain sqlite3_api->stmt_isexplain
|
|
||||||
#define sqlite3_value_frombind sqlite3_api->value_frombind
|
|
||||||
/* Version 3.30.0 and later */
|
|
||||||
#define sqlite3_drop_modules sqlite3_api->drop_modules
|
|
||||||
/* Version 3.31.0 and later */
|
|
||||||
#define sqlite3_hard_heap_limit64 sqlite3_api->hard_heap_limit64
|
|
||||||
#define sqlite3_uri_key sqlite3_api->uri_key
|
|
||||||
#define sqlite3_filename_database sqlite3_api->filename_database
|
|
||||||
#define sqlite3_filename_journal sqlite3_api->filename_journal
|
|
||||||
#define sqlite3_filename_wal sqlite3_api->filename_wal
|
|
||||||
/* Version 3.32.0 and later */
|
|
||||||
#define sqlite3_create_filename sqlite3_api->create_filename
|
|
||||||
#define sqlite3_free_filename sqlite3_api->free_filename
|
|
||||||
#define sqlite3_database_file_object sqlite3_api->database_file_object
|
|
||||||
/* Version 3.34.0 and later */
|
|
||||||
#define sqlite3_txn_state sqlite3_api->txn_state
|
|
||||||
/* Version 3.36.1 and later */
|
|
||||||
#define sqlite3_changes64 sqlite3_api->changes64
|
|
||||||
#define sqlite3_total_changes64 sqlite3_api->total_changes64
|
|
||||||
/* Version 3.37.0 and later */
|
|
||||||
#define sqlite3_autovacuum_pages sqlite3_api->autovacuum_pages
|
|
||||||
/* Version 3.38.0 and later */
|
|
||||||
#define sqlite3_error_offset sqlite3_api->error_offset
|
|
||||||
#define sqlite3_vtab_rhs_value sqlite3_api->vtab_rhs_value
|
|
||||||
#define sqlite3_vtab_distinct sqlite3_api->vtab_distinct
|
|
||||||
#define sqlite3_vtab_in sqlite3_api->vtab_in
|
|
||||||
#define sqlite3_vtab_in_first sqlite3_api->vtab_in_first
|
|
||||||
#define sqlite3_vtab_in_next sqlite3_api->vtab_in_next
|
|
||||||
/* Version 3.39.0 and later */
|
|
||||||
#ifndef SQLITE_OMIT_DESERIALIZE
|
|
||||||
#define sqlite3_deserialize sqlite3_api->deserialize
|
|
||||||
#define sqlite3_serialize sqlite3_api->serialize
|
|
||||||
#endif
|
|
||||||
#define sqlite3_db_name sqlite3_api->db_name
|
|
||||||
/* Version 3.40.0 and later */
|
|
||||||
#define sqlite3_value_encoding sqlite3_api->value_encoding
|
|
||||||
/* Version 3.41.0 and later */
|
|
||||||
#define sqlite3_is_interrupted sqlite3_api->is_interrupted
|
|
||||||
/* Version 3.43.0 and later */
|
|
||||||
#define sqlite3_stmt_explain sqlite3_api->stmt_explain
|
|
||||||
/* Version 3.44.0 and later */
|
|
||||||
#define sqlite3_get_clientdata sqlite3_api->get_clientdata
|
|
||||||
#define sqlite3_set_clientdata sqlite3_api->set_clientdata
|
|
||||||
#endif /* !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION) */
|
|
||||||
|
|
||||||
#if !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION)
|
|
||||||
/* This case when the file really is being compiled as a loadable
|
|
||||||
** extension */
|
|
||||||
# define SQLITE_EXTENSION_INIT1 const sqlite3_api_routines *sqlite3_api=0;
|
|
||||||
# define SQLITE_EXTENSION_INIT2(v) sqlite3_api=v;
|
|
||||||
# define SQLITE_EXTENSION_INIT3 \
|
|
||||||
extern const sqlite3_api_routines *sqlite3_api;
|
|
||||||
#else
|
|
||||||
/* This case when the file is being statically linked into the
|
|
||||||
** application */
|
|
||||||
# define SQLITE_EXTENSION_INIT1 /*no-op*/
|
|
||||||
# define SQLITE_EXTENSION_INIT2(v) (void)v; /* unused parameter */
|
|
||||||
# define SQLITE_EXTENSION_INIT3 /*no-op*/
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif /* SQLITE3EXT_H */
|
|
||||||
655
src/sqlite/vfs.c
655
src/sqlite/vfs.c
@ -1,655 +0,0 @@
|
|||||||
/*
|
|
||||||
** 2010 April 7
|
|
||||||
**
|
|
||||||
** The author disclaims copyright to this source code. In place of
|
|
||||||
** a legal notice, here is a blessing:
|
|
||||||
**
|
|
||||||
** May you do good and not evil.
|
|
||||||
** May you find forgiveness for yourself and forgive others.
|
|
||||||
** May you share freely, never taking more than you give.
|
|
||||||
**
|
|
||||||
*************************************************************************
|
|
||||||
**
|
|
||||||
** This file implements an example of a simple VFS implementation that
|
|
||||||
** omits complex features often not required or not possible on embedded
|
|
||||||
** platforms. Code is included to buffer writes to the journal file,
|
|
||||||
** which can be a significant performance improvement on some embedded
|
|
||||||
** platforms.
|
|
||||||
**
|
|
||||||
** OVERVIEW
|
|
||||||
**
|
|
||||||
** The code in this file implements a minimal SQLite VFS that can be
|
|
||||||
** used on Linux and other posix-like operating systems. The following
|
|
||||||
** system calls are used:
|
|
||||||
**
|
|
||||||
** File-system: access(), unlink(), getcwd()
|
|
||||||
** File IO: open(), read(), write(), fsync(), close(), fstat()
|
|
||||||
** Other: sleep(), usleep(), time()
|
|
||||||
**
|
|
||||||
** The following VFS features are omitted:
|
|
||||||
**
|
|
||||||
** 1. File locking. The user must ensure that there is at most one
|
|
||||||
** connection to each database when using this VFS. Multiple
|
|
||||||
** connections to a single shared-cache count as a single connection
|
|
||||||
** for the purposes of the previous statement.
|
|
||||||
**
|
|
||||||
** 2. The loading of dynamic extensions (shared libraries).
|
|
||||||
**
|
|
||||||
** 3. Temporary files. The user must configure SQLite to use in-memory
|
|
||||||
** temp files when using this VFS. The easiest way to do this is to
|
|
||||||
** compile with:
|
|
||||||
**
|
|
||||||
** -DSQLITE_TEMP_STORE=3
|
|
||||||
**
|
|
||||||
** 4. File truncation. As of version 3.6.24, SQLite may run without
|
|
||||||
** a working xTruncate() call, providing the user does not configure
|
|
||||||
** SQLite to use "journal_mode=truncate", or use both
|
|
||||||
** "journal_mode=persist" and ATTACHed databases.
|
|
||||||
**
|
|
||||||
** It is assumed that the system uses UNIX-like path-names. Specifically,
|
|
||||||
** that '/' characters are used to separate path components and that
|
|
||||||
** a path-name is a relative path unless it begins with a '/'. And that
|
|
||||||
** no UTF-8 encoded paths are greater than 512 bytes in length.
|
|
||||||
**
|
|
||||||
** JOURNAL WRITE-BUFFERING
|
|
||||||
**
|
|
||||||
** To commit a transaction to the database, SQLite first writes rollback
|
|
||||||
** information into the journal file. This usually consists of 4 steps:
|
|
||||||
**
|
|
||||||
** 1. The rollback information is sequentially written into the journal
|
|
||||||
** file, starting at the start of the file.
|
|
||||||
** 2. The journal file is synced to disk.
|
|
||||||
** 3. A modification is made to the first few bytes of the journal file.
|
|
||||||
** 4. The journal file is synced to disk again.
|
|
||||||
**
|
|
||||||
** Most of the data is written in step 1 using a series of calls to the
|
|
||||||
** VFS xWrite() method. The buffers passed to the xWrite() calls are of
|
|
||||||
** various sizes. For example, as of version 3.6.24, when committing a
|
|
||||||
** transaction that modifies 3 pages of a database file that uses 4096
|
|
||||||
** byte pages residing on a media with 512 byte sectors, SQLite makes
|
|
||||||
** eleven calls to the xWrite() method to create the rollback journal,
|
|
||||||
** as follows:
|
|
||||||
**
|
|
||||||
** Write offset | Bytes written
|
|
||||||
** ----------------------------
|
|
||||||
** 0 512
|
|
||||||
** 512 4
|
|
||||||
** 516 4096
|
|
||||||
** 4612 4
|
|
||||||
** 4616 4
|
|
||||||
** 4620 4096
|
|
||||||
** 8716 4
|
|
||||||
** 8720 4
|
|
||||||
** 8724 4096
|
|
||||||
** 12820 4
|
|
||||||
** ++++++++++++SYNC+++++++++++
|
|
||||||
** 0 12
|
|
||||||
** ++++++++++++SYNC+++++++++++
|
|
||||||
**
|
|
||||||
** On many operating systems, this is an efficient way to write to a file.
|
|
||||||
** However, on some embedded systems that do not cache writes in OS
|
|
||||||
** buffers it is much more efficient to write data in blocks that are
|
|
||||||
** an integer multiple of the sector-size in size and aligned at the
|
|
||||||
** start of a sector.
|
|
||||||
**
|
|
||||||
** To work around this, the code in this file allocates a fixed size
|
|
||||||
** buffer of SQLITE_DEMOVFS_BUFFERSZ using sqlite3_malloc() whenever a
|
|
||||||
** journal file is opened. It uses the buffer to coalesce sequential
|
|
||||||
** writes into aligned SQLITE_DEMOVFS_BUFFERSZ blocks. When SQLite
|
|
||||||
** invokes the xSync() method to sync the contents of the file to disk,
|
|
||||||
** all accumulated data is written out, even if it does not constitute
|
|
||||||
** a complete block. This means the actual IO to create the rollback
|
|
||||||
** journal for the example transaction above is this:
|
|
||||||
**
|
|
||||||
** Write offset | Bytes written
|
|
||||||
** ----------------------------
|
|
||||||
** 0 8192
|
|
||||||
** 8192 4632
|
|
||||||
** ++++++++++++SYNC+++++++++++
|
|
||||||
** 0 12
|
|
||||||
** ++++++++++++SYNC+++++++++++
|
|
||||||
**
|
|
||||||
** Much more efficient if the underlying OS is not caching write
|
|
||||||
** operations.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*removed tests from https://www.sqlite.org/src/doc/trunk/src/test_demovfs.c*/
|
|
||||||
|
|
||||||
#if defined(GEKKO) || defined(__SWITCH__)
|
|
||||||
|
|
||||||
#include "sqlite3.h"
|
|
||||||
|
|
||||||
#include <assert.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <sys/stat.h>
|
|
||||||
#include <sys/file.h>
|
|
||||||
#include <sys/param.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <time.h>
|
|
||||||
#include <errno.h>
|
|
||||||
#include <fcntl.h>
|
|
||||||
|
|
||||||
/*
|
|
||||||
** Size of the write buffer used by journal files in bytes.
|
|
||||||
*/
|
|
||||||
#ifndef SQLITE_DEMOVFS_BUFFERSZ
|
|
||||||
# define SQLITE_DEMOVFS_BUFFERSZ 8192
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*
|
|
||||||
** The maximum pathname length supported by this VFS.
|
|
||||||
*/
|
|
||||||
#define MAXPATHNAME 512
|
|
||||||
|
|
||||||
/*
|
|
||||||
** When using this VFS, the sqlite3_file* handles that SQLite uses are
|
|
||||||
** actually pointers to instances of type DemoFile.
|
|
||||||
*/
|
|
||||||
typedef struct DemoFile DemoFile;
|
|
||||||
struct DemoFile {
|
|
||||||
sqlite3_file base; /* Base class. Must be first. */
|
|
||||||
int fd; /* File descriptor */
|
|
||||||
|
|
||||||
char *aBuffer; /* Pointer to malloc'd buffer */
|
|
||||||
int nBuffer; /* Valid bytes of data in zBuffer */
|
|
||||||
sqlite3_int64 iBufferOfst; /* Offset in file of zBuffer[0] */
|
|
||||||
};
|
|
||||||
|
|
||||||
/*
|
|
||||||
** Write directly to the file passed as the first argument. Even if the
|
|
||||||
** file has a write-buffer (DemoFile.aBuffer), ignore it.
|
|
||||||
*/
|
|
||||||
static int demoDirectWrite(
|
|
||||||
DemoFile *p, /* File handle */
|
|
||||||
const void *zBuf, /* Buffer containing data to write */
|
|
||||||
int iAmt, /* Size of data to write in bytes */
|
|
||||||
sqlite_int64 iOfst /* File offset to write to */
|
|
||||||
){
|
|
||||||
off_t ofst; /* Return value from lseek() */
|
|
||||||
size_t nWrite; /* Return value from write() */
|
|
||||||
|
|
||||||
ofst = lseek(p->fd, iOfst, SEEK_SET);
|
|
||||||
if( ofst!=iOfst ){
|
|
||||||
return SQLITE_IOERR_WRITE;
|
|
||||||
}
|
|
||||||
|
|
||||||
nWrite = write(p->fd, zBuf, iAmt);
|
|
||||||
if( nWrite!=iAmt ){
|
|
||||||
return SQLITE_IOERR_WRITE;
|
|
||||||
}
|
|
||||||
|
|
||||||
return SQLITE_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
** Flush the contents of the DemoFile.aBuffer buffer to disk. This is a
|
|
||||||
** no-op if this particular file does not have a buffer (i.e. it is not
|
|
||||||
** a journal file) or if the buffer is currently empty.
|
|
||||||
*/
|
|
||||||
static int demoFlushBuffer(DemoFile *p){
|
|
||||||
int rc = SQLITE_OK;
|
|
||||||
if( p->nBuffer ){
|
|
||||||
rc = demoDirectWrite(p, p->aBuffer, p->nBuffer, p->iBufferOfst);
|
|
||||||
p->nBuffer = 0;
|
|
||||||
}
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
** Close a file.
|
|
||||||
*/
|
|
||||||
static int demoClose(sqlite3_file *pFile){
|
|
||||||
int rc;
|
|
||||||
DemoFile *p = (DemoFile*)pFile;
|
|
||||||
rc = demoFlushBuffer(p);
|
|
||||||
sqlite3_free(p->aBuffer);
|
|
||||||
close(p->fd);
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
** Read data from a file.
|
|
||||||
*/
|
|
||||||
static int demoRead(
|
|
||||||
sqlite3_file *pFile,
|
|
||||||
void *zBuf,
|
|
||||||
int iAmt,
|
|
||||||
sqlite_int64 iOfst
|
|
||||||
){
|
|
||||||
DemoFile *p = (DemoFile*)pFile;
|
|
||||||
off_t ofst; /* Return value from lseek() */
|
|
||||||
int nRead; /* Return value from read() */
|
|
||||||
int rc; /* Return code from demoFlushBuffer() */
|
|
||||||
|
|
||||||
/* Flush any data in the write buffer to disk in case this operation
|
|
||||||
** is trying to read data the file-region currently cached in the buffer.
|
|
||||||
** It would be possible to detect this case and possibly save an
|
|
||||||
** unnecessary write here, but in practice SQLite will rarely read from
|
|
||||||
** a journal file when there is data cached in the write-buffer.
|
|
||||||
*/
|
|
||||||
rc = demoFlushBuffer(p);
|
|
||||||
if( rc!=SQLITE_OK ){
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
ofst = lseek(p->fd, iOfst, SEEK_SET);
|
|
||||||
if( ofst!=iOfst ){
|
|
||||||
return SQLITE_IOERR_READ;
|
|
||||||
}
|
|
||||||
nRead = read(p->fd, zBuf, iAmt);
|
|
||||||
|
|
||||||
if( nRead==iAmt ){
|
|
||||||
return SQLITE_OK;
|
|
||||||
}else if( nRead>=0 ){
|
|
||||||
if( nRead<iAmt ){
|
|
||||||
memset(&((char*)zBuf)[nRead], 0, iAmt-nRead);
|
|
||||||
}
|
|
||||||
return SQLITE_IOERR_SHORT_READ;
|
|
||||||
}
|
|
||||||
|
|
||||||
return SQLITE_IOERR_READ;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
** Write data to a crash-file.
|
|
||||||
*/
|
|
||||||
static int demoWrite(
|
|
||||||
sqlite3_file *pFile,
|
|
||||||
const void *zBuf,
|
|
||||||
int iAmt,
|
|
||||||
sqlite_int64 iOfst
|
|
||||||
){
|
|
||||||
DemoFile *p = (DemoFile*)pFile;
|
|
||||||
|
|
||||||
if( p->aBuffer ){
|
|
||||||
char *z = (char *)zBuf; /* Pointer to remaining data to write */
|
|
||||||
int n = iAmt; /* Number of bytes at z */
|
|
||||||
sqlite3_int64 i = iOfst; /* File offset to write to */
|
|
||||||
|
|
||||||
while( n>0 ){
|
|
||||||
int nCopy; /* Number of bytes to copy into buffer */
|
|
||||||
|
|
||||||
/* If the buffer is full, or if this data is not being written directly
|
|
||||||
** following the data already buffered, flush the buffer. Flushing
|
|
||||||
** the buffer is a no-op if it is empty.
|
|
||||||
*/
|
|
||||||
if( p->nBuffer==SQLITE_DEMOVFS_BUFFERSZ || p->iBufferOfst+p->nBuffer!=i ){
|
|
||||||
int rc = demoFlushBuffer(p);
|
|
||||||
if( rc!=SQLITE_OK ){
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
assert( p->nBuffer==0 || p->iBufferOfst+p->nBuffer==i );
|
|
||||||
p->iBufferOfst = i - p->nBuffer;
|
|
||||||
|
|
||||||
/* Copy as much data as possible into the buffer. */
|
|
||||||
nCopy = SQLITE_DEMOVFS_BUFFERSZ - p->nBuffer;
|
|
||||||
if( nCopy>n ){
|
|
||||||
nCopy = n;
|
|
||||||
}
|
|
||||||
memcpy(&p->aBuffer[p->nBuffer], z, nCopy);
|
|
||||||
p->nBuffer += nCopy;
|
|
||||||
|
|
||||||
n -= nCopy;
|
|
||||||
i += nCopy;
|
|
||||||
z += nCopy;
|
|
||||||
}
|
|
||||||
}else{
|
|
||||||
return demoDirectWrite(p, zBuf, iAmt, iOfst);
|
|
||||||
}
|
|
||||||
|
|
||||||
return SQLITE_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
** Truncate a file. This is a no-op for this VFS (see header comments at
|
|
||||||
** the top of the file).
|
|
||||||
*/
|
|
||||||
static int demoTruncate(sqlite3_file *pFile, sqlite_int64 size){
|
|
||||||
#if 0
|
|
||||||
if( ftruncate(((DemoFile *)pFile)->fd, size) ) return SQLITE_IOERR_TRUNCATE;
|
|
||||||
#endif
|
|
||||||
return SQLITE_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
** Sync the contents of the file to the persistent media.
|
|
||||||
*/
|
|
||||||
static int demoSync(sqlite3_file *pFile, int flags){
|
|
||||||
DemoFile *p = (DemoFile*)pFile;
|
|
||||||
int rc;
|
|
||||||
|
|
||||||
rc = demoFlushBuffer(p);
|
|
||||||
if( rc!=SQLITE_OK ){
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
rc = fsync(p->fd);
|
|
||||||
return (rc==0 ? SQLITE_OK : SQLITE_IOERR_FSYNC);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
** Write the size of the file in bytes to *pSize.
|
|
||||||
*/
|
|
||||||
static int demoFileSize(sqlite3_file *pFile, sqlite_int64 *pSize){
|
|
||||||
DemoFile *p = (DemoFile*)pFile;
|
|
||||||
int rc; /* Return code from fstat() call */
|
|
||||||
struct stat sStat; /* Output of fstat() call */
|
|
||||||
|
|
||||||
/* Flush the contents of the buffer to disk. As with the flush in the
|
|
||||||
** demoRead() method, it would be possible to avoid this and save a write
|
|
||||||
** here and there. But in practice this comes up so infrequently it is
|
|
||||||
** not worth the trouble.
|
|
||||||
*/
|
|
||||||
rc = demoFlushBuffer(p);
|
|
||||||
if( rc!=SQLITE_OK ){
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
rc = fstat(p->fd, &sStat);
|
|
||||||
if( rc!=0 ) return SQLITE_IOERR_FSTAT;
|
|
||||||
*pSize = sStat.st_size;
|
|
||||||
return SQLITE_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
** Locking functions. The xLock() and xUnlock() methods are both no-ops.
|
|
||||||
** The xCheckReservedLock() always indicates that no other process holds
|
|
||||||
** a reserved lock on the database file. This ensures that if a hot-journal
|
|
||||||
** file is found in the file-system it is rolled back.
|
|
||||||
*/
|
|
||||||
static int demoLock(sqlite3_file *pFile, int eLock){
|
|
||||||
return SQLITE_OK;
|
|
||||||
}
|
|
||||||
static int demoUnlock(sqlite3_file *pFile, int eLock){
|
|
||||||
return SQLITE_OK;
|
|
||||||
}
|
|
||||||
static int demoCheckReservedLock(sqlite3_file *pFile, int *pResOut){
|
|
||||||
*pResOut = 0;
|
|
||||||
return SQLITE_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
** No xFileControl() verbs are implemented by this VFS.
|
|
||||||
*/
|
|
||||||
static int demoFileControl(sqlite3_file *pFile, int op, void *pArg){
|
|
||||||
return SQLITE_NOTFOUND;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
** The xSectorSize() and xDeviceCharacteristics() methods. These two
|
|
||||||
** may return special values allowing SQLite to optimize file-system
|
|
||||||
** access to some extent. But it is also safe to simply return 0.
|
|
||||||
*/
|
|
||||||
static int demoSectorSize(sqlite3_file *pFile){
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
static int demoDeviceCharacteristics(sqlite3_file *pFile){
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
** Open a file handle.
|
|
||||||
*/
|
|
||||||
static int demoOpen(
|
|
||||||
sqlite3_vfs *pVfs, /* VFS */
|
|
||||||
const char *zName, /* File to open, or 0 for a temp file */
|
|
||||||
sqlite3_file *pFile, /* Pointer to DemoFile struct to populate */
|
|
||||||
int flags, /* Input SQLITE_OPEN_XXX flags */
|
|
||||||
int *pOutFlags /* Output SQLITE_OPEN_XXX flags (or NULL) */
|
|
||||||
){
|
|
||||||
static const sqlite3_io_methods demoio = {
|
|
||||||
1, /* iVersion */
|
|
||||||
demoClose, /* xClose */
|
|
||||||
demoRead, /* xRead */
|
|
||||||
demoWrite, /* xWrite */
|
|
||||||
demoTruncate, /* xTruncate */
|
|
||||||
demoSync, /* xSync */
|
|
||||||
demoFileSize, /* xFileSize */
|
|
||||||
demoLock, /* xLock */
|
|
||||||
demoUnlock, /* xUnlock */
|
|
||||||
demoCheckReservedLock, /* xCheckReservedLock */
|
|
||||||
demoFileControl, /* xFileControl */
|
|
||||||
demoSectorSize, /* xSectorSize */
|
|
||||||
demoDeviceCharacteristics /* xDeviceCharacteristics */
|
|
||||||
};
|
|
||||||
|
|
||||||
DemoFile *p = (DemoFile*)pFile; /* Populate this structure */
|
|
||||||
int oflags = 0; /* flags to pass to open() call */
|
|
||||||
char *aBuf = 0;
|
|
||||||
|
|
||||||
if( zName==0 ){
|
|
||||||
return SQLITE_IOERR;
|
|
||||||
}
|
|
||||||
|
|
||||||
if( flags&SQLITE_OPEN_MAIN_JOURNAL ){
|
|
||||||
aBuf = (char *)sqlite3_malloc(SQLITE_DEMOVFS_BUFFERSZ);
|
|
||||||
if( !aBuf ){
|
|
||||||
return SQLITE_NOMEM;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if( flags&SQLITE_OPEN_EXCLUSIVE ) oflags |= O_EXCL;
|
|
||||||
if( flags&SQLITE_OPEN_CREATE ) oflags |= O_CREAT;
|
|
||||||
if( flags&SQLITE_OPEN_READONLY ) oflags |= O_RDONLY;
|
|
||||||
if( flags&SQLITE_OPEN_READWRITE ) oflags |= O_RDWR;
|
|
||||||
|
|
||||||
memset(p, 0, sizeof(DemoFile));
|
|
||||||
p->fd = open(zName, oflags);
|
|
||||||
if( p->fd<0 ){
|
|
||||||
sqlite3_free(aBuf);
|
|
||||||
return SQLITE_CANTOPEN;
|
|
||||||
}
|
|
||||||
p->aBuffer = aBuf;
|
|
||||||
|
|
||||||
if( pOutFlags ){
|
|
||||||
*pOutFlags = flags;
|
|
||||||
}
|
|
||||||
p->base.pMethods = &demoio;
|
|
||||||
return SQLITE_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
** Delete the file identified by argument zPath. If the dirSync parameter
|
|
||||||
** is non-zero, then ensure the file-system modification to delete the
|
|
||||||
** file has been synced to disk before returning.
|
|
||||||
*/
|
|
||||||
static int demoDelete(sqlite3_vfs *pVfs, const char *zPath, int dirSync){
|
|
||||||
int rc; /* Return code */
|
|
||||||
|
|
||||||
rc = unlink(zPath);
|
|
||||||
if( rc!=0 && errno==ENOENT ) return SQLITE_OK;
|
|
||||||
|
|
||||||
if( rc==0 && dirSync ){
|
|
||||||
int dfd; /* File descriptor open on directory */
|
|
||||||
char *zSlash;
|
|
||||||
char zDir[MAXPATHNAME+1]; /* Name of directory containing file zPath */
|
|
||||||
|
|
||||||
/* Figure out the directory name from the path of the file deleted. */
|
|
||||||
sqlite3_snprintf(MAXPATHNAME, zDir, "%s", zPath);
|
|
||||||
zDir[MAXPATHNAME] = '\0';
|
|
||||||
zSlash = strrchr(zDir,'/');
|
|
||||||
if( zSlash ){
|
|
||||||
/* Open a file-descriptor on the directory. Sync. Close. */
|
|
||||||
zSlash[0] = 0;
|
|
||||||
dfd = open(zDir, O_RDONLY, 0);
|
|
||||||
if( dfd<0 ){
|
|
||||||
rc = -1;
|
|
||||||
}else{
|
|
||||||
rc = fsync(dfd);
|
|
||||||
close(dfd);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return (rc==0 ? SQLITE_OK : SQLITE_IOERR_DELETE);
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifndef F_OK
|
|
||||||
# define F_OK 0
|
|
||||||
#endif
|
|
||||||
#ifndef R_OK
|
|
||||||
# define R_OK 4
|
|
||||||
#endif
|
|
||||||
#ifndef W_OK
|
|
||||||
# define W_OK 2
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*
|
|
||||||
** Query the file-system to see if the named file exists, is readable or
|
|
||||||
** is both readable and writable.
|
|
||||||
*/
|
|
||||||
static int demoAccess(
|
|
||||||
sqlite3_vfs *pVfs,
|
|
||||||
const char *zPath,
|
|
||||||
int flags,
|
|
||||||
int *pResOut
|
|
||||||
){
|
|
||||||
int rc; /* access() return code */
|
|
||||||
int eAccess = F_OK; /* Second argument to access() */
|
|
||||||
|
|
||||||
assert( flags==SQLITE_ACCESS_EXISTS /* access(zPath, F_OK) */
|
|
||||||
|| flags==SQLITE_ACCESS_READ /* access(zPath, R_OK) */
|
|
||||||
|| flags==SQLITE_ACCESS_READWRITE /* access(zPath, R_OK|W_OK) */
|
|
||||||
);
|
|
||||||
|
|
||||||
if( flags==SQLITE_ACCESS_READWRITE ) eAccess = R_OK|W_OK;
|
|
||||||
if( flags==SQLITE_ACCESS_READ ) eAccess = R_OK;
|
|
||||||
|
|
||||||
rc = access(zPath, eAccess);
|
|
||||||
*pResOut = (rc==0);
|
|
||||||
return SQLITE_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
** Argument zPath points to a nul-terminated string containing a file path.
|
|
||||||
** If zPath is an absolute path, then it is copied as is into the output
|
|
||||||
** buffer. Otherwise, if it is a relative path, then the equivalent full
|
|
||||||
** path is written to the output buffer.
|
|
||||||
**
|
|
||||||
** This function assumes that paths are UNIX style. Specifically, that:
|
|
||||||
**
|
|
||||||
** 1. Path components are separated by a '/'. and
|
|
||||||
** 2. Full paths begin with a '/' character.
|
|
||||||
*/
|
|
||||||
static int demoFullPathname(
|
|
||||||
sqlite3_vfs *pVfs, /* VFS */
|
|
||||||
const char *zPath, /* Input path (possibly a relative path) */
|
|
||||||
int nPathOut, /* Size of output buffer in bytes */
|
|
||||||
char *zPathOut /* Pointer to output buffer */
|
|
||||||
){
|
|
||||||
char zDir[MAXPATHNAME+1];
|
|
||||||
if( zPath[0]=='/' ){
|
|
||||||
zDir[0] = '\0';
|
|
||||||
}else{
|
|
||||||
if( getcwd(zDir, sizeof(zDir))==0 ) return SQLITE_IOERR;
|
|
||||||
}
|
|
||||||
zDir[MAXPATHNAME] = '\0';
|
|
||||||
|
|
||||||
sqlite3_snprintf(nPathOut, zPathOut, "%s/%s", zDir, zPath);
|
|
||||||
zPathOut[nPathOut-1] = '\0';
|
|
||||||
|
|
||||||
return SQLITE_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
** The following four VFS methods:
|
|
||||||
**
|
|
||||||
** xDlOpen
|
|
||||||
** xDlError
|
|
||||||
** xDlSym
|
|
||||||
** xDlClose
|
|
||||||
**
|
|
||||||
** are supposed to implement the functionality needed by SQLite to load
|
|
||||||
** extensions compiled as shared objects. This simple VFS does not support
|
|
||||||
** this functionality, so the following functions are no-ops.
|
|
||||||
*/
|
|
||||||
static void *demoDlOpen(sqlite3_vfs *pVfs, const char *zPath){
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
static void demoDlError(sqlite3_vfs *pVfs, int nByte, char *zErrMsg){
|
|
||||||
sqlite3_snprintf(nByte, zErrMsg, "Loadable extensions are not supported");
|
|
||||||
zErrMsg[nByte-1] = '\0';
|
|
||||||
}
|
|
||||||
static void (*demoDlSym(sqlite3_vfs *pVfs, void *pH, const char *z))(void){
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
static void demoDlClose(sqlite3_vfs *pVfs, void *pHandle){
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
** Parameter zByte points to a buffer nByte bytes in size. Populate this
|
|
||||||
** buffer with pseudo-random data.
|
|
||||||
*/
|
|
||||||
static int demoRandomness(sqlite3_vfs *pVfs, int nByte, char *zByte){
|
|
||||||
return SQLITE_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
** Sleep for at least nMicro microseconds. Return the (approximate) number
|
|
||||||
** of microseconds slept for.
|
|
||||||
*/
|
|
||||||
static int demoSleep(sqlite3_vfs *pVfs, int nMicro){
|
|
||||||
sleep(nMicro / 1000000);
|
|
||||||
usleep(nMicro % 1000000);
|
|
||||||
return nMicro;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
** Set *pTime to the current UTC time expressed as a Julian day. Return
|
|
||||||
** SQLITE_OK if successful, or an error code otherwise.
|
|
||||||
**
|
|
||||||
** http://en.wikipedia.org/wiki/Julian_day
|
|
||||||
**
|
|
||||||
** This implementation is not very good. The current time is rounded to
|
|
||||||
** an integer number of seconds. Also, assuming time_t is a signed 32-bit
|
|
||||||
** value, it will stop working some time in the year 2038 AD (the so-called
|
|
||||||
** "year 2038" problem that afflicts systems that store time this way).
|
|
||||||
*/
|
|
||||||
static int demoCurrentTime(sqlite3_vfs *pVfs, double *pTime){
|
|
||||||
time_t t = time(0);
|
|
||||||
*pTime = t/86400.0 + 2440587.5;
|
|
||||||
return SQLITE_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
** This function returns a pointer to the VFS implemented in this file.
|
|
||||||
** To make the VFS available to SQLite:
|
|
||||||
**
|
|
||||||
** sqlite3_vfs_register(sqlite3_demovfs(), 0);
|
|
||||||
*/
|
|
||||||
uid_t geteuid(void)
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int fchown(int fildes, uid_t owner, gid_t group)
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
sqlite3_vfs *sqlite3_demovfs(void){
|
|
||||||
static sqlite3_vfs demovfs = {
|
|
||||||
1, /* iVersion */
|
|
||||||
sizeof(DemoFile), /* szOsFile */
|
|
||||||
MAXPATHNAME, /* mxPathname */
|
|
||||||
0, /* pNext */
|
|
||||||
"demo", /* zName */
|
|
||||||
0, /* pAppData */
|
|
||||||
demoOpen, /* xOpen */
|
|
||||||
demoDelete, /* xDelete */
|
|
||||||
demoAccess, /* xAccess */
|
|
||||||
demoFullPathname, /* xFullPathname */
|
|
||||||
demoDlOpen, /* xDlOpen */
|
|
||||||
demoDlError, /* xDlError */
|
|
||||||
demoDlSym, /* xDlSym */
|
|
||||||
demoDlClose, /* xDlClose */
|
|
||||||
demoRandomness, /* xRandomness */
|
|
||||||
demoSleep, /* xSleep */
|
|
||||||
demoCurrentTime, /* xCurrentTime */
|
|
||||||
};
|
|
||||||
return &demovfs;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@ -8,16 +8,7 @@
|
|||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(CROSSLANG_ENABLE_SQLITE)
|
|
||||||
extern "C" {
|
|
||||||
#include "../sqlite/sqlite3.h"
|
|
||||||
}
|
|
||||||
#if defined(GEKKO) || defined(__SWITCH__)
|
|
||||||
extern "C" {
|
|
||||||
sqlite3_vfs *sqlite3_demovfs();
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
using namespace Tesses::Framework::Threading;
|
using namespace Tesses::Framework::Threading;
|
||||||
using namespace std::chrono;
|
using namespace std::chrono;
|
||||||
namespace Tesses::CrossLang
|
namespace Tesses::CrossLang
|
||||||
@ -32,13 +23,12 @@ namespace Tesses::CrossLang
|
|||||||
}
|
}
|
||||||
GC::GC()
|
GC::GC()
|
||||||
{
|
{
|
||||||
tzset();
|
|
||||||
#if defined(CROSSLANG_ENABLE_SQLITE)
|
this->tpool=new Tesses::Framework::Lazy<Tesses::Framework::Threading::ThreadPool*>([]()->Tesses::Framework::Threading::ThreadPool*{
|
||||||
sqlite3_initialize();
|
auto threads = Tesses::Framework::Threading::ThreadPool::GetNumberOfCores();
|
||||||
#if defined(GEKKO) || defined(__SWITCH__)
|
if(threads < 4) threads=4;
|
||||||
sqlite3_vfs_register(sqlite3_demovfs(),1);
|
return new Tesses::Framework::Threading::ThreadPool(threads);
|
||||||
#endif
|
},[](Tesses::Framework::Threading::ThreadPool* p)->void{delete p;});
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
TDictionary* CreateThread(GCList& ls, TCallable* callable,bool detached)
|
TDictionary* CreateThread(GCList& ls, TCallable* callable,bool detached)
|
||||||
{
|
{
|
||||||
@ -206,6 +196,10 @@ namespace Tesses::CrossLang
|
|||||||
this->BarrierEnd();
|
this->BarrierEnd();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Tesses::Framework::Threading::ThreadPool* GC::GetPool()
|
||||||
|
{
|
||||||
|
return this->tpool->GetValue();
|
||||||
|
}
|
||||||
void GC::UnsetRoot(TObject obj)
|
void GC::UnsetRoot(TObject obj)
|
||||||
{
|
{
|
||||||
if(std::holds_alternative<THeapObjectHolder>(obj))
|
if(std::holds_alternative<THeapObjectHolder>(obj))
|
||||||
@ -234,6 +228,7 @@ namespace Tesses::CrossLang
|
|||||||
delete this->thrd;
|
delete this->thrd;
|
||||||
for(auto item : objects) delete item;
|
for(auto item : objects) delete item;
|
||||||
delete this->mtx;
|
delete this->mtx;
|
||||||
|
delete this->tpool;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GC::RegisterEverythingCallback(std::function<void(GC* gc, TRootEnvironment* env)> cb)
|
void GC::RegisterEverythingCallback(std::function<void(GC* gc, TRootEnvironment* env)> cb)
|
||||||
|
|||||||
@ -3150,6 +3150,28 @@ namespace Tesses::CrossLang {
|
|||||||
auto natObj = dynamic_cast<TNativeObject*>(obj);
|
auto natObj = dynamic_cast<TNativeObject*>(obj);
|
||||||
auto cls = dynamic_cast<TClassObject*>(obj);
|
auto cls = dynamic_cast<TClassObject*>(obj);
|
||||||
auto aArray=dynamic_cast<TAssociativeArray*>(obj);
|
auto aArray=dynamic_cast<TAssociativeArray*>(obj);
|
||||||
|
auto ttask = dynamic_cast<TTask*>(obj);
|
||||||
|
|
||||||
|
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)
|
if(natObj != nullptr)
|
||||||
{
|
{
|
||||||
@ -3321,6 +3343,20 @@ namespace Tesses::CrossLang {
|
|||||||
cse.back()->Push(gc,nullptr);
|
cse.back()->Push(gc,nullptr);
|
||||||
return false;
|
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 == "RegisterSDL2")
|
||||||
|
{
|
||||||
|
if((myEnv->permissions.canRegisterEverything || myEnv->permissions.canRegisterSDL2)&& !rootEnv->permissions.locked)
|
||||||
|
TStd::RegisterSDL2(gc, rootEnv);
|
||||||
|
cse.back()->Push(gc,nullptr);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
if(key == "RegisterConsole")
|
if(key == "RegisterConsole")
|
||||||
{
|
{
|
||||||
if((myEnv->permissions.canRegisterEverything || myEnv->permissions.canRegisterConsole) && !rootEnv->permissions.locked)
|
if((myEnv->permissions.canRegisterEverything || myEnv->permissions.canRegisterConsole) && !rootEnv->permissions.locked)
|
||||||
@ -5191,6 +5227,17 @@ namespace Tesses::CrossLang {
|
|||||||
auto natObj = dynamic_cast<TNativeObject*>(obj);
|
auto natObj = dynamic_cast<TNativeObject*>(obj);
|
||||||
auto cls = dynamic_cast<TClassObject*>(obj);
|
auto cls = dynamic_cast<TClassObject*>(obj);
|
||||||
auto aarray = dynamic_cast<TAssociativeArray*>(obj);
|
auto aarray = dynamic_cast<TAssociativeArray*>(obj);
|
||||||
|
auto task = dynamic_cast<TTask*>(obj);
|
||||||
|
if(task != nullptr)
|
||||||
|
{
|
||||||
|
if(key == "IsCompleted")
|
||||||
|
{
|
||||||
|
cse.back()->Push(gc,task->IsCompleted());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
cse.back()->Push(gc,Undefined());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
if(aarray != nullptr)
|
if(aarray != nullptr)
|
||||||
{
|
{
|
||||||
if(key == "Count" || key == "Length")
|
if(key == "Count" || key == "Length")
|
||||||
|
|||||||
Reference in New Issue
Block a user