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