diff options
Diffstat (limited to 'heimdall/source/Arguments.cpp')
-rw-r--r-- | heimdall/source/Arguments.cpp | 212 |
1 files changed, 212 insertions, 0 deletions
diff --git a/heimdall/source/Arguments.cpp b/heimdall/source/Arguments.cpp new file mode 100644 index 0000000..321c12f --- /dev/null +++ b/heimdall/source/Arguments.cpp @@ -0,0 +1,212 @@ +/* Copyright (c) 2010-2012 Benjamin Dobell, Glass Echidna + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE.*/ + +// Heimdall +#include "Arguments.h" +#include "Heimdall.h" +#include "Interface.h" +#include "Utility.h" + +using namespace Heimdall; + +FlagArgument *FlagArgument::ParseArgument(int argc, char **argv, int& argi) +{ + return new FlagArgument(); +} + + + +StringArgument *StringArgument::ParseArgument(int argc, char **argv, int& argi) +{ + if (++argi < argc) + { + return (new StringArgument(argv[argi])); + } + else + { + Interface::Print("Missing parameter for argument: %s\n\n", argv[argi - 1]); + return (nullptr); + } +} + + + +UnsignedIntegerArgument *UnsignedIntegerArgument::ParseArgument(int argc, char **argv, int& argi) +{ + UnsignedIntegerArgument *unsignedIntegerArgument = nullptr; + + if (++argi < argc) + { + unsigned int value; + + if (Utility::ParseUnsignedInt(value, argv[argi]) == kNumberParsingStatusSuccess) + unsignedIntegerArgument = new UnsignedIntegerArgument(value); + else + Interface::Print("%s must be a positive integer.", argv[argi - 1]); + } + else + { + Interface::Print("Missing parameter for argument: %s\n\n", argv[argi - 1]); + } + + return (unsignedIntegerArgument); +} + + + +Arguments::Arguments(const map<string, ArgumentType>& argumentTypes, const map<string, string>& shortArgumentAliases, + const map<string, string> argumentAliases) : + argumentTypes(argumentTypes), + shortArgumentAliases(shortArgumentAliases), + argumentAliases(argumentAliases) +{ +} + +Arguments::~Arguments() +{ + for (map<string, Argument *>::const_iterator it = arguments.begin(); it != arguments.end(); it++) + delete it->second; +} + +bool Arguments::ParseArguments(int argc, char **argv, int argi) +{ + for (; argi < argc; ++argi) + { + string argumentName = argv[argi]; + string nonwildcardArgumentName; + + if (argumentName.find_first_of("--") == 0) + { + // Regular argument + argumentName = argumentName.substr(2); + nonwildcardArgumentName = argumentName; + } + else if (argumentName.find_first_of("-") == 0) + { + // Short argument alias + string shortArgumentAlias = argumentName.substr(1); + map<string, string>::const_iterator shortAliasIt = shortArgumentAliases.find(shortArgumentAlias); + + if (shortAliasIt != shortArgumentAliases.end()) + { + argumentName = shortAliasIt->second; + nonwildcardArgumentName = argumentName; + } + else + { + Interface::Print("Unknown argument: %s\n\n", argv[argi]); + return (false); + } + } + else + { + Interface::Print("Invalid argument: %s\n\n", argv[argi]); + return (false); + } + + map<string, ArgumentType>::const_iterator argumentTypeIt = argumentTypes.find(argumentName); + + if (argumentTypeIt == argumentTypes.end()) + { + // No argument with that name, maybe it's an alias... + map<string, string>::const_iterator aliasIt = argumentAliases.find(argumentName); + + if (aliasIt != argumentAliases.end()) + { + argumentName = aliasIt->second; + nonwildcardArgumentName = argumentName; + + argumentTypeIt = argumentTypes.find(argumentName); + } + } + + // Handle wilcards + + unsigned int unsignedIntName; + + if (argumentTypeIt == argumentTypes.end()) + { + // Look for the unsigned integer wildcard "%d". + if (Utility::ParseUnsignedInt(unsignedIntName, argumentName.c_str()) == kNumberParsingStatusSuccess) + { + argumentTypeIt = argumentTypes.find("%d"); + argumentName = "%d"; + } + + // Look for the string wildcard "%s" + if (argumentTypeIt == argumentTypes.end()) + { + argumentTypeIt = argumentTypes.find("%s"); + argumentName = "%s"; + } + } + + Argument *argument = nullptr; + + if (argumentTypeIt != argumentTypes.end()) + { + switch (argumentTypeIt->second) + { + case kArgumentTypeFlag: + argument = FlagArgument::ParseArgument(argc, argv, argi); + break; + + case kArgumentTypeString: + argument = StringArgument::ParseArgument(argc, argv, argi); + break; + + case kArgumentTypeUnsignedInteger: + argument = UnsignedIntegerArgument::ParseArgument(argc, argv, argi); + break; + + default: + Interface::Print("Unknown argument type: %s\n\n", argv[argi]); + break; + } + } + else + { + Interface::Print("Unknown argument: %s\n\n", argv[argi]); + } + + // We don't want to insert wild-cards into our argument map. + if (argumentName == "%d" || argumentName == "%s") + argumentName = nonwildcardArgumentName; + + if (argument) + { + pair<map<string, Argument *>::iterator, bool> insertResult = arguments.insert(pair<string, Argument *>(argumentName, argument)); + + if (!insertResult.second) + { + Interface::Print("Duplicate argument: %s (%s)\n\n", argv[argi], insertResult.first->first.c_str()); + delete argument; + + return (false); + } + } + else + { + return (false); + } + } + + return (true); +} |