changes (part 1) from 1.4.3 branch (XMLConfiguration delimiter, OptionProcessor)

This commit is contained in:
Marian Krivos 2011-11-15 13:59:05 +00:00
Родитель 97ec3f5bf6
Коммит cc90b38ae5
6 изменённых файлов: 245 добавлений и 119 удалений

Просмотреть файл

@ -55,13 +55,13 @@ class Util_API OptionProcessor
/// An OptionProcessor is used to process the command line
/// arguments of an application.
///
/// The process() method takes an argument from the command line.
/// If that argument starts with an option prefix, the argument
/// is further processed. Otherwise, the argument is ignored and
/// false is ignored. The argument must match one of the options
/// given in the OptionSet that is passed to the OptionProcessor
/// with the constructor. If an option is part of a group, at most
/// one option of the group can be passed to the OptionProcessor.
/// The process() method takes an argument from the command line.
/// If that argument starts with an option prefix, the argument
/// is further processed. Otherwise, the argument is ignored and
/// false is returned. The argument must match one of the options
/// given in the OptionSet that is passed to the OptionProcessor
/// with the constructor. If an option is part of a group, at most
/// one option of the group can be passed to the OptionProcessor.
/// Otherwise an IncompatibleOptionsException is thrown.
/// If the same option is given multiple times, but the option
/// is not repeatable, a DuplicateOptionException is thrown.
@ -79,12 +79,22 @@ class Util_API OptionProcessor
/// by a short option name, or another dash, followed by a (partial)
/// long option name.
/// In default mode, the option prefix is a slash '/', followed by
/// a (partial) long option name.
/// If the special option '--' is encountered in Unix mode, all following
/// options are ignored.
/// a (partial) long option name.
/// If the special option '--' is encountered in Unix mode, all following
/// options are ignored.
///
/// Option arguments can be specified in three ways. If a Unix short option
/// ("-o") is given, the argument directly follows the option name, without
/// any delimiting character or space ("-ovalue"). In default option mode, or if a
/// Unix long option ("--option") is given, the option argument is
/// delimited from the option name with either an equal sign ('=') or
/// a colon (':'), as in "--option=value" or "/option:value". Finally,
/// a required option argument can be specified on the command line after the
/// option, delimited with a space, as in "--option value" or "-o value".
/// The latter only works for required option arguments, not optional ones.
{
public:
OptionProcessor(const OptionSet& options);
OptionProcessor(const OptionSet& options);
/// Creates the OptionProcessor, using the given OptionSet.
~OptionProcessor();
@ -127,9 +137,10 @@ private:
const OptionSet& _options;
bool _unixStyle;
bool _ignore;
std::set<std::string> _groups;
std::set<std::string> _specifiedOptions;
bool _ignore;
std::set<std::string> _groups;
std::set<std::string> _specifiedOptions;
std::string _deferredOption;
};

Просмотреть файл

@ -86,35 +86,68 @@ class Util_API XMLConfiguration: public AbstractConfiguration
/// prop5[1] -> value6
/// prop5[@id=first] -> value5
/// prop5[@id='second'] -> value6
///
/// Enumerating attributes is not supported.
/// Calling keys("prop3.prop4") will return an empty range.
///
/// Enumerating attributes is not supported.
/// Calling keys("prop3.prop4") will return an empty range.
///
/// As a special feature, the delimiter character used to delimit
/// property names can be changed to something other than period ('.') by
/// passing the desired character to the constructor. This allows
/// working with XML documents having element names with periods
/// in them.
{
public:
XMLConfiguration();
/// Creates an empty XMLConfiguration.
XMLConfiguration();
/// Creates an empty XMLConfiguration.
XMLConfiguration(Poco::XML::InputSource* pInputSource);
/// Creates an XMLConfiguration and loads the XML document from
/// the given InputSource.
XMLConfiguration(char delim);
/// Creates an empty XMLConfiguration, using the given
/// delimiter char instead of the default '.'.
XMLConfiguration(std::istream& istr);
/// Creates an XMLConfiguration and loads the XML document from
/// the given stream.
XMLConfiguration(Poco::XML::InputSource* pInputSource);
/// Creates an XMLConfiguration and loads the XML document from
/// the given InputSource.
XMLConfiguration(const std::string& path);
/// Creates an XMLConfiguration and loads the XML document from
/// the given path.
XMLConfiguration(Poco::XML::InputSource* pInputSource, char delim);
/// Creates an XMLConfiguration and loads the XML document from
/// the given InputSource. Uses the given delimiter char instead
/// of the default '.'.
XMLConfiguration(const Poco::XML::Document* pDocument);
/// Creates the XMLConfiguration using the given XML document.
XMLConfiguration(const Poco::XML::Node* pNode);
/// Creates the XMLConfiguration using the given XML node.
XMLConfiguration(std::istream& istr);
/// Creates an XMLConfiguration and loads the XML document from
/// the given stream.
void load(Poco::XML::InputSource* pInputSource);
/// Loads the XML document containing the configuration data
/// from the given InputSource.
XMLConfiguration(std::istream& istr, char delim);
/// Creates an XMLConfiguration and loads the XML document from
/// the given stream. Uses the given delimiter char instead
/// of the default '.'.
XMLConfiguration(const std::string& path);
/// Creates an XMLConfiguration and loads the XML document from
/// the given path.
XMLConfiguration(const std::string& path, char delim);
/// Creates an XMLConfiguration and loads the XML document from
/// the given path. Uses the given delimiter char instead
/// of the default '.'.
XMLConfiguration(const Poco::XML::Document* pDocument);
/// Creates the XMLConfiguration using the given XML document.
XMLConfiguration(const Poco::XML::Document* pDocument, char delim);
/// Creates the XMLConfiguration using the given XML document.
/// Uses the given delimiter char instead of the default '.'.
XMLConfiguration(const Poco::XML::Node* pNode);
/// Creates the XMLConfiguration using the given XML node.
XMLConfiguration(const Poco::XML::Node* pNode, char delim);
/// Creates the XMLConfiguration using the given XML node.
/// Uses the given delimiter char instead of the default '.'.
void load(Poco::XML::InputSource* pInputSource);
/// Loads the XML document containing the configuration data
/// from the given InputSource.
void load(std::istream& istr);
/// Loads the XML document containing the configuration data
@ -164,16 +197,17 @@ protected:
~XMLConfiguration();
private:
const Poco::XML::Node* findNode(const std::string& key) const;
Poco::XML::Node* findNode(const std::string& key);
static Poco::XML::Node* findNode(std::string::const_iterator& it, const std::string::const_iterator& end, Poco::XML::Node* pNode, bool create = false);
static Poco::XML::Node* findElement(const std::string& name, Poco::XML::Node* pNode, bool create);
static Poco::XML::Node* findElement(int index, Poco::XML::Node* pNode, bool create);
static Poco::XML::Node* findElement(const std::string& attr, const std::string& value, Poco::XML::Node* pNode);
const Poco::XML::Node* findNode(const std::string& key) const;
Poco::XML::Node* findNode(const std::string& key);
Poco::XML::Node* findNode(std::string::const_iterator& it, const std::string::const_iterator& end, Poco::XML::Node* pNode, bool create = false) const;
static Poco::XML::Node* findElement(const std::string& name, Poco::XML::Node* pNode, bool create);
static Poco::XML::Node* findElement(int index, Poco::XML::Node* pNode, bool create);
static Poco::XML::Node* findElement(const std::string& attr, const std::string& value, Poco::XML::Node* pNode);
static Poco::XML::Node* findAttribute(const std::string& name, Poco::XML::Node* pNode, bool create);
Poco::XML::AutoPtr<Poco::XML::Node> _pRoot;
Poco::XML::AutoPtr<Poco::XML::Document> _pDocument;
Poco::XML::AutoPtr<Poco::XML::Node> _pRoot;
Poco::XML::AutoPtr<Poco::XML::Document> _pDocument;
char _delim;
};

Просмотреть файл

@ -116,15 +116,15 @@ void Application::setup()
_pConfig->add(new SystemConfiguration, PRIO_SYSTEM, false, false);
_pConfig->add(new MapConfiguration, PRIO_APPLICATION, true, false);
addSubsystem(new LoggingSubsystem);
addSubsystem(new LoggingSubsystem);
#if defined(POCO_OS_FAMILY_UNIX) && !defined(POCO_VXWORKS)
_workingDirAtLaunch = Path::current();
_workingDirAtLaunch = Path::current();
#if !defined(_DEBUG)
Poco::SignalHandler::install();
#endif
#if !defined(_DEBUG)
Poco::SignalHandler::install();
#endif
#else
setUnixOptions(false);
#endif
@ -368,13 +368,13 @@ void Application::processOptions()
while (it != _args.end() && !_stopOptionsProcessing)
{
std::string name;
std::string value;
if (processor.process(*it, name, value))
{
if (!name.empty()) // "--" option to end options processing
{
handleOption(name, value);
}
std::string value;
if (processor.process(*it, name, value))
{
if (!name.empty()) // "--" option to end options processing or deferred argument
{
handleOption(name, value);
}
it = _args.erase(it);
}
else ++it;
@ -393,19 +393,19 @@ void Application::getApplicationPath(Poco::Path& appPath) const
if (path.isAbsolute())
{
appPath = path;
}
else
{
appPath = _workingDirAtLaunch;
appPath.append(path);
}
}
else
{
if (!Path::find(Environment::get("PATH"), _command, appPath))
appPath = Path(_workingDirAtLaunch, _command);
appPath.makeAbsolute();
}
}
else
{
appPath = _workingDirAtLaunch;
appPath.append(path);
}
}
else
{
if (!Path::find(Environment::get("PATH"), _command, appPath))
appPath = Path(_workingDirAtLaunch, _command);
appPath.makeAbsolute();
}
#elif defined(POCO_OS_FAMILY_WINDOWS)
#if defined(POCO_WIN32_UTF8) && !defined(POCO_NO_WSTRING)
wchar_t path[1024];

Просмотреть файл

@ -173,12 +173,20 @@ int HelpFormatter::calcIndent() const
void HelpFormatter::formatOptions(std::ostream& ostr) const
{
int optWidth = calcIndent();
for (OptionSet::Iterator it = _options.begin(); it != _options.end(); ++it)
{
formatOption(ostr, *it, optWidth);
formatText(ostr, it->description(), _indent, optWidth);
ostr << '\n';
}
for (OptionSet::Iterator it = _options.begin(); it != _options.end(); ++it)
{
formatOption(ostr, *it, optWidth);
if (_indent < optWidth)
{
ostr << '\n' << std::string(_indent, ' ');
formatText(ostr, it->description(), _indent, _indent);
}
else
{
formatText(ostr, it->description(), _indent, optWidth);
}
ostr << '\n';
}
}

Просмотреть файл

@ -65,12 +65,16 @@ void OptionProcessor::setUnixStyle(bool flag)
bool OptionProcessor::process(const std::string& argument, std::string& optionName, std::string& optionArg)
{
if (!_ignore)
{
if (_unixStyle)
return processUnix(argument, optionName, optionArg);
else
return processDefault(argument, optionName, optionArg);
optionName.clear();
optionArg.clear();
if (!_ignore)
{
if (!_deferredOption.empty())
return processCommon(argument, false, optionName, optionArg);
else if (_unixStyle)
return processUnix(argument, optionName, optionArg);
else
return processDefault(argument, optionName, optionArg);
}
return false;
}
@ -80,9 +84,15 @@ void OptionProcessor::checkRequired() const
{
for (OptionSet::Iterator it = _options.begin(); it != _options.end(); ++it)
{
if (it->required() && _specifiedOptions.find(it->fullName()) == _specifiedOptions.end())
throw MissingOptionException(it->fullName());
}
if (it->required() && _specifiedOptions.find(it->fullName()) == _specifiedOptions.end())
throw MissingOptionException(it->fullName());
}
if (!_deferredOption.empty())
{
std::string optionArg;
const Option& option = _options.getOption(_deferredOption, false);
option.process(_deferredOption, optionArg); // will throw MissingArgumentException
}
}
@ -133,9 +143,20 @@ bool OptionProcessor::processDefault(const std::string& argument, std::string& o
bool OptionProcessor::processCommon(const std::string& optionStr, bool isShort, std::string& optionName, std::string& optionArg)
{
if (optionStr.empty()) throw EmptyOptionException();
const Option& option = _options.getOption(optionStr, isShort);
const std::string& group = option.group();
if (!_deferredOption.empty())
{
const Option& option = _options.getOption(_deferredOption, false);
std::string optionWithArg(_deferredOption);
_deferredOption.clear();
optionWithArg += '=';
optionWithArg += optionStr;
option.process(optionWithArg, optionArg);
optionName = option.fullName();
return true;
}
if (optionStr.empty()) throw EmptyOptionException();
const Option& option = _options.getOption(optionStr, isShort);
const std::string& group = option.group();
if (!group.empty())
{
if (_groups.find(group) != _groups.end())
@ -143,12 +164,17 @@ bool OptionProcessor::processCommon(const std::string& optionStr, bool isShort,
else
_groups.insert(group);
}
if (_specifiedOptions.find(option.fullName()) != _specifiedOptions.end() && !option.repeatable())
throw DuplicateOptionException(option.fullName());
_specifiedOptions.insert(option.fullName());
option.process(optionStr, optionArg);
optionName = option.fullName();
return true;
if (_specifiedOptions.find(option.fullName()) != _specifiedOptions.end() && !option.repeatable())
throw DuplicateOptionException(option.fullName());
_specifiedOptions.insert(option.fullName());
if (option.argumentRequired() && ((!isShort && optionStr.find_first_of(":=") == std::string::npos) || (isShort && optionStr.length() == option.shortName().length())))
{
_deferredOption = option.fullName();
return true;
}
option.process(optionStr, optionArg);
optionName = option.fullName();
return true;
}

Просмотреть файл

@ -51,38 +51,85 @@ namespace Poco {
namespace Util {
XMLConfiguration::XMLConfiguration()
XMLConfiguration::XMLConfiguration():
_delim('.')
{
}
XMLConfiguration::XMLConfiguration(Poco::XML::InputSource* pInputSource)
XMLConfiguration::XMLConfiguration(char delim):
_delim(delim)
{
load(pInputSource);
}
XMLConfiguration::XMLConfiguration(std::istream& istr)
XMLConfiguration::XMLConfiguration(Poco::XML::InputSource* pInputSource):
_delim('.')
{
load(istr);
load(pInputSource);
}
XMLConfiguration::XMLConfiguration(const std::string& path)
XMLConfiguration::XMLConfiguration(Poco::XML::InputSource* pInputSource, char delim):
_delim(delim)
{
load(path);
load(pInputSource);
}
XMLConfiguration::XMLConfiguration(const Poco::XML::Document* pDocument)
XMLConfiguration::XMLConfiguration(std::istream& istr):
_delim('.')
{
load(pDocument);
load(istr);
}
XMLConfiguration::XMLConfiguration(const Poco::XML::Node* pNode)
XMLConfiguration::XMLConfiguration(std::istream& istr, char delim):
_delim(delim)
{
load(pNode);
load(istr);
}
XMLConfiguration::XMLConfiguration(const std::string& path):
_delim('.')
{
load(path);
}
XMLConfiguration::XMLConfiguration(const std::string& path, char delim):
_delim(delim)
{
load(path);
}
XMLConfiguration::XMLConfiguration(const Poco::XML::Document* pDocument):
_delim('.')
{
load(pDocument);
}
XMLConfiguration::XMLConfiguration(const Poco::XML::Document* pDocument, char delim):
_delim(delim)
{
load(pDocument);
}
XMLConfiguration::XMLConfiguration(const Poco::XML::Node* pNode):
_delim('.')
{
load(pNode);
}
XMLConfiguration::XMLConfiguration(const Poco::XML::Node* pNode, char delim):
_delim(delim)
{
load(pNode);
}
@ -294,10 +341,10 @@ Poco::XML::Node* XMLConfiguration::findNode(const std::string& key)
}
Poco::XML::Node* XMLConfiguration::findNode(std::string::const_iterator& it, const std::string::const_iterator& end, Poco::XML::Node* pNode, bool create)
Poco::XML::Node* XMLConfiguration::findNode(std::string::const_iterator& it, const std::string::const_iterator& end, Poco::XML::Node* pNode, bool create) const
{
if (pNode && it != end)
{
if (pNode && it != end)
{
if (*it == '[')
{
++it;
@ -336,15 +383,15 @@ Poco::XML::Node* XMLConfiguration::findNode(std::string::const_iterator& it, con
if (it != end) ++it;
return findNode(it, end, findElement(Poco::NumberParser::parse(index), pNode, create), create);
}
}
else
{
while (it != end && *it == '.') ++it;
std::string key;
while (it != end && *it != '.' && *it != '[') key += *it++;
return findNode(it, end, findElement(key, pNode, create), create);
}
}
}
else
{
while (it != end && *it == _delim) ++it;
std::string key;
while (it != end && *it != _delim && *it != '[') key += *it++;
return findNode(it, end, findElement(key, pNode, create), create);
}
}
else return pNode;
}