diff options
author | initial.commit <initial.commit@0039d316-1c4b-4281-b951-d872f2087c98> | 2008-07-26 21:49:38 +0000 |
---|---|---|
committer | initial.commit <initial.commit@0039d316-1c4b-4281-b951-d872f2087c98> | 2008-07-26 21:49:38 +0000 |
commit | d7cae12696b96500c05dd2d430f6238922c20c96 (patch) | |
tree | ecff27b367735535b2a66477f8cd89d3c462a6c0 /base/command_line.cc | |
parent | ee2815e28d408216cf94e874825b6bcf76c69083 (diff) | |
download | chromium_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.cc | 246 |
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); + } +} |