summaryrefslogtreecommitdiffstats
path: root/base/command_line.cc
diff options
context:
space:
mode:
authorinitial.commit <initial.commit@0039d316-1c4b-4281-b951-d872f2087c98>2008-07-26 21:49:38 +0000
committerinitial.commit <initial.commit@0039d316-1c4b-4281-b951-d872f2087c98>2008-07-26 21:49:38 +0000
commitd7cae12696b96500c05dd2d430f6238922c20c96 (patch)
treeecff27b367735535b2a66477f8cd89d3c462a6c0 /base/command_line.cc
parentee2815e28d408216cf94e874825b6bcf76c69083 (diff)
downloadchromium_src-d7cae12696b96500c05dd2d430f6238922c20c96.zip
chromium_src-d7cae12696b96500c05dd2d430f6238922c20c96.tar.gz
chromium_src-d7cae12696b96500c05dd2d430f6238922c20c96.tar.bz2
Add base to the repository.
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@8 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'base/command_line.cc')
-rw-r--r--base/command_line.cc246
1 files changed, 246 insertions, 0 deletions
diff --git a/base/command_line.cc b/base/command_line.cc
new file mode 100644
index 0000000..7755578
--- /dev/null
+++ b/base/command_line.cc
@@ -0,0 +1,246 @@
+// Copyright 2008, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include <windows.h>
+#include <shellapi.h>
+
+#include <algorithm>
+
+#include "base/command_line.h"
+
+#include "base/logging.h"
+#include "base/singleton.h"
+#include "base/string_util.h"
+
+using namespace std;
+
+// Since we use a lazy match, make sure that longer versions (like L"--")
+// are listed before shorter versions (like L"-") of similar prefixes.
+const wchar_t* const CommandLine::kSwitchPrefixes[] = {L"--", L"-", L"/"};
+
+const wchar_t CommandLine::kSwitchValueSeparator[] = L"=";
+
+static void Lowercase(wstring* parameter) {
+ transform(parameter->begin(), parameter->end(), parameter->begin(), tolower);
+}
+
+// CommandLine::Data
+//
+// This object holds the parsed data for a command line. We hold this in a
+// separate object from |CommandLine| so that we can share the parsed data
+// across multiple |CommandLine| objects. When we share |Data|, we might be
+// accessing this object on multiple threads. To ensure thread safety, the
+// public interface of this object is const only.
+//
+// Do NOT add any non-const methods to this object. You have been warned.
+class CommandLine::Data {
+ public:
+ Data() {
+ Init(GetCommandLineW());
+ }
+
+ Data(const wstring& command_line) {
+ Init(command_line);
+ }
+
+ const std::wstring& command_line_string() const {
+ return command_line_string_;
+ }
+
+ const std::wstring& program() const {
+ return program_;
+ }
+
+ const std::map<std::wstring, std::wstring>& switches() const {
+ return switches_;
+ }
+
+ const std::vector<std::wstring>& loose_values() const {
+ return loose_values_;
+ }
+
+ private:
+ // Returns true if parameter_string represents a switch. If true,
+ // switch_string and switch_value are set. (If false, both are
+ // set to the empty string.)
+ static bool IsSwitch(const wstring& parameter_string,
+ wstring* switch_string,
+ wstring* switch_value) {
+
+ *switch_string = L"";
+ *switch_value = L"";
+
+ for (size_t i = 0; i < arraysize(kSwitchPrefixes); ++i) {
+ std::wstring prefix(kSwitchPrefixes[i]);
+ if (parameter_string.find(prefix) != 0) // check prefix
+ continue;
+
+ const size_t switch_start = prefix.length();
+ const size_t equals_position = parameter_string.find(
+ kSwitchValueSeparator, switch_start);
+ if (equals_position == wstring::npos) {
+ *switch_string = parameter_string.substr(switch_start);
+ } else {
+ *switch_string = parameter_string.substr(
+ switch_start, equals_position - switch_start);
+ *switch_value = parameter_string.substr(equals_position + 1);
+ }
+ Lowercase(switch_string);
+
+ return true;
+ }
+
+ return false;
+ }
+
+ // Does the actual parsing of the command line.
+ void Init(const std::wstring& command_line) {
+ TrimWhitespace(command_line, TRIM_ALL, &command_line_string_);
+
+ if (command_line_string_.empty())
+ return;
+
+ int num_args = 0;
+ wchar_t** args = NULL;
+
+ args = CommandLineToArgvW(command_line_string_.c_str(), &num_args);
+
+ // Populate program_ with the trimmed version of the first arg.
+ TrimWhitespace(args[0], TRIM_ALL, &program_);
+
+ for (int i = 1; i < num_args; ++i) {
+ wstring arg;
+ TrimWhitespace(args[i], TRIM_ALL, &arg);
+
+ wstring switch_string;
+ wstring switch_value;
+ if (IsSwitch(arg, &switch_string, &switch_value)) {
+ switches_[switch_string] = switch_value;
+ } else {
+ loose_values_.push_back(arg);
+ }
+ }
+
+ if (args)
+ LocalFree(args);
+ }
+
+ std::wstring command_line_string_;
+ std::wstring program_;
+ std::map<std::wstring, std::wstring> switches_;
+ std::vector<std::wstring> loose_values_;
+
+ DISALLOW_EVIL_CONSTRUCTORS(CommandLine::Data);
+};
+
+CommandLine::CommandLine()
+ : we_own_data_(false), // The Singleton class will manage it for us.
+ data_(Singleton<Data>::get()) {
+}
+
+CommandLine::CommandLine(const wstring& command_line)
+ : we_own_data_(true),
+ data_(new Data(command_line)) {
+}
+
+CommandLine::~CommandLine() {
+ if (we_own_data_)
+ delete data_;
+}
+
+bool CommandLine::HasSwitch(const wstring& switch_string) const {
+ wstring lowercased_switch(switch_string);
+ Lowercase(&lowercased_switch);
+ return data_->switches().find(lowercased_switch) != data_->switches().end();
+}
+
+wstring CommandLine::GetSwitchValue(const wstring& switch_string) const {
+ wstring lowercased_switch(switch_string);
+ Lowercase(&lowercased_switch);
+
+ const map<wstring, wstring>::const_iterator result =
+ data_->switches().find(lowercased_switch);
+
+ if (result == data_->switches().end()) {
+ return L"";
+ } else {
+ return result->second;
+ }
+}
+
+size_t CommandLine::GetLooseValueCount() const {
+ return data_->loose_values().size();
+}
+
+CommandLine::LooseValueIterator CommandLine::GetLooseValuesBegin() const {
+ return data_->loose_values().begin();
+}
+
+CommandLine::LooseValueIterator CommandLine::GetLooseValuesEnd() const {
+ return data_->loose_values().end();
+}
+
+std::wstring CommandLine::command_line_string() const {
+ return data_->command_line_string();
+}
+
+std::wstring CommandLine::program() const {
+ return data_->program();
+}
+
+// static
+void CommandLine::AppendSwitch(wstring* command_line_string,
+ const wstring& switch_string) {
+ DCHECK(command_line_string);
+ command_line_string->append(L" ");
+ command_line_string->append(kSwitchPrefixes[0]);
+ command_line_string->append(switch_string);
+}
+
+// static
+void CommandLine::AppendSwitchWithValue(wstring* command_line_string,
+ const wstring& switch_string,
+ const wstring& value_string) {
+ AppendSwitch(command_line_string, switch_string);
+
+ if (value_string.empty())
+ return;
+
+ command_line_string->append(kSwitchValueSeparator);
+ // NOTE(jhughes): If the value contains a quotation mark at one
+ // end but not both, you may get unusable output.
+ if ((value_string.find(L" ") != std::wstring::npos) &&
+ (value_string[0] != L'"') &&
+ (value_string[value_string.length() - 1] != L'"')) {
+ // need to provide quotes
+ StringAppendF(command_line_string, L"\"%s\"", value_string.c_str());
+ } else {
+ command_line_string->append(value_string);
+ }
+}