mirror of https://gitee.com/bigwinds/arangodb
168 lines
4.5 KiB
C++
168 lines
4.5 KiB
C++
////////////////////////////////////////////////////////////////////////////////
|
|
/// DISCLAIMER
|
|
///
|
|
/// Copyright 2016 ArangoDB GmbH, Cologne, Germany
|
|
///
|
|
/// 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.
|
|
///
|
|
/// Copyright holder is ArangoDB GmbH, Cologne, Germany
|
|
///
|
|
/// @author Jan Steemann
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
#ifndef ARANGODB_PROGRAM_OPTIONS_ARGUMENT_PARSER_H
|
|
#define ARANGODB_PROGRAM_OPTIONS_ARGUMENT_PARSER_H 1
|
|
|
|
#include "Basics/Common.h"
|
|
|
|
#include "ProgramOptions/ProgramOptions.h"
|
|
|
|
namespace arangodb {
|
|
namespace options {
|
|
|
|
class ArgumentParser {
|
|
public:
|
|
explicit ArgumentParser(ProgramOptions* options) : _options(options) {}
|
|
|
|
// get the name of the section for which help was requested, and "*" if only
|
|
// --help was specified
|
|
std::string helpSection(int argc, char* argv[]) {
|
|
for (int i = 1; i < argc; ++i) {
|
|
std::string const current(argv[i]);
|
|
|
|
if (current == "--") {
|
|
break;
|
|
}
|
|
|
|
if (current.size() >= 6 && current.substr(0, 6) == "--help") {
|
|
if (current.size() <= 7) {
|
|
return "*";
|
|
}
|
|
return current.substr(7);
|
|
}
|
|
}
|
|
return "";
|
|
}
|
|
|
|
// parse options from argc/argv. returns true if all is well, false otherwise
|
|
// errors that occur during parse are reported to _options
|
|
bool parse(int argc, char* argv[]) {
|
|
// set context for parsing (used in error messages)
|
|
_options->setContext("command-line options");
|
|
|
|
std::string lastOption;
|
|
bool optionsDone = false;
|
|
|
|
for (int i = 1; i < argc; ++i) {
|
|
std::string option;
|
|
std::string value;
|
|
std::string const current(argv[i]);
|
|
|
|
if (!lastOption.empty()) {
|
|
option = lastOption;
|
|
}
|
|
|
|
if (!option.empty()) {
|
|
value = current;
|
|
} else {
|
|
if (current == "--") {
|
|
optionsDone = true;
|
|
continue;
|
|
}
|
|
|
|
option = current;
|
|
|
|
size_t dashes = 0;
|
|
|
|
if (! optionsDone) {
|
|
if (option.substr(0, 2) == "--") {
|
|
dashes = 2;
|
|
} else if (option.substr(0, 1) == "-") {
|
|
dashes = 1;
|
|
}
|
|
}
|
|
|
|
if (dashes == 0) {
|
|
_options->addPositional(option);
|
|
continue;
|
|
}
|
|
|
|
option = option.substr(dashes);
|
|
|
|
size_t const pos = option.find('=');
|
|
|
|
if (pos == std::string::npos) {
|
|
// only option
|
|
if (dashes == 1) {
|
|
option = _options->translateShorthand(option);
|
|
}
|
|
if (!_options->require(option)) {
|
|
return false;
|
|
}
|
|
|
|
if (!_options->requiresValue(option)) {
|
|
// option does not require a parameter
|
|
std::string nextValue;
|
|
if (i + 1 < argc) {
|
|
// we have a next option. check if its true or false
|
|
std::string const next(argv[i + 1]);
|
|
if (next == "true" || next == "false" ||
|
|
next == "on" || next == "off" ||
|
|
next == "1" || next == "0") {
|
|
nextValue = next;
|
|
++i; // skip next argument when continuing the parsing
|
|
}
|
|
}
|
|
if (!_options->setValue(option, nextValue)) {
|
|
return false;
|
|
}
|
|
} else {
|
|
// option requires a parameter
|
|
lastOption = option;
|
|
}
|
|
continue;
|
|
} else {
|
|
// option = value
|
|
value = option.substr(pos + 1);
|
|
option = option.substr(0, pos);
|
|
if (dashes == 1) {
|
|
option = _options->translateShorthand(option);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!_options->setValue(option, value)) {
|
|
return false;
|
|
}
|
|
lastOption = "";
|
|
}
|
|
|
|
// we got some previous option, but no value was specified for it
|
|
if (!lastOption.empty()) {
|
|
return _options->fail("no value specified for option '--" + lastOption +
|
|
"'");
|
|
}
|
|
|
|
// all is well
|
|
_options->endPass();
|
|
return true;
|
|
}
|
|
|
|
private:
|
|
ProgramOptions* _options;
|
|
};
|
|
}
|
|
}
|
|
|
|
#endif
|