From def5c50960eea4c112647f88361a3ae7155901a8 Mon Sep 17 00:00:00 2001 From: egor-tensin Date: Tue, 4 Jul 2023 00:48:00 +0000 Subject: =?UTF-8?q?Deploying=20to=20gh-pages=20from=20@=20egor-tensin/wina?= =?UTF-8?q?pi-common@0c196cbe8b4927c78c02b2c7312fc69a507db845=20?= =?UTF-8?q?=F0=9F=9A=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- cmd__line_8cpp_source.html | 249 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 249 insertions(+) create mode 100644 cmd__line_8cpp_source.html (limited to 'cmd__line_8cpp_source.html') diff --git a/cmd__line_8cpp_source.html b/cmd__line_8cpp_source.html new file mode 100644 index 0000000..6192ded --- /dev/null +++ b/cmd__line_8cpp_source.html @@ -0,0 +1,249 @@ + + + + + + + +winapi_common: src/cmd_line.cpp Source File + + + + + + + + + +
+
+ + + + + + +
+
winapi_common +
+
+
+ + + + + + + + +
+
+ + +
+ +
+ + +
+
+
+
cmd_line.cpp
+
+
+
1 // Copyright (c) 2020 Egor Tensin <Egor.Tensin@gmail.com>
+
2 // This file is part of the "winapi-common" project.
+
3 // For details, see https://github.com/egor-tensin/winapi-common.
+
4 // Distributed under the MIT License.
+
5 
+
6 #include <winapi/cmd_line.hpp>
+
7 #include <winapi/error.hpp>
+
8 #include <winapi/utf8.hpp>
+
9 #include <winapi/utils.hpp>
+
10 
+
11 #include <boost/algorithm/string.hpp>
+
12 
+
13 // clang-format off
+
14 #include <windows.h>
+
15 #include <shellapi.h>
+
16 // clang-format on
+
17 
+
18 #include <cstddef>
+
19 #include <memory>
+
20 #include <sstream>
+
21 #include <stdexcept>
+
22 #include <string>
+
23 #include <utility>
+
24 #include <vector>
+
25 
+
26 namespace winapi {
+
27 namespace {
+
28 
+
29 std::vector<std::string> narrow_all(int argc, wchar_t** argv) {
+
30  std::vector<std::string> utf;
+
31  utf.reserve(argc);
+
32  for (int i = 0; i < argc; ++i)
+
33  utf.emplace_back(narrow(argv[i]));
+
34  return utf;
+
35 }
+
36 
+
37 CommandLine do_parse(std::wstring src) {
+
38  boost::trim(src);
+
39  if (src.empty()) {
+
40  throw std::runtime_error{"Command line cannot be an empty string"};
+
41  }
+
42 
+
43  int argc = 0;
+
44  std::unique_ptr<wchar_t*, LocalDelete> argv{::CommandLineToArgvW(src.c_str(), &argc)};
+
45 
+
46  if (argv.get() == NULL) {
+
47  throw error::windows(GetLastError(), "CommandLineToArgvW");
+
48  }
+
49  if (argc == 0) {
+
50  throw std::runtime_error{"Command line must contain at least one token"};
+
51  }
+
52 
+
53  return CommandLine{narrow_all(argc, argv.get())};
+
54 }
+
55 
+
56 std::string split_argv0(std::vector<std::string>& argv) {
+
57  if (argv.empty()) {
+
58  throw std::range_error{"argv must contain at least one element"};
+
59  }
+
60  auto argv0 = argv[0];
+
61  argv.erase(argv.begin());
+
62  return argv0;
+
63 }
+
64 
+
65 std::vector<std::string> escape_all(const std::vector<std::string>& xs) {
+
66  std::vector<std::string> escaped;
+
67  escaped.reserve(xs.size());
+
68  for (const auto& x : xs)
+
69  escaped.emplace_back(CommandLine::escape(x));
+
70  return escaped;
+
71 }
+
72 
+
73 } // namespace
+
74 
+ +
76  return do_parse(::GetCommandLineW());
+
77 }
+
78 
+
79 CommandLine CommandLine::parse(const std::string& src) {
+
80  return do_parse(widen(src));
+
81 }
+
82 
+
83 CommandLine CommandLine::from_main(int argc, wchar_t* argv[]) {
+
84  if (argc < 1)
+
85  throw std::range_error{"argc must be a positive number"};
+
86  return CommandLine{narrow_all(argc, argv)};
+
87 }
+
88 
+
89 CommandLine::CommandLine(std::vector<std::string> argv) : m_args{std::move(argv)} {
+
90  m_argv0 = split_argv0(m_args);
+
91 }
+
92 
+
93 std::string CommandLine::escape(const std::string& arg) {
+
94  std::ostringstream safe;
+
95  safe << '"';
+
96 
+
97  for (auto it = arg.cbegin(); it != arg.cend(); ++it) {
+
98  std::size_t numof_backslashes = 0;
+
99 
+
100  for (; it != arg.cend() && *it == '\\'; ++it)
+
101  ++numof_backslashes;
+
102 
+
103  if (it == arg.cend()) {
+
104  safe << std::string(2 * numof_backslashes, '\\');
+
105  break;
+
106  }
+
107 
+
108  switch (*it) {
+
109  case L'"':
+
110  safe << std::string(2 * numof_backslashes + 1, '\\');
+
111  break;
+
112 
+
113  default:
+
114  safe << std::string(numof_backslashes, '\\');
+
115  break;
+
116  }
+
117 
+
118  safe << *it;
+
119  }
+
120 
+
121  safe << '"';
+
122  return safe.str();
+
123 }
+
124 
+
125 std::string CommandLine::escape_cmd(const std::string& arg) {
+
126  static constexpr auto escape_symbol = '^';
+
127  static const std::string dangerous_symbols{"^!\"%&()<>|"};
+
128 
+
129  auto safe = escape(arg);
+
130  for (const auto danger : dangerous_symbols) {
+
131  std::ostringstream replacement;
+
132  replacement << escape_symbol << danger;
+
133  boost::replace_all(safe, std::string{danger}, replacement.str());
+
134  }
+
135  return safe;
+
136 }
+
137 
+
138 std::string CommandLine::to_string() const {
+
139  return boost::algorithm::join(escape_argv(), std::string{token_sep()});
+
140 }
+
141 
+
142 std::string CommandLine::args_to_string() const {
+
143  return boost::algorithm::join(escape_args(), std::string{token_sep()});
+
144 }
+
145 
+
146 std::vector<std::string> CommandLine::get_argv() const {
+
147  auto argv = get_args();
+
148  argv.emplace(argv.begin(), get_argv0());
+
149  return argv;
+
150 }
+
151 
+
152 std::vector<std::string> CommandLine::escape_args() const {
+
153  return escape_all(get_args());
+
154 }
+
155 
+
156 std::vector<std::string> CommandLine::escape_argv() const {
+
157  return escape_all(get_argv());
+
158 }
+
159 
+
160 } // namespace winapi
+
Command line for the current process or for launching new processes.
Definition: cmd_line.hpp:21
+
static CommandLine from_main(int argc, wchar_t *argv[])
Definition: cmd_line.cpp:83
+
std::string get_argv0() const
Definition: cmd_line.hpp:87
+
static CommandLine query()
Definition: cmd_line.cpp:75
+
static CommandLine parse(const std::string &src)
Definition: cmd_line.cpp:79
+
std::vector< std::string > get_argv() const
Definition: cmd_line.cpp:146
+
std::string to_string() const
Definition: cmd_line.cpp:138
+ +
const std::vector< std::string > & get_args() const
Definition: cmd_line.hpp:96
+
std::string args_to_string() const
Definition: cmd_line.cpp:142
+
Make std::system_error work with GetLastError().
+
+ + + + -- cgit v1.2.3