Move things from crosslang to here

This commit is contained in:
2025-06-21 23:05:12 -05:00
parent 71a2c83e5a
commit 81f0d3be2e
41 changed files with 275029 additions and 96 deletions

View File

@ -17,6 +17,8 @@ src/Http/ContentDisposition.cpp
src/Http/WebSocket.cpp src/Http/WebSocket.cpp
src/Mail/Smtp.cpp src/Mail/Smtp.cpp
src/Serialization/Json.cpp src/Serialization/Json.cpp
src/Serialization/SQLite.cpp
src/Platform/Environment.cpp
src/Streams/FileStream.cpp src/Streams/FileStream.cpp
src/Streams/MemoryStream.cpp src/Streams/MemoryStream.cpp
src/Streams/NetworkStream.cpp src/Streams/NetworkStream.cpp
@ -35,6 +37,7 @@ src/TextStreams/StringReader.cpp
src/TextStreams/StringWriter.cpp src/TextStreams/StringWriter.cpp
src/Threading/Thread.cpp src/Threading/Thread.cpp
src/Threading/Mutex.cpp src/Threading/Mutex.cpp
src/Threading/ThreadPool.cpp
src/Filesystem/VFS.cpp src/Filesystem/VFS.cpp
src/Filesystem/LocalFS.cpp src/Filesystem/LocalFS.cpp
src/Filesystem/MemoryFilesystem.cpp src/Filesystem/MemoryFilesystem.cpp
@ -57,6 +60,9 @@ src/SDL2/Views/LabelView.cpp
src/SDL2/Views/TextListView.cpp src/SDL2/Views/TextListView.cpp
src/SDL2/Views/ProgressView.cpp src/SDL2/Views/ProgressView.cpp
src/SDL2/Views/CheckView.cpp src/SDL2/Views/CheckView.cpp
src/SDL2/Views/EditTextView.cpp
src/SDL2/Views/PictureView.cpp
) )
set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON) set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON)
@ -65,7 +71,19 @@ option(TESSESFRAMEWORK_EMBED_CERT_BUNDLE "Embed the certificate chain bundle" ON
option(TESSESFRAMEWORK_ENABLE_MBED "Enable Tesses Framework mbedtls" ON) option(TESSESFRAMEWORK_ENABLE_MBED "Enable Tesses Framework mbedtls" ON)
option(TESSESFRAMEWORK_ENABLE_NETWORKING "Enable Networking" ON) option(TESSESFRAMEWORK_ENABLE_NETWORKING "Enable Networking" ON)
option(TESSESFRAMEWORK_ENABLE_THREADING "Enable Threading" ON) option(TESSESFRAMEWORK_ENABLE_THREADING "Enable Threading" ON)
option(TESSESFRAMEWORK_ENABLE_SQLITE "Enable sqlite (embedded in source)" ON)
option(TESSESFRAMEWORK_ENABLE_PLATFORMFOLDERS "Enable sago platformfolders (embedded in source)" ON)
if(TESSESFRAMEWORK_ENABLE_SQLITE)
list(APPEND TESSESFRAMEWORK_SOURCE
src/Serialization/sqlite/sqlite3.c
src/Serialization/sqlite/vfs.c
)
endif()
if(TESSESFRAMEWORK_ENABLE_PLATFORMFOLDERS)
list(APPEND TESSESFRAMEWORK_SOURCE
src/Platform/sago/platform_folders.cpp
)
endif()
option(TESSESFRAMEWORK_ENABLE_EXAMPLES "Enable Tesses Framework examples" ON) option(TESSESFRAMEWORK_ENABLE_EXAMPLES "Enable Tesses Framework examples" ON)
option(TESSESFRAMEWORK_ENABLE_APPS "Enable Tesses Framework cli apps" ON) option(TESSESFRAMEWORK_ENABLE_APPS "Enable Tesses Framework cli apps" ON)
option(TESSESFRAMEWORK_INSTALL_DEVELOPMENT "Enable Installing Tesses Framework Development Packages" ON) option(TESSESFRAMEWORK_INSTALL_DEVELOPMENT "Enable Installing Tesses Framework Development Packages" ON)
@ -88,10 +106,18 @@ include(cmake/bin2h.cmake)
if(TESSESFRAMEWORK_ENABLE_SDL2) if(TESSESFRAMEWORK_ENABLE_SDL2)
find_package(SDL2 REQUIRED)
find_package(SDL2_ttf REQUIRED)
find_package(SDL2_image REQUIRED)
if("${CMAKE_SYSTEM_NAME}" STREQUAL "NintendoWii" OR "${CMAKE_SYSTEM_NAME}" STREQUAL "NintendoGameCube" OR "${CMAKE_SYSTEM_NAME}" STREQUAL "NintendoSwitch")
find_package(PkgConfig)
pkg_search_module(SDL2 REQUIRED sdl2)
pkg_search_module(SDL2_TTF REQUIRED SDL2_ttf)
pkg_search_module(SDL2_IMAGE REQUIRED SDL2_image)
else()
find_package(SDL2 REQUIRED)
find_package(SDL2_image REQUIRED)
find_package(SDL2_ttf REQUIRED)
endif()
file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/include/TessesFramework/TanoheSans-Regular.h" "#pragma once\n") file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/include/TessesFramework/TanoheSans-Regular.h" "#pragma once\n")
bin2h(SOURCE_FILE "${CMAKE_CURRENT_SOURCE_DIR}/font/NonMono/TanoheSans-Regular.ttf" HEADER_FILE "${CMAKE_CURRENT_BINARY_DIR}/include/TessesFramework/TanoheSans-Regular.h" VARIABLE_NAME TanoheSansRegular APPEND NULL_TERMINATE) bin2h(SOURCE_FILE "${CMAKE_CURRENT_SOURCE_DIR}/font/NonMono/TanoheSans-Regular.ttf" HEADER_FILE "${CMAKE_CURRENT_BINARY_DIR}/include/TessesFramework/TanoheSans-Regular.h" VARIABLE_NAME TanoheSansRegular APPEND NULL_TERMINATE)
file(APPEND "${CMAKE_CURRENT_BINARY_DIR}/include/TessesFramework/TanoheSans-Regular.h" "\n") file(APPEND "${CMAKE_CURRENT_BINARY_DIR}/include/TessesFramework/TanoheSans-Regular.h" "\n")
@ -113,7 +139,6 @@ else()
target_compile_definitions(TessesFramework PUBLIC TESSESFRAMEWORK_CERT_BUNDLE_FILE=${TESSESFRAMEWORK_CERT_BUNDLE_FILE}) target_compile_definitions(TessesFramework PUBLIC TESSESFRAMEWORK_CERT_BUNDLE_FILE=${TESSESFRAMEWORK_CERT_BUNDLE_FILE})
endif() endif()
if(TESSESFRAMEWORK_FETCHCONTENT) if(TESSESFRAMEWORK_FETCHCONTENT)
set(MBEDTLS_FATAL_WARNINGS OFF) set(MBEDTLS_FATAL_WARNINGS OFF)
set(ENABLE_TESTING OFF) set(ENABLE_TESTING OFF)
@ -133,6 +158,12 @@ endif()
endif() endif()
function(TESSESFRAMEWORK_LINKDEPS TessesFramework_TARGET) function(TESSESFRAMEWORK_LINKDEPS TessesFramework_TARGET)
if(TESSESFRAMEWORK_ENABLE_SQLITE)
target_compile_definitions(${TessesFramework_TARGET} PUBLIC TESSESFRAMEWORK_ENABLE_SQLITE)
endif()
if(TESSESFRAMEWORK_ENABLE_PLATFORMFOLDERS)
target_compile_definitions(${TessesFramework_TARGET} PUBLIC TESSESFRAMEWORK_ENABLE_PLATFORMFOLDERS)
endif()
target_include_directories(${TessesFramework_TARGET} target_include_directories(${TessesFramework_TARGET}
PUBLIC PUBLIC
"$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>" "$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>"
@ -156,7 +187,19 @@ if(TESSESFRAMEWORK_ENABLE_NETWORKING)
target_compile_definitions(${TessesFramework_TARGET} PUBLIC TESSESFRAMEWORK_ENABLE_NETWORKING) target_compile_definitions(${TessesFramework_TARGET} PUBLIC TESSESFRAMEWORK_ENABLE_NETWORKING)
endif() endif()
if(TESSESFRAMEWORK_ENABLE_SDL2) if(TESSESFRAMEWORK_ENABLE_SDL2)
if("${CMAKE_SYSTEM_NAME}" STREQUAL "NintendoWii" OR "${CMAKE_SYSTEM_NAME}" STREQUAL "NintendoGameCube" OR "${CMAKE_SYSTEM_NAME}" STREQUAL "NintendoSwitch")
target_link_libraries(${TessesFramework_TARGET} PUBLIC ${SDL2_LIBRARIES})
target_include_directories(${TessesFramework_TARGET} PUBLIC ${SDL2_INCLUDE_DIRS})
target_compile_options(${TessesFramework_TARGET} PUBLIC ${SDL2_CFLAGS_OTHER})
target_link_libraries(${TessesFramework_TARGET} PUBLIC ${SDL2_TTF_LIBRARIES})
target_include_directories(${TessesFramework_TARGET} PUBLIC ${SDL2_TTF_INCLUDE_DIRS})
target_compile_options(${TessesFramework_TARGET} PUBLIC ${SDL2_TTF_CFLAGS_OTHER})
target_link_libraries(${TessesFramework_TARGET} PUBLIC ${SDL2_IMAGE_LIBRARIES})
target_include_directories(${TessesFramework_TARGET} PUBLIC ${SDL2_IMAGE_INCLUDE_DIRS})
target_compile_options(${TessesFramework_TARGET} PUBLIC ${SDL2_IMAGE_CFLAGS_OTHER})
else()
target_link_libraries(${TessesFramework_TARGET} PUBLIC SDL2::SDL2 SDL2_image::SDL2_image SDL2_ttf::SDL2_ttf) target_link_libraries(${TessesFramework_TARGET} PUBLIC SDL2::SDL2 SDL2_image::SDL2_image SDL2_ttf::SDL2_ttf)
endif()
target_compile_definitions(${TessesFramework_TARGET} PUBLIC TESSESFRAMEWORK_ENABLE_SDL2) target_compile_definitions(${TessesFramework_TARGET} PUBLIC TESSESFRAMEWORK_ENABLE_SDL2)
endif() endif()
if(TESSESFRAMEWORK_ENABLE_MBED) if(TESSESFRAMEWORK_ENABLE_MBED)
@ -178,6 +221,10 @@ endif()
if("${CMAKE_SYSTEM_NAME}" STREQUAL "NintendoWii" OR "${CMAKE_SYSTEM_NAME}" STREQUAL "NintendoGameCube") if("${CMAKE_SYSTEM_NAME}" STREQUAL "NintendoWii" OR "${CMAKE_SYSTEM_NAME}" STREQUAL "NintendoGameCube")
target_link_libraries(${TessesFramework_TARGET} PUBLIC fat) target_link_libraries(${TessesFramework_TARGET} PUBLIC fat)
endif()
if("${CMAKE_SYSTEM_NAME}" STREQUAL "NintendoSwitch" AND TESSESFRAMEWORK_ENABLE_THREADING)
target_link_libraries(${TessesFramework_TARGET} PUBLIC -lpthread)
endif() endif()
if("${CMAKE_SYSTEM_NAME}" STREQUAL "NintendoWii") if("${CMAKE_SYSTEM_NAME}" STREQUAL "NintendoWii")
target_link_libraries(${TessesFramework_TARGET} PUBLIC wiisocket) target_link_libraries(${TessesFramework_TARGET} PUBLIC wiisocket)
@ -281,8 +328,12 @@ endif()
if(TESSESFRAMEWORK_ENABLE_EXAMPLES) if(TESSESFRAMEWORK_ENABLE_EXAMPLES)
if(TESSESFRAMEWORK_ENABLE_SDL2) if(TESSESFRAMEWORK_ENABLE_SDL2)
add_executable(sdl2 examples/sdl2.cpp) if(TESSESFRAMEWORK_ENABLE_SQLITE AND TESSESFRAMEWORK_ENABLE_PLATFORMFOLDERS)
target_link_libraries(sdl2 PUBLIC tessesframework) add_executable(databaseex examples/databaseex.cpp)
target_link_libraries(databaseex PUBLIC tessesframework)
endif()
add_executable(guikitchensink examples/guikitchensink.cpp)
target_link_libraries(guikitchensink PUBLIC tessesframework)
endif() endif()
add_executable(copyfile examples/copyfile.cpp) add_executable(copyfile examples/copyfile.cpp)
target_link_libraries(copyfile PUBLIC tessesframework) target_link_libraries(copyfile PUBLIC tessesframework)

View File

@ -17,8 +17,11 @@ if(${TESSESFRAMEWORK_ENABLE_LIBWEBCAM})
find_package(libwebcam) find_package(libwebcam)
endif() endif()
set(TESSESFRAMEWORK_ENABLE_SQLITE @TESSESFRAMEWORK_ENABLE_SQLITE@)
set(TESSESFRAMEWORK_ENABLE_PLATFORMFOLDERS @TESSESFRAMEWORK_ENABLE_PLATFORMFOLDERS@)
set(TESSESFRAMEWORK_ENABLE_SDL2 @TESSESFRAMEWORK_ENABLE_SDL2@) set(TESSESFRAMEWORK_ENABLE_SDL2 @TESSESFRAMEWORK_ENABLE_SDL2@)
if(${TESSESFRAMEWORK_ENABLE_SDL2}) if(${TESSESFRAMEWORK_ENABLE_SDL2})
find_package(SDL2 REQUIRED) find_package(SDL2 REQUIRED)
find_package(SDL2_ttf REQUIRED) find_package(SDL2_ttf REQUIRED)

View File

@ -1,6 +1,12 @@
#pragma once #pragma once
#define TESSES_FRAMEWORK_FLAG_OFF 0 #define TESSES_FRAMEWORK_FLAG_OFF 0
#define TESSES_FRAMEWORK_FLAG_ON 1 #define TESSES_FRAMEWORK_FLAG_ON 1
#if TESSES_FRAMEWORK_FLAG_@TESSESFRAMEWORK_ENABLE_SQLITE@
#define TESSESFRAMEWORK_ENABLE_SQLITE
#endif
#if TESSES_FRAMEWORK_FLAG_@TESSESFRAMEWORK_ENABLE_PLATFORMFOLDERS@
#define TESSESFRAMEWORK_ENABLE_PLATFORMFOLDERS
#endif
#if TESSES_FRAMEWORK_FLAG_@TESSESFRAMEWORK_ENABLE_MBED@ #if TESSES_FRAMEWORK_FLAG_@TESSESFRAMEWORK_ENABLE_MBED@
#define TESSESFRAMEWORK_ENABLE_MBED #define TESSESFRAMEWORK_ENABLE_MBED
#endif #endif

View File

@ -9,7 +9,7 @@ using namespace Tesses::Framework::Threading;
void print_help(const char* name) void print_help(const char* name)
{ {
printf("Tesses FileServer\nUSAGE: %s [OPTIONS] <dir>\n",name); printf("Tesses FileServer\nUSAGE: %s [OPTIONS] <dir>\n",name);
printf("OPTIONS:\n-p PORT, --port PORT: Change port from 10000\n-l, --listing: Enable listing\n-s, --spa: Enable SPA mode (send \"/\" body instead of not found)\n-h, --help: This Screen\n"); printf("OPTIONS:\n-p PORT, --port PORT: Change port from 9852\n-l, --listing: Enable listing\n-s, --spa: Enable SPA mode (send \"/\" body instead of not found)\n-h, --help: This Screen\n");
exit(1); exit(1);
} }
int main(int argc, char** argv) int main(int argc, char** argv)
@ -21,7 +21,7 @@ int main(int argc, char** argv)
const char* directory = "wwwroot"; const char* directory = "wwwroot";
bool spa=false; bool spa=false;
bool allowListing = false; bool allowListing = false;
uint16_t port = 10000L; uint16_t port = 9852L;
for(int i = 1; i < argc; i++) for(int i = 1; i < argc; i++)
{ {

110
examples/databaseex.cpp Normal file
View File

@ -0,0 +1,110 @@
#if defined(TESSESFRAMEWORK_ENABLE_SDL2)
#define SDL_MAIN_HANDLED
#include "TessesFramework/Platform/Environment.hpp"
#include "TessesFramework/Serialization/SQLite.hpp"
#include "TessesFramework/SDL2/GUI.hpp"
#include "TessesFramework/SDL2/Views/ButtonView.hpp"
#include "TessesFramework/SDL2/Views/AbsoluteView.hpp"
#include "TessesFramework/SDL2/Views/LabelView.hpp"
#include "TessesFramework/SDL2/Views/TextListView.hpp"
#include "TessesFramework/SDL2/Views/ProgressView.hpp"
#include "TessesFramework/SDL2/Views/CheckView.hpp"
#include "TessesFramework/SDL2/Views/EditTextView.hpp"
using namespace Tesses::Framework::Filesystem;
using namespace Tesses::Framework::SDL2;
using namespace Tesses::Framework::Serialization;
using namespace Tesses::Framework;
using namespace Tesses::Framework::Platform::Environment::SpecialFolders;
VFSPath DatabasePath()
{
auto path = GetConfig() / "Tesses" / "Framework" / "Examples";
LocalFS.CreateDirectory(path);
return path / "databaseex.sqlite";
}
void CreateTable()
{
SQLiteDatabase db(DatabasePath());
db.Exec("CREATE TABLE IF NOT EXISTS names (id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT);");
}
void ClearTable()
{
SQLiteDatabase db(DatabasePath());
db.Exec("DROP TABLE names;");
db.Exec("CREATE TABLE IF NOT EXISTS names (id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT);");
}
void LoadDB(std::vector<std::string>& items)
{
SQLiteDatabase db(DatabasePath());
for(auto item : db.Exec("SELECT name FROM names;"))
{
for(auto kvp : item)
{
if(kvp.first == "name" && kvp.second)
items.push_back(kvp.second.value());
}
}
}
void Append(std::string item)
{
SQLiteDatabase db(DatabasePath());
db.Exec("INSERT INTO names (name) VALUES (" + SQLiteDatabase::Escape(item) + ");");
}
int main(int argc,char** argv)
{
std::string json = "{\"Child\":{\"Items\":[{\"Bounds\":{\"Height\":50,\"Width\":440,\"X\":16,\"Y\":16},\"Hint\":\"Enter name\",\"Id\":\"name\",\"Type\":\"EditTextView\"},{\"Bounds\":{\"Height\":50,\"Width\":70,\"X\":470,\"Y\":17},\"Id\":\"addBtn\",\"Text\":\"Add\",\"Type\":\"ButtonView\"},{\"Bounds\":{\"Height\":50,\"Width\":70,\"X\":550,\"Y\":17},\"Id\":\"clearBtn\",\"Text\":\"Clear\",\"Type\":\"ButtonView\"},{\"Bounds\":{\"Height\":382,\"Width\":608,\"X\":16,\"Y\":82},\"Id\":\"listView\",\"Type\":\"TextListView\"}],\"Type\":\"AbsoluteView\"}}";
TF_Init();
CreateTable();
GUIPalette pal(true,{.r=255,.g=0,.b=0,.a=255});
GUIWindow window("Names",640,480,0,pal);
window.SetView(Json::Json::Decode(json));
auto name = dynamic_cast<Views::EditTextView*>(window.FindViewById("name"));
auto addBtn = dynamic_cast<Views::ButtonView*>(window.FindViewById("addBtn"));
auto clearBtn = dynamic_cast<Views::ButtonView*>(window.FindViewById("clearBtn"));
auto listView = dynamic_cast<Views::TextListView*>(window.FindViewById("listView"));
if(name == nullptr || addBtn == nullptr || clearBtn == nullptr || listView == nullptr)
{
TF_Quit();
return 1;
}
LoadDB(listView->items);
addBtn->Click += std::make_shared<FunctionalEvent<View*,GUIEventArgs&>>([&](View* view,GUIEventArgs& e)->void {
std::string text = name->GetText();
if(!text.empty())
{
name->SetText("");
Append(text);
listView->items.push_back(text);
}
});
clearBtn->Click += std::make_shared<FunctionalEvent<View*,GUIEventArgs&>>([&](View* view,GUIEventArgs& e)->void {
listView->items.clear();
ClearTable();
});
TF_RunEventLoop();
TF_Quit();
}
#endif

View File

@ -1,5 +1,7 @@
#if defined(TESSESFRAMEWORK_ENABLE_SDL2) #if defined(TESSESFRAMEWORK_ENABLE_SDL2)
#define SDL_MAIN_HANDLED
#include "TessesFramework/SDL2/GUI.hpp" #include "TessesFramework/SDL2/GUI.hpp"
#include "TessesFramework/SDL2/Views/ButtonView.hpp" #include "TessesFramework/SDL2/Views/ButtonView.hpp"
#include "TessesFramework/SDL2/Views/AbsoluteView.hpp" #include "TessesFramework/SDL2/Views/AbsoluteView.hpp"
@ -8,6 +10,7 @@
#include "TessesFramework/Filesystem/LocalFS.hpp" #include "TessesFramework/Filesystem/LocalFS.hpp"
#include "TessesFramework/SDL2/Views/ProgressView.hpp" #include "TessesFramework/SDL2/Views/ProgressView.hpp"
#include "TessesFramework/SDL2/Views/CheckView.hpp" #include "TessesFramework/SDL2/Views/CheckView.hpp"
#include "TessesFramework/SDL2/Views/EditTextView.hpp"
#include <iostream> #include <iostream>
using namespace Tesses::Framework; using namespace Tesses::Framework;
using namespace Tesses::Framework::SDL2; using namespace Tesses::Framework::SDL2;
@ -36,24 +39,26 @@ int main(int argc,char** argv)
size_t color_index=0; size_t color_index=0;
GUIPalette pal0(darkMode,colors[color_index % colors.size()].first,20); GUIPalette pal0(darkMode,colors[color_index % colors.size()].first,20);
GUIWindow window("My Window Title",640,480,SDL_WINDOW_RESIZABLE,pal0); TF_LOG("Create pallete");
GUIWindow window("My Window Title",1280,720,SDL_WINDOW_RESIZABLE,pal0);
TF_LOG("Created GUIWindow success");
Views::LabelView lbl("A random label\nThat spans lines."); Views::LabelView lbl("A random label\nThat spans lines.");
Views::ButtonView btn("Dark Mode"); Views::ButtonView btn("Dark Mode");
Views::ButtonView btn2(colors[0].second); Views::ButtonView btn2(colors[0].second);
Views::ProgressView progress(42.42); Views::ProgressView progress(42.42);
Views::CheckView cv(false,"Checkbox"); Views::CheckView cv(false,"Checkbox");
Views::CheckView cv2(false,"Another Checkbox"); Views::CheckView cv2(false,"Another Checkbox");
Views::EditTextView edit("Enter some text");
Views::TextListView list; Views::TextListView list;
for(auto item : Tesses::Framework::Filesystem::LocalFS.EnumeratePaths((std::string)"/usr/bin")) /*for(auto item : Tesses::Framework::Filesystem::LocalFS.EnumeratePaths((std::string)"/usr/bin"))
{ {
list.items.push_back(item.GetFileName()); list.items.push_back(item.GetFileName());
} }*/
@ -73,15 +78,29 @@ int main(int argc,char** argv)
abs.Add({.x=32,.y=230,.w=320,.h=240},&list,false); abs.Add({.x=32,.y=230,.w=320,.h=240},&list,false);
abs.Add({.x=32,.y=478,.w=300,.h=200},&edit,false);
window.SetView(&abs,false); window.SetView(&abs,false);
window.SDLEvent += std::make_shared<FunctionalEvent<View*,GUISDLEventEventArgs&>>([&window,&lbl](View* sender, GUISDLEventEventArgs& e)->void {
std::string sdl2_event = "SDL_Event: " + std::to_string(e.event.type);
TF_LOG(sdl2_event);
if(e.event.type == SDL_EventType::SDL_WINDOWEVENT)
{
if(e.event.window.event == SDL_WINDOWEVENT_RESIZED)
{
std::string text ="A random label\nThat spans lines, WindowSize: "
+std::to_string(e.event.window.data1) + "x" + std::to_string(e.event.window.data2) + ".";
lbl.SetText(text);
}
}
});
btn.Click += std::make_shared<FunctionalEvent<View*,GUIEventArgs&>>([&window,&darkMode,&color_index,&colors,&btn](View* sender, GUIEventArgs& e)->void{ btn.Click += std::make_shared<FunctionalEvent<View*,GUIEventArgs&>>([&window,&darkMode,&color_index,&colors,&btn](View* sender, GUIEventArgs& e)->void{
darkMode = !darkMode; darkMode = !darkMode;
btn.SetText(darkMode ? "Light Mode" : "Dark Mode"); btn.SetText(darkMode ? "Light Mode" : "Dark Mode");
GUIPalette palette(darkMode,colors[color_index % colors.size()].first,20); GUIPalette palette(darkMode,colors[color_index % colors.size()].first,20);
window.SetPalette(palette); window.SetPalette(palette);
}); });
//"A random label\nThat spans lines."
btn2.Click += std::make_shared<FunctionalEvent<View*,GUIEventArgs&>>([&window,&darkMode,&color_index,&colors,&btn2](View* sender, GUIEventArgs& e)->void{ btn2.Click += std::make_shared<FunctionalEvent<View*,GUIEventArgs&>>([&window,&darkMode,&color_index,&colors,&btn2](View* sender, GUIEventArgs& e)->void{
color_index++; color_index++;
@ -98,4 +117,4 @@ int main(int argc,char** argv)
TF_Quit(); TF_Quit();
#endif #endif
return 0; return 0;
} }

View File

@ -38,6 +38,7 @@ template<typename T>
else else
{ {
this->value = this->init(); this->value = this->init();
this->hasInit=true;
mtx.Unlock(); mtx.Unlock();
return this->value; return this->value;
} }
@ -48,4 +49,4 @@ template<typename T>
if(hasInit) this->free(this->value); if(hasInit) this->free(this->value);
} }
}; };
} }

View File

@ -0,0 +1,34 @@
#pragma once
#include "TessesFramework/Filesystem/VFSFix.hpp"
#include "TessesFramework/Filesystem/LocalFS.hpp"
#include <optional>
namespace Tesses::Framework::Platform::Environment
{
extern const char EnvPathSeperator;
namespace SpecialFolders {
Tesses::Framework::Filesystem::VFSPath GetHomeFolder();
Tesses::Framework::Filesystem::VFSPath GetDownloads();
Tesses::Framework::Filesystem::VFSPath GetMusic();
Tesses::Framework::Filesystem::VFSPath GetPictures();
Tesses::Framework::Filesystem::VFSPath GetVideos();
Tesses::Framework::Filesystem::VFSPath GetDocuments();
Tesses::Framework::Filesystem::VFSPath GetConfig();
Tesses::Framework::Filesystem::VFSPath GetDesktop();
Tesses::Framework::Filesystem::VFSPath GetState();
Tesses::Framework::Filesystem::VFSPath GetCache();
Tesses::Framework::Filesystem::VFSPath GetData();
}
std::string GetPlatform();
Tesses::Framework::Filesystem::VFSPath GetRealExecutablePath(Tesses::Framework::Filesystem::VFSPath realPath);
std::optional<std::string> GetVariable(std::string name);
void SetVariable(std::string name, std::optional<std::string> var);
void GetEnvironmentVariables(std::vector<std::pair<std::string,std::string>>& env);
}

View File

@ -0,0 +1,39 @@
#include <vector>
#include <string>
#include "TessesFramework/Streams/Stream.hpp"
#include "TessesFramework/HiddenField.hpp"
namespace Tesses::Framework::Platform {
class Process {
private:
HiddenField hidden;
public:
std::string name;
std::vector<std::string> args;
std::vector<std::pair<std::string,std::string>> env;
bool includeThisEnv;
bool redirectStdIn=false;
bool redirectStdOut=false;
bool redirectStdErr=false;
//YOU ARE RESPONSABLE FOR FREEING THIS STREAM
Tesses::Framework::Streams::Stream* GetStdinStream(bool closeUnderlying=true);
//YOU ARE RESPONSABLE FOR FREEING THIS STREAM
Tesses::Framework::Streams::Stream* GetStdoutStream(bool closeUnderlying=true);
//YOU ARE RESPONSABLE FOR FREEING THIS STREAM
Tesses::Framework::Streams::Stream* GetStderrStream(bool closeUnderlying=true);
Process();
Process(std::string name, std::vector<std::string> args,bool includeThisEnv=true);
Process(std::string name, std::vector<std::string> args, std::vector<std::pair<std::string,std::string>> env,bool includeThisEnv=false);
Process(std::string name, std::vector<std::string> args, std::vector<std::string> env,bool includeThisEnv=false);
bool Start();
void Kill(int signal);
int WaitForExit();
~Process();
};
}

View File

@ -61,6 +61,7 @@ namespace Tesses::Framework::SDL2
constexpr uint64_t VIEWFLAG_TABSTOP=(uint64_t)1<<3; constexpr uint64_t VIEWFLAG_TABSTOP=(uint64_t)1<<3;
constexpr uint64_t VIEWFLAG_INTERCEPT_TAB=(uint64_t)1<<4; constexpr uint64_t VIEWFLAG_INTERCEPT_TAB=(uint64_t)1<<4;
constexpr uint64_t VIEWFLAG_CHECKED=(uint64_t)1<<5; constexpr uint64_t VIEWFLAG_CHECKED=(uint64_t)1<<5;
constexpr uint64_t VIEWFLAG_TOUCHED=(uint64_t)1<<6;
class GUIPopup; class GUIPopup;
class GUIWindow; class GUIWindow;
class ContainerView; class ContainerView;
@ -96,6 +97,8 @@ namespace Tesses::Framework::SDL2
ContainerView* parent; ContainerView* parent;
public: public:
bool GetViewFlag(uint64_t flag) bool GetViewFlag(uint64_t flag)
{ {
@ -124,6 +127,11 @@ namespace Tesses::Framework::SDL2
virtual std::string GetId(); virtual std::string GetId();
virtual View* FindViewById(std::string id); virtual View* FindViewById(std::string id);
friend class ContainerView; friend class ContainerView;
virtual std::pair<int,int> PreferedMinSize();
std::pair<int,int> GetCordFromEvent(SDL_Event& event);
}; };
class ContainerView : public View { class ContainerView : public View {
public: public:
@ -210,11 +218,15 @@ namespace Tesses::Framework::SDL2
friend class GUI; friend class GUI;
friend class GUIPopup; friend class GUIPopup;
friend class View;
void SetText(std::string text); void SetText(std::string text);
void SetView(Tesses::Framework::Serialization::Json::JToken json); void SetView(Tesses::Framework::Serialization::Json::JToken json);
SDL_Window* GetSDLWindow();
SDL_Renderer* GetSDLRenderer();
View* CreateViewFromJson(Tesses::Framework::Serialization::Json::JObject json); View* CreateViewFromJson(Tesses::Framework::Serialization::Json::JObject json);
}; };

View File

@ -0,0 +1,24 @@
#pragma once
#if defined(TESSESFRAMEWORK_ENABLE_SDL2)
#include "../GUI.hpp"
namespace Tesses::Framework::SDL2::Views
{
class EditTextView : public View {
protected:
virtual void OnDraw(SDL_Renderer* renderer, SDL_Rect& r);
virtual bool OnEvent(SDL_Event& event, SDL_Rect& myBounds, SDL_Rect& visibleBounds);
std::string hint;
size_t cursorPos;
size_t cursorEnd;
public:
EditTextView();
EditTextView(std::string hint);
virtual std::string GetHint();
virtual void SetHint(std::string hint);
virtual void SetText(std::string text);
virtual void TypeText(std::string text);
virtual std::pair<int,int> PreferedMinSize();
};
}
#endif

View File

@ -0,0 +1,22 @@
#pragma once
#if defined(TESSESFRAMEWORK_ENABLE_SDL2)
#include "../GUI.hpp"
namespace Tesses::Framework::SDL2::Views
{
class PictureView : public View {
SDL_Texture* tex;
bool ownsTex;
SDL_Surface* surf;
bool ownsSurf;
protected:
virtual void OnDraw(SDL_Renderer* renderer, SDL_Rect& r);
public:
PictureView();
void SetPicture(SDL_Texture* tex, bool owns=true);
void SetPicture(SDL_Surface* surface,bool owns=true);
~PictureView();
};
}
#endif

View File

@ -0,0 +1,18 @@
#pragma once
#include "TessesFramework/Filesystem/VFSFix.hpp"
#include "TessesFramework/Filesystem/VFS.hpp"
#include <optional>
namespace Tesses::Framework::Serialization {
class SQLiteDatabase {
private:
void* data;
static int collector(void* user, int count,char** vals, char** keys);
public:
SQLiteDatabase(Tesses::Framework::Filesystem::VFSPath path);
static std::string Escape(std::string text);
static bool IsEnabled();
void Exec(std::string statement,std::vector<std::vector<std::pair<std::string,std::optional<std::string>>>>& results);
std::vector<std::vector<std::pair<std::string,std::optional<std::string>>>> Exec(std::string statement);
~SQLiteDatabase();
};
}

View File

@ -32,6 +32,8 @@
#include "Mail/Smtp.hpp" #include "Mail/Smtp.hpp"
#include "HiddenField.hpp" #include "HiddenField.hpp"
#include "Serialization/Json.hpp" #include "Serialization/Json.hpp"
#include "Serialization/SQLite.hpp"
#include "Platform/Environment.hpp"
#include "SDL2/FontCache.hpp" #include "SDL2/FontCache.hpp"
#include "SDL2/Stream.hpp" #include "SDL2/Stream.hpp"
#include "SDL2/GUI.hpp" #include "SDL2/GUI.hpp"

View File

@ -11,13 +11,15 @@ namespace Tesses::Framework::Threading
class ThreadPool class ThreadPool
{ {
std::vector<Thread*> threads; std::vector<Thread*> threads;
std::queue<std::function<void()>> callbacks; std::queue<std::function<void(size_t)>> callbacks;
Mutex mtx; Mutex mtx;
volatile bool isRunning; volatile bool isRunning;
public: public:
static size_t GetNumberOfCores(); static size_t GetNumberOfCores();
ThreadPool(size_t threads); ThreadPool(size_t threads);
void Schedule(std::function<void()> cb); size_t ThreadCount();
bool Empty();
void Schedule(std::function<void(size_t)> cb);
~ThreadPool(); ~ThreadPool();
}; };
} }

View File

@ -137,7 +137,7 @@ namespace Tesses::Framework::Crypto
mbedtls_ssl_cache_get, mbedtls_ssl_cache_get,
mbedtls_ssl_cache_set); mbedtls_ssl_cache_set);
#endif*/ #endif*/
mbedtls_ssl_conf_authmode(&data->conf, verify ? MBEDTLS_SSL_VERIFY_REQUIRED: MBEDTLS_SSL_VERIFY_OPTIONAL); mbedtls_ssl_conf_authmode(&data->conf, verify ? MBEDTLS_SSL_VERIFY_REQUIRED: MBEDTLS_SSL_VERIFY_NONE);
mbedtls_ssl_conf_ca_chain(&data->conf, &data->cachain, NULL); mbedtls_ssl_conf_ca_chain(&data->conf, &data->cachain, NULL);

View File

@ -169,7 +169,7 @@ namespace Tesses::Framework::Filesystem
{ {
auto firstPartPath = p.path.front(); auto firstPartPath = p.path.front();
if(!firstPartPath.empty() && firstPartPath.back() == '/') p.relative=false; if(!firstPartPath.empty() && firstPartPath.back() == ':') p.relative=false;
} }
} }
return p; return p;

View File

@ -65,7 +65,7 @@ namespace Tesses::Framework::Http
} }
void StreamHttpRequestBody::Write(Tesses::Framework::Streams::Stream* strm) void StreamHttpRequestBody::Write(Tesses::Framework::Streams::Stream* strm)
{ {
strm->CopyTo(this->strm); this->strm->CopyTo(strm);
} }
StreamHttpRequestBody::~StreamHttpRequestBody() StreamHttpRequestBody::~StreamHttpRequestBody()
{ {
@ -706,4 +706,4 @@ namespace Tesses::Framework::Http
thrd.Join(); thrd.Join();
} }
} }

View File

@ -0,0 +1,263 @@
#include "TessesFramework/Platform/Environment.hpp"
#include "TessesFramework/Http/HttpUtils.hpp"
#if defined(TESSESFRAMEWORK_ENABLE_PLATFORMFOLDERS)
#include "sago/platform_folders.h"
#endif
#if defined(_WIN32)
#include <windows.h>
#endif
#if !defined(_WIN32)
extern char** environ;
#endif
using namespace Tesses::Framework::Filesystem;
namespace Tesses::Framework::Platform::Environment
{
#if defined(_WIN32)
const char EnvPathSeperator=';';
#else
const char EnvPathSeperator=':';
#endif
namespace SpecialFolders
{
VFSPath GetHomeFolder()
{
#if defined(TESSESFRAMEWORK_ENABLE_PLATFORMFOLDERS) && !defined(SAGO_DISABLE)
return sago::getHomeDir();
#elif defined(__EMSCRIPTEN__)
return (std::string)"/home/web_user";
#else
return (std::string)"/TF_User";
#endif
}
VFSPath GetDownloads()
{
#if defined(TESSESFRAMEWORK_ENABLE_PLATFORMFOLDERS) && !defined(SAGO_DISABLE)
return sago::getDownloadFolder();
#else
return GetHomeFolder() / "Downloads";
#endif
}
VFSPath GetMusic()
{
#if defined(TESSESFRAMEWORK_ENABLE_PLATFORMFOLDERS) && !defined(SAGO_DISABLE)
return sago::getMusicFolder();
#else
return GetHomeFolder() / "Music";
#endif
}
VFSPath GetPictures()
{
#if defined(TESSESFRAMEWORK_ENABLE_PLATFORMFOLDERS) && !defined(SAGO_DISABLE)
return sago::getPicturesFolder();
#else
return GetHomeFolder() / "Pictures";
#endif
}
VFSPath GetVideos()
{
#if defined(TESSESFRAMEWORK_ENABLE_PLATFORMFOLDERS) && !defined(SAGO_DISABLE)
return sago::getVideoFolder();
#else
return GetHomeFolder() / "Videos";
#endif
}
VFSPath GetDocuments()
{
#if defined(TESSESFRAMEWORK_ENABLE_PLATFORMFOLDERS) && !defined(SAGO_DISABLE)
return sago::getDocumentsFolder();
#else
return GetHomeFolder() / "Documents";
#endif
}
VFSPath GetConfig()
{
#if defined(TESSESFRAMEWORK_ENABLE_PLATFORMFOLDERS) && !defined(SAGO_DISABLE)
return sago::getConfigHome();
#else
return GetHomeFolder() / "Config";
#endif
}
VFSPath GetDesktop()
{
#if defined(TESSESFRAMEWORK_ENABLE_PLATFORMFOLDERS) && !defined(SAGO_DISABLE)
return sago::getDesktopFolder();
#else
return GetHomeFolder() / "Desktop";
#endif
}
VFSPath GetState()
{
#if defined(TESSESFRAMEWORK_ENABLE_PLATFORMFOLDERS) && !defined(SAGO_DISABLE)
return sago::getStateDir();
#else
return GetHomeFolder() / "State";
#endif
}
VFSPath GetCache()
{
#if defined(TESSESFRAMEWORK_ENABLE_PLATFORMFOLDERS) && !defined(SAGO_DISABLE)
return sago::getCacheDir();
#else
return GetHomeFolder() / "Cache";
#endif
}
VFSPath GetData()
{
#if defined(TESSESFRAMEWORK_ENABLE_PLATFORMFOLDERS) && !defined(SAGO_DISABLE)
return sago::getDataHome();
#else
return GetHomeFolder() / "Data";
#endif
}
}
VFSPath GetRealExecutablePath(VFSPath realPath)
{
using namespace Tesses::Framework::Http;
if(!realPath.relative) return realPath.MakeAbsolute();
if(LocalFS.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 newPathExt = newPath + item2;
if(LocalFS.FileExists(newPathExt)) return newPathExt;
}
auto newPath = LocalFS.SystemToVFSPath(item) / realPath;
if(LocalFS.FileExists(newPath)) return newPath;
}
return realPath;
#else
auto pathParts = HttpUtils::SplitString(path,":");
for(auto item : pathParts)
{
auto newPath = LocalFS.SystemToVFSPath(item) / realPath;
if(LocalFS.FileExists(newPath)) return newPath;
}
return realPath.MakeAbsolute();
#endif
}
std::optional<std::string> GetVariable(std::string name)
{
auto res = std::getenv(name.c_str());
if(res == nullptr) return std::nullopt;
std::string value = res;
return value;
}
void SetVariable(std::string name, std::optional<std::string> var)
{
if(var)
#if defined(_WIN32)
SetEnvironmentVariable(name.c_str(),var->c_str());
#else
setenv(name.c_str(), var->c_str(),1);
#endif
else
#if defined(_WIN32)
{
SetEnvironmentVariable(name.c_str(),NULL);
}
#else
unsetenv(name.c_str());
#endif
}
void GetEnvironmentVariables(std::vector<std::pair<std::string,std::string>>& env)
{
#if defined(_WIN32)
char *environ0 = GetEnvironmentStrings();
char* envthing = environ0;
while(*envthing)
{
auto items = Http::HttpUtils::SplitString(envthing,"=",2);
if(items.size() == 2)
{
env.push_back(std::pair<std::string,std::string>(items[0],items[1]));
}
else if(items.size() == 1)
{
env.push_back(std::pair<std::string,std::string>(items[0],""));
}
envthing += strlen(envthing)+1;
}
FreeEnvironmentStrings(environ0);
#else
for(char** envthing = environ; envthing != NULL; envthing++)
{
auto items = Http::HttpUtils::SplitString(*envthing,"=",2);
if(items.size() == 2)
{
env.push_back(std::pair<std::string,std::string>(items[0],items[1]));
}
else if(items.size() == 1)
{
env.push_back(std::pair<std::string,std::string>(items[0],""));
}
}
#endif
}
std::string GetPlatform()
{
#if defined(__SWITCH__)
return "Nintendo Switch";
#endif
#if defined(__PS2__)
return "PlayStation 2";
#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";
}
}

386
src/Platform/Process.cpp Normal file
View File

@ -0,0 +1,386 @@
#include "TessesFramework/Platform/Process.hpp"
#include "TessesFramework/Http/HttpUtils.hpp"
#include "TessesFramework/Platform/Environment.hpp"
#include <unistd.h>
#include <signal.h>
#include <sys/wait.h>
namespace Tesses::Framework::Platform {
class ProcessData {
public:
//TODO: Implement for WIN32
#if defined(_WIN32)
#elif defined(GEKKO) || defined(__PS2__) || defined(__SWITCH__)
#else
int stdin_strm;
int stdout_strm;
int stderr_strm;
pid_t pid;
#endif
ProcessData() {
//TODO: Implement for WIN32
#if defined(_WIN32)
#elif defined(GEKKO) || defined(__PS2__) || defined(__SWITCH__)
#else
this->stdin_strm=-1;
this->stdout_strm = -1;
this->stderr_strm=-1;
#endif
}
};
class ProcessStream : public Tesses::Framework::Streams::Stream {
#if defined(_WIN32)
#elif defined(GEKKO) || defined(__PS2__) defined(__SWITCH__)
#else
int strm;
bool writing;
bool shouldClose;
bool eos;
#endif
public:
#if defined(_WIN32)
#elif defined(GEKKO) || defined(__PS2__) defined(__SWITCH__)
#else
ProcessStream(int strm, bool writing, bool shouldClose)
{
this->strm = strm;
this->writing = writing;
this->shouldClose=shouldClose;
this->eos=false;
}
#endif
bool EndOfStream()
{
//TODO: Implement for WIN32
#if defined(_WIN32)
return true;
#elif defined(GEKKO) || defined(__PS2__) defined(__SWITCH__)
return true;
#else
return this->strm < 0 || eos;
#endif
}
bool CanRead()
{
//TODO: Implement for WIN32
#if defined(_WIN32)
return false;
#elif defined(GEKKO) || defined(__PS2__) defined(__SWITCH__)
return false;
#else
return !writing && this->strm > -1;
#endif
}
bool CanWrite()
{
//TODO: Implement for WIN32
#if defined(_WIN32)
return false;
#elif defined(GEKKO) || defined(__PS2__) defined(__SWITCH__)
return false;
#else
return writing && this->strm > -1;
#endif
}
size_t Read(uint8_t* buff, size_t sz)
{
//TODO: Implement for WIN32
#if defined(_WIN32)
return 0;
#elif defined(GEKKO) || defined(__PS2__) defined(__SWITCH__)
return 0;
#else
if(this->strm < 0 || this->eos && writing) return 0;
auto r = read(this->strm,buff,sz);
if(r == -1) return 0;
if(r == 0 && sz != 0) { this->eos=true; return 0;}
return (size_t)r;
#endif
}
size_t Write(const uint8_t* buff, size_t sz)
{
//TODO: Implement for WIN32
#if defined(_WIN32)
return 0;
#elif defined(GEKKO) || defined(__PS2__) defined(__SWITCH__)
return 0;
#else
if(this->strm < 0 && !writing) return 0;
auto r = write(this->strm,buff,sz);
if(r == -1) return 0;
return (size_t)r;
#endif
}
~ProcessStream()
{
//TODO: Implement for WIN32
#if defined(_WIN32)
#elif defined(GEKKO) || defined(__PS2__) defined(__SWITCH__)
//do nothing
#else
if(this->strm > -1 && this->shouldClose)
close(this->strm);
#endif
}
};
Process::Process() : Process("",{},true)
{
}
Process::Process(std::string name, std::vector<std::string> args,bool includeThisEnv) : Process(name,args,std::vector<std::pair<std::string,std::string>>(),includeThisEnv)
{
}
Process::Process(std::string name, std::vector<std::string> args, std::vector<std::pair<std::string,std::string>> env,bool includeThisEnv)
{
this->name = name;
this->args = args;
this->env = env;
this->includeThisEnv = includeThisEnv;
this->hidden.AllocField<ProcessData>();
}
Process::Process(std::string name, std::vector<std::string> args, std::vector<std::string> env,bool includeThisEnv) : Process(name,args,std::vector<std::pair<std::string,std::string>>(),includeThisEnv)
{
this->env.resize(env.size());
for(size_t i =0; i < env.size(); i++)
{
auto res=Http::HttpUtils::SplitString(env[i],"=",2);
if(res.size() == 2)
{
this->env[i].first = res[0];
this->env[i].second = res[1];
}
else if(res.size() == 1)
{
this->env[i].first = res[0];
this->env[i].second = "";
}
}
}
Process::~Process()
{
}
bool Process::Start()
{
auto p =
this->hidden.GetField<ProcessData*>();
std::vector<std::pair<std::string,std::string>> envs;
if(this->includeThisEnv)
Environment::GetEnvironmentVariables(envs);
for(auto itemNew : this->env)
{
bool has=false;
for(auto& item : envs)
{
if(item.first == itemNew.first)
{
item.second = itemNew.second;
has=true;
break;
}
}
if(!has) envs.push_back(itemNew);
}
#if defined(_WIN32)
return false;
#elif defined(GEKKO) || defined(__PS2__) defined(__SWITCH__)
return false;
#else
int strm_stdin[2];
int strm_stdout[2];
int strm_stderr[2];
if(this->redirectStdIn)
{
if(pipe(strm_stdin) == -1) return false;
p->stdin_strm = strm_stdin[1];
}
if(this->redirectStdOut)
{
if(pipe(strm_stdout) == -1)
{
if(this->redirectStdIn)
{
close(strm_stdin[0]);
close(strm_stdin[1]);
}
return false;
}
p->stdout_strm = strm_stdout[0];
}
if(this->redirectStdErr)
{
if(pipe(strm_stderr) == -1)
{
if(this->redirectStdIn)
{
close(strm_stdin[0]);
close(strm_stdin[1]);
}
if(this->redirectStdOut)
{
close(strm_stdout[0]);
close(strm_stdout[1]);
}
return false;
}
p->stderr_strm = strm_stderr[0];
}
auto pid=fork();
if(pid == -1) {
if(this->redirectStdIn)
{
close(strm_stdin[0]);
close(strm_stdin[1]);
}
if(this->redirectStdOut)
{
close(strm_stdout[0]);
close(strm_stdout[1]);
}
if(this->redirectStdErr)
{
close(strm_stderr[0]);
close(strm_stderr[1]);
}
return false;
}
if(pid == 0)
{
std::vector<std::string> env2;
env2.resize(envs.size());
for(size_t i = 0; i < envs.size(); i++)
{
env2[i] = envs[i].first + "=" + envs[i].second;
}
char** argv = new char*[args.size()+1];
argv[args.size()]=NULL;
char** envp = new char*[env2.size()+1];
envp[env.size()]=NULL;
for(size_t i = 0; i < args.size();i++)
{
argv[i] = (char*)args[i].c_str();
}
for(size_t i = 0; i < env.size();i++)
{
envp[i] = (char*)env2[i].c_str();
}
if(this->redirectStdIn)
{
dup2(strm_stdin[0],0);
close(strm_stdin[0]);
close(strm_stdin[1]);
}
if(this->redirectStdOut)
{
dup2(strm_stdout[1],1);
close(strm_stdout[0]);
close(strm_stdout[1]);
}
if(this->redirectStdErr)
{
dup2(strm_stderr[1],2);
close(strm_stderr[0]);
close(strm_stderr[1]);
}
execve(this->name.c_str(),argv,envp);
exit(1);
}
p->pid = pid;
if(this->redirectStdIn)
close(strm_stdin[0]);
if(this->redirectStdOut)
close(strm_stdout[1]);
if(this->redirectStdErr)
close(strm_stderr[1]);
return true;
#endif
}
void Process::Kill(int signal)
{
#if defined(_WIN32)
#elif defined(GEKKO) || defined(__PS2__) defined(__SWITCH__)
#else
kill(this->hidden.GetField<ProcessData*>()->pid,signal);
#endif
}
int Process::WaitForExit()
{
#if defined(_WIN32)
#elif defined(GEKKO) || defined(__PS2__) defined(__SWITCH__)
reutnr -1;
#else
int r;
if(waitpid(this->hidden.GetField<ProcessData*>()->pid,&r,0) != -1)
return r;
return -1;
#endif
}
Tesses::Framework::Streams::Stream* Process::GetStdinStream(bool closeUnderlying)
{
#if defined(_WIN32)
return nullptr;
#elif defined(GEKKO) || defined(__PS2__) defined(__SWITCH__)
return nullptr;
#else
return new ProcessStream(this->hidden.GetField<ProcessData*>()->stdin_strm,true,closeUnderlying);
#endif
}
Tesses::Framework::Streams::Stream* Process::GetStdoutStream(bool closeUnderlying)
{
#if defined(_WIN32)
return nullptr;
#elif defined(GEKKO) || defined(__PS2__) defined(__SWITCH__)
return nullptr;
#else
return new ProcessStream(this->hidden.GetField<ProcessData*>()->stdout_strm,false,closeUnderlying);
#endif
}
Tesses::Framework::Streams::Stream* Process::GetStderrStream(bool closeUnderlying)
{
#if defined(_WIN32)
return nullptr;
#elif defined(GEKKO) || defined(__PS2__) defined(__SWITCH__)
return nullptr;
#else
return new ProcessStream(this->hidden.GetField<ProcessData*>()->stderr_strm,false,closeUnderlying);
#endif
}
}

View File

@ -0,0 +1,472 @@
/*
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

@ -0,0 +1,305 @@
/*
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__) || defined(__PS2__)
#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 */

View File

@ -1,6 +1,11 @@
#if defined(TESSESFRAMEWORK_ENABLE_SDL2) #if defined(TESSESFRAMEWORK_ENABLE_SDL2)
#include "TessesFramework/SDL2/GUI.hpp" #include "TessesFramework/SDL2/GUI.hpp"
#include <iostream> #include <iostream>
#if defined(__SWITCH__)
extern "C" {
#include <switch.h>
}
#endif
namespace Tesses::Framework::SDL2 namespace Tesses::Framework::SDL2
{ {
GUI gui; GUI gui;
@ -17,11 +22,12 @@ namespace Tesses::Framework::SDL2
} }
if(this->windows.empty()) return; if(this->windows.empty()) return;
SDL_Event event; SDL_Event event;
while(SDL_PollEvent(&event)) while(SDL_PollEvent(&event))
{ {
for(auto win : this->windows) for(auto win : this->windows)
{ {
if(win == nullptr) continue; if(win == nullptr) continue;
@ -34,6 +40,14 @@ namespace Tesses::Framework::SDL2
win->Event(event); win->Event(event);
} }
break; break;
case SDL_EventType::SDL_FINGERDOWN:
case SDL_EventType::SDL_FINGERUP:
if(event.tfinger.windowID == id)
{
win->Event(event);
}
break;
case SDL_EventType::SDL_MOUSEBUTTONDOWN: case SDL_EventType::SDL_MOUSEBUTTONDOWN:
case SDL_EventType::SDL_MOUSEBUTTONUP: case SDL_EventType::SDL_MOUSEBUTTONUP:
if(event.button.windowID == id) if(event.button.windowID == id)
@ -198,6 +212,7 @@ namespace Tesses::Framework::SDL2
{ {
return "SDLEvent"; return "SDLEvent";
} }
GUIPalette::GUIPalette(bool isDarkMode, SDL_Color accent,int fontSize) GUIPalette::GUIPalette(bool isDarkMode, SDL_Color accent,int fontSize)
{ {

View File

@ -7,7 +7,16 @@
#include "TessesFramework/SDL2/Views/ProgressView.hpp" #include "TessesFramework/SDL2/Views/ProgressView.hpp"
#include "TessesFramework/SDL2/Views/TextListView.hpp" #include "TessesFramework/SDL2/Views/TextListView.hpp"
#include "TessesFramework/SDL2/Views/AbsoluteView.hpp" #include "TessesFramework/SDL2/Views/AbsoluteView.hpp"
#include "TessesFramework/SDL2/Views/EditTextView.hpp"
#include "TessesFramework/SDL2/Views/PictureView.hpp"
#include "TessesFramework/SDL2/ParseColor.hpp" #include "TessesFramework/SDL2/ParseColor.hpp"
#if defined(__SWITCH__)
extern "C" {
#include <switch.h>
}
#endif
namespace Tesses::Framework::SDL2 namespace Tesses::Framework::SDL2
{ {
void GUIWindow::MakeActive(View* view) void GUIWindow::MakeActive(View* view)
@ -119,6 +128,7 @@ namespace Tesses::Framework::SDL2
SDL_Rect r={.x=0,.y=0,.w=w,.h=h}; SDL_Rect r={.x=0,.y=0,.w=w,.h=h};
OnEvent(event,r,r); OnEvent(event,r,r);
} }
void GUIWindow::OnDraw(SDL_Renderer* renderer, SDL_Rect& r) void GUIWindow::OnDraw(SDL_Renderer* renderer, SDL_Rect& r)
{ {
SDL_SetRenderDrawColor(renderer,this->palette.background.r,this->palette.background.g,this->palette.background.b,this->palette.background.a); SDL_SetRenderDrawColor(renderer,this->palette.background.r,this->palette.background.g,this->palette.background.b,this->palette.background.a);
@ -144,9 +154,56 @@ namespace Tesses::Framework::SDL2
} }
GUIWindow::GUIWindow(std::string title, int w, int h, Uint32 flags, const GUIPalette& palette) : ContainerView(title) GUIWindow::GUIWindow(std::string title, int w, int h, Uint32 flags, const GUIPalette& palette) : ContainerView(title)
{ {
TF_LOG("About to create window");
#if defined(__SWITCH__)
auto nxwin = nwindowGetDefault();
w = (int)nxwin->default_width;
h = (int)nxwin->default_height;
flags = 0;
std::string onSwitch = "On switch: " + std::to_string(w) + "x" + std::to_string(h);
TF_LOG(onSwitch);
#endif
this->window = SDL_CreateWindow(title.c_str(),SDL_WINDOWPOS_CENTERED,SDL_WINDOWPOS_CENTERED,w,h,flags); this->window = SDL_CreateWindow(title.c_str(),SDL_WINDOWPOS_CENTERED,SDL_WINDOWPOS_CENTERED,w,h,flags);
std::string sdl_window_is_null = "SDL_Window is";
if(this->window != nullptr)
sdl_window_is_null.append(" not");
sdl_window_is_null.append(" null");
if(this->window == nullptr)
{
sdl_window_is_null.append(" reason ");
sdl_window_is_null.append(SDL_GetError());
}
TF_LOG(sdl_window_is_null);
/*#if defined(__SWITCH__) || defined(__PS2__) || defined(GEKKO)
this->renderer = SDL_CreateRenderer(this->window,-1,SDL_RENDERER_SOFTWARE);
#else*/
TF_LOG("About to create renderer");
this->renderer = SDL_CreateRenderer(this->window,-1,SDL_RENDERER_ACCELERATED); this->renderer = SDL_CreateRenderer(this->window,-1,SDL_RENDERER_ACCELERATED);
sdl_window_is_null = "SDL_Renderer is";
if(this->renderer!= nullptr)
sdl_window_is_null.append(" not");
sdl_window_is_null.append(" null");
if(this->renderer == nullptr)
{
sdl_window_is_null.append(" reason ");
sdl_window_is_null.append(SDL_GetError());
}
TF_LOG(sdl_window_is_null);
//#endif
SDL_SetRenderDrawBlendMode(renderer,SDL_BlendMode::SDL_BLENDMODE_BLEND); SDL_SetRenderDrawBlendMode(renderer,SDL_BlendMode::SDL_BLENDMODE_BLEND);
TF_LOG("Renderer blend mode set");
this->child=nullptr; this->child=nullptr;
this->parent=nullptr; this->parent=nullptr;
this->ownsChild=false; this->ownsChild=false;
@ -246,6 +303,16 @@ namespace Tesses::Framework::SDL2
} }
} }
} }
SDL_Window* GUIWindow::GetSDLWindow()
{
return this->window;
}
SDL_Renderer* GUIWindow::GetSDLRenderer()
{
return this->renderer;
}
View* GUIWindow::CreateViewFromJson(Tesses::Framework::Serialization::Json::JObject json) View* GUIWindow::CreateViewFromJson(Tesses::Framework::Serialization::Json::JObject json)
{ {
@ -349,6 +416,22 @@ namespace Tesses::Framework::SDL2
} }
return av; return av;
} }
else if(type == "EditTextView")
{
auto etv = new Views::EditTextView();
etv->SetId(id);
etv->SetText(text);
std::string hint;
json.TryGetValueAsType("Hint",hint);
etv->SetHint(hint);
return etv;
}
else if(type == "PictureView")
{
auto pv = new Views::PictureView();
pv->SetId(id);
return pv;
}
else { else {
GUIJsonViewNotFoundEventArgs e; GUIJsonViewNotFoundEventArgs e;
e.destView == nullptr; e.destView == nullptr;

View File

@ -1,6 +1,7 @@
#include "TessesFramework/SDL2/GUI.hpp" #include "TessesFramework/SDL2/GUI.hpp"
using namespace Tesses::Framework::Serialization::Json;
#if defined(TESSESFRAMEWORK_ENABLE_SDL2) #if defined(TESSESFRAMEWORK_ENABLE_SDL2)
using namespace Tesses::Framework::Serialization::Json;
#include "TessesFramework/SDL2/Views/ButtonView.hpp" #include "TessesFramework/SDL2/Views/ButtonView.hpp"
#include "TessesFramework/SDL2/Views/CheckView.hpp" #include "TessesFramework/SDL2/Views/CheckView.hpp"
#include "TessesFramework/SDL2/Views/LabelView.hpp" #include "TessesFramework/SDL2/Views/LabelView.hpp"
@ -81,7 +82,17 @@ namespace Tesses::Framework::SDL2
GUISDLEventEventArgs sdle; GUISDLEventEventArgs sdle;
sdle.event = event; sdle.event = event;
this->SDLEvent.Invoke(this,sdle); this->SDLEvent.Invoke(this,sdle);
if(event.type == SDL_MOUSEBUTTONDOWN) if(event.type == SDL_FINGERUP)
{
auto cord = this->GetCordFromEvent(event);
if(cord.first >= myVisibleBounds.x && cord.first < myVisibleBounds.x+myVisibleBounds.w && cord.second >= myVisibleBounds.y && cord.second < myVisibleBounds.y+myVisibleBounds.h) {
GUIEventArgs cea2;
OnClick(cea2);
this->Click.Invoke(this,cea2);
return true;
}
}
else if(event.type == SDL_MOUSEBUTTONDOWN)
{ {
if(event.button.x >= myVisibleBounds.x && event.button.x < myVisibleBounds.x+myVisibleBounds.w && event.button.y >= myVisibleBounds.y && event.button.y < myVisibleBounds.y+myVisibleBounds.h) if(event.button.x >= myVisibleBounds.x && event.button.x < myVisibleBounds.x+myVisibleBounds.w && event.button.y >= myVisibleBounds.y && event.button.y < myVisibleBounds.y+myVisibleBounds.h)
{ {
@ -95,7 +106,7 @@ namespace Tesses::Framework::SDL2
this->MouseDown.Invoke(this,cea); this->MouseDown.Invoke(this,cea);
} }
} }
if(event.type == SDL_MOUSEBUTTONUP) else if(event.type == SDL_MOUSEBUTTONUP)
{ {
if(this->GetViewFlag(VIEWFLAG_MOUSEDOWN_STATE)) if(this->GetViewFlag(VIEWFLAG_MOUSEDOWN_STATE))
{ {
@ -109,7 +120,7 @@ namespace Tesses::Framework::SDL2
this->MouseUp.Invoke(this,cea); this->MouseUp.Invoke(this,cea);
GUIEventArgs cea2; GUIEventArgs cea2;
OnClick(cea2); OnClick(cea2);
this->Click.Invoke(this,cea); this->Click.Invoke(this,cea2);
return true; return true;
} }
@ -162,7 +173,32 @@ namespace Tesses::Framework::SDL2
} }
return nullptr; return nullptr;
} }
std::pair<int,int> View::PreferedMinSize()
{
return std::pair<int,int>(-1,-1);
}
std::pair<int,int> View::GetCordFromEvent(SDL_Event& event)
{
switch(event.type)
{
case SDL_MOUSEBUTTONDOWN:
case SDL_MOUSEBUTTONUP:
return std::pair<int,int>(event.button.x,event.button.y);
break;
case SDL_FINGERUP:
case SDL_FINGERDOWN:
{
GUIWindow* win = this->GetWindow();
int w,h;
SDL_GetWindowSize(win->window,&w,&h);
return std::pair<int,int>(w*event.tfinger.x,h*event.tfinger.y);
}
break;
}
return std::pair<int,int>(-1,-1);
}
View::~View() View::~View()
{ {
@ -170,4 +206,4 @@ namespace Tesses::Framework::SDL2
} }
} }
#endif #endif

View File

@ -41,7 +41,7 @@ namespace Tesses::Framework::SDL2::Views
if(CallOnEvent(item.first.first,event,theirBounds, theirVisibleBounds)) if(CallOnEvent(item.first.first,event,theirBounds, theirVisibleBounds))
handled=true; handled=true;
if(handled && event.type != SDL_MOUSEBUTTONUP && event.type != SDL_MOUSEMOTION) if(handled && event.type != SDL_MOUSEBUTTONUP && event.type != SDL_MOUSEMOTION && event.type != SDL_FINGERUP)
{ {
GUISDLEventEventArgs sdle; GUISDLEventEventArgs sdle;
sdle.event = event; this->SDLEvent.Invoke(this,sdle); sdle.event = event; this->SDLEvent.Invoke(this,sdle);

View File

@ -35,6 +35,14 @@ namespace Tesses::Framework::SDL2::Views
this->GetWindow()->MakeActive(this); this->GetWindow()->MakeActive(this);
} }
} }
if(event.type == SDL_FINGERUP)
{
auto pos = this->GetCordFromEvent(event);
if(pos.first >= myVisibleBounds.x && pos.first < myVisibleBounds.x+myVisibleBounds.w && pos.second >= myVisibleBounds.y && pos.second < myVisibleBounds.y+myVisibleBounds.h)
{
this->GetWindow()->MakeActive(this);
}
}
return View::OnEvent(event,myBounds,myVisibleBounds); return View::OnEvent(event,myBounds,myVisibleBounds);
} }
void ButtonView::OnDraw(SDL_Renderer* renderer, SDL_Rect& r) void ButtonView::OnDraw(SDL_Renderer* renderer, SDL_Rect& r)

View File

@ -87,6 +87,18 @@ namespace Tesses::Framework::SDL2::Views
} }
} }
} }
if(event.type == SDL_FINGERUP)
{
auto pos = this->GetCordFromEvent(event);
if(pos.first >= visibleBounds.x && pos.first < visibleBounds.x+visibleBounds.w && pos.second >= visibleBounds.y && pos.second < visibleBounds.y+visibleBounds.h)
{
this->GetWindow()->MakeActive(this);
this->SetViewFlag(VIEWFLAG_CHECKED,!this->GetViewFlag(VIEWFLAG_CHECKED));
GUIEventArgs e;
this->OnCheckChanged(e);
this->CheckChanged.Invoke(this,e);
}
}
if(event.type == SDL_MOUSEBUTTONUP) if(event.type == SDL_MOUSEBUTTONUP)
{ {
if(event.button.x >= visibleBounds.x && event.button.x < visibleBounds.x+visibleBounds.w && event.button.y >= visibleBounds.y && event.button.y < visibleBounds.y+visibleBounds.h) if(event.button.x >= visibleBounds.x && event.button.x < visibleBounds.x+visibleBounds.w && event.button.y >= visibleBounds.y && event.button.y < visibleBounds.y+visibleBounds.h)

View File

@ -0,0 +1,384 @@
#if defined(TESSESFRAMEWORK_ENABLE_SDL2)
#include "TessesFramework/SDL2/Views/EditTextView.hpp"
namespace Tesses::Framework::SDL2::Views
{
EditTextView::EditTextView() : EditTextView(std::string())
{
}
EditTextView::EditTextView(std::string hint) : View()
{
this->hint = hint;
this->cursorPos=0;
this->cursorEnd=std::string::npos;
}
void EditTextView::TypeText(std::string text)
{
size_t cursorBegin = this->cursorPos;
size_t cursorEnd = this->cursorEnd;
if(cursorBegin > cursorEnd)
{
cursorBegin ^= cursorEnd;
cursorEnd ^= cursorBegin;
cursorBegin ^= cursorEnd;
}
if(cursorEnd != std::string::npos && cursorEnd <= this->text.size())
{
this->text.erase(cursorBegin,cursorEnd-cursorBegin);
this->text.insert(cursorBegin,text);
}
else if(cursorBegin <= this->text.size()) {
this->text.insert(cursorBegin,text);
}
this->cursorPos = cursorBegin+text.size();
this->cursorEnd = std::string::npos;
}
void EditTextView::SetText(std::string text)
{
View::SetText(text);
this->cursorPos=0;
this->cursorEnd = std::string::npos;
}
void EditTextView::SetHint(std::string hint)
{
this->hint = hint;
}
std::string EditTextView::GetHint()
{
return this->hint;
}
std::pair<int,int> EditTextView::PreferedMinSize()
{
int x=-2;
int y=-2;
auto win = this->GetWindow();
if(win != nullptr)
{
x=-1;
y=win->monospaced_font->MaxHeight()+16;
}
return std::pair<int,int>(x,y);
}
bool EditTextView::OnEvent(SDL_Event& event, SDL_Rect& myBounds, SDL_Rect& myVisibleBounds)
{
if(this->GetViewFlag(VIEWFLAG_ISACTIVE))
{
if(event.type == SDL_TEXTINPUT)
{
if(this->GetViewFlag(VIEWFLAG_TOUCHED))
{
this->SetViewFlag(VIEWFLAG_TOUCHED,false);
if(!this->text.empty())
{
this->cursorPos=0;
this->cursorEnd=this->text.size();
}
}
TypeText(event.text.text);
}
else if(event.type == SDL_KEYDOWN)
{
switch(event.key.keysym.sym)
{
case SDL_KeyCode::SDLK_c:
{
if((event.key.keysym.mod & KMOD_CTRL) != 0)
{
size_t cursorBegin = cursorPos;
size_t cursorEnd = this->cursorEnd;
if(cursorBegin > cursorEnd)
{
cursorBegin ^= cursorEnd;
cursorEnd ^= cursorBegin;
cursorBegin ^= cursorEnd;
}
if(cursorEnd != std::string::npos && cursorEnd <= this->text.size() && this->text.size() > 0)
{
std::string res = this->text.substr(cursorBegin,cursorEnd-cursorBegin);
//SDL_GetClipboardText()
SDL_SetClipboardText(res.c_str());
}
}
}
break;
case SDL_KeyCode::SDLK_v:
{
if((event.key.keysym.mod & KMOD_CTRL) != 0)
{
if(SDL_HasClipboardText())
{
char* text = SDL_GetClipboardText();
if(text != NULL)
{
TypeText(text);
}
SDL_free(text);
}
}
}
break;
case SDL_KeyCode::SDLK_x:
{
if((event.key.keysym.mod & KMOD_CTRL) != 0)
{
size_t cursorBegin = cursorPos;
size_t cursorEnd = this->cursorEnd;
if(cursorBegin > cursorEnd)
{
cursorBegin ^= cursorEnd;
cursorEnd ^= cursorBegin;
cursorBegin ^= cursorEnd;
}
if(cursorEnd != std::string::npos && cursorEnd <= this->text.size() && this->text.size() > 0)
{
std::string res = this->text.substr(cursorBegin,cursorEnd-cursorBegin);
//SDL_GetClipboardText()
SDL_SetClipboardText(res.c_str());
TypeText("");
}
}
}
break;
case SDL_KeyCode::SDLK_a:
{
if((event.key.keysym.mod & KMOD_CTRL) != 0)
{
this->cursorPos=0;
this->cursorEnd=this->text.size();
}
}
break;
case SDL_KeyCode::SDLK_BACKSPACE:
{
if(this->cursorEnd == std::string::npos)
{
if(this->cursorPos > 0)
{
this->cursorPos--;
this->text.erase(this->cursorPos,1);
}
}
else {
TypeText("");
}
}
break;
case SDL_KeyCode::SDLK_DELETE:
{
if(this->cursorEnd == std::string::npos)
{
if(this->cursorPos + 1 <= this->text.size())
{
this->text.erase(this->cursorPos,1);
}
}
else {
TypeText("");
}
}
break;
case SDL_KeyCode::SDLK_LEFT:
{
if((event.key.keysym.mod & KMOD_SHIFT) != 0)
{
if(this->cursorEnd > this->text.size())
this->cursorEnd = this->cursorPos;
this->cursorEnd--;
if(this->cursorEnd > this->text.size()) this->cursorEnd=0;
if(this->cursorEnd == this->cursorPos) this->cursorEnd = std::string::npos;
}
else
{
if(cursorPos > cursorEnd)
{
cursorPos ^= cursorEnd;
cursorEnd ^= cursorPos;
cursorPos ^= cursorEnd;
}
this->cursorPos--;
this->cursorEnd=std::string::npos;
if(this->cursorPos > this->text.size()) this->cursorPos=0;
}
}
break;
case SDL_KeyCode::SDLK_RIGHT:
if((event.key.keysym.mod & KMOD_SHIFT) != 0)
{
if(this->cursorEnd == std::string::npos)
this->cursorEnd = this->cursorPos;
this->cursorEnd++;
if(this->cursorEnd > this->text.size()) this->cursorEnd=this->text.size();
if(this->cursorEnd == this->cursorPos) this->cursorEnd = std::string::npos;
}
else
{
if(cursorPos > cursorEnd)
{
cursorPos ^= cursorEnd;
cursorEnd ^= cursorPos;
cursorPos ^= cursorEnd;
}
if(cursorEnd != std::string::npos)
{
this->cursorPos=cursorEnd+1;
}else {
this->cursorPos++;
}
this->cursorEnd=std::string::npos;
if(this->cursorPos > this->text.size()) this->cursorPos=this->text.size();
}
break;
}
}
}
if(event.type == SDL_MOUSEBUTTONDOWN)
{
if(event.button.x >= myVisibleBounds.x && event.button.x < myVisibleBounds.x+myVisibleBounds.w && event.button.y >= myVisibleBounds.y && event.button.y < myVisibleBounds.y+myVisibleBounds.h)
{
this->GetWindow()->MakeActive(this);
this->SetViewFlag(VIEWFLAG_TOUCHED,false);
SDL_StartTextInput();
}
}
if(event.type == SDL_FINGERDOWN)
{
auto pos = this->GetCordFromEvent(event);
if(pos.first >= myVisibleBounds.x && pos.first < myVisibleBounds.x+myVisibleBounds.w && pos.second >= myVisibleBounds.y && pos.second < myVisibleBounds.y+myVisibleBounds.h)
{
this->GetWindow()->MakeActive(this);
this->SetViewFlag(VIEWFLAG_TOUCHED,true);
SDL_StartTextInput();
}
}
return View::OnEvent(event,myBounds,myVisibleBounds);
}
void EditTextView::OnDraw(SDL_Renderer* renderer, SDL_Rect& r)
{
size_t cursorBegin = this->cursorPos;
size_t cursorEnd = this->cursorEnd;
if(cursorBegin > cursorEnd)
{
cursorBegin ^= cursorEnd;
cursorEnd ^= cursorBegin;
cursorBegin ^= cursorEnd;
}
auto win = this->GetWindow();
//SDL_SetRenderDrawColor(renderer,win->palette.accent.r,win->palette.accent.g,win->palette.accent.b,win->palette.accent.a);
//SDL_RenderFillRect(renderer,&r);
int textW=win->monospaced_font->MaxWidth()+2;
int textH=win->monospaced_font->MaxHeight();
int noChars = (r.w-16) / textW;
int x=0;
int y=(r.h/2)-((textH+16)/2);
x+=r.x+8;
y+=r.y+8;
auto isHovering = this->GetViewFlag(VIEWFLAG_HOVER_STATE);
auto isActive = this->GetViewFlag(VIEWFLAG_ISACTIVE);
auto isMouseDown = this->GetViewFlag(VIEWFLAG_MOUSEDOWN_STATE);
SDL_Color& color = win->palette.GetBorderColor(isHovering,isActive,isMouseDown);
size_t tracking = this->cursorPos;
if(cursorEnd != std::string::npos)
tracking = this->cursorEnd;
size_t off = noChars == 0 ? (size_t)0 : ((tracking / (size_t)noChars) * (size_t)noChars);
std::string& datext = this->text.empty() ? this->hint : this->text;
//printf("%i %i %i\n",(int) tracking,(int)off,(int)noChars);
for(size_t i = 0; i < (size_t)noChars; i++)
{
if(cursorEnd == std::string::npos && (i+off) == cursorBegin)
{
SDL_SetRenderDrawColor(renderer,color.r,color.g,color.b,color.a);
int x1=((int)i*textW)+x;
int y1 = y;
int y2 = y+textH;
SDL_RenderDrawLine(renderer,x1,y1,x1,y2);
}
if(i + off < datext.size())
{
if(cursorEnd != std::string::npos && (i+off) >= cursorBegin && (i+off) < cursorEnd)
{
SDL_Rect r0={.x=((int)i*textW)+x,.y=y,.w=textW,.h=textH+8};
SDL_SetRenderDrawColor(renderer,win->palette.accent.r,win->palette.accent.g,win->palette.accent.b,win->palette.accent.a);
SDL_RenderFillRect(renderer,&r0);
auto ch=win->monospaced_font->GetCharOfColor(datext[i+off],color);
SDL_Rect src={.x=0,.y=0,.w=0,.h=0};
SDL_QueryTexture(ch,NULL,NULL,&src.w,&src.h);
SDL_Rect dest = {.x=((int)i*textW)+x+1,.y=y,.w=src.w,.h=src.h};
SDL_RenderCopy(renderer,ch,&src,&dest);
}
else {
auto ch=win->monospaced_font->GetCharOfColor(datext[i+off],this->text.empty() ? color : win->palette.accent);
SDL_Rect src={.x=0,.y=0,.w=0,.h=0};
SDL_QueryTexture(ch,NULL,NULL,&src.w,&src.h);
SDL_Rect dest = {.x=((int)i*textW)+x+1,.y=y,.w=src.w,.h=src.h};
SDL_RenderCopy(renderer,ch,&src,&dest);
}
}
}
SDL_SetRenderDrawColor(renderer,color.r,color.g,color.b,color.a);
SDL_Rect r2={.x=r.x,.y=y-4,.w=r.w,.h=textH+16};
for(size_t i=0;i < 4; i++)
{
SDL_RenderDrawRect(renderer,&r2);
r2.x++;
r2.y++;
r2.w-=2;
r2.h-=2;
}
}
}
#endif

View File

@ -0,0 +1,54 @@
#if defined(TESSESFRAMEWORK_ENABLE_SDL2)
#include "TessesFramework/SDL2/Views/PictureView.hpp"
namespace Tesses::Framework::SDL2::Views
{
PictureView::PictureView()
{
this->tex = nullptr;
this->ownsTex=false;
this->surf = nullptr;
this->ownsSurf=false;
}
void PictureView::OnDraw(SDL_Renderer* renderer, SDL_Rect& r)
{
if(this->surf != nullptr)
{
this->SetPicture(SDL_CreateTextureFromSurface(renderer,this->surf));
if(this->ownsSurf) SDL_FreeSurface(this->surf);
this->surf=nullptr;
}
if(this->tex != nullptr)
{
SDL_Rect sr={.x=0,.y=0};
SDL_QueryTexture(this->tex,nullptr,nullptr,&sr.w,&sr.h);
SDL_RenderCopy(renderer,this->tex,&sr,&r);
}
}
void PictureView::SetPicture(SDL_Texture* tex, bool owns)
{
if(this->tex != nullptr && this->tex != tex && this->ownsTex)
SDL_DestroyTexture(this->tex);
this->tex = tex;
this->ownsTex = owns;
}
void PictureView::SetPicture(SDL_Surface* surface,bool owns)
{
if(this->surf != nullptr && this->surf != surf && this->ownsSurf)
SDL_FreeSurface(this->surf);
this->surf = surface;
this->ownsSurf = owns;
}
PictureView::~PictureView()
{
if(this->tex != nullptr && this->ownsTex)
SDL_DestroyTexture(this->tex);
if(this->surf != nullptr && this->ownsSurf)
SDL_FreeSurface(this->surf);
}
}
#endif

View File

@ -0,0 +1,80 @@
#include "TessesFramework/Serialization/SQLite.hpp"
#if defined(TESSESFRAMEWORK_ENABLE_SQLITE)
#include "sqlite/sqlite3.h"
#endif
namespace Tesses::Framework::Serialization {
int SQLiteDatabase::collector(void* user, int count,char** vals, char** keys)
{
auto list = static_cast<std::vector<std::vector<std::pair<std::string,std::optional<std::string>>>>*>(user);
std::vector<std::pair<std::string,std::optional<std::string>>> d;
for(int i = 0; i < count; i++)
{
std::string key = keys[i] == nullptr ? "" : keys[i];
std::optional<std::string> value = vals[i] == nullptr ? std::nullopt : (std::optional<std::string>)vals[i];
d.push_back(std::pair<std::string,std::optional<std::string>>(key,value));
}
list->push_back(d);
return 0;
}
SQLiteDatabase::SQLiteDatabase(Tesses::Framework::Filesystem::VFSPath path)
{
#if defined(TESSESFRAMEWORK_ENABLE_SQLITE)
auto name = path.ToString();
sqlite3* sqlite;
int rc =sqlite3_open(name.c_str(),&sqlite);
if(rc)
{
std::string error = sqlite3_errmsg(sqlite);
throw TextException(error);
}
this->data = static_cast<void*>(sqlite);
#endif
}
std::string SQLiteDatabase::Escape(std::string text)
{
std::string myStr = "\'";
for(auto c : text)
{
if(c == '\'') myStr += "\'\'";
else
myStr += c;
}
myStr += '\'';
return myStr;
}
bool SQLiteDatabase::IsEnabled()
{
#if defined(TESSESFRAMEWORK_ENABLE_SQLITE)
return true;
#endif
return false;
}
std::vector<std::vector<std::pair<std::string,std::optional<std::string>>>> SQLiteDatabase::Exec(std::string statement)
{
std::vector<std::vector<std::pair<std::string,std::optional<std::string>>>> items;
Exec(statement,items);
return items;
}
void SQLiteDatabase::Exec(std::string statement,std::vector<std::vector<std::pair<std::string,std::optional<std::string>>>>& items)
{
#if defined(TESSESFRAMEWORK_ENABLE_SQLITE)
char* err;
int res = sqlite3_exec(static_cast<sqlite3*>(this->data),statement.c_str(),SQLiteDatabase::collector,&items,&err);
if(res != SQLITE_OK)
{
std::string errstr = err == nullptr ? "" : err;
sqlite3_free(err);
throw TextException(errstr);
}
#endif
}
SQLiteDatabase::~SQLiteDatabase()
{
#if defined(TESSESFRAMEWORK_ENABLE_SQLITE)
sqlite3_close(static_cast<sqlite3*>(this->data));
#endif
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,719 @@
/*
** 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

@ -0,0 +1,655 @@
/*
** 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

@ -35,7 +35,7 @@ extern "C" {
#include <netdb.h> #include <netdb.h>
#include <fcntl.h> #include <fcntl.h>
#include <unistd.h> #include <unistd.h>
#if defined(AF_UNIX) #if defined(AF_UNIX) && !defined(GEKKO) && !defined(__SWITCH__) && !defined(__PS2__)
#include <sys/un.h> #include <sys/un.h>
#endif #endif
} }
@ -278,7 +278,7 @@ namespace Tesses::Framework::Streams {
this->endOfStream=false; this->endOfStream=false;
this->owns = true; this->owns = true;
this->success=false; this->success=false;
#if defined(AF_UNIX) #if defined(AF_UNIX) && !defined(GEKKO) && !defined(__PS2__) && !defined(__SWITCH__)
this->sock = NETWORK_SOCKET(AF_UNIX,SOCK_STREAM,0); this->sock = NETWORK_SOCKET(AF_UNIX,SOCK_STREAM,0);
if(this->sock < 0) if(this->sock < 0)
{ {
@ -319,7 +319,8 @@ namespace Tesses::Framework::Streams {
this->owns=true; this->owns=true;
this->valid=false; this->valid=false;
#if defined(AF_UNIX) #if defined(AF_UNIX) && !defined(GEKKO) && !defined(__PS2__) && !defined(__SWITCH__)
this->sock = NETWORK_SOCKET(AF_UNIX,SOCK_STREAM,0); this->sock = NETWORK_SOCKET(AF_UNIX,SOCK_STREAM,0);
if(this->sock < 0) if(this->sock < 0)
{ {

View File

@ -1,5 +1,5 @@
#include "TessesFramework/Streams/PtyStream.hpp" #include "TessesFramework/Streams/PtyStream.hpp"
#if !defined(GEKKO) && !defined(__PS2__) && !defined(_WIN32) #if !defined(GEKKO) && !defined(__PS2__) && !defined(_WIN32) && !defined(__SWITCH__)
#include <pty.h> #include <pty.h>
#include <fcntl.h> #include <fcntl.h>
#include <unistd.h> #include <unistd.h>
@ -10,7 +10,7 @@
namespace Tesses::Framework::Streams { namespace Tesses::Framework::Streams {
PtyStream::PtyStream(WindowSize windowSize,std::string filename, std::vector<std::string> args, std::vector<std::string> env) PtyStream::PtyStream(WindowSize windowSize,std::string filename, std::vector<std::string> args, std::vector<std::string> env)
{ {
#if !defined(GEKKO) && !defined(__PS2__) && !defined(_WIN32) #if !defined(GEKKO) && !defined(__PS2__) && !defined(_WIN32) && !defined(__SWITCH__)
this->wS = windowSize; this->wS = windowSize;
this->eos=false; this->eos=false;
winsize sz; winsize sz;
@ -80,7 +80,7 @@ namespace Tesses::Framework::Streams {
size_t PtyStream::Read(uint8_t* buff, size_t sz) size_t PtyStream::Read(uint8_t* buff, size_t sz)
{ {
if(this->eos) return 0; if(this->eos) return 0;
#if !defined(GEKKO) && !defined(__PS2__) && !defined(_WIN32) #if !defined(GEKKO) && !defined(__PS2__) && !defined(_WIN32) && !defined(__SWITCH__)
auto res = read(this->socket, buff,sz); auto res = read(this->socket, buff,sz);
if(res == -1) if(res == -1)
@ -96,7 +96,7 @@ namespace Tesses::Framework::Streams {
} }
size_t PtyStream::Write(const uint8_t* buff, size_t sz) size_t PtyStream::Write(const uint8_t* buff, size_t sz)
{ {
#if !defined(GEKKO) && !defined(__PS2__) && !defined(_WIN32) #if !defined(GEKKO) && !defined(__PS2__) && !defined(_WIN32) && !defined(__SWITCH__)
auto res = write(this->socket, buff,sz); auto res = write(this->socket, buff,sz);
return res; return res;
#else #else
@ -109,7 +109,7 @@ namespace Tesses::Framework::Streams {
} }
void PtyStream::Resize(WindowSize windowSize) void PtyStream::Resize(WindowSize windowSize)
{ {
#if !defined(GEKKO) && !defined(__PS2__) && !defined(_WIN32) #if !defined(GEKKO) && !defined(__PS2__) && !defined(_WIN32) && !defined(__SWITCH__)
this->wS = windowSize; this->wS = windowSize;
winsize sz; winsize sz;
sz.ws_col =(unsigned short)windowSize.Columns; sz.ws_col =(unsigned short)windowSize.Columns;
@ -123,7 +123,7 @@ namespace Tesses::Framework::Streams {
PtyStream::~PtyStream() PtyStream::~PtyStream()
{ {
this->eos=true; this->eos=true;
#if !defined(GEKKO) && !defined(__PS2__) && !defined(_WIN32) #if !defined(GEKKO) && !defined(__PS2__) && !defined(_WIN32) && !defined(__SWITCH__)
close(this->socket); close(this->socket);
kill((pid_t)this->pid,SIGHUP); kill((pid_t)this->pid,SIGHUP);

View File

@ -1,8 +1,21 @@
#include "TessesFramework/Common.hpp" #include "TessesFramework/Common.hpp"
#include "TessesFramework/Streams/NetworkStream.hpp" #include "TessesFramework/Streams/NetworkStream.hpp"
#include "TessesFramework/Lazy.hpp"
#include <atomic> #include <atomic>
#include <csignal> #include <csignal>
#include <iostream> #include <iostream>
#if defined(TESSESFRAMEWORK_ENABLE_SQLITE)
extern "C" {
#include "Serialization/sqlite/sqlite3.h"
}
#if defined(GEKKO) || defined(__SWITCH__) || defined(__PS2__)
extern "C" {
sqlite3_vfs *sqlite3_demovfs();
}
#endif
#endif
#if defined(_WIN32) #if defined(_WIN32)
#include <windows.h> #include <windows.h>
#undef min #undef min
@ -140,11 +153,22 @@ namespace Tesses::Framework
} }
void TF_Init() void TF_Init()
{ {
#if defined(TESSESFRAMEWORK_ENABLE_SQLITE)
sqlite3_initialize();
#if defined(GEKKO) || defined(__SWITCH__) || defined(__PS2__)
sqlite3_vfs_register(sqlite3_demovfs(),1);
#endif
#endif
#if defined(TESSESFRAMEWORK_ENABLE_SDL2) #if defined(TESSESFRAMEWORK_ENABLE_SDL2)
//SDL_SetHint(SDL_HINT_NO_SIGNAL_HANDLERS,"1"); //SDL_SetHint(SDL_HINT_NO_SIGNAL_HANDLERS,"1");
SDL_Init(SDL_INIT_EVERYTHING); SDL_Init(SDL_INIT_EVERYTHING);
TTF_Init(); TTF_Init();
int r = IMG_INIT_JPG | IMG_INIT_PNG | IMG_INIT_TIF | IMG_INIT_WEBP | IMG_INIT_JXL |IMG_INIT_AVIF; int r = IMG_INIT_JPG | IMG_INIT_PNG | IMG_INIT_TIF | IMG_INIT_WEBP
#if !defined(GEKKO) && !defined(__SWITCH__) && !defined(__PS2__)
| IMG_INIT_JXL |IMG_INIT_AVIF
#endif
;
if(IMG_Init( if(IMG_Init(
r r
) != r) ) != r)
@ -153,6 +177,8 @@ namespace Tesses::Framework
} }
#endif #endif
tzset(); tzset();
#if defined(_WIN32) #if defined(_WIN32)
system(" "); system(" ");

View File

@ -6,10 +6,6 @@
#undef min #undef min
#elif defined(GEKKO) #elif defined(GEKKO)
#include <ogc/mutex.h> #include <ogc/mutex.h>
#elif defined(__SWITCH__)
extern "C" {
#include <switch/kernel/mutex.h>
}
#else #else
#include <pthread.h> #include <pthread.h>
#endif #endif
@ -24,8 +20,6 @@ namespace Tesses::Framework::Threading
HANDLE mtx; HANDLE mtx;
#elif defined(GEKKO) #elif defined(GEKKO)
mutex_t mtx; mutex_t mtx;
#elif defined(__SWITCH__)
RMutex mtx;
#else #else
pthread_mutex_t mtx; pthread_mutex_t mtx;
pthread_mutexattr_t attr; pthread_mutexattr_t attr;
@ -36,7 +30,6 @@ namespace Tesses::Framework::Threading
CloseHandle(mtx); CloseHandle(mtx);
#elif defined(GEKKO) #elif defined(GEKKO)
LWP_MutexDestroy(mtx); LWP_MutexDestroy(mtx);
#elif defined(__SWITCH__)
#else #else
pthread_mutex_destroy(&mtx); pthread_mutex_destroy(&mtx);
@ -54,8 +47,7 @@ namespace Tesses::Framework::Threading
#elif defined(GEKKO) #elif defined(GEKKO)
md->mtx = LWP_MUTEX_NULL; md->mtx = LWP_MUTEX_NULL;
LWP_MutexInit(&md->mtx, true); LWP_MutexInit(&md->mtx, true);
#elif defined(__SWITCH__)
rmutexInit(&md->mtx);
#else #else
pthread_mutexattr_init(&md->attr); pthread_mutexattr_init(&md->attr);
pthread_mutexattr_settype(&md->attr,PTHREAD_MUTEX_RECURSIVE); pthread_mutexattr_settype(&md->attr,PTHREAD_MUTEX_RECURSIVE);
@ -72,8 +64,7 @@ namespace Tesses::Framework::Threading
WaitForSingleObject(md->mtx, INFINITE); WaitForSingleObject(md->mtx, INFINITE);
#elif defined(GEKKO) #elif defined(GEKKO)
LWP_MutexLock(md->mtx); LWP_MutexLock(md->mtx);
#elif defined(__SWITCH__)
rmutexLock(&md->mtx);
#else #else
pthread_mutex_lock(&md->mtx); pthread_mutex_lock(&md->mtx);
#endif #endif
@ -87,8 +78,7 @@ namespace Tesses::Framework::Threading
ReleaseMutex(md->mtx); ReleaseMutex(md->mtx);
#elif defined(GEKKO) #elif defined(GEKKO)
LWP_MutexUnlock(md->mtx); LWP_MutexUnlock(md->mtx);
#elif defined(__SWITCH__)
rmutexUnlock(&md->mtx);
#else #else
pthread_mutex_unlock(&md->mtx); pthread_mutex_unlock(&md->mtx);
#endif #endif
@ -102,8 +92,7 @@ namespace Tesses::Framework::Threading
return WaitForSingleObject(md->mtx, 100) == WAIT_OBJECT_0; return WaitForSingleObject(md->mtx, 100) == WAIT_OBJECT_0;
#elif defined(GEKKO) #elif defined(GEKKO)
return LWP_MutexTryLock(md->mtx) == 0; return LWP_MutexTryLock(md->mtx) == 0;
#elif defined(__SWITCH__)
return rmutexTryLock(&md->mtx);
#else #else
return pthread_mutex_trylock(&md->mtx) == 0; return pthread_mutex_trylock(&md->mtx) == 0;
#endif #endif

View File

@ -7,9 +7,8 @@
#if defined(__SWITCH__) #if defined(__SWITCH__)
extern "C" { extern "C" {
#include <switch.h> #include <switch.h>
#include <switch/kernel/thread.h> #include <pthread.h>
} }
using NxThread = Thread;
#endif #endif
namespace Tesses::Framework::Threading namespace Tesses::Framework::Threading
{ {
@ -21,12 +20,8 @@ namespace Tesses::Framework::Threading
Mutex needed_to_be_joined_mtx; Mutex needed_to_be_joined_mtx;
class NeedToBeJoinnedThread { class NeedToBeJoinnedThread {
#if defined(GEKKO)
static void* cb(void* data) static void* cb(void* data)
#elif defined(__SWITCH__) {
static void cb(void* data)
#endif
{
auto ntbjt = static_cast<NeedToBeJoinnedThread*>(data); auto ntbjt = static_cast<NeedToBeJoinnedThread*>(data);
@ -37,14 +32,12 @@ namespace Tesses::Framework::Threading
TF_LOG("Finished calling thread func"); TF_LOG("Finished calling thread func");
ntbjt->hasExited=true; ntbjt->hasExited=true;
#if defined(GEKKO) return NULL;
return NULL;
#endif
} }
std::function<void()> _cb; std::function<void()> _cb;
std::atomic<bool> hasInvoked=false; std::atomic<bool> hasInvoked=false;
#if defined(__SWITCH__) #if defined(__SWITCH__)
NxThread thrd; pthread_t thrd;
#elif defined(GEKKO) #elif defined(GEKKO)
lwp_t thrd; lwp_t thrd;
#endif #endif
@ -58,29 +51,8 @@ namespace Tesses::Framework::Threading
#if defined(GEKKO) #if defined(GEKKO)
LWP_CreateThread(&thrd, this->cb, static_cast<void*>(this), nullptr,12000, 98); LWP_CreateThread(&thrd, this->cb, static_cast<void*>(this), nullptr,12000, 98);
#elif defined(__SWITCH__) #elif defined(__SWITCH__)
TF_LOG("Before Thread create"); pthread_create(&thrd,NULL,this->cb,static_cast<void*>(this));
Result rc = threadCreate(&thrd,this->cb,
static_cast<void*>(this), NULL, 0x100000,
0x20 , 2);
if (R_FAILED(rc))
{
this->hasExited=true;
this->joinned=true;
TF_LOG("Failed to create Thread");
return;
}
TF_LOG("After Thread create, before starting");
rc = threadStart(&thrd);
if (R_FAILED(rc))
{
TF_LOG("Failed to start thread");
threadClose(&thrd);
this->hasExited=true;
this->joinned=true;
return;
}
TF_LOG("Starting");
#endif #endif
} }
std::atomic<bool> joinned; std::atomic<bool> joinned;
@ -102,8 +74,7 @@ namespace Tesses::Framework::Threading
} }
joinning=true; joinning=true;
#if defined(__SWITCH__) #if defined(__SWITCH__)
threadWaitForExit(&this->thrd); pthread_join(this->thrd,NULL);
threadClose(&this->thrd);
#elif defined(GEKKO) #elif defined(GEKKO)
void* res; void* res;
LWP_JoinThread(this->thrd,&res); LWP_JoinThread(this->thrd,&res);

View File

@ -14,13 +14,25 @@ namespace Tesses::Framework::Threading
return 1; return 1;
#endif #endif
} }
size_t ThreadPool::ThreadCount()
{
return this->threads.size();
}
bool ThreadPool::Empty()
{
bool qie;
this->mtx.Lock();
qie = this->callbacks.empty();
this->mtx.Unlock();
return qie;
}
ThreadPool::ThreadPool(size_t threads) ThreadPool::ThreadPool(size_t threads)
{ {
#if defined(TESSESFRAMEWORK_ENABLE_THREADING) #if defined(TESSESFRAMEWORK_ENABLE_THREADING)
this->isRunning=true; this->isRunning=true;
for(size_t i = 0; i < threads; i++) for(size_t i = 0; i < threads; i++)
{ {
this->threads.push_back(new Thread([this]()->void{ this->threads.push_back(new Thread([this,i]()->void{
while(true) while(true)
{ {
this->mtx.Lock(); this->mtx.Lock();
@ -31,22 +43,22 @@ namespace Tesses::Framework::Threading
return; return;
} }
std::function<void()> fn=nullptr; std::function<void(size_t)> fn=nullptr;
if(this->callbacks.empty()) if(!this->callbacks.empty())
{ {
fn=this->callbacks.front(); fn=this->callbacks.front();
this->callbacks.pop(); this->callbacks.pop();
} }
this->mtx.Unlock(); this->mtx.Unlock();
if(fn) if(fn)
fn(); fn(i);
} }
})); }));
} }
#endif #endif
} }
void ThreadPool::Schedule(std::function<void()> cb) void ThreadPool::Schedule(std::function<void(size_t)> cb)
{ {
#if defined(TESSESFRAMEWORK_ENABLE_THREADING) #if defined(TESSESFRAMEWORK_ENABLE_THREADING)
this->mtx.Lock(); this->mtx.Lock();