diff options
author | Andy Schwerin <schwerin@10gen.com> | 2012-12-04 15:15:40 -0500 |
---|---|---|
committer | Andy Schwerin <schwerin@10gen.com> | 2012-12-04 18:29:00 -0500 |
commit | 0753b2b2a5ed8e70763d50e6945aea72f0e9f372 (patch) | |
tree | b79f0e16309af25735d7506068ed1f066cd59ca2 | |
parent | ed810cab19d462ae99c07c40ee976fd680435245 (diff) | |
download | mongo-0753b2b2a5ed8e70763d50e6945aea72f0e9f372.tar.gz |
SERVER-7252 Introduce and test function for building a Windows command line from an argument vector.
-rw-r--r-- | src/mongo/SConscript | 2 | ||||
-rw-r--r-- | src/mongo/util/text.cpp | 48 | ||||
-rw-r--r-- | src/mongo/util/text.h | 9 | ||||
-rw-r--r-- | src/mongo/util/text_test.cpp | 59 |
4 files changed, 118 insertions, 0 deletions
diff --git a/src/mongo/SConscript b/src/mongo/SConscript index 9f9f8ff0f3f..da38faaded6 100644 --- a/src/mongo/SConscript +++ b/src/mongo/SConscript @@ -41,6 +41,8 @@ env.StaticLibrary('foundation', '$BUILD_DIR/third_party/shim_allocator', '$BUILD_DIR/third_party/shim_boost']) +env.CppUnitTest('text_test', 'util/text_test.cpp', LIBDEPS=['foundation']) + env.StaticLibrary('stringutils', ['util/stringutils.cpp', 'util/base64.cpp',]) env.StaticLibrary('md5', [ diff --git a/src/mongo/util/text.cpp b/src/mongo/util/text.cpp index 1c587b6d303..1c075773177 100644 --- a/src/mongo/util/text.cpp +++ b/src/mongo/util/text.cpp @@ -18,6 +18,8 @@ #include "pch.h" #include <boost/smart_ptr/scoped_array.hpp> +#include <sstream> + #ifdef _WIN32 #include <io.h> #endif @@ -299,5 +301,51 @@ namespace mongo { #endif // #if defined(_WIN32) + // See "Parsing C++ Command-Line Arguments (C++)" + // http://msdn.microsoft.com/en-us/library/windows/desktop/17w5ykft(v=vs.85).aspx + static void quoteForWindowsCommandLine(const std::string& arg, std::ostream& os) { + if (arg.find_first_of(" \t\"") == std::string::npos) { + os << arg; + } + else { + os << '"'; + std::string backslashes = ""; + for (std::string::const_iterator iter = arg.begin(), end = arg.end(); + iter != end; ++iter) { + + switch (*iter) { + case '\\': + backslashes.push_back(*iter); + if (iter + 1 == end) + os << backslashes << backslashes; + break; + case '"': + os << backslashes << backslashes << "\\\""; + break; + default: + os << backslashes << *iter; + backslashes.clear(); + break; + } + } + os << '"'; + } + } + + std::string constructUtf8WindowsCommandLine(const std::vector<std::string>& argv) { + if (argv.empty()) + return ""; + + std::ostringstream commandLine; + std::vector<std::string>::const_iterator iter = argv.begin(); + std::vector<std::string>::const_iterator end = argv.end(); + quoteForWindowsCommandLine(*iter, commandLine); + ++iter; + for (; iter != end; ++iter) { + commandLine << ' '; + quoteForWindowsCommandLine(*iter, commandLine); + } + return commandLine.str(); + } } diff --git a/src/mongo/util/text.h b/src/mongo/util/text.h index 148f0d2e2d6..0cca26968d0 100644 --- a/src/mongo/util/text.h +++ b/src/mongo/util/text.h @@ -89,4 +89,13 @@ namespace mongo { #endif // #if defined(_WIN32) + /** + * Construct a Windows command line string, UTF-8 encoded, from a vector of + * UTF-8 arguments, "argv". + * + * See "Parsing C++ Command-Line Arguments (C++)" + * http://msdn.microsoft.com/en-us/library/windows/desktop/17w5ykft(v=vs.85).aspx + */ + std::string constructUtf8WindowsCommandLine(const std::vector<std::string>& argv); + } // namespace mongo diff --git a/src/mongo/util/text_test.cpp b/src/mongo/util/text_test.cpp new file mode 100644 index 00000000000..bea19e8c3c0 --- /dev/null +++ b/src/mongo/util/text_test.cpp @@ -0,0 +1,59 @@ +/* + * Copyright 2012 10gen Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <cstdarg> +#include <string> +#include <vector> + +#include "mongo/unittest/unittest.h" +#include "mongo/util/text.h" + +using namespace mongo; + +static std::vector<std::string> svec(const char* first, ...) { + std::vector<std::string> result; + if (first) { + result.push_back(first); + va_list ap; + va_start(ap, first); + const char* curr; + while (NULL != (curr = va_arg(ap, const char*))) { + result.push_back(curr); + } + va_end(ap); + } + return result; +} + +TEST(WindowsCommandLineConstruction, EmptyCommandLine) { + ASSERT_EQUALS("", constructUtf8WindowsCommandLine(svec(NULL))); +} + +TEST(WindowsCommandLineConstruction, NothingToQuote) { + ASSERT_EQUALS("abc d e", + constructUtf8WindowsCommandLine(svec("abc", "d", "e", NULL))); +} + +TEST(WindowsCommandLineConstruction, ThingsToQuote) { + ASSERT_EQUALS("a\\\\\\b \"de fg\" h", + constructUtf8WindowsCommandLine(svec("a\\\\\\b", "de fg", "h", NULL))); + ASSERT_EQUALS("\"a\\\\b c\" d e", + constructUtf8WindowsCommandLine(svec("a\\\\b c", "d" , "e", NULL))); + ASSERT_EQUALS("\"a \\\\\" \\", + constructUtf8WindowsCommandLine(svec("a \\", "\\", NULL))); + ASSERT_EQUALS("\"\\\\\\\\\\\"\"", + constructUtf8WindowsCommandLine(svec("\\\\\"", NULL))); +} |