Refactored command parsing.

Allows for automatically tested command parsing by splitting parsing
and invokation of the commands.
This commit is contained in:
Jan Vidar Krey
2011-12-19 00:34:20 +01:00
parent fc5e09aa9e
commit f2cb84180a
11 changed files with 698 additions and 443 deletions

View File

@@ -17,20 +17,51 @@
*
*/
#include "uhub.h"
#ifndef HAVE_UHUB_COMMANDS_H
#define HAVE_UHUB_COMMANDS_H
struct command_base;
struct command_handle;
struct hub_command;
struct hub_command
typedef int (*command_handler)(struct command_base* cbase, struct hub_user* user, struct hub_command* cmd);
enum command_parse_status
{
const char* message;
char* prefix;
size_t prefix_len;
struct linked_list* args;
cmd_status_ok, /** <<< "Everything seems to OK" */
cmd_status_not_found, /** <<< "Command was not found" */
cmd_status_access_error, /** <<< "You don't have access to this command" */
cmd_status_syntax_error, /** <<< "Not a valid command." */
cmd_status_missing_args, /** <<< "Missing some or all required arguments." */
cmd_status_arg_nick, /** <<< "A nick argument does not match an online user. ('n')" */
cmd_status_arg_cid, /** <<< "A cid argument does not match an online user. ('i')." */
cmd_status_arg_address, /** <<< "A address range argument is not valid ('a')." */
cmd_status_arg_number, /** <<< "A number argument is not valid ('N')" */
cmd_status_arg_cred, /** <<< "A credentials argument is not valid ('C')" */
cmd_status_arg_command, /** <<< "A command argument is not valid ('c')" */
};
typedef int (*command_handler)(struct command_base*, struct hub_user* user, struct command_handle*, struct hub_command*);
/**
* This struct contains all information needed to invoke
* a command, which includes the whole message, the prefix,
* the decoded arguments (according to parameter list), and
* the user pointer (ptr) which comes from the command it was matched to.
*
* The message and prefix is generally always available, but args only
* if status == cmd_status_ok.
* Handler and ptr are NULL if status == cmd_status_not_found, or status == cmd_status_access_error.
* Ptr might also be NULL if cmd_status_ok because the command that handles it was added with a NULL ptr.
*/
struct hub_command
{
enum command_parse_status status; /**<<< "Status of the hub_command." */
const char* message; /**<<< "The complete message." */
char* prefix; /**<<< "The prefix extracted from the message." */
struct linked_list* args; /**<<< "List of all parsed arguments from the message. Type depends on expectations." */
command_handler handler; /**<<< "The function handler to call in order to invoke this command." */
const struct hub_user* user; /**<<< "The user who invoked this command." */
void* ptr; /**<<< "A pointer of data which came from struct command_handler" */
};
/**
* Argument codes are used to automatically parse arguments
@@ -55,18 +86,16 @@ typedef int (*command_handler)(struct command_base*, struct hub_user* user, stru
*/
struct command_handle
{
const char* prefix; /**<<< "Command prefix, for instance 'help' would be the prefix for the !help command." */
size_t length; /**<<< "Length of the prefix" */
const char* args; /**<<< "Argument codes (see above)" */
enum auth_credentials cred; /**<<< "Minimum access level for the command" */
command_handler handler; /**<<< "Function pointer for the command" */
const char* description; /**<<< "Description for the command" */
const char* origin; /**<<< "Name of module where the command is implemented." */
void* ptr;
const char* prefix; /**<<< "Command prefix, for instance 'help' would be the prefix for the !help command." */
size_t length; /**<<< "Length of the prefix" */
const char* args; /**<<< "Argument codes (see above)" */
enum auth_credentials cred; /**<<< "Minimum access level for the command" */
command_handler handler; /**<<< "Function pointer for the command" */
const char* description; /**<<< "Description for the command" */
const char* origin; /**<<< "Name of module where the command is implemented." */
void* ptr; /**<<< "A pointer which will be passed along to the handler. @See hub_command::ptr" */
};
/**
* Returns NULL on error, or handle
*/
@@ -85,11 +114,6 @@ extern int command_add(struct command_base*, struct command_handle*, void* ptr);
*/
extern int command_del(struct command_base*, struct command_handle*);
/**
* Returns 1 if a command is available to a user (user has access to run it.)
*/
extern int command_is_available(struct command_handle*, struct hub_user* user);
/**
* Dispatch a message and forward it as a command.
* Returns 1 if the message should be forwarded as a chat message, or 0 if
@@ -99,3 +123,22 @@ extern int command_is_available(struct command_handle*, struct hub_user* user);
* for that command if the sufficient access credentials are met.
*/
extern int command_invoke(struct command_base*, struct hub_user* user, const char* message);
/**
* Parse a message as a command and return a status indicating if the command
* is valid and that the arguments are sane.
*
* @param cbase Command base pointer.
* @param user User who invoked the command.
* @param message The message that is to be interpreted as a command (including the invokation prefix '!' or '+')
*
* @return a hub_command that must be freed with command_free(). @See struct hub_command.
*/
extern struct hub_command* command_parse(struct command_base* cbase, const struct hub_user* user, const char* message);
/**
* Free a hub_command that was created in command_parse().
*/
extern void command_free(struct hub_command* command);
#endif /* HAVE_UHUB_COMMANDS_H */