genode/repos/os/src/app/cli_monitor/command_line.h

171 lines
3.5 KiB
C++

/*
* \brief Utility for command-line parsing
* \author Norman Feske
* \date 2013-03-18
*/
/*
* Copyright (C) 2013 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2.
*/
#ifndef _COMMAND_LINE_H_
#define _COMMAND_LINE_H_
#include <line_editor.h>
class Command_line
{
private:
char const *_cmd_line;
Command &_command;
bool _parameter_is_known(Token token)
{
return Argument_tracker::lookup(token, _command.parameters()) != 0;
}
Token _tag_token(char const *tag)
{
for (Token token(_cmd_line); token; token = token.next())
if (strcmp(token.start(), tag, token.len()) == 0
&& strlen(tag) == token.len()
&& _parameter_is_known(token))
return token;
return Token();
}
Token _value_token(char const *tag)
{
return _tag_token(tag).next().next();
}
static bool _is_parameter(Token token)
{
return token[0] == '-' && token[1] == '-';
}
public:
/**
* Constructor
*
* \param cmd_line null-terminated command line string
* \param command meta data about the command
*/
Command_line(char const *cmd_line, Command &command)
: _cmd_line(cmd_line), _command(command) { }
/**
* Return true if tag is specified at the command line
*/
bool parameter_exists(char const *tag)
{
return _tag_token(tag);
}
/**
* Return number argument specified for the given tag
*/
template <typename T>
bool parameter(char const *tag, T &result)
{
Token value = _value_token(tag);
return value && Genode::ascii_to(value.start(), result) != 0;
}
/**
* Return string argument specified for the given tag
*/
bool parameter(char const *tag, char *result, size_t result_len)
{
Token value = _value_token(tag);
if (!value)
return false;
value.string(result, result_len);
return true;
}
bool argument(unsigned index, char *result, size_t result_len)
{
Argument_tracker argument_tracker(_command);
/* argument counter */
unsigned cnt = 0;
for (Token token(_cmd_line); token; token = token.next()) {
argument_tracker.supply_token(token);
if (!argument_tracker.valid())
return false;
if (!argument_tracker.expect_arg())
continue;
Token arg = token.next();
if (!arg)
return false;
/*
* The 'arg' token could either the tag of a parameter or
* an argument. We only want to count the arguments. So
* we skip tokens that have the usual form a parameter tag.
*/
if (_is_parameter(arg))
continue;
if (cnt == index) {
arg.string(result, result_len);
return true;
}
cnt++;
}
return false;
}
/**
* Validate parameter tags
*
* \return tag token of first unexpected parameter, or
* invalid token if no unexpected parameter was found
*/
Token unexpected_parameter()
{
Argument_tracker argument_tracker(_command);
for (Token token(_cmd_line); token; token = token.next()) {
argument_tracker.supply_token(token);
if (!argument_tracker.valid())
return token;
if (!argument_tracker.expect_arg())
continue;
Token arg = token.next();
/* ignore non-parameter tokens (i.e., normal arguments) */
if (!_is_parameter(arg))
continue;
/* if parameter with the given tag exists, we are fine */
if (_parameter_is_known(arg))
continue;
/* we hit an unknown parameter tag */
return arg;
}
return Token();
}
};
#endif /* _COMMAND_LINE_H_ */