Parse paths with boost rules when it's quoted, but use the string verbatim when it's not

pull/3225/head
AnyOldName3 3 years ago
parent 8fb0b5846e
commit 84d6de3eba

@ -88,11 +88,11 @@ std::pair<Files::PathContainer, std::vector<std::string> > CS::Editor::readConfi
boost::program_options::options_description desc("Syntax: openmw-cs <options>\nAllowed options");
desc.add_options()
("data", boost::program_options::value<Files::ReluctantPathContainer>()->default_value(Files::ReluctantPathContainer(), "data")->multitoken()->composing())
("data-local", boost::program_options::value<Files::ReluctantPathContainer::value_type>()->default_value(Files::ReluctantPathContainer::value_type(), ""))
("data", boost::program_options::value<Files::MaybeQuotedPathContainer>()->default_value(Files::MaybeQuotedPathContainer(), "data")->multitoken()->composing())
("data-local", boost::program_options::value<Files::MaybeQuotedPathContainer::value_type>()->default_value(Files::MaybeQuotedPathContainer::value_type(), ""))
("fs-strict", boost::program_options::value<bool>()->implicit_value(true)->default_value(false))
("encoding", boost::program_options::value<std::string>()->default_value("win1252"))
("resources", boost::program_options::value<Files::ReluctantPath>()->default_value(Files::ReluctantPath(), "resources"))
("resources", boost::program_options::value<Files::MaybeQuotedPath>()->default_value(Files::MaybeQuotedPath(), "resources"))
("fallback-archive", boost::program_options::value<std::vector<std::string>>()->
default_value(std::vector<std::string>(), "fallback-archive")->multitoken())
("fallback", boost::program_options::value<FallbackMap>()->default_value(FallbackMap(), "")
@ -112,7 +112,7 @@ std::pair<Files::PathContainer, std::vector<std::string> > CS::Editor::readConfi
mDocumentManager.setEncoding(ToUTF8::calculateEncoding(mEncodingName));
mFileDialog.setEncoding (QString::fromUtf8(mEncodingName.c_str()));
mDocumentManager.setResourceDir (mResources = variables["resources"].as<Files::ReluctantPath>());
mDocumentManager.setResourceDir (mResources = variables["resources"].as<Files::MaybeQuotedPath>());
if (variables["script-blacklist-use"].as<bool>())
mDocumentManager.setBlacklistedScripts (
@ -122,10 +122,10 @@ std::pair<Files::PathContainer, std::vector<std::string> > CS::Editor::readConfi
Files::PathContainer dataDirs, dataLocal;
if (!variables["data"].empty()) {
dataDirs = asPathContainer(variables["data"].as<Files::ReluctantPathContainer>());
dataDirs = asPathContainer(variables["data"].as<Files::MaybeQuotedPathContainer>());
}
Files::PathContainer::value_type local(variables["data-local"].as<Files::ReluctantPathContainer::value_type>());
Files::PathContainer::value_type local(variables["data-local"].as<Files::MaybeQuotedPathContainer::value_type>());
if (!local.empty())
dataLocal.push_back(local);

@ -56,7 +56,7 @@ bool parseOptions (int argc, char** argv, OMW::Engine& engine, Files::Configurat
{
cfgMgr.readConfiguration(variables, desc, true);
Version::Version v = Version::getOpenmwVersion(variables["resources"].as<Files::ReluctantPath>().string());
Version::Version v = Version::getOpenmwVersion(variables["resources"].as<Files::MaybeQuotedPath>().string());
getRawStdout() << v.describe() << std::endl;
return false;
}
@ -65,7 +65,7 @@ bool parseOptions (int argc, char** argv, OMW::Engine& engine, Files::Configurat
cfgMgr.readConfiguration(variables, desc);
Files::mergeComposingVariables(variables, composingVariables, desc);
Version::Version v = Version::getOpenmwVersion(variables["resources"].as<Files::ReluctantPath>().string());
Version::Version v = Version::getOpenmwVersion(variables["resources"].as<Files::MaybeQuotedPath>().string());
Log(Debug::Info) << v.describe();
engine.setGrabMouse(!variables["no-grab"].as<bool>());
@ -78,15 +78,15 @@ bool parseOptions (int argc, char** argv, OMW::Engine& engine, Files::Configurat
// directory settings
engine.enableFSStrict(variables["fs-strict"].as<bool>());
Files::PathContainer dataDirs(asPathContainer(variables["data"].as<Files::ReluctantPathContainer>()));
Files::PathContainer dataDirs(asPathContainer(variables["data"].as<Files::MaybeQuotedPathContainer>()));
Files::PathContainer::value_type local(variables["data-local"].as<Files::ReluctantPathContainer::value_type>());
Files::PathContainer::value_type local(variables["data-local"].as<Files::MaybeQuotedPathContainer::value_type>());
if (!local.empty())
dataDirs.push_back(local);
cfgMgr.processPaths(dataDirs);
engine.setResourceDir(variables["resources"].as<Files::ReluctantPath>());
engine.setResourceDir(variables["resources"].as<Files::MaybeQuotedPath>());
engine.setDataDirs(dataDirs);
// fallback archives
@ -141,7 +141,7 @@ bool parseOptions (int argc, char** argv, OMW::Engine& engine, Files::Configurat
engine.setWarningsMode (variables["script-warn"].as<int>());
engine.setScriptBlacklist (variables["script-blacklist"].as<StringsVector>());
engine.setScriptBlacklistUse (variables["script-blacklist-use"].as<bool>());
engine.setSaveGameFile (variables["load-savegame"].as<Files::ReluctantPath>().string());
engine.setSaveGameFile (variables["load-savegame"].as<Files::MaybeQuotedPath>().string());
// other settings
Fallback::Map::init(variables["fallback"].as<FallbackMap>().mMap);

@ -25,16 +25,16 @@ namespace OpenMW
("replace", bpo::value<StringsVector>()->default_value(StringsVector(), "")
->multitoken()->composing(), "settings where the values from the current source should replace those from lower-priority sources instead of being appended")
("data", bpo::value<Files::ReluctantPathContainer>()->default_value(Files::ReluctantPathContainer(), "data")
("data", bpo::value<Files::MaybeQuotedPathContainer>()->default_value(Files::MaybeQuotedPathContainer(), "data")
->multitoken()->composing(), "set data directories (later directories have higher priority)")
("data-local", bpo::value<Files::ReluctantPathContainer::value_type>()->default_value(Files::ReluctantPathContainer::value_type(), ""),
("data-local", bpo::value<Files::MaybeQuotedPathContainer::value_type>()->default_value(Files::MaybeQuotedPathContainer::value_type(), ""),
"set local data directory (highest priority)")
("fallback-archive", bpo::value<StringsVector>()->default_value(StringsVector(), "fallback-archive")
->multitoken()->composing(), "set fallback BSA archives (later archives have higher priority)")
("resources", bpo::value<Files::ReluctantPath>()->default_value(Files::ReluctantPath(), "resources"),
("resources", bpo::value<Files::MaybeQuotedPath>()->default_value(Files::MaybeQuotedPath(), "resources"),
"set resources directory")
("start", bpo::value<std::string>()->default_value(""),
@ -77,7 +77,7 @@ namespace OpenMW
("script-blacklist-use", bpo::value<bool>()->implicit_value(true)
->default_value(true), "enable script blacklisting")
("load-savegame", bpo::value<Files::ReluctantPath>()->default_value(Files::ReluctantPath(), ""),
("load-savegame", bpo::value<Files::MaybeQuotedPath>()->default_value(Files::MaybeQuotedPath(), ""),
"load a save game file on game startup (specify an absolute filename or a filename relative to the current working directory)")
("skip-menu", bpo::value<bool>()->implicit_value(true)

@ -58,10 +58,10 @@ struct ContentFileTest : public ::testing::Test
boost::program_options::options_description desc("Allowed options");
desc.add_options()
("data", boost::program_options::value<Files::ReluctantPathContainer>()->default_value(Files::ReluctantPathContainer(), "data")->multitoken()->composing())
("data", boost::program_options::value<Files::MaybeQuotedPathContainer>()->default_value(Files::MaybeQuotedPathContainer(), "data")->multitoken()->composing())
("content", boost::program_options::value<std::vector<std::string>>()->default_value(std::vector<std::string>(), "")
->multitoken()->composing(), "content file(s): esm/esp, or omwgame/omwaddon")
("data-local", boost::program_options::value<Files::ReluctantPathContainer::value_type>()->default_value(Files::ReluctantPathContainer::value_type(), ""));
("data-local", boost::program_options::value<Files::MaybeQuotedPathContainer::value_type>()->default_value(Files::MaybeQuotedPathContainer::value_type(), ""));
boost::program_options::notify(variables);
@ -69,10 +69,10 @@ struct ContentFileTest : public ::testing::Test
Files::PathContainer dataDirs, dataLocal;
if (!variables["data"].empty()) {
dataDirs = asPathContainer(variables["data"].as<Files::ReluctantPathContainer>());
dataDirs = asPathContainer(variables["data"].as<Files::MaybeQuotedPathContainer>());
}
Files::PathContainer::value_type local(variables["data-local"].as<Files::ReluctantPathContainer::value_type>());
Files::PathContainer::value_type local(variables["data-local"].as<Files::MaybeQuotedPathContainer::value_type>());
if (!local.empty()) {
dataLocal.push_back(local);
}

@ -40,7 +40,7 @@ namespace
const std::array arguments {"openmw", "--load-savegame=save.omwsave"};
bpo::variables_map variables;
parseArgs(arguments, variables, description);
EXPECT_EQ(variables["load-savegame"].as<Files::ReluctantPath>().string(), "save.omwsave");
EXPECT_EQ(variables["load-savegame"].as<Files::MaybeQuotedPath>().string(), "save.omwsave");
}
TEST(OpenMWOptionsFromArguments, should_support_single_word_load_savegame_path)
@ -49,7 +49,7 @@ namespace
const std::array arguments {"openmw", "--load-savegame", "save.omwsave"};
bpo::variables_map variables;
parseArgs(arguments, variables, description);
EXPECT_EQ(variables["load-savegame"].as<Files::ReluctantPath>().string(), "save.omwsave");
EXPECT_EQ(variables["load-savegame"].as<Files::MaybeQuotedPath>().string(), "save.omwsave");
}
TEST(OpenMWOptionsFromArguments, should_support_multi_component_load_savegame_path)
@ -58,7 +58,7 @@ namespace
const std::array arguments {"openmw", "--load-savegame", "/home/user/openmw/save.omwsave"};
bpo::variables_map variables;
parseArgs(arguments, variables, description);
EXPECT_EQ(variables["load-savegame"].as<Files::ReluctantPath>().string(), "/home/user/openmw/save.omwsave");
EXPECT_EQ(variables["load-savegame"].as<Files::MaybeQuotedPath>().string(), "/home/user/openmw/save.omwsave");
}
TEST(OpenMWOptionsFromArguments, should_support_windows_multi_component_load_savegame_path)
@ -67,7 +67,7 @@ namespace
const std::array arguments {"openmw", "--load-savegame", R"(C:\OpenMW\save.omwsave)"};
bpo::variables_map variables;
parseArgs(arguments, variables, description);
EXPECT_EQ(variables["load-savegame"].as<Files::ReluctantPath>().string(), R"(C:\OpenMW\save.omwsave)");
EXPECT_EQ(variables["load-savegame"].as<Files::MaybeQuotedPath>().string(), R"(C:\OpenMW\save.omwsave)");
}
TEST(OpenMWOptionsFromArguments, should_support_load_savegame_path_with_spaces)
@ -76,8 +76,7 @@ namespace
const std::array arguments {"openmw", "--load-savegame", "my save.omwsave"};
bpo::variables_map variables;
parseArgs(arguments, variables, description);
EXPECT_EQ(variables["load-savegame"].as<Files::ReluctantPath>().string(), "my");
// EXPECT_EQ(variables["load-savegame"].as<Files::ReluctantPath>().string(), "my save.omwsave");
EXPECT_EQ(variables["load-savegame"].as<Files::MaybeQuotedPath>().string(), "my save.omwsave");
}
TEST(OpenMWOptionsFromArguments, should_support_load_savegame_path_with_octothorpe)
@ -86,7 +85,7 @@ namespace
const std::array arguments {"openmw", "--load-savegame", "my#save.omwsave"};
bpo::variables_map variables;
parseArgs(arguments, variables, description);
EXPECT_EQ(variables["load-savegame"].as<Files::ReluctantPath>().string(), "my#save.omwsave");
EXPECT_EQ(variables["load-savegame"].as<Files::MaybeQuotedPath>().string(), "my#save.omwsave");
}
TEST(OpenMWOptionsFromArguments, should_support_load_savegame_path_with_at_sign)
@ -95,7 +94,7 @@ namespace
const std::array arguments {"openmw", "--load-savegame", "my@save.omwsave"};
bpo::variables_map variables;
parseArgs(arguments, variables, description);
EXPECT_EQ(variables["load-savegame"].as<Files::ReluctantPath>().string(), "my@save.omwsave");
EXPECT_EQ(variables["load-savegame"].as<Files::MaybeQuotedPath>().string(), "my@save.omwsave");
}
TEST(OpenMWOptionsFromArguments, should_support_load_savegame_path_with_quote)
@ -104,7 +103,7 @@ namespace
const std::array arguments {"openmw", "--load-savegame", R"(my"save.omwsave)"};
bpo::variables_map variables;
parseArgs(arguments, variables, description);
EXPECT_EQ(variables["load-savegame"].as<Files::ReluctantPath>().string(), R"(my"save.omwsave)");
EXPECT_EQ(variables["load-savegame"].as<Files::MaybeQuotedPath>().string(), R"(my"save.omwsave)");
}
TEST(OpenMWOptionsFromArguments, should_support_quoted_load_savegame_path)
@ -113,8 +112,8 @@ namespace
const std::array arguments {"openmw", "--load-savegame", R"("save".omwsave)"};
bpo::variables_map variables;
parseArgs(arguments, variables, description);
EXPECT_EQ(variables["load-savegame"].as<Files::ReluctantPath>().string(), R"(save)");
// EXPECT_EQ(variables["load-savegame"].as<Files::ReluctantPath>().string(), R"("save".omwsave)");
EXPECT_EQ(variables["load-savegame"].as<Files::MaybeQuotedPath>().string(), R"(save)");
// EXPECT_EQ(variables["load-savegame"].as<Files::MaybeQuotedPath>().string(), R"("save".omwsave)");
}
TEST(OpenMWOptionsFromArguments, should_support_quoted_load_savegame_path_with_escaped_quote_by_ampersand)
@ -123,7 +122,7 @@ namespace
const std::array arguments {"openmw", "--load-savegame", R"("save&".omwsave")"};
bpo::variables_map variables;
parseArgs(arguments, variables, description);
EXPECT_EQ(variables["load-savegame"].as<Files::ReluctantPath>().string(), R"(save".omwsave)");
EXPECT_EQ(variables["load-savegame"].as<Files::MaybeQuotedPath>().string(), R"(save".omwsave)");
}
TEST(OpenMWOptionsFromArguments, should_support_quoted_load_savegame_path_with_escaped_ampersand)
@ -132,7 +131,7 @@ namespace
const std::array arguments {"openmw", "--load-savegame", R"("save.omwsave&&")"};
bpo::variables_map variables;
parseArgs(arguments, variables, description);
EXPECT_EQ(variables["load-savegame"].as<Files::ReluctantPath>().string(), "save.omwsave&");
EXPECT_EQ(variables["load-savegame"].as<Files::MaybeQuotedPath>().string(), "save.omwsave&");
}
TEST(OpenMWOptionsFromArguments, should_support_load_savegame_path_with_ampersand)
@ -141,7 +140,7 @@ namespace
const std::array arguments {"openmw", "--load-savegame", "save&.omwsave"};
bpo::variables_map variables;
parseArgs(arguments, variables, description);
EXPECT_EQ(variables["load-savegame"].as<Files::ReluctantPath>().string(), "save&.omwsave");
EXPECT_EQ(variables["load-savegame"].as<Files::MaybeQuotedPath>().string(), "save&.omwsave");
}
TEST(OpenMWOptionsFromArguments, should_support_load_savegame_path_with_multiple_quotes)
@ -150,7 +149,7 @@ namespace
const std::array arguments {"openmw", "--load-savegame", R"(my"save".omwsave)"};
bpo::variables_map variables;
parseArgs(arguments, variables, description);
EXPECT_EQ(variables["load-savegame"].as<Files::ReluctantPath>().string(), R"(my"save".omwsave)");
EXPECT_EQ(variables["load-savegame"].as<Files::MaybeQuotedPath>().string(), R"(my"save".omwsave)");
}
TEST(OpenMWOptionsFromArguments, should_compose_data)
@ -159,7 +158,7 @@ namespace
const std::array arguments {"openmw", "--data", "1", "--data", "2"};
bpo::variables_map variables;
parseArgs(arguments, variables, description);
EXPECT_THAT(variables["data"].as<Files::ReluctantPathContainer>(), ElementsAre(IsPath("1"), IsPath("2")));
EXPECT_THAT(variables["data"].as<Files::MaybeQuotedPathContainer>(), ElementsAre(IsPath("1"), IsPath("2")));
}
TEST(OpenMWOptionsFromArguments, should_compose_data_from_single_flag)
@ -168,7 +167,7 @@ namespace
const std::array arguments {"openmw", "--data", "1", "2"};
bpo::variables_map variables;
parseArgs(arguments, variables, description);
EXPECT_THAT(variables["data"].as<Files::ReluctantPathContainer>(), ElementsAre(IsPath("1"), IsPath("2")));
EXPECT_THAT(variables["data"].as<Files::MaybeQuotedPathContainer>(), ElementsAre(IsPath("1"), IsPath("2")));
}
TEST(OpenMWOptionsFromArguments, should_throw_on_multiple_load_savegame)
@ -189,7 +188,7 @@ namespace
const std::array arguments {"openmw", "--load-savegame", pathArgument.c_str()};
bpo::variables_map variables;
parseArgs(arguments, variables, description);
EXPECT_EQ(variables["load-savegame"].as<Files::ReluctantPath>().string(), path);
EXPECT_EQ(variables["load-savegame"].as<Files::MaybeQuotedPath>().string(), path);
}
INSTANTIATE_TEST_SUITE_P(
@ -204,7 +203,7 @@ namespace
std::istringstream stream("load-savegame=save.omwsave");
bpo::variables_map variables;
Files::parseConfig(stream, variables, description);
EXPECT_EQ(variables["load-savegame"].as<Files::ReluctantPath>().string(), "save.omwsave");
EXPECT_EQ(variables["load-savegame"].as<Files::MaybeQuotedPath>().string(), "save.omwsave");
}
TEST(OpenMWOptionsFromConfig, should_strip_quotes_from_load_savegame_path)
@ -213,7 +212,7 @@ namespace
std::istringstream stream(R"(load-savegame="save.omwsave")");
bpo::variables_map variables;
Files::parseConfig(stream, variables, description);
EXPECT_EQ(variables["load-savegame"].as<Files::ReluctantPath>().string(), "save.omwsave");
EXPECT_EQ(variables["load-savegame"].as<Files::MaybeQuotedPath>().string(), "save.omwsave");
}
TEST(OpenMWOptionsFromConfig, should_strip_outer_quotes_from_load_savegame_path)
@ -222,8 +221,8 @@ namespace
std::istringstream stream(R"(load-savegame=""save".omwsave")");
bpo::variables_map variables;
Files::parseConfig(stream, variables, description);
EXPECT_EQ(variables["load-savegame"].as<Files::ReluctantPath>().string(), "");
// EXPECT_EQ(variables["load-savegame"].as<Files::ReluctantPath>().string(), R"(""save".omwsave")");
EXPECT_EQ(variables["load-savegame"].as<Files::MaybeQuotedPath>().string(), "");
// EXPECT_EQ(variables["load-savegame"].as<Files::MaybeQuotedPath>().string(), R"(""save".omwsave")");
}
TEST(OpenMWOptionsFromConfig, should_strip_quotes_from_load_savegame_path_with_space)
@ -232,7 +231,7 @@ namespace
std::istringstream stream(R"(load-savegame="my save.omwsave")");
bpo::variables_map variables;
Files::parseConfig(stream, variables, description);
EXPECT_EQ(variables["load-savegame"].as<Files::ReluctantPath>().string(), "my save.omwsave");
EXPECT_EQ(variables["load-savegame"].as<Files::MaybeQuotedPath>().string(), "my save.omwsave");
}
TEST(OpenMWOptionsFromConfig, should_support_quoted_load_savegame_path_with_octothorpe)
@ -241,7 +240,7 @@ namespace
std::istringstream stream("load-savegame=save#.omwsave");
bpo::variables_map variables;
Files::parseConfig(stream, variables, description);
EXPECT_EQ(variables["load-savegame"].as<Files::ReluctantPath>().string(), "save#.omwsave");
EXPECT_EQ(variables["load-savegame"].as<Files::MaybeQuotedPath>().string(), "save#.omwsave");
}
TEST(OpenMWOptionsFromConfig, should_support_quoted_load_savegame_path_with_at_sign)
@ -250,7 +249,7 @@ namespace
std::istringstream stream("load-savegame=save@.omwsave");
bpo::variables_map variables;
Files::parseConfig(stream, variables, description);
EXPECT_EQ(variables["load-savegame"].as<Files::ReluctantPath>().string(), "save@.omwsave");
EXPECT_EQ(variables["load-savegame"].as<Files::MaybeQuotedPath>().string(), "save@.omwsave");
}
TEST(OpenMWOptionsFromConfig, should_support_quoted_load_savegame_path_with_quote)
@ -259,7 +258,7 @@ namespace
std::istringstream stream(R"(load-savegame=save".omwsave)");
bpo::variables_map variables;
Files::parseConfig(stream, variables, description);
EXPECT_EQ(variables["load-savegame"].as<Files::ReluctantPath>().string(), R"(save".omwsave)");
EXPECT_EQ(variables["load-savegame"].as<Files::MaybeQuotedPath>().string(), R"(save".omwsave)");
}
TEST(OpenMWOptionsFromConfig, should_support_confusing_savegame_path_with_lots_going_on)
@ -268,7 +267,7 @@ namespace
std::istringstream stream(R"(load-savegame="one &"two"three".omwsave")");
bpo::variables_map variables;
Files::parseConfig(stream, variables, description);
EXPECT_EQ(variables["load-savegame"].as<Files::ReluctantPath>().string(), R"(one "two)");
EXPECT_EQ(variables["load-savegame"].as<Files::MaybeQuotedPath>().string(), R"(one "two)");
}
TEST(OpenMWOptionsFromConfig, should_support_confusing_savegame_path_with_even_more_going_on)
@ -277,7 +276,7 @@ namespace
std::istringstream stream(R"(load-savegame="one &"two"three ".omwsave")");
bpo::variables_map variables;
Files::parseConfig(stream, variables, description);
EXPECT_EQ(variables["load-savegame"].as<Files::ReluctantPath>().string(), R"(one "two)");
EXPECT_EQ(variables["load-savegame"].as<Files::MaybeQuotedPath>().string(), R"(one "two)");
}
TEST(OpenMWOptionsFromConfig, should_ignore_commented_option)
@ -286,7 +285,7 @@ namespace
std::istringstream stream("#load-savegame=save.omwsave");
bpo::variables_map variables;
Files::parseConfig(stream, variables, description);
EXPECT_EQ(variables["load-savegame"].as<Files::ReluctantPath>().string(), "");
EXPECT_EQ(variables["load-savegame"].as<Files::MaybeQuotedPath>().string(), "");
}
TEST(OpenMWOptionsFromConfig, should_ignore_whitespace_prefixed_commented_option)
@ -295,7 +294,7 @@ namespace
std::istringstream stream(" \t#load-savegame=save.omwsave");
bpo::variables_map variables;
Files::parseConfig(stream, variables, description);
EXPECT_EQ(variables["load-savegame"].as<Files::ReluctantPath>().string(), "");
EXPECT_EQ(variables["load-savegame"].as<Files::MaybeQuotedPath>().string(), "");
}
TEST(OpenMWOptionsFromConfig, should_support_whitespace_around_option)
@ -304,7 +303,7 @@ namespace
std::istringstream stream(" load-savegame = save.omwsave ");
bpo::variables_map variables;
Files::parseConfig(stream, variables, description);
EXPECT_EQ(variables["load-savegame"].as<Files::ReluctantPath>().string(), "save.omwsave");
EXPECT_EQ(variables["load-savegame"].as<Files::MaybeQuotedPath>().string(), "save.omwsave");
}
TEST(OpenMWOptionsFromConfig, should_throw_on_multiple_load_savegame)
@ -321,7 +320,7 @@ namespace
std::istringstream stream("load-savegame=/home/user/openmw/save.omwsave");
bpo::variables_map variables;
Files::parseConfig(stream, variables, description);
EXPECT_EQ(variables["load-savegame"].as<Files::ReluctantPath>().string(), "/home/user/openmw/save.omwsave");
EXPECT_EQ(variables["load-savegame"].as<Files::MaybeQuotedPath>().string(), "/home/user/openmw/save.omwsave");
}
TEST(OpenMWOptionsFromConfig, should_support_windows_multi_component_load_savegame_path)
@ -330,7 +329,7 @@ namespace
std::istringstream stream(R"(load-savegame=C:\OpenMW\save.omwsave)");
bpo::variables_map variables;
Files::parseConfig(stream, variables, description);
EXPECT_EQ(variables["load-savegame"].as<Files::ReluctantPath>().string(), R"(C:\OpenMW\save.omwsave)");
EXPECT_EQ(variables["load-savegame"].as<Files::MaybeQuotedPath>().string(), R"(C:\OpenMW\save.omwsave)");
}
TEST(OpenMWOptionsFromConfig, should_compose_data)
@ -339,7 +338,7 @@ namespace
std::istringstream stream("data=1\ndata=2");
bpo::variables_map variables;
Files::parseConfig(stream, variables, description);
EXPECT_THAT(variables["data"].as<Files::ReluctantPathContainer>(), ElementsAre(IsPath("1"), IsPath("2")));
EXPECT_THAT(variables["data"].as<Files::MaybeQuotedPathContainer>(), ElementsAre(IsPath("1"), IsPath("2")));
}
TEST(OpenMWOptionsFromConfig, should_support_quoted_load_savegame_path_with_escaped_quote_by_ampersand)
@ -348,7 +347,7 @@ namespace
std::istringstream stream(R"(load-savegame="save&".omwsave")");
bpo::variables_map variables;
Files::parseConfig(stream, variables, description);
EXPECT_EQ(variables["load-savegame"].as<Files::ReluctantPath>().string(), R"(save".omwsave)");
EXPECT_EQ(variables["load-savegame"].as<Files::MaybeQuotedPath>().string(), R"(save".omwsave)");
}
TEST(OpenMWOptionsFromConfig, should_support_quoted_load_savegame_path_with_escaped_ampersand)
@ -357,7 +356,7 @@ namespace
std::istringstream stream(R"(load-savegame="save.omwsave&&")");
bpo::variables_map variables;
Files::parseConfig(stream, variables, description);
EXPECT_EQ(variables["load-savegame"].as<Files::ReluctantPath>().string(), "save.omwsave&");
EXPECT_EQ(variables["load-savegame"].as<Files::MaybeQuotedPath>().string(), "save.omwsave&");
}
TEST(OpenMWOptionsFromConfig, should_support_load_savegame_path_with_ampersand)
@ -366,7 +365,7 @@ namespace
std::istringstream stream("load-savegame=save&.omwsave");
bpo::variables_map variables;
Files::parseConfig(stream, variables, description);
EXPECT_EQ(variables["load-savegame"].as<Files::ReluctantPath>().string(), "save&.omwsave");
EXPECT_EQ(variables["load-savegame"].as<Files::MaybeQuotedPath>().string(), "save&.omwsave");
}
struct OpenMWOptionsFromConfigStrings : TestWithParam<std::string> {};
@ -378,7 +377,7 @@ namespace
std::istringstream stream("load-savegame=\"" + path + "\"");
bpo::variables_map variables;
Files::parseConfig(stream, variables, description);
EXPECT_EQ(variables["load-savegame"].as<Files::ReluctantPath>().string(), path);
EXPECT_EQ(variables["load-savegame"].as<Files::MaybeQuotedPath>().string(), path);
}
INSTANTIATE_TEST_SUITE_P(

@ -138,10 +138,10 @@ void mergeComposingVariables(boost::program_options::variables_map& first, boost
boost::any& firstValue = firstPosition->second.value();
const boost::any& secondValue = second[name].value();
if (firstValue.type() == typeid(Files::ReluctantPathContainer))
if (firstValue.type() == typeid(Files::MaybeQuotedPathContainer))
{
auto& firstPathContainer = boost::any_cast<Files::ReluctantPathContainer&>(firstValue);
const auto& secondPathContainer = boost::any_cast<const Files::ReluctantPathContainer&>(secondValue);
auto& firstPathContainer = boost::any_cast<Files::MaybeQuotedPathContainer&>(firstValue);
const auto& secondPathContainer = boost::any_cast<const Files::MaybeQuotedPathContainer&>(secondValue);
firstPathContainer.insert(firstPathContainer.end(), secondPathContainer.begin(), secondPathContainer.end());
}
@ -317,22 +317,31 @@ void parseConfig(std::istream& stream, boost::program_options::variables_map& va
);
}
std::istream& operator>> (std::istream& istream, ReluctantPath& reluctantPath)
std::istream& operator>> (std::istream& istream, MaybeQuotedPath& MaybeQuotedPath)
{
// Read from stream using boost::filesystem::path rules, then discard anything remaining.
// If the stream starts with a double quote, read from stream using boost::filesystem::path rules, then discard anything remaining.
// This prevents boost::program_options getting upset that we've not consumed the whole stream.
istream >> static_cast<boost::filesystem::path&>(reluctantPath);
if (istream && !istream.eof() && istream.peek() != EOF)
// If it doesn't start with a double quote, read the whole thing verbatim
if (istream.peek() == '"')
{
std::string remainder(std::istreambuf_iterator(istream), {});
Log(Debug::Warning) << "Trailing data in path setting. Used '" << reluctantPath.string() << "' but '" << remainder << "' remained";
istream >> static_cast<boost::filesystem::path&>(MaybeQuotedPath);
if (istream && !istream.eof() && istream.peek() != EOF)
{
std::string remainder(std::istreambuf_iterator(istream), {});
Log(Debug::Warning) << "Trailing data in path setting. Used '" << MaybeQuotedPath.string() << "' but '" << remainder << "' remained";
}
}
else
{
std::string intermediate(std::istreambuf_iterator(istream), {});
static_cast<boost::filesystem::path&>(MaybeQuotedPath) = intermediate;
}
return istream;
}
PathContainer asPathContainer(const ReluctantPathContainer& reluctantPathContainer)
PathContainer asPathContainer(const MaybeQuotedPathContainer& MaybeQuotedPathContainer)
{
return PathContainer(reluctantPathContainer.begin(), reluctantPathContainer.end());
return PathContainer(MaybeQuotedPathContainer.begin(), MaybeQuotedPathContainer.end());
}
} /* namespace Cfg */

@ -77,17 +77,17 @@ void parseArgs(int argc, const char* const argv[], boost::program_options::varia
void parseConfig(std::istream& stream, boost::program_options::variables_map& variables,
boost::program_options::options_description& description);
class ReluctantPath : public boost::filesystem::path
class MaybeQuotedPath : public boost::filesystem::path
{
public:
operator boost::filesystem::path() { return *this; }
};
std::istream& operator>> (std::istream& istream, ReluctantPath& reluctantPath);
std::istream& operator>> (std::istream& istream, MaybeQuotedPath& MaybeQuotedPath);
typedef std::vector<ReluctantPath> ReluctantPathContainer;
typedef std::vector<MaybeQuotedPath> MaybeQuotedPathContainer;
PathContainer asPathContainer(const ReluctantPathContainer& reluctantPathContainer);
PathContainer asPathContainer(const MaybeQuotedPathContainer& MaybeQuotedPathContainer);
} /* namespace Cfg */

Loading…
Cancel
Save