~rcr/rirc

ref: 3e478875afa86a8af3832419bddbd019ed7d91dd rirc/src/components/mode.h -rw-r--r-- 4.1 KiB
3e478875 — Richard Robbins refactor namespacing of includes 1 year, 2 months ago
                                                                                
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
#ifndef RIRC_COMPONENTS_MODE_H
#define RIRC_COMPONENTS_MODE_H

/* usermodes, chanmodes and prfxmode configuration
 *
 * `usermodes`, `chanmodes`, parsed from numeric 004 (RPL_MYINFO)
 * `CHANMODES`, `PREFIX`,    parsed from numeric 005 (RPL_ISUPPORT)
 *
 * Three categories of modes exist, depending on the MODE message target:
 *   - Modes set server-wide for the rirc user (usermode)
 *   - Modes set for a channel                 (chanmode)
 *   - Modes set for a user on a channel       (prfxmode)
 *
 * mode_cfg.chanmodes apply to a channel and the subtypes are given by A,B,C,D:
 *   - A = Mode that adds or removes a nick or address to a list. Always has a parameter.
 *   - B = Mode that changes a setting and always has a parameter.
 *   - C = Mode that changes a setting and only has a parameter when set.
 *   - D = Mode that changes a setting and never has a parameter.
 *
 * mode_cfg.usermodes apply to the IRC user at a server level
 *
 * PREFIX maps a subset of modes to user prefixes for that channel, in order of
 * precedence. Multiple prefix modes can be set for a user, but only one mode flag
 * should be shown, e.g.:
 *   - if "ov" maps to "@+", then:
 *     - user +v  ->  "+user"
 *     - user +o  ->  "@user"
 *     - user -o  ->  "+user"
 *     - user -v  ->   "user"
 *
 * PREFIX modes are not included in CHANMODES
 *
 * MODES specifies the maximum number of channel modes with parameter
 * allowed per MODE command
 *
 * Numeric 353 (RPL_NAMREPLY) sets chanmode and prfxmode for users on a channel
 * by providing the prefix character rather than the flag
 */

#include <stdint.h>

/* [azAZ] */
#define MODE_STR_LEN 26 * 2

#define MODE_EMPTY (struct mode) \
{                \
    .prefix = 0, \
    .lower  = 0, \
    .upper  = 0, \
}

enum mode_err_t
{
	MODE_ERR_DUPLICATE      = -5,
	MODE_ERR_INVALID_CONFIG = -4,
	MODE_ERR_INVALID_PREFIX = -3,
	MODE_ERR_INVALID_FLAG   = -2,
	MODE_ERR_INVALID_SET    = -1,
	MODE_ERR_NONE
};

enum mode_cfg_t
{
	MODE_CFG_DEFAULTS,  /* Set RFC2811 mode defaults */
	MODE_CFG_CHANMODES, /* Set numeric 004 chanmdoes string */
	MODE_CFG_USERMODES, /* Set numeric 004 usermodes string */
	MODE_CFG_PREFIX,    /* Set numeric 005 PREFIX */
	MODE_CFG_SUBTYPES,  /* Set numeric 005 CHANMODES subtypes */
	MODE_CFG_MODES,     /* Set numeric 005 MODES */
	MODE_CFG_T_SIZE
};

enum mode_set_t
{
	MODE_SET_OFF = 0,
	MODE_SET_ON  = 1,
	MODE_SET_INVALID,
	MODE_SET_T_SIZE
};

enum chanmode_flag_t
{
	MODE_FLAG_INVALID_FLAG,
	MODE_FLAG_INVALID_SET,
	MODE_FLAG_CHANMODE,       /* Chanmode flag without parameter */
	MODE_FLAG_CHANMODE_PARAM, /* Chanmode flag with parameter */
	MODE_FLAG_PREFIX,         /* Chanmode flag that sets prfxmode */
	MODE_FLAG_T_SIZE
};

struct mode
{
	char prefix;    /* Prefix character for chanmode, prfxmode */
	uint32_t lower; /* Lowercase mode bits */
	uint32_t upper; /* Uppercase mode bits */
};

struct mode_cfg
{
	unsigned int MODES;    /* Numeric 005 MODES */
	struct mode chanmodes; /* Numeric 004 chanmodes string */
	struct mode usermodes; /* Numeric 004 usermodes string */
	struct
	{
		struct mode A; /* Numeric 005 CHANMODES substrings */
		struct mode B;
		struct mode C;
		struct mode D;
	} CHANMODES;
	struct
	{
		char F[MODE_STR_LEN + 1]; /* prfxmode mapping `from` */
		char T[MODE_STR_LEN + 1]; /* prfxmode mapping `to`  */
	} PREFIX;
};

struct mode_str
{
	char str[MODE_STR_LEN + 1];
	enum mode_str_t
	{
		MODE_STR_UNSET = 0,
		MODE_STR_CHANMODE,
		MODE_STR_USERMODE,
		MODE_STR_PRFXMODE,
		MODE_STR_T_SIZE
	} type;
};

const char* mode_str(const struct mode*, struct mode_str*);
enum chanmode_flag_t chanmode_type(const struct mode_cfg*, enum mode_set_t, int);
enum mode_err_t mode_cfg(struct mode_cfg*, const char*, enum mode_cfg_t);
enum mode_err_t mode_chanmode_prefix(struct mode*, const struct mode_cfg*, int);
enum mode_err_t mode_chanmode_set(struct mode*, const struct mode_cfg*, int, enum mode_set_t);
enum mode_err_t mode_prfxmode_prefix(struct mode*, const struct mode_cfg*, int);
enum mode_err_t mode_prfxmode_set(struct mode*, const struct mode_cfg*, int, enum mode_set_t);
enum mode_err_t mode_usermode_set(struct mode*, const struct mode_cfg*, int, enum mode_set_t);
void mode_reset(struct mode*, struct mode_str*);

#endif