]> jfr.im git - irc/quakenet/newserv.git/blame - whowas/whowas_channels.c
whowas: Keep track of channels.
[irc/quakenet/newserv.git] / whowas / whowas_channels.c
CommitLineData
dd33b9ca
GB
1#include <string.h>
2#include <assert.h>
3#include "../nick/nick.h"
4#include "../chanindex/chanindex.h"
5#include "../channel/channel.h"
6#include "../core/hooks.h"
7#include "whowas.h"
8
9static int wwcnext, wwccext;
10
11static void wwc_refchannel(chanindex *cip) {
12 uintptr_t *refcount = (uintptr_t *)&cip->exts[wwccext];
13 (*refcount)++;
14}
15
16static void wwc_derefchannel(chanindex *cip) {
17 uintptr_t *refcount = (uintptr_t *)&cip->exts[wwccext];
18 (*refcount)--;
19
20 assert(*refcount >= 0);
21
22 if (*refcount == 0)
23 releasechanindex(cip);
24}
25
26static void wwc_hook_joincreate(int hooknum, void *arg) {
27 void **args = arg;
28 channel *cp = args[0];
29 nick *np = args[1];
30 chanindex **wchans = np->exts[wwcnext];
31
32 if (!wchans) {
33 wchans = calloc(sizeof(chanindex *), WW_MAXCHANNELS);
34 np->exts[wwcnext] = wchans;
35 }
36
37 wwc_refchannel(cp->index);
38
39 memmove(&wchans[1], &wchans[0], sizeof(chanindex *) * (WW_MAXCHANNELS - 1));
40 wchans[0] = cp->index;
41}
42
43static void wwc_hook_lostnick(int hooknum, void *arg) {
44 nick *np = arg;
45 chanindex **wchans = np->exts[wwcnext];
46 int i;
47
48 if (!wchans)
49 return;
50
51 for (i = 0; i < WW_MAXCHANNELS; i++) {
52 if (!wchans[i])
53 break;
54
55 wwc_derefchannel(wchans[i]);
56 }
57
58 free(wchans);
59}
60
61static void wwc_hook_newrecord(int hooknum, void *arg) {
62 void **args = arg;
63 whowas *ww = args[0];
64 nick *np = args[1];
65 chanindex **wchans = np->exts[wwcnext];
66 int i;
67
68 memset(ww->channels, 0, sizeof(ww->channels));
69
70 if (!wchans)
71 return;
72
73 for (i = 0; i < WW_MAXCHANNELS; i++) {
74 if (!wchans[i])
75 break;
76
77 wwc_refchannel(wchans[i]);
78 ww->channels[i] = wchans[i];
79 }
80}
81
82static void wwc_hook_lostrecord(int hooknum, void *arg) {
83 whowas *ww = arg;
84 int i;
85
86 for (i = 0; i < WW_MAXCHANNELS; i++) {
87 if (!ww->channels[i])
88 break;
89
90 wwc_derefchannel(ww->channels[i]);
91 }
92}
93
94void _init(void) {
95 wwcnext = registernickext("whowas_channels");
96 wwccext = registerchanext("whowas_channels");
97
98 registerhook(HOOK_CHANNEL_JOIN, &wwc_hook_joincreate);
99 registerhook(HOOK_CHANNEL_CREATE, &wwc_hook_joincreate);
100 registerhook(HOOK_NICK_LOSTNICK, &wwc_hook_lostnick);
101 registerhook(HOOK_WHOWAS_NEWRECORD, &wwc_hook_newrecord);
102 registerhook(HOOK_WHOWAS_LOSTRECORD, &wwc_hook_lostrecord);
103}
104
105void _fini(void) {
106 releasenickext(wwcnext);
107 releasechanext(wwccext);
108
109 deregisterhook(HOOK_CHANNEL_JOIN, &wwc_hook_joincreate);
110 deregisterhook(HOOK_CHANNEL_CREATE, &wwc_hook_joincreate);
111 deregisterhook(HOOK_NICK_LOSTNICK, &wwc_hook_lostnick);
112 deregisterhook(HOOK_WHOWAS_NEWRECORD, &wwc_hook_newrecord);
113 deregisterhook(HOOK_WHOWAS_LOSTRECORD, &wwc_hook_lostrecord);
114}