Skip to content

Commit

Permalink
SERVER-7252 Introduce and test function for building a Windows comman…
Browse files Browse the repository at this point in the history
…d line from an argument vector.
  • Loading branch information
Andy Schwerin committed Dec 4, 2012
1 parent ed810ca commit 0753b2b
Show file tree
Hide file tree
Showing 4 changed files with 118 additions and 0 deletions.
2 changes: 2 additions & 0 deletions src/mongo/SConscript
Original file line number Diff line number Diff line change
Expand Up @@ -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', [
Expand Down
48 changes: 48 additions & 0 deletions src/mongo/util/text.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@
#include "pch.h"

#include <boost/smart_ptr/scoped_array.hpp>
#include <sstream>

#ifdef _WIN32
#include <io.h>
#endif
Expand Down Expand Up @@ -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();
}
}

9 changes: 9 additions & 0 deletions src/mongo/util/text.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
59 changes: 59 additions & 0 deletions src/mongo/util/text_test.cpp
Original file line number Diff line number Diff line change
@@ -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)));
}

0 comments on commit 0753b2b

Please sign in to comment.