#ifndef IRC_LINE_H
#define IRC_LINE_H
/**
* @file
*
* The low-level IRC protocol unit is a line, with prefix, command and arguments
*/
#include "irc_proto.h"
#include "error.h"
/**
* The maximum length of a line, without terminating CRLF, but including NUL
*/
#define IRC_LINE_MAX (510 + 1)
/**
* The maximum number of arguments for a single command
*/
#define IRC_ARG_MAX 15
/**
* Chars that are invalid inside of tokens
*/
#define IRC_TOKEN_INVALID "\r\n\n "
/**
* Chars that are invalid inside of the trailing-argument token
*/
#define IRC_TOKEN_TRAILING_INVALID "\r\n\n"
/**
* Low-level IRC protocol unit. Note that all fields are specifically constant strings, MUST NOT be modified, and
* usually point at stack-allocated memory. Hence, if you need to mutate or store these values, you must copy them.
*/
struct irc_line {
/** The message source as a nickmask, for those messages that have a valid prefix. May be NULL otherwise */
const struct irc_nm *source;
/** The command, either a numeric or a primary command */
const char *command;
/** The arguments, with unused ones set to NULL */
const char *args[IRC_ARG_MAX];
};
/**
* Parse an IRC message to fill in an irc_line. This mutates the contents of data (to insert NULs between tokens), and
* stores pointers into this memory in the irc_line.
*
* If the prefix is a valid nickmask, it will be stored in the given given irc_nm, and irc_line.nm set to this.
*
* The irc_line will have the first N args values set to valid values, and all the rest set to NULL.
*
* XXX: strip trailing \r\n
*/
err_t irc_line_parse (struct irc_line *line, struct irc_nm *nm, char *data);
/**
* Formats an irc_line as a protocol line into the given buffer (which should hold at least IRC_LINE_MAX bytes).
*
* The irc_line.args are ignored from the first NULL argument onwards.
*
* An error is returned if a token has an invalid value (e.g. a space in the command or an argument other than the last
* one), or if the resulting line is too long.
*
* XXX: append trailing \r\n
*/
err_t irc_line_build (const struct irc_line *line, char *buf);
/**
* Iterate through the arguments in an irc_line
*/
#define FOREACH_IRC_LINE_ARGS(line, arg_ptr) \
for (size_t _irc_line_arg_idx = 0; _irc_line_arg_idx < IRC_ARG_MAX && (arg_ptr = line->args[_irc_line_arg_idx]); _irc_line_arg_idx++)
#endif /* IRC_LINE_H */