mirror of
https://git.tesses.org/tesses50/tessesframework.git
synced 2026-10-01 17:14:13 +00:00
Fix license compliance and fix things up
This commit is contained in:
+4
-1
@@ -1,6 +1,9 @@
|
||||
/*
|
||||
TessesFramework a library to make C++ easier for me, used in CrossLang:
|
||||
https://git.tesses.org/tesses50/crosslang Copyright (C) 2026 Mike Nolan
|
||||
https://git.tesses.org/tesses50/crosslang
|
||||
|
||||
Copyright (C) 2026 Mike Nolan
|
||||
SPDX-License-Identifier: GPL-3.0-or-later WITH TessesFramework-Exception-1.0
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
/*
|
||||
TessesFramework a library to make C++ easier for me, used in CrossLang:
|
||||
https://git.tesses.org/tesses50/crosslang Copyright (C) 2026 Mike Nolan
|
||||
https://git.tesses.org/tesses50/crosslang
|
||||
|
||||
Copyright (C) 2026 Mike Nolan
|
||||
SPDX-License-Identifier: GPL-3.0-or-later WITH TessesFramework-Exception-1.0
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
/*
|
||||
TessesFramework a library to make C++ easier for me, used in CrossLang:
|
||||
https://git.tesses.org/tesses50/crosslang Copyright (C) 2026 Mike Nolan
|
||||
https://git.tesses.org/tesses50/crosslang
|
||||
|
||||
Copyright (C) 2026 Mike Nolan
|
||||
SPDX-License-Identifier: GPL-3.0-or-later WITH TessesFramework-Exception-1.0
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
|
||||
+484
-35
@@ -1,26 +1,45 @@
|
||||
/*
|
||||
TessesFramework a library to make C++ easier for me, used in CrossLang:
|
||||
https://git.tesses.org/tesses50/crosslang Copyright (C) 2026 Mike Nolan
|
||||
TessesFramework a library to make C++ easier for me, used in CrossLang:
|
||||
https://git.tesses.org/tesses50/crosslang
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
Copyright (C) 2026 Mike Nolan
|
||||
SPDX-License-Identifier: GPL-3.0-or-later WITH TessesFramework-Exception-1.0
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "TessesFramework/Console.hpp"
|
||||
#include "TessesFramework/Http/HttpUtils.hpp"
|
||||
#include "TessesFramework/Text/StringConverter.hpp"
|
||||
|
||||
#if __has_include(<termios.h>)
|
||||
#if defined(__SWITCH__)
|
||||
|
||||
extern "C" {
|
||||
#include <switch.h>
|
||||
}
|
||||
|
||||
#elif defined(GEKKO)
|
||||
#include <gccore.h>
|
||||
#include <ogc/pad.h>
|
||||
|
||||
#if defined(HW_RVL)
|
||||
#include <wiikeyboard/keyboard.h>
|
||||
#include <wiikeyboard/usbkeyboard.h>
|
||||
#include <wiiuse/wpad.h>
|
||||
#endif
|
||||
|
||||
#elif __has_include(<termios.h>)
|
||||
#include <sys/ioctl.h>
|
||||
#include <termios.h>
|
||||
#include <unistd.h>
|
||||
@@ -33,13 +52,16 @@
|
||||
#include <limits>
|
||||
|
||||
namespace Tesses::Framework {
|
||||
|
||||
#if defined(__SWITCH__)
|
||||
extern bool initedConsole;
|
||||
extern PadState default_pad;
|
||||
constexpr int CONSOLE_READ_BUFFER_MAX = 32768;
|
||||
#endif
|
||||
class ConsoleHelpers {
|
||||
|
||||
bool canon;
|
||||
bool echo;
|
||||
bool signals;
|
||||
|
||||
#if defined(_WIN32)
|
||||
WORD colorFlags;
|
||||
|
||||
@@ -47,9 +69,14 @@ class ConsoleHelpers {
|
||||
|
||||
public:
|
||||
ConsoleHelpers() {
|
||||
|
||||
canon = Console::GetCanonical();
|
||||
echo = Console::GetEcho();
|
||||
signals = Console::GetSignals();
|
||||
|
||||
#if defined(HW_RVL)
|
||||
KEYBOARD_Init(NULL);
|
||||
#endif
|
||||
#if defined(_WIN32)
|
||||
HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||
if (hConsole == INVALID_HANDLE_VALUE)
|
||||
@@ -82,11 +109,16 @@ class ConsoleHelpers {
|
||||
Console::SetEcho(echo);
|
||||
Console::SetSignals(signals);
|
||||
reset();
|
||||
|
||||
#if defined(HW_RVL)
|
||||
KEYBOARD_Deinit();
|
||||
#endif
|
||||
}
|
||||
};
|
||||
ConsoleHelpers consoleHelpers;
|
||||
|
||||
size_t Console::List(std::vector<std::string> &strs) {
|
||||
|
||||
if (!IsTTY())
|
||||
return std::string::npos;
|
||||
|
||||
@@ -123,7 +155,77 @@ size_t Console::List(std::vector<std::string> &strs) {
|
||||
}
|
||||
|
||||
Console::SetInvertedColors(false);
|
||||
#if defined(__SWITCH__)
|
||||
if (!appletMainLoop()) {
|
||||
TF_Quit();
|
||||
break;
|
||||
}
|
||||
|
||||
padUpdate(&default_pad);
|
||||
|
||||
u64 kDown = padGetButtonsDown(&default_pad);
|
||||
|
||||
if (kDown & HidNpadButton_AnyUp) {
|
||||
i--;
|
||||
if (i >= strs.size())
|
||||
i = strs.size() - 1;
|
||||
} else if (kDown & HidNpadButton_AnyDown) {
|
||||
i++;
|
||||
if (i >= strs.size())
|
||||
i = 0;
|
||||
} else if (kDown & HidNpadButton_A) {
|
||||
break;
|
||||
}
|
||||
|
||||
consoleUpdate(NULL);
|
||||
|
||||
#elif defined(GEKKO)
|
||||
|
||||
PAD_ScanPads();
|
||||
bool down = false;
|
||||
bool up = false;
|
||||
bool a = false;
|
||||
bool exit = false;
|
||||
|
||||
auto gcdown = PAD_ButtonsDown(PAD_CHAN0);
|
||||
if (gcdown & PAD_BUTTON_DOWN)
|
||||
down = true;
|
||||
if (gcdown & PAD_BUTTON_UP)
|
||||
up = true;
|
||||
if (gcdown & PAD_BUTTON_A)
|
||||
a = true;
|
||||
if (gcdown & PAD_BUTTON_START)
|
||||
exit = true;
|
||||
|
||||
#if defined(HW_RVL)
|
||||
WPAD_ScanPads();
|
||||
auto wiidown = WPAD_ButtonsDown(WPAD_CHAN_0);
|
||||
|
||||
if (wiidown & WPAD_BUTTON_UP)
|
||||
up = true;
|
||||
if (wiidown & WPAD_BUTTON_DOWN)
|
||||
down = true;
|
||||
if (wiidown & WPAD_BUTTON_A)
|
||||
a = true;
|
||||
if (wiidown & WPAD_BUTTON_PLUS)
|
||||
exit = true;
|
||||
#endif
|
||||
if (up) {
|
||||
i--;
|
||||
if (i >= strs.size())
|
||||
i = strs.size() - 1;
|
||||
} else if (down) {
|
||||
i++;
|
||||
if (i >= strs.size())
|
||||
i = 0;
|
||||
} else if (a) {
|
||||
break;
|
||||
} else if (exit) {
|
||||
TF_Quit();
|
||||
break;
|
||||
}
|
||||
VIDEO_WaitVSync();
|
||||
#else
|
||||
int code = Console::Read();
|
||||
|
||||
if (code == 10)
|
||||
@@ -148,16 +250,52 @@ size_t Console::List(std::vector<std::string> &strs) {
|
||||
} else if (code == -1)
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
Console::SetEcho(echo);
|
||||
Console::SetCanonical(canonical);
|
||||
Console::SetInvertedColors(false);
|
||||
|
||||
#if defined(__SWITCH__)
|
||||
consoleUpdate(NULL);
|
||||
#endif
|
||||
return i;
|
||||
}
|
||||
|
||||
void Console::Reset() { consoleHelpers.reset(); }
|
||||
#if defined(GEKKO)
|
||||
static bool vt100_inverted = false;
|
||||
|
||||
#if defined(_WIN32)
|
||||
static ConsoleColor fg_color = ConsoleColor::CC_WHITE;
|
||||
static ConsoleColor bg_color = ConsoleColor::CC_BLACK;
|
||||
static bool fg_intense = false;
|
||||
static bool bg_intense = false;
|
||||
|
||||
#if defined(HW_RVL)
|
||||
static bool wii_echo = true;
|
||||
static bool wii_cannon = true;
|
||||
#endif
|
||||
|
||||
static void _setcol(ConsoleColor col, bool alt, bool bg) {
|
||||
if (bg) {
|
||||
bg_color = col;
|
||||
bg_intense = alt;
|
||||
if (alt) {
|
||||
printf("\x1b[%im", ((int)col) + 100); // this should be Write
|
||||
} else {
|
||||
printf("\x1b[%im", ((int)col) + 40); // this too
|
||||
}
|
||||
} else {
|
||||
fg_color = col;
|
||||
fg_intense = alt;
|
||||
if (alt) {
|
||||
printf("\x1b[%im", ((int)col) + 90); // this should be Write
|
||||
} else {
|
||||
printf("\x1b[%im", ((int)col) + 30); // this too
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#elif defined(_WIN32)
|
||||
static bool vt100_inverted = false;
|
||||
static void _setcol(ConsoleColor col, bool alt, bool bg) {
|
||||
if (bg) {
|
||||
@@ -219,12 +357,22 @@ static void _setcol(ConsoleColor col, bool alt, bool bg) {
|
||||
}
|
||||
#endif
|
||||
|
||||
void Console::Reset() {
|
||||
#if defined(GEKKO)
|
||||
vt100_inverted = false;
|
||||
Console::SetBackgroundColor(ConsoleColor::CC_BLACK, false);
|
||||
Console::SetForegroundColor(ConsoleColor::CC_WHITE, false);
|
||||
#elif defined(_WIN32)
|
||||
vt100_inverted = false;
|
||||
#endif
|
||||
consoleHelpers.reset();
|
||||
}
|
||||
void Console::SetForegroundColor(ConsoleColor col, bool alt) {
|
||||
|
||||
if (!IsTTY())
|
||||
return;
|
||||
|
||||
#if defined(_WIN32)
|
||||
#if defined(_WIN32) || defined(GEKKO)
|
||||
|
||||
_setcol(col, alt, vt100_inverted);
|
||||
|
||||
@@ -241,7 +389,7 @@ void Console::SetBackgroundColor(ConsoleColor col, bool alt) {
|
||||
if (!IsTTY())
|
||||
return;
|
||||
|
||||
#if defined(_WIN32)
|
||||
#if defined(_WIN32) || defined(GEKKO)
|
||||
_setcol(col, alt, !vt100_inverted);
|
||||
#else
|
||||
if (alt) {
|
||||
@@ -255,7 +403,30 @@ void Console::SetBackgroundColor(ConsoleColor col, bool alt) {
|
||||
void Console::SetInvertedColors(bool inverted) {
|
||||
if (!IsTTY())
|
||||
return;
|
||||
#if defined(_WIN32)
|
||||
#if defined(GEKKO)
|
||||
|
||||
if (inverted != vt100_inverted) {
|
||||
auto tmpC = fg_color;
|
||||
auto tmpI = fg_intense;
|
||||
fg_color = bg_color;
|
||||
fg_intense = bg_intense;
|
||||
bg_color = tmpC;
|
||||
bg_intense = tmpI;
|
||||
vt100_inverted = inverted;
|
||||
|
||||
if (bg_intense) {
|
||||
printf("\x1b[%im", ((int)bg_color) + 100); // this should be Write
|
||||
} else {
|
||||
printf("\x1b[%im", ((int)bg_color) + 40); // this too
|
||||
}
|
||||
|
||||
if (fg_intense) {
|
||||
printf("\x1b[%im", ((int)fg_color) + 90); // this should be Write
|
||||
} else {
|
||||
printf("\x1b[%im", ((int)fg_color) + 30); // this too
|
||||
}
|
||||
}
|
||||
#elif defined(_WIN32)
|
||||
if (inverted != vt100_inverted) {
|
||||
HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||
if (hConsole == INVALID_HANDLE_VALUE)
|
||||
@@ -290,7 +461,15 @@ void Console::SetInvertedColors(bool inverted) {
|
||||
bool Console::SetEcho(bool echo) {
|
||||
if (!IsTTY())
|
||||
return false;
|
||||
#if __has_include(<termios.h>)
|
||||
#if defined(__SWITCH__) || defined(GEKKO)
|
||||
|
||||
#if defined(HW_RVL)
|
||||
wii_echo = echo;
|
||||
return true;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
#elif __has_include(<termios.h>)
|
||||
struct termios raw;
|
||||
if (tcgetattr(0, &raw) != 0)
|
||||
return false;
|
||||
@@ -302,7 +481,7 @@ bool Console::SetEcho(bool echo) {
|
||||
|
||||
if (tcsetattr(0, TCSAFLUSH, &raw) != 0)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
#elif defined(_WIN32)
|
||||
HANDLE hConsole = GetStdHandle(STD_INPUT_HANDLE);
|
||||
if (hConsole == INVALID_HANDLE_VALUE)
|
||||
@@ -323,7 +502,13 @@ bool Console::SetEcho(bool echo) {
|
||||
bool Console::GetEcho() {
|
||||
if (!IsTTY())
|
||||
return false;
|
||||
#if __has_include(<termios.h>)
|
||||
#if defined(__SWITCH__) || defined(GEKKO)
|
||||
#if defined(HW_RVL)
|
||||
return wii_echo;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
#elif __has_include(<termios.h>)
|
||||
|
||||
struct termios raw;
|
||||
if (tcgetattr(0, &raw) != 0)
|
||||
@@ -345,7 +530,13 @@ bool Console::GetEcho() {
|
||||
bool Console::GetCanonical() {
|
||||
if (!IsTTY())
|
||||
return false;
|
||||
#if __has_include(<termios.h>)
|
||||
#if defined(__SWITCH__) || defined(GEKKO)
|
||||
#if defined(HW_RVL)
|
||||
return wii_cannon;
|
||||
#else
|
||||
return true;
|
||||
#endif
|
||||
#elif __has_include(<termios.h>)
|
||||
struct termios raw;
|
||||
if (tcgetattr(0, &raw) != 0)
|
||||
return false;
|
||||
@@ -365,7 +556,14 @@ bool Console::GetCanonical() {
|
||||
bool Console::SetCanonical(bool can) {
|
||||
if (!IsTTY())
|
||||
return false;
|
||||
#if __has_include(<termios.h>)
|
||||
#if defined(__SWITCH__) || defined(GEKKO)
|
||||
#if defined(HW_RVL)
|
||||
wii_cannon = can;
|
||||
return true;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
#elif __has_include(<termios.h>)
|
||||
struct termios raw;
|
||||
if (tcgetattr(0, &raw) != 0)
|
||||
return false;
|
||||
@@ -399,7 +597,9 @@ bool Console::SetCanonical(bool can) {
|
||||
bool Console::GetSignals() {
|
||||
if (!IsTTY())
|
||||
return true;
|
||||
#if __has_include(<termios.h>)
|
||||
#if defined(__SWITCH__) || defined(GEKKO)
|
||||
return false;
|
||||
#elif __has_include(<termios.h>)
|
||||
struct termios raw;
|
||||
if (tcgetattr(0, &raw) != 0)
|
||||
return false;
|
||||
@@ -411,7 +611,9 @@ bool Console::GetSignals() {
|
||||
bool Console::SetSignals(bool sig) {
|
||||
if (!IsTTY())
|
||||
return false;
|
||||
#if __has_include(<termios.h>)
|
||||
#if defined(__SWITCH__) || defined(GEKKO)
|
||||
return false;
|
||||
#elif __has_include(<termios.h>)
|
||||
struct termios raw;
|
||||
if (tcgetattr(0, &raw) != 0)
|
||||
return false;
|
||||
@@ -431,6 +633,33 @@ bool Console::SetSignals(bool sig) {
|
||||
// ISIG
|
||||
|
||||
std::string Console::ReadPassword() {
|
||||
|
||||
#if defined(__SWITCH__)
|
||||
consoleUpdate(NULL);
|
||||
// bring up nx keyboard
|
||||
SwkbdConfig kbd;
|
||||
Result rc = swkbdCreate(&kbd, 0);
|
||||
if (R_SUCCEEDED(rc)) {
|
||||
|
||||
swkbdConfigMakePresetPassword(&kbd);
|
||||
char *text = new char[CONSOLE_READ_BUFFER_MAX];
|
||||
rc = swkbdShow(&kbd, text, CONSOLE_READ_BUFFER_MAX);
|
||||
if (R_SUCCEEDED(rc)) {
|
||||
swkbdClose(&kbd);
|
||||
|
||||
std::string str = text;
|
||||
delete[] text;
|
||||
Console::WriteLine("");
|
||||
return str;
|
||||
}
|
||||
delete[] text;
|
||||
|
||||
swkbdClose(&kbd);
|
||||
}
|
||||
|
||||
Console::WriteLine("");
|
||||
return "";
|
||||
#else
|
||||
bool echo = GetEcho();
|
||||
if (!SetEcho(false)) {
|
||||
Write("\nWARN: the password will be visible: ");
|
||||
@@ -440,6 +669,7 @@ std::string Console::ReadPassword() {
|
||||
Write("\n");
|
||||
|
||||
return text;
|
||||
#endif
|
||||
}
|
||||
|
||||
#if defined(_WIN32)
|
||||
@@ -447,8 +677,72 @@ thread_local std::string key;
|
||||
thread_local int keyOffset = -1;
|
||||
#endif
|
||||
|
||||
#if defined(HW_RVL)
|
||||
static std::vector<char> keybuffer;
|
||||
static bool ready = false;
|
||||
static bool amEof = false;
|
||||
|
||||
static int read_char_wiikeyboard() {
|
||||
if (Console::GetCanonical()) {
|
||||
|
||||
if (ready && keybuffer.empty())
|
||||
ready = false;
|
||||
|
||||
if (!ready) {
|
||||
if (amEof)
|
||||
return -1;
|
||||
while (1) {
|
||||
auto val = fgetc(stdin);
|
||||
if (val == 127 || val == 8) {
|
||||
keybuffer.pop_back();
|
||||
|
||||
if (Console::GetEcho())
|
||||
printf("\x08");
|
||||
} else if (val == '\n') {
|
||||
|
||||
if (Console::GetEcho())
|
||||
printf("\n");
|
||||
keybuffer.push_back('\n');
|
||||
ready = true;
|
||||
break;
|
||||
} else if (val == -1) {
|
||||
ready = true;
|
||||
amEof = true;
|
||||
break;
|
||||
} else {
|
||||
keybuffer.push_back((char)val);
|
||||
if (Console::GetEcho())
|
||||
printf("%c", (char)val);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (ready) {
|
||||
char c = keybuffer.front();
|
||||
keybuffer.erase(keybuffer.begin());
|
||||
return c;
|
||||
}
|
||||
|
||||
} else {
|
||||
int c = fgetc(stdin);
|
||||
if (c == -1)
|
||||
return -1;
|
||||
if (Console::GetEcho())
|
||||
printf("%c", (char)c);
|
||||
return c;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
int Console::Read() {
|
||||
#if defined(WIN32)
|
||||
#if defined(__SWITCH__) || defined(GEKKO)
|
||||
#if defined(HW_RVL)
|
||||
if (USBKeyboard_IsConnected()) {
|
||||
return read_char_wiikeyboard();
|
||||
}
|
||||
#endif
|
||||
return -1;
|
||||
#elif defined(WIN32)
|
||||
if (keyOffset >= 0 && keyOffset < key.size()) {
|
||||
return (int)key[keyOffset++];
|
||||
} else {
|
||||
@@ -609,6 +903,48 @@ int Console::Read() {
|
||||
}
|
||||
|
||||
std::string Console::ReadLine() {
|
||||
#if defined(GEKKO)
|
||||
#if defined(HW_RVL)
|
||||
if (USBKeyboard_IsConnected()) {
|
||||
std::string text;
|
||||
|
||||
while (true) {
|
||||
int chr = read_char_wiikeyboard();
|
||||
if (chr == '\n' || chr == -1)
|
||||
break;
|
||||
else
|
||||
text.push_back((char)chr);
|
||||
}
|
||||
|
||||
return text;
|
||||
}
|
||||
#endif
|
||||
return "";
|
||||
#elif defined(__SWITCH__)
|
||||
consoleUpdate(NULL);
|
||||
// bring up nx keyboard
|
||||
SwkbdConfig kbd;
|
||||
Result rc = swkbdCreate(&kbd, 0);
|
||||
if (R_SUCCEEDED(rc)) {
|
||||
swkbdConfigMakePresetDefault(&kbd);
|
||||
// swkbdConfigMakePresetPassword(&kbd);
|
||||
char *text = new char[CONSOLE_READ_BUFFER_MAX];
|
||||
rc = swkbdShow(&kbd, text, CONSOLE_READ_BUFFER_MAX);
|
||||
if (R_SUCCEEDED(rc)) {
|
||||
swkbdClose(&kbd);
|
||||
|
||||
std::string str = text;
|
||||
delete[] text;
|
||||
Console::WriteLine(str);
|
||||
return str;
|
||||
}
|
||||
delete[] text;
|
||||
swkbdClose(&kbd);
|
||||
}
|
||||
|
||||
Console::WriteLine("");
|
||||
return "";
|
||||
#else
|
||||
std::string text;
|
||||
int c = Read();
|
||||
while (c != '\n' && c != -1) {
|
||||
@@ -619,6 +955,7 @@ std::string Console::ReadLine() {
|
||||
if (!text.empty() && text.back() == '\r')
|
||||
text.resize(text.size() - 1);
|
||||
return text;
|
||||
#endif
|
||||
}
|
||||
#if defined(_WIN32)
|
||||
void writeTextWin32(HANDLE hndl, const std::string &text) {
|
||||
@@ -651,7 +988,100 @@ void writeTextUnix(FILE *f, std::string_view view) {
|
||||
}
|
||||
#endif
|
||||
void Console::WriteToStream(std::string_view view, bool isStderr) {
|
||||
#if defined(_WIN32)
|
||||
#if defined(GEKKO) // BECAUSE GEKKO's console doesn't allow you to switch chars,
|
||||
// we must emulate
|
||||
std::string text;
|
||||
for (size_t i = 0; i < view.size(); ++i) {
|
||||
if (view[i] == '\x1b') {
|
||||
if (!text.empty()) {
|
||||
|
||||
writeTextUnix(isStderr ? stderr : stdout, text);
|
||||
// fwrite(text.c_str(), 1, text.size(), f);
|
||||
text.clear();
|
||||
}
|
||||
i++;
|
||||
if (i < view.size()) {
|
||||
if (view[i] == '[') {
|
||||
i++;
|
||||
for (; i < view.size(); ++i) {
|
||||
text += view[i];
|
||||
if (view[i] >= 0x40 && view[i] <= 0x7e)
|
||||
break;
|
||||
}
|
||||
if (text.size() > 0 && text.back() == 'H') {
|
||||
MoveToHome();
|
||||
}
|
||||
if (text.size() > 0 && text.back() == 'J') {
|
||||
if (text[0] == '2') {
|
||||
ClearRetainPosition(
|
||||
ClearBehaviour::CB_ENTIRESCREEN);
|
||||
}
|
||||
|
||||
if (text[0] == '1') {
|
||||
ClearRetainPosition(
|
||||
ClearBehaviour::CB_CURSORANDABOVE);
|
||||
}
|
||||
if (text[0] == '0') {
|
||||
ClearRetainPosition(
|
||||
ClearBehaviour::CB_CURSORANDBELOW);
|
||||
}
|
||||
}
|
||||
|
||||
if (text.size() > 0 && text.back() == 'm') {
|
||||
if (text.size() == 1) {
|
||||
consoleHelpers.reset();
|
||||
} else {
|
||||
try {
|
||||
auto num =
|
||||
std::stol(text.substr(0, text.size() - 1));
|
||||
if (num == 0)
|
||||
consoleHelpers.reset();
|
||||
if (num == 7)
|
||||
Console::SetInvertedColors(true);
|
||||
if (num == 27)
|
||||
Console::SetInvertedColors(false);
|
||||
if (num >= 30 && num <= 37) {
|
||||
SetForegroundColor((ConsoleColor)(num - 30),
|
||||
false);
|
||||
} else if (num >= 40 && num <= 47) {
|
||||
SetBackgroundColor((ConsoleColor)(num - 40),
|
||||
false);
|
||||
} else if (num >= 90 && num <= 97) {
|
||||
SetForegroundColor((ConsoleColor)(num - 90),
|
||||
true);
|
||||
} else if (num >= 100 && num <= 107) {
|
||||
SetBackgroundColor(
|
||||
(ConsoleColor)(num - 100), true);
|
||||
}
|
||||
} catch (...) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
text.clear();
|
||||
|
||||
} else {
|
||||
text += "\x1B";
|
||||
text += view[i];
|
||||
}
|
||||
}
|
||||
|
||||
} else if (view[i] == '\n') {
|
||||
text += "\r\n";
|
||||
|
||||
writeTextUnix(isStderr ? stderr : stdout, text);
|
||||
text.clear();
|
||||
} else {
|
||||
text += view[i];
|
||||
}
|
||||
}
|
||||
|
||||
if (!text.empty()) {
|
||||
|
||||
writeTextUnix(isStderr ? stderr : stdout, text);
|
||||
text.clear();
|
||||
}
|
||||
#elif defined(_WIN32)
|
||||
HANDLE hOut = GetStdHandle(isStderr ? STD_ERROR_HANDLE : STD_OUTPUT_HANDLE);
|
||||
if (hOut == INVALID_HANDLE_VALUE)
|
||||
return;
|
||||
@@ -777,7 +1207,9 @@ void Console::ErrorLineView(std::string_view view) {
|
||||
}
|
||||
void Console::ErrorView(std::string_view view) { WriteToStream(view, true); }
|
||||
bool Console::IsTTY() {
|
||||
#if defined(_WIN32)
|
||||
#if defined(GEKKO) || defined(__SWITCH__)
|
||||
return true;
|
||||
#elif defined(_WIN32)
|
||||
HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||
if (hOut == INVALID_HANDLE_VALUE)
|
||||
return false;
|
||||
@@ -829,8 +1261,16 @@ void Console::ProgressBar(int v) { ProgressBar((double)v / 100.0); }
|
||||
std::pair<int, int> Console::GetSize() {
|
||||
if (!Console::IsTTY())
|
||||
return std::pair<int, int>(0, 0);
|
||||
|
||||
#if __has_include(<termios.h>)
|
||||
#if defined(GEKKO)
|
||||
int w, h;
|
||||
CON_GetMetrics(&w, &h);
|
||||
return std::pair<int, int>(w, h);
|
||||
#elif defined(__SWITCH__)
|
||||
PrintConsole *console = consoleGetDefault();
|
||||
if (console == nullptr)
|
||||
return std::pair<int, int>(0, 0);
|
||||
return std::pair<int, int>(console->consoleWidth, console->consoleHeight);
|
||||
#elif __has_include(<termios.h>)
|
||||
struct winsize ws;
|
||||
if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &ws) == 0) {
|
||||
return std::make_pair<int, int>(ws.ws_col, ws.ws_row);
|
||||
@@ -854,7 +1294,7 @@ std::pair<int, int> Console::GetSize() {
|
||||
void Console::SetPosition(int x, int y) {
|
||||
if (!IsTTY())
|
||||
return;
|
||||
#if __has_include(<termios.h>)
|
||||
#if __has_include(<termios.h>) || defined(__SWITCH__) || defined(GEKKO)
|
||||
printf("\x1B[%i;%iH", y + 1, x + 1);
|
||||
#elif defined(_WIN32)
|
||||
HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||
@@ -876,7 +1316,10 @@ void Console::Clear() {
|
||||
}
|
||||
|
||||
void Console::ClearRetainPosition(ClearBehaviour cb) {
|
||||
#if __has_include(<termios.h>)
|
||||
#if defined(GEKKO) || defined(__SWITCH__)
|
||||
printf("\x1b[%iJ", (int)cb);
|
||||
Flush();
|
||||
#elif __has_include(<termios.h>)
|
||||
if (isatty(STDOUT_FILENO)) {
|
||||
printf("\x1b[%iJ", (int)cb);
|
||||
Flush();
|
||||
@@ -946,7 +1389,13 @@ void Console::ClearRetainPosition(ClearBehaviour cb) {
|
||||
#endif
|
||||
}
|
||||
void Console::MoveToHome() {
|
||||
#if __has_include(<termios.h>)
|
||||
#if defined(GEKKO)
|
||||
printf("\x1b[h");
|
||||
fflush(stdout);
|
||||
#elif defined(__SWITCH__)
|
||||
Write("\x1b[H");
|
||||
Flush();
|
||||
#elif __has_include(<termios.h>)
|
||||
if (isatty(STDOUT_FILENO)) {
|
||||
Write("\x1b[H");
|
||||
Flush();
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
/*
|
||||
TessesFramework a library to make C++ easier for me, used in CrossLang:
|
||||
https://git.tesses.org/tesses50/crosslang Copyright (C) 2026 Mike Nolan
|
||||
https://git.tesses.org/tesses50/crosslang
|
||||
|
||||
Copyright (C) 2026 Mike Nolan
|
||||
SPDX-License-Identifier: GPL-3.0-or-later WITH TessesFramework-Exception-1.0
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
/*
|
||||
TessesFramework a library to make C++ easier for me, used in CrossLang:
|
||||
https://git.tesses.org/tesses50/crosslang Copyright (C) 2026 Mike Nolan
|
||||
https://git.tesses.org/tesses50/crosslang
|
||||
|
||||
Copyright (C) 2026 Mike Nolan
|
||||
SPDX-License-Identifier: GPL-3.0-or-later WITH TessesFramework-Exception-1.0
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
|
||||
+6
-8
@@ -27,16 +27,17 @@
|
||||
#include <sstream>
|
||||
using namespace std::chrono;
|
||||
using namespace date;
|
||||
#if defined(__FreeBSD__)
|
||||
extern int tf_timezone;
|
||||
extern bool tf_daylight;
|
||||
#endif
|
||||
namespace Tesses::Framework::Date {
|
||||
int GetTimeZone() {
|
||||
|
||||
#if defined(__SWITCH__) || defined(_WIN32) || defined(GEKKO) || defined(__PS2__)
|
||||
return (int)(-_timezone);
|
||||
#elif defined(__FreeBSD__)
|
||||
struct timeval tv;
|
||||
struct timezone tz;
|
||||
gettimeofday(&tv, &tz);
|
||||
return (tz.tz_minuteswest / 60);
|
||||
return tf_timezone;
|
||||
#else
|
||||
return (int)(-timezone);
|
||||
#endif
|
||||
@@ -45,10 +46,7 @@ bool TimeZoneSupportDST() {
|
||||
#if defined(__SWITCH__) || defined(_WIN32) || defined(GEKKO) || defined(__PS2__)
|
||||
return _daylight == 1;
|
||||
#elif defined(__FreeBSD__)
|
||||
struct timeval tv;
|
||||
struct timezone tz;
|
||||
gettimeofday(&tv, &tz);
|
||||
return tz.tz_dsttime != 0;
|
||||
return tf_daylight;
|
||||
#else
|
||||
return daylight == 1;
|
||||
#endif
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
/*
|
||||
TessesFramework a library to make C++ easier for me, used in CrossLang:
|
||||
https://git.tesses.org/tesses50/crosslang Copyright (C) 2026 Mike Nolan
|
||||
https://git.tesses.org/tesses50/crosslang
|
||||
|
||||
Copyright (C) 2026 Mike Nolan
|
||||
SPDX-License-Identifier: GPL-3.0-or-later WITH TessesFramework-Exception-1.0
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
/*
|
||||
TessesFramework a library to make C++ easier for me, used in CrossLang:
|
||||
https://git.tesses.org/tesses50/crosslang Copyright (C) 2026 Mike Nolan
|
||||
https://git.tesses.org/tesses50/crosslang
|
||||
|
||||
Copyright (C) 2026 Mike Nolan
|
||||
SPDX-License-Identifier: GPL-3.0-or-later WITH TessesFramework-Exception-1.0
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@@ -241,7 +244,7 @@ void LocalFilesystem::Chmod(VFSPath path, uint32_t mode) {
|
||||
}
|
||||
void LocalFilesystem::Chown(VFSPath path, uint32_t uid, uint32_t gid) {
|
||||
auto pathStr = this->VFSPathToSystem(path);
|
||||
#if defined(_WIN32)
|
||||
#if defined(_WIN32) || defined(GEKKO) || defined(__SWITCH__)
|
||||
|
||||
#else
|
||||
chown(pathStr.c_str(), (uid_t)uid, (gid_t)gid);
|
||||
@@ -250,7 +253,8 @@ void LocalFilesystem::Chown(VFSPath path, uint32_t uid, uint32_t gid) {
|
||||
|
||||
FIFOCreationResult LocalFilesystem::CreateFIFO(VFSPath path, uint32_t mod) {
|
||||
auto pathStr = this->VFSPathToSystem(path);
|
||||
#if defined(_WIN32)
|
||||
|
||||
#if defined(_WIN32) || defined(GEKKO) || defined(__SWITCH__)
|
||||
return FIFOCreationResult::Unsupported;
|
||||
#else
|
||||
int res = mkfifo(pathStr.c_str(), (mode_t)mod);
|
||||
|
||||
@@ -1,3 +1,24 @@
|
||||
/*
|
||||
TessesFramework a library to make C++ easier for me, used in CrossLang:
|
||||
https://git.tesses.org/tesses50/crosslang
|
||||
|
||||
Copyright (C) 2026 Mike Nolan
|
||||
SPDX-License-Identifier: GPL-3.0-or-later WITH TessesFramework-Exception-1.0
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "TessesFramework/Filesystem/MountableFilesystem.hpp"
|
||||
#include "TessesFramework/Filesystem/NullFilesystem.hpp"
|
||||
#include <iostream>
|
||||
|
||||
@@ -1,3 +1,24 @@
|
||||
/*
|
||||
TessesFramework a library to make C++ easier for me, used in CrossLang:
|
||||
https://git.tesses.org/tesses50/crosslang
|
||||
|
||||
Copyright (C) 2026 Mike Nolan
|
||||
SPDX-License-Identifier: GPL-3.0-or-later WITH TessesFramework-Exception-1.0
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "TessesFramework/Filesystem/NullFilesystem.hpp"
|
||||
|
||||
namespace Tesses::Framework::Filesystem {
|
||||
|
||||
@@ -1,3 +1,24 @@
|
||||
/*
|
||||
TessesFramework a library to make C++ easier for me, used in CrossLang:
|
||||
https://git.tesses.org/tesses50/crosslang
|
||||
|
||||
Copyright (C) 2026 Mike Nolan
|
||||
SPDX-License-Identifier: GPL-3.0-or-later WITH TessesFramework-Exception-1.0
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "TessesFramework/Filesystem/RelativeFilesystem.hpp"
|
||||
|
||||
namespace Tesses::Framework::Filesystem {
|
||||
|
||||
@@ -1,3 +1,24 @@
|
||||
/*
|
||||
TessesFramework a library to make C++ easier for me, used in CrossLang:
|
||||
https://git.tesses.org/tesses50/crosslang
|
||||
|
||||
Copyright (C) 2026 Mike Nolan
|
||||
SPDX-License-Identifier: GPL-3.0-or-later WITH TessesFramework-Exception-1.0
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "TessesFramework/Filesystem/SubdirFilesystem.hpp"
|
||||
#include "TessesFramework/Filesystem/LocalFS.hpp"
|
||||
#include <iostream>
|
||||
|
||||
@@ -1,3 +1,24 @@
|
||||
/*
|
||||
TessesFramework a library to make C++ easier for me, used in CrossLang:
|
||||
https://git.tesses.org/tesses50/crosslang
|
||||
|
||||
Copyright (C) 2026 Mike Nolan
|
||||
SPDX-License-Identifier: GPL-3.0-or-later WITH TessesFramework-Exception-1.0
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "TessesFramework/Filesystem/TempFS.hpp"
|
||||
#include "TessesFramework/Filesystem/LocalFS.hpp"
|
||||
#include "TessesFramework/Filesystem/SubdirFilesystem.hpp"
|
||||
|
||||
@@ -1,3 +1,24 @@
|
||||
/*
|
||||
TessesFramework a library to make C++ easier for me, used in CrossLang:
|
||||
https://git.tesses.org/tesses50/crosslang
|
||||
|
||||
Copyright (C) 2026 Mike Nolan
|
||||
SPDX-License-Identifier: GPL-3.0-or-later WITH TessesFramework-Exception-1.0
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "TessesFramework/Filesystem/VFS.hpp"
|
||||
#include "TessesFramework/Filesystem/LocalFS.hpp"
|
||||
#include "TessesFramework/Http/HttpUtils.hpp"
|
||||
|
||||
+4
-1
@@ -1,6 +1,9 @@
|
||||
/*
|
||||
TessesFramework a library to make C++ easier for me, used in CrossLang:
|
||||
https://git.tesses.org/tesses50/crosslang Copyright (C) 2026 Mike Nolan
|
||||
https://git.tesses.org/tesses50/crosslang
|
||||
|
||||
Copyright (C) 2026 Mike Nolan
|
||||
SPDX-License-Identifier: GPL-3.0-or-later WITH TessesFramework-Exception-1.0
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
|
||||
@@ -963,8 +963,8 @@ operator<<(std::basic_ostream<CharT, Traits>& os, const year_month_weekday_last&
|
||||
inline namespace literals
|
||||
{
|
||||
|
||||
CONSTCD11 date::day operator "" _d(unsigned long long d) NOEXCEPT;
|
||||
CONSTCD11 date::year operator "" _y(unsigned long long y) NOEXCEPT;
|
||||
CONSTCD11 date::day operator ""_d(unsigned long long d) NOEXCEPT;
|
||||
CONSTCD11 date::year operator ""_y(unsigned long long y) NOEXCEPT;
|
||||
|
||||
} // inline namespace literals
|
||||
#endif // !defined(_MSC_VER) || (_MSC_VER >= 1900)
|
||||
@@ -1972,7 +1972,7 @@ inline namespace literals
|
||||
CONSTCD11
|
||||
inline
|
||||
date::day
|
||||
operator "" _d(unsigned long long d) NOEXCEPT
|
||||
operator ""_d(unsigned long long d) NOEXCEPT
|
||||
{
|
||||
return date::day{static_cast<unsigned>(d)};
|
||||
}
|
||||
@@ -1980,7 +1980,7 @@ operator "" _d(unsigned long long d) NOEXCEPT
|
||||
CONSTCD11
|
||||
inline
|
||||
date::year
|
||||
operator "" _y(unsigned long long y) NOEXCEPT
|
||||
operator ""_y(unsigned long long y) NOEXCEPT
|
||||
{
|
||||
return date::year(static_cast<int>(y));
|
||||
}
|
||||
@@ -6784,7 +6784,7 @@ from_stream(std::basic_istream<CharT, Traits>& is, const CharT* fmt,
|
||||
checked_set(m, static_cast<int>(i % 12 + 1), not_a_month, is);
|
||||
ws(is);
|
||||
int td = not_a_day;
|
||||
read(is, rs{td, 1, 2});
|
||||
read(is, ru{td, 1, 2});
|
||||
checked_set(d, td, not_a_day, is);
|
||||
ws(is);
|
||||
using dfs = detail::decimal_format_seconds<Duration>;
|
||||
@@ -6800,7 +6800,9 @@ from_stream(std::basic_istream<CharT, Traits>& is, const CharT* fmt,
|
||||
not_a_second, is);
|
||||
ws(is);
|
||||
int tY = not_a_year;
|
||||
read(is, rs{tY, 1, 4u});
|
||||
// No need for `rs` here, negative years can't parse
|
||||
// with "%c" since `width` is hardcoded to 4
|
||||
read(is, ru{tY, 1, 4u});
|
||||
checked_set(Y, tY, not_a_year, is);
|
||||
#endif
|
||||
}
|
||||
@@ -6834,7 +6836,7 @@ from_stream(std::basic_istream<CharT, Traits>& is, const CharT* fmt,
|
||||
int tm = not_a_month;
|
||||
int td = not_a_day;
|
||||
read(is, ru{tm, 1, 2}, CharT{'/'}, ru{td, 1, 2}, CharT{'/'},
|
||||
rs{ty, 1, 2});
|
||||
ru{ty, 1, 2});
|
||||
checked_set(y, ty, not_a_2digit_year, is);
|
||||
checked_set(m, tm, not_a_month, is);
|
||||
checked_set(d, td, not_a_day, is);
|
||||
@@ -6930,7 +6932,7 @@ from_stream(std::basic_istream<CharT, Traits>& is, const CharT* fmt,
|
||||
int ty = not_a_2digit_year;
|
||||
read(is, ru{tn, 1, 2}, CharT{'\0'}, CharT{'/'}, CharT{'\0'},
|
||||
ru{td, 1, 2}, CharT{'\0'}, CharT{'/'}, CharT{'\0'},
|
||||
rs{ty, 1, 2});
|
||||
ru{ty, 1, 2});
|
||||
checked_set(y, ty, not_a_2digit_year, is);
|
||||
checked_set(m, tn, not_a_month, is);
|
||||
checked_set(d, td, not_a_day, is);
|
||||
@@ -6978,7 +6980,7 @@ from_stream(std::basic_istream<CharT, Traits>& is, const CharT* fmt,
|
||||
#endif
|
||||
{
|
||||
int td = not_a_day;
|
||||
read(is, rs{td, 1, width == -1 ? 2u : static_cast<unsigned>(width)});
|
||||
read(is, ru{td, 1, width == -1 ? 2u : static_cast<unsigned>(width)});
|
||||
checked_set(d, td, not_a_day, is);
|
||||
}
|
||||
#if !ONLY_C_LOCALE
|
||||
@@ -7042,7 +7044,7 @@ from_stream(std::basic_istream<CharT, Traits>& is, const CharT* fmt,
|
||||
{
|
||||
int tI = not_a_hour_12_value;
|
||||
// reads in an hour into I, but most be in [1, 12]
|
||||
read(is, rs{tI, 1, width == -1 ? 2u : static_cast<unsigned>(width)});
|
||||
read(is, ru{tI, 1, width == -1 ? 2u : static_cast<unsigned>(width)});
|
||||
if (!(1 <= tI && tI <= 12))
|
||||
is.setstate(ios::failbit);
|
||||
checked_set(I, tI, not_a_hour_12_value, is);
|
||||
@@ -7116,7 +7118,7 @@ from_stream(std::basic_istream<CharT, Traits>& is, const CharT* fmt,
|
||||
#endif
|
||||
{
|
||||
int tn = not_a_month;
|
||||
read(is, rs{tn, 1, width == -1 ? 2u : static_cast<unsigned>(width)});
|
||||
read(is, ru{tn, 1, width == -1 ? 2u : static_cast<unsigned>(width)});
|
||||
checked_set(m, tn, not_a_month, is);
|
||||
}
|
||||
#if !ONLY_C_LOCALE
|
||||
@@ -7536,7 +7538,7 @@ from_stream(std::basic_istream<CharT, Traits>& is, const CharT* fmt,
|
||||
}
|
||||
if (modified == CharT{})
|
||||
{
|
||||
read(is, rs{tH, 2, 2});
|
||||
read(is, ru{tH, 2, 2});
|
||||
if (!is.fail())
|
||||
toff = hours{std::abs(tH)};
|
||||
if (is.good())
|
||||
@@ -7556,7 +7558,7 @@ from_stream(std::basic_istream<CharT, Traits>& is, const CharT* fmt,
|
||||
}
|
||||
else
|
||||
{
|
||||
read(is, rs{tH, 1, 2});
|
||||
read(is, ru{tH, 1, 2});
|
||||
if (!is.fail())
|
||||
toff = hours{std::abs(tH)};
|
||||
if (is.good())
|
||||
@@ -7575,7 +7577,7 @@ from_stream(std::basic_istream<CharT, Traits>& is, const CharT* fmt,
|
||||
}
|
||||
}
|
||||
}
|
||||
if (neg)
|
||||
if (neg && !is.fail())
|
||||
toff = -toff;
|
||||
checked_set(temp_offset, toff, not_a_offset, is);
|
||||
command = nullptr;
|
||||
|
||||
@@ -758,8 +758,8 @@ operator<<(std::basic_ostream<CharT, Traits>& os, const year_month_weekday_last&
|
||||
inline namespace literals
|
||||
{
|
||||
|
||||
CONSTCD11 islamic::day operator "" _d(unsigned long long d) NOEXCEPT;
|
||||
CONSTCD11 islamic::year operator "" _y(unsigned long long y) NOEXCEPT;
|
||||
CONSTCD11 islamic::day operator ""_d(unsigned long long d) NOEXCEPT;
|
||||
CONSTCD11 islamic::year operator ""_y(unsigned long long y) NOEXCEPT;
|
||||
|
||||
} // inline namespace literals
|
||||
#endif // !defined(_MSC_VER) || (_MSC_VER >= 1900)
|
||||
@@ -1339,7 +1339,7 @@ inline namespace literals
|
||||
CONSTCD11
|
||||
inline
|
||||
islamic::day
|
||||
operator "" _d(unsigned long long d) NOEXCEPT
|
||||
operator ""_d(unsigned long long d) NOEXCEPT
|
||||
{
|
||||
return islamic::day{static_cast<unsigned>(d)};
|
||||
}
|
||||
@@ -1347,7 +1347,7 @@ operator "" _d(unsigned long long d) NOEXCEPT
|
||||
CONSTCD11
|
||||
inline
|
||||
islamic::year
|
||||
operator "" _y(unsigned long long y) NOEXCEPT
|
||||
operator ""_y(unsigned long long y) NOEXCEPT
|
||||
{
|
||||
return islamic::year(static_cast<int>(y));
|
||||
}
|
||||
|
||||
@@ -747,7 +747,7 @@ inline namespace literals
|
||||
CONSTCD11
|
||||
inline
|
||||
iso_week::year
|
||||
operator "" _y(unsigned long long y) NOEXCEPT
|
||||
operator ""_y(unsigned long long y) NOEXCEPT
|
||||
{
|
||||
return iso_week::year(static_cast<int>(y));
|
||||
}
|
||||
@@ -755,7 +755,7 @@ operator "" _y(unsigned long long y) NOEXCEPT
|
||||
CONSTCD11
|
||||
inline
|
||||
iso_week::weeknum
|
||||
operator "" _w(unsigned long long wn) NOEXCEPT
|
||||
operator ""_w(unsigned long long wn) NOEXCEPT
|
||||
{
|
||||
return iso_week::weeknum(static_cast<unsigned>(wn));
|
||||
}
|
||||
|
||||
@@ -758,8 +758,8 @@ operator<<(std::basic_ostream<CharT, Traits>& os, const year_month_weekday_last&
|
||||
inline namespace literals
|
||||
{
|
||||
|
||||
CONSTCD11 julian::day operator "" _d(unsigned long long d) NOEXCEPT;
|
||||
CONSTCD11 julian::year operator "" _y(unsigned long long y) NOEXCEPT;
|
||||
CONSTCD11 julian::day operator ""_d(unsigned long long d) NOEXCEPT;
|
||||
CONSTCD11 julian::year operator ""_y(unsigned long long y) NOEXCEPT;
|
||||
|
||||
// CONSTDATA julian::month jan{1};
|
||||
// CONSTDATA julian::month feb{2};
|
||||
@@ -1333,7 +1333,7 @@ inline namespace literals
|
||||
CONSTCD11
|
||||
inline
|
||||
julian::day
|
||||
operator "" _d(unsigned long long d) NOEXCEPT
|
||||
operator ""_d(unsigned long long d) NOEXCEPT
|
||||
{
|
||||
return julian::day{static_cast<unsigned>(d)};
|
||||
}
|
||||
@@ -1341,7 +1341,7 @@ operator "" _d(unsigned long long d) NOEXCEPT
|
||||
CONSTCD11
|
||||
inline
|
||||
julian::year
|
||||
operator "" _y(unsigned long long y) NOEXCEPT
|
||||
operator ""_y(unsigned long long y) NOEXCEPT
|
||||
{
|
||||
return julian::year(static_cast<int>(y));
|
||||
}
|
||||
|
||||
@@ -792,8 +792,8 @@ operator<<(std::basic_ostream<CharT, Traits>& os, const year_month_weekday_last&
|
||||
inline namespace literals
|
||||
{
|
||||
|
||||
CONSTCD11 solar_hijri::day operator "" _d(unsigned long long d) NOEXCEPT;
|
||||
CONSTCD11 solar_hijri::year operator "" _y(unsigned long long y) NOEXCEPT;
|
||||
CONSTCD11 solar_hijri::day operator ""_d(unsigned long long d) NOEXCEPT;
|
||||
CONSTCD11 solar_hijri::year operator ""_y(unsigned long long y) NOEXCEPT;
|
||||
|
||||
} // inline namespace literals
|
||||
#endif // !defined(_MSC_VER) || (_MSC_VER >= 1900)
|
||||
@@ -1364,7 +1364,7 @@ inline namespace literals
|
||||
CONSTCD11
|
||||
inline
|
||||
solar_hijri::day
|
||||
operator "" _d(unsigned long long d) NOEXCEPT
|
||||
operator ""_d(unsigned long long d) NOEXCEPT
|
||||
{
|
||||
return solar_hijri::day{static_cast<unsigned>(d)};
|
||||
}
|
||||
@@ -1372,7 +1372,7 @@ operator "" _d(unsigned long long d) NOEXCEPT
|
||||
CONSTCD11
|
||||
inline
|
||||
solar_hijri::year
|
||||
operator "" _y(unsigned long long y) NOEXCEPT
|
||||
operator ""_y(unsigned long long y) NOEXCEPT
|
||||
{
|
||||
return solar_hijri::year(static_cast<int>(y));
|
||||
}
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
/*
|
||||
TessesFramework a library to make C++ easier for me, used in CrossLang:
|
||||
https://git.tesses.org/tesses50/crosslang Copyright (C) 2026 Mike Nolan
|
||||
https://git.tesses.org/tesses50/crosslang
|
||||
|
||||
Copyright (C) 2026 Mike Nolan
|
||||
SPDX-License-Identifier: GPL-3.0-or-later WITH TessesFramework-Exception-1.0
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
/*
|
||||
TessesFramework a library to make C++ easier for me, used in CrossLang:
|
||||
https://git.tesses.org/tesses50/crosslang Copyright (C) 2026 Mike Nolan
|
||||
https://git.tesses.org/tesses50/crosslang
|
||||
|
||||
Copyright (C) 2026 Mike Nolan
|
||||
SPDX-License-Identifier: GPL-3.0-or-later WITH TessesFramework-Exception-1.0
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
/*
|
||||
TessesFramework a library to make C++ easier for me, used in CrossLang:
|
||||
https://git.tesses.org/tesses50/crosslang Copyright (C) 2026 Mike Nolan
|
||||
https://git.tesses.org/tesses50/crosslang
|
||||
|
||||
Copyright (C) 2026 Mike Nolan
|
||||
SPDX-License-Identifier: GPL-3.0-or-later WITH TessesFramework-Exception-1.0
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
/*
|
||||
TessesFramework a library to make C++ easier for me, used in CrossLang:
|
||||
https://git.tesses.org/tesses50/crosslang Copyright (C) 2026 Mike Nolan
|
||||
https://git.tesses.org/tesses50/crosslang
|
||||
|
||||
Copyright (C) 2026 Mike Nolan
|
||||
SPDX-License-Identifier: GPL-3.0-or-later WITH TessesFramework-Exception-1.0
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
/*
|
||||
TessesFramework a library to make C++ easier for me, used in CrossLang:
|
||||
https://git.tesses.org/tesses50/crosslang Copyright (C) 2026 Mike Nolan
|
||||
https://git.tesses.org/tesses50/crosslang
|
||||
|
||||
Copyright (C) 2026 Mike Nolan
|
||||
SPDX-License-Identifier: GPL-3.0-or-later WITH TessesFramework-Exception-1.0
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
/*
|
||||
TessesFramework a library to make C++ easier for me, used in CrossLang:
|
||||
https://git.tesses.org/tesses50/crosslang Copyright (C) 2026 Mike Nolan
|
||||
https://git.tesses.org/tesses50/crosslang
|
||||
|
||||
Copyright (C) 2026 Mike Nolan
|
||||
SPDX-License-Identifier: GPL-3.0-or-later WITH TessesFramework-Exception-1.0
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
/*
|
||||
TessesFramework a library to make C++ easier for me, used in CrossLang:
|
||||
https://git.tesses.org/tesses50/crosslang Copyright (C) 2026 Mike Nolan
|
||||
https://git.tesses.org/tesses50/crosslang
|
||||
|
||||
Copyright (C) 2026 Mike Nolan
|
||||
SPDX-License-Identifier: GPL-3.0-or-later WITH TessesFramework-Exception-1.0
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@@ -72,7 +75,7 @@ void StreamHttpRequestBody::Write(
|
||||
this->strm->CopyTo(strm);
|
||||
}
|
||||
StreamHttpRequestBody::~StreamHttpRequestBody() {}
|
||||
HttpRequest::HttpRequest() {
|
||||
HttpRequest::HttpRequest() : requestHeaders(false) {
|
||||
this->body = nullptr;
|
||||
this->followRedirects = true;
|
||||
this->ignoreSSLErrors = false;
|
||||
@@ -151,7 +154,8 @@ HttpResponse::GetInternalStream() {
|
||||
|
||||
HttpResponse::~HttpResponse() {}
|
||||
|
||||
HttpResponse::HttpResponse(std::shared_ptr<Stream> strm) {
|
||||
HttpResponse::HttpResponse(std::shared_ptr<Stream> strm)
|
||||
: responseHeaders(false) {
|
||||
this->handleStrm = nullptr;
|
||||
StreamReader reader(strm);
|
||||
std::string statusLine;
|
||||
@@ -176,7 +180,7 @@ HttpResponse::HttpResponse(std::shared_ptr<Stream> strm) {
|
||||
this->handleStrm = strm;
|
||||
}
|
||||
|
||||
HttpResponse::HttpResponse(HttpRequest &req) {
|
||||
HttpResponse::HttpResponse(HttpRequest &req) : responseHeaders(false) {
|
||||
this->handleStrm = nullptr;
|
||||
|
||||
std::string url = req.url;
|
||||
|
||||
+62
-77
@@ -1,6 +1,9 @@
|
||||
/*
|
||||
TessesFramework a library to make C++ easier for me, used in CrossLang:
|
||||
https://git.tesses.org/tesses50/crosslang Copyright (C) 2026 Mike Nolan
|
||||
https://git.tesses.org/tesses50/crosslang
|
||||
|
||||
Copyright (C) 2026 Mike Nolan
|
||||
SPDX-License-Identifier: GPL-3.0-or-later WITH TessesFramework-Exception-1.0
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@@ -349,71 +352,6 @@ class WSServer {
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
static int _header_field(multipart_parser* p, const char *at, size_t length)
|
||||
{
|
||||
UploadData* data = static_cast<UploadData*>(multipart_parser_get_data(p));
|
||||
data->currentHeaderKey = std::string(at,length);
|
||||
return 0;
|
||||
}
|
||||
static int _header_value(multipart_parser* p, const char *at, size_t length)
|
||||
{
|
||||
UploadData* data = static_cast<UploadData*>(multipart_parser_get_data(p));
|
||||
data->currentHeaders.AddValue(data->currentHeaderKey,
|
||||
std::string(at,length)); std::cout << data->currentHeaderKey << ": " <<
|
||||
std::string(at,length) << std::endl; return 0;
|
||||
}
|
||||
static int _part_begin(multipart_parser* p)
|
||||
{
|
||||
UploadData* data = static_cast<UploadData*>(multipart_parser_get_data(p));
|
||||
std::string cd0;
|
||||
ContentDisposition cd1;
|
||||
std::string ct;
|
||||
if(!data->currentHeaders.TryGetFirst("Content-Type",ct))
|
||||
ct = "application/octet-stream";
|
||||
if(data->currentHeaders.TryGetFirst("Content-Disposition", cd0) &&
|
||||
ContentDisposition::TryParse(cd0,cd1))
|
||||
{
|
||||
if(cd1.filename.empty())
|
||||
{
|
||||
data->isFile=false;
|
||||
data->key = cd1.fieldName;
|
||||
data->currentBody = new MemoryStream(true);
|
||||
}
|
||||
else
|
||||
{
|
||||
data->isFile = true;
|
||||
data->currentBody = data->cb(ct, cd1.filename, cd1.fieldName);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
static int _part_end(multipart_parser* p)
|
||||
{
|
||||
UploadData* data = static_cast<UploadData*>(multipart_parser_get_data(p));
|
||||
if(data->currentBody == nullptr) return 0;
|
||||
if(data->isFile)
|
||||
{
|
||||
delete data->currentBody;
|
||||
data->currentBody = nullptr;
|
||||
}
|
||||
else
|
||||
{
|
||||
MemoryStream* ms = dynamic_cast<MemoryStream*>(data->currentBody);
|
||||
if(ms != nullptr)
|
||||
{
|
||||
ms->Seek(0, SeekOrigin::Begin);
|
||||
auto& buff = ms->GetBuffer();
|
||||
data->ctx->queryParams.AddValue(data->key,
|
||||
std::string(buff.begin(),buff.end()));
|
||||
}
|
||||
delete data->currentBody;
|
||||
data->currentBody=nullptr;
|
||||
}
|
||||
data->currentHeaders.Clear();
|
||||
return 0;
|
||||
}*/
|
||||
|
||||
std::string ServerContext::GetUrlWithQuery() {
|
||||
if (this->queryParams.kvp.empty())
|
||||
return this->path;
|
||||
@@ -470,6 +408,8 @@ std::string ServerContext::ReadString() {
|
||||
return {};
|
||||
}
|
||||
bool ServerContext::NeedToParseFormData() {
|
||||
if (method == "GET" || method == "HEAD")
|
||||
return false;
|
||||
std::string ct;
|
||||
if (this->requestHeaders.TryGetFirst("Content-Type", ct)) {
|
||||
if (ct.find("multipart/form-data") == 0) {
|
||||
@@ -478,6 +418,13 @@ bool ServerContext::NeedToParseFormData() {
|
||||
}
|
||||
return false;
|
||||
}
|
||||
/*
|
||||
* The following function is adapted from SimpleHttp.
|
||||
* Original C# Source:
|
||||
* https://github.com/dajuric/simple-http/blob/master/Source/SimpleHTTP/Extensions/Request/RequestExtensions.Multipart.cs
|
||||
* Original Author: Darko Jurić
|
||||
* License: MIT
|
||||
*/
|
||||
static bool
|
||||
parseUntillBoundaryEnd(std::shared_ptr<Tesses::Framework::Streams::Stream> src,
|
||||
std::shared_ptr<Tesses::Framework::Streams::Stream> dest,
|
||||
@@ -542,13 +489,19 @@ parseUntillBoundaryEnd(std::shared_ptr<Tesses::Framework::Streams::Stream> src,
|
||||
}
|
||||
return hasMore;
|
||||
}
|
||||
|
||||
/*
|
||||
* The following function is adapted from SimpleHttp.
|
||||
* Original C# Source:
|
||||
* https://github.com/dajuric/simple-http/blob/master/Source/SimpleHTTP/Extensions/Request/RequestExtensions.Multipart.cs
|
||||
* Original Author: Darko Jurić
|
||||
* License: MIT
|
||||
*/
|
||||
static bool
|
||||
parseSection(ServerContext *ctx, std::string boundary,
|
||||
std::function<std::shared_ptr<Tesses::Framework::Streams::Stream>(
|
||||
std::string mime, std::string filename, std::string name)>
|
||||
cb) {
|
||||
HttpDictionary req;
|
||||
HttpDictionary req(false);
|
||||
StreamReader reader(ctx->GetStream());
|
||||
std::string line;
|
||||
while (reader.ReadLineHttp(line)) {
|
||||
@@ -574,8 +527,8 @@ parseSection(ServerContext *ctx, std::string boundary,
|
||||
parseUntillBoundaryEnd(ctx->GetStream(), ms, boundary);
|
||||
auto &buff = ms->GetBuffer();
|
||||
|
||||
ctx->queryParams.AddValue(cd1.fieldName,
|
||||
std::string(buff.begin(), buff.end()));
|
||||
ctx->bodyParams.AddValue(cd1.fieldName,
|
||||
std::string(buff.begin(), buff.end()));
|
||||
|
||||
return retVal;
|
||||
|
||||
@@ -591,11 +544,19 @@ parseSection(ServerContext *ctx, std::string boundary,
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* The following function is adapted from SimpleHttp.
|
||||
* Original C# Source:
|
||||
* https://github.com/dajuric/simple-http/blob/master/Source/SimpleHTTP/Extensions/Request/RequestExtensions.Multipart.cs
|
||||
* Original Author: Darko Jurić
|
||||
* License: MIT
|
||||
*/
|
||||
void ServerContext::ParseFormData(
|
||||
std::function<std::shared_ptr<Tesses::Framework::Streams::Stream>(
|
||||
std::string mime, std::string filename, std::string name)>
|
||||
cb) {
|
||||
if (method == "GET" || method == "HEAD")
|
||||
return;
|
||||
std::string ct;
|
||||
if (this->requestHeaders.TryGetFirst("Content-Type", ct)) {
|
||||
if (ct.find("multipart/form-data") != 0) {
|
||||
@@ -731,13 +692,13 @@ HttpServer::~HttpServer() {
|
||||
}
|
||||
}
|
||||
IHttpServer::~IHttpServer() {}
|
||||
ServerContext::ServerContext(std::shared_ptr<Stream> strm, bool debug) {
|
||||
ServerContext::ServerContext(std::shared_ptr<Stream> strm, bool debug)
|
||||
: queryParams(true), bodyParams(true), pathArguments(true),
|
||||
requestHeaders(false), responseHeaders(false) {
|
||||
this->statusCode = OK;
|
||||
this->strm = strm;
|
||||
this->debug = debug;
|
||||
this->sent = false;
|
||||
this->queryParams.SetCaseSensitive(true);
|
||||
this->pathArguments.SetCaseSensitive(true);
|
||||
this->responseHeaders.AddValue("Server", "TessesFrameworkWebServer");
|
||||
}
|
||||
std::shared_ptr<Stream> ServerContext::GetStream() { return this->strm; }
|
||||
@@ -788,6 +749,16 @@ ServerContext::~ServerContext() {
|
||||
}
|
||||
}
|
||||
ServerContextData::~ServerContextData() {}
|
||||
|
||||
/*
|
||||
* The following function is inspired or adapted from SimpleHttp.
|
||||
* I don't remember if I used his range code or not but I am declaring this just
|
||||
* in case Original C# Source:
|
||||
* https://github.com/dajuric/simple-http/blob/master/Source/SimpleHTTP/Extensions/Response/ResponseExtensions.PartialStream.cs
|
||||
*
|
||||
* Original Author: Darko Jurić
|
||||
* License: MIT
|
||||
*/
|
||||
void ServerContext::SendStream(std::shared_ptr<Stream> strm) {
|
||||
if (sent)
|
||||
return;
|
||||
@@ -1053,7 +1024,20 @@ void HttpServer::Process(std::shared_ptr<Stream> strm,
|
||||
.SendText("First line is not 3 elements");
|
||||
return;
|
||||
}
|
||||
|
||||
if (v[0] == "TRACE") {
|
||||
std::string httpdata = line + "\r\n";
|
||||
line.clear();
|
||||
while (reader.ReadLineHttp(line)) {
|
||||
httpdata += line + "\r\n";
|
||||
line.clear();
|
||||
}
|
||||
ctx.WithMimeType("message/http").SendText(httpdata);
|
||||
|
||||
return;
|
||||
}
|
||||
ctx.method = v[0];
|
||||
|
||||
auto pp = HttpUtils::SplitString(v[1], "?", 2);
|
||||
pp.resize(2);
|
||||
|
||||
@@ -1090,18 +1074,19 @@ void HttpServer::Process(std::shared_ptr<Stream> strm,
|
||||
std::string type;
|
||||
int64_t length;
|
||||
|
||||
if (ctx.requestHeaders.TryGetFirst("Content-Type", type) &&
|
||||
if (!(ctx.method == "GET" || ctx.method == "HEAD") &&
|
||||
ctx.requestHeaders.TryGetFirst("Content-Type", type) &&
|
||||
type == "application/x-www-form-urlencoded" &&
|
||||
ctx.requestHeaders.TryGetFirstInt("Content-Length", length)) {
|
||||
size_t len = (size_t)length;
|
||||
std::vector<uint8_t> buffer(len);
|
||||
len = bStrm->ReadBlock(buffer.data(), len);
|
||||
std::string query((const char *)buffer.data(), len);
|
||||
HttpUtils::QueryParamsDecode(ctx.queryParams, query);
|
||||
HttpUtils::QueryParamsDecode(ctx.bodyParams, query);
|
||||
}
|
||||
|
||||
if (!server->Handle(ctx)) {
|
||||
if ((int)ctx.statusCode < 400)
|
||||
if ((int)ctx.statusCode == 200)
|
||||
ctx.SendNotFound();
|
||||
else
|
||||
ctx.SendErrorPage(true);
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
/*
|
||||
TessesFramework a library to make C++ easier for me, used in CrossLang:
|
||||
https://git.tesses.org/tesses50/crosslang Copyright (C) 2026 Mike Nolan
|
||||
https://git.tesses.org/tesses50/crosslang
|
||||
|
||||
Copyright (C) 2026 Mike Nolan
|
||||
SPDX-License-Identifier: GPL-3.0-or-later WITH TessesFramework-Exception-1.0
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
/*
|
||||
TessesFramework a library to make C++ easier for me, used in CrossLang:
|
||||
https://git.tesses.org/tesses50/crosslang Copyright (C) 2026 Mike Nolan
|
||||
https://git.tesses.org/tesses50/crosslang
|
||||
|
||||
Copyright (C) 2026 Mike Nolan
|
||||
SPDX-License-Identifier: GPL-3.0-or-later WITH TessesFramework-Exception-1.0
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@@ -138,7 +141,7 @@ bool Uri::TryParse(std::string url, Uri &uri) {
|
||||
|
||||
return true;
|
||||
}
|
||||
Uri::Uri() { this->query.SetCaseSensitive(true); }
|
||||
Uri::Uri() : query(true) {}
|
||||
std::string Uri::GetPathAndQuery() { return this->path + this->GetQuery(); }
|
||||
std::string Uri::GetQuery() {
|
||||
if (this->query.kvp.empty())
|
||||
@@ -180,7 +183,8 @@ std::string HttpUtils::Replace(std::string text, std::string find,
|
||||
}
|
||||
|
||||
std::string HttpUtils::LeftPad(std::string text, int count, char c) {
|
||||
if(text.size() >= (size_t)count) return text;
|
||||
if (text.size() >= (size_t)count)
|
||||
return text;
|
||||
|
||||
text.insert(text.begin(), (size_t)count - text.size(), c);
|
||||
return text;
|
||||
@@ -740,14 +744,10 @@ CaseInsensitiveLess::CaseInsensitiveLess() {
|
||||
this->caseSensitive = false;
|
||||
this->offset = this;
|
||||
}
|
||||
void HttpDictionary::SetCaseSensitive(bool isCaseSensitive) {
|
||||
HttpDictionary::HttpDictionary(bool isCaseSensitive) {
|
||||
|
||||
this->kvp.key_comp().offset->caseSensitive = isCaseSensitive;
|
||||
}
|
||||
HttpDictionary::HttpDictionary(bool isCaseSensitive) {
|
||||
this->SetCaseSensitive(isCaseSensitive);
|
||||
}
|
||||
HttpDictionary::HttpDictionary() : HttpDictionary(false) {}
|
||||
|
||||
bool HttpDictionary::AnyEquals(std::string key, std::string value) {
|
||||
if (this->kvp.count(key) > 0)
|
||||
for (auto v : this->kvp[key])
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
/*
|
||||
TessesFramework a library to make C++ easier for me, used in CrossLang:
|
||||
https://git.tesses.org/tesses50/crosslang Copyright (C) 2026 Mike Nolan
|
||||
https://git.tesses.org/tesses50/crosslang
|
||||
|
||||
Copyright (C) 2026 Mike Nolan
|
||||
SPDX-License-Identifier: GPL-3.0-or-later WITH TessesFramework-Exception-1.0
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
/*
|
||||
TessesFramework a library to make C++ easier for me, used in CrossLang:
|
||||
https://git.tesses.org/tesses50/crosslang Copyright (C) 2026 Mike Nolan
|
||||
https://git.tesses.org/tesses50/crosslang
|
||||
|
||||
Copyright (C) 2026 Mike Nolan
|
||||
SPDX-License-Identifier: GPL-3.0-or-later WITH TessesFramework-Exception-1.0
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@@ -95,8 +98,8 @@ void RouteServer::Delete(std::string pattern, ServerRequestHandler handler) {
|
||||
Add("DELETE", pattern, handler);
|
||||
}
|
||||
|
||||
void RouteServer::Trace(std::string pattern, ServerRequestHandler handler) {
|
||||
Add("TRACE", pattern, handler);
|
||||
void RouteServer::Query(std::string pattern, ServerRequestHandler handler) {
|
||||
Add("QUERY", pattern, handler);
|
||||
}
|
||||
void RouteServer::Options(std::string pattern, ServerRequestHandler handler) {
|
||||
Add("OPTIONS", pattern, handler);
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
/*
|
||||
TessesFramework a library to make C++ easier for me, used in CrossLang:
|
||||
https://git.tesses.org/tesses50/crosslang Copyright (C) 2026 Mike Nolan
|
||||
https://git.tesses.org/tesses50/crosslang
|
||||
|
||||
Copyright (C) 2026 Mike Nolan
|
||||
SPDX-License-Identifier: GPL-3.0-or-later WITH TessesFramework-Exception-1.0
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
|
||||
+4
-1
@@ -1,6 +1,9 @@
|
||||
/*
|
||||
TessesFramework a library to make C++ easier for me, used in CrossLang:
|
||||
https://git.tesses.org/tesses50/crosslang Copyright (C) 2026 Mike Nolan
|
||||
https://git.tesses.org/tesses50/crosslang
|
||||
|
||||
Copyright (C) 2026 Mike Nolan
|
||||
SPDX-License-Identifier: GPL-3.0-or-later WITH TessesFramework-Exception-1.0
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
/*
|
||||
TessesFramework a library to make C++ easier for me, used in CrossLang:
|
||||
https://git.tesses.org/tesses50/crosslang Copyright (C) 2026 Mike Nolan
|
||||
https://git.tesses.org/tesses50/crosslang
|
||||
|
||||
Copyright (C) 2026 Mike Nolan
|
||||
SPDX-License-Identifier: GPL-3.0-or-later WITH TessesFramework-Exception-1.0
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@@ -25,8 +28,9 @@
|
||||
|
||||
// clang-format off
|
||||
#include <windows.h>
|
||||
#include "TessesFramework/Text/StringConverter.hpp"
|
||||
#include "TessesFramework/Filesystem/VFSFix.hpp"
|
||||
#include "TessesFramework/Text/StringConverter.hpp"
|
||||
|
||||
// clang-format on
|
||||
|
||||
using namespace Tesses::Framework::Text::StringConverter;
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
/*
|
||||
TessesFramework a library to make C++ easier for me, used in CrossLang:
|
||||
https://git.tesses.org/tesses50/crosslang Copyright (C) 2026 Mike Nolan
|
||||
https://git.tesses.org/tesses50/crosslang
|
||||
|
||||
Copyright (C) 2026 Mike Nolan
|
||||
SPDX-License-Identifier: GPL-3.0-or-later WITH TessesFramework-Exception-1.0
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@@ -15,7 +18,6 @@
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "TessesFramework/Platform/Process.hpp"
|
||||
#include "TessesFramework/Http/HttpUtils.hpp"
|
||||
#include "TessesFramework/Platform/Environment.hpp"
|
||||
@@ -41,7 +43,7 @@ static void escape_windows_args(std::string &str,
|
||||
|
||||
for (auto c : item) {
|
||||
if (c == '"')
|
||||
str.append("\\\"");
|
||||
str.append("\"\"");
|
||||
else
|
||||
str.push_back(c);
|
||||
}
|
||||
|
||||
+4
-1
@@ -1,6 +1,9 @@
|
||||
/*
|
||||
TessesFramework a library to make C++ easier for me, used in CrossLang:
|
||||
https://git.tesses.org/tesses50/crosslang Copyright (C) 2026 Mike Nolan
|
||||
https://git.tesses.org/tesses50/crosslang
|
||||
|
||||
Copyright (C) 2026 Mike Nolan
|
||||
SPDX-License-Identifier: GPL-3.0-or-later WITH TessesFramework-Exception-1.0
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
/*
|
||||
TessesFramework a library to make C++ easier for me, used in CrossLang:
|
||||
https://git.tesses.org/tesses50/crosslang Copyright (C) 2026 Mike Nolan
|
||||
https://git.tesses.org/tesses50/crosslang
|
||||
|
||||
Copyright (C) 2026 Mike Nolan
|
||||
SPDX-License-Identifier: GPL-3.0-or-later WITH TessesFramework-Exception-1.0
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
/*
|
||||
TessesFramework a library to make C++ easier for me, used in CrossLang:
|
||||
https://git.tesses.org/tesses50/crosslang Copyright (C) 2026 Mike Nolan
|
||||
https://git.tesses.org/tesses50/crosslang
|
||||
|
||||
Copyright (C) 2026 Mike Nolan
|
||||
SPDX-License-Identifier: GPL-3.0-or-later WITH TessesFramework-Exception-1.0
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
|
||||
+44
-64
@@ -1,6 +1,9 @@
|
||||
/*
|
||||
TessesFramework a library to make C++ easier for me, used in CrossLang:
|
||||
https://git.tesses.org/tesses50/crosslang Copyright (C) 2026 Mike Nolan
|
||||
https://git.tesses.org/tesses50/crosslang
|
||||
|
||||
Copyright (C) 2026 Mike Nolan
|
||||
SPDX-License-Identifier: GPL-3.0-or-later WITH TessesFramework-Exception-1.0
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@@ -15,9 +18,11 @@
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "TessesFramework/Serialization/Json.hpp"
|
||||
#include "TessesFramework/Http/HttpUtils.hpp"
|
||||
#include "TessesFramework/TessesFramework.hpp"
|
||||
#include "TessesFramework/Text/StringConverter.hpp"
|
||||
#include <functional>
|
||||
|
||||
#include "TessesFramework/Common.hpp"
|
||||
@@ -126,78 +131,53 @@ JToken Json::Decode(std::string str) {
|
||||
uint16_t v = 0;
|
||||
if (i + 4 <= str.size()) {
|
||||
for (size_t i2 = 0; i2 < 4; i2++, i++) {
|
||||
if (!((str[i] >= '0' && str[i] <= '9') ||
|
||||
(str[i] >= 'A' && str[i] <= 'F') ||
|
||||
(str[i] >= 'a' && str[i] <= 'f')))
|
||||
throw std::runtime_error(
|
||||
"Invalid hex value");
|
||||
|
||||
v |= HttpUtils::HexToNibble(str[i])
|
||||
<< ((3 - i2) * 4);
|
||||
}
|
||||
i--;
|
||||
|
||||
uint32_t v2 = v;
|
||||
|
||||
if ((v & 0xFC00) == 0xD800) {
|
||||
|
||||
v2 = (v & 0x03FF) << 10;
|
||||
if (i + 6 <= str.size() &&
|
||||
str.substr(i, 2) == "\\u") {
|
||||
i += 2;
|
||||
v = 0;
|
||||
|
||||
for (size_t i2 = 0; i2 < 4; i2++, i++) {
|
||||
v |= HttpUtils::HexToNibble(str[i])
|
||||
<< ((3 - i2) * 4);
|
||||
}
|
||||
if ((v & 0xFC00) != 0xDC00) {
|
||||
throw std::runtime_error(
|
||||
"Not a lower utf-16 surrogate "
|
||||
"pair.");
|
||||
}
|
||||
|
||||
v2 |= (v & 0x03FF);
|
||||
|
||||
v2 += 0x10000;
|
||||
} else {
|
||||
std::u16string unicode = {(char16_t)v};
|
||||
std::string utf8;
|
||||
|
||||
if ((v >= 0xD800) && (v <= 0xDBFF)) {
|
||||
v = 0;
|
||||
i++;
|
||||
if (i + 6 > str.size())
|
||||
throw std::runtime_error(
|
||||
"Could not read lower utf-16 "
|
||||
"surrogate pair.");
|
||||
}
|
||||
if (v2 <= 0x7F) {
|
||||
str2.push_back((char)v2);
|
||||
} else if (v2 >= 0x80 && v2 <= 0x7FF) {
|
||||
uint8_t high = 0b11000000 |
|
||||
((v2 >> 6) & 0b00011111);
|
||||
uint8_t low =
|
||||
0b10000000 | (v2 & 0b00111111);
|
||||
str2.push_back((char)high);
|
||||
str2.push_back((char)low);
|
||||
} else if (v2 >= 0x800 && v2 <= 0xFFFF) {
|
||||
uint8_t highest =
|
||||
0b11100000 |
|
||||
((v2 >> 12) & 0b00001111);
|
||||
uint8_t high = 0b10000000 |
|
||||
((v2 >> 6) & 0b00111111);
|
||||
uint8_t low =
|
||||
0b10000000 | (v2 & 0b00111111);
|
||||
str2.push_back((char)highest);
|
||||
str2.push_back((char)high);
|
||||
str2.push_back((char)low);
|
||||
} else if (v2 >= 0x010000 &&
|
||||
v2 <= 0x10FFFF) {
|
||||
uint8_t highest =
|
||||
0b11110000 |
|
||||
((v2 >> 18) & 0b00000111);
|
||||
uint8_t high =
|
||||
0b10000000 |
|
||||
((v2 >> 12) & 0b00111111);
|
||||
uint8_t low = 0b10000000 |
|
||||
((v2 >> 6) & 0b00111111);
|
||||
uint8_t lowest =
|
||||
0b10000000 | (v2 & 0b00111111);
|
||||
str2.push_back((char)highest);
|
||||
str2.push_back((char)high);
|
||||
str2.push_back((char)low);
|
||||
str2.push_back((char)lowest);
|
||||
"Not enough chars");
|
||||
|
||||
if (str[i] != '\\' || str[i + 1] != 'u')
|
||||
throw std::runtime_error(
|
||||
"Low surogate must begin with \\u");
|
||||
i += 2;
|
||||
for (size_t i2 = 0; i2 < 4; i2++, i++) {
|
||||
if (!((str[i] >= '0' &&
|
||||
str[i] <= '9') ||
|
||||
(str[i] >= 'A' &&
|
||||
str[i] <= 'F') ||
|
||||
(str[i] >= 'a' && str[i] <= 'f')))
|
||||
throw std::runtime_error(
|
||||
"Invalid hex value");
|
||||
|
||||
v |= HttpUtils::HexToNibble(str[i])
|
||||
<< ((3 - i2) * 4);
|
||||
}
|
||||
i--;
|
||||
|
||||
unicode.push_back(v);
|
||||
}
|
||||
|
||||
Text::StringConverter::UTF8::FromUTF16(utf8,
|
||||
unicode);
|
||||
str2.append(utf8);
|
||||
} else {
|
||||
throw std::runtime_error("Not enough chars");
|
||||
}
|
||||
} else {
|
||||
str2.push_back(str[i]);
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
/*
|
||||
TessesFramework a library to make C++ easier for me, used in CrossLang:
|
||||
https://git.tesses.org/tesses50/crosslang Copyright (C) 2026 Mike Nolan
|
||||
https://git.tesses.org/tesses50/crosslang
|
||||
|
||||
Copyright (C) 2026 Mike Nolan
|
||||
SPDX-License-Identifier: GPL-3.0-or-later WITH TessesFramework-Exception-1.0
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
/*
|
||||
TessesFramework a library to make C++ easier for me, used in CrossLang:
|
||||
https://git.tesses.org/tesses50/crosslang Copyright (C) 2026 Mike Nolan
|
||||
https://git.tesses.org/tesses50/crosslang
|
||||
|
||||
Copyright (C) 2026 Mike Nolan
|
||||
SPDX-License-Identifier: GPL-3.0-or-later WITH TessesFramework-Exception-1.0
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
/*
|
||||
TessesFramework a library to make C++ easier for me, used in CrossLang:
|
||||
https://git.tesses.org/tesses50/crosslang Copyright (C) 2026 Mike Nolan
|
||||
https://git.tesses.org/tesses50/crosslang
|
||||
|
||||
Copyright (C) 2026 Mike Nolan
|
||||
SPDX-License-Identifier: GPL-3.0-or-later WITH TessesFramework-Exception-1.0
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
/*
|
||||
TessesFramework a library to make C++ easier for me, used in CrossLang:
|
||||
https://git.tesses.org/tesses50/crosslang Copyright (C) 2026 Mike Nolan
|
||||
https://git.tesses.org/tesses50/crosslang
|
||||
|
||||
Copyright (C) 2026 Mike Nolan
|
||||
SPDX-License-Identifier: GPL-3.0-or-later WITH TessesFramework-Exception-1.0
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
/*
|
||||
TessesFramework a library to make C++ easier for me, used in CrossLang:
|
||||
https://git.tesses.org/tesses50/crosslang Copyright (C) 2026 Mike Nolan
|
||||
https://git.tesses.org/tesses50/crosslang
|
||||
|
||||
Copyright (C) 2026 Mike Nolan
|
||||
SPDX-License-Identifier: GPL-3.0-or-later WITH TessesFramework-Exception-1.0
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
/*
|
||||
TessesFramework a library to make C++ easier for me, used in CrossLang:
|
||||
https://git.tesses.org/tesses50/crosslang Copyright (C) 2026 Mike Nolan
|
||||
https://git.tesses.org/tesses50/crosslang
|
||||
|
||||
Copyright (C) 2026 Mike Nolan
|
||||
SPDX-License-Identifier: GPL-3.0-or-later WITH TessesFramework-Exception-1.0
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
/*
|
||||
TessesFramework a library to make C++ easier for me, used in CrossLang:
|
||||
https://git.tesses.org/tesses50/crosslang Copyright (C) 2026 Mike Nolan
|
||||
https://git.tesses.org/tesses50/crosslang
|
||||
|
||||
Copyright (C) 2026 Mike Nolan
|
||||
SPDX-License-Identifier: GPL-3.0-or-later WITH TessesFramework-Exception-1.0
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@@ -40,8 +43,8 @@ using HttpUtils = Tesses::Framework::Http::HttpUtils;
|
||||
#else
|
||||
|
||||
#if defined(_WIN32)
|
||||
#include <winsock2.h>
|
||||
#include <iphlpapi.h>
|
||||
#include <winsock2.h>
|
||||
|
||||
#include <ws2tcpip.h>
|
||||
|
||||
@@ -886,7 +889,7 @@ void NetworkStream::SetReuseAddress(bool reuse) {}
|
||||
void NetworkStream::SetReusePort(bool reuse) {}
|
||||
void NetworkStream::SetMulticastTTL(uint8_t ttl) {}
|
||||
void NetworkStream::SetMulticastMembership(std::string multicastAddress,
|
||||
std::string ifaceIP = "0.0.0.0") {}
|
||||
std::string ifaceIP) {}
|
||||
|
||||
std::shared_ptr<NetworkStream> NetworkStream::Accept(std::string &ip,
|
||||
uint16_t &port) {
|
||||
|
||||
+19
-23
@@ -1,6 +1,9 @@
|
||||
/*
|
||||
TessesFramework a library to make C++ easier for me, used in CrossLang:
|
||||
https://git.tesses.org/tesses50/crosslang Copyright (C) 2026 Mike Nolan
|
||||
https://git.tesses.org/tesses50/crosslang
|
||||
|
||||
Copyright (C) 2026 Mike Nolan
|
||||
SPDX-License-Identifier: GPL-3.0-or-later WITH TessesFramework-Exception-1.0
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@@ -17,9 +20,8 @@
|
||||
*/
|
||||
|
||||
#include "TessesFramework/Streams/PtyStream.hpp"
|
||||
#if !defined(GEKKO) && !defined(__PS2__) && \
|
||||
!defined(_WIN32) && !defined(__SWITCH__) && \
|
||||
defined(TESSESFRAMEWORK_ENABLE_PROCESS)
|
||||
#if !defined(GEKKO) && !defined(__PS2__) && !defined(_WIN32) && \
|
||||
!defined(__SWITCH__) && defined(TESSESFRAMEWORK_ENABLE_PROCESS)
|
||||
#if __has_include(<util.h>)
|
||||
#include <util.h>
|
||||
#elif __has_include(<pty.h>)
|
||||
@@ -29,18 +31,17 @@
|
||||
#endif
|
||||
#include <fcntl.h>
|
||||
#include <signal.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <termios.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#endif
|
||||
namespace Tesses::Framework::Streams {
|
||||
PtyStream::PtyStream(WindowSize windowSize, std::string filename,
|
||||
std::vector<std::string> args,
|
||||
std::vector<std::string> env) {
|
||||
#if !defined(GEKKO) && !defined(__PS2__) && \
|
||||
!defined(_WIN32) && !defined(__SWITCH__) && \
|
||||
defined(TESSESFRAMEWORK_ENABLE_PROCESS)
|
||||
#if !defined(GEKKO) && !defined(__PS2__) && !defined(_WIN32) && \
|
||||
!defined(__SWITCH__) && defined(TESSESFRAMEWORK_ENABLE_PROCESS)
|
||||
this->wS = windowSize;
|
||||
this->eos = false;
|
||||
winsize sz;
|
||||
@@ -96,9 +97,8 @@ bool PtyStream::CanWrite() { return true; }
|
||||
size_t PtyStream::Read(uint8_t *buff, size_t sz) {
|
||||
if (this->eos)
|
||||
return 0;
|
||||
#if !defined(GEKKO) && !defined(__PS2__) && \
|
||||
!defined(_WIN32) && !defined(__SWITCH__) && \
|
||||
defined(TESSESFRAMEWORK_ENABLE_PROCESS)
|
||||
#if !defined(GEKKO) && !defined(__PS2__) && !defined(_WIN32) && \
|
||||
!defined(__SWITCH__) && defined(TESSESFRAMEWORK_ENABLE_PROCESS)
|
||||
auto res = read(this->socket, buff, sz);
|
||||
|
||||
if (res == -1) {
|
||||
@@ -112,9 +112,8 @@ size_t PtyStream::Read(uint8_t *buff, size_t sz) {
|
||||
#endif
|
||||
}
|
||||
size_t PtyStream::Write(const uint8_t *buff, size_t sz) {
|
||||
#if !defined(GEKKO) && !defined(__PS2__) && \
|
||||
!defined(_WIN32) && !defined(__SWITCH__) && \
|
||||
defined(TESSESFRAMEWORK_ENABLE_PROCESS)
|
||||
#if !defined(GEKKO) && !defined(__PS2__) && !defined(_WIN32) && \
|
||||
!defined(__SWITCH__) && defined(TESSESFRAMEWORK_ENABLE_PROCESS)
|
||||
auto res = write(this->socket, buff, sz);
|
||||
return res;
|
||||
#else
|
||||
@@ -123,9 +122,8 @@ size_t PtyStream::Write(const uint8_t *buff, size_t sz) {
|
||||
}
|
||||
WindowSize PtyStream::GetWindowSize() { return this->wS; }
|
||||
void PtyStream::Resize(WindowSize windowSize) {
|
||||
#if !defined(GEKKO) && !defined(__PS2__) && \
|
||||
!defined(_WIN32) && !defined(__SWITCH__) && \
|
||||
defined(TESSESFRAMEWORK_ENABLE_PROCESS)
|
||||
#if !defined(GEKKO) && !defined(__PS2__) && !defined(_WIN32) && \
|
||||
!defined(__SWITCH__) && defined(TESSESFRAMEWORK_ENABLE_PROCESS)
|
||||
this->wS = windowSize;
|
||||
winsize sz;
|
||||
sz.ws_col = (unsigned short)windowSize.Columns;
|
||||
@@ -140,9 +138,8 @@ PtyStream::~PtyStream() {
|
||||
if (this->eos)
|
||||
return;
|
||||
this->eos = true;
|
||||
#if !defined(GEKKO) && !defined(__PS2__) && \
|
||||
!defined(_WIN32) && !defined(__SWITCH__) && \
|
||||
defined(TESSESFRAMEWORK_ENABLE_PROCESS)
|
||||
#if !defined(GEKKO) && !defined(__PS2__) && !defined(_WIN32) && \
|
||||
!defined(__SWITCH__) && defined(TESSESFRAMEWORK_ENABLE_PROCESS)
|
||||
close(this->socket);
|
||||
|
||||
kill((pid_t)this->pid, SIGHUP);
|
||||
@@ -152,9 +149,8 @@ void PtyStream::Close() {
|
||||
if (this->eos)
|
||||
return;
|
||||
this->eos = true;
|
||||
#if !defined(GEKKO) && !defined(__PS2__) && \
|
||||
!defined(_WIN32) && !defined(__SWITCH__) && \
|
||||
defined(TESSESFRAMEWORK_ENABLE_PROCESS)
|
||||
#if !defined(GEKKO) && !defined(__PS2__) && !defined(_WIN32) && \
|
||||
!defined(__SWITCH__) && defined(TESSESFRAMEWORK_ENABLE_PROCESS)
|
||||
close(this->socket);
|
||||
|
||||
kill((pid_t)this->pid, SIGHUP);
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
/*
|
||||
TessesFramework a library to make C++ easier for me, used in CrossLang:
|
||||
https://git.tesses.org/tesses50/crosslang Copyright (C) 2026 Mike Nolan
|
||||
https://git.tesses.org/tesses50/crosslang
|
||||
|
||||
Copyright (C) 2026 Mike Nolan
|
||||
SPDX-License-Identifier: GPL-3.0-or-later WITH TessesFramework-Exception-1.0
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
|
||||
+20
-10
@@ -1,6 +1,9 @@
|
||||
/*
|
||||
TessesFramework a library to make C++ easier for me, used in CrossLang:
|
||||
https://git.tesses.org/tesses50/crosslang Copyright (C) 2026 Mike Nolan
|
||||
https://git.tesses.org/tesses50/crosslang
|
||||
|
||||
Copyright (C) 2026 Mike Nolan
|
||||
SPDX-License-Identifier: GPL-3.0-or-later WITH TessesFramework-Exception-1.0
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@@ -46,6 +49,9 @@
|
||||
|
||||
#if defined(__FreeBSD__)
|
||||
#include <sys/sysctl.h>
|
||||
int tf_timezone = 0;
|
||||
bool tf_daylight = false;
|
||||
|
||||
#endif
|
||||
|
||||
#if defined(TESSESFRAMEWORK_ENABLE_SQLITE)
|
||||
@@ -262,8 +268,7 @@ int64_t TF_Timer_Handle::GetIntervalMilliseconds() {
|
||||
}
|
||||
|
||||
void TF_RunEventLoopItteration() {
|
||||
#if defined(TESSESFRAMEWORK_ENABLE_THREADING) && \
|
||||
(defined(GEKKO) || defined(__SWITCH__))
|
||||
#if defined(TESSESFRAMEWORK_ENABLE_THREADING) && (defined(__SWITCH__))
|
||||
Tesses::Framework::Threading::LookForFinishedThreads();
|
||||
|
||||
#endif
|
||||
@@ -314,8 +319,7 @@ void TF_RunEventLoopItteration() {
|
||||
void TF_SetIsRunning(bool _isRunning) { isRunning = _isRunning; }
|
||||
void TF_Quit() {
|
||||
isRunning = false;
|
||||
#if defined(TESSESFRAMEWORK_ENABLE_THREADING) && \
|
||||
(defined(GEKKO) || defined(__SWITCH__))
|
||||
#if defined(TESSESFRAMEWORK_ENABLE_THREADING) && (defined(__SWITCH__))
|
||||
Tesses::Framework::Threading::JoinAllThreads();
|
||||
#endif
|
||||
}
|
||||
@@ -330,8 +334,15 @@ void TF_Init() {
|
||||
sqlite3_vfs_register(sqlite3_demovfs(), 1);
|
||||
#endif
|
||||
#endif
|
||||
#if defined(__FreeBSD__)
|
||||
|
||||
time_t t = 0;
|
||||
auto tz = localtime(&t);
|
||||
tf_timezone = tz->tm_gmtoff;
|
||||
tf_daylight = tz->tm_isdst;
|
||||
#else
|
||||
tzset();
|
||||
#endif
|
||||
#if defined(_WIN32)
|
||||
signal(SIGINT, _sigInt);
|
||||
signal(SIGTERM, _sigInt);
|
||||
@@ -510,7 +521,7 @@ std::string TF_GetExecutableName() {
|
||||
if (sysctl(mib, 4, path.data(), &len, NULL, 0) < 0) {
|
||||
return "";
|
||||
}
|
||||
path.resize(len-1);
|
||||
path.resize(strlen(path.c_str()));
|
||||
return path;
|
||||
#elif defined(__NetBSD__)
|
||||
auto path = Filesystem::LocalFS->ReadLink(
|
||||
@@ -526,13 +537,12 @@ std::string TF_GetExecutableName() {
|
||||
path.resize(1025);
|
||||
uint32_t bufsize = (uint32_t)path.size();
|
||||
if (_NSGetExecutablePath(path.data(), &bufsize) == 0) {
|
||||
path.resize(bufsize-1);
|
||||
path.resize(strlen(path.c_str()));
|
||||
return path;
|
||||
} else {
|
||||
path.resize(bufsize);
|
||||
if (_NSGetExecutablePath(path.data(), &bufsize) == 0)
|
||||
{
|
||||
path.resize(bufsize-1);
|
||||
if (_NSGetExecutablePath(path.data(), &bufsize) == 0) {
|
||||
path.resize(strlen(path.c_str()));
|
||||
return path;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
/*
|
||||
TessesFramework a library to make C++ easier for me, used in CrossLang:
|
||||
https://git.tesses.org/tesses50/crosslang Copyright (C) 2026 Mike Nolan
|
||||
https://git.tesses.org/tesses50/crosslang
|
||||
|
||||
Copyright (C) 2026 Mike Nolan
|
||||
SPDX-License-Identifier: GPL-3.0-or-later WITH TessesFramework-Exception-1.0
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
|
||||
+29
-202
@@ -1,6 +1,9 @@
|
||||
/*
|
||||
TessesFramework a library to make C++ easier for me, used in CrossLang:
|
||||
https://git.tesses.org/tesses50/crosslang Copyright (C) 2026 Mike Nolan
|
||||
https://git.tesses.org/tesses50/crosslang
|
||||
|
||||
Copyright (C) 2026 Mike Nolan
|
||||
SPDX-License-Identifier: GPL-3.0-or-later WITH TessesFramework-Exception-1.0
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@@ -17,228 +20,52 @@
|
||||
*/
|
||||
|
||||
#include "TessesFramework/Text/StringConverter.hpp"
|
||||
#include "icubaby.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);
|
||||
}
|
||||
}
|
||||
icubaby::t16_8 t;
|
||||
auto it = icubaby::iterator{&t, std::back_inserter(utf8)};
|
||||
std::copy(std::begin(utf16), std::end(utf16), it);
|
||||
t.end_cp(it);
|
||||
}
|
||||
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);
|
||||
}
|
||||
}
|
||||
icubaby::t32_8 t;
|
||||
auto it = icubaby::iterator{&t, std::back_inserter(utf8)};
|
||||
std::copy(std::begin(utf32), std::end(utf32), it);
|
||||
t.end_cp(it);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
icubaby::t8_16 t;
|
||||
auto it = icubaby::iterator{&t, std::back_inserter(utf16)};
|
||||
std::copy(std::begin(utf8), std::end(utf8), it);
|
||||
t.end_cp(it);
|
||||
}
|
||||
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);
|
||||
}
|
||||
}
|
||||
icubaby::t32_16 t;
|
||||
auto it = icubaby::iterator{&t, std::back_inserter(utf16)};
|
||||
std::copy(std::begin(utf32), std::end(utf32), it);
|
||||
t.end_cp(it);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
icubaby::t8_32 t;
|
||||
auto it = icubaby::iterator{&t, std::back_inserter(utf32)};
|
||||
std::copy(std::begin(utf8), std::end(utf8), it);
|
||||
t.end_cp(it);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
icubaby::t16_32 t;
|
||||
auto it = icubaby::iterator{&t, std::back_inserter(utf32)};
|
||||
std::copy(std::begin(utf16), std::end(utf16), it);
|
||||
t.end_cp(it);
|
||||
}
|
||||
} // namespace Tesses::Framework::Text::StringConverter
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,6 +1,9 @@
|
||||
/*
|
||||
TessesFramework a library to make C++ easier for me, used in CrossLang:
|
||||
https://git.tesses.org/tesses50/crosslang Copyright (C) 2026 Mike Nolan
|
||||
https://git.tesses.org/tesses50/crosslang
|
||||
|
||||
Copyright (C) 2026 Mike Nolan
|
||||
SPDX-License-Identifier: GPL-3.0-or-later WITH TessesFramework-Exception-1.0
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@@ -15,6 +18,7 @@
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "TessesFramework/TextStreams/StdIOReader.hpp"
|
||||
#include "TessesFramework/Console.hpp"
|
||||
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
/*
|
||||
TessesFramework a library to make C++ easier for me, used in CrossLang:
|
||||
https://git.tesses.org/tesses50/crosslang Copyright (C) 2026 Mike Nolan
|
||||
https://git.tesses.org/tesses50/crosslang
|
||||
|
||||
Copyright (C) 2026 Mike Nolan
|
||||
SPDX-License-Identifier: GPL-3.0-or-later WITH TessesFramework-Exception-1.0
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
/*
|
||||
TessesFramework a library to make C++ easier for me, used in CrossLang:
|
||||
https://git.tesses.org/tesses50/crosslang Copyright (C) 2026 Mike Nolan
|
||||
https://git.tesses.org/tesses50/crosslang
|
||||
|
||||
Copyright (C) 2026 Mike Nolan
|
||||
SPDX-License-Identifier: GPL-3.0-or-later WITH TessesFramework-Exception-1.0
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
/*
|
||||
TessesFramework a library to make C++ easier for me, used in CrossLang:
|
||||
https://git.tesses.org/tesses50/crosslang Copyright (C) 2026 Mike Nolan
|
||||
https://git.tesses.org/tesses50/crosslang
|
||||
|
||||
Copyright (C) 2026 Mike Nolan
|
||||
SPDX-License-Identifier: GPL-3.0-or-later WITH TessesFramework-Exception-1.0
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
/*
|
||||
TessesFramework a library to make C++ easier for me, used in CrossLang:
|
||||
https://git.tesses.org/tesses50/crosslang Copyright (C) 2026 Mike Nolan
|
||||
https://git.tesses.org/tesses50/crosslang
|
||||
|
||||
Copyright (C) 2026 Mike Nolan
|
||||
SPDX-License-Identifier: GPL-3.0-or-later WITH TessesFramework-Exception-1.0
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
/*
|
||||
TessesFramework a library to make C++ easier for me, used in CrossLang:
|
||||
https://git.tesses.org/tesses50/crosslang Copyright (C) 2026 Mike Nolan
|
||||
https://git.tesses.org/tesses50/crosslang
|
||||
|
||||
Copyright (C) 2026 Mike Nolan
|
||||
SPDX-License-Identifier: GPL-3.0-or-later WITH TessesFramework-Exception-1.0
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
/*
|
||||
TessesFramework a library to make C++ easier for me, used in CrossLang:
|
||||
https://git.tesses.org/tesses50/crosslang Copyright (C) 2026 Mike Nolan
|
||||
https://git.tesses.org/tesses50/crosslang
|
||||
|
||||
Copyright (C) 2026 Mike Nolan
|
||||
SPDX-License-Identifier: GPL-3.0-or-later WITH TessesFramework-Exception-1.0
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@@ -63,16 +66,17 @@ bool TextReader::ReadLine(std::string &str) {
|
||||
r = ReadChar();
|
||||
if (r == -1)
|
||||
break;
|
||||
if (r == '\n')
|
||||
{
|
||||
if(!str.empty() && str.back() == '\r') str.resize(str.size()-1);
|
||||
if (r == '\n') {
|
||||
if (!str.empty() && str.back() == '\r')
|
||||
str.resize(str.size() - 1);
|
||||
return true;
|
||||
}
|
||||
str.push_back((char)(uint8_t)r);
|
||||
ret = true;
|
||||
} while (r != -1);
|
||||
|
||||
if(!str.empty() && str.back() == '\r') str.resize(str.size()-1);
|
||||
|
||||
if (!str.empty() && str.back() == '\r')
|
||||
str.resize(str.size() - 1);
|
||||
return ret;
|
||||
}
|
||||
void TextReader::ReadAllLines(std::vector<std::string> &lines) {
|
||||
@@ -84,12 +88,11 @@ void TextReader::ReadAllLines(std::vector<std::string> &lines) {
|
||||
r = ReadChar();
|
||||
if (r == -1)
|
||||
break;
|
||||
|
||||
if (r == '\n') {
|
||||
|
||||
if(!builder.empty() && builder.back() == '\r')
|
||||
builder.resize(builder.size()-1);
|
||||
|
||||
if (r == '\n') {
|
||||
|
||||
if (!builder.empty() && builder.back() == '\r')
|
||||
builder.resize(builder.size() - 1);
|
||||
|
||||
lines.push_back(builder);
|
||||
builder.clear();
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
/*
|
||||
TessesFramework a library to make C++ easier for me, used in CrossLang:
|
||||
https://git.tesses.org/tesses50/crosslang Copyright (C) 2026 Mike Nolan
|
||||
https://git.tesses.org/tesses50/crosslang
|
||||
|
||||
Copyright (C) 2026 Mike Nolan
|
||||
SPDX-License-Identifier: GPL-3.0-or-later WITH TessesFramework-Exception-1.0
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
/*
|
||||
TessesFramework a library to make C++ easier for me, used in CrossLang:
|
||||
https://git.tesses.org/tesses50/crosslang Copyright (C) 2026 Mike Nolan
|
||||
https://git.tesses.org/tesses50/crosslang
|
||||
|
||||
Copyright (C) 2026 Mike Nolan
|
||||
SPDX-License-Identifier: GPL-3.0-or-later WITH TessesFramework-Exception-1.0
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@@ -51,10 +54,6 @@ Mutex::Mutex() {
|
||||
auto md = this->data.AllocField<MutexHiddenFieldData>();
|
||||
#if defined(_WIN32)
|
||||
md->mtx = CreateMutex(NULL, false, NULL);
|
||||
#elif defined(GEKKO)
|
||||
md->mtx = LWP_MUTEX_NULL;
|
||||
LWP_MutexInit(&md->mtx, true);
|
||||
|
||||
#else
|
||||
pthread_mutexattr_init(&md->attr);
|
||||
pthread_mutexattr_settype(&md->attr, PTHREAD_MUTEX_RECURSIVE);
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
/*
|
||||
TessesFramework a library to make C++ easier for me, used in CrossLang:
|
||||
https://git.tesses.org/tesses50/crosslang Copyright (C) 2026 Mike Nolan
|
||||
https://git.tesses.org/tesses50/crosslang
|
||||
|
||||
Copyright (C) 2026 Mike Nolan
|
||||
SPDX-License-Identifier: GPL-3.0-or-later WITH TessesFramework-Exception-1.0
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@@ -21,12 +24,18 @@
|
||||
#include "TessesFramework/Threading/Mutex.hpp"
|
||||
#include <iostream>
|
||||
#include <memory>
|
||||
#if defined(__SWITCH__)
|
||||
#if defined(_WIN32)
|
||||
#include <windows.h>
|
||||
#undef min
|
||||
#elif defined(__SWITCH__)
|
||||
extern "C" {
|
||||
#include <pthread.h>
|
||||
#include <switch.h>
|
||||
}
|
||||
#else
|
||||
#include <pthread.h>
|
||||
#endif
|
||||
|
||||
namespace Tesses::Framework::Threading {
|
||||
|
||||
#if defined(TESSESFRAMEWORK_ENABLE_THREADING)
|
||||
@@ -61,7 +70,6 @@ class NeedToBeJoinnedThread {
|
||||
hasExited = false;
|
||||
|
||||
pthread_create(&thrd, NULL, this->cb, static_cast<void *>(this));
|
||||
|
||||
}
|
||||
std::atomic<bool> joinned;
|
||||
std::atomic<bool> joinning;
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
/*
|
||||
TessesFramework a library to make C++ easier for me, used in CrossLang:
|
||||
https://git.tesses.org/tesses50/crosslang Copyright (C) 2026 Mike Nolan
|
||||
https://git.tesses.org/tesses50/crosslang
|
||||
|
||||
Copyright (C) 2026 Mike Nolan
|
||||
SPDX-License-Identifier: GPL-3.0-or-later WITH TessesFramework-Exception-1.0
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
|
||||
+4
-1
@@ -1,6 +1,9 @@
|
||||
/*
|
||||
TessesFramework a library to make C++ easier for me, used in CrossLang:
|
||||
https://git.tesses.org/tesses50/crosslang Copyright (C) 2026 Mike Nolan
|
||||
https://git.tesses.org/tesses50/crosslang
|
||||
|
||||
Copyright (C) 2026 Mike Nolan
|
||||
SPDX-License-Identifier: GPL-3.0-or-later WITH TessesFramework-Exception-1.0
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
|
||||
Reference in New Issue
Block a user