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

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
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 CommandLine::StringType WindowsStyleQuote(const CommandLine::StringType& arg) {
evanm 2011/02/28 21:04:19 Here's another case where I think the typedef make
msw 2011/02/28 23:44:47 Reverted for now; will become string16 in another
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" \\\"") == CommandLine::StringType::npos) {
59 // No quoting necessary. 57 // No quoting necessary.
60 return arg; 58 return arg;
61 } 59 }
62 60
63 std::wstring out; 61 CommandLine::StringType out;
64 out.push_back(L'"'); 62 out.push_back(L'"');
65 for (size_t i = 0; i < arg.size(); ++i) { 63 for (size_t i = 0; i < arg.size(); ++i) {
66 if (arg[i] == '\\') { 64 if (arg[i] == '\\') {
67 // Find the extent of this run of backslashes. 65 // Find the extent of this run of backslashes.
68 size_t start = i, end = start + 1; 66 size_t start = i, end = start + 1;
69 for (; end < arg.size() && arg[end] == '\\'; ++end) 67 for (; end < arg.size() && arg[end] == '\\'; ++end)
70 /* empty */; 68 /* empty */;
71 size_t backslash_count = end - start; 69 size_t backslash_count = end - start;
72 70
73 // Backslashes are escapes only if the run is followed by a double quote. 71 // Backslashes are escapes only if the run is followed by a double quote.
(...skipping 12 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;
100 } 131 }
101 132
102 #if defined(OS_WIN) 133 } // namespace
134
103 CommandLine::CommandLine(NoProgram no_program) { 135 CommandLine::CommandLine(NoProgram no_program) {
104 } 136 #if defined(OS_POSIX)
105 137 // Push an empty argument, because we always assume argv_[0] is a program.
106 void CommandLine::ParseFromString(const std::wstring& command_line) { 138 argv_.push_back("");
107 TrimWhitespace(command_line, TRIM_ALL, &command_line_string_); 139 #endif
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
149 CommandLine CommandLine::FromString(const std::wstring& command_line) {
150 CommandLine cmd;
151 cmd.ParseFromString(command_line);
152 return cmd;
153 } 140 }
154 141
155 CommandLine::CommandLine(const FilePath& program) { 142 CommandLine::CommandLine(const FilePath& program) {
143 #if defined(OS_WIN)
156 if (!program.empty()) { 144 if (!program.empty()) {
157 program_ = program.value(); 145 program_ = program.value();
158 // TODO(evanm): proper quoting here. 146 // TODO(evanm): proper quoting here.
159 command_line_string_ = L'"' + program.value() + L'"'; 147 command_line_string_ = L'"' + program.value() + L'"';
160 } 148 }
149 #elif defined(OS_POSIX)
150 argv_.push_back(program.value());
151 #endif
161 } 152 }
162 153
163 #elif defined(OS_POSIX) 154 #if 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) { 155 CommandLine::CommandLine(int argc, const char* const* argv) {
170 InitFromArgv(argc, argv); 156 InitFromArgv(argc, argv);
171 } 157 }
172 158
173 CommandLine::CommandLine(const std::vector<std::string>& argv) { 159 CommandLine::CommandLine(const StringVector& argv) {
174 InitFromArgv(argv); 160 InitFromArgv(argv);
175 } 161 }
162 #endif // OS_POSIX
176 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_;
186 }
187
188 #if defined(OS_WIN)
189 // static
190 CommandLine CommandLine::FromString(
191 const CommandLine::StringType& command_line) {
192 CommandLine cmd;
193 cmd.ParseFromString(command_line);
194 return cmd;
195 }
196 #endif // OS_WIN
197
198 #if defined(OS_POSIX)
177 void CommandLine::InitFromArgv(int argc, const char* const* argv) { 199 void CommandLine::InitFromArgv(int argc, const char* const* argv) {
178 for (int i = 0; i < argc; ++i) 200 for (int i = 0; i < argc; ++i)
179 argv_.push_back(argv[i]); 201 argv_.push_back(argv[i]);
180 InitFromArgv(argv_); 202 InitFromArgv(argv_);
181 } 203 }
182 204
183 void CommandLine::InitFromArgv(const std::vector<std::string>& argv) { 205 void CommandLine::InitFromArgv(const StringVector& argv) {
184 argv_ = argv; 206 argv_ = argv;
185 bool parse_switches = true; 207 bool parse_switches = true;
186 for (size_t i = 1; i < argv_.size(); ++i) { 208 for (size_t i = 1; i < argv_.size(); ++i) {
187 const std::string& arg = argv_[i]; 209 const std::string& arg = argv_[i];
188 210
189 if (!parse_switches) { 211 if (!parse_switches) {
190 args_.push_back(arg); 212 args_.push_back(arg);
191 continue; 213 continue;
192 } 214 }
193 215
194 if (arg == kSwitchTerminator) { 216 if (arg == kSwitchTerminator) {
195 parse_switches = false; 217 parse_switches = false;
196 continue; 218 continue;
197 } 219 }
198 220
199 std::string switch_string; 221 std::string switch_string;
200 std::string switch_value; 222 StringType switch_value;
201 if (IsSwitch(arg, &switch_string, &switch_value)) { 223 if (IsSwitch(arg, &switch_string, &switch_value)) {
202 switches_[switch_string] = switch_value; 224 switches_[switch_string] = switch_value;
203 } else { 225 } else {
204 args_.push_back(arg); 226 args_.push_back(arg);
205 } 227 }
206 } 228 }
207 } 229 }
230 #endif // OS_POSIX
208 231
209 CommandLine::CommandLine(const FilePath& program) { 232 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) 233 #if defined(OS_WIN)
239 *switch_string = WideToASCII(switch_native); 234 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) 235 #elif defined(OS_POSIX)
258 current_process_commandline_->InitFromArgv(argc, argv); 236 return JoinString(argv_, ' ');
259 #endif 237 #endif
260 } 238 }
261 239
262 void CommandLine::Reset() { 240 FilePath CommandLine::GetProgram() const {
263 DCHECK(current_process_commandline_ != NULL); 241 #if defined(OS_WIN)
264 delete current_process_commandline_; 242 return FilePath(program_);
265 current_process_commandline_ = NULL; 243 #else
266 } 244 DCHECK_GT(argv_.size(), 0U);
267 245 return FilePath(argv_[0]);
268 // static 246 #endif
269 CommandLine* CommandLine::ForCurrentProcess() {
270 DCHECK(current_process_commandline_);
271 return current_process_commandline_;
272 } 247 }
273 248
274 bool CommandLine::HasSwitch(const std::string& switch_string) const { 249 bool CommandLine::HasSwitch(const std::string& switch_string) const {
275 std::string lowercased_switch(switch_string); 250 std::string lowercased_switch(switch_string);
276 #if defined(OS_WIN) 251 #if defined(OS_WIN)
277 Lowercase(&lowercased_switch); 252 Lowercase(&lowercased_switch);
278 #endif 253 #endif
279 return switches_.find(lowercased_switch) != switches_.end(); 254 return switches_.find(lowercased_switch) != switches_.end();
280 } 255 }
281 256
(...skipping 16 matching lines...) Expand all
298 return FilePath(GetSwitchValueNative(switch_string)); 273 return FilePath(GetSwitchValueNative(switch_string));
299 } 274 }
300 275
301 CommandLine::StringType CommandLine::GetSwitchValueNative( 276 CommandLine::StringType CommandLine::GetSwitchValueNative(
302 const std::string& switch_string) const { 277 const std::string& switch_string) const {
303 std::string lowercased_switch(switch_string); 278 std::string lowercased_switch(switch_string);
304 #if defined(OS_WIN) 279 #if defined(OS_WIN)
305 Lowercase(&lowercased_switch); 280 Lowercase(&lowercased_switch);
306 #endif 281 #endif
307 282
308 std::map<std::string, StringType>::const_iterator result = 283 SwitchMap::const_iterator result = switches_.find(lowercased_switch);
309 switches_.find(lowercased_switch);
310 284
311 if (result == switches_.end()) { 285 if (result == switches_.end()) {
312 return CommandLine::StringType(); 286 return CommandLine::StringType();
313 } else { 287 } else {
314 return result->second; 288 return result->second;
315 } 289 }
316 } 290 }
317 291
318 FilePath CommandLine::GetProgram() const { 292 size_t CommandLine::GetSwitchCount() const {
293 return switches_.size();
294 }
295
296 void CommandLine::AppendSwitch(const std::string& switch_string) {
319 #if defined(OS_WIN) 297 #if defined(OS_WIN)
320 return FilePath(program_); 298 command_line_string_.append(L" ");
321 #else 299 command_line_string_.append(kSwitchPrefixes[0] + ASCIIToWide(switch_string));
322 DCHECK_GT(argv_.size(), 0U); 300 switches_[switch_string] = L"";
323 return FilePath(argv_[0]); 301 #elif defined(OS_POSIX)
302 argv_.push_back(kSwitchPrefixes[0] + switch_string);
303 switches_[switch_string] = "";
324 #endif 304 #endif
325 } 305 }
326 306
327 #if defined(OS_POSIX) 307 void CommandLine::AppendSwitchPath(const std::string& switch_string,
328 std::string CommandLine::command_line_string() const { 308 const FilePath& path) {
329 return JoinString(argv_, ' '); 309 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 } 310 }
339 311
340 void CommandLine::AppendSwitchNative(const std::string& switch_string, 312 void CommandLine::AppendSwitchNative(const std::string& switch_string,
341 const std::wstring& value) { 313 const CommandLine::StringType& value) {
342 std::wstring combined_switch_string = 314 #if defined(OS_WIN)
315 StringType combined_switch_string =
343 kSwitchPrefixes[0] + ASCIIToWide(switch_string); 316 kSwitchPrefixes[0] + ASCIIToWide(switch_string);
344 if (!value.empty()) 317 if (!value.empty())
345 combined_switch_string += kSwitchValueSeparator + WindowsStyleQuote(value); 318 combined_switch_string += kSwitchValueSeparator + WindowsStyleQuote(value);
346 319
347 command_line_string_.append(L" "); 320 command_line_string_.append(L" ");
348 command_line_string_.append(combined_switch_string); 321 command_line_string_.append(combined_switch_string);
349 322
350 switches_[switch_string] = value; 323 switches_[switch_string] = value;
324 #elif defined(OS_POSIX)
325 StringType combined_switch_string = kSwitchPrefixes[0] + switch_string;
326 if (!value.empty())
327 combined_switch_string += kSwitchValueSeparator + value;
328 argv_.push_back(combined_switch_string);
329 switches_[switch_string] = value;
330 #endif
evanm 2011/02/28 21:04:19 Is the intent that these code paths will become mo
msw 2011/02/28 23:44:47 Yes, the code will become a single cross-platform
351 } 331 }
352 332
353 void CommandLine::AppendSwitchASCII(const std::string& switch_string, 333 void CommandLine::AppendSwitchASCII(const std::string& switch_string,
354 const std::string& value_string) { 334 const std::string& value_string) {
335 #if defined(OS_WIN)
355 AppendSwitchNative(switch_string, ASCIIToWide(value_string)); 336 AppendSwitchNative(switch_string, ASCIIToWide(value_string));
337 #elif defined(OS_POSIX)
338 AppendSwitchNative(switch_string, value_string);
339 #endif
340 }
341
342 void CommandLine::AppendSwitches(const CommandLine& other) {
343 SwitchMap::const_iterator i;
344 for (i = other.switches_.begin(); i != other.switches_.end(); ++i)
345 AppendSwitchNative(i->first, i->second);
346 }
347
348 void CommandLine::CopySwitchesFrom(const CommandLine& source,
349 const char* const switches[],
350 size_t count) {
351 for (size_t i = 0; i < count; ++i) {
352 if (source.HasSwitch(switches[i])) {
353 StringType value = source.GetSwitchValueNative(switches[i]);
354 AppendSwitchNative(switches[i], value);
355 }
356 }
356 } 357 }
357 358
358 void CommandLine::AppendArg(const std::string& value) { 359 void CommandLine::AppendArg(const std::string& value) {
360 #if defined(OS_WIN)
359 DCHECK(IsStringUTF8(value)); 361 DCHECK(IsStringUTF8(value));
360 AppendArgNative(UTF8ToWide(value)); 362 AppendArgNative(UTF8ToWide(value));
363 #elif defined(OS_POSIX)
364 AppendArgNative(value);
365 #endif
361 } 366 }
362 367
363 void CommandLine::AppendArgNative(const std::wstring& value) { 368 void CommandLine::AppendArgPath(const FilePath& path) {
369 AppendArgNative(path.value());
370 }
371
372 void CommandLine::AppendArgNative(const CommandLine::StringType& value) {
373 #if defined(OS_WIN)
364 command_line_string_.append(L" "); 374 command_line_string_.append(L" ");
365 command_line_string_.append(WindowsStyleQuote(value)); 375 command_line_string_.append(WindowsStyleQuote(value));
366 args_.push_back(value); 376 args_.push_back(value);
377 #elif defined(OS_POSIX)
378 DCHECK(IsStringUTF8(value));
379 argv_.push_back(value);
380 #endif
381 }
382
383 void CommandLine::AppendArgs(const CommandLine& other) {
384 if(other.args_.size() <= 0)
385 return;
386 #if defined(OS_WIN)
387 command_line_string_.append(L" --");
388 #endif // OS_WIN
389 StringVector::const_iterator i;
390 for (i = other.args_.begin(); i != other.args_.end(); ++i)
391 AppendArgNative(*i);
367 } 392 }
368 393
369 void CommandLine::AppendArguments(const CommandLine& other, 394 void CommandLine::AppendArguments(const CommandLine& other,
370 bool include_program) { 395 bool include_program) {
396 #if defined(OS_WIN)
371 // Verify include_program is used correctly. 397 // Verify include_program is used correctly.
372 DCHECK(!include_program || !other.GetProgram().empty()); 398 DCHECK(!include_program || !other.GetProgram().empty());
373 if (include_program) 399 if (include_program)
374 program_ = other.program_; 400 program_ = other.program_;
375 401
376 if (!command_line_string_.empty()) 402 if (!command_line_string_.empty())
377 command_line_string_ += L' '; 403 command_line_string_ += L' ';
378 404
379 command_line_string_ += other.command_line_string_; 405 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) 406 #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. 407 // Verify include_program is used correctly.
429 // Logic could be shorter but this is clearer. 408 // Logic could be shorter but this is clearer.
430 DCHECK_EQ(include_program, !other.GetProgram().empty()); 409 DCHECK_EQ(include_program, !other.GetProgram().empty());
431 410
432 if (include_program) 411 if (include_program)
433 argv_[0] = other.argv_[0]; 412 argv_[0] = other.argv_[0];
434 413
435 // Skip the first arg when copying since it's the program but push all 414 // Skip the first arg when copying since it's the program but push all
436 // arguments to our arg vector. 415 // arguments to our arg vector.
437 for (size_t i = 1; i < other.argv_.size(); ++i) 416 for (size_t i = 1; i < other.argv_.size(); ++i)
438 argv_.push_back(other.argv_[i]); 417 argv_.push_back(other.argv_[i]);
418 #endif
439 419
440 std::map<std::string, StringType>::const_iterator i; 420 SwitchMap::const_iterator i;
441 for (i = other.switches_.begin(); i != other.switches_.end(); ++i) 421 for (i = other.switches_.begin(); i != other.switches_.end(); ++i)
442 switches_[i->first] = i->second; 422 switches_[i->first] = i->second;
443 } 423 }
444 424
445 void CommandLine::PrependWrapper(const std::string& wrapper) { 425 void CommandLine::PrependWrapper(const CommandLine::StringType& wrapper) {
446 // The wrapper may have embedded arguments (like "gdb --args"). In this case, 426 // 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. 427 // we don't pretend to do anything fancy, we just split on spaces.
448 std::vector<std::string> wrapper_and_args; 428 if (wrapper.empty())
429 return;
430 StringVector wrapper_and_args;
431 #if defined(OS_WIN)
432 base::SplitString(wrapper, ' ', &wrapper_and_args);
433 program_ = wrapper_and_args[0];
434 command_line_string_ = wrapper + L" " + command_line_string_;
435 #elif defined(OS_POSIX)
449 base::SplitString(wrapper, ' ', &wrapper_and_args); 436 base::SplitString(wrapper, ' ', &wrapper_and_args);
450 argv_.insert(argv_.begin(), wrapper_and_args.begin(), wrapper_and_args.end()); 437 argv_.insert(argv_.begin(), wrapper_and_args.begin(), wrapper_and_args.end());
438 #endif
451 } 439 }
452 440
453 #endif 441 #if defined(OS_WIN)
442 void CommandLine::ParseFromString(const CommandLine::StringType& command_line) {
443 TrimWhitespace(command_line, TRIM_ALL, &command_line_string_);
454 444
455 void CommandLine::AppendSwitchPath(const std::string& switch_string, 445 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; 446 return;
473 447
474 #if defined(OS_WIN) 448 int num_args = 0;
475 command_line_string_.append(L" --"); 449 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 450
482 void CommandLine::CopySwitchesFrom(const CommandLine& source, 451 args = CommandLineToArgvW(command_line_string_.c_str(), &num_args);
483 const char* const switches[], 452
484 size_t count) { 453 // Populate program_ with the trimmed version of the first arg.
485 for (size_t i = 0; i < count; ++i) { 454 TrimWhitespace(args[0], TRIM_ALL, &program_);
486 if (source.HasSwitch(switches[i])) { 455
487 StringType value = source.GetSwitchValueNative(switches[i]); 456 bool parse_switches = true;
488 AppendSwitchNative(switches[i], value); 457 for (int i = 1; i < num_args; ++i) {
458 StringType arg;
459 TrimWhitespace(args[i], TRIM_ALL, &arg);
460
461 if (!parse_switches) {
462 args_.push_back(arg);
463 continue;
464 }
465
466 if (arg == kSwitchTerminator) {
467 parse_switches = false;
468 continue;
469 }
470
471 std::string switch_string;
472 StringType switch_value;
473 if (IsSwitch(arg, &switch_string, &switch_value)) {
474 switches_[switch_string] = switch_value;
475 } else {
476 args_.push_back(arg);
489 } 477 }
490 } 478 }
479
480 if (args)
481 LocalFree(args);
491 } 482 }
492 483 #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

Powered by Google App Engine
This is Rietveld 408576698