xref: /third_party/gn/src/base/command_line.h (revision 6d528ed9)
1// Copyright (c) 2012 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5// This class works with command lines: building and parsing.
6// Arguments with prefixes ('--', '-', and on Windows, '/') are switches.
7// Switches will precede all other arguments without switch prefixes.
8// Switches can optionally have values, delimited by '=', e.g., "-switch=value".
9// An argument of "--" will terminate switch parsing during initialization,
10// interpreting subsequent tokens as non-switch arguments, regardless of prefix.
11
12// There is a singleton read-only CommandLine that represents the command line
13// that the current process was started with.  It must be initialized in main().
14
15#ifndef BASE_COMMAND_LINE_H_
16#define BASE_COMMAND_LINE_H_
17
18#include <stddef.h>
19#include <map>
20#include <string>
21#include <string_view>
22#include <vector>
23
24#include "util/build_config.h"
25
26namespace base {
27
28class FilePath;
29
30class CommandLine {
31 public:
32#if defined(OS_WIN)
33  // The native command line string type.
34  // See StringTypeToUTF8() and UTF8ToStringType() below.
35  using StringType = std::u16string;
36#elif defined(OS_POSIX) || defined(OS_FUCHSIA)
37  using StringType = std::string;
38#endif
39
40  using CharType = StringType::value_type;
41  using StringVector = std::vector<StringType>;
42  using SwitchMap = std::multimap<std::string, StringType, std::less<>>;
43
44  // A constructor for CommandLines that only carry switches and arguments.
45  enum NoProgram { NO_PROGRAM };
46  explicit CommandLine(NoProgram no_program);
47
48  // Construct a new command line with |program| as argv[0].
49  explicit CommandLine(const FilePath& program);
50
51  // Construct a new command line from an argument list.
52  CommandLine(int argc, const CharType* const* argv);
53  explicit CommandLine(const StringVector& argv);
54
55  // Override copy and assign to ensure |switches_by_stringpiece_| is valid.
56  CommandLine(const CommandLine& other);
57  CommandLine& operator=(const CommandLine& other);
58
59  ~CommandLine();
60
61  // Converts the platform string type to/from UTF-8.
62  static std::string StringTypeToUTF8(const StringType& input);
63  static StringType UTF8ToStringType(std::string_view input);
64
65#if defined(OS_WIN)
66  // By default this class will treat command-line arguments beginning with
67  // slashes as switches on Windows, but not other platforms.
68  //
69  // If this behavior is inappropriate for your application, you can call this
70  // function BEFORE initializing the current process' global command line
71  // object and the behavior will be the same as Posix systems (only hyphens
72  // begin switches, everything else will be an arg).
73  static void set_slash_is_not_a_switch();
74
75  // Normally when the CommandLine singleton is initialized it gets the command
76  // line via the GetCommandLineW API and then uses the shell32 API
77  // CommandLineToArgvW to parse the command line and convert it back to
78  // argc and argv. Tests who don't want this dependency on shell32 and need
79  // to honor the arguments passed in should use this function.
80  static void InitUsingArgvForTesting(int argc, const char* const* argv);
81#endif
82
83  // Initialize the current process CommandLine singleton. On Windows, ignores
84  // its arguments (we instead parse GetCommandLineW() directly) because we
85  // don't trust the CRT's parsing of the command line, but it still must be
86  // called to set up the command line. Returns false if initialization has
87  // already occurred, and true otherwise. Only the caller receiving a 'true'
88  // return value should take responsibility for calling Reset.
89  static bool Init(int argc, const char* const* argv);
90
91  // Destroys the current process CommandLine singleton. This is necessary if
92  // you want to reset the base library to its initial state (for example, in an
93  // outer library that needs to be able to terminate, and be re-initialized).
94  // If Init is called only once, as in main(), Reset() is not necessary.
95  // Do not call this in tests. Use base::test::ScopedCommandLine instead.
96  static void Reset();
97
98  // Get the singleton CommandLine representing the current process's
99  // command line. Note: returned value is mutable, but not thread safe;
100  // only mutate if you know what you're doing!
101  static CommandLine* ForCurrentProcess();
102
103  // Returns true if the CommandLine has been initialized for the given process.
104  static bool InitializedForCurrentProcess();
105
106#if defined(OS_WIN)
107  static CommandLine FromString(const std::u16string& command_line);
108#endif
109
110  // Initialize from an argv vector.
111  void InitFromArgv(int argc, const CharType* const* argv);
112  void InitFromArgv(const StringVector& argv);
113
114  // Constructs and returns the represented command line string.
115  // CAUTION! This should be avoided on POSIX because quoting behavior is
116  // unclear.
117  StringType GetCommandLineString() const {
118    return GetCommandLineStringInternal(false);
119  }
120
121#if defined(OS_WIN)
122  // Constructs and returns the represented command line string. Assumes the
123  // command line contains placeholders (eg, %1) and quotes any program or
124  // argument with a '%' in it. This should be avoided unless the placeholder is
125  // required by an external interface (eg, the Windows registry), because it is
126  // not generally safe to replace it with an arbitrary string. If possible,
127  // placeholders should be replaced *before* converting the command line to a
128  // string.
129  StringType GetCommandLineStringWithPlaceholders() const {
130    return GetCommandLineStringInternal(true);
131  }
132#endif
133
134  // Constructs and returns the represented arguments string.
135  // CAUTION! This should be avoided on POSIX because quoting behavior is
136  // unclear.
137  StringType GetArgumentsString() const {
138    return GetArgumentsStringInternal(false);
139  }
140
141#if defined(OS_WIN)
142  // Constructs and returns the represented arguments string. Assumes the
143  // command line contains placeholders (eg, %1) and quotes any argument with a
144  // '%' in it. This should be avoided unless the placeholder is required by an
145  // external interface (eg, the Windows registry), because it is not generally
146  // safe to replace it with an arbitrary string. If possible, placeholders
147  // should be replaced *before* converting the arguments to a string.
148  StringType GetArgumentsStringWithPlaceholders() const {
149    return GetArgumentsStringInternal(true);
150  }
151#endif
152
153  // Returns the original command line string as a vector of strings.
154  const StringVector& argv() const { return argv_; }
155
156  // Get and Set the program part of the command line string (the first item).
157  FilePath GetProgram() const;
158  void SetProgram(const FilePath& program);
159
160  // Enables/disables the parsing of switches for future argument appending.
161  // True by default, but can be set to false to ensure that no re-ordering
162  // is done.
163  void SetParseSwitches(bool parse_switches) {
164    parse_switches_ = parse_switches;
165  }
166
167  // Returns true if this command line contains the given switch.
168  // Switch names must be lowercase.
169  // The second override provides an optimized version to avoid inlining codegen
170  // at every callsite to find the length of the constant and construct a
171  // std::string_view.
172  bool HasSwitch(std::string_view switch_string) const;
173  bool HasSwitch(const char switch_constant[]) const;
174
175  // Returns the last value associated with the given switch. If the switch has
176  // no value or isn't present, this method returns the empty string. Switch
177  // names must be lowercase.
178  //
179  // The "string" version returns an 8-bit representation. On Windows, this will
180  // convert to UTF-8, on 8-bit systems it will return the raw input.
181  std::string GetSwitchValueString(std::string_view switch_string) const;
182  FilePath GetSwitchValuePath(std::string_view switch_string) const;
183  StringType GetSwitchValueNative(std::string_view switch_string) const;
184
185  // Returns all values associated with the given switch.
186  std::vector<std::string> GetSwitchValueStrings(
187      std::string_view switch_string) const;
188  std::vector<StringType> GetSwitchValuesNative(
189      std::string_view switch_string) const;
190
191  // Get a copy of all switches, along with their values.
192  const SwitchMap& GetSwitches() const { return switches_; }
193
194  // Append a switch [with optional value] to the command line.
195  // Note: Switches will precede arguments regardless of appending order.
196  //
197  // The version that takes an 8-bit switch value converts from UTF-8 on
198  // Windows.
199  void AppendSwitch(const std::string& switch_string);
200  void AppendSwitchPath(const std::string& switch_string, const FilePath& path);
201  void AppendSwitchNative(const std::string& switch_string,
202                          const StringType& value);
203  void AppendSwitch(const std::string& switch_string, const std::string& value);
204
205  // Copy a set of switches (and any values) from another command line.
206  // Commonly used when launching a subprocess.
207  void CopySwitchesFrom(const CommandLine& source,
208                        const char* const switches[],
209                        size_t count);
210
211  // Get the remaining arguments to the command.
212  StringVector GetArgs() const;
213
214  // Append an argument to the command line. Note that the argument is quoted
215  // properly such that it is interpreted as one argument to the target command.
216  // AppendArg is primarily for ASCII; non-ASCII input is interpreted as UTF-8.
217  // Note: Switches will precede arguments regardless of appending order.
218  void AppendArg(const std::string& value);
219  void AppendArgPath(const FilePath& value);
220  void AppendArgNative(const StringType& value);
221
222  // Append the switches and arguments from another command line to this one.
223  // If |include_program| is true, include |other|'s program as well.
224  void AppendArguments(const CommandLine& other, bool include_program);
225
226  // Insert a command before the current command.
227  // Common for debuggers, like "gdb --args".
228  void PrependWrapper(const StringType& wrapper);
229
230#if defined(OS_WIN)
231  // Initialize by parsing the given command line string.
232  // The program name is assumed to be the first item in the string.
233  void ParseFromString(const std::u16string& command_line);
234#endif
235
236 private:
237  // Disallow default constructor; a program name must be explicitly specified.
238  CommandLine() = delete;
239  // Allow the copy constructor. A common pattern is to copy of the current
240  // process's command line and then add some flags to it. For example:
241  //   CommandLine cl(*CommandLine::ForCurrentProcess());
242  //   cl.AppendSwitch(...);
243
244  // Internal version of GetCommandLineString. If |quote_placeholders| is true,
245  // also quotes parts with '%' in them.
246  StringType GetCommandLineStringInternal(bool quote_placeholders) const;
247
248  // Internal version of GetArgumentsString. If |quote_placeholders| is true,
249  // also quotes parts with '%' in them.
250  StringType GetArgumentsStringInternal(bool quote_placeholders) const;
251
252  // The singleton CommandLine representing the current process's command line.
253  static CommandLine* current_process_commandline_;
254
255  // The argv array: { program, [(--|-|/)switch[=value]]*, [--], [argument]* }
256  StringVector argv_;
257
258  // Parsed-out switch keys and values.
259  SwitchMap switches_;
260
261  // The index after the program and switches, any arguments start here.
262  size_t begin_args_;
263
264  // Whether or not to parse arguments that look like switches as switches.
265  bool parse_switches_;
266};
267
268}  // namespace base
269
270#endif  // BASE_COMMAND_LINE_H_
271