summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndy Schwerin <schwerin@10gen.com>2012-12-04 15:15:40 -0500
committerAndy Schwerin <schwerin@10gen.com>2012-12-04 18:29:00 -0500
commit0753b2b2a5ed8e70763d50e6945aea72f0e9f372 (patch)
treeb79f0e16309af25735d7506068ed1f066cd59ca2
parented810cab19d462ae99c07c40ee976fd680435245 (diff)
downloadmongo-0753b2b2a5ed8e70763d50e6945aea72f0e9f372.tar.gz
SERVER-7252 Introduce and test function for building a Windows command line from an argument vector.
-rw-r--r--src/mongo/SConscript2
-rw-r--r--src/mongo/util/text.cpp48
-rw-r--r--src/mongo/util/text.h9
-rw-r--r--src/mongo/util/text_test.cpp59
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)));
+}