Move things from crosslang to here
This commit is contained in:
@ -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)
|
||||||
|
|||||||
@ -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)
|
||||||
|
|||||||
@ -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
|
||||||
|
|||||||
@ -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
110
examples/databaseex.cpp
Normal 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
|
||||||
@ -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++;
|
||||||
@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
34
include/TessesFramework/Platform/Environment.hpp
Normal file
34
include/TessesFramework/Platform/Environment.hpp
Normal 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);
|
||||||
|
}
|
||||||
|
|
||||||
39
include/TessesFramework/Platform/Process.hpp
Normal file
39
include/TessesFramework/Platform/Process.hpp
Normal 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();
|
||||||
|
};
|
||||||
|
}
|
||||||
@ -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);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
24
include/TessesFramework/SDL2/Views/EditTextView.hpp
Normal file
24
include/TessesFramework/SDL2/Views/EditTextView.hpp
Normal 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
|
||||||
22
include/TessesFramework/SDL2/Views/PictureView.hpp
Normal file
22
include/TessesFramework/SDL2/Views/PictureView.hpp
Normal 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
|
||||||
18
include/TessesFramework/Serialization/SQLite.hpp
Normal file
18
include/TessesFramework/Serialization/SQLite.hpp
Normal 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();
|
||||||
|
};
|
||||||
|
}
|
||||||
@ -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"
|
||||||
@ -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();
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -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);
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -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;
|
||||||
|
|||||||
@ -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()
|
||||||
{
|
{
|
||||||
|
|||||||
263
src/Platform/Environment.cpp
Normal file
263
src/Platform/Environment.cpp
Normal 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
386
src/Platform/Process.cpp
Normal 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
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
472
src/Platform/sago/platform_folders.cpp
Normal file
472
src/Platform/sago/platform_folders.cpp
Normal 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
|
||||||
305
src/Platform/sago/platform_folders.h
Normal file
305
src/Platform/sago/platform_folders.h
Normal 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 */
|
||||||
@ -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;
|
||||||
@ -18,10 +23,11 @@ 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)
|
||||||
@ -199,6 +213,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)
|
||||||
{
|
{
|
||||||
this->accent = accent;
|
this->accent = accent;
|
||||||
|
|||||||
@ -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;
|
||||||
|
|||||||
@ -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()
|
||||||
{
|
{
|
||||||
|
|||||||
@ -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);
|
||||||
|
|||||||
@ -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)
|
||||||
|
|||||||
@ -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)
|
||||||
|
|||||||
384
src/SDL2/Views/EditTextView.cpp
Normal file
384
src/SDL2/Views/EditTextView.cpp
Normal 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
|
||||||
54
src/SDL2/Views/PictureView.cpp
Normal file
54
src/SDL2/Views/PictureView.cpp
Normal 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
|
||||||
80
src/Serialization/SQLite.cpp
Normal file
80
src/Serialization/SQLite.cpp
Normal 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
|
||||||
|
}
|
||||||
|
}
|
||||||
257688
src/Serialization/sqlite/sqlite3.c
Normal file
257688
src/Serialization/sqlite/sqlite3.c
Normal file
File diff suppressed because it is too large
Load Diff
13431
src/Serialization/sqlite/sqlite3.h
Normal file
13431
src/Serialization/sqlite/sqlite3.h
Normal file
File diff suppressed because it is too large
Load Diff
719
src/Serialization/sqlite/sqlite3ext.h
Normal file
719
src/Serialization/sqlite/sqlite3ext.h
Normal 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 */
|
||||||
655
src/Serialization/sqlite/vfs.c
Normal file
655
src/Serialization/sqlite/vfs.c
Normal 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
|
||||||
@ -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)
|
||||||
{
|
{
|
||||||
|
|||||||
@ -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);
|
||||||
|
|||||||
@ -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(" ");
|
||||||
|
|||||||
@ -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
|
||||||
|
|||||||
@ -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,11 +20,7 @@ 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);
|
||||||
|
|||||||
@ -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();
|
||||||
|
|||||||
Reference in New Issue
Block a user