Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(40)

Side by Side Diff: base/command_line.cc

Issue 6596020: Reorganize CommandLine code. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Address comments. Created 9 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « base/command_line.h ('k') | chrome/test/in_process_browser_test.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "base/command_line.h" 5 #include "base/command_line.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 8
9 #include "base/file_path.h" 9 #include "base/file_path.h"
10 #include "base/file_util.h" 10 #include "base/file_util.h"
11 #include "base/logging.h" 11 #include "base/logging.h"
12 #include "base/singleton.h" 12 #include "base/singleton.h"
13 #include "base/string_split.h" 13 #include "base/string_split.h"
14 #include "base/string_util.h" 14 #include "base/string_util.h"
15 #include "base/sys_string_conversions.h" 15 #include "base/sys_string_conversions.h"
16 #include "base/utf_string_conversions.h" 16 #include "base/utf_string_conversions.h"
17 #include "build/build_config.h" 17 #include "build/build_config.h"
18 18
19 #if defined(OS_WIN) 19 #if defined(OS_WIN)
20 #include <windows.h> 20 #include <windows.h>
21 #include <shellapi.h> 21 #include <shellapi.h>
22 #elif defined(OS_POSIX) 22 #elif defined(OS_POSIX)
23 #include <limits.h> 23 #include <limits.h>
24 #include <stdlib.h> 24 #include <stdlib.h>
25 #include <unistd.h> 25 #include <unistd.h>
26 #endif 26 #endif
27 27
28 CommandLine* CommandLine::current_process_commandline_ = NULL; 28 CommandLine* CommandLine::current_process_commandline_ = NULL;
29 29
30 // Since we use a lazy match, make sure that longer versions (like L"--") 30 namespace {
31 // are listed before shorter versions (like L"-") of similar prefixes. 31 typedef CommandLine::StringType::value_type CharType;
32
33 const CharType kSwitchTerminator[] = FILE_PATH_LITERAL("--");
34 const CharType kSwitchValueSeparator[] = FILE_PATH_LITERAL("=");
35 // Since we use a lazy match, make sure that longer versions (like "--") are
36 // listed before shorter versions (like "-") of similar prefixes.
32 #if defined(OS_WIN) 37 #if defined(OS_WIN)
33 const wchar_t* const kSwitchPrefixes[] = {L"--", L"-", L"/"}; 38 const CharType* const kSwitchPrefixes[] = {L"--", L"-", L"/"};
34 const wchar_t kSwitchTerminator[] = L"--";
35 const wchar_t kSwitchValueSeparator[] = L"=";
36 #elif defined(OS_POSIX) 39 #elif defined(OS_POSIX)
37 // Unixes don't use slash as a switch. 40 // Unixes don't use slash as a switch.
38 const char* const kSwitchPrefixes[] = {"--", "-"}; 41 const CharType* const kSwitchPrefixes[] = {"--", "-"};
39 const char kSwitchTerminator[] = "--";
40 const char kSwitchValueSeparator[] = "=";
41 #endif 42 #endif
42 43
43 #if defined(OS_WIN) 44 #if defined(OS_WIN)
44 namespace { 45 // Lowercase a string for case-insensitivity of switches.
45 // Lowercase a string. This is used to lowercase switch names. 46 // Is this desirable? It exists for backwards compatibility on Windows.
46 // Is this what we really want? It seems crazy to me. I've left it in 47 void Lowercase(std::string* arg) {
47 // for backwards compatibility on Windows. 48 transform(arg->begin(), arg->end(), arg->begin(), tolower);
48 void Lowercase(std::string* parameter) {
49 transform(parameter->begin(), parameter->end(), parameter->begin(),
50 tolower);
51 } 49 }
52 50
53 // Quote a string if necessary, such that CommandLineToArgvW() will 51 // Quote a string if necessary, such that CommandLineToArgvW() will always
54 // always process it as a single argument. 52 // process it as a single argument.
55 std::wstring WindowsStyleQuote(const std::wstring& arg) { 53 std::wstring WindowsStyleQuote(const std::wstring& arg) {
56 // We follow the quoting rules of CommandLineToArgvW. 54 // We follow the quoting rules of CommandLineToArgvW.
57 // http://msdn.microsoft.com/en-us/library/17w5ykft.aspx 55 // http://msdn.microsoft.com/en-us/library/17w5ykft.aspx
58 if (arg.find_first_of(L" \\\"") == std::wstring::npos) { 56 if (arg.find_first_of(L" \\\"") == std::wstring::npos) {
59 // No quoting necessary. 57 // No quoting necessary.
60 return arg; 58 return arg;
61 } 59 }
62 60
63 std::wstring out; 61 std::wstring out;
64 out.push_back(L'"'); 62 out.push_back(L'"');
(...skipping 21 matching lines...) Expand all
86 out.push_back('\\'); 84 out.push_back('\\');
87 out.push_back('"'); 85 out.push_back('"');
88 } else { 86 } else {
89 out.push_back(arg[i]); 87 out.push_back(arg[i]);
90 } 88 }
91 } 89 }
92 out.push_back('"'); 90 out.push_back('"');
93 91
94 return out; 92 return out;
95 } 93 }
96 } // namespace
97 #endif 94 #endif
98 95
99 CommandLine::~CommandLine() { 96 // Returns true and fills in |switch_string| and |switch_value| if
97 // |parameter_string| represents a switch.
98 bool IsSwitch(const CommandLine::StringType& parameter_string,
99 std::string* switch_string,
100 CommandLine::StringType* switch_value) {
101 switch_string->clear();
102 switch_value->clear();
103
104 for (size_t i = 0; i < arraysize(kSwitchPrefixes); ++i) {
105 CommandLine::StringType prefix(kSwitchPrefixes[i]);
106 if (parameter_string.find(prefix) != 0)
107 continue;
108
109 const size_t switch_start = prefix.length();
110 const size_t equals_position = parameter_string.find(
111 kSwitchValueSeparator, switch_start);
112 CommandLine::StringType switch_native;
113 if (equals_position == CommandLine::StringType::npos) {
114 switch_native = parameter_string.substr(switch_start);
115 } else {
116 switch_native = parameter_string.substr(
117 switch_start, equals_position - switch_start);
118 *switch_value = parameter_string.substr(equals_position + 1);
119 }
120 #if defined(OS_WIN)
121 *switch_string = WideToASCII(switch_native);
122 Lowercase(switch_string);
123 #else
124 *switch_string = switch_native;
125 #endif
126
127 return true;
128 }
129
130 return false;
131 }
132
133 } // namespace
134
135 CommandLine::CommandLine(NoProgram no_program) {
136 #if defined(OS_POSIX)
137 // Push an empty argument, because we always assume argv_[0] is a program.
138 argv_.push_back("");
139 #endif
140 }
141
142 CommandLine::CommandLine(const FilePath& program) {
143 #if defined(OS_WIN)
144 if (!program.empty()) {
145 program_ = program.value();
146 // TODO(evanm): proper quoting here.
147 command_line_string_ = L'"' + program.value() + L'"';
148 }
149 #elif defined(OS_POSIX)
150 argv_.push_back(program.value());
151 #endif
152 }
153
154 #if defined(OS_POSIX)
155 CommandLine::CommandLine(int argc, const char* const* argv) {
156 InitFromArgv(argc, argv);
157 }
158
159 CommandLine::CommandLine(const StringVector& argv) {
160 InitFromArgv(argv);
161 }
162 #endif // OS_POSIX
163
164 // static
165 void CommandLine::Init(int argc, const char* const* argv) {
166 delete current_process_commandline_;
167 current_process_commandline_ = new CommandLine;
168 #if defined(OS_WIN)
169 current_process_commandline_->ParseFromString(::GetCommandLineW());
170 #elif defined(OS_POSIX)
171 current_process_commandline_->InitFromArgv(argc, argv);
172 #endif
173 }
174
175 // static
176 void CommandLine::Reset() {
177 DCHECK(current_process_commandline_);
178 delete current_process_commandline_;
179 current_process_commandline_ = NULL;
180 }
181
182 // static
183 CommandLine* CommandLine::ForCurrentProcess() {
184 DCHECK(current_process_commandline_);
185 return current_process_commandline_;
100 } 186 }
101 187
102 #if defined(OS_WIN) 188 #if defined(OS_WIN)
103 CommandLine::CommandLine(NoProgram no_program) {
104 }
105
106 void CommandLine::ParseFromString(const std::wstring& command_line) {
107 TrimWhitespace(command_line, TRIM_ALL, &command_line_string_);
108
109 if (command_line_string_.empty())
110 return;
111
112 int num_args = 0;
113 wchar_t** args = NULL;
114
115 args = CommandLineToArgvW(command_line_string_.c_str(), &num_args);
116
117 // Populate program_ with the trimmed version of the first arg.
118 TrimWhitespace(args[0], TRIM_ALL, &program_);
119
120 bool parse_switches = true;
121 for (int i = 1; i < num_args; ++i) {
122 std::wstring arg;
123 TrimWhitespace(args[i], TRIM_ALL, &arg);
124
125 if (!parse_switches) {
126 args_.push_back(arg);
127 continue;
128 }
129
130 if (arg == kSwitchTerminator) {
131 parse_switches = false;
132 continue;
133 }
134
135 std::string switch_string;
136 std::wstring switch_value;
137 if (IsSwitch(arg, &switch_string, &switch_value)) {
138 switches_[switch_string] = switch_value;
139 } else {
140 args_.push_back(arg);
141 }
142 }
143
144 if (args)
145 LocalFree(args);
146 }
147
148 // static 189 // static
149 CommandLine CommandLine::FromString(const std::wstring& command_line) { 190 CommandLine CommandLine::FromString(const std::wstring& command_line) {
150 CommandLine cmd; 191 CommandLine cmd;
151 cmd.ParseFromString(command_line); 192 cmd.ParseFromString(command_line);
152 return cmd; 193 return cmd;
153 } 194 }
195 #endif // OS_WIN
154 196
155 CommandLine::CommandLine(const FilePath& program) { 197 #if defined(OS_POSIX)
156 if (!program.empty()) {
157 program_ = program.value();
158 // TODO(evanm): proper quoting here.
159 command_line_string_ = L'"' + program.value() + L'"';
160 }
161 }
162
163 #elif defined(OS_POSIX)
164 CommandLine::CommandLine(NoProgram no_program) {
165 // Push an empty argument, because we always assume argv_[0] is a program.
166 argv_.push_back("");
167 }
168
169 CommandLine::CommandLine(int argc, const char* const* argv) {
170 InitFromArgv(argc, argv);
171 }
172
173 CommandLine::CommandLine(const std::vector<std::string>& argv) {
174 InitFromArgv(argv);
175 }
176
177 void CommandLine::InitFromArgv(int argc, const char* const* argv) { 198 void CommandLine::InitFromArgv(int argc, const char* const* argv) {
178 for (int i = 0; i < argc; ++i) 199 for (int i = 0; i < argc; ++i)
179 argv_.push_back(argv[i]); 200 argv_.push_back(argv[i]);
180 InitFromArgv(argv_); 201 InitFromArgv(argv_);
181 } 202 }
182 203
183 void CommandLine::InitFromArgv(const std::vector<std::string>& argv) { 204 void CommandLine::InitFromArgv(const StringVector& argv) {
184 argv_ = argv; 205 argv_ = argv;
185 bool parse_switches = true; 206 bool parse_switches = true;
186 for (size_t i = 1; i < argv_.size(); ++i) { 207 for (size_t i = 1; i < argv_.size(); ++i) {
187 const std::string& arg = argv_[i]; 208 const std::string& arg = argv_[i];
188 209
189 if (!parse_switches) { 210 if (!parse_switches) {
190 args_.push_back(arg); 211 args_.push_back(arg);
191 continue; 212 continue;
192 } 213 }
193 214
194 if (arg == kSwitchTerminator) { 215 if (arg == kSwitchTerminator) {
195 parse_switches = false; 216 parse_switches = false;
196 continue; 217 continue;
197 } 218 }
198 219
199 std::string switch_string; 220 std::string switch_string;
200 std::string switch_value; 221 StringType switch_value;
201 if (IsSwitch(arg, &switch_string, &switch_value)) { 222 if (IsSwitch(arg, &switch_string, &switch_value)) {
202 switches_[switch_string] = switch_value; 223 switches_[switch_string] = switch_value;
203 } else { 224 } else {
204 args_.push_back(arg); 225 args_.push_back(arg);
205 } 226 }
206 } 227 }
207 } 228 }
229 #endif // OS_POSIX
208 230
209 CommandLine::CommandLine(const FilePath& program) { 231 CommandLine::StringType CommandLine::command_line_string() const {
210 argv_.push_back(program.value());
211 }
212
213 #endif
214
215 // static
216 bool CommandLine::IsSwitch(const StringType& parameter_string,
217 std::string* switch_string,
218 StringType* switch_value) {
219 switch_string->clear();
220 switch_value->clear();
221
222 for (size_t i = 0; i < arraysize(kSwitchPrefixes); ++i) {
223 StringType prefix(kSwitchPrefixes[i]);
224 if (parameter_string.find(prefix) != 0)
225 continue;
226
227 const size_t switch_start = prefix.length();
228 const size_t equals_position = parameter_string.find(
229 kSwitchValueSeparator, switch_start);
230 StringType switch_native;
231 if (equals_position == StringType::npos) {
232 switch_native = parameter_string.substr(switch_start);
233 } else {
234 switch_native = parameter_string.substr(
235 switch_start, equals_position - switch_start);
236 *switch_value = parameter_string.substr(equals_position + 1);
237 }
238 #if defined(OS_WIN) 232 #if defined(OS_WIN)
239 *switch_string = WideToASCII(switch_native); 233 return command_line_string_;
240 Lowercase(switch_string);
241 #else
242 *switch_string = switch_native;
243 #endif
244
245 return true;
246 }
247
248 return false;
249 }
250
251 // static
252 void CommandLine::Init(int argc, const char* const* argv) {
253 delete current_process_commandline_;
254 current_process_commandline_ = new CommandLine;
255 #if defined(OS_WIN)
256 current_process_commandline_->ParseFromString(::GetCommandLineW());
257 #elif defined(OS_POSIX) 234 #elif defined(OS_POSIX)
258 current_process_commandline_->InitFromArgv(argc, argv); 235 return JoinString(argv_, ' ');
259 #endif 236 #endif
260 } 237 }
261 238
262 void CommandLine::Reset() { 239 FilePath CommandLine::GetProgram() const {
263 DCHECK(current_process_commandline_ != NULL); 240 #if defined(OS_WIN)
264 delete current_process_commandline_; 241 return FilePath(program_);
265 current_process_commandline_ = NULL; 242 #else
266 } 243 DCHECK_GT(argv_.size(), 0U);
267 244 return FilePath(argv_[0]);
268 // static 245 #endif
269 CommandLine* CommandLine::ForCurrentProcess() {
270 DCHECK(current_process_commandline_);
271 return current_process_commandline_;
272 } 246 }
273 247
274 bool CommandLine::HasSwitch(const std::string& switch_string) const { 248 bool CommandLine::HasSwitch(const std::string& switch_string) const {
275 std::string lowercased_switch(switch_string); 249 std::string lowercased_switch(switch_string);
276 #if defined(OS_WIN) 250 #if defined(OS_WIN)
277 Lowercase(&lowercased_switch); 251 Lowercase(&lowercased_switch);
278 #endif 252 #endif
279 return switches_.find(lowercased_switch) != switches_.end(); 253 return switches_.find(lowercased_switch) != switches_.end();
280 } 254 }
281 255
(...skipping 16 matching lines...) Expand all
298 return FilePath(GetSwitchValueNative(switch_string)); 272 return FilePath(GetSwitchValueNative(switch_string));
299 } 273 }
300 274
301 CommandLine::StringType CommandLine::GetSwitchValueNative( 275 CommandLine::StringType CommandLine::GetSwitchValueNative(
302 const std::string& switch_string) const { 276 const std::string& switch_string) const {
303 std::string lowercased_switch(switch_string); 277 std::string lowercased_switch(switch_string);
304 #if defined(OS_WIN) 278 #if defined(OS_WIN)
305 Lowercase(&lowercased_switch); 279 Lowercase(&lowercased_switch);
306 #endif 280 #endif
307 281
308 std::map<std::string, StringType>::const_iterator result = 282 SwitchMap::const_iterator result = switches_.find(lowercased_switch);
309 switches_.find(lowercased_switch);
310 283
311 if (result == switches_.end()) { 284 if (result == switches_.end()) {
312 return CommandLine::StringType(); 285 return CommandLine::StringType();
313 } else { 286 } else {
314 return result->second; 287 return result->second;
315 } 288 }
316 } 289 }
317 290
318 FilePath CommandLine::GetProgram() const { 291 size_t CommandLine::GetSwitchCount() const {
292 return switches_.size();
293 }
294
295 void CommandLine::AppendSwitch(const std::string& switch_string) {
319 #if defined(OS_WIN) 296 #if defined(OS_WIN)
320 return FilePath(program_); 297 command_line_string_.append(L" ");
321 #else 298 command_line_string_.append(kSwitchPrefixes[0] + ASCIIToWide(switch_string));
322 DCHECK_GT(argv_.size(), 0U); 299 switches_[switch_string] = L"";
323 return FilePath(argv_[0]); 300 #elif defined(OS_POSIX)
301 argv_.push_back(kSwitchPrefixes[0] + switch_string);
302 switches_[switch_string] = "";
324 #endif 303 #endif
325 } 304 }
326 305
327 #if defined(OS_POSIX) 306 void CommandLine::AppendSwitchPath(const std::string& switch_string,
328 std::string CommandLine::command_line_string() const { 307 const FilePath& path) {
329 return JoinString(argv_, ' '); 308 AppendSwitchNative(switch_string, path.value());
330 }
331 #endif
332
333 #if defined(OS_WIN)
334 void CommandLine::AppendSwitch(const std::string& switch_string) {
335 command_line_string_.append(L" ");
336 command_line_string_.append(kSwitchPrefixes[0] + ASCIIToWide(switch_string));
337 switches_[switch_string] = L"";
338 } 309 }
339 310
340 void CommandLine::AppendSwitchNative(const std::string& switch_string, 311 void CommandLine::AppendSwitchNative(const std::string& switch_string,
341 const std::wstring& value) { 312 const CommandLine::StringType& value) {
342 std::wstring combined_switch_string = 313 #if defined(OS_WIN)
314 StringType combined_switch_string =
343 kSwitchPrefixes[0] + ASCIIToWide(switch_string); 315 kSwitchPrefixes[0] + ASCIIToWide(switch_string);
344 if (!value.empty()) 316 if (!value.empty())
345 combined_switch_string += kSwitchValueSeparator + WindowsStyleQuote(value); 317 combined_switch_string += kSwitchValueSeparator + WindowsStyleQuote(value);
346 318
347 command_line_string_.append(L" "); 319 command_line_string_.append(L" ");
348 command_line_string_.append(combined_switch_string); 320 command_line_string_.append(combined_switch_string);
349 321
350 switches_[switch_string] = value; 322 switches_[switch_string] = value;
323 #elif defined(OS_POSIX)
324 StringType combined_switch_string = kSwitchPrefixes[0] + switch_string;
325 if (!value.empty())
326 combined_switch_string += kSwitchValueSeparator + value;
327 argv_.push_back(combined_switch_string);
328 switches_[switch_string] = value;
329 #endif
351 } 330 }
352 331
353 void CommandLine::AppendSwitchASCII(const std::string& switch_string, 332 void CommandLine::AppendSwitchASCII(const std::string& switch_string,
354 const std::string& value_string) { 333 const std::string& value_string) {
334 #if defined(OS_WIN)
355 AppendSwitchNative(switch_string, ASCIIToWide(value_string)); 335 AppendSwitchNative(switch_string, ASCIIToWide(value_string));
336 #elif defined(OS_POSIX)
337 AppendSwitchNative(switch_string, value_string);
338 #endif
339 }
340
341 void CommandLine::AppendSwitches(const CommandLine& other) {
342 SwitchMap::const_iterator i;
343 for (i = other.switches_.begin(); i != other.switches_.end(); ++i)
344 AppendSwitchNative(i->first, i->second);
345 }
346
347 void CommandLine::CopySwitchesFrom(const CommandLine& source,
348 const char* const switches[],
349 size_t count) {
350 for (size_t i = 0; i < count; ++i) {
351 if (source.HasSwitch(switches[i])) {
352 StringType value = source.GetSwitchValueNative(switches[i]);
353 AppendSwitchNative(switches[i], value);
354 }
355 }
356 } 356 }
357 357
358 void CommandLine::AppendArg(const std::string& value) { 358 void CommandLine::AppendArg(const std::string& value) {
359 #if defined(OS_WIN)
359 DCHECK(IsStringUTF8(value)); 360 DCHECK(IsStringUTF8(value));
360 AppendArgNative(UTF8ToWide(value)); 361 AppendArgNative(UTF8ToWide(value));
362 #elif defined(OS_POSIX)
363 AppendArgNative(value);
364 #endif
361 } 365 }
362 366
363 void CommandLine::AppendArgNative(const std::wstring& value) { 367 void CommandLine::AppendArgPath(const FilePath& path) {
368 AppendArgNative(path.value());
369 }
370
371 void CommandLine::AppendArgNative(const CommandLine::StringType& value) {
372 #if defined(OS_WIN)
364 command_line_string_.append(L" "); 373 command_line_string_.append(L" ");
365 command_line_string_.append(WindowsStyleQuote(value)); 374 command_line_string_.append(WindowsStyleQuote(value));
366 args_.push_back(value); 375 args_.push_back(value);
376 #elif defined(OS_POSIX)
377 DCHECK(IsStringUTF8(value));
378 argv_.push_back(value);
379 #endif
380 }
381
382 void CommandLine::AppendArgs(const CommandLine& other) {
383 if(other.args_.size() <= 0)
384 return;
385 #if defined(OS_WIN)
386 command_line_string_.append(L" --");
387 #endif // OS_WIN
388 StringVector::const_iterator i;
389 for (i = other.args_.begin(); i != other.args_.end(); ++i)
390 AppendArgNative(*i);
367 } 391 }
368 392
369 void CommandLine::AppendArguments(const CommandLine& other, 393 void CommandLine::AppendArguments(const CommandLine& other,
370 bool include_program) { 394 bool include_program) {
395 #if defined(OS_WIN)
371 // Verify include_program is used correctly. 396 // Verify include_program is used correctly.
372 DCHECK(!include_program || !other.GetProgram().empty()); 397 DCHECK(!include_program || !other.GetProgram().empty());
373 if (include_program) 398 if (include_program)
374 program_ = other.program_; 399 program_ = other.program_;
375 400
376 if (!command_line_string_.empty()) 401 if (!command_line_string_.empty())
377 command_line_string_ += L' '; 402 command_line_string_ += L' ';
378 403
379 command_line_string_ += other.command_line_string_; 404 command_line_string_ += other.command_line_string_;
380
381 std::map<std::string, StringType>::const_iterator i;
382 for (i = other.switches_.begin(); i != other.switches_.end(); ++i)
383 switches_[i->first] = i->second;
384 }
385
386 void CommandLine::PrependWrapper(const std::wstring& wrapper) {
387 if (wrapper.empty())
388 return;
389 // The wrapper may have embedded arguments (like "gdb --args"). In this case,
390 // we don't pretend to do anything fancy, we just split on spaces.
391 std::vector<std::wstring> wrapper_and_args;
392 base::SplitString(wrapper, ' ', &wrapper_and_args);
393 program_ = wrapper_and_args[0];
394 command_line_string_ = wrapper + L" " + command_line_string_;
395 }
396
397 #elif defined(OS_POSIX) 405 #elif defined(OS_POSIX)
398 void CommandLine::AppendSwitch(const std::string& switch_string) {
399 argv_.push_back(kSwitchPrefixes[0] + switch_string);
400 switches_[switch_string] = "";
401 }
402
403 void CommandLine::AppendSwitchNative(const std::string& switch_string,
404 const std::string& value) {
405 std::string combined_switch_string = kSwitchPrefixes[0] + switch_string;
406 if (!value.empty())
407 combined_switch_string += kSwitchValueSeparator + value;
408 argv_.push_back(combined_switch_string);
409 switches_[switch_string] = value;
410 }
411
412 void CommandLine::AppendSwitchASCII(const std::string& switch_string,
413 const std::string& value_string) {
414 AppendSwitchNative(switch_string, value_string);
415 }
416
417 void CommandLine::AppendArg(const std::string& value) {
418 AppendArgNative(value);
419 }
420
421 void CommandLine::AppendArgNative(const std::string& value) {
422 DCHECK(IsStringUTF8(value));
423 argv_.push_back(value);
424 }
425
426 void CommandLine::AppendArguments(const CommandLine& other,
427 bool include_program) {
428 // Verify include_program is used correctly. 406 // Verify include_program is used correctly.
429 // Logic could be shorter but this is clearer. 407 // Logic could be shorter but this is clearer.
430 DCHECK_EQ(include_program, !other.GetProgram().empty()); 408 DCHECK_EQ(include_program, !other.GetProgram().empty());
431 409
432 if (include_program) 410 if (include_program)
433 argv_[0] = other.argv_[0]; 411 argv_[0] = other.argv_[0];
434 412
435 // Skip the first arg when copying since it's the program but push all 413 // Skip the first arg when copying since it's the program but push all
436 // arguments to our arg vector. 414 // arguments to our arg vector.
437 for (size_t i = 1; i < other.argv_.size(); ++i) 415 for (size_t i = 1; i < other.argv_.size(); ++i)
438 argv_.push_back(other.argv_[i]); 416 argv_.push_back(other.argv_[i]);
417 #endif
439 418
440 std::map<std::string, StringType>::const_iterator i; 419 SwitchMap::const_iterator i;
441 for (i = other.switches_.begin(); i != other.switches_.end(); ++i) 420 for (i = other.switches_.begin(); i != other.switches_.end(); ++i)
442 switches_[i->first] = i->second; 421 switches_[i->first] = i->second;
443 } 422 }
444 423
445 void CommandLine::PrependWrapper(const std::string& wrapper) { 424 void CommandLine::PrependWrapper(const CommandLine::StringType& wrapper) {
446 // The wrapper may have embedded arguments (like "gdb --args"). In this case, 425 // The wrapper may have embedded arguments (like "gdb --args"). In this case,
447 // we don't pretend to do anything fancy, we just split on spaces. 426 // we don't pretend to do anything fancy, we just split on spaces.
448 std::vector<std::string> wrapper_and_args; 427 if (wrapper.empty())
428 return;
429 StringVector wrapper_and_args;
430 #if defined(OS_WIN)
431 base::SplitString(wrapper, ' ', &wrapper_and_args);
432 program_ = wrapper_and_args[0];
433 command_line_string_ = wrapper + L" " + command_line_string_;
434 #elif defined(OS_POSIX)
449 base::SplitString(wrapper, ' ', &wrapper_and_args); 435 base::SplitString(wrapper, ' ', &wrapper_and_args);
450 argv_.insert(argv_.begin(), wrapper_and_args.begin(), wrapper_and_args.end()); 436 argv_.insert(argv_.begin(), wrapper_and_args.begin(), wrapper_and_args.end());
437 #endif
451 } 438 }
452 439
453 #endif 440 #if defined(OS_WIN)
441 void CommandLine::ParseFromString(const std::wstring& command_line) {
442 TrimWhitespace(command_line, TRIM_ALL, &command_line_string_);
454 443
455 void CommandLine::AppendSwitchPath(const std::string& switch_string, 444 if (command_line_string_.empty())
456 const FilePath& path) {
457 AppendSwitchNative(switch_string, path.value());
458 }
459
460 void CommandLine::AppendSwitches(const CommandLine& other) {
461 std::map<std::string, StringType>::const_iterator i;
462 for (i = other.switches_.begin(); i != other.switches_.end(); ++i)
463 AppendSwitchNative(i->first, i->second);
464 }
465
466 void CommandLine::AppendArgPath(const FilePath& path) {
467 AppendArgNative(path.value());
468 }
469
470 void CommandLine::AppendArgs(const CommandLine& other) {
471 if(other.args_.size() <= 0)
472 return; 445 return;
473 446
474 #if defined(OS_WIN) 447 int num_args = 0;
475 command_line_string_.append(L" --"); 448 wchar_t** args = NULL;
476 #endif // OS_WIN
477 std::vector<StringType>::const_iterator i;
478 for (i = other.args_.begin(); i != other.args_.end(); ++i)
479 AppendArgNative(*i);
480 }
481 449
482 void CommandLine::CopySwitchesFrom(const CommandLine& source, 450 args = CommandLineToArgvW(command_line_string_.c_str(), &num_args);
483 const char* const switches[], 451
484 size_t count) { 452 // Populate program_ with the trimmed version of the first arg.
485 for (size_t i = 0; i < count; ++i) { 453 TrimWhitespace(args[0], TRIM_ALL, &program_);
486 if (source.HasSwitch(switches[i])) { 454
487 StringType value = source.GetSwitchValueNative(switches[i]); 455 bool parse_switches = true;
488 AppendSwitchNative(switches[i], value); 456 for (int i = 1; i < num_args; ++i) {
457 std::wstring arg;
458 TrimWhitespace(args[i], TRIM_ALL, &arg);
459
460 if (!parse_switches) {
461 args_.push_back(arg);
462 continue;
463 }
464
465 if (arg == kSwitchTerminator) {
466 parse_switches = false;
467 continue;
468 }
469
470 std::string switch_string;
471 std::wstring switch_value;
472 if (IsSwitch(arg, &switch_string, &switch_value)) {
473 switches_[switch_string] = switch_value;
474 } else {
475 args_.push_back(arg);
489 } 476 }
490 } 477 }
478
479 if (args)
480 LocalFree(args);
491 } 481 }
492 482 #endif
493 // private
494 CommandLine::CommandLine() {
495 }
496
497 // static
498 CommandLine* CommandLine::ForCurrentProcessMutable() {
499 DCHECK(current_process_commandline_);
500 return current_process_commandline_;
501 }
OLDNEW
« no previous file with comments | « base/command_line.h ('k') | chrome/test/in_process_browser_test.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698