C++ Utilities 5.12.0
Useful C++ classes and routines such as argument parser, IO and conversion utilities
commandlineutils.cpp
Go to the documentation of this file.
3
4#include <iostream>
5#include <string>
6
7#ifndef PLATFORM_WINDOWS
8#include <sys/ioctl.h>
9#include <unistd.h>
10#else
11#include <fcntl.h>
12#include <windows.h>
13#endif
14
15using namespace std;
16
17namespace CppUtilities {
18
22bool confirmPrompt(const char *message, Response defaultResponse)
23{
24 cout << message;
25 cout << ' ' << '[';
26 cout << (defaultResponse == Response::Yes ? 'Y' : 'y');
27 cout << '/' << (defaultResponse == Response::No ? 'N' : 'n');
28 cout << ']' << ' ';
29 cout.flush();
30 for (string line;;) {
31 getline(cin, line);
32 if (line == "y" || line == "Y" || (defaultResponse == Response::Yes && line.empty())) {
33 return true;
34 } else if (line == "n" || line == "N" || (defaultResponse == Response::No && line.empty())) {
35 return false;
36 } else {
37 cout << "Please enter [y] or [n]: ";
38 cout.flush();
39 }
40 }
41}
42
48{
49 TerminalSize size;
50#ifndef PLATFORM_WINDOWS
51 ioctl(STDOUT_FILENO, TIOCGWINSZ, reinterpret_cast<winsize *>(&size));
52#else
53 CONSOLE_SCREEN_BUFFER_INFO consoleBufferInfo;
54 if (const HANDLE stdHandle = GetStdHandle(STD_OUTPUT_HANDLE)) {
55 GetConsoleScreenBufferInfo(stdHandle, &consoleBufferInfo);
56 if (consoleBufferInfo.dwSize.X > 0) {
57 size.columns = static_cast<unsigned short>(consoleBufferInfo.dwSize.X);
58 }
59 if (consoleBufferInfo.dwSize.Y > 0) {
60 size.rows = static_cast<unsigned short>(consoleBufferInfo.dwSize.Y);
61 }
62 }
63#endif
64 return size;
65}
66
67#ifdef PLATFORM_WINDOWS
72void stopConsole()
73{
74 fclose(stdout);
75 fclose(stdin);
76 fclose(stderr);
77 if (auto *const consoleWindow = GetConsoleWindow()) {
78 PostMessage(consoleWindow, WM_KEYUP, VK_RETURN, 0);
79 FreeConsole();
80 }
81}
82
98void startConsole()
99{
100 // attach to the parent process' console or allocate a new console if that's not possible
101 const auto consoleEnabled = isEnvVariableSet("ENABLE_CONSOLE");
102 if ((!consoleEnabled.has_value() || consoleEnabled.value()) && (AttachConsole(ATTACH_PARENT_PROCESS) || AllocConsole())) {
103 // redirect stdout
104 auto stdHandle = reinterpret_cast<intptr_t>(GetStdHandle(STD_OUTPUT_HANDLE));
105 auto conHandle = _open_osfhandle(stdHandle, _O_TEXT);
106 auto fp = _fdopen(conHandle, "w");
107 *stdout = *fp;
108 setvbuf(stdout, nullptr, _IONBF, 0);
109 // redirect stdin
110 stdHandle = reinterpret_cast<intptr_t>(GetStdHandle(STD_INPUT_HANDLE));
111 conHandle = _open_osfhandle(stdHandle, _O_TEXT);
112 fp = _fdopen(conHandle, "r");
113 *stdin = *fp;
114 setvbuf(stdin, nullptr, _IONBF, 0);
115 // redirect stderr
116 stdHandle = reinterpret_cast<intptr_t>(GetStdHandle(STD_ERROR_HANDLE));
117 conHandle = _open_osfhandle(stdHandle, _O_TEXT);
118 fp = _fdopen(conHandle, "w");
119 *stderr = *fp;
120 setvbuf(stderr, nullptr, _IONBF, 0);
121 // sync
122 ios::sync_with_stdio(true);
123 // ensure the console prompt is shown again when app terminates
124 atexit(stopConsole);
125 }
126
127 // set console character set to UTF-8
128 const auto utf8Enabled = isEnvVariableSet("ENABLE_CP_UTF8");
129 if (!utf8Enabled.has_value() || utf8Enabled.value()) {
130 SetConsoleCP(CP_UTF8);
131 SetConsoleOutputCP(CP_UTF8);
132 }
133}
134
139pair<vector<unique_ptr<char[]>>, vector<char *>> convertArgsToUtf8()
140{
141 pair<vector<unique_ptr<char[]>>, vector<char *>> res;
142 int argc;
143
144 LPWSTR *argv_w = CommandLineToArgvW(GetCommandLineW(), &argc);
145 if (!argv_w || argc <= 0) {
146 return res;
147 }
148
149 res.first.reserve(static_cast<size_t>(argc));
150 res.second.reserve(static_cast<size_t>(argc));
151 for (LPWSTR *i = argv_w, *end = argv_w + argc; i != end; ++i) {
152 int requiredSize = WideCharToMultiByte(CP_UTF8, 0, *i, -1, nullptr, 0, 0, 0);
153 if (requiredSize <= 0) {
154 break; // just stop on error
155 }
156
157 auto argv = make_unique<char[]>(static_cast<size_t>(requiredSize));
158 requiredSize = WideCharToMultiByte(CP_UTF8, 0, *i, -1, argv.get(), requiredSize, 0, 0);
159 if (requiredSize <= 0) {
160 break;
161 }
162
163 res.second.emplace_back(argv.get());
164 res.first.emplace_back(move(argv));
165 }
166
167 LocalFree(argv_w);
168 return res;
169}
170#endif
171
172} // namespace CppUtilities
Contains all utilities provides by the c++utilities library.
CPP_UTILITIES_EXPORT TerminalSize determineTerminalSize()
Returns the current size of the terminal.
Response
The Response enum is used to specify the default response for the confirmPrompt() method.
CPP_UTILITIES_EXPORT bool confirmPrompt(const char *message, Response defaultResponse=Response::None)
Prompts for confirmation displaying the specified message.
std::optional< bool > isEnvVariableSet(const char *variableName)
Returns whether the specified env variable is set to a non-zero and non-white-space-only value.
STL namespace.
The TerminalSize struct describes a terminal size.
unsigned short columns
number of columns
unsigned short rows
number of rows
constexpr int i