Fill Process on Windows
This commit is contained in:
2
.gitignore
vendored
2
.gitignore
vendored
@ -1,3 +1,5 @@
|
|||||||
build
|
build
|
||||||
builds
|
builds
|
||||||
.vscode
|
.vscode
|
||||||
|
out
|
||||||
|
/.vs
|
||||||
|
|||||||
@ -27,6 +27,7 @@ src/Streams/BufferedStream.cpp
|
|||||||
src/Streams/ByteReader.cpp
|
src/Streams/ByteReader.cpp
|
||||||
src/Streams/ByteWriter.cpp
|
src/Streams/ByteWriter.cpp
|
||||||
src/Streams/PtyStream.cpp
|
src/Streams/PtyStream.cpp
|
||||||
|
src/Text/StringConverter.cpp
|
||||||
src/TextStreams/StreamReader.cpp
|
src/TextStreams/StreamReader.cpp
|
||||||
src/TextStreams/StreamWriter.cpp
|
src/TextStreams/StreamWriter.cpp
|
||||||
src/TextStreams/TextReader.cpp
|
src/TextStreams/TextReader.cpp
|
||||||
@ -93,12 +94,17 @@ option(TESSESFRAMEWORK_ENABLE_SETDATE "Enable setting date to file" ON)
|
|||||||
option(TESSESFRAMEWORK_LOGTOFILE "TessesFramework Log to file" OFF)
|
option(TESSESFRAMEWORK_LOGTOFILE "TessesFramework Log to file" OFF)
|
||||||
option(TESSESFRAMEWORK_ENABLE_SDL2 "Enable SDL2" OFF)
|
option(TESSESFRAMEWORK_ENABLE_SDL2 "Enable SDL2" OFF)
|
||||||
option(TESSESFRAMEWORK_FETCHCONTENT "TessesFramework fetchcontent" OFF)
|
option(TESSESFRAMEWORK_FETCHCONTENT "TessesFramework fetchcontent" OFF)
|
||||||
|
option(TESSESFRAMEWORK_VENDERCERTCHAIN "Use the ca-certificates.crt in project rather than system" ON)
|
||||||
if(TESSESFRAMEWORK_FETCHCONTENT)
|
if(TESSESFRAMEWORK_FETCHCONTENT)
|
||||||
set(TESSESFRAMEWORK_CERT_BUNDLE_FILE "${CMAKE_CURRENT_SOURCE_DIR}/ca-certificates.crt" CACHE FILEPATH "Path to ca-chain")
|
set(TESSESFRAMEWORK_CERT_BUNDLE_FILE "${CMAKE_CURRENT_SOURCE_DIR}/ca-certificates.crt" CACHE FILEPATH "Path to ca-chain")
|
||||||
include(FetchContent)
|
include(FetchContent)
|
||||||
else()
|
else()
|
||||||
|
if(TESSESFRAMEWORK_VENDERCERTCHAIN)
|
||||||
|
set(TESSESFRAMEWORK_CERT_BUNDLE_FILE "${CMAKE_CURRENT_SOURCE_DIR}/ca-certificates.crt" CACHE FILEPATH "Path to ca-chain")
|
||||||
|
else()
|
||||||
set(TESSESFRAMEWORK_CERT_BUNDLE_FILE "/etc/ssl/certs/ca-certificates.crt" CACHE FILEPATH "Path to ca-chain")
|
set(TESSESFRAMEWORK_CERT_BUNDLE_FILE "/etc/ssl/certs/ca-certificates.crt" CACHE FILEPATH "Path to ca-chain")
|
||||||
endif()
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/include)
|
file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/include)
|
||||||
|
|
||||||
@ -148,8 +154,8 @@ set(USE_SHARED_MBEDTLS_LIBRARY ON)
|
|||||||
endif()
|
endif()
|
||||||
FetchContent_Declare(
|
FetchContent_Declare(
|
||||||
mbedtls
|
mbedtls
|
||||||
GIT_REPOSITORY https://github.com/Mbed-TLS/mbedtls.git
|
URL https://downloads.tesses.net/cache/libraries/source/mbedtls-3.6.3.1.tar.bz2
|
||||||
GIT_PROGRESS TRUE
|
|
||||||
)
|
)
|
||||||
FetchContent_MakeAvailable(mbedtls)
|
FetchContent_MakeAvailable(mbedtls)
|
||||||
else()
|
else()
|
||||||
@ -281,14 +287,15 @@ endif()
|
|||||||
add_library(tessesframework_shared SHARED ${TESSESFRAMEWORK_SOURCE})
|
add_library(tessesframework_shared SHARED ${TESSESFRAMEWORK_SOURCE})
|
||||||
TESSESFRAMEWORK_LINKDEPS(tessesframework_shared)
|
TESSESFRAMEWORK_LINKDEPS(tessesframework_shared)
|
||||||
|
|
||||||
if(TESSESFRAMEWORK_FETCHCONTENT AND TESSESFRAMEWORK_ENABLE_MBED)
|
if(TESSESFRAMEWORK_ENABLE_MBED)
|
||||||
|
if(TESSESFRAMEWORK_FETCHCONTENT)
|
||||||
target_link_libraries(tessesframework_shared PUBLIC mbedtls mbedx509 mbedcrypto everest p256m)
|
target_link_libraries(tessesframework_shared PUBLIC mbedtls mbedx509 mbedcrypto everest p256m)
|
||||||
|
|
||||||
else()
|
else()
|
||||||
target_link_libraries(tessesframework_shared PUBLIC mbedtls mbedx509 mbedcrypto)
|
target_link_libraries(tessesframework_shared PUBLIC mbedtls mbedx509 mbedcrypto)
|
||||||
|
|
||||||
endif()
|
endif()
|
||||||
|
endif()
|
||||||
list(APPEND TessesFrameworkLibs tessesframework_shared)
|
list(APPEND TessesFrameworkLibs tessesframework_shared)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
|||||||
89
CMakePresets.json
Normal file
89
CMakePresets.json
Normal file
@ -0,0 +1,89 @@
|
|||||||
|
{
|
||||||
|
"version": 3,
|
||||||
|
"configurePresets": [
|
||||||
|
{
|
||||||
|
"name": "linux-debug",
|
||||||
|
"displayName": "Linux Debug",
|
||||||
|
"description": "Target the Windows Subsystem for Linux (WSL) or a remote Linux system.",
|
||||||
|
"generator": "Ninja",
|
||||||
|
"binaryDir": "${sourceDir}/out/build/${presetName}",
|
||||||
|
"installDir": "${sourceDir}/out/install/${presetName}",
|
||||||
|
"cacheVariables": { "CMAKE_BUILD_TYPE": "Debug" },
|
||||||
|
"condition": {
|
||||||
|
"type": "equals",
|
||||||
|
"lhs": "${hostSystemName}",
|
||||||
|
"rhs": "Linux"
|
||||||
|
},
|
||||||
|
"vendor": { "microsoft.com/VisualStudioRemoteSettings/CMake/2.0": { "remoteSourceRootDir": "$env{HOME}/.vs/$ms{projectDirName}" } }
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "macos-debug",
|
||||||
|
"displayName": "macOS Debug",
|
||||||
|
"description": "Target a remote macOS system.",
|
||||||
|
"generator": "Ninja",
|
||||||
|
"binaryDir": "${sourceDir}/out/build/${presetName}",
|
||||||
|
"installDir": "${sourceDir}/out/install/${presetName}",
|
||||||
|
"cacheVariables": { "CMAKE_BUILD_TYPE": "Debug" },
|
||||||
|
"condition": {
|
||||||
|
"type": "equals",
|
||||||
|
"lhs": "${hostSystemName}",
|
||||||
|
"rhs": "Darwin"
|
||||||
|
},
|
||||||
|
"vendor": { "microsoft.com/VisualStudioRemoteSettings/CMake/1.0": { "sourceDir": "$env{HOME}/.vs/$ms{projectDirName}" } }
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "windows-base",
|
||||||
|
"description": "Target Windows with the Visual Studio development environment.",
|
||||||
|
"hidden": true,
|
||||||
|
"generator": "Ninja",
|
||||||
|
"binaryDir": "${sourceDir}/out/build/${presetName}",
|
||||||
|
"installDir": "${sourceDir}/out/install/${presetName}",
|
||||||
|
"cacheVariables": {
|
||||||
|
"CMAKE_C_COMPILER": "cl.exe",
|
||||||
|
"CMAKE_CXX_COMPILER": "cl.exe",
|
||||||
|
"TESSESFRAMEWORK_FETCHCONTENT": true
|
||||||
|
},
|
||||||
|
"condition": {
|
||||||
|
"type": "equals",
|
||||||
|
"lhs": "${hostSystemName}",
|
||||||
|
"rhs": "Windows"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "x64-debug",
|
||||||
|
"displayName": "x64 Debug",
|
||||||
|
"description": "Target Windows (64-bit) with the Visual Studio development environment. (Debug)",
|
||||||
|
"inherits": "windows-base",
|
||||||
|
"architecture": {
|
||||||
|
"value": "x64",
|
||||||
|
"strategy": "external"
|
||||||
|
},
|
||||||
|
"cacheVariables": { "CMAKE_BUILD_TYPE": "Debug" }
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "x64-release",
|
||||||
|
"displayName": "x64 Release",
|
||||||
|
"description": "Target Windows (64-bit) with the Visual Studio development environment. (RelWithDebInfo)",
|
||||||
|
"inherits": "x64-debug",
|
||||||
|
"cacheVariables": { "CMAKE_BUILD_TYPE": "Release" }
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "x86-debug",
|
||||||
|
"displayName": "x86 Debug",
|
||||||
|
"description": "Target Windows (32-bit) with the Visual Studio development environment. (Debug)",
|
||||||
|
"inherits": "windows-base",
|
||||||
|
"architecture": {
|
||||||
|
"value": "x86",
|
||||||
|
"strategy": "external"
|
||||||
|
},
|
||||||
|
"cacheVariables": { "CMAKE_BUILD_TYPE": "Debug" }
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "x86-release",
|
||||||
|
"displayName": "x86 Release",
|
||||||
|
"description": "Target Windows (32-bit) with the Visual Studio development environment. (RelWithDebInfo)",
|
||||||
|
"inherits": "x86-debug",
|
||||||
|
"cacheVariables": { "CMAKE_BUILD_TYPE": "Release" }
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@ -10,17 +10,22 @@ class Process {
|
|||||||
public:
|
public:
|
||||||
std::string name;
|
std::string name;
|
||||||
std::vector<std::string> args;
|
std::vector<std::string> args;
|
||||||
|
std::string workingDirectory;
|
||||||
std::vector<std::pair<std::string,std::string>> env;
|
std::vector<std::pair<std::string,std::string>> env;
|
||||||
bool includeThisEnv;
|
bool includeThisEnv;
|
||||||
bool redirectStdIn=false;
|
bool redirectStdIn=false;
|
||||||
bool redirectStdOut=false;
|
bool redirectStdOut=false;
|
||||||
bool redirectStdErr=false;
|
bool redirectStdErr=false;
|
||||||
//YOU ARE RESPONSABLE FOR FREEING THIS STREAM
|
|
||||||
Tesses::Framework::Streams::Stream* GetStdinStream(bool closeUnderlying=true);
|
void CloseStdInNow();
|
||||||
//YOU ARE RESPONSABLE FOR FREEING THIS STREAM
|
//YOU ARE RESPONSABLE FOR FREEING THIS STREAM OBJECT
|
||||||
Tesses::Framework::Streams::Stream* GetStdoutStream(bool closeUnderlying=true);
|
|
||||||
//YOU ARE RESPONSABLE FOR FREEING THIS STREAM
|
Tesses::Framework::Streams::Stream* GetStdinStream();
|
||||||
Tesses::Framework::Streams::Stream* GetStderrStream(bool closeUnderlying=true);
|
|
||||||
|
//YOU ARE RESPONSABLE FOR FREEING THIS STREAM OBJECT
|
||||||
|
Tesses::Framework::Streams::Stream* GetStdoutStream();
|
||||||
|
//YOU ARE RESPONSABLE FOR FREEING THIS STREAM OBJECT
|
||||||
|
Tesses::Framework::Streams::Stream* GetStderrStream();
|
||||||
|
|
||||||
Process();
|
Process();
|
||||||
Process(std::string name, std::vector<std::string> args,bool includeThisEnv=true);
|
Process(std::string name, std::vector<std::string> args,bool includeThisEnv=true);
|
||||||
|
|||||||
@ -18,6 +18,7 @@
|
|||||||
#include "TextStreams/StdIOWriter.hpp"
|
#include "TextStreams/StdIOWriter.hpp"
|
||||||
#include "TextStreams/StringReader.hpp"
|
#include "TextStreams/StringReader.hpp"
|
||||||
#include "TextStreams/StringWriter.hpp"
|
#include "TextStreams/StringWriter.hpp"
|
||||||
|
#include "Text/StringConverter.hpp"
|
||||||
#include "Threading/Thread.hpp"
|
#include "Threading/Thread.hpp"
|
||||||
#include "Threading/Mutex.hpp"
|
#include "Threading/Mutex.hpp"
|
||||||
#include "Threading/ThreadPool.hpp"
|
#include "Threading/ThreadPool.hpp"
|
||||||
|
|||||||
19
include/TessesFramework/Text/StringConverter.hpp
Normal file
19
include/TessesFramework/Text/StringConverter.hpp
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
#pragma once
|
||||||
|
#include <string>
|
||||||
|
namespace Tesses::Framework::Text::StringConverter {
|
||||||
|
class UTF8 {
|
||||||
|
public:
|
||||||
|
static void FromUTF16(std::basic_string<char>& utf8, const std::basic_string<char16_t>& utf16);
|
||||||
|
static void FromUTF32(std::basic_string<char>& utf8, const std::basic_string<char32_t>& utf32);
|
||||||
|
};
|
||||||
|
class UTF16 {
|
||||||
|
public:
|
||||||
|
static void FromUTF8(std::basic_string<char16_t>& utf16, const std::basic_string<char>& utf8);
|
||||||
|
static void FromUTF32(std::basic_string<char16_t>& utf16, const std::basic_string<char32_t>& utf32);
|
||||||
|
};
|
||||||
|
class UTF32 {
|
||||||
|
public:
|
||||||
|
static void FromUTF8(std::basic_string<char32_t>& utf32, const std::basic_string<char>& utf8);
|
||||||
|
static void FromUTF16(std::basic_string<char32_t>& utf32, const std::basic_string<char16_t>& utf16);
|
||||||
|
};
|
||||||
|
}
|
||||||
@ -5,6 +5,9 @@
|
|||||||
#endif
|
#endif
|
||||||
#if defined(_WIN32)
|
#if defined(_WIN32)
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
|
#include "TessesFramework/Filesystem/VFSFix.hpp"
|
||||||
|
#include "TessesFramework/Text/StringConverter.hpp"
|
||||||
|
using namespace Tesses::Framework::Text::StringConverter;
|
||||||
#endif
|
#endif
|
||||||
#if !defined(_WIN32)
|
#if !defined(_WIN32)
|
||||||
extern char** environ;
|
extern char** environ;
|
||||||
@ -128,12 +131,13 @@ namespace Tesses::Framework::Platform::Environment
|
|||||||
auto pathParts = HttpUtils::SplitString(path,";");
|
auto pathParts = HttpUtils::SplitString(path,";");
|
||||||
for(auto item : pathParts)
|
for(auto item : pathParts)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
auto newPath = LocalFS.SystemToVFSPath(item) / realPath;
|
||||||
for(auto item2 : pext)
|
for(auto item2 : pext)
|
||||||
{
|
{
|
||||||
auto newPathExt = newPath + item2;
|
auto newPathExt = newPath + item2;
|
||||||
if(LocalFS.FileExists(newPathExt)) return newPathExt;
|
if(LocalFS.FileExists(newPathExt)) return newPathExt;
|
||||||
}
|
}
|
||||||
auto newPath = LocalFS.SystemToVFSPath(item) / realPath;
|
|
||||||
if(LocalFS.FileExists(newPath)) return newPath;
|
if(LocalFS.FileExists(newPath)) return newPath;
|
||||||
}
|
}
|
||||||
return realPath;
|
return realPath;
|
||||||
@ -158,16 +162,28 @@ namespace Tesses::Framework::Platform::Environment
|
|||||||
}
|
}
|
||||||
void SetVariable(std::string name, std::optional<std::string> var)
|
void SetVariable(std::string name, std::optional<std::string> var)
|
||||||
{
|
{
|
||||||
if(var)
|
if (var)
|
||||||
#if defined(_WIN32)
|
#if defined(_WIN32)
|
||||||
SetEnvironmentVariable(name.c_str(),var->c_str());
|
{
|
||||||
|
std::u16string nameu16 = {};
|
||||||
|
|
||||||
|
std::u16string varu16 = {};
|
||||||
|
|
||||||
|
UTF16::FromUTF8(nameu16, name);
|
||||||
|
UTF16::FromUTF8(varu16, var.value());
|
||||||
|
SetEnvironmentVariableW((LPCWSTR)nameu16.c_str(),(LPCWSTR)varu16.c_str());
|
||||||
|
}
|
||||||
#else
|
#else
|
||||||
setenv(name.c_str(), var->c_str(),1);
|
setenv(name.c_str(), var->c_str(),1);
|
||||||
#endif
|
#endif
|
||||||
else
|
else
|
||||||
#if defined(_WIN32)
|
#if defined(_WIN32)
|
||||||
{
|
{
|
||||||
SetEnvironmentVariable(name.c_str(),NULL);
|
std::u16string nameu16 = {};
|
||||||
|
|
||||||
|
UTF16::FromUTF8(nameu16, name);
|
||||||
|
|
||||||
|
SetEnvironmentVariableW((LPCWSTR)nameu16.c_str(),NULL);
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
unsetenv(name.c_str());
|
unsetenv(name.c_str());
|
||||||
@ -179,11 +195,14 @@ namespace Tesses::Framework::Platform::Environment
|
|||||||
void GetEnvironmentVariables(std::vector<std::pair<std::string,std::string>>& env)
|
void GetEnvironmentVariables(std::vector<std::pair<std::string,std::string>>& env)
|
||||||
{
|
{
|
||||||
#if defined(_WIN32)
|
#if defined(_WIN32)
|
||||||
char *environ0 = GetEnvironmentStrings();
|
auto environ0 = GetEnvironmentStringsW();
|
||||||
char* envthing = environ0;
|
auto envthing = environ0;
|
||||||
while(*envthing)
|
while(*envthing)
|
||||||
{
|
{
|
||||||
auto items = Http::HttpUtils::SplitString(envthing,"=",2);
|
std::u16string str = (const char16_t*)envthing;
|
||||||
|
std::string stru8;
|
||||||
|
UTF8::FromUTF16(stru8, str);
|
||||||
|
auto items = Http::HttpUtils::SplitString(stru8, "=", 2);
|
||||||
if(items.size() == 2)
|
if(items.size() == 2)
|
||||||
{
|
{
|
||||||
|
|
||||||
@ -193,9 +212,9 @@ namespace Tesses::Framework::Platform::Environment
|
|||||||
{
|
{
|
||||||
env.push_back(std::pair<std::string,std::string>(items[0],""));
|
env.push_back(std::pair<std::string,std::string>(items[0],""));
|
||||||
}
|
}
|
||||||
envthing += strlen(envthing)+1;
|
envthing += str.size() + 1;
|
||||||
}
|
}
|
||||||
FreeEnvironmentStrings(environ0);
|
FreeEnvironmentStringsW(environ0);
|
||||||
#else
|
#else
|
||||||
for(char** envthing = environ; envthing != NULL; envthing++)
|
for(char** envthing = environ; envthing != NULL; envthing++)
|
||||||
{
|
{
|
||||||
|
|||||||
@ -3,16 +3,63 @@
|
|||||||
#include "TessesFramework/Platform/Environment.hpp"
|
#include "TessesFramework/Platform/Environment.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
#if defined(_WIN32)
|
||||||
|
extern "C" {
|
||||||
|
#include <windows.h>
|
||||||
|
}
|
||||||
|
#include "TessesFramework/Filesystem/VFSFix.hpp"
|
||||||
|
#include 'TessesFramework/Text/StringConverter.hpp'
|
||||||
|
using namespace Tesses::Framework::Text::StringConverter;
|
||||||
|
static void escape_windows_args(std::string& str, std::vector<std::string> args)
|
||||||
|
{
|
||||||
|
bool first = true;
|
||||||
|
for (auto item : args)
|
||||||
|
{
|
||||||
|
if (first)
|
||||||
|
{
|
||||||
|
str.push_back('\"');
|
||||||
|
first = false;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
str.append(" \"");
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto c : item)
|
||||||
|
{
|
||||||
|
if (c == '"') str.append("\\\"");
|
||||||
|
else str.push_back(c);
|
||||||
|
}
|
||||||
|
|
||||||
|
str.push_back('\"');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#else
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
#include <sys/wait.h>
|
#include <sys/wait.h>
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
namespace Tesses::Framework::Platform {
|
namespace Tesses::Framework::Platform {
|
||||||
|
|
||||||
class ProcessData {
|
class ProcessData {
|
||||||
public:
|
public:
|
||||||
//TODO: Implement for WIN32
|
//TODO: Implement for WIN32
|
||||||
#if defined(_WIN32)
|
#if defined(_WIN32)
|
||||||
|
STARTUPINFO si;
|
||||||
|
PROCESS_INFORMATION pi;
|
||||||
|
|
||||||
|
HANDLE stdin_strm;
|
||||||
|
HANDLE stdout_strm;
|
||||||
|
HANDLE stderr_strm;
|
||||||
|
|
||||||
|
|
||||||
#elif defined(GEKKO) || defined(__PS2__) || defined(__SWITCH__)
|
#elif defined(GEKKO) || defined(__PS2__) || defined(__SWITCH__)
|
||||||
#else
|
#else
|
||||||
int stdin_strm;
|
int stdin_strm;
|
||||||
@ -23,6 +70,11 @@ namespace Tesses::Framework::Platform {
|
|||||||
ProcessData() {
|
ProcessData() {
|
||||||
//TODO: Implement for WIN32
|
//TODO: Implement for WIN32
|
||||||
#if defined(_WIN32)
|
#if defined(_WIN32)
|
||||||
|
stdin_strm = NULL;
|
||||||
|
stdout_strm = NULL;
|
||||||
|
stderr_strm = NULL;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#elif defined(GEKKO) || defined(__PS2__) || defined(__SWITCH__)
|
#elif defined(GEKKO) || defined(__PS2__) || defined(__SWITCH__)
|
||||||
|
|
||||||
@ -35,23 +87,30 @@ namespace Tesses::Framework::Platform {
|
|||||||
};
|
};
|
||||||
class ProcessStream : public Tesses::Framework::Streams::Stream {
|
class ProcessStream : public Tesses::Framework::Streams::Stream {
|
||||||
#if defined(_WIN32)
|
#if defined(_WIN32)
|
||||||
|
HANDLE strm;
|
||||||
|
bool writing;
|
||||||
|
bool eos;
|
||||||
#elif defined(GEKKO) || defined(__PS2__) defined(__SWITCH__)
|
#elif defined(GEKKO) || defined(__PS2__) defined(__SWITCH__)
|
||||||
#else
|
#else
|
||||||
int strm;
|
int strm;
|
||||||
|
|
||||||
bool writing;
|
bool writing;
|
||||||
bool shouldClose;
|
|
||||||
bool eos;
|
bool eos;
|
||||||
#endif
|
#endif
|
||||||
public:
|
public:
|
||||||
#if defined(_WIN32)
|
#if defined(_WIN32)
|
||||||
#elif defined(GEKKO) || defined(__PS2__) defined(__SWITCH__)
|
ProcessStream(HANDLE strm, bool writing)
|
||||||
#else
|
{
|
||||||
ProcessStream(int strm, bool writing, bool shouldClose)
|
this->strm = strm;
|
||||||
|
this->writing = writing;
|
||||||
|
this->eos = false;
|
||||||
|
}
|
||||||
|
#elif defined(GEKKO) || defined(__PS2__) defined(__SWITCH__)
|
||||||
|
#else
|
||||||
|
ProcessStream(int strm, bool writing)
|
||||||
{
|
{
|
||||||
this->strm = strm;
|
this->strm = strm;
|
||||||
this->writing = writing;
|
this->writing = writing;
|
||||||
this->shouldClose=shouldClose;
|
|
||||||
this->eos=false;
|
this->eos=false;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@ -59,7 +118,7 @@ namespace Tesses::Framework::Platform {
|
|||||||
{
|
{
|
||||||
//TODO: Implement for WIN32
|
//TODO: Implement for WIN32
|
||||||
#if defined(_WIN32)
|
#if defined(_WIN32)
|
||||||
return true;
|
return this->strm == NULL || eos;
|
||||||
#elif defined(GEKKO) || defined(__PS2__) defined(__SWITCH__)
|
#elif defined(GEKKO) || defined(__PS2__) defined(__SWITCH__)
|
||||||
return true;
|
return true;
|
||||||
#else
|
#else
|
||||||
@ -70,7 +129,7 @@ namespace Tesses::Framework::Platform {
|
|||||||
{
|
{
|
||||||
//TODO: Implement for WIN32
|
//TODO: Implement for WIN32
|
||||||
#if defined(_WIN32)
|
#if defined(_WIN32)
|
||||||
return false;
|
return !writing && this->strm != NULL;
|
||||||
#elif defined(GEKKO) || defined(__PS2__) defined(__SWITCH__)
|
#elif defined(GEKKO) || defined(__PS2__) defined(__SWITCH__)
|
||||||
return false;
|
return false;
|
||||||
#else
|
#else
|
||||||
@ -81,7 +140,8 @@ namespace Tesses::Framework::Platform {
|
|||||||
{
|
{
|
||||||
//TODO: Implement for WIN32
|
//TODO: Implement for WIN32
|
||||||
#if defined(_WIN32)
|
#if defined(_WIN32)
|
||||||
return false;
|
|
||||||
|
return writing && this->strm != NULL;
|
||||||
#elif defined(GEKKO) || defined(__PS2__) defined(__SWITCH__)
|
#elif defined(GEKKO) || defined(__PS2__) defined(__SWITCH__)
|
||||||
return false;
|
return false;
|
||||||
#else
|
#else
|
||||||
@ -93,7 +153,15 @@ namespace Tesses::Framework::Platform {
|
|||||||
{
|
{
|
||||||
//TODO: Implement for WIN32
|
//TODO: Implement for WIN32
|
||||||
#if defined(_WIN32)
|
#if defined(_WIN32)
|
||||||
|
if (this->strm == NULL || this->eos && writing) return 0;
|
||||||
|
|
||||||
|
DWORD dataR = (DWORD)sz;
|
||||||
|
if (!ReadFile(this->strm, buff, dataR, &dataR, NULL))
|
||||||
return 0;
|
return 0;
|
||||||
|
if (dataR == 0) {
|
||||||
|
this->eos = true;
|
||||||
|
}
|
||||||
|
return (size_t)dataW;
|
||||||
#elif defined(GEKKO) || defined(__PS2__) defined(__SWITCH__)
|
#elif defined(GEKKO) || defined(__PS2__) defined(__SWITCH__)
|
||||||
return 0;
|
return 0;
|
||||||
#else
|
#else
|
||||||
@ -110,30 +178,22 @@ namespace Tesses::Framework::Platform {
|
|||||||
{
|
{
|
||||||
//TODO: Implement for WIN32
|
//TODO: Implement for WIN32
|
||||||
#if defined(_WIN32)
|
#if defined(_WIN32)
|
||||||
|
if (this->strm == NULL || !writing) return 0;
|
||||||
|
DWORD dataW=(DWORD)sz;
|
||||||
|
if (!WriteFile(this->strm, buff, dataW, &dataW, NULL))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
return (size_t)dataW;
|
||||||
#elif defined(GEKKO) || defined(__PS2__) defined(__SWITCH__)
|
#elif defined(GEKKO) || defined(__PS2__) defined(__SWITCH__)
|
||||||
return 0;
|
return 0;
|
||||||
#else
|
#else
|
||||||
if(this->strm < 0 && !writing) return 0;
|
if(this->strm < 0 || !writing) return 0;
|
||||||
auto r = write(this->strm,buff,sz);
|
auto r = write(this->strm,buff,sz);
|
||||||
if(r == -1) return 0;
|
if(r == -1) return 0;
|
||||||
return (size_t)r;
|
return (size_t)r;
|
||||||
#endif
|
#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
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -174,14 +234,28 @@ namespace Tesses::Framework::Platform {
|
|||||||
}
|
}
|
||||||
Process::~Process()
|
Process::~Process()
|
||||||
{
|
{
|
||||||
|
ProcessData* p = this->hidden.GetField<ProcessData*>();
|
||||||
|
|
||||||
|
#if defined(_WIN32)
|
||||||
|
if (p->stdin_strm != NULL)
|
||||||
|
CloseHandle(p->stdin_strm);
|
||||||
|
|
||||||
|
if (p->stdout_strm != NULL)
|
||||||
|
CloseHandle(p->stdout_strm);
|
||||||
|
|
||||||
|
if (p->stderr_strm != NULL)
|
||||||
|
CloseHandle(p->stderr_strm);
|
||||||
|
|
||||||
|
CloseHandle(p->pi.hProcess);
|
||||||
|
CloseHandle(p->pi.hThread);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
bool Process::Start()
|
bool Process::Start()
|
||||||
{
|
{
|
||||||
auto p =
|
ProcessData* p =
|
||||||
this->hidden.GetField<ProcessData*>();
|
this->hidden.GetField<ProcessData*>();
|
||||||
std::vector<std::pair<std::string,std::string>> envs;
|
std::vector<std::pair<std::string,std::string>> envs;
|
||||||
|
|
||||||
@ -204,6 +278,114 @@ namespace Tesses::Framework::Platform {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#if defined(_WIN32)
|
#if defined(_WIN32)
|
||||||
|
std::u16string u16_name;
|
||||||
|
std::u16string u16_args;
|
||||||
|
std::string args;
|
||||||
|
escape_windows_args(args,this->args);
|
||||||
|
UTF16::FromUTF8(u16_name,this->name);
|
||||||
|
UTF16::FromUTF8(u16_args, args);
|
||||||
|
std::u16string env = {};
|
||||||
|
|
||||||
|
for (auto envItem : this->env)
|
||||||
|
{
|
||||||
|
auto partOld = envItem.first + "=" + envItem.second;
|
||||||
|
std::u16string part = {};
|
||||||
|
|
||||||
|
UTF16::FromUTF8(part,partOld);
|
||||||
|
env.append(part);
|
||||||
|
env.push_back(0);
|
||||||
|
}
|
||||||
|
env.push_back(0);
|
||||||
|
|
||||||
|
std::u16string workDir = {};
|
||||||
|
|
||||||
|
if (!this->workingDirectory.empty())
|
||||||
|
UTF16::FromUTF8(workDir, this->workingDirectory);
|
||||||
|
|
||||||
|
SECURITY_ATTRIBUTES attr;
|
||||||
|
attr.nLength = sizeof(attr);
|
||||||
|
attr.lpSecurityDescriptor = NULL;
|
||||||
|
attr.bInheritHandle = true;
|
||||||
|
p->si->hStdInput = NULL;
|
||||||
|
p->si->hStdOutput = NULL;
|
||||||
|
|
||||||
|
p->si->hStdError = NULL;
|
||||||
|
|
||||||
|
p->stdin_strm = NULL;
|
||||||
|
p->stdout_strm = NULL;
|
||||||
|
p->stderr_strm = NULL;
|
||||||
|
|
||||||
|
if (this->redirectStdIn)
|
||||||
|
{
|
||||||
|
if (!CreatePipe(&p->si->hStdInput, &p->stdin_strm, &attr,0)) return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this->redirectStdOut)
|
||||||
|
{
|
||||||
|
if (!CreatePipe(&p->stdout_strm, &p->si->hStdOutput, &attr, 0))
|
||||||
|
{
|
||||||
|
if (this->redirectStdIn)
|
||||||
|
{
|
||||||
|
CloseHandle(p->stdin_strm);
|
||||||
|
CloseHandle(p->si->hStdInput);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (this->redirectStdErr)
|
||||||
|
{
|
||||||
|
if (!CreatePipe(&p->stderr_strm, &p->si->hStdError, &attr, 0))
|
||||||
|
{
|
||||||
|
if (this->redirectStdIn)
|
||||||
|
{
|
||||||
|
CloseHandle(p->stdin_strm);
|
||||||
|
CloseHandle(p->si->hStdInput);
|
||||||
|
}
|
||||||
|
if (this->redirectStdOut)
|
||||||
|
{
|
||||||
|
CloseHandle(p->stdout_strm);
|
||||||
|
CloseHandle(p->si->hStdOutput);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!CreateProcessW(u16_name.c_str(), u16_args.data(), NULL, NULL, (this->redirectStdIn || this->redirectStdOut || this->redirectStdErr), CREATE_UNICODE_ENVIRONMENT, (LPCWSTR)env.c_str(), workDir.empty() ? (LPCWSTR)NULL : (LPCWSTR)workDir.c_str(), &(p->si), &(p->pi)))
|
||||||
|
{
|
||||||
|
if (this->redirectStdIn)
|
||||||
|
{
|
||||||
|
CloseHandle(p->stdin_strm);
|
||||||
|
CloseHandle(p->si->hStdInput);
|
||||||
|
}
|
||||||
|
if (this->redirectStdOut)
|
||||||
|
{
|
||||||
|
CloseHandle(p->stdout_strm);
|
||||||
|
CloseHandle(p->si->hStdOutput);
|
||||||
|
}
|
||||||
|
if (this->redirectStdErr)
|
||||||
|
{
|
||||||
|
CloseHandle(p->stderr_strm);
|
||||||
|
CloseHandle(p->si->hStdError);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
BOOL
|
||||||
|
WINAPI
|
||||||
|
CreateProcessW(
|
||||||
|
_In_opt_ LPCWSTR lpApplicationName,
|
||||||
|
_Inout_opt_ LPWSTR lpCommandLine,
|
||||||
|
_In_opt_ LPSECURITY_ATTRIBUTES lpProcessAttributes,
|
||||||
|
_In_opt_ LPSECURITY_ATTRIBUTES lpThreadAttributes,
|
||||||
|
_In_ BOOL bInheritHandles,
|
||||||
|
_In_ DWORD dwCreationFlags,
|
||||||
|
_In_opt_ LPVOID lpEnvironment,
|
||||||
|
_In_opt_ LPCWSTR lpCurrentDirectory,
|
||||||
|
_In_ LPSTARTUPINFOW lpStartupInfo,
|
||||||
|
_Out_ LPPROCESS_INFORMATION lpProcessInformation
|
||||||
|
);
|
||||||
|
*/
|
||||||
return false;
|
return false;
|
||||||
#elif defined(GEKKO) || defined(__PS2__) defined(__SWITCH__)
|
#elif defined(GEKKO) || defined(__PS2__) defined(__SWITCH__)
|
||||||
return false;
|
return false;
|
||||||
@ -352,34 +534,34 @@ namespace Tesses::Framework::Platform {
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
Tesses::Framework::Streams::Stream* Process::GetStdinStream(bool closeUnderlying)
|
Tesses::Framework::Streams::Stream* Process::GetStdinStream()
|
||||||
{
|
{
|
||||||
#if defined(_WIN32)
|
#if defined(_WIN32)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
#elif defined(GEKKO) || defined(__PS2__) defined(__SWITCH__)
|
#elif defined(GEKKO) || defined(__PS2__) defined(__SWITCH__)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
#else
|
#else
|
||||||
return new ProcessStream(this->hidden.GetField<ProcessData*>()->stdin_strm,true,closeUnderlying);
|
return new ProcessStream(this->hidden.GetField<ProcessData*>()->stdin_strm,true);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
Tesses::Framework::Streams::Stream* Process::GetStdoutStream(bool closeUnderlying)
|
Tesses::Framework::Streams::Stream* Process::GetStdoutStream()
|
||||||
{
|
{
|
||||||
#if defined(_WIN32)
|
#if defined(_WIN32)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
#elif defined(GEKKO) || defined(__PS2__) defined(__SWITCH__)
|
#elif defined(GEKKO) || defined(__PS2__) defined(__SWITCH__)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
#else
|
#else
|
||||||
return new ProcessStream(this->hidden.GetField<ProcessData*>()->stdout_strm,false,closeUnderlying);
|
return new ProcessStream(this->hidden.GetField<ProcessData*>()->stdout_strm,false);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
Tesses::Framework::Streams::Stream* Process::GetStderrStream(bool closeUnderlying)
|
Tesses::Framework::Streams::Stream* Process::GetStderrStream()
|
||||||
{
|
{
|
||||||
#if defined(_WIN32)
|
#if defined(_WIN32)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
#elif defined(GEKKO) || defined(__PS2__) defined(__SWITCH__)
|
#elif defined(GEKKO) || defined(__PS2__) defined(__SWITCH__)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
#else
|
#else
|
||||||
return new ProcessStream(this->hidden.GetField<ProcessData*>()->stderr_strm,false,closeUnderlying);
|
return new ProcessStream(this->hidden.GetField<ProcessData*>()->stderr_strm,false);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -6,6 +6,7 @@ using HttpUtils = Tesses::Framework::Http::HttpUtils;
|
|||||||
#if defined(TESSESFRAMEWORK_ENABLE_NETWORKING)
|
#if defined(TESSESFRAMEWORK_ENABLE_NETWORKING)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#if defined(GEKKO)
|
#if defined(GEKKO)
|
||||||
|
|
||||||
#define ss_family sin_family
|
#define ss_family sin_family
|
||||||
@ -24,9 +25,11 @@ using HttpUtils = Tesses::Framework::Http::HttpUtils;
|
|||||||
#include <winsock2.h>
|
#include <winsock2.h>
|
||||||
#include <iphlpapi.h>
|
#include <iphlpapi.h>
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
|
#include <afunix.h>
|
||||||
#undef min
|
#undef min
|
||||||
#pragma comment(lib, "ws2_32.lib")
|
#pragma comment(lib, "ws2_32.lib")
|
||||||
#else
|
#else
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#include <netinet/in.h>
|
#include <netinet/in.h>
|
||||||
#include <netinet/tcp.h>
|
#include <netinet/tcp.h>
|
||||||
|
|||||||
@ -114,7 +114,7 @@ namespace Tesses::Framework::Streams {
|
|||||||
strm.Flush();
|
strm.Flush();
|
||||||
|
|
||||||
#if defined(_WIN32)
|
#if defined(_WIN32)
|
||||||
delete buffer;
|
delete[] buffer;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
Stream::~Stream()
|
Stream::~Stream()
|
||||||
|
|||||||
270
src/Text/StringConverter.cpp
Normal file
270
src/Text/StringConverter.cpp
Normal file
@ -0,0 +1,270 @@
|
|||||||
|
#include "TessesFramework/Text/StringConverter.hpp"
|
||||||
|
|
||||||
|
namespace Tesses::Framework::Text::StringConverter {
|
||||||
|
void UTF8::FromUTF16(std::basic_string<char>& utf8, const std::basic_string<char16_t>& utf16)
|
||||||
|
{
|
||||||
|
for (size_t i=0; i < utf16.size();i++)
|
||||||
|
{
|
||||||
|
char32_t c = utf16[i];
|
||||||
|
if ((c & 0xFC00) == 0xD800)
|
||||||
|
{
|
||||||
|
c = (c & 0x03FF) << 10;
|
||||||
|
i++;
|
||||||
|
if (i >= utf16.size()) return;
|
||||||
|
|
||||||
|
|
||||||
|
char32_t c2 = utf16[i];
|
||||||
|
if ((c2 & 0xFC00) != 0xDC00) continue;
|
||||||
|
|
||||||
|
|
||||||
|
c |= (c2 & 0x03FF);
|
||||||
|
|
||||||
|
c += 0x10000;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (c <= 0x7F)
|
||||||
|
{
|
||||||
|
utf8.push_back((char)c);
|
||||||
|
}
|
||||||
|
else if (c >= 0x80 && c <= 0x7FF)
|
||||||
|
{
|
||||||
|
uint8_t high = 0b11000000 | ((c >> 6) & 0b00011111);
|
||||||
|
uint8_t low = 0b10000000 | (c & 0b00111111);
|
||||||
|
utf8.push_back((char)high);
|
||||||
|
utf8.push_back((char)low);
|
||||||
|
}
|
||||||
|
else if (c >= 0x800 && c <= 0xFFFF)
|
||||||
|
{
|
||||||
|
uint8_t highest = 0b11100000 | ((c >> 12) & 0b00001111);
|
||||||
|
uint8_t high = 0b10000000 | ((c >> 6) & 0b00111111);
|
||||||
|
uint8_t low = 0b10000000 | (c & 0b00111111);
|
||||||
|
utf8.push_back((char)highest);
|
||||||
|
utf8.push_back((char)high);
|
||||||
|
utf8.push_back((char)low);
|
||||||
|
}
|
||||||
|
else if (c >= 0x010000 && c <= 0x10FFFF)
|
||||||
|
{
|
||||||
|
uint8_t highest = 0b11110000 | ((c >> 18) & 0b00000111);
|
||||||
|
uint8_t high = 0b10000000 | ((c >> 12) & 0b00111111);
|
||||||
|
uint8_t low = 0b10000000 | ((c >> 6) & 0b00111111);
|
||||||
|
uint8_t lowest = 0b10000000 | (c & 0b00111111);
|
||||||
|
utf8.push_back((char)highest);
|
||||||
|
utf8.push_back((char)high);
|
||||||
|
utf8.push_back((char)low);
|
||||||
|
utf8.push_back((char)lowest);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void UTF8::FromUTF32(std::basic_string<char>& utf8, const std::basic_string<char32_t>& utf32)
|
||||||
|
{
|
||||||
|
for (auto c : utf32)
|
||||||
|
{
|
||||||
|
if (c <= 0x7F)
|
||||||
|
{
|
||||||
|
utf8.push_back((char)c);
|
||||||
|
}
|
||||||
|
else if (c >= 0x80 && c <= 0x7FF)
|
||||||
|
{
|
||||||
|
uint8_t high = 0b11000000 | ((c >> 6) & 0b00011111);
|
||||||
|
uint8_t low = 0b10000000 | (c & 0b00111111);
|
||||||
|
utf8.push_back((char)high);
|
||||||
|
utf8.push_back((char)low);
|
||||||
|
}
|
||||||
|
else if (c >= 0x800 && c <= 0xFFFF)
|
||||||
|
{
|
||||||
|
uint8_t highest = 0b11100000 | ((c >> 12) & 0b00001111);
|
||||||
|
uint8_t high = 0b10000000 | ((c >> 6) & 0b00111111);
|
||||||
|
uint8_t low = 0b10000000 | (c & 0b00111111);
|
||||||
|
utf8.push_back((char)highest);
|
||||||
|
utf8.push_back((char)high);
|
||||||
|
utf8.push_back((char)low);
|
||||||
|
}
|
||||||
|
else if (c >= 0x010000 && c <= 0x10FFFF)
|
||||||
|
{
|
||||||
|
uint8_t highest = 0b11110000 | ((c >> 18) & 0b00000111);
|
||||||
|
uint8_t high = 0b10000000 | ((c >> 12) & 0b00111111);
|
||||||
|
uint8_t low = 0b10000000 | ((c >> 6) & 0b00111111);
|
||||||
|
uint8_t lowest = 0b10000000 | (c & 0b00111111);
|
||||||
|
utf8.push_back((char)highest);
|
||||||
|
utf8.push_back((char)high);
|
||||||
|
utf8.push_back((char)low);
|
||||||
|
utf8.push_back((char)lowest);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void UTF16::FromUTF8(std::basic_string<char16_t>& utf16, const std::basic_string<char>& utf8)
|
||||||
|
{
|
||||||
|
for (size_t i = 0; i < utf8.size();i++)
|
||||||
|
{
|
||||||
|
uint8_t c = (uint8_t)utf8[i];
|
||||||
|
char32_t cres = 0;
|
||||||
|
if (c <= 127)
|
||||||
|
{
|
||||||
|
cres = (char32_t)c;
|
||||||
|
}
|
||||||
|
else if ((c & 0b11100000) == 0b11000000)
|
||||||
|
{
|
||||||
|
if (i + 1 < utf8.size())
|
||||||
|
{
|
||||||
|
|
||||||
|
uint8_t c2 = (uint8_t)utf8[++i];
|
||||||
|
cres |= c2 & 0b00111111;
|
||||||
|
cres |= (c & 0b00011111) << 6;
|
||||||
|
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
i++;
|
||||||
|
continue;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
else if ((c & 0b11110000) == 0b11100000)
|
||||||
|
{
|
||||||
|
if (i + 2 < utf8.size())
|
||||||
|
{
|
||||||
|
uint8_t c2 = (uint8_t)utf8[++i];
|
||||||
|
uint8_t c3 = (uint8_t)utf8[++i];
|
||||||
|
cres |= c3 & 0b00111111;
|
||||||
|
cres |= (c2 & 0b00111111) << 6;
|
||||||
|
cres |= (c & 0b00001111) << 12;
|
||||||
|
|
||||||
|
}
|
||||||
|
else { i += 2; continue; }
|
||||||
|
}
|
||||||
|
else if ((c & 0b11111000) == 0b11110000)
|
||||||
|
{
|
||||||
|
if (i + 3 < utf8.size())
|
||||||
|
{
|
||||||
|
uint8_t c2 = (uint8_t)utf8[++i];
|
||||||
|
uint8_t c3 = (uint8_t)utf8[++i];
|
||||||
|
uint8_t c4 = (uint8_t)utf8[++i];
|
||||||
|
|
||||||
|
cres |= c4 & 0b00111111;
|
||||||
|
cres |= (c3 & 0b00111111) << 6;
|
||||||
|
cres |= (c2 & 0b00111111) << 12;
|
||||||
|
cres |= (c & 0b00000111) << 18;
|
||||||
|
|
||||||
|
}
|
||||||
|
else { i += 3; continue; }
|
||||||
|
}
|
||||||
|
if (cres >= 0x10000 && cres <= 0x10FFFF)
|
||||||
|
{
|
||||||
|
auto subtracted = cres - 0x10000;
|
||||||
|
|
||||||
|
auto high = (0x3FF & (subtracted >> 10)) | 0xD800;
|
||||||
|
auto low = (0x3FF & subtracted) | 0xDC00;
|
||||||
|
|
||||||
|
utf16.push_back(high);
|
||||||
|
utf16.push_back(low);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
utf16.push_back((char16_t)cres);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void UTF16::FromUTF32(std::basic_string<char16_t>& utf16, const std::basic_string<char32_t>& utf32)
|
||||||
|
{
|
||||||
|
for (auto cres : utf32)
|
||||||
|
{
|
||||||
|
if (cres >= 0x10000 && cres <= 0x10FFFF)
|
||||||
|
{
|
||||||
|
auto subtracted = cres - 0x10000;
|
||||||
|
|
||||||
|
auto high = (0x3FF & (subtracted >> 10)) | 0xD800;
|
||||||
|
auto low = (0x3FF & subtracted) | 0xDC00;
|
||||||
|
|
||||||
|
utf16.push_back(high);
|
||||||
|
utf16.push_back(low);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
utf16.push_back((char16_t)cres);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void UTF32::FromUTF8(std::basic_string<char32_t>& utf32, const std::basic_string<char>& utf8)
|
||||||
|
{
|
||||||
|
for (size_t i = 0; i < utf8.size();i++)
|
||||||
|
{
|
||||||
|
uint8_t c = (uint8_t)utf8[i];
|
||||||
|
char32_t cres = 0;
|
||||||
|
if (c <= 127)
|
||||||
|
{
|
||||||
|
cres=(char32_t)c;
|
||||||
|
}
|
||||||
|
else if ((c & 0b11100000) == 0b11000000)
|
||||||
|
{
|
||||||
|
if (i + 1 < utf8.size())
|
||||||
|
{
|
||||||
|
|
||||||
|
uint8_t c2 = (uint8_t)utf8[++i];
|
||||||
|
cres |= c2 & 0b00111111;
|
||||||
|
cres |= (c & 0b00011111) << 6;
|
||||||
|
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
i++;
|
||||||
|
continue;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
else if ((c & 0b11110000) == 0b11100000)
|
||||||
|
{
|
||||||
|
if (i + 2 < utf8.size())
|
||||||
|
{
|
||||||
|
uint8_t c2 = (uint8_t)utf8[++i];
|
||||||
|
uint8_t c3 = (uint8_t)utf8[++i];
|
||||||
|
cres |= c3 & 0b00111111;
|
||||||
|
cres |= (c2 & 0b00111111) << 6;
|
||||||
|
cres |= (c & 0b00001111) << 12;
|
||||||
|
|
||||||
|
}
|
||||||
|
else { i += 2; continue; }
|
||||||
|
}
|
||||||
|
else if ((c & 0b11111000) == 0b11110000)
|
||||||
|
{
|
||||||
|
if (i + 3 < utf8.size())
|
||||||
|
{
|
||||||
|
uint8_t c2 = (uint8_t)utf8[++i];
|
||||||
|
uint8_t c3 = (uint8_t)utf8[++i];
|
||||||
|
uint8_t c4 = (uint8_t)utf8[++i];
|
||||||
|
|
||||||
|
cres |= c4 & 0b00111111;
|
||||||
|
cres |= (c3 & 0b00111111) << 6;
|
||||||
|
cres |= (c2 & 0b00111111) << 12;
|
||||||
|
cres |= (c & 0b00000111) << 18;
|
||||||
|
|
||||||
|
}
|
||||||
|
else { i += 3; continue; }
|
||||||
|
}
|
||||||
|
utf32.push_back(cres);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void UTF32::FromUTF16(std::basic_string<char32_t>& utf32, const std::basic_string<char16_t>& utf16)
|
||||||
|
{
|
||||||
|
for (size_t i = 0; i < utf16.size();i++)
|
||||||
|
{
|
||||||
|
char32_t c = utf16[i];
|
||||||
|
if ((c & 0xFC00) == 0xD800)
|
||||||
|
{
|
||||||
|
c = (c & 0x03FF) << 10;
|
||||||
|
i++;
|
||||||
|
if (i >= utf16.size()) return;
|
||||||
|
|
||||||
|
|
||||||
|
char32_t c2 = utf16[i];
|
||||||
|
if ((c2 & 0xFC00) != 0xDC00) continue;
|
||||||
|
|
||||||
|
|
||||||
|
c |= (c2 & 0x03FF);
|
||||||
|
|
||||||
|
c += 0x10000;
|
||||||
|
}
|
||||||
|
utf32.push_back(c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user