/* Copyright 2013 10gen Inc. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License, version 3, * as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . * * As a special exception, the copyright holders give permission to link the * code of portions of this program with the OpenSSL library under certain * conditions as described in each individual source file and distribute * linked combinations including the program with the OpenSSL library. You * must comply with the GNU Affero General Public License in all respects * for all of the code used other than as permitted herein. If you modify * file(s) with this exception, you may extend this exception to your * version of the file(s), but you are not obligated to do so. If you do not * wish to do so, delete this exception statement from your version. If you * delete this exception statement from all source files in the program, * then also delete it in the license file. */ #pragma once #include #include #include "mongo/base/status.h" #include "mongo/util/options_parser/constraints.h" #include "mongo/util/options_parser/value.h" namespace mongo { namespace optionenvironment { /** * An OptionType is an enum of all the types we support in the OptionsParser * * NOTE(sverch): The semantics of "Switch" options are completely identical to "Bool" options, * except that on the command line they do not take a value. */ enum OptionType { StringVector, // po::value< std::vector > StringMap, // po::value< std::vector > (but in "key=value" format) Bool, // po::value Double, // po::value Int, // po::value Long, // po::value String, // po::value UnsignedLongLong, // po::value Unsigned, // po::value Switch // po::bool_switch }; /** * An OptionSources is an enum representing where an option can come from */ enum OptionSources { SourceCommandLine = 1, SourceINIConfig = 2, SourceYAMLConfig = 4, SourceAllConfig = SourceINIConfig | SourceYAMLConfig, SourceAllLegacy = SourceINIConfig | SourceCommandLine, SourceAll = SourceCommandLine | SourceINIConfig | SourceYAMLConfig }; /** * The OptionDescription class is a container for information about the options we are expecting * either on the command line or in config files. These should be registered in an * OptionSection instance and passed to an OptionsParser. */ class OptionDescription { public: OptionDescription(const std::string& dottedName, const std::string& singleName, const OptionType type, const std::string& description); OptionDescription(const std::string& dottedName, const std::string& singleName, const OptionType type, const std::string& description, const std::vector& deprecatedDottedNames); /* * The following functions are part of the chaining interface for option registration. See * comments below for what each of these attributes mean, and the OptionSection class for * more details on the chaining interface. */ /** * Parsing Attributes. * * The functions below specify various attributes of our option that are relevant for * parsing. */ /* * Make this option hidden so it does not appear in command line help */ OptionDescription& hidden(); /* * Add a default value for this option if it is not specified * * throws DBException on errors, such as trying to set a default that does not have the same * type as the option, or trying to set a default for a composing option. */ OptionDescription& setDefault(Value defaultValue); /* * Add an implicit value for this option if it is specified with no argument * * throws DBException on errors, such as trying to set an implicit value that does not have * the same type as the option, or trying to set an implicit value for a composing option. */ OptionDescription& setImplicit(Value implicitValue); /* * Make this option composing so that the different sources add their values instead of * overriding (eg. setParameter values in the config file and on the command line all get * aggregated together) * * throws DBException on errors, such as trying to make an option that is not a vector type * composing, or or trying to set an implicit or default value for a composing option. */ OptionDescription& composing(); /* * Specify the allowed sources for this option, such as CommandLine, JSONConfig, or * INIConfig. The default is SourceAll which means the option can be present in any source */ OptionDescription& setSources(OptionSources sources); /* * Specify that this is a positional option. "start" should be the first position the * option can be found in, and "end" is the last position, inclusive. The positions start * at index 1 (after the executable name). If "start" is greater than "end", then the * option must be able to support multiple values. Specifying -1 for the "end" means that * the option can repeat forever. Any "holes" in the positional ranges will result in an * error during parsing. * * Examples: * * .positional(1,1) // Single positional argument at position 1 * ... * .positional(2,3) // More positional arguments at position 2 and 3 (multivalued option) * ... * .positional(4,-1) // Can repeat this positional option forever after position 4 * * * (sverch) TODO: When we can support it (i.e. when we can get rid of boost) add a * "positionalOnly" attribute that specifies that it is not also a command line flag. In * boost program options, the only way to have a positional argument is to register a flag * and mark it as also being positional. */ OptionDescription& positional(int start, int end); /** * Validation Constraints. * * The functions below specify constraints that must be met in order for this option to be * valid. These do not get checked during parsing, but will be added to the result * Environment so that they will get checked when the Environment is validated. */ /** * Specifies the range allowed for this option. Only allowed for options with numeric type. */ OptionDescription& validRange(long min, long max); /** * Specifies that this option is incompatible with another option. The std::string provided must * be the dottedName, which is the name used to access the option in the result Environment. * * TODO: Find a way to check that that option actually exists in our section somewhere. */ OptionDescription& incompatibleWith(const std::string& otherDottedName); /** * Specifies that this option is requires another option to be specified. The string * provided must be the dottedName, which is the name used to access the option in the * result Environment. */ OptionDescription& requires(const std::string& otherDottedName); /** * Specifies that this option is required to match the given format, specified as a regular * expression. The displayFormat argument is what gets printed to the user in the case * where this constraint is not satisfied. This is only allowed on std::string options. */ OptionDescription& format(const std::string& regexFormat, const std::string& displayFormat); /** * Adds a constraint for this option. During parsing, this Constraint will be added to the * result Environment, ensuring that it will get checked when the environment is validated. * See the documentation on the Constraint and Environment classes for more details. * * WARNING: This function takes ownership of the Constraint pointer that is passed in. */ OptionDescription& addConstraint(Constraint* c); std::string _dottedName; // Used for JSON config and in Environment std::string _singleName; // Used for boost command line and INI OptionType _type; // Storage type of the argument value, or switch type (bool) // (required by boost) std::string _description; // Description of option printed in help output bool _isVisible; // Visible in help output Value _default; // Value if option is not specified Value _implicit; // Value if option is specified with no argument bool _isComposing; // Aggregate values from different sources instead of overriding OptionSources _sources; // Places where an option can be specified (current sources are // command line, json config, and ini config) int _positionalStart; // The starting position if this is a positional option. -1 otherwise. int _positionalEnd; // The ending position if this is a positional option. -1 if unlimited. // TODO(sverch): We have to use pointers to keep track of the Constrants because we rely on // inheritance to make Constraints work. We have to use shared_ptrs because the // OptionDescription is sometimes copied and because it is stored in a std::list in the // OptionSection. We should think about a better solution for the ownership semantics of // these classes. Note that the Environment (the storage for results of option parsing) has // to know about the constraints for all the options, which is another factor to consider // when thinking about ownership. std::vector > _constraints; // Constraints that must be met // for this option to be valid // Deprecated dotted names - aliases for '_dottedName'. std::vector _deprecatedDottedNames; }; } // namespace optionenvironment } // namespace mongo