Compare commits

..

10 Commits

Author SHA1 Message Date
f5e17217dd Fix for tessesframework migration 2025-07-03 16:18:29 -05:00
7797b0b387 Add GUI Support 2025-06-12 15:48:44 -05:00
18b15136b5 Add GUI Support 2025-06-12 15:48:37 -05:00
bfb029ec36 Add typeisclass 2025-06-01 18:49:47 -05:00
03f28a33db fix on macos 2025-05-31 16:23:57 -05:00
fe5cb54361 Make rpath relative 2025-05-30 22:57:56 -05:00
b0fe57b7c5 Make rpath relative 2025-05-30 22:57:26 -05:00
fc9d9aa1bf Make rpath relative 2025-05-30 22:54:40 -05:00
76be268ffa Make rpath relative 2025-05-30 22:53:21 -05:00
5403a09337 Make rpath relative 2025-05-30 22:51:50 -05:00
25 changed files with 2208 additions and 273625 deletions

View File

@ -16,11 +16,10 @@
"CROSSLANG_ENABLE_TERMIOS=1",
"CROSSLANG_ENABLE_MBED=1",
"CROSSLANG_ENABLE_SQLITE=1",
"CROSSLANG_ENABLE_SDL2=1",
"TESSESFRAMEWORK_ENABLE_SDL2=1",
"CROSSLANG_ENABLE_PROCESS=1",
"CROSSLANG_ENABLE_FFI=1",
"CROSSLANG_ENABLE_SHARED=1",
"CROSSLANG_ENABLE_GOBJECT_FFI=1"
"CROSSLANG_ENABLE_SHARED=1"
],
"compilerPath": "/usr/bin/gcc",
"cStandard": "c17",

View File

@ -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_INSTALL_DEVELOPMENT "Enable Tesses CrossLang development files" 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_PLATFORM_FOLDERS "Enable platform folders" ON)
option(CROSSLANG_ENABLE_TIME "Enable Time" ON)
option(CROSSLANG_SHARED_EXECUTABLES "Link with libcrosslang_shared" ON)
option(CROSSLANG_FETCHCONTENT "Use fetchcontent" ON)
option(CROSSLANG_ENABLE_CONFIG_ENVVAR "Allow setting config directory via the environment variable CROSSLANG_CONFIG" ON)
@ -113,6 +109,9 @@ endif()
if("${CMAKE_SYSTEM_NAME}" STREQUAL "NintendoWii")
target_link_libraries(${CROSSLANG_TARGET_NAME} PUBLIC wiisocket)
endif()
if(CROSSLANG_ENABLE_SHARED AND NOT ("${CMAKE_SYSTEM_NAME}" STREQUAL "Windows"))
target_link_libraries(${CROSSLANG_TARGET_NAME} PUBLIC dl)
endif()
target_include_directories(${CROSSLANG_TARGET_NAME}
PUBLIC
"$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>"
@ -140,6 +139,8 @@ src/runtime_methods/ogc.cpp
src/runtime_methods/path.cpp
src/runtime_methods/env.cpp
src/runtime_methods/process.cpp
src/runtime_methods/sdl2.cpp
src/types/async.cpp
src/types/associativearray.cpp
src/types/any.cpp
src/types/datetime.cpp
@ -164,12 +165,6 @@ src/archive.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 "")
else()

View File

@ -16,7 +16,6 @@
#include <TessesFramework/TessesFramework.hpp>
#include <regex>
#include <time.h>
#include <cstdbool>
#include <any>
/**
@ -65,7 +64,6 @@ namespace Tesses::CrossLang {
*/
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
*
@ -842,7 +840,7 @@ class CharInstruction : public ByteCodeInstruction {
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>;
@ -861,6 +859,35 @@ struct CodeGenClass {
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 {
uint32_t id;
@ -872,9 +899,9 @@ class CodeGen {
SyntaxNode StringifyListOfVars(SyntaxNode n);
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> 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>,uint32_t>> funcs;
@ -1243,6 +1270,10 @@ constexpr std::string_view RootPathExpression = "rootPathExpression";
*
*/
constexpr std::string_view RelativePathExpression = "relativePathExpression";
/**
* @brief await expression for async/await
*/
constexpr std::string_view AwaitExpression = "awaitExpression";
/**
* @brief Advanced AST node
*
@ -1280,6 +1311,8 @@ class AdvancedSyntaxNode {
SyntaxNode Deserialize(std::string astData);
std::string Serialize(SyntaxNode node);
class GC;
class TRootEnvironment;
/**
* @brief Token Parser
*
@ -1314,13 +1347,17 @@ class Parser {
SyntaxNode ParseValue();
SyntaxNode ParseUnary();
void ParseHtml(std::vector<SyntaxNode>& nodes,std::string var);
GC* gc;
TRootEnvironment* env;
public:
/**
* @brief Construct a new Parser object
*
* @param tokens the tokens from lexer
*/
Parser(std::vector<LexToken> tokens);
Parser(std::vector<LexToken> tokens, GC* gc, TRootEnvironment* env);
/**
* @brief Turn tokens into abstract syntax tree
*
@ -1350,6 +1387,7 @@ class Parser {
};
class THeapObjectHolder
{
public:
@ -1371,6 +1409,7 @@ class Parser {
};
class TDateTime {
Tesses::Framework::Date::DateTime* dt;
public:
@ -1401,8 +1440,11 @@ class GC {
volatile std::atomic<bool> running;
std::vector<THeapObject*> roots;
std::vector<THeapObject*> objects;
Tesses::Framework::Lazy<Tesses::Framework::Threading::ThreadPool*>* tpool;
std::vector<std::function<void(GC* gc, TRootEnvironment* env)>> register_everything;
public:
Tesses::Framework::Threading::ThreadPool* GetPool();
bool UsingNullThreads();
GC();
void Start();
@ -1763,6 +1805,7 @@ class GC {
bool canRegisterOGC;
bool canRegisterEnv;
bool canRegisterClass;
bool canRegisterSDL2;
bool sqlite3Scoped;
bool locked;
};
@ -1822,6 +1865,7 @@ class GC {
static void RegisterEnv(GC* gc, TRootEnvironment* env);
static void RegisterProcess(GC* gc, TRootEnvironment* env);
static void RegisterClass(GC* gc, TRootEnvironment* env);
static void RegisterSDL2(GC* gc,TRootEnvironment* env);
};
class TSubEnvironment : public TEnvironment
@ -2171,6 +2215,36 @@ class GC {
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;
class InterperterThread : public THeapObject

View File

@ -57,7 +57,7 @@ namespace Tesses::CrossLang
}
if(!this->icon.empty())
{
this->GetResource(this->icon);
this->GetResource(std::make_shared<ResourceFile>(this->icon));
}
for(auto& res : this->res)
@ -234,38 +234,15 @@ namespace Tesses::CrossLang
{
memcpy(buffer,"RESO",4);
Write(stream,buffer,4);
if(vfs == nullptr)
{
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);
}
WriteInt(stream,reso->GetLength(vfs));
reso->Write(stream);
}
if(!this->icon.empty())
{
memcpy(buffer,"ICON",4);
Write(stream,buffer,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);
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++)
{
if(this->res[i] == res) return i;
if(this->res[i]->IsEqual(resource.get())) return i;
}
uint32_t resI = (uint32_t)this->res.size();
this->res.push_back(res);
this->res.push_back(resource);
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));}
@ -516,6 +493,12 @@ namespace Tesses::CrossLang
{
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))
{
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]))
{
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)
@ -1520,20 +1503,6 @@ namespace Tesses::CrossLang
this->chunks[fnindex] = std::pair<std::vector<uint32_t>,std::vector<ByteCodeInstruction*>>(args, fnInstructions);
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]))
{
//func NAME(ARGS) {}
@ -1763,4 +1732,58 @@ namespace Tesses::CrossLang
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());
}
}

View File

@ -3,6 +3,65 @@
#include <stdexcept>
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)
{
switch(t)
@ -103,10 +162,16 @@ namespace Tesses::CrossLang
}
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->tokens = tokens;
this->gc = gc;
this->env = env;
}
void Parser::ParseHtml(std::vector<SyntaxNode>& nodes,std::string var)
{
@ -625,6 +690,42 @@ namespace Tesses::CrossLang
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"))
{
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()});
}
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("/"))
{
if(this->i < this->tokens.size() && (this->tokens[this->i].type == LexTokenType::String || this->tokens[this->i].type == LexTokenType::Identifier))
@ -1124,21 +1288,83 @@ namespace Tesses::CrossLang
}
else
{
auto nameAndArgs = ParseExpression();
if(IsSymbol("{",false))
if(IsIdentifier("async"))
{
auto nameAndArgs = ParseExpression();
if(IsSymbol("{",false))
{
name_and_methods.push_back(AdvancedSyntaxNode::Create(MethodStatement,false,{documentation,myTkn.text,nameAndArgs,ParseNode()}));
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
else if(IsIdentifier("enumerable"))
{
auto v = ParseExpression();
EnsureSymbol(";");
name_and_methods.push_back(AdvancedSyntaxNode::Create(MethodStatement,false,{documentation,myTkn.text,nameAndArgs,AdvancedSyntaxNode::Create(ReturnStatement,false,{v})}));
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();
if(IsSymbol("{",false))
{
name_and_methods.push_back(AdvancedSyntaxNode::Create(MethodStatement,false,{documentation,myTkn.text,nameAndArgs,ParseNode()}));
}
else
{
auto v = ParseExpression();
EnsureSymbol(";");
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");
}
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();
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
{
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"))
{
auto nameAndArgs = ParseExpression();
if(IsSymbol("{",false))

View File

@ -58,7 +58,7 @@ int main(int argc, char** argv)
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)
{

View File

@ -17,6 +17,7 @@ void Help(const char* filename)
printf(" -n: Set name (MyAppOrLibName defaults to out)\n");
printf(" -r: Set resource directory (RESDIR defaults to res)\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");
exit(1);
}
@ -43,9 +44,12 @@ int main(int argc, char** argv)
std::string name="out";
std::string info="{}";
std::string icon="";
std::string comptime="none";
TVMVersion version;
for(int i = 1; i < argc; i++)
{
if(strcmp(argv[i],"--help") == 0 || strcmp(argv[i],"-h")==0)
@ -68,6 +72,15 @@ int main(int argc, char** argv)
resourceDir = argv[i];
}
}
else if(strcmp(argv[i], "-e") == 0)
{
i++;
if(i < argc)
{
comptime = argv[i];
}
}
else if(strcmp(argv[i], "-i") == 0)
{
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;
gen.GenRoot(parser.ParseRoot());
@ -220,5 +274,10 @@ int main(int argc, char** argv)
gen.Save(&sfs,&strm);
}
if(gc != nullptr)
{
delete ls;
delete gc;
}
return 0;
}

View File

@ -8,7 +8,7 @@ using namespace Tesses::CrossLang;
using namespace Tesses::Framework::Filesystem;
int main(int argc, char** argv)
{
TF_Init();
TF_InitWithConsole();
GC gc;
gc.Start();
GCList ls(gc);

View File

@ -9,7 +9,7 @@
int main(int argc,char** argv)
{
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)
{

View File

@ -59,6 +59,80 @@ namespace Tesses::CrossLang
TDItem("Entries",EntriesToList(ls,f->classes.at(index).entry))
});
}
static TObject Class_CreateInstance(TRootEnvironment* env,GCList& ls, std::vector<TObject> args)
{
TList* args_ls;
if(!GetArgumentHeap(args,1,args_ls)) return nullptr;
TList* list;
TClassObject* obj;
std::string str;
if(GetArgumentHeap(args,0,list))
{
std::vector<std::string> clsName;
for(int64_t i = 0; i < list->Count(); i++)
{
auto o = list->Get(i);
if(GetObject(o,str)) clsName.push_back(str);
}
for(auto& item : env->classes)
{
auto& f=item.first->classes.at(item.second);
if(f.name.size() != clsName.size()) continue;
bool found=true;
for(size_t i = 0; i < f.name.size(); i++)
if(f.name[i] != clsName[i])
{
found=false;
break;
}
if(found)
{
return TClassObject::Create(ls,item.first,item.second,env,args_ls->items);
}
else
continue;
}
}
else if(GetArgument(args,0,str))
{
std::vector<std::string> clsName=Tesses::Framework::Http::HttpUtils::SplitString(str,".");
for(auto& item : env->classes)
{
auto& f=item.first->classes.at(item.second);
if(f.name.size() != clsName.size()) continue;
bool found=true;
for(size_t i = 0; i < f.name.size(); i++)
if(f.name[i] != clsName[i])
{
found=false;
break;
}
if(found)
{
return TClassObject::Create(ls,item.first,item.second,env,args_ls->items);
}
else
continue;
}
}
return nullptr;
}
static TObject Class_GetClassNames(TRootEnvironment* env,GCList& ls, std::vector<TObject> args)
{
TList* list = TList::Create(ls);
ls.GetGC()->BarrierBegin();
for(auto& item : env->classes)
{
list->Add(JoinPeriod(item.first->classes.at(item.second).name));
}
ls.GetGC()->BarrierEnd();
return list;
}
static TObject Class_GetInfo(TRootEnvironment* env,GCList& ls, std::vector<TObject> args)
{
@ -138,6 +212,28 @@ namespace Tesses::CrossLang
ext->watch.push_back(env);
cls->SetValue("GetInfo",ext);
ext = TExternalMethod::Create(ls ,"Get the class names",{},[env](GCList& ls, std::vector<TObject> args)->TObject {
return Class_GetClassNames(env,ls,args);
});
ext->watch.push_back(env);
cls->SetValue("GetClassNames",ext);
ext = TExternalMethod::Create(ls ,"Create an instance of class",{"name","args"},[env](GCList& ls, std::vector<TObject> args)->TObject {
return Class_CreateInstance(env,ls,args);
});
ext->watch.push_back(env);
cls->SetValue("CreateInstance",ext);
cls->DeclareFunction(gc,"Name","Get class name via instance",{"instance"},[](GCList& ls, std::vector<TObject> args)->TObject {
TClassObject* cls;
if(GetArgumentHeap(args,0,cls))
{
return cls->name;
}
return "";
});
gc->BarrierEnd();
}
}

View File

@ -1,80 +1,25 @@
#include "CrossLang.hpp"
#if defined(CROSSLANG_ENABLE_PLATFORM_FOLDERS)
#include "../sago/platform_folders.h"
#endif
#if defined(_WIN32)
#include <windows.h>
#endif
namespace Tesses::CrossLang
{
using namespace Tesses::Framework::Platform::Environment;
#if defined(_WIN32)
static char EnvPathSeperator=';';
#else
static char EnvPathSeperator=':';
#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()
{
#if defined(CROSSLANG_ENABLE_CONFIG_ENVVAR)
char* conf = std::getenv("CROSSLANG_CONFIG");
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";
return SpecialFolders::GetConfig() / "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)
@ -83,56 +28,16 @@ namespace Tesses::CrossLang
}
static TObject Env_getPlatform(GCList& ls, std::vector<TObject> args)
{
#if defined(__SWITCH__)
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";
return Tesses::Framework::Platform::Environment::GetPlatform();
}
static TObject Env_GetAt(GCList& ls, std::vector<TObject> args)
{
std::string key;
if(GetArgument(args,0,key))
{
auto res = std::getenv(key.c_str());
if(res == nullptr) return nullptr;
std::string value = res;
return value;
auto v = GetVariable(key);
if(v) return v.value();
}
return nullptr;
}
@ -143,108 +48,62 @@ namespace Tesses::CrossLang
if(GetArgument(args,0,key))
{
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);
return value;
}
else
{
SetVariable(key,std::nullopt);
}
#else
unsetenv(key.c_str());
#endif
return value;
}
return nullptr;
}
static TObject Env_getDownloads(GCList& ls, std::vector<TObject> args)
{
#if defined(CROSSLANG_ENABLE_PLATFORM_FOLDERS)
return sago::getDownloadFolder();
#else
return GetHomeFolder() + "/Downloads";
#endif
return SpecialFolders::GetDownloads();
}
static TObject Env_getMusic(GCList& ls, std::vector<TObject> args)
{
#if defined(CROSSLANG_ENABLE_PLATFORM_FOLDERS)
return sago::getMusicFolder();
#else
return GetHomeFolder() + "/Music";
#endif
return SpecialFolders::GetMusic();
}
static TObject Env_getPictures(GCList& ls, std::vector<TObject> args)
{
#if defined(CROSSLANG_ENABLE_PLATFORM_FOLDERS)
return sago::getPicturesFolder();
#else
return GetHomeFolder() + "/Pictures";
#endif
return SpecialFolders::GetPictures();
}
static TObject Env_getVideos(GCList& ls, std::vector<TObject> args)
{
#if defined(CROSSLANG_ENABLE_PLATFORM_FOLDERS)
return sago::getVideoFolder();
#else
return GetHomeFolder() + "/Videos";
#endif
return SpecialFolders::GetVideos();
}
static TObject Env_getDocuments(GCList& ls, std::vector<TObject> args)
{
#if defined(CROSSLANG_ENABLE_PLATFORM_FOLDERS)
return sago::getDocumentsFolder();
#else
return GetHomeFolder() + "/Documents";
#endif
return SpecialFolders::GetDocuments();
}
static TObject Env_getConfig(GCList& ls, std::vector<TObject> args)
{
#if defined(CROSSLANG_ENABLE_PLATFORM_FOLDERS)
return sago::getConfigHome();
#else
return GetHomeFolder() + "/Config";
#endif
return SpecialFolders::GetConfig();
}
static TObject Env_getDesktop(GCList& ls, std::vector<TObject> args)
{
#if defined(CROSSLANG_ENABLE_PLATFORM_FOLDERS)
return sago::getDesktopFolder();
#else
return GetHomeFolder() + "/Desktop";
#endif
return SpecialFolders::GetDesktop();
}
static TObject Env_getState(GCList& ls, std::vector<TObject> args)
{
#if defined(CROSSLANG_ENABLE_PLATFORM_FOLDERS)
return sago::getStateDir();
#else
return GetHomeFolder() + "/State";
#endif
return SpecialFolders::GetState();
}
static TObject Env_getCache(GCList& ls, std::vector<TObject> args)
{
#if defined(CROSSLANG_ENABLE_PLATFORM_FOLDERS)
return sago::getCacheDir();
#else
return GetHomeFolder() + "/Cache";
#endif
return SpecialFolders::GetCache();
}
static TObject Env_getData(GCList& ls, std::vector<TObject> args)
{
#if defined(CROSSLANG_ENABLE_PLATFORM_FOLDERS)
return sago::getDataHome();
#else
return GetHomeFolder() + "/Data";
#endif
return SpecialFolders::GetData();
}
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)
{

View File

@ -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{
return ctx->NeedToParseFormData();
});
dict->DeclareFunction(gc,"ReadString","Read string from request",{},[ctx](Tesses::CrossLang::GCList &ls2, std::vector<Tesses::CrossLang::TObject> args2)->TObject{
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{
return Json_Decode(ls2,ctx->ReadString());
});
@ -615,6 +622,7 @@ namespace Tesses::CrossLang
_obj = dict->GetValue("Key");
GetObject(_obj,key);
_obj = dict->GetValue("Value");
GetObject(_obj,value);
req.requestHeaders.AddValue(key,value);
}
@ -863,7 +871,7 @@ namespace Tesses::CrossLang
_obj = dict->GetValue("Key");
GetObject(_obj,key);
_obj = dict->GetValue("Value");
GetObject(_obj,value);
hdict.AddValue(key,value);
}
}

View File

@ -17,7 +17,8 @@ namespace Tesses::CrossLang
//Process.Start({
// FileName = "git",
// Arguments = ["clone","https://gitea.site.tesses.net/tesses50/crosslang.git"],
// Environment = []
// Environment = [],
// InheritParentEnvironment=true
//})
TDictionary* dict;

1254
src/runtime_methods/sdl2.cpp Normal file

File diff suppressed because it is too large Load Diff

View File

@ -1,32 +1,84 @@
#include "CrossLang.hpp"
#if defined(CROSSLANG_ENABLE_SQLITE)
#include "../sqlite/sqlite3.h"
#endif
#include <TessesFramework/TessesFrameworkFeatures.h>
#include <iostream>
namespace Tesses::CrossLang {
#if defined(CROSSLANG_ENABLE_SQLITE)
static int sqlcollector(void* user, int count,char** vals, char** keys)
#if defined(TESSESFRAMEWORK_ENABLE_SQLITE)
using namespace Tesses::Framework::Serialization;
class SQLiteObject : public TNativeObject
{
std::pair<GCList*,TList*>* ls2 = static_cast<std::pair<GCList*,TList*>*>(user);
TDictionary* dict = TDictionary::Create(ls2->first);
for(int i = 0; i < count; i++)
{
std::string key = keys[i] == nullptr ? "" : keys[i];
if(vals[i] == nullptr)
public:
SQLiteDatabase* db;
SQLiteObject(Tesses::Framework::Filesystem::VFSPath path)
{
dict->SetValue(key,nullptr);
db=new SQLiteDatabase(path);
}
else
{
dict->SetValue(key,vals[i]);
}
}
ls2->second->Add(dict);
return 0;
}
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
dict->SetValue(item2.first,nullptr);
}
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)
{
Tesses::Framework::Filesystem::VFSPath p;
@ -36,20 +88,8 @@ namespace Tesses::CrossLang {
{
p = env->permissions.sqliteOffsetPath / p.CollapseRelativeParents();
}
std::string name = p.ToString();
sqlite3* sqlite;
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 TNativeObject::Create<SQLiteObject>(ls,p);
}
return Undefined();
@ -57,26 +97,11 @@ namespace Tesses::CrossLang {
}
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);
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 sql->CallMethod(ls,"Exec",{cmd});
}
return Undefined();
@ -85,32 +110,21 @@ namespace Tesses::CrossLang {
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]);
std::string myStr = "\'";
for(auto c : srcStr)
{
if(c == '\'') myStr += "\'\'";
else
myStr += c;
}
myStr += '\'';
return myStr;
return SQLiteDatabase::Escape(str);
}
return Undefined();
}
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);
if(native != nullptr && !native->GetDestroyed())
{
native->Destroy();
}
sql->Close();
}
return Undefined();
}
@ -120,7 +134,7 @@ namespace Tesses::CrossLang {
{
env->permissions.canRegisterSqlite=true;
#if defined(CROSSLANG_ENABLE_SQLITE)
#if defined(TESSESFRAMEWORK_ENABLE_SQLITE)
GCList ls(gc);
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 {

View File

@ -428,6 +428,13 @@ namespace Tesses::CrossLang
cb(gc,env);
#endif
}
static TObject TypeIsClass(GCList& ls, std::vector<TObject> args)
{
if(args.empty()) return nullptr;
if(args.empty()) return nullptr;
TClassObject* co;
return GetArgumentHeap(args,0,co);
}
static TObject TypeIsDefined(GCList& ls,std::vector<TObject> args)
{
@ -852,9 +859,11 @@ namespace Tesses::CrossLang
{
GCList ls(gc);
gc->BarrierBegin();
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, "getNow", "Get the current time",{},DateTime_getNow);
date->DeclareFunction(gc, "getNowUTC","Get the current time in UTC",{},DateTime_getNowUTC);
@ -862,14 +871,27 @@ namespace Tesses::CrossLang
date->DeclareFunction(gc, "TryParseHttpDate","Parse the http date",{},DateTime_TryParseHttpDate);
gc->BarrierBegin();
date->SetValue("Zone", Tesses::Framework::Date::GetTimeZone());
date->SetValue("Zone", (int64_t)Tesses::Framework::Date::GetTimeZone());
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");
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);
@ -917,6 +939,8 @@ namespace Tesses::CrossLang
env->DeclareFunction(gc, "TypeIsDouble","Get whether object is a double (not a long)",{"object"},TypeIsDouble);
env->DeclareFunction(gc, "TypeIsString","Get whether object is a string",{"object"},TypeIsString);
env->DeclareFunction(gc, "TypeIsCallable","Get whether object is callable",{"object"},TypeIsCallable);
env->DeclareFunction(gc, "TypeIsClass","Get whether object is class instance",{"object"},TypeIsClass);
env->DeclareFunction(gc, "TypeIsDictionary","Get whether object is a dictionary or dynamic dictionary",{"object"},TypeIsDictionary);
env->DeclareFunction(gc, "TypeIsList","Get whether object is a list or dynamic list",{"object"},TypeIsList);
env->DeclareFunction(gc, "TypeIsStream","Get whether object is a stream",{"object"},TypeIsStream);
@ -924,6 +948,7 @@ namespace Tesses::CrossLang
env->DeclareFunction(gc, "TypeIsDateTime","Get whether object is a DateTime",{"object"},TypeIsDateTime);
newTypes->DeclareFunction(gc, "Regex", "Create regex object",{"regex"},[](GCList& ls,std::vector<TObject> args)->TObject {
std::string str;
if(GetArgument(args,0,str))
@ -1008,7 +1033,7 @@ namespace Tesses::CrossLang
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);
gc->BarrierBegin();
env->DeclareVariable("Version", TDictionary::Create(ls,{
TDItem("Parse",TExternalMethod::Create(ls,"Parse version from string",{"versionStr"},[](GCList& ls, std::vector<TObject> args)->TObject{
std::string str;
@ -1047,6 +1072,8 @@ namespace Tesses::CrossLang
}));
env->DeclareVariable("InvokeMethod",MethodInvoker());
gc->BarrierEnd();
}
void TStd::RegisterStd(GC* gc, TRootEnvironment* env)
@ -1066,6 +1093,7 @@ namespace Tesses::CrossLang
RegisterOGC(gc, env);
RegisterProcess(gc,env);
RegisterClass(gc,env);
RegisterSDL2(gc,env);
gc->RegisterEverything(env);

View File

@ -5,6 +5,101 @@
namespace Tesses::CrossLang
{
class OnItterationObj : public TNativeObject
{
private:
GC* gc;
std::vector<TCallable*> callables;
std::shared_ptr<Tesses::Framework::FunctionalEvent<uint64_t>> fevent;
public:
OnItterationObj(GC* gc)
{
this->gc=gc;
this->fevent = std::make_shared<Tesses::Framework::FunctionalEvent<uint64_t>>(
[this](uint64_t n)->void{
this->Exec(n);
}
);
Tesses::Framework::OnItteraton += this->fevent;
}
~OnItterationObj()
{
Tesses::Framework::OnItteraton -= this->fevent;
}
std::string TypeName()
{
return "OnItteration";
}
TObject CallMethod(GCList& ls, std::string key, std::vector<TObject> args)
{
if(key == "operator+")
{
TCallable* callable;
if(GetArgumentHeap(args,0,callable))
{
gc->BarrierBegin();
bool found=false;
for(auto item : this->callables)
{
if(item == callable) {found=true; break;}
}
if(!found)
{
this->callables.push_back(callable);
}
gc->BarrierEnd();
}
return this;
}
if(key == "operator-")
{
TCallable* callable;
if(GetArgumentHeap(args,0,callable))
{
gc->BarrierBegin();
for(auto index = this->callables.begin(); index < this->callables.end(); index++)
{
if(*index == callable) {
this->callables.erase(index);
break;
}
}
gc->BarrierEnd();
}
return this;
}
if(key == "ToString")
{
gc->BarrierBegin();
std::string str = "Registered: " + std::to_string(this->callables.size());
gc->BarrierEnd();
return str;
}
return Undefined();
}
void Mark()
{
if(this->marked) return;
this->marked=true;
for(auto item : callables) item->Mark();
}
void Exec(uint64_t n)
{
gc->BarrierBegin();
for(auto item : callables)
{
gc->BarrierEnd();
GCList ls(gc);
item->Call(ls,{(int64_t)n});
gc->BarrierBegin();
}
gc->BarrierEnd();
}
};
static TObject AstToTObject(GCList& ls,SyntaxNode node)
{
if(std::holds_alternative<std::nullptr_t>(node))
@ -147,15 +242,18 @@ namespace Tesses::CrossLang
TObject _tools = dict->GetValue("Tools");
TObject _info = dict->GetValue("Info");
TObject _icon = dict->GetValue("Icon");
TObject _comptime = dict->GetValue("CompTime");
TObject _resourceFileSystem = dict->GetValue("ResourceFileSystem");
TObject _out = dict->GetValue("Output");
TList* _toolList;
TList* _depList; TList* srcLst;
TRootEnvironment* comptimeEnv=nullptr;
GetObject<std::string>(_name,name);
GetObject<std::string>(_info,info);
GetObject<std::string>(_icon,icon);
GetObjectHeap(_resourceFileSystem, vfsHO);
GetObjectHeap(_comptime,comptimeEnv);
std::string v2;
if(GetObject<std::string>(_version,v2))
TVMVersion::TryParse(v2, version);
@ -253,7 +351,7 @@ namespace Tesses::CrossLang
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();
CodeGen gen;
gen.GenRoot(n);
@ -317,8 +415,24 @@ namespace Tesses::CrossLang
dict->DeclareFunction(gc, "getRuntimeVersion","Get the runtime version",{},[](GCList& ls,std::vector<TObject> args)->TObject {
return TVMVersion(TVM_MAJOR,TVM_MINOR,TVM_PATCH,TVM_BUILD,TVM_VERSIONSTAGE);
});
dict->DeclareFunction(gc, "getIsRunning","Is the program still running",{},[](GCList& ls, std::vector<TObject> args)->TObject {
return Tesses::Framework::TF_IsRunning();
});
dict->DeclareFunction(gc, "RunEventLoopItteration","Run Event Loop Itteration",{},[](GCList& ls, std::vector<TObject> args)->TObject {
Tesses::Framework::TF_RunEventLoopItteration();
return Undefined();
});
dict->DeclareFunction(gc, "RunEventLoop","Run Event Loop",{},[](GCList& ls, std::vector<TObject> args)->TObject {
Tesses::Framework::TF_RunEventLoop();
return Undefined();
});
gc->BarrierBegin();
auto ittrobj = TNativeObject::Create<OnItterationObj>(ls,gc);
dict->SetValue("OnItteration", ittrobj);
env->DeclareVariable("VM", dict);
gc->BarrierEnd();
}

View File

@ -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

View File

@ -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 */

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -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 */

View File

@ -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

View File

@ -8,16 +8,7 @@
#include <unistd.h>
#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 std::chrono;
namespace Tesses::CrossLang
@ -32,13 +23,12 @@ namespace Tesses::CrossLang
}
GC::GC()
{
tzset();
#if defined(CROSSLANG_ENABLE_SQLITE)
sqlite3_initialize();
#if defined(GEKKO) || defined(__SWITCH__)
sqlite3_vfs_register(sqlite3_demovfs(),1);
#endif
#endif
this->tpool=new Tesses::Framework::Lazy<Tesses::Framework::Threading::ThreadPool*>([]()->Tesses::Framework::Threading::ThreadPool*{
auto threads = Tesses::Framework::Threading::ThreadPool::GetNumberOfCores();
if(threads < 4) threads=4;
return new Tesses::Framework::Threading::ThreadPool(threads);
},[](Tesses::Framework::Threading::ThreadPool* p)->void{delete p;});
}
TDictionary* CreateThread(GCList& ls, TCallable* callable,bool detached)
{
@ -81,7 +71,7 @@ namespace Tesses::CrossLang
});
dict->DeclareFunction(ls.GetGC(),"getFinished","Get whether thread has finished",{},[th](GCList& _ls, std::vector<TObject> _args)-> TObject{
return th->hasReturned;
return (bool)(th->hasReturned==true);
});
ls.GetGC()->BarrierEnd();
@ -206,6 +196,10 @@ namespace Tesses::CrossLang
this->BarrierEnd();
}
}
Tesses::Framework::Threading::ThreadPool* GC::GetPool()
{
return this->tpool->GetValue();
}
void GC::UnsetRoot(TObject obj)
{
if(std::holds_alternative<THeapObjectHolder>(obj))
@ -234,6 +228,7 @@ namespace Tesses::CrossLang
delete this->thrd;
for(auto item : objects) delete item;
delete this->mtx;
delete this->tpool;
}
void GC::RegisterEverythingCallback(std::function<void(GC* gc, TRootEnvironment* env)> cb)

View File

@ -2208,7 +2208,7 @@ namespace Tesses::CrossLang {
}
else if(std::holds_alternative<char>(left) && std::holds_alternative<char>(right))
{
cse.back()->Push(gc,std::get<char>(left) + std::get<char>(right));
cse.back()->Push(gc,(char)(std::get<char>(left) + std::get<char>(right)));
}
else if(std::holds_alternative<int64_t>(left) && std::holds_alternative<char>(right))
{
@ -3150,6 +3150,28 @@ namespace Tesses::CrossLang {
auto natObj = dynamic_cast<TNativeObject*>(obj);
auto cls = dynamic_cast<TClassObject*>(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)
{
@ -3321,6 +3343,20 @@ namespace Tesses::CrossLang {
cse.back()->Push(gc,nullptr);
return false;
}
if(key == "RegisterClass")
{
if((myEnv->permissions.canRegisterEverything || myEnv->permissions.canRegisterClass) && !rootEnv->permissions.locked)
TStd::RegisterClass(gc, rootEnv);
cse.back()->Push(gc,nullptr);
return false;
}
if(key == "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((myEnv->permissions.canRegisterEverything || myEnv->permissions.canRegisterConsole) && !rootEnv->permissions.locked)
@ -3960,7 +3996,7 @@ namespace Tesses::CrossLang {
{
if(key == "GetPort")
{
cse.back()->Push(gc, netStrm->GetPort());
cse.back()->Push(gc, (int64_t)netStrm->GetPort());
return false;
}
if(key == "Bind")
@ -5191,6 +5227,17 @@ namespace Tesses::CrossLang {
auto natObj = dynamic_cast<TNativeObject*>(obj);
auto cls = dynamic_cast<TClassObject*>(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(key == "Count" || key == "Length")
@ -5669,7 +5716,9 @@ namespace Tesses::CrossLang {
cse.back()->Push(gc,callable->Call(ls,{value}));
return false;
}
gc->BarrierBegin();
cls->SetValue(cse.back()->callable->className,key,value);
gc->BarrierEnd();
cse.back()->Push(gc,value);
return false;
@ -6277,12 +6326,26 @@ namespace Tesses::CrossLang {
if(std::holds_alternative<THeapObjectHolder>(objhold) && std::holds_alternative<std::string>(k))
{
auto dict= dynamic_cast<TDictionary*>(std::get<THeapObjectHolder>(objhold).obj);
auto cls = dynamic_cast<TClassObject*>(std::get<THeapObjectHolder>(objhold).obj);
if(dict != nullptr)
{
dict->SetValue(std::get<std::string>(k), value);
}
else if(cls != nullptr)
{
auto obj=cls->GetValue(cse.back()->callable->className,"set"+std::get<std::string>(k));
TCallable* callable;
if(GetObjectHeap(obj,callable))
{
gc->BarrierEnd();
callable->Call(ls,{value});
gc->BarrierBegin();
}else {
cls->SetValue(cse.back()->callable->className,std::get<std::string>(k),value);
}
}
}
stk->Push(gc, objhold);