cpp-terminal 1.0.0
Small C++ library for writing multiplatform terminal applications
Loading...
Searching...
No Matches
file_initializer.cpp
Go to the documentation of this file.
1/*
2* cpp-terminal
3* C++ library for writing multi-platform terminal applications.
4*
5* SPDX-FileCopyrightText: 2019-2024 cpp-terminal
6*
7* SPDX-License-Identifier: MIT
8*/
9
11
14
15#if defined(_WIN32)
17
18 #include <io.h>
19 #pragma warning(push)
20 #pragma warning(disable : 4668)
21 #define WIN32_LEAN_AND_MEAN
22 #include <windows.h>
23 #pragma warning(pop)
24 #if defined(MessageBox)
25 #undef MessageBox
26 #endif
27#else
28 #include <sys/stat.h>
29#endif
30
32
34
36try
37{
38#if defined(_WIN32)
39 // If something happen here we still don't have a console so we can only use a MessageBox to warn the users something is very bad and that they should contact us.
40 Term::Private::WindowsError error{Term::Private::WindowsError().check_if(AttachConsole(ATTACH_PARENT_PROCESS) == 0)};
41 bool need_allocation{false};
42 switch(error.error())
43 {
44 case ERROR_SUCCESS: break; // Has been attached
45 case ERROR_ACCESS_DENIED: need_allocation = false; break; // Already attached that's good !
46 case ERROR_INVALID_PARAMETER: error.throw_exception("The specified process does not exist !"); break; // Should never happen !
47 case ERROR_INVALID_HANDLE: need_allocation = true; break; // Need to allocate th console !
48 }
49 if(need_allocation)
50 {
51 Term::Private::WindowsError().check_if(AllocConsole() == 0).throw_exception("AllocConsole()");
52 m_consoleCreated = true;
53 }
54#endif
55}
56catch(...)
57{
58 detachConsole();
60}
61
63try
64{
65#if defined(_WIN32)
66 if(m_consoleCreated) { Term::Private::WindowsError().check_if(0 == FreeConsole()).throw_exception("FreeConsole()"); }
67#endif
68}
69catch(...)
70{
72}
73
75try
76{
77 // MacOS was not happy wish a static mutex in the class so we create it and pass to each class;
78 static std::recursive_mutex ioMutex;
79 if(0 == m_counter)
80 {
81 attachConsole();
82 openStandardStreams();
83 if(nullptr == new(&Term::Private::in) InputFileHandler(ioMutex)) { throw Term::Exception("new(&Term::Private::in) InputFileHandler(ioMutex)"); }
84 if(nullptr == new(&Term::Private::out) OutputFileHandler(ioMutex)) { throw Term::Exception("new(&Term::Private::out) OutputFileHandler(ioMutex)"); }
85 }
86 ++m_counter;
87}
88catch(...)
89{
91}
92
94try
95{
96 --m_counter;
97 if(0 == m_counter)
98 {
99 (&Term::Private::in)->~InputFileHandler(); //NOSONAR(S3432)
100 (&Term::Private::out)->~OutputFileHandler(); //NOSONAR(S3432)
101 detachConsole();
102 }
103}
104catch(...)
105{
107}
108
110try
111{
112#if defined(_WIN32)
113 FILE* fDummy{nullptr};
114 if(_fileno(stderr) < 0 || _get_osfhandle(_fileno(stderr)) < 0) { Term::Private::Errno().check_if(_wfreopen_s(&fDummy, L"CONOUT$", L"w", stderr) != 0).throw_exception(R"(_wfreopen_s(&fDummy, L"CONOUT$", L"w", stderr))"); }
115 if(_fileno(stdout) < 0 || _get_osfhandle(_fileno(stdout)) < 0) { Term::Private::Errno().check_if(_wfreopen_s(&fDummy, L"CONOUT$", L"w", stdout) != 0).throw_exception(R"(_wfreopen_s(&fDummy, L"CONOUT$", L"w", stdout))"); }
116 if(_fileno(stdin) < 0 || _get_osfhandle(_fileno(stdin)) < 0) { Term::Private::Errno().check_if(_wfreopen_s(&fDummy, L"CONIN$", L"r", stdin) != 0).throw_exception(R"(_wfreopen_s(&fDummy, L"CONIN$", L"r", stdin))"); }
117 const std::size_t bestSize{BUFSIZ > 4096 ? BUFSIZ : 4096};
118#else
119 if(::fileno(stderr) < 0) { Term::Private::Errno().check_if(nullptr == std::freopen("/dev/tty", "w", stderr)).throw_exception(R"(std::freopen("/dev/tty", "w", stderr))"); } //NOLINT(cppcoreguidelines-owning-memory)
120 if(::fileno(stdout) < 0) { Term::Private::Errno().check_if(nullptr == std::freopen("/dev/tty", "w", stdout)).throw_exception(R"(std::freopen("/dev/tty", "w", stdout))"); } //NOLINT(cppcoreguidelines-owning-memory)
121 if(::fileno(stdin) < 0) { Term::Private::Errno().check_if(nullptr == std::freopen("/dev/tty", "r", stdin)).throw_exception(R"(std::freopen("/dev/tty", "r", stdin))"); } //NOLINT(cppcoreguidelines-owning-memory)
122 struct stat stats = {};
123 ::stat("/dev/tty", &stats);
124 const std::size_t bestSize{static_cast<std::size_t>(stats.st_blksize) > 0 ? static_cast<std::size_t>(stats.st_blksize) : BUFSIZ}; //NOSONAR(S1774)
125#endif
126 Term::Private::Errno().check_if(std::setvbuf(stderr, nullptr, _IONBF, 0) != 0).throw_exception("std::setvbuf(stderr, nullptr, _IONBF, 0)");
127 Term::Private::Errno().check_if(std::setvbuf(stdout, nullptr, _IOLBF, bestSize) != 0).throw_exception("std::setvbuf(stdout, nullptr, _IOLBF, bestSize)");
128 Term::Private::Errno().check_if(std::setvbuf(stdin, nullptr, _IOLBF, bestSize) != 0).throw_exception("std::setvbuf(stdin, nullptr, _IOLBF, bestSize)");
129}
130catch(...)
131{
133}
void throw_exception(const std::string &str={}) const
Errno & check_if(const bool &ret) noexcept
static void attachConsole() noexcept
Attach the console.
static void openStandardStreams() noexcept
Open the standard streams.
static void detachConsole() noexcept
Detach the console.
WindowsError & check_if(const bool &ret) noexcept
Definition exception.cpp:75
void throw_exception(const std::string &str=std::string()) const
Definition exception.cpp:82
InputFileHandler & in
Definition file.cpp:43
void ExceptionHandler(const ExceptionDestination &destination=ExceptionDestination::StdErr) noexcept
OutputFileHandler & out
Definition file.cpp:44