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-2025 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
74#ifdef _WIN32
75 #pragma warning(push)
76 #pragma warning(disable : 4297)
77#endif
78
80try
81{
82 // MacOS was not happy wish a static mutex in the class so we create it and pass to each class;
83 static std::recursive_mutex ioMutex;
84 if(0 == m_counter)
85 {
88 if(nullptr == new(&Term::Private::in) InputFileHandler(ioMutex)) { throw Term::Exception("new(&Term::Private::in) InputFileHandler(ioMutex)"); }
89 if(nullptr == new(&Term::Private::out) OutputFileHandler(ioMutex)) { throw Term::Exception("new(&Term::Private::out) OutputFileHandler(ioMutex)"); }
90 }
91 ++m_counter;
92}
93catch(...)
94{
96}
97
99try
100{
101 --m_counter;
102 if(0 == m_counter)
103 {
104 (&Term::Private::in)->~InputFileHandler(); //NOSONAR(S3432)
105 (&Term::Private::out)->~OutputFileHandler(); //NOSONAR(S3432)
107 }
108}
109catch(...)
110{
112}
113
114#ifdef _WIN32
115 #pragma warning(pop)
116#endif
117
119try
120{
121#if defined(_WIN32)
122 FILE* fDummy{nullptr};
123 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))"); }
124 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))"); }
125 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))"); }
126 const std::size_t bestSize{BUFSIZ > 4096 ? BUFSIZ : 4096};
127#else
128 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)
129 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)
130 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)
131 struct stat stats = {};
132 ::stat("/dev/tty", &stats);
133 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)
134#endif
135 Term::Private::Errno().check_if(std::setvbuf(stderr, nullptr, _IONBF, 0) != 0).throw_exception("std::setvbuf(stderr, nullptr, _IONBF, 0)");
136 Term::Private::Errno().check_if(std::setvbuf(stdout, nullptr, _IOLBF, bestSize) != 0).throw_exception("std::setvbuf(stdout, nullptr, _IOLBF, bestSize)");
137 Term::Private::Errno().check_if(std::setvbuf(stdin, nullptr, _IOLBF, bestSize) != 0).throw_exception("std::setvbuf(stdin, nullptr, _IOLBF, bestSize)");
138}
139catch(...)
140{
142}
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