Loading native/dicttoolkit/src/command_executors/makedict_executor.cpp +6 −0 Original line number Diff line number Diff line Loading @@ -24,6 +24,12 @@ namespace dicttoolkit { const char *const MakedictExecutor::COMMAND_NAME = "makedict"; /* static */ int MakedictExecutor::run(const int argc, char **argv) { const ArgumentsAndOptions argumentsAndOptions = getArgumentsParser().parseArguments(argc, argv, true /* printErrorMessages */); if (!argumentsAndOptions.isValid()) { printUsage(); return 1; } fprintf(stderr, "Command '%s' has not been implemented yet.\n", COMMAND_NAME); return 0; } Loading native/dicttoolkit/src/utils/arguments_and_options.h +23 −0 Original line number Diff line number Diff line Loading @@ -42,6 +42,29 @@ class ArgumentsAndOptions { return mOptions.find(optionName) != mOptions.end(); } const std::string &getOptionValue(const std::string &optionName) const { const auto &it = mOptions.find(optionName); ASSERT(it != mOptions.end()); return it->second; } bool hasArgument(const std::string &name) const { const auto &it = mArguments.find(name); return it != mArguments.end() && !it->second.empty(); } const std::string &getSingleArgument(const std::string &name) const { const auto &it = mArguments.find(name); ASSERT(it != mArguments.end() && !it->second.empty()); return it->second.front(); } const std::vector<std::string> &getVariableLengthArguments(const std::string &name) const { const auto &it = mArguments.find(name); ASSERT(it != mArguments.end()); return it->second; } private: DISALLOW_ASSIGNMENT_OPERATOR(ArgumentsAndOptions); Loading native/dicttoolkit/src/utils/arguments_parser.cpp +74 −7 Original line number Diff line number Diff line Loading @@ -21,7 +21,7 @@ namespace latinime { namespace dicttoolkit { const int ArgumentSpec::UNLIMITED_COUNT = -1; const size_t ArgumentSpec::UNLIMITED_COUNT = S_INT_MAX; bool ArgumentsParser::validateSpecs() const { std::unordered_set<std::string> argumentNameSet; Loading Loading @@ -53,7 +53,7 @@ void ArgumentsParser::printUsage(const std::string &commandName, const std::string &optionName = option.first; const OptionSpec &spec = option.second; printf(" [-%s", optionName.c_str()); if (spec.takeValue()) { if (spec.needsValue()) { printf(" <%s>", spec.getValueName().c_str()); } printf("]"); Loading @@ -74,11 +74,11 @@ void ArgumentsParser::printUsage(const std::string &commandName, const std::string &optionName = option.first; const OptionSpec &spec = option.second; printf(" -%s", optionName.c_str()); if (spec.takeValue()) { if (spec.needsValue()) { printf(" <%s>", spec.getValueName().c_str()); } printf("\t\t\t%s", spec.getDescription().c_str()); if (spec.takeValue() && !spec.getDefaultValue().empty()) { if (spec.needsValue() && !spec.getDefaultValue().empty()) { printf("\tdefault: %s", spec.getDefaultValue().c_str()); } printf("\n"); Loading @@ -89,10 +89,77 @@ void ArgumentsParser::printUsage(const std::string &commandName, printf("\n\n"); } const ArgumentsAndOptions ArgumentsParser::parseArguments(const int argc, char **argv) const { // TODO: Implement const ArgumentsAndOptions ArgumentsParser::parseArguments(const int argc, char **argv, const bool printErrorMessage) const { if (argc <= 0) { AKLOGE("Invalid argc (%d).", argc); ASSERT(false); return ArgumentsAndOptions(); } std::unordered_map<std::string, std::string> options; for (const auto &entry : mOptionSpecs) { const std::string &optionName = entry.first; const OptionSpec &optionSpec = entry.second; if (optionSpec.needsValue() && !optionSpec.getDefaultValue().empty()) { // Set default value. options[optionName] = optionSpec.getDefaultValue(); } } std::unordered_map<std::string, std::vector<std::string>> arguments; auto argumentSpecIt = mArgumentSpecs.cbegin(); for (int i = 1; i < argc; ++i) { const std::string arg = argv[i]; if (arg.length() > 1 && arg[0] == '-') { // option const std::string optionName = arg.substr(1); const auto it = mOptionSpecs.find(optionName); if (it == mOptionSpecs.end()) { if (printErrorMessage) { fprintf(stderr, "Unknown option: '%s'\n", optionName.c_str()); } return ArgumentsAndOptions(); } std::string optionValue; if (it->second.needsValue()) { ++i; if (i >= argc) { if (printErrorMessage) { fprintf(stderr, "Missing argument for option '%s'\n", optionName.c_str()); } return ArgumentsAndOptions(); } optionValue = argv[i]; } options[optionName] = optionValue; } else { // argument if (argumentSpecIt == mArgumentSpecs.end()) { if (printErrorMessage) { fprintf(stderr, "Too many arguments.\n"); } return ArgumentsAndOptions(); } arguments[argumentSpecIt->getName()].push_back(arg); if (arguments[argumentSpecIt->getName()].size() >= argumentSpecIt->getMaxCount()) { ++argumentSpecIt; } } } if (argumentSpecIt != mArgumentSpecs.end()) { const auto &it = arguments.find(argumentSpecIt->getName()); const size_t minCount = argumentSpecIt->getMinCount(); const size_t actualcount = it == arguments.end() ? 0 : it->second.size(); if (minCount > actualcount) { if (printErrorMessage) { fprintf(stderr, "Not enough arguments. %zd argumant(s) required for <%s>\n", minCount, argumentSpecIt->getName().c_str()); } return ArgumentsAndOptions(); } } return ArgumentsAndOptions(std::move(options), std::move(arguments)); } } // namespace dicttoolkit } // namespace latinime native/dicttoolkit/src/utils/arguments_parser.h +18 −17 Original line number Diff line number Diff line Loading @@ -35,29 +35,29 @@ class OptionSpec { static OptionSpec keyValueOption(const std::string &valueName, const std::string &defaultValue, const std::string &description) { return OptionSpec(true /* takeValue */, valueName, defaultValue, description); return OptionSpec(true /* needsValue */, valueName, defaultValue, description); } static OptionSpec switchOption(const std::string &description) { return OptionSpec(false /* takeValue */, "" /* valueName */, "" /* defaultValue */, return OptionSpec(false /* needsValue */, "" /* valueName */, "" /* defaultValue */, description); } bool takeValue() const { return mTakeValue; } bool needsValue() const { return mNeedsValue; } const std::string &getValueName() const { return mValueName; } const std::string &getDefaultValue() const { return mDefaultValue; } const std::string &getDescription() const { return mDescription; } private: OptionSpec(const bool takeValue, const std::string &valueName, const std::string &defaultValue, OptionSpec(const bool needsValue, const std::string &valueName, const std::string &defaultValue, const std::string &description) : mTakeValue(takeValue), mValueName(valueName), mDefaultValue(defaultValue), : mNeedsValue(needsValue), mValueName(valueName), mDefaultValue(defaultValue), mDescription(description) {} // Whether the option have to be used with a value or just a switch. // e.g. 'f' in "command -f /path/to/file" is mTakeValue == true. // 'f' in "command -f -t" is mTakeValue == false. bool mTakeValue; // e.g. 'f' in "command -f /path/to/file" is mNeedsValue == true. // 'f' in "command -f -t" is mNeedsValue == false. bool mNeedsValue; // Name of the value used to show usage. std::string mValueName; std::string mDefaultValue; Loading @@ -66,32 +66,32 @@ class OptionSpec { class ArgumentSpec { public: static const int UNLIMITED_COUNT; static const size_t UNLIMITED_COUNT; static ArgumentSpec singleArgument(const std::string &name, const std::string &description) { return ArgumentSpec(name, 1 /* minCount */, 1 /* maxCount */, description); } static ArgumentSpec variableLengthArguments(const std::string &name, const int minCount, const int maxCount, const std::string &description) { static ArgumentSpec variableLengthArguments(const std::string &name, const size_t minCount, const size_t maxCount, const std::string &description) { return ArgumentSpec(name, minCount, maxCount, description); } const std::string &getName() const { return mName; } int getMinCount() const { return mMinCount; } int getMaxCount() const { return mMaxCount; } size_t getMinCount() const { return mMinCount; } size_t getMaxCount() const { return mMaxCount; } const std::string &getDescription() const { return mDescription; } private: DISALLOW_DEFAULT_CONSTRUCTOR(ArgumentSpec); ArgumentSpec(const std::string &name, const int minCount, const int maxCount, ArgumentSpec(const std::string &name, const size_t minCount, const size_t maxCount, const std::string &description) : mName(name), mMinCount(minCount), mMaxCount(maxCount), mDescription(description) {} const std::string mName; const int mMinCount; const int mMaxCount; const size_t mMinCount; const size_t mMaxCount; const std::string mDescription; }; Loading @@ -101,7 +101,8 @@ class ArgumentsParser { const std::vector<ArgumentSpec> &&argumentSpecs) : mOptionSpecs(std::move(optionSpecs)), mArgumentSpecs(std::move(argumentSpecs)) {} const ArgumentsAndOptions parseArguments(const int argc, char **argv) const; const ArgumentsAndOptions parseArguments(const int argc, char **argv, const bool printErrorMessage) const; bool validateSpecs() const; void printUsage(const std::string &commandName, const std::string &description) const; Loading native/dicttoolkit/tests/utils/arguments_parser_test.cpp +74 −0 Original line number Diff line number Diff line Loading @@ -68,6 +68,80 @@ TEST(ArgumentsParserTests, TestValitadeSpecs) { } } int initArgv(char *mutableCommandLine, char **argv) { bool readingSeparator = false; int argc = 1; argv[0] = mutableCommandLine; const size_t length = strlen(mutableCommandLine); for (size_t i = 0; i < length; ++i) { if (mutableCommandLine[i] != ' ' && readingSeparator) { readingSeparator = false; argv[argc] = mutableCommandLine + i; ++argc; } else if (mutableCommandLine[i] == ' ' && !readingSeparator) { readingSeparator = true; mutableCommandLine[i] = '\0'; } } argv[argc] = nullptr; return argc; } TEST(ArgumentsParserTests, TestParseArguments) { std::unordered_map<std::string, OptionSpec> optionSpecs; optionSpecs["a"] = OptionSpec::switchOption("description"); optionSpecs["b"] = OptionSpec::keyValueOption("valueName", "default", "description"); const std::vector<ArgumentSpec> argumentSpecs = { ArgumentSpec::singleArgument("arg0", "description"), ArgumentSpec::variableLengthArguments("arg1", 0 /* minCount */, 2 /* maxCount */, "description"), }; const ArgumentsParser parser = ArgumentsParser(std::move(optionSpecs), std::move(argumentSpecs)); { char kMutableCommandLine[1024] = "command arg"; char *argv[128] = {}; const int argc = initArgv(kMutableCommandLine, argv); ASSERT_EQ(2, argc); const ArgumentsAndOptions argumentsAndOptions = parser.parseArguments( argc, argv, false /* printErrorMessages */); EXPECT_FALSE(argumentsAndOptions.hasOption("a")); EXPECT_EQ("default", argumentsAndOptions.getOptionValue("b")); EXPECT_EQ("arg", argumentsAndOptions.getSingleArgument("arg0")); EXPECT_FALSE(argumentsAndOptions.hasArgument("arg1")); } { char kArgumentBuffer[1024] = "command -a arg arg"; char *argv[128] = {}; const int argc = initArgv(kArgumentBuffer, argv); ASSERT_EQ(4, argc); const ArgumentsAndOptions argumentsAndOptions = parser.parseArguments( argc, argv, false /* printErrorMessages */); EXPECT_TRUE(argumentsAndOptions.hasOption("a")); EXPECT_EQ("default", argumentsAndOptions.getOptionValue("b")); EXPECT_EQ("arg", argumentsAndOptions.getSingleArgument("arg0")); EXPECT_TRUE(argumentsAndOptions.hasArgument("arg1")); EXPECT_EQ(1u, argumentsAndOptions.getVariableLengthArguments("arg1").size()); } { char kArgumentBuffer[1024] = "command -b value arg arg1 arg2"; char *argv[128] = {}; const int argc = initArgv(kArgumentBuffer, argv); ASSERT_EQ(6, argc); const ArgumentsAndOptions argumentsAndOptions = parser.parseArguments( argc, argv, false /* printErrorMessages */); EXPECT_FALSE(argumentsAndOptions.hasOption("a")); EXPECT_EQ("value", argumentsAndOptions.getOptionValue("b")); EXPECT_EQ("arg", argumentsAndOptions.getSingleArgument("arg0")); const std::vector<std::string> &arg1 = argumentsAndOptions.getVariableLengthArguments("arg1"); EXPECT_EQ(2u, arg1.size()); EXPECT_EQ("arg1", arg1[0]); EXPECT_EQ("arg2", arg1[1]); } } } // namespace } // namespace dicttoolkit } // namespace latinime Loading
native/dicttoolkit/src/command_executors/makedict_executor.cpp +6 −0 Original line number Diff line number Diff line Loading @@ -24,6 +24,12 @@ namespace dicttoolkit { const char *const MakedictExecutor::COMMAND_NAME = "makedict"; /* static */ int MakedictExecutor::run(const int argc, char **argv) { const ArgumentsAndOptions argumentsAndOptions = getArgumentsParser().parseArguments(argc, argv, true /* printErrorMessages */); if (!argumentsAndOptions.isValid()) { printUsage(); return 1; } fprintf(stderr, "Command '%s' has not been implemented yet.\n", COMMAND_NAME); return 0; } Loading
native/dicttoolkit/src/utils/arguments_and_options.h +23 −0 Original line number Diff line number Diff line Loading @@ -42,6 +42,29 @@ class ArgumentsAndOptions { return mOptions.find(optionName) != mOptions.end(); } const std::string &getOptionValue(const std::string &optionName) const { const auto &it = mOptions.find(optionName); ASSERT(it != mOptions.end()); return it->second; } bool hasArgument(const std::string &name) const { const auto &it = mArguments.find(name); return it != mArguments.end() && !it->second.empty(); } const std::string &getSingleArgument(const std::string &name) const { const auto &it = mArguments.find(name); ASSERT(it != mArguments.end() && !it->second.empty()); return it->second.front(); } const std::vector<std::string> &getVariableLengthArguments(const std::string &name) const { const auto &it = mArguments.find(name); ASSERT(it != mArguments.end()); return it->second; } private: DISALLOW_ASSIGNMENT_OPERATOR(ArgumentsAndOptions); Loading
native/dicttoolkit/src/utils/arguments_parser.cpp +74 −7 Original line number Diff line number Diff line Loading @@ -21,7 +21,7 @@ namespace latinime { namespace dicttoolkit { const int ArgumentSpec::UNLIMITED_COUNT = -1; const size_t ArgumentSpec::UNLIMITED_COUNT = S_INT_MAX; bool ArgumentsParser::validateSpecs() const { std::unordered_set<std::string> argumentNameSet; Loading Loading @@ -53,7 +53,7 @@ void ArgumentsParser::printUsage(const std::string &commandName, const std::string &optionName = option.first; const OptionSpec &spec = option.second; printf(" [-%s", optionName.c_str()); if (spec.takeValue()) { if (spec.needsValue()) { printf(" <%s>", spec.getValueName().c_str()); } printf("]"); Loading @@ -74,11 +74,11 @@ void ArgumentsParser::printUsage(const std::string &commandName, const std::string &optionName = option.first; const OptionSpec &spec = option.second; printf(" -%s", optionName.c_str()); if (spec.takeValue()) { if (spec.needsValue()) { printf(" <%s>", spec.getValueName().c_str()); } printf("\t\t\t%s", spec.getDescription().c_str()); if (spec.takeValue() && !spec.getDefaultValue().empty()) { if (spec.needsValue() && !spec.getDefaultValue().empty()) { printf("\tdefault: %s", spec.getDefaultValue().c_str()); } printf("\n"); Loading @@ -89,10 +89,77 @@ void ArgumentsParser::printUsage(const std::string &commandName, printf("\n\n"); } const ArgumentsAndOptions ArgumentsParser::parseArguments(const int argc, char **argv) const { // TODO: Implement const ArgumentsAndOptions ArgumentsParser::parseArguments(const int argc, char **argv, const bool printErrorMessage) const { if (argc <= 0) { AKLOGE("Invalid argc (%d).", argc); ASSERT(false); return ArgumentsAndOptions(); } std::unordered_map<std::string, std::string> options; for (const auto &entry : mOptionSpecs) { const std::string &optionName = entry.first; const OptionSpec &optionSpec = entry.second; if (optionSpec.needsValue() && !optionSpec.getDefaultValue().empty()) { // Set default value. options[optionName] = optionSpec.getDefaultValue(); } } std::unordered_map<std::string, std::vector<std::string>> arguments; auto argumentSpecIt = mArgumentSpecs.cbegin(); for (int i = 1; i < argc; ++i) { const std::string arg = argv[i]; if (arg.length() > 1 && arg[0] == '-') { // option const std::string optionName = arg.substr(1); const auto it = mOptionSpecs.find(optionName); if (it == mOptionSpecs.end()) { if (printErrorMessage) { fprintf(stderr, "Unknown option: '%s'\n", optionName.c_str()); } return ArgumentsAndOptions(); } std::string optionValue; if (it->second.needsValue()) { ++i; if (i >= argc) { if (printErrorMessage) { fprintf(stderr, "Missing argument for option '%s'\n", optionName.c_str()); } return ArgumentsAndOptions(); } optionValue = argv[i]; } options[optionName] = optionValue; } else { // argument if (argumentSpecIt == mArgumentSpecs.end()) { if (printErrorMessage) { fprintf(stderr, "Too many arguments.\n"); } return ArgumentsAndOptions(); } arguments[argumentSpecIt->getName()].push_back(arg); if (arguments[argumentSpecIt->getName()].size() >= argumentSpecIt->getMaxCount()) { ++argumentSpecIt; } } } if (argumentSpecIt != mArgumentSpecs.end()) { const auto &it = arguments.find(argumentSpecIt->getName()); const size_t minCount = argumentSpecIt->getMinCount(); const size_t actualcount = it == arguments.end() ? 0 : it->second.size(); if (minCount > actualcount) { if (printErrorMessage) { fprintf(stderr, "Not enough arguments. %zd argumant(s) required for <%s>\n", minCount, argumentSpecIt->getName().c_str()); } return ArgumentsAndOptions(); } } return ArgumentsAndOptions(std::move(options), std::move(arguments)); } } // namespace dicttoolkit } // namespace latinime
native/dicttoolkit/src/utils/arguments_parser.h +18 −17 Original line number Diff line number Diff line Loading @@ -35,29 +35,29 @@ class OptionSpec { static OptionSpec keyValueOption(const std::string &valueName, const std::string &defaultValue, const std::string &description) { return OptionSpec(true /* takeValue */, valueName, defaultValue, description); return OptionSpec(true /* needsValue */, valueName, defaultValue, description); } static OptionSpec switchOption(const std::string &description) { return OptionSpec(false /* takeValue */, "" /* valueName */, "" /* defaultValue */, return OptionSpec(false /* needsValue */, "" /* valueName */, "" /* defaultValue */, description); } bool takeValue() const { return mTakeValue; } bool needsValue() const { return mNeedsValue; } const std::string &getValueName() const { return mValueName; } const std::string &getDefaultValue() const { return mDefaultValue; } const std::string &getDescription() const { return mDescription; } private: OptionSpec(const bool takeValue, const std::string &valueName, const std::string &defaultValue, OptionSpec(const bool needsValue, const std::string &valueName, const std::string &defaultValue, const std::string &description) : mTakeValue(takeValue), mValueName(valueName), mDefaultValue(defaultValue), : mNeedsValue(needsValue), mValueName(valueName), mDefaultValue(defaultValue), mDescription(description) {} // Whether the option have to be used with a value or just a switch. // e.g. 'f' in "command -f /path/to/file" is mTakeValue == true. // 'f' in "command -f -t" is mTakeValue == false. bool mTakeValue; // e.g. 'f' in "command -f /path/to/file" is mNeedsValue == true. // 'f' in "command -f -t" is mNeedsValue == false. bool mNeedsValue; // Name of the value used to show usage. std::string mValueName; std::string mDefaultValue; Loading @@ -66,32 +66,32 @@ class OptionSpec { class ArgumentSpec { public: static const int UNLIMITED_COUNT; static const size_t UNLIMITED_COUNT; static ArgumentSpec singleArgument(const std::string &name, const std::string &description) { return ArgumentSpec(name, 1 /* minCount */, 1 /* maxCount */, description); } static ArgumentSpec variableLengthArguments(const std::string &name, const int minCount, const int maxCount, const std::string &description) { static ArgumentSpec variableLengthArguments(const std::string &name, const size_t minCount, const size_t maxCount, const std::string &description) { return ArgumentSpec(name, minCount, maxCount, description); } const std::string &getName() const { return mName; } int getMinCount() const { return mMinCount; } int getMaxCount() const { return mMaxCount; } size_t getMinCount() const { return mMinCount; } size_t getMaxCount() const { return mMaxCount; } const std::string &getDescription() const { return mDescription; } private: DISALLOW_DEFAULT_CONSTRUCTOR(ArgumentSpec); ArgumentSpec(const std::string &name, const int minCount, const int maxCount, ArgumentSpec(const std::string &name, const size_t minCount, const size_t maxCount, const std::string &description) : mName(name), mMinCount(minCount), mMaxCount(maxCount), mDescription(description) {} const std::string mName; const int mMinCount; const int mMaxCount; const size_t mMinCount; const size_t mMaxCount; const std::string mDescription; }; Loading @@ -101,7 +101,8 @@ class ArgumentsParser { const std::vector<ArgumentSpec> &&argumentSpecs) : mOptionSpecs(std::move(optionSpecs)), mArgumentSpecs(std::move(argumentSpecs)) {} const ArgumentsAndOptions parseArguments(const int argc, char **argv) const; const ArgumentsAndOptions parseArguments(const int argc, char **argv, const bool printErrorMessage) const; bool validateSpecs() const; void printUsage(const std::string &commandName, const std::string &description) const; Loading
native/dicttoolkit/tests/utils/arguments_parser_test.cpp +74 −0 Original line number Diff line number Diff line Loading @@ -68,6 +68,80 @@ TEST(ArgumentsParserTests, TestValitadeSpecs) { } } int initArgv(char *mutableCommandLine, char **argv) { bool readingSeparator = false; int argc = 1; argv[0] = mutableCommandLine; const size_t length = strlen(mutableCommandLine); for (size_t i = 0; i < length; ++i) { if (mutableCommandLine[i] != ' ' && readingSeparator) { readingSeparator = false; argv[argc] = mutableCommandLine + i; ++argc; } else if (mutableCommandLine[i] == ' ' && !readingSeparator) { readingSeparator = true; mutableCommandLine[i] = '\0'; } } argv[argc] = nullptr; return argc; } TEST(ArgumentsParserTests, TestParseArguments) { std::unordered_map<std::string, OptionSpec> optionSpecs; optionSpecs["a"] = OptionSpec::switchOption("description"); optionSpecs["b"] = OptionSpec::keyValueOption("valueName", "default", "description"); const std::vector<ArgumentSpec> argumentSpecs = { ArgumentSpec::singleArgument("arg0", "description"), ArgumentSpec::variableLengthArguments("arg1", 0 /* minCount */, 2 /* maxCount */, "description"), }; const ArgumentsParser parser = ArgumentsParser(std::move(optionSpecs), std::move(argumentSpecs)); { char kMutableCommandLine[1024] = "command arg"; char *argv[128] = {}; const int argc = initArgv(kMutableCommandLine, argv); ASSERT_EQ(2, argc); const ArgumentsAndOptions argumentsAndOptions = parser.parseArguments( argc, argv, false /* printErrorMessages */); EXPECT_FALSE(argumentsAndOptions.hasOption("a")); EXPECT_EQ("default", argumentsAndOptions.getOptionValue("b")); EXPECT_EQ("arg", argumentsAndOptions.getSingleArgument("arg0")); EXPECT_FALSE(argumentsAndOptions.hasArgument("arg1")); } { char kArgumentBuffer[1024] = "command -a arg arg"; char *argv[128] = {}; const int argc = initArgv(kArgumentBuffer, argv); ASSERT_EQ(4, argc); const ArgumentsAndOptions argumentsAndOptions = parser.parseArguments( argc, argv, false /* printErrorMessages */); EXPECT_TRUE(argumentsAndOptions.hasOption("a")); EXPECT_EQ("default", argumentsAndOptions.getOptionValue("b")); EXPECT_EQ("arg", argumentsAndOptions.getSingleArgument("arg0")); EXPECT_TRUE(argumentsAndOptions.hasArgument("arg1")); EXPECT_EQ(1u, argumentsAndOptions.getVariableLengthArguments("arg1").size()); } { char kArgumentBuffer[1024] = "command -b value arg arg1 arg2"; char *argv[128] = {}; const int argc = initArgv(kArgumentBuffer, argv); ASSERT_EQ(6, argc); const ArgumentsAndOptions argumentsAndOptions = parser.parseArguments( argc, argv, false /* printErrorMessages */); EXPECT_FALSE(argumentsAndOptions.hasOption("a")); EXPECT_EQ("value", argumentsAndOptions.getOptionValue("b")); EXPECT_EQ("arg", argumentsAndOptions.getSingleArgument("arg0")); const std::vector<std::string> &arg1 = argumentsAndOptions.getVariableLengthArguments("arg1"); EXPECT_EQ(2u, arg1.size()); EXPECT_EQ("arg1", arg1[0]); EXPECT_EQ("arg2", arg1[1]); } } } // namespace } // namespace dicttoolkit } // namespace latinime