Compare commits

..

No commits in common. "38e1c3f8b760d3e22cc2e8f8fdfb5a8816308740" and "d8adf47d10b2da72ecd541490a4600efb0520c6c" have entirely different histories.

6 changed files with 0 additions and 1110 deletions

View File

@ -1,462 +0,0 @@
#include "Miscellaneous/Console.h"
#include <cstdio>
#if PLATFORM_WINDOWS
# undef TEXT
# include <windows.h>
#elif PLATFORM_LINUX
# include <sys/ioctl.h>
# include <unistd.h>
#endif
NAMESPACE_REDCRAFT_BEGIN
NAMESPACE_MODULE_BEGIN(Redcraft)
NAMESPACE_MODULE_BEGIN(Utility)
#if PLATFORM_WINDOWS
NODISCARD bool InitANSIConsole()
{
static bool bResult = []
{
HANDLE Console = GetStdHandle(STD_OUTPUT_HANDLE);
if (Console == INVALID_HANDLE_VALUE) return false;
DWORD ConsoleMode = 0;
if (!GetConsoleMode(Console, &ConsoleMode)) return false;
ConsoleMode |= ENABLE_VIRTUAL_TERMINAL_PROCESSING;
if (!SetConsoleMode(Console, ConsoleMode)) return false;
return true;
}
();
return bResult;
}
#endif
EColor GForegroundColor = EColor::Default;
EColor GBackgroundColor = EColor::Default;
EColor GetForegroundColor()
{
# if PLATFORM_WINDOWS
{
if (InitANSIConsole()) return GForegroundColor;
const HANDLE Console = GetStdHandle(STD_OUTPUT_HANDLE);
if (Console == INVALID_HANDLE_VALUE) return EColor::Default;
CONSOLE_SCREEN_BUFFER_INFO ConsoleInfo;
if (!GetConsoleScreenBufferInfo(Console, &ConsoleInfo)) return EColor::Default;
const WORD Color = ConsoleInfo.wAttributes;
EColor Result = EColor::Black;
if (Color & FOREGROUND_RED) Result |= EColor::Red;
if (Color & FOREGROUND_GREEN) Result |= EColor::Green;
if (Color & FOREGROUND_BLUE) Result |= EColor::Blue;
if (Color & FOREGROUND_INTENSITY) Result |= EColor::Intensity;
return Result;
}
# endif
return GForegroundColor;
}
EColor GetBackgroundColor()
{
# if PLATFORM_WINDOWS
{
if (InitANSIConsole()) return GBackgroundColor;
const HANDLE Console = GetStdHandle(STD_OUTPUT_HANDLE);
if (Console == INVALID_HANDLE_VALUE) return EColor::Default;
CONSOLE_SCREEN_BUFFER_INFO ConsoleInfo;
if (!GetConsoleScreenBufferInfo(Console, &ConsoleInfo)) return EColor::Default;
const WORD Color = ConsoleInfo.wAttributes;
EColor Result = EColor::Black;
if (Color & BACKGROUND_RED) Result |= EColor::Red;
if (Color & BACKGROUND_GREEN) Result |= EColor::Green;
if (Color & BACKGROUND_BLUE) Result |= EColor::Blue;
if (Color & BACKGROUND_INTENSITY) Result |= EColor::Intensity;
return Result;
}
# endif
return GBackgroundColor;
}
EColor SetForegroundColor(EColor InColor)
{
if (IsOutputRedirected()) return GetForegroundColor();
# if PLATFORM_WINDOWS
{
if (!InitANSIConsole())
{
const HANDLE Console = GetStdHandle(STD_OUTPUT_HANDLE);
if (Console == INVALID_HANDLE_VALUE) return GetForegroundColor();
CONSOLE_SCREEN_BUFFER_INFO ConsoleInfo;
if (!GetConsoleScreenBufferInfo(Console, &ConsoleInfo)) return GetForegroundColor();
WORD Color = ConsoleInfo.wAttributes & ~(FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY);
if (InColor == EColor::Default) InColor = EColor::White;
if (!!(InColor & EColor::Red)) Color |= FOREGROUND_RED;
if (!!(InColor & EColor::Green)) Color |= FOREGROUND_GREEN;
if (!!(InColor & EColor::Blue)) Color |= FOREGROUND_BLUE;
if (!!(InColor & EColor::Intensity)) Color |= FOREGROUND_INTENSITY;
if (!SetConsoleTextAttribute(Console, Color)) return GetForegroundColor();
return InColor;
}
}
# endif
# if PLATFORM_WINDOWS || PLATFORM_LINUX
{
int Result;
switch (InColor)
{
case EColor::Black: Result = std::fputs("\033[30m", stdout); break;
case EColor::Red: Result = std::fputs("\033[31m", stdout); break;
case EColor::Green: Result = std::fputs("\033[32m", stdout); break;
case EColor::Yellow: Result = std::fputs("\033[33m", stdout); break;
case EColor::Blue: Result = std::fputs("\033[34m", stdout); break;
case EColor::Magenta: Result = std::fputs("\033[35m", stdout); break;
case EColor::Cyan: Result = std::fputs("\033[36m", stdout); break;
case EColor::White: Result = std::fputs("\033[37m", stdout); break;
case EColor::BrightBlack: Result = std::fputs("\033[90m", stdout); break;
case EColor::BrightRed: Result = std::fputs("\033[91m", stdout); break;
case EColor::BrightGreen: Result = std::fputs("\033[92m", stdout); break;
case EColor::BrightYellow: Result = std::fputs("\033[93m", stdout); break;
case EColor::BrightBlue: Result = std::fputs("\033[94m", stdout); break;
case EColor::BrightMagenta: Result = std::fputs("\033[95m", stdout); break;
case EColor::BrightCyan: Result = std::fputs("\033[96m", stdout); break;
case EColor::BrightWhite: Result = std::fputs("\033[97m", stdout); break;
default: Result = std::fputs("\033[39m", stdout); break;
}
if (Result == EOF) return GetForegroundColor();
return GForegroundColor = InColor;
}
# endif
return GetForegroundColor();
}
EColor SetBackgroundColor(EColor InColor)
{
if (IsOutputRedirected()) return GetBackgroundColor();
# if PLATFORM_WINDOWS
{
if (!InitANSIConsole())
{
const HANDLE Console = GetStdHandle(STD_OUTPUT_HANDLE);
if (Console == INVALID_HANDLE_VALUE) return GetBackgroundColor();
CONSOLE_SCREEN_BUFFER_INFO ConsoleInfo;
if (!GetConsoleScreenBufferInfo(Console, &ConsoleInfo)) return GetBackgroundColor();
WORD Color = ConsoleInfo.wAttributes & ~(BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE | BACKGROUND_INTENSITY);
if (InColor == EColor::Default) InColor = EColor::Black;
if (!!(InColor & EColor::Red)) Color |= BACKGROUND_RED;
if (!!(InColor & EColor::Green)) Color |= BACKGROUND_GREEN;
if (!!(InColor & EColor::Blue)) Color |= BACKGROUND_BLUE;
if (!!(InColor & EColor::Intensity)) Color |= BACKGROUND_INTENSITY;
if (!SetConsoleTextAttribute(Console, Color)) return GetBackgroundColor();
return InColor;
}
}
# endif
# if PLATFORM_WINDOWS || PLATFORM_LINUX
{
int Result;
switch (InColor)
{
case EColor::Black: Result = std::fputs("\033[40m", stdout); break;
case EColor::Red: Result = std::fputs("\033[41m", stdout); break;
case EColor::Green: Result = std::fputs("\033[42m", stdout); break;
case EColor::Yellow: Result = std::fputs("\033[43m", stdout); break;
case EColor::Blue: Result = std::fputs("\033[44m", stdout); break;
case EColor::Magenta: Result = std::fputs("\033[45m", stdout); break;
case EColor::Cyan: Result = std::fputs("\033[46m", stdout); break;
case EColor::White: Result = std::fputs("\033[47m", stdout); break;
case EColor::BrightBlack: Result = std::fputs("\033[100m", stdout); break;
case EColor::BrightRed: Result = std::fputs("\033[101m", stdout); break;
case EColor::BrightGreen: Result = std::fputs("\033[102m", stdout); break;
case EColor::BrightYellow: Result = std::fputs("\033[103m", stdout); break;
case EColor::BrightBlue: Result = std::fputs("\033[104m", stdout); break;
case EColor::BrightMagenta: Result = std::fputs("\033[105m", stdout); break;
case EColor::BrightCyan: Result = std::fputs("\033[106m", stdout); break;
case EColor::BrightWhite: Result = std::fputs("\033[107m", stdout); break;
default: Result = std::fputs("\033[49m", stdout); break;
}
if (Result == EOF) return GetBackgroundColor();
return GBackgroundColor = InColor;
}
# endif
return GetBackgroundColor();
}
uint GetWindowWidth()
{
# if PLATFORM_WINDOWS
{
const HANDLE Console = GetStdHandle(STD_OUTPUT_HANDLE);
if (Console == INVALID_HANDLE_VALUE) return static_cast<uint>(-1);
CONSOLE_SCREEN_BUFFER_INFO ConsoleInfo;
if (!GetConsoleScreenBufferInfo(Console, &ConsoleInfo)) return static_cast<uint>(-1);
return static_cast<uint>(ConsoleInfo.srWindow.Right - ConsoleInfo.srWindow.Left + 1);
}
# elif PLATFORM_LINUX
{
winsize Size;
if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &Size) == -1) return static_cast<uint>(-1);
return static_cast<uint>(Size.ws_col);
}
# endif
return static_cast<uint>(-1);
}
uint GetWindowHeight()
{
# if PLATFORM_WINDOWS
{
const HANDLE Console = GetStdHandle(STD_OUTPUT_HANDLE);
if (Console == INVALID_HANDLE_VALUE) return static_cast<uint>(-1);
CONSOLE_SCREEN_BUFFER_INFO ConsoleInfo;
if (!GetConsoleScreenBufferInfo(Console, &ConsoleInfo)) return static_cast<uint>(-1);
return static_cast<uint>(ConsoleInfo.srWindow.Bottom - ConsoleInfo.srWindow.Top + 1);
}
# elif PLATFORM_LINUX
{
winsize Size;
if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &Size) == -1) return static_cast<uint>(-1);
return static_cast<uint>(Size.ws_row);
}
# endif
return static_cast<uint>(-1);
}
bool IsInputRedirected()
{
# if PLATFORM_WINDOWS
{
const HANDLE StandardInput = GetStdHandle(STD_INPUT_HANDLE);
if (StandardInput == INVALID_HANDLE_VALUE) return false;
DWORD FileType = GetFileType(StandardInput);
return FileType != FILE_TYPE_CHAR;
}
# elif PLATFORM_LINUX
{
return isatty(fileno(stdin)) == 0;
}
# endif
return false;
}
bool IsOutputRedirected()
{
# if PLATFORM_WINDOWS
{
const HANDLE StandardOutput = GetStdHandle(STD_OUTPUT_HANDLE);
if (StandardOutput == INVALID_HANDLE_VALUE) return false;
DWORD FileType = GetFileType(StandardOutput);
return FileType != FILE_TYPE_CHAR;
}
# elif PLATFORM_LINUX
{
return isatty(fileno(stdout)) == 0;
}
# endif
return false;
}
bool IsErrorRedirected()
{
# if PLATFORM_WINDOWS
{
const HANDLE StandardError = GetStdHandle(STD_ERROR_HANDLE);
if (StandardError == INVALID_HANDLE_VALUE) return false;
DWORD FileType = GetFileType(StandardError);
return FileType != FILE_TYPE_CHAR;
}
# elif PLATFORM_LINUX
{
return isatty(fileno(stderr)) == 0;
}
# endif
return false;
}
void Clear()
{
if (IsOutputRedirected()) return;
# if PLATFORM_WINDOWS
{
std::system("cls");
}
# elif PLATFORM_LINUX
{
Ignore = std::fputs("\033[2J\033[1;1H", stdout);
}
# endif
}
char Input(bool bEcho)
{
if (bEcho || IsOutputRedirected())
{
const int Result = std::getchar();
if (Result == EOF) return static_cast<char>(-1);
return static_cast<char>(Result);
}
# if PLATFORM_WINDOWS
{
const HANDLE Console = GetStdHandle(STD_INPUT_HANDLE);
if (Console == INVALID_HANDLE_VALUE) return static_cast<char>(-1);
DWORD ConsoleMode = 0;
GetConsoleMode(Console, &ConsoleMode);
SetConsoleMode(Console, ConsoleMode & ~ENABLE_ECHO_INPUT);
const char Result = Input();
SetConsoleMode(Console, ConsoleMode);
return Result;
}
# elif PLATFORM_LINUX
{ }
# endif
return static_cast<char>(-1);
}
FString InputLn(bool bEcho)
{
if (bEcho || IsOutputRedirected())
{
FString Result;
while (true)
{
const int Char = std::getchar();
if (Char == EOF || Char == '\n') break;
Result.PushBack(static_cast<char>(Char));
}
return Result;
}
# if PLATFORM_WINDOWS
{
const HANDLE Console = GetStdHandle(STD_INPUT_HANDLE);
if (Console == INVALID_HANDLE_VALUE) return "";
DWORD ConsoleMode = 0;
GetConsoleMode(Console, &ConsoleMode);
SetConsoleMode(Console, ConsoleMode & ~ENABLE_ECHO_INPUT);
const FString Result = InputLn();
SetConsoleMode(Console, ConsoleMode);
return Result;
}
# elif PLATFORM_LINUX
{ }
# endif
return "";
}
bool Print(char Char)
{
return std::putchar(Char) != EOF;
}
bool Error(char Char)
{
return std::fputc(Char, stderr) != EOF;
}
NAMESPACE_MODULE_END(Utility)
NAMESPACE_MODULE_END(Redcraft)
NAMESPACE_REDCRAFT_END

View File

@ -1,295 +0,0 @@
#include <Miscellaneous/FileSystem.h>
#include "Numerics/Bit.h"
#include "Templates/ScopeHelper.h"
#include "Containers/StaticArray.h"
#include <cstdio>
#pragma warning(push)
#pragma warning(disable: 4996)
NAMESPACE_REDCRAFT_BEGIN
NAMESPACE_MODULE_BEGIN(Redcraft)
NAMESPACE_MODULE_BEGIN(Utility)
NAMESPACE_BEGIN(FileSystem)
bool LoadFileToArray(TArray<uint8>& Result, FStringView Path)
{
FILE* File = std::fopen(*Path, "rb");
if (File == nullptr) return false;
auto FileGuard = TScopeCallback([=] { Ignore = std::fclose(File); });
if (std::fseek(File, 0, SEEK_END) != 0) return false;
const long Length = std::ftell(File);
if (Length == -1) return false;
if (std::fseek(File, 0, SEEK_SET) != 0) return false;
Result.SetNum(Length);
if (std::fread(Result.GetData(), sizeof(uint8), Length, File) != static_cast<size_t>(Length)) return false;
FileGuard.Release();
if (std::fclose(File) != 0) return false;
return true;
}
bool SaveArrayToFile(TArrayView<const uint8> Data, FStringView Path)
{
FILE* File = std::fopen(*Path, "wb");
if (File == nullptr) return false;
auto FileGuard = TScopeCallback([=] { Ignore = std::fclose(File); });
if (std::fwrite(Data.GetData(), sizeof(uint8), Data.Num(), File) != Data.Num()) return false;
FileGuard.Release();
if (std::fclose(File) != 0) return false;
return true;
}
template <CCharType T>
bool LoadFileToString(TString<T>& Result, FStringView Path, FileSystem::EEncoding Encoding /* = FileSystem::EEncoding::Default */, bool bVerify /* = false */)
{
FILE* File = std::fopen(*Path, "rb");
if (File == nullptr) return false;
auto FileGuard = TScopeCallback([=] { Ignore = std::fclose(File); });
if (std::fseek(File, 0, SEEK_END) != 0) return false;
long Length = std::ftell(File);
if (Length == -1) return false;
if (std::fseek(File, 0, SEEK_SET) != 0) return false;
TStaticArray<uint8, 4> Buffer = { 0xAA, 0xAA, 0xAA, 0xAA };
Ignore = std::fread(Buffer.GetData(), sizeof(uint8), Buffer.Num(), File);
// Auto-detect the encoding if it is not specified.
if (Encoding == FileSystem::EEncoding::Default)
{
// Check if the file is a UTF-32 encoded file.
if (Buffer[0] == 0x00 && Buffer[1] == 0x00 && Buffer[2] == 0xFE && Buffer[3] == 0xFF) Encoding = FileSystem::EEncoding::UTF32BE;
else if (Buffer[0] == 0xFF && Buffer[1] == 0xFE && Buffer[2] == 0x00 && Buffer[3] == 0x00) Encoding = FileSystem::EEncoding::UTF32LE;
// Check if the file is a UTF-16 encoded file.
else if (Buffer[0] == 0xFF && Buffer[1] == 0xFE) Encoding = FileSystem::EEncoding::UTF16LE;
else if (Buffer[0] == 0xFE && Buffer[1] == 0xFF) Encoding = FileSystem::EEncoding::UTF16BE;
// Check if the file is a UTF-8 encoded file.
else if (Buffer[0] == 0xEF && Buffer[1] == 0xBB && Buffer[2] == 0xBF) Encoding = FileSystem::EEncoding::UTF8;
// Check if the file is a wide character encoded file.
else if (Buffer[0] == 0x00 || Buffer[1] == 0x00 || Buffer[2] == 0x00 || Buffer[3] == 0x00) Encoding = FileSystem::EEncoding::Wide;
// Check if the file is a narrow character encoded file.
else Encoding = FileSystem::EEncoding::Narrow;
}
// Jump to the BOM character if the file is a UTF-8, UTF-16 or UTF-32 encoded file.
switch (Encoding)
{
case FileSystem::EEncoding::Narrow:
case FileSystem::EEncoding::Wide: { Length -= 0; if (std::fseek(File, 0, SEEK_SET) != 0) return false; } break;
case FileSystem::EEncoding::UTF8: if (Buffer[0] == 0xEF && Buffer[1] == 0xBB && Buffer[2] == 0xBF) { Length -= 3; if (std::fseek(File, 3, SEEK_SET) != 0) return false; } break;
case FileSystem::EEncoding::UTF16BE: if (Buffer[0] == 0xFE && Buffer[1] == 0xFF) { Length -= 2; if (std::fseek(File, 2, SEEK_SET) != 0) return false; } break;
case FileSystem::EEncoding::UTF16LE: if (Buffer[0] == 0xFF && Buffer[1] == 0xFE) { Length -= 2; if (std::fseek(File, 2, SEEK_SET) != 0) return false; } break;
case FileSystem::EEncoding::UTF32BE: if (Buffer[0] == 0x00 && Buffer[1] == 0x00 && Buffer[2] == 0xFE && Buffer[3] == 0xFF) { Length -= 4; if (std::fseek(File, 4, SEEK_SET) != 0) return false; } break;
case FileSystem::EEncoding::UTF32LE: if (Buffer[0] == 0xFF && Buffer[1] == 0xFE && Buffer[2] == 0x00 && Buffer[3] == 0x00) { Length -= 4; if (std::fseek(File, 4, SEEK_SET) != 0) return false; } break;
default: check_no_entry();
}
check(Math::EEndian::Native == Math::EEndian::Big || Math::EEndian::Native == Math::EEndian::Little);
const bool bByteSwap =
Math::EEndian::Native == Math::EEndian::Big ? Encoding == FileSystem::EEncoding::UTF16LE || Encoding == FileSystem::EEncoding::UTF32LE :
Math::EEndian::Native == Math::EEndian::Little ? Encoding == FileSystem::EEncoding::UTF16BE || Encoding == FileSystem::EEncoding::UTF32BE : false;
const auto LoadImpl = [File, Length, bByteSwap]<typename U>(TString<U>& String) -> bool
{
if (Length % sizeof(U) != 0) return false;
String.Reserve(Length / sizeof(U));
while (true)
{
U Char;
const size_t ReadNum = std::fread(&Char, 1, sizeof(U), File);
if (ReadNum == 0) break;
if (ReadNum != sizeof(U)) return false;
if constexpr (sizeof(U) > 1) if (bByteSwap) Char = Math::ByteSwap(Char);
# if PLATFORM_WINDOWS
{
if (!String.IsEmpty() && String.Back() == LITERAL(U, '\r') && Char == LITERAL(U, '\n'))
{
String.PopBack();
}
}
# endif
String.PushBack(Char);
}
return true;
};
bool bCompatible = false;
if constexpr (CSameAs<T, char>) bCompatible |= Encoding == FileSystem::EEncoding::Narrow;
else if constexpr (CSameAs<T, wchar>) bCompatible |= Encoding == FileSystem::EEncoding::Wide;
else if constexpr (CSameAs<T, u8char>) bCompatible |= Encoding == FileSystem::EEncoding::UTF8;
else if constexpr (CSameAs<T, u16char>) bCompatible |= Encoding == FileSystem::EEncoding::UTF16BE || Encoding == FileSystem::EEncoding::UTF16LE;
else if constexpr (CSameAs<T, u32char>) bCompatible |= Encoding == FileSystem::EEncoding::UTF32BE || Encoding == FileSystem::EEncoding::UTF32LE;
else static_assert(sizeof(T) == -1, "Unsupported character type");
if (!bCompatible || bVerify)
{
switch (Encoding)
{
case FileSystem::EEncoding::Narrow: { FString Temp; if (!LoadImpl(Temp)) return false; if (!Result.DecodeFrom(Temp)) return false; break; }
case FileSystem::EEncoding::Wide: { FWString Temp; if (!LoadImpl(Temp)) return false; if (!Result.DecodeFrom(Temp)) return false; break; }
case FileSystem::EEncoding::UTF8: { FU8String Temp; if (!LoadImpl(Temp)) return false; if (!Result.DecodeFrom(Temp)) return false; break; }
case FileSystem::EEncoding::UTF16BE:
case FileSystem::EEncoding::UTF16LE: { FU16String Temp; if (!LoadImpl(Temp)) return false; if (!Result.DecodeFrom(Temp)) return false; break; }
case FileSystem::EEncoding::UTF32BE:
case FileSystem::EEncoding::UTF32LE: { FU32String Temp; if (!LoadImpl(Temp)) return false; if (!Result.DecodeFrom(Temp)) return false; break; }
default: check_no_entry();
}
}
else if (!LoadImpl(Result)) return false;
FileGuard.Release();
if (std::fclose(File) != 0) return false;
return true;
}
template <CCharType T>
bool SaveStringToFile(TStringView<T> String, FStringView Path, FileSystem::EEncoding Encoding /* = FileSystem::EEncoding::Default */, bool bWithBOM /* = true */)
{
bool bCompatible = Encoding == FileSystem::EEncoding::Default;
if constexpr (CSameAs<T, char>) bCompatible |= Encoding == FileSystem::EEncoding::Narrow;
else if constexpr (CSameAs<T, wchar>) bCompatible |= Encoding == FileSystem::EEncoding::Wide;
else if constexpr (CSameAs<T, u8char>) bCompatible |= Encoding == FileSystem::EEncoding::UTF8;
else if constexpr (CSameAs<T, u16char>) bCompatible |= Encoding == FileSystem::EEncoding::UTF16BE || Encoding == FileSystem::EEncoding::UTF16LE;
else if constexpr (CSameAs<T, u32char>) bCompatible |= Encoding == FileSystem::EEncoding::UTF32BE || Encoding == FileSystem::EEncoding::UTF32LE;
else static_assert(sizeof(T) == -1, "Unsupported character type");
if (bCompatible)
{
FILE* File = std::fopen(*Path, "wb");
if (File == nullptr) return false;
auto FileGuard = TScopeCallback([=] { Ignore = std::fclose(File); });
if (bWithBOM)
{
if constexpr (CSameAs<T, u8char>)
{
if (std::fwrite(U8TEXT("\uFEFF"), 1, 3, File) != 3) return false;
}
else if constexpr (CSameAs<T, u16char>)
{
constexpr TStaticArray<uint8, 2> BufferBE = { 0xFE, 0xFF };
constexpr TStaticArray<uint8, 2> BufferLE = { 0xFF, 0xFE };
if (Encoding == FileSystem::EEncoding::UTF16BE) { if (std::fwrite(BufferBE.GetData(), 1, BufferBE.Num(), File) != BufferBE.Num()) return false; }
else if (Encoding == FileSystem::EEncoding::UTF16LE) { if (std::fwrite(BufferLE.GetData(), 1, BufferLE.Num(), File) != BufferLE.Num()) return false; }
else if (std::fwrite(U16TEXT("\uFEFF"), 1, sizeof(T), File) != sizeof(T)) return false;
}
else if constexpr (CSameAs<T, u32char>)
{
constexpr TStaticArray<uint8, 4> BufferBE = { 0x00, 0x00, 0xFE, 0xFF };
constexpr TStaticArray<uint8, 4> BufferLE = { 0xFF, 0xFE, 0x00, 0x00 };
if (Encoding == FileSystem::EEncoding::UTF32BE) { if (std::fwrite(BufferBE.GetData() , 1, BufferBE.Num(), File) != BufferBE.Num()) return false; }
else if (Encoding == FileSystem::EEncoding::UTF32LE) { if (std::fwrite(BufferLE.GetData() , 1, BufferLE.Num(), File) != BufferLE.Num()) return false; }
else if (std::fwrite(U32TEXT("\uFEFF"), 1, sizeof(T), File) != sizeof(T)) return false;
}
}
check(Math::EEndian::Native == Math::EEndian::Big || Math::EEndian::Native == Math::EEndian::Little);
const bool bByteSwap =
Math::EEndian::Native == Math::EEndian::Big ? Encoding == FileSystem::EEncoding::UTF16LE || Encoding == FileSystem::EEncoding::UTF32LE :
Math::EEndian::Native == Math::EEndian::Little ? Encoding == FileSystem::EEncoding::UTF16BE || Encoding == FileSystem::EEncoding::UTF32BE : false;
for (T Char : String)
{
# if PLATFORM_WINDOWS
{
if (Char == LITERAL(T, '\n'))
{
T Return = LITERAL(T, '\r');
if constexpr (sizeof(T) > 1) if (bByteSwap) Return = Math::ByteSwap(Return);
if (std::fwrite(&Return, 1, sizeof(T), File) != sizeof(T)) return false;
}
}
# endif
if constexpr (sizeof(T) > 1) if (bByteSwap) Char = Math::ByteSwap(Char);
if (std::fwrite(&Char, 1, sizeof(T), File) != sizeof(T)) return false;
}
FileGuard.Release();
if (std::fclose(File) != 0) return false;
return true;
}
switch (Encoding)
{
case FileSystem::EEncoding::Narrow: { FString Temp; if (!Temp.DecodeFrom(String)) return false; if (!FileSystem::SaveStringToFile(Temp, Path, FileSystem::EEncoding::Narrow, bWithBOM)) return false; break; }
case FileSystem::EEncoding::Wide: { FWString Temp; if (!Temp.DecodeFrom(String)) return false; if (!FileSystem::SaveStringToFile(Temp, Path, FileSystem::EEncoding::Wide, bWithBOM)) return false; break; }
case FileSystem::EEncoding::UTF8: { FU8String Temp; if (!Temp.DecodeFrom(String)) return false; if (!FileSystem::SaveStringToFile(Temp, Path, FileSystem::EEncoding::UTF8, bWithBOM)) return false; break; }
case FileSystem::EEncoding::UTF16BE: { FU16String Temp; if (!Temp.DecodeFrom(String)) return false; if (!FileSystem::SaveStringToFile(Temp, Path, FileSystem::EEncoding::UTF16BE, bWithBOM)) return false; break; }
case FileSystem::EEncoding::UTF16LE: { FU16String Temp; if (!Temp.DecodeFrom(String)) return false; if (!FileSystem::SaveStringToFile(Temp, Path, FileSystem::EEncoding::UTF16LE, bWithBOM)) return false; break; }
case FileSystem::EEncoding::UTF32BE: { FU32String Temp; if (!Temp.DecodeFrom(String)) return false; if (!FileSystem::SaveStringToFile(Temp, Path, FileSystem::EEncoding::UTF32BE, bWithBOM)) return false; break; }
case FileSystem::EEncoding::UTF32LE: { FU32String Temp; if (!Temp.DecodeFrom(String)) return false; if (!FileSystem::SaveStringToFile(Temp, Path, FileSystem::EEncoding::UTF32LE, bWithBOM)) return false; break; }
default: check_no_entry(); return false;
}
return true;
}
NAMESPACE_END(FileSystem)
NAMESPACE_MODULE_END(Utility)
NAMESPACE_MODULE_END(Redcraft)
NAMESPACE_REDCRAFT_END
#pragma warning(pop)

View File

@ -1,32 +0,0 @@
#pragma once
#include "CoreTypes.h"
#include "TypeTraits/TypeTraits.h"
NAMESPACE_REDCRAFT_BEGIN
NAMESPACE_MODULE_BEGIN(Redcraft)
NAMESPACE_MODULE_BEGIN(Utility)
#define ENABLE_ENUM_CLASS_BITWISE_OPERATIONS(Enum) \
NODISCARD FORCEINLINE constexpr Enum operator| (Enum LHS, Enum RHS) { return static_cast<Enum>(static_cast<TUnderlyingType<Enum>>(LHS) | static_cast<TUnderlyingType<Enum>>(RHS)); } \
NODISCARD FORCEINLINE constexpr Enum operator& (Enum LHS, Enum RHS) { return static_cast<Enum>(static_cast<TUnderlyingType<Enum>>(LHS) & static_cast<TUnderlyingType<Enum>>(RHS)); } \
NODISCARD FORCEINLINE constexpr Enum operator^ (Enum LHS, Enum RHS) { return static_cast<Enum>(static_cast<TUnderlyingType<Enum>>(LHS) ^ static_cast<TUnderlyingType<Enum>>(RHS)); } \
FORCEINLINE constexpr Enum& operator|=(Enum& LHS, Enum RHS) { LHS = LHS | RHS; return LHS; } \
FORCEINLINE constexpr Enum& operator&=(Enum& LHS, Enum RHS) { LHS = LHS & RHS; return LHS; } \
FORCEINLINE constexpr Enum& operator^=(Enum& LHS, Enum RHS) { LHS = LHS ^ RHS; return LHS; } \
NODISCARD FORCEINLINE constexpr bool operator! (Enum E ) { return !static_cast<TUnderlyingType<Enum>>(E); } \
NODISCARD FORCEINLINE constexpr Enum operator~ (Enum E ) { return static_cast<Enum>(~static_cast<TUnderlyingType<Enum>>(E)); }
#define FRIEND_ENUM_CLASS_BITWISE_OPERATIONS(Enum) \
friend constexpr Enum operator| (Enum , Enum); \
friend constexpr Enum operator& (Enum , Enum); \
friend constexpr Enum operator^ (Enum , Enum); \
friend constexpr Enum& operator|=(Enum&, Enum); \
friend constexpr Enum& operator&=(Enum&, Enum); \
friend constexpr Enum& operator^=(Enum&, Enum); \
friend constexpr bool operator! (Enum ); \
friend constexpr Enum operator~ (Enum );
NAMESPACE_MODULE_END(Utility)
NAMESPACE_MODULE_END(Redcraft)
NAMESPACE_REDCRAFT_END

View File

@ -1,217 +0,0 @@
#pragma once
#include "CoreTypes.h"
#include "TypeTraits/TypeTraits.h"
#include "Templates/Utility.h"
#include "Iterators/Utility.h"
#include "Strings/Formatting.h"
#include "Strings/StringView.h"
#include "Strings/String.h"
#include "Miscellaneous/BitwiseEnum.h"
NAMESPACE_REDCRAFT_BEGIN
NAMESPACE_MODULE_BEGIN(Redcraft)
NAMESPACE_MODULE_BEGIN(Utility)
/** An enumeration that defines the color of the console. */
enum class EColor : uint8
{
Default = 0xFF,
Black = 0b0000,
Red = 0b0001,
Green = 0b0010,
Blue = 0b0100,
Intensity = 0b1000,
Cyan = Green | Blue,
Magenta = Blue | Red,
Yellow = Red | Green,
White = Red | Green | Blue,
BrightBlack = Intensity | Black,
BrightRed = Intensity | Red,
BrightGreen = Intensity | Green,
BrightBlue = Intensity | Blue,
BrightYellow = Intensity | Yellow,
BrightMagenta = Intensity | Magenta,
BrightCyan = Intensity | Cyan,
BrightWhite = Intensity | White
};
ENABLE_ENUM_CLASS_BITWISE_OPERATIONS(EColor)
/** @return The color of the console. */
NODISCARD REDCRAFTUTILITY_API EColor GetForegroundColor();
NODISCARD REDCRAFTUTILITY_API EColor GetBackgroundColor();
/** Set the color of the console. Returns the color that was successfully set. */
REDCRAFTUTILITY_API EColor SetForegroundColor(EColor InColor);
REDCRAFTUTILITY_API EColor SetBackgroundColor(EColor InColor);
/** @return The size of the console window. */
NODISCARD REDCRAFTUTILITY_API uint GetWindowWidth();
NODISCARD REDCRAFTUTILITY_API uint GetWindowHeight();
/** @return true if the standard stream is redirected. */
NODISCARD REDCRAFTUTILITY_API bool IsInputRedirected();
NODISCARD REDCRAFTUTILITY_API bool IsOutputRedirected();
NODISCARD REDCRAFTUTILITY_API bool IsErrorRedirected();
/** Clear the console screen. */
REDCRAFTUTILITY_API void Clear();
/** @return The input character from the standard input. */
NODISCARD REDCRAFTUTILITY_API char Input(bool bEcho = true);
/** @return The input line from the standard input. */
NODISCARD REDCRAFTUTILITY_API FString InputLn(bool bEcho = true);
/** Print the character to the standard output. */
REDCRAFTUTILITY_API bool Print(char Char);
/** Print the formatted string to the standard output. */
template <CFormattable... Ts>
FORCEINLINE bool Print(FStringView Fmt, Ts&&... Args)
{
struct FStandardOutputIterator
{
FORCEINLINE constexpr FStandardOutputIterator& operator=(char Char)
{
bError |= !Print(Char);
return *this;
}
FORCEINLINE constexpr bool operator==(FDefaultSentinel) const { return bError; }
FORCEINLINE constexpr FStandardOutputIterator& operator*() { return *this; }
FORCEINLINE constexpr FStandardOutputIterator& operator++() { return *this; }
FORCEINLINE constexpr FStandardOutputIterator& operator++(int) { return *this; }
bool bError = false;
};
static_assert(COutputIterator<FStandardOutputIterator, char>);
FStandardOutputIterator Iter;
auto Range = Ranges::View(Iter, DefaultSentinel);
Iter = Algorithms::Format(Range, Fmt, Forward<Ts>(Args)...);
return Iter != DefaultSentinel;
}
/** Print the value to the standard output. */
template <CFormattable T>
FORCEINLINE bool Print(T&& Value)
{
if constexpr (CSameAs<TRemoveCVRef<T>, char>)
{
return Print(static_cast<char>(Value));
}
else if constexpr (CConvertibleTo<T, FStringView>)
{
return Print(static_cast<FStringView>(Value));
}
else return Print(TEXT("{0}"), Forward<T>(Value));
}
/** Print the newline character to the standard output. */
FORCEINLINE bool PrintLn()
{
return Print(TEXT("\n"));
}
/** Print the string to the standard output and append the newline character. */
template <CFormattable... Ts>
FORCEINLINE bool PrintLn(FStringView Fmt, Ts&&... Args)
{
return Print(Fmt, Forward<Ts>(Args)...) && Print(TEXT("\n"));
}
/** Print the value to the standard output and append the newline character. */
template <CFormattable T>
FORCEINLINE bool PrintLn(T&& Value)
{
return Print(Forward<T>(Value)) && Print(TEXT("\n"));
}
/** Print the character to the standard error. */
REDCRAFTUTILITY_API bool Error(char Char);
/** Print the formatted string to the standard error. */
template <CFormattable... Ts>
FORCEINLINE bool Error(FStringView Fmt, Ts&&... Args)
{
struct FStandardOutputIterator
{
FORCEINLINE constexpr FStandardOutputIterator& operator=(char Char)
{
bError |= !Error(Char);
return *this;
}
FORCEINLINE constexpr bool operator==(FDefaultSentinel) const { return bError; }
FORCEINLINE constexpr FStandardOutputIterator& operator*() { return *this; }
FORCEINLINE constexpr FStandardOutputIterator& operator++() { return *this; }
FORCEINLINE constexpr FStandardOutputIterator& operator++(int) { return *this; }
bool bError = false;
};
static_assert(COutputIterator<FStandardOutputIterator, char>);
FStandardOutputIterator Iter;
auto Range = Ranges::View(Iter, DefaultSentinel);
Iter = Algorithms::Format(Range, Fmt, Forward<Ts>(Args)...);
return Iter != DefaultSentinel;
}
/** Print the value to the standard error. */
template <CFormattable T>
FORCEINLINE bool Error(T&& Value)
{
if constexpr (CSameAs<TRemoveCVRef<T>, char>)
{
return Error(static_cast<char>(Value));
}
else if constexpr (CConvertibleTo<T, FStringView>)
{
return Error(static_cast<FStringView>(Value));
}
else return Error(TEXT("{0}"), Forward<T>(Value));
}
/** Print the newline character to the standard error. */
FORCEINLINE bool ErrorLn()
{
return Error(TEXT("\n"));
}
/** Print the string to the standard error and append the newline character. */
template <CFormattable... Ts>
FORCEINLINE bool ErrorLn(FStringView Fmt, Ts&&... Args)
{
return Error(Fmt, Forward<Ts>(Args)...) && Error(TEXT("\n"));
}
/** Print the value to the standard error and append the newline character. */
template <CFormattable T>
FORCEINLINE bool ErrorLn(T&& Value)
{
return Error(Forward<T>(Value)) && Error(TEXT("\n"));
}
NAMESPACE_MODULE_END(Utility)
NAMESPACE_MODULE_END(Redcraft)
NAMESPACE_REDCRAFT_END

View File

@ -1,99 +0,0 @@
#pragma once
#include "CoreTypes.h"
#include "TypeTraits/TypeTraits.h"
#include "Containers/Array.h"
#include "Strings/StringView.h"
#include "Strings/String.h"
NAMESPACE_REDCRAFT_BEGIN
NAMESPACE_MODULE_BEGIN(Redcraft)
NAMESPACE_MODULE_BEGIN(Utility)
NAMESPACE_BEGIN(FileSystem)
/** The encoding of the text file. */
enum class EEncoding : uint8
{
Default,
Narrow,
Wide,
UTF8,
UTF16BE,
UTF16LE,
UTF32BE,
UTF32LE,
};
/** Loads the file at the specified path into the byte array. */
REDCRAFTUTILITY_API bool LoadFileToArray(TArray<uint8>& Result, FStringView Path);
/** Saves the byte array to the file at the specified path. */
REDCRAFTUTILITY_API bool SaveArrayToFile(TArrayView<const uint8> Data, FStringView Path);
/**
* Loads the file at the specified path into the string.
*
* @param Result - The string to load the file into.
* @param Path - The path to the file to load.
* @param Encoding - The encoding of the file. The default value indicates automatic detection.
* @param bVerify - Whether to verify the character validity of the file.
*
* @return true if the file was successfully loaded, false otherwise.
*/
template <CCharType T>
bool LoadFileToString(TString<T>& Result, FStringView Path, FileSystem::EEncoding Encoding = FileSystem::EEncoding::Default, bool bVerify = false);
template REDCRAFTUTILITY_API bool LoadFileToString<char> (FString&, FStringView, FileSystem::EEncoding, bool);
template REDCRAFTUTILITY_API bool LoadFileToString<wchar> (FWString&, FStringView, FileSystem::EEncoding, bool);
template REDCRAFTUTILITY_API bool LoadFileToString<u8char> (FU8String&, FStringView, FileSystem::EEncoding, bool);
template REDCRAFTUTILITY_API bool LoadFileToString<u16char>(FU16String&, FStringView, FileSystem::EEncoding, bool);
template REDCRAFTUTILITY_API bool LoadFileToString<u32char>(FU32String&, FStringView, FileSystem::EEncoding, bool);
/**
* Saves the string to the file at the specified path.
*
* @param String - The string to save to the file.
* @param Path - The path to the file to save.
* @param Encoding - The encoding of the file. The default value indicates the same as the string.
* @param bWithBOM - Whether to write the BOM character at the beginning of the file. Not valid for narrow and wide encoding.
*
* @return true if the file was successfully saved, false otherwise.
*/
template <CCharType T>
bool SaveStringToFile(TStringView<T> String, FStringView Path, FileSystem::EEncoding Encoding = FileSystem::EEncoding::Default, bool bWithBOM = true);
template REDCRAFTUTILITY_API bool SaveStringToFile<char> (FStringView, FStringView, FileSystem::EEncoding, bool);
template REDCRAFTUTILITY_API bool SaveStringToFile<wchar> (FWStringView, FStringView, FileSystem::EEncoding, bool);
template REDCRAFTUTILITY_API bool SaveStringToFile<u8char> (FU8StringView, FStringView, FileSystem::EEncoding, bool);
template REDCRAFTUTILITY_API bool SaveStringToFile<u16char>(FU16StringView, FStringView, FileSystem::EEncoding, bool);
template REDCRAFTUTILITY_API bool SaveStringToFile<u32char>(FU32StringView, FStringView, FileSystem::EEncoding, bool);
/**
* Saves the string to the file at the specified path.
*
* @param String - The string to save to the file.
* @param Path - The path to the file to save.
* @param Encoding - The encoding of the file. The default value indicates the same as the string.
* @param bWithBOM - Whether to write the BOM character at the beginning of the file. Not valid for narrow and wide encoding.
*
* @return true if the file was successfully saved, false otherwise.
*/
template <typename T> requires (CConvertibleTo<T&&, FStringView> || CConvertibleTo<T&&, FWStringView>
|| CConvertibleTo<T&&, FU8StringView> || CConvertibleTo<T&&, FU16StringView> || CConvertibleTo<T&&, FU32StringView>)
bool SaveStringToFile(T&& String, FStringView Path, FileSystem::EEncoding Encoding = FileSystem::EEncoding::Default, bool bWithBOM = true)
{
if constexpr (CConvertibleTo<T&&, FStringView>) return SaveStringToFile(FStringView (Forward<T>(String)), Path, Encoding, bWithBOM);
else if constexpr (CConvertibleTo<T&&, FWStringView>) return SaveStringToFile(FWStringView (Forward<T>(String)), Path, Encoding, bWithBOM);
else if constexpr (CConvertibleTo<T&&, FU8StringView>) return SaveStringToFile(FU8StringView (Forward<T>(String)), Path, Encoding, bWithBOM);
else if constexpr (CConvertibleTo<T&&, FU16StringView>) return SaveStringToFile(FU16StringView(Forward<T>(String)), Path, Encoding, bWithBOM);
else if constexpr (CConvertibleTo<T&&, FU32StringView>) return SaveStringToFile(FU32StringView(Forward<T>(String)), Path, Encoding, bWithBOM);
return false;
}
NAMESPACE_END(FileSystem)
NAMESPACE_MODULE_END(Utility)
NAMESPACE_MODULE_END(Redcraft)
NAMESPACE_REDCRAFT_END

View File

@ -15,9 +15,6 @@
#include <charconv> #include <charconv>
#pragma warning(push)
#pragma warning(disable: 4244)
NAMESPACE_REDCRAFT_BEGIN NAMESPACE_REDCRAFT_BEGIN
NAMESPACE_MODULE_BEGIN(Redcraft) NAMESPACE_MODULE_BEGIN(Redcraft)
NAMESPACE_MODULE_BEGIN(Utility) NAMESPACE_MODULE_BEGIN(Utility)
@ -3179,5 +3176,3 @@ private:
NAMESPACE_MODULE_END(Utility) NAMESPACE_MODULE_END(Utility)
NAMESPACE_MODULE_END(Redcraft) NAMESPACE_MODULE_END(Redcraft)
NAMESPACE_REDCRAFT_END NAMESPACE_REDCRAFT_END
#pragma warning(pop)