|
| 1 | +#include "cpp-terminal/platforms/file.hpp" |
| 2 | + |
| 3 | +#include <new> |
| 4 | + |
| 5 | +#if defined(_WIN32) |
| 6 | + #include <windows.h> |
| 7 | +typedef void* Handle; |
| 8 | +#else |
| 9 | + #include <cstdio> |
| 10 | +typedef FILE* Handle; |
| 11 | +#endif |
| 12 | + |
| 13 | +namespace Term |
| 14 | +{ |
| 15 | + |
| 16 | +namespace Private |
| 17 | +{ |
| 18 | +static char stdin_buf[sizeof(Term::Private::FileHandler)]; |
| 19 | +Term::Private::FileHandler& std_cin = reinterpret_cast<Term::Private::FileHandler&>(stdin_buf); |
| 20 | +static char stdout_buf[sizeof(Term::Private::FileHandler)]; |
| 21 | +Term::Private::FileHandler& std_cout = reinterpret_cast<Term::Private::FileHandler&>(stdout_buf); |
| 22 | +} // namespace Private |
| 23 | + |
| 24 | +} // namespace Term |
| 25 | + |
| 26 | +Term::Private::FileHandler::FileHandler(const char* filename, const char* mode) |
| 27 | +{ |
| 28 | +#if defined(_WIN32) |
| 29 | + m_file = {CreateFile(filename, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL)}; |
| 30 | + if(m_file == INVALID_HANDLE_VALUE) |
| 31 | + { |
| 32 | + m_file = {CreateFile("NUL", GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL)}; |
| 33 | + m_isNull = true; |
| 34 | + } |
| 35 | +#else |
| 36 | + m_file = {std::fopen(filename, mode)}; |
| 37 | + if(m_file == nullptr) |
| 38 | + { |
| 39 | + m_file = {std::fopen("/dev/null", mode)}; |
| 40 | + m_isNull = true; |
| 41 | + } |
| 42 | +#endif |
| 43 | +} |
| 44 | + |
| 45 | +Term::Private::FileHandler::~FileHandler() |
| 46 | +{ |
| 47 | +#if defined(_WIN32) |
| 48 | + CloseHandle(reinterpret_cast<HANDLE>(m_file)); |
| 49 | +#else |
| 50 | + std::fclose(reinterpret_cast<FILE*>(m_file)); |
| 51 | +#endif |
| 52 | +} |
| 53 | + |
| 54 | +bool Term::Private::FileHandler::isNull() { return m_isNull; } |
| 55 | + |
| 56 | +Term::Private::consoleFileHandler Term::Private::FileHandler::getHandler() |
| 57 | +{ |
| 58 | +#if defined(_WIN32) |
| 59 | + return m_file; |
| 60 | +#else |
| 61 | + return fileno(reinterpret_cast<FILE*>(m_file)); |
| 62 | +#endif |
| 63 | +} |
| 64 | + |
| 65 | +int Term::Private::FileInitializer::m_counter = {0}; |
| 66 | + |
| 67 | +void Term::Private::FileInitializer::initialize() |
| 68 | +{ |
| 69 | + if(m_counter++ == 0) |
| 70 | + { |
| 71 | +#if defined(_WIN32) |
| 72 | + new(&Term::Private::std_cin) FileHandler("CONIN$", ""); |
| 73 | + new(&Term::Private::std_cout) FileHandler("CONOUT$", ""); |
| 74 | +#else |
| 75 | + new(&Term::Private::std_cin) FileHandler("/dev/tty", "r"); |
| 76 | + new(&Term::Private::std_cout) FileHandler("/dev/tty", "w"); |
| 77 | +#endif |
| 78 | + } |
| 79 | +} |
| 80 | + |
| 81 | +Term::Private::FileInitializer::FileInitializer() { initialize(); } |
| 82 | + |
| 83 | +Term::Private::FileInitializer::~FileInitializer() |
| 84 | +{ |
| 85 | + if(--m_counter == 0) |
| 86 | + { |
| 87 | + (&Term::Private::std_cin)->~FileHandler(); |
| 88 | + (&Term::Private::std_cout)->~FileHandler(); |
| 89 | + } |
| 90 | +} |
0 commit comments