summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--dev/kernel/src/FS/HeFS.cc82
-rw-r--r--dev/kernel/src/PEFCodeMgr.cc4
-rw-r--r--dev/kernel/src/UserProcessScheduler.cc4
-rw-r--r--tooling/mkfs.h8
-rw-r--r--tooling/mkfs.hefs.cc17
-rw-r--r--tooling/rang.h711
6 files changed, 411 insertions, 415 deletions
diff --git a/dev/kernel/src/FS/HeFS.cc b/dev/kernel/src/FS/HeFS.cc
index 89415ee5..0969d2a5 100644
--- a/dev/kernel/src/FS/HeFS.cc
+++ b/dev/kernel/src/FS/HeFS.cc
@@ -29,7 +29,8 @@ namespace Detail {
/// @note This function is used to traverse the RB-Tree of the filesystem.
/// @internal Internal filesystem use only.
STATIC ATTRIBUTE(unused) _Output Void
- hefsi_traverse_tree(HEFS_INDEX_NODE_DIRECTORY* dir, Lba& start);
+ hefsi_traverse_tree(HEFS_INDEX_NODE_DIRECTORY* dir, DriveTrait* mnt, const Lba& start_ind,
+ Lba& start, const BOOL alloc_in_mind = NO);
/// @brief Get the index node of a file or directory.
/// @param root The root node of the filesystem.
@@ -74,19 +75,52 @@ namespace Detail {
/// @param start The starting point of the traversal.
/// @note This function is used to traverse the RB-Tree of the filesystem.
/// @internal Internal filesystem use only.
- STATIC ATTRIBUTE(unused) _Output Void
- hefsi_traverse_tree(HEFS_INDEX_NODE_DIRECTORY* dir, Lba& start) {
- if (dir->fNext != 0) {
- start = dir->fNext;
- } else if (dir->fPrev != 0) {
- start = dir->fPrev;
- } else {
- if (dir->fParent != 0) {
- start = dir->fParent;
+ STATIC ATTRIBUTE(unused) Void
+ hefsi_traverse_tree(HEFS_INDEX_NODE_DIRECTORY* dir, DriveTrait* mnt, const Lba& ind_start,
+ Lba& start, const BOOL alloc_in_mind) {
+ if (!mnt || !dir) return;
+
+ BOOL check_is_good = NO;
+
+ while (YES) {
+ mnt->fPacket.fPacketLba = start;
+ mnt->fPacket.fPacketSize = sizeof(HEFS_INDEX_NODE_DIRECTORY);
+ mnt->fPacket.fPacketContent = dir;
+ mnt->fInput(mnt->fPacket);
+
+ if (dir->fNext != 0) {
+ if (check_is_good) break;
+
+ start = dir->fNext;
+
+ check_is_good = YES;
+ continue;
} else if (dir->fPrev != 0) {
- start = dir->fPrev;
+ if (check_is_good) break;
+
+ start = dir->fPrev;
+ check_is_good = YES;
+ continue;
} else {
- start += kHeFSINDStartOffset;
+ if (dir->fParent != 0) {
+ if (check_is_good) break;
+
+ start = dir->fParent;
+ check_is_good = YES;
+ continue;
+ } else if (dir->fPrev != 0) {
+ if (check_is_good) break;
+
+ start = dir->fPrev;
+ check_is_good = YES;
+ continue;
+ } else {
+ if (!alloc_in_mind) break;
+
+ if (start < 1) start = ind_start;
+
+ start += kHeFSINDStartOffset;
+ }
}
}
@@ -320,13 +354,13 @@ namespace Detail {
}
child += sizeof(HEFS_INDEX_NODE_DIRECTORY);
- if (child < root->fStartIND || child > root->fEndIND) break;
+ if (child > root->fEndIND) break;
}
dirent->fColor = kHeFSRed;
dirent->fChild = child;
- if (child > root->fEndIND) dirent->fChild = root->fEndIND;
+ if (child > root->fEndIND) dirent->fChild = root->fStartIND;
}
for (SizeT index = 0UL; index < (kHeFSSliceCount * 2); index += 2) {
@@ -358,7 +392,7 @@ namespace Detail {
return YES;
}
- hefsi_traverse_tree(tmpdir, start);
+ hefsi_traverse_tree(tmpdir, mnt, root->fStartIND, start, YES);
if (start > root->fEndIND || start == 0) break;
}
@@ -404,7 +438,7 @@ namespace Detail {
}
}
- hefsi_traverse_tree(dir, start);
+ hefsi_traverse_tree(dir, mnt, root->fStartIND, start);
if (start > root->fEndIND || start == 0) break;
}
}
@@ -493,7 +527,7 @@ namespace Detail {
}
}
- hefsi_traverse_tree(dir, start);
+ hefsi_traverse_tree(dir, mnt, root->fStartIND, start);
if (start > root->fEndIND || start == 0) break;
}
}
@@ -544,7 +578,7 @@ namespace Detail {
}
}
- hefsi_traverse_tree(dir, start);
+ hefsi_traverse_tree(dir, mnt, root->fStartIND, start);
if (start > root->fEndIND || start == 0) break;
}
@@ -632,7 +666,7 @@ namespace Detail {
if (dir_parent->fNext == start) {
hefsi_rotate_tree(start, mnt, YES);
- hefsi_traverse_tree(dir_parent, start);
+ hefsi_traverse_tree(dir_parent, mnt, root->fStartIND, start);
if (start > root->fEndIND || start == 0) break;
@@ -658,7 +692,7 @@ namespace Detail {
hefsi_rotate_tree(start, mnt, NO);
- hefsi_traverse_tree(dir, start);
+ hefsi_traverse_tree(dir, mnt, root->fStartIND, start);
if (start > root->fEndIND || start == 0) break;
}
@@ -750,7 +784,7 @@ _Output Bool HeFileSystemParser::Format(_Input _Output DriveTrait* drive, _Input
const SizeT dir_max = max_lba / 20; // 20% for directory metadata
const SizeT inode_max = max_lba / 10; // 10% for inodes
- root->fStartIND = drive->fLbaStart + kHeFSINDStartOffset;
+ root->fStartIND = drive->fLbaStart + kHeFSINDStartOffset + sizeof(HEFS_BOOT_NODE);
root->fEndIND = root->fStartIND + dir_max;
root->fStartIN = root->fEndIND + kHeFSINDStartOffset;
@@ -799,7 +833,7 @@ _Output Bool HeFileSystemParser::Format(_Input _Output DriveTrait* drive, _Input
return NO;
}
- const Utf8Char* kFileMap[kHeFSPreallocateCount] = {
+ const Utf8Char kFileMap[kHeFSPreallocateCount][kHeFSFileNameLen] = {
u8"/", u8"/boot", u8"/system", u8"/network", u8"/devices", u8"/media", u8"/vm",
};
@@ -847,7 +881,9 @@ _Output Bool HeFileSystemParser::CreateDirectory(_Input DriveTrait* drive, _Inpu
urt_copy_memory((VoidPtr) dir, name, urt_string_len(dir) + 1);
if (Detail::hefsi_allocate_index_node_directory(root, drive, name, flags)) {
- Detail::hefsi_balance_filesystem(root, drive);
+ // todo: make it smarter for high-throughput.
+ if (root->fINDCount > 1024) Detail::hefsi_balance_filesystem(root, drive);
+
mm_delete_heap((VoidPtr) root);
delete[] name;
return YES;
diff --git a/dev/kernel/src/PEFCodeMgr.cc b/dev/kernel/src/PEFCodeMgr.cc
index 40a0cff9..5da3a499 100644
--- a/dev/kernel/src/PEFCodeMgr.cc
+++ b/dev/kernel/src/PEFCodeMgr.cc
@@ -246,8 +246,8 @@ namespace Utils {
stacksym = ErrorOr<VoidPtr>{(VoidPtr) new UIntPtr(kSchedMaxStackSz)};
}
- if ((*(volatile UIntPtr*)stacksym.Leak().Leak()) > kSchedMaxStackSz) {
- *(volatile UIntPtr*)stacksym.Leak().Leak() = kSchedMaxStackSz;
+ if ((*(volatile UIntPtr*) stacksym.Leak().Leak()) > kSchedMaxStackSz) {
+ *(volatile UIntPtr*) stacksym.Leak().Leak() = kSchedMaxStackSz;
}
UserProcessScheduler::The().CurrentTeam().AsArray()[id].Kind = process_kind;
diff --git a/dev/kernel/src/UserProcessScheduler.cc b/dev/kernel/src/UserProcessScheduler.cc
index 5012e8a3..45a95b5b 100644
--- a/dev/kernel/src/UserProcessScheduler.cc
+++ b/dev/kernel/src/UserProcessScheduler.cc
@@ -490,8 +490,7 @@ SizeT UserProcessScheduler::Run() noexcept {
return 0UL;
}
- if (kCurrentlySwitching)
- return 0UL;
+ if (kCurrentlySwitching) return 0UL;
kCurrentlySwitching = Yes;
@@ -503,7 +502,6 @@ SizeT UserProcessScheduler::Run() noexcept {
//! Check if the process needs to be run.
if (UserProcessHelper::CanBeScheduled(process)) {
-
if (process.StackSize > kSchedMaxStackSz) {
kout << "The process: " << process.Name << ", has not a valid stack size! Crashing it...\r";
process.Crash();
diff --git a/tooling/mkfs.h b/tooling/mkfs.h
index 650261db..7180b179 100644
--- a/tooling/mkfs.h
+++ b/tooling/mkfs.h
@@ -6,9 +6,9 @@
#pragma once
+#include <tooling/rang.h>
#include <iostream>
#include <string>
-#include <tooling/rang.h>
/// @internal
namespace mkfs {
@@ -28,9 +28,9 @@ inline std::basic_string<CharType> get_option(const std::basic_string<CharType>&
}
inline auto console_out() -> std::ostream& {
- std::ostream& conout = std::cout;
- conout << rang::fg::red << "mkfs: " << rang::style::reset;
+ std::ostream& conout = std::cout;
+ conout << rang::fg::red << "mkfs: " << rang::style::reset;
- return conout;
+ return conout;
}
} // namespace mkfs \ No newline at end of file
diff --git a/tooling/mkfs.hefs.cc b/tooling/mkfs.hefs.cc
index d9928858..23772023 100644
--- a/tooling/mkfs.hefs.cc
+++ b/tooling/mkfs.hefs.cc
@@ -16,10 +16,8 @@ static size_t kSectorSize = 512;
int main(int argc, char** argv) {
if (argc < 2) {
- mkfs::console_out() <<
- "hefs: Usage: mkfs.hefs -L <label> -s <sector_size> -p <part_start> -e " <<
- "<part_end> -S <disk_size> -o <output_device>"
- << std::endl;
+ mkfs::console_out() << "hefs: Usage: mkfs.hefs -L <label> -s <sector_size> -p <part_start> -e "
+ << "<part_end> -S <disk_size> -o <output_device>" << std::endl;
return EXIT_FAILURE;
}
@@ -51,8 +49,8 @@ int main(int argc, char** argv) {
std::strtol(mkfs::get_option<char>(args, "-S").data(), nullptr, 10) * 1024 * 1024 * 1024;
if (kDiskSize == 0) {
- mkfs::console_out() << "hefs: Error: Unable to deduce future disk size for output_device: " << output_device
- << std::endl;
+ mkfs::console_out() << "hefs: Error: Unable to deduce future disk size for output_device: "
+ << output_device << std::endl;
return EXIT_FAILURE;
}
@@ -61,7 +59,7 @@ int main(int argc, char** argv) {
if (!filesystem.good()) {
mkfs::console_out() << "hefs: Info: Unable to open output_device: " << output_device
- << std::endl;
+ << std::endl;
return EXIT_FAILURE;
}
@@ -92,7 +90,7 @@ int main(int argc, char** argv) {
if (!filesystem.good()) {
mkfs::console_out() << "hefs: Error: Unable to write FS to output_device: " << output_device
- << std::endl;
+ << std::endl;
return EXIT_FAILURE;
}
@@ -101,8 +99,7 @@ int main(int argc, char** argv) {
filesystem.flush();
filesystem.close();
- mkfs::console_out() << "hefs: Info: Wrote FS to output_device: " << output_device
- << std::endl;
+ mkfs::console_out() << "hefs: Info: Wrote FS to output_device: " << output_device << std::endl;
return EXIT_SUCCESS;
} \ No newline at end of file
diff --git a/tooling/rang.h b/tooling/rang.h
index 204ab1dc..5d1c68ef 100644
--- a/tooling/rang.h
+++ b/tooling/rang.h
@@ -17,14 +17,14 @@
#elif defined(OS_WIN)
#if defined(_WIN32_WINNT) && (_WIN32_WINNT < 0x0600)
-#error \
- "Please include rang.hpp before any windows system headers or set _WIN32_WINNT at least to _WIN32_WINNT_VISTA"
+#error \
+ "Please include rang.hpp before any windows system headers or set _WIN32_WINNT at least to _WIN32_WINNT_VISTA"
#elif !defined(_WIN32_WINNT)
#define _WIN32_WINNT _WIN32_WINNT_VISTA
#endif
-#include <windows.h>
#include <io.h>
+#include <windows.h>
#include <memory>
// Only defined in windows 10 onwards, redefining in lower windows since it
@@ -49,448 +49,413 @@ namespace rang {
* Note that on Windows terminals bold style is same as fgB color.
*/
enum class style {
- reset = 0,
- bold = 1,
- dim = 2,
- italic = 3,
- underline = 4,
- blink = 5,
- rblink = 6,
- reversed = 7,
- conceal = 8,
- crossed = 9
+ reset = 0,
+ bold = 1,
+ dim = 2,
+ italic = 3,
+ underline = 4,
+ blink = 5,
+ rblink = 6,
+ reversed = 7,
+ conceal = 8,
+ crossed = 9
};
enum class fg {
- black = 30,
- red = 31,
- green = 32,
- yellow = 33,
- blue = 34,
- magenta = 35,
- cyan = 36,
- gray = 37,
- reset = 39
+ black = 30,
+ red = 31,
+ green = 32,
+ yellow = 33,
+ blue = 34,
+ magenta = 35,
+ cyan = 36,
+ gray = 37,
+ reset = 39
};
enum class bg {
- black = 40,
- red = 41,
- green = 42,
- yellow = 43,
- blue = 44,
- magenta = 45,
- cyan = 46,
- gray = 47,
- reset = 49
+ black = 40,
+ red = 41,
+ green = 42,
+ yellow = 43,
+ blue = 44,
+ magenta = 45,
+ cyan = 46,
+ gray = 47,
+ reset = 49
};
enum class fgB {
- black = 90,
- red = 91,
- green = 92,
- yellow = 93,
- blue = 94,
- magenta = 95,
- cyan = 96,
- gray = 97
+ black = 90,
+ red = 91,
+ green = 92,
+ yellow = 93,
+ blue = 94,
+ magenta = 95,
+ cyan = 96,
+ gray = 97
};
enum class bgB {
- black = 100,
- red = 101,
- green = 102,
- yellow = 103,
- blue = 104,
- magenta = 105,
- cyan = 106,
- gray = 107
+ black = 100,
+ red = 101,
+ green = 102,
+ yellow = 103,
+ blue = 104,
+ magenta = 105,
+ cyan = 106,
+ gray = 107
};
enum class control { // Behaviour of rang function calls
- Off = 0, // toggle off rang style/color calls
- Auto = 1, // (Default) autodect terminal and colorize if needed
- Force = 2 // force ansi color output to non terminal streams
+ Off = 0, // toggle off rang style/color calls
+ Auto = 1, // (Default) autodect terminal and colorize if needed
+ Force = 2 // force ansi color output to non terminal streams
};
// Use rang::setControlMode to set rang control mode
enum class winTerm { // Windows Terminal Mode
- Auto = 0, // (Default) automatically detects wheter Ansi or Native API
- Ansi = 1, // Force use Ansi API
- Native = 2 // Force use Native API
+ Auto = 0, // (Default) automatically detects wheter Ansi or Native API
+ Ansi = 1, // Force use Ansi API
+ Native = 2 // Force use Native API
};
// Use rang::setWinTermMode to explicitly set terminal API for Windows
// Calling rang::setWinTermMode have no effect on other OS
namespace rang_implementation {
- inline std::atomic<control> &controlMode() noexcept
- {
- static std::atomic<control> value(control::Auto);
- return value;
- }
+ inline std::atomic<control>& controlMode() noexcept {
+ static std::atomic<control> value(control::Auto);
+ return value;
+ }
- inline std::atomic<winTerm> &winTermMode() noexcept
- {
- static std::atomic<winTerm> termMode(winTerm::Auto);
- return termMode;
- }
+ inline std::atomic<winTerm>& winTermMode() noexcept {
+ static std::atomic<winTerm> termMode(winTerm::Auto);
+ return termMode;
+ }
- inline bool supportsColor() noexcept
- {
+ inline bool supportsColor() noexcept {
#if defined(OS_LINUX) || defined(OS_MAC)
- static const bool result = [] {
- const char *Terms[]
- = { "ansi", "color", "console", "cygwin", "gnome",
- "konsole", "kterm", "linux", "msys", "putty",
- "rxvt", "screen", "vt100", "xterm" };
-
- const char *env_p = std::getenv("TERM");
- if (env_p == nullptr) {
- return false;
- }
- return std::any_of(std::begin(Terms), std::end(Terms),
- [&](const char *term) {
- return std::strstr(env_p, term) != nullptr;
- });
- }();
+ static const bool result = [] {
+ const char* Terms[] = {"ansi", "color", "console", "cygwin", "gnome", "konsole", "kterm",
+ "linux", "msys", "putty", "rxvt", "screen", "vt100", "xterm"};
+
+ const char* env_p = std::getenv("TERM");
+ if (env_p == nullptr) {
+ return false;
+ }
+ return std::any_of(std::begin(Terms), std::end(Terms),
+ [&](const char* term) { return std::strstr(env_p, term) != nullptr; });
+ }();
#elif defined(OS_WIN)
- // All windows versions support colors through native console methods
- static constexpr bool result = true;
+ // All windows versions support colors through native console methods
+ static constexpr bool result = true;
#endif
- return result;
- }
+ return result;
+ }
#ifdef OS_WIN
-
- inline bool isMsysPty(int fd) noexcept
- {
- // Dynamic load for binary compability with old Windows
- const auto ptrGetFileInformationByHandleEx
- = reinterpret_cast<decltype(&GetFileInformationByHandleEx)>(
- GetProcAddress(GetModuleHandle(TEXT("kernel32.dll")),
- "GetFileInformationByHandleEx"));
- if (!ptrGetFileInformationByHandleEx) {
- return false;
- }
-
- HANDLE h = reinterpret_cast<HANDLE>(_get_osfhandle(fd));
- if (h == INVALID_HANDLE_VALUE) {
- return false;
- }
-
- // Check that it's a pipe:
- if (GetFileType(h) != FILE_TYPE_PIPE) {
- return false;
- }
-
- // POD type is binary compatible with FILE_NAME_INFO from WinBase.h
- // It have the same alignment and used to avoid UB in caller code
- struct MY_FILE_NAME_INFO {
- DWORD FileNameLength;
- WCHAR FileName[MAX_PATH];
- };
-
- auto pNameInfo = std::unique_ptr<MY_FILE_NAME_INFO>(
- new (std::nothrow) MY_FILE_NAME_INFO());
- if (!pNameInfo) {
- return false;
- }
-
- // Check pipe name is template of
- // {"cygwin-","msys-"}XXXXXXXXXXXXXXX-ptyX-XX
- if (!ptrGetFileInformationByHandleEx(h, FileNameInfo, pNameInfo.get(),
- sizeof(MY_FILE_NAME_INFO))) {
- return false;
- }
- std::wstring name(pNameInfo->FileName, pNameInfo->FileNameLength / sizeof(WCHAR));
- if ((name.find(L"msys-") == std::wstring::npos
- && name.find(L"cygwin-") == std::wstring::npos)
- || name.find(L"-pty") == std::wstring::npos) {
- return false;
- }
-
- return true;
+ inline bool isMsysPty(int fd) noexcept {
+ // Dynamic load for binary compability with old Windows
+ const auto ptrGetFileInformationByHandleEx =
+ reinterpret_cast<decltype(&GetFileInformationByHandleEx)>(
+ GetProcAddress(GetModuleHandle(TEXT("kernel32.dll")), "GetFileInformationByHandleEx"));
+ if (!ptrGetFileInformationByHandleEx) {
+ return false;
}
-#endif
+ HANDLE h = reinterpret_cast<HANDLE>(_get_osfhandle(fd));
+ if (h == INVALID_HANDLE_VALUE) {
+ return false;
+ }
- inline bool isTerminal(const std::streambuf *osbuf) noexcept
- {
- using std::cerr;
- using std::clog;
- using std::cout;
-#if defined(OS_LINUX) || defined(OS_MAC)
- if (osbuf == cout.rdbuf()) {
- static const bool cout_term = isatty(fileno(stdout)) != 0;
- return cout_term;
- } else if (osbuf == cerr.rdbuf() || osbuf == clog.rdbuf()) {
- static const bool cerr_term = isatty(fileno(stderr)) != 0;
- return cerr_term;
- }
-#elif defined(OS_WIN)
- if (osbuf == cout.rdbuf()) {
- static const bool cout_term
- = (_isatty(_fileno(stdout)) || isMsysPty(_fileno(stdout)));
- return cout_term;
- } else if (osbuf == cerr.rdbuf() || osbuf == clog.rdbuf()) {
- static const bool cerr_term
- = (_isatty(_fileno(stderr)) || isMsysPty(_fileno(stderr)));
- return cerr_term;
- }
-#endif
- return false;
+ // Check that it's a pipe:
+ if (GetFileType(h) != FILE_TYPE_PIPE) {
+ return false;
}
- template <typename T>
- using enableStd = typename std::enable_if<
- std::is_same<T, rang::style>::value || std::is_same<T, rang::fg>::value
- || std::is_same<T, rang::bg>::value || std::is_same<T, rang::fgB>::value
- || std::is_same<T, rang::bgB>::value,
- std::ostream &>::type;
+ // POD type is binary compatible with FILE_NAME_INFO from WinBase.h
+ // It have the same alignment and used to avoid UB in caller code
+ struct MY_FILE_NAME_INFO {
+ DWORD FileNameLength;
+ WCHAR FileName[MAX_PATH];
+ };
+ auto pNameInfo = std::unique_ptr<MY_FILE_NAME_INFO>(new (std::nothrow) MY_FILE_NAME_INFO());
+ if (!pNameInfo) {
+ return false;
+ }
-#ifdef OS_WIN
+ // Check pipe name is template of
+ // {"cygwin-","msys-"}XXXXXXXXXXXXXXX-ptyX-XX
+ if (!ptrGetFileInformationByHandleEx(h, FileNameInfo, pNameInfo.get(),
+ sizeof(MY_FILE_NAME_INFO))) {
+ return false;
+ }
+ std::wstring name(pNameInfo->FileName, pNameInfo->FileNameLength / sizeof(WCHAR));
+ if ((name.find(L"msys-") == std::wstring::npos &&
+ name.find(L"cygwin-") == std::wstring::npos) ||
+ name.find(L"-pty") == std::wstring::npos) {
+ return false;
+ }
- struct SGR { // Select Graphic Rendition parameters for Windows console
- BYTE fgColor; // foreground color (0-15) lower 3 rgb bits + intense bit
- BYTE bgColor; // background color (0-15) lower 3 rgb bits + intense bit
- BYTE bold; // emulated as FOREGROUND_INTENSITY bit
- BYTE underline; // emulated as BACKGROUND_INTENSITY bit
- BOOLEAN inverse; // swap foreground/bold & background/underline
- BOOLEAN conceal; // set foreground/bold to background/underline
- };
+ return true;
+ }
- enum class AttrColor : BYTE { // Color attributes for console screen buffer
- black = 0,
- red = 4,
- green = 2,
- yellow = 6,
- blue = 1,
- magenta = 5,
- cyan = 3,
- gray = 7
- };
+#endif
- inline HANDLE getConsoleHandle(const std::streambuf *osbuf) noexcept
- {
- if (osbuf == std::cout.rdbuf()) {
- static const HANDLE hStdout = GetStdHandle(STD_OUTPUT_HANDLE);
- return hStdout;
- } else if (osbuf == std::cerr.rdbuf() || osbuf == std::clog.rdbuf()) {
- static const HANDLE hStderr = GetStdHandle(STD_ERROR_HANDLE);
- return hStderr;
- }
- return INVALID_HANDLE_VALUE;
+ inline bool isTerminal(const std::streambuf* osbuf) noexcept {
+ using std::cerr;
+ using std::clog;
+ using std::cout;
+#if defined(OS_LINUX) || defined(OS_MAC)
+ if (osbuf == cout.rdbuf()) {
+ static const bool cout_term = isatty(fileno(stdout)) != 0;
+ return cout_term;
+ } else if (osbuf == cerr.rdbuf() || osbuf == clog.rdbuf()) {
+ static const bool cerr_term = isatty(fileno(stderr)) != 0;
+ return cerr_term;
}
-
- inline bool setWinTermAnsiColors(const std::streambuf *osbuf) noexcept
- {
- HANDLE h = getConsoleHandle(osbuf);
- if (h == INVALID_HANDLE_VALUE) {
- return false;
- }
- DWORD dwMode = 0;
- if (!GetConsoleMode(h, &dwMode)) {
- return false;
- }
- dwMode |= ENABLE_VIRTUAL_TERMINAL_PROCESSING;
- if (!SetConsoleMode(h, dwMode)) {
- return false;
- }
- return true;
+#elif defined(OS_WIN)
+ if (osbuf == cout.rdbuf()) {
+ static const bool cout_term = (_isatty(_fileno(stdout)) || isMsysPty(_fileno(stdout)));
+ return cout_term;
+ } else if (osbuf == cerr.rdbuf() || osbuf == clog.rdbuf()) {
+ static const bool cerr_term = (_isatty(_fileno(stderr)) || isMsysPty(_fileno(stderr)));
+ return cerr_term;
}
+#endif
+ return false;
+ }
- inline bool supportsAnsi(const std::streambuf *osbuf) noexcept
- {
- using std::cerr;
- using std::clog;
- using std::cout;
- if (osbuf == cout.rdbuf()) {
- static const bool cout_ansi
- = (isMsysPty(_fileno(stdout)) || setWinTermAnsiColors(osbuf));
- return cout_ansi;
- } else if (osbuf == cerr.rdbuf() || osbuf == clog.rdbuf()) {
- static const bool cerr_ansi
- = (isMsysPty(_fileno(stderr)) || setWinTermAnsiColors(osbuf));
- return cerr_ansi;
- }
- return false;
- }
+ template <typename T>
+ using enableStd = typename std::enable_if<
+ std::is_same<T, rang::style>::value || std::is_same<T, rang::fg>::value ||
+ std::is_same<T, rang::bg>::value || std::is_same<T, rang::fgB>::value ||
+ std::is_same<T, rang::bgB>::value,
+ std::ostream&>::type;
- inline const SGR &defaultState() noexcept
- {
- static const SGR defaultSgr = []() -> SGR {
- CONSOLE_SCREEN_BUFFER_INFO info;
- WORD attrib = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE;
- if (GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE),
- &info)
- || GetConsoleScreenBufferInfo(GetStdHandle(STD_ERROR_HANDLE),
- &info)) {
- attrib = info.wAttributes;
- }
- SGR sgr = { 0, 0, 0, 0, FALSE, FALSE };
- sgr.fgColor = attrib & 0x0F;
- sgr.bgColor = (attrib & 0xF0) >> 4;
- return sgr;
- }();
- return defaultSgr;
- }
+#ifdef OS_WIN
- inline BYTE ansi2attr(BYTE rgb) noexcept
- {
- static const AttrColor rev[8]
- = { AttrColor::black, AttrColor::red, AttrColor::green,
- AttrColor::yellow, AttrColor::blue, AttrColor::magenta,
- AttrColor::cyan, AttrColor::gray };
- return static_cast<BYTE>(rev[rgb]);
+ struct SGR { // Select Graphic Rendition parameters for Windows console
+ BYTE fgColor; // foreground color (0-15) lower 3 rgb bits + intense bit
+ BYTE bgColor; // background color (0-15) lower 3 rgb bits + intense bit
+ BYTE bold; // emulated as FOREGROUND_INTENSITY bit
+ BYTE underline; // emulated as BACKGROUND_INTENSITY bit
+ BOOLEAN inverse; // swap foreground/bold & background/underline
+ BOOLEAN conceal; // set foreground/bold to background/underline
+ };
+
+ enum class AttrColor : BYTE { // Color attributes for console screen buffer
+ black = 0,
+ red = 4,
+ green = 2,
+ yellow = 6,
+ blue = 1,
+ magenta = 5,
+ cyan = 3,
+ gray = 7
+ };
+
+ inline HANDLE getConsoleHandle(const std::streambuf* osbuf) noexcept {
+ if (osbuf == std::cout.rdbuf()) {
+ static const HANDLE hStdout = GetStdHandle(STD_OUTPUT_HANDLE);
+ return hStdout;
+ } else if (osbuf == std::cerr.rdbuf() || osbuf == std::clog.rdbuf()) {
+ static const HANDLE hStderr = GetStdHandle(STD_ERROR_HANDLE);
+ return hStderr;
}
+ return INVALID_HANDLE_VALUE;
+ }
- inline void setWinSGR(rang::bg col, SGR &state) noexcept
- {
- if (col != rang::bg::reset) {
- state.bgColor = ansi2attr(static_cast<BYTE>(col) - 40);
- } else {
- state.bgColor = defaultState().bgColor;
- }
+ inline bool setWinTermAnsiColors(const std::streambuf* osbuf) noexcept {
+ HANDLE h = getConsoleHandle(osbuf);
+ if (h == INVALID_HANDLE_VALUE) {
+ return false;
}
-
- inline void setWinSGR(rang::fg col, SGR &state) noexcept
- {
- if (col != rang::fg::reset) {
- state.fgColor = ansi2attr(static_cast<BYTE>(col) - 30);
- } else {
- state.fgColor = defaultState().fgColor;
- }
+ DWORD dwMode = 0;
+ if (!GetConsoleMode(h, &dwMode)) {
+ return false;
}
-
- inline void setWinSGR(rang::bgB col, SGR &state) noexcept
- {
- state.bgColor = (BACKGROUND_INTENSITY >> 4)
- | ansi2attr(static_cast<BYTE>(col) - 100);
+ dwMode |= ENABLE_VIRTUAL_TERMINAL_PROCESSING;
+ if (!SetConsoleMode(h, dwMode)) {
+ return false;
}
-
- inline void setWinSGR(rang::fgB col, SGR &state) noexcept
- {
- state.fgColor
- = FOREGROUND_INTENSITY | ansi2attr(static_cast<BYTE>(col) - 90);
+ return true;
+ }
+
+ inline bool supportsAnsi(const std::streambuf* osbuf) noexcept {
+ using std::cerr;
+ using std::clog;
+ using std::cout;
+ if (osbuf == cout.rdbuf()) {
+ static const bool cout_ansi = (isMsysPty(_fileno(stdout)) || setWinTermAnsiColors(osbuf));
+ return cout_ansi;
+ } else if (osbuf == cerr.rdbuf() || osbuf == clog.rdbuf()) {
+ static const bool cerr_ansi = (isMsysPty(_fileno(stderr)) || setWinTermAnsiColors(osbuf));
+ return cerr_ansi;
}
-
- inline void setWinSGR(rang::style style, SGR &state) noexcept
- {
- switch (style) {
- case rang::style::reset: state = defaultState(); break;
- case rang::style::bold: state.bold = FOREGROUND_INTENSITY; break;
- case rang::style::underline:
- case rang::style::blink:
- state.underline = BACKGROUND_INTENSITY;
- break;
- case rang::style::reversed: state.inverse = TRUE; break;
- case rang::style::conceal: state.conceal = TRUE; break;
- default: break;
- }
+ return false;
+ }
+
+ inline const SGR& defaultState() noexcept {
+ static const SGR defaultSgr = []() -> SGR {
+ CONSOLE_SCREEN_BUFFER_INFO info;
+ WORD attrib = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE;
+ if (GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &info) ||
+ GetConsoleScreenBufferInfo(GetStdHandle(STD_ERROR_HANDLE), &info)) {
+ attrib = info.wAttributes;
+ }
+ SGR sgr = {0, 0, 0, 0, FALSE, FALSE};
+ sgr.fgColor = attrib & 0x0F;
+ sgr.bgColor = (attrib & 0xF0) >> 4;
+ return sgr;
+ }();
+ return defaultSgr;
+ }
+
+ inline BYTE ansi2attr(BYTE rgb) noexcept {
+ static const AttrColor rev[8] = {AttrColor::black, AttrColor::red, AttrColor::green,
+ AttrColor::yellow, AttrColor::blue, AttrColor::magenta,
+ AttrColor::cyan, AttrColor::gray};
+ return static_cast<BYTE>(rev[rgb]);
+ }
+
+ inline void setWinSGR(rang::bg col, SGR& state) noexcept {
+ if (col != rang::bg::reset) {
+ state.bgColor = ansi2attr(static_cast<BYTE>(col) - 40);
+ } else {
+ state.bgColor = defaultState().bgColor;
}
+ }
- inline SGR &current_state() noexcept
- {
- static SGR state = defaultState();
- return state;
+ inline void setWinSGR(rang::fg col, SGR& state) noexcept {
+ if (col != rang::fg::reset) {
+ state.fgColor = ansi2attr(static_cast<BYTE>(col) - 30);
+ } else {
+ state.fgColor = defaultState().fgColor;
}
-
- inline WORD SGR2Attr(const SGR &state) noexcept
- {
- WORD attrib = 0;
- if (state.conceal) {
- if (state.inverse) {
- attrib = (state.fgColor << 4) | state.fgColor;
- if (state.bold)
- attrib |= FOREGROUND_INTENSITY | BACKGROUND_INTENSITY;
- } else {
- attrib = (state.bgColor << 4) | state.bgColor;
- if (state.underline)
- attrib |= FOREGROUND_INTENSITY | BACKGROUND_INTENSITY;
- }
- } else if (state.inverse) {
- attrib = (state.fgColor << 4) | state.bgColor;
- if (state.bold) attrib |= BACKGROUND_INTENSITY;
- if (state.underline) attrib |= FOREGROUND_INTENSITY;
- } else {
- attrib = state.fgColor | (state.bgColor << 4) | state.bold
- | state.underline;
- }
- return attrib;
+ }
+
+ inline void setWinSGR(rang::bgB col, SGR& state) noexcept {
+ state.bgColor = (BACKGROUND_INTENSITY >> 4) | ansi2attr(static_cast<BYTE>(col) - 100);
+ }
+
+ inline void setWinSGR(rang::fgB col, SGR& state) noexcept {
+ state.fgColor = FOREGROUND_INTENSITY | ansi2attr(static_cast<BYTE>(col) - 90);
+ }
+
+ inline void setWinSGR(rang::style style, SGR& state) noexcept {
+ switch (style) {
+ case rang::style::reset:
+ state = defaultState();
+ break;
+ case rang::style::bold:
+ state.bold = FOREGROUND_INTENSITY;
+ break;
+ case rang::style::underline:
+ case rang::style::blink:
+ state.underline = BACKGROUND_INTENSITY;
+ break;
+ case rang::style::reversed:
+ state.inverse = TRUE;
+ break;
+ case rang::style::conceal:
+ state.conceal = TRUE;
+ break;
+ default:
+ break;
}
-
- template <typename T>
- inline void setWinColorAnsi(std::ostream &os, T const value)
- {
- os << "\033[" << static_cast<int>(value) << "m";
+ }
+
+ inline SGR& current_state() noexcept {
+ static SGR state = defaultState();
+ return state;
+ }
+
+ inline WORD SGR2Attr(const SGR& state) noexcept {
+ WORD attrib = 0;
+ if (state.conceal) {
+ if (state.inverse) {
+ attrib = (state.fgColor << 4) | state.fgColor;
+ if (state.bold) attrib |= FOREGROUND_INTENSITY | BACKGROUND_INTENSITY;
+ } else {
+ attrib = (state.bgColor << 4) | state.bgColor;
+ if (state.underline) attrib |= FOREGROUND_INTENSITY | BACKGROUND_INTENSITY;
+ }
+ } else if (state.inverse) {
+ attrib = (state.fgColor << 4) | state.bgColor;
+ if (state.bold) attrib |= BACKGROUND_INTENSITY;
+ if (state.underline) attrib |= FOREGROUND_INTENSITY;
+ } else {
+ attrib = state.fgColor | (state.bgColor << 4) | state.bold | state.underline;
}
-
- template <typename T>
- inline void setWinColorNative(std::ostream &os, T const value)
- {
- const HANDLE h = getConsoleHandle(os.rdbuf());
- if (h != INVALID_HANDLE_VALUE) {
- setWinSGR(value, current_state());
- // Out all buffered text to console with previous settings:
- os.flush();
- SetConsoleTextAttribute(h, SGR2Attr(current_state()));
- }
+ return attrib;
+ }
+
+ template <typename T>
+ inline void setWinColorAnsi(std::ostream& os, T const value) {
+ os << "\033[" << static_cast<int>(value) << "m";
+ }
+
+ template <typename T>
+ inline void setWinColorNative(std::ostream& os, T const value) {
+ const HANDLE h = getConsoleHandle(os.rdbuf());
+ if (h != INVALID_HANDLE_VALUE) {
+ setWinSGR(value, current_state());
+ // Out all buffered text to console with previous settings:
+ os.flush();
+ SetConsoleTextAttribute(h, SGR2Attr(current_state()));
}
-
- template <typename T>
- inline enableStd<T> setColor(std::ostream &os, T const value)
- {
- if (winTermMode() == winTerm::Auto) {
- if (supportsAnsi(os.rdbuf())) {
- setWinColorAnsi(os, value);
- } else {
- setWinColorNative(os, value);
- }
- } else if (winTermMode() == winTerm::Ansi) {
- setWinColorAnsi(os, value);
- } else {
- setWinColorNative(os, value);
- }
- return os;
+ }
+
+ template <typename T>
+ inline enableStd<T> setColor(std::ostream& os, T const value) {
+ if (winTermMode() == winTerm::Auto) {
+ if (supportsAnsi(os.rdbuf())) {
+ setWinColorAnsi(os, value);
+ } else {
+ setWinColorNative(os, value);
+ }
+ } else if (winTermMode() == winTerm::Ansi) {
+ setWinColorAnsi(os, value);
+ } else {
+ setWinColorNative(os, value);
}
+ return os;
+ }
#else
- template <typename T>
- inline enableStd<T> setColor(std::ostream &os, T const value)
- {
- return os << "\033[" << static_cast<int>(value) << "m";
- }
+ template <typename T>
+ inline enableStd<T> setColor(std::ostream& os, T const value) {
+ return os << "\033[" << static_cast<int>(value) << "m";
+ }
#endif
} // namespace rang_implementation
template <typename T>
-inline rang_implementation::enableStd<T> operator<<(std::ostream &os,
- const T value)
-{
- const control option = rang_implementation::controlMode();
- switch (option) {
- case control::Auto:
- return rang_implementation::supportsColor()
- && rang_implementation::isTerminal(os.rdbuf())
- ? rang_implementation::setColor(os, value)
- : os;
- case control::Force: return rang_implementation::setColor(os, value);
- default: return os;
- }
+inline rang_implementation::enableStd<T> operator<<(std::ostream& os, const T value) {
+ const control option = rang_implementation::controlMode();
+ switch (option) {
+ case control::Auto:
+ return rang_implementation::supportsColor() && rang_implementation::isTerminal(os.rdbuf())
+ ? rang_implementation::setColor(os, value)
+ : os;
+ case control::Force:
+ return rang_implementation::setColor(os, value);
+ default:
+ return os;
+ }
}
-inline void setWinTermMode(const rang::winTerm value) noexcept
-{
- rang_implementation::winTermMode() = value;
+inline void setWinTermMode(const rang::winTerm value) noexcept {
+ rang_implementation::winTermMode() = value;
}
-inline void setControlMode(const control value) noexcept
-{
- rang_implementation::controlMode() = value;
+inline void setControlMode(const control value) noexcept {
+ rang_implementation::controlMode() = value;
}
} // namespace rang