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