]> jfr.im git - irc/quakenet/newserv.git/blob - chanindex/chanindex.c
A4STATS: remove E style escapes and switch to createtable for indices
[irc/quakenet/newserv.git] / chanindex / chanindex.c
1 /* channelindex.c */
2
3 #include "chanindex.h"
4 #include "../irc/irc_config.h"
5 #include "../lib/irc_string.h"
6 #include "../core/error.h"
7 #include "../core/nsmalloc.h"
8 #include "../lib/version.h"
9
10 #include <stdio.h>
11 #include <string.h>
12
13 MODULE_VERSION("")
14
15 #define channelhash(x) (irc_crc32i(x)%CHANNELHASHSIZE)
16
17 chanindex *chantable[CHANNELHASHSIZE];
18 sstring *extnames[MAXCHANNELEXTS];
19
20 unsigned int channelmarker;
21
22 void _init() {
23 memset(chantable,0,sizeof(chantable));
24 memset(extnames,0,sizeof(extnames));
25 channelmarker=0;
26 }
27
28 void _fini() {
29 nsfreeall(POOL_CHANINDEX);
30 }
31
32 chanindex *getchanindex() {
33 return nsmalloc(POOL_CHANINDEX, sizeof(chanindex));
34 }
35
36 void freechanindex(chanindex *cip) {
37 nsfree(POOL_CHANINDEX, cip);
38 }
39
40 chanindex *findchanindex(const char *name) {
41 chanindex *cip;
42 int hash=channelhash(name);
43
44 for (cip=chantable[hash];cip;cip=cip->next) {
45 if (!ircd_strcmp(cip->name->content,name)) {
46 return cip;
47 }
48 }
49
50 return NULL;
51 }
52
53 chanindex *findorcreatechanindex(const char *name) {
54 chanindex *cip;
55 int hash=channelhash(name);
56 int i;
57
58 for (cip=chantable[hash];cip;cip=cip->next) {
59 if (!ircd_strcmp(cip->name->content,name)) {
60 return cip;
61 }
62 }
63
64 cip=getchanindex();
65
66 cip->name=getsstring(name,CHANNELLEN);
67 cip->channel=NULL;
68 cip->marker=0;
69 cip->next=chantable[hash];
70 chantable[hash]=cip;
71
72 for(i=0;i<MAXCHANNELEXTS;i++) {
73 cip->exts[i]=NULL;
74 }
75
76 return cip;
77 }
78
79 void releasechanindex(chanindex *cip) {
80 int i;
81 chanindex **cih;
82 int hash;
83
84 /* If any module is still using the channel, do nothing */
85 /* Same if the channel is still present on the network */
86
87 if (cip->channel!=NULL) {
88 return;
89 }
90
91 for (i=0;i<MAXCHANNELEXTS;i++) {
92 if (cip->exts[i]!=NULL) {
93 return;
94 }
95 }
96
97 /* Now remove the index record from the index. */
98 hash=channelhash(cip->name->content);
99
100 for(cih=&(chantable[hash]);*cih;cih=&((*cih)->next)) {
101 if (*cih==cip) {
102 (*cih)=cip->next;
103 freesstring(cip->name);
104 freechanindex(cip);
105 return;
106 }
107 }
108
109 Error("channel",ERR_ERROR,"Tried to release chanindex record for %s not found in hash",cip->name->content);
110 }
111
112 int registerchanext(const char *name) {
113 int i;
114
115 if (findchanext(name)!=-1) {
116 Error("channel",ERR_WARNING,"Tried to register duplicate extension %s",name);
117 return -1;
118 }
119
120 for (i=0;i<MAXCHANNELEXTS;i++) {
121 if (extnames[i]==NULL) {
122 extnames[i]=getsstring(name,100);
123 return i;
124 }
125 }
126
127 Error("channel",ERR_WARNING,"Tried to register too many extensions: %s",name);
128 return -1;
129 }
130
131 int findchanext(const char *name) {
132 int i;
133
134 for (i=0;i<MAXCHANNELEXTS;i++) {
135 if (extnames[i]!=NULL && !ircd_strcmp(name,extnames[i]->content)) {
136 return i;
137 }
138 }
139
140 return -1;
141 }
142
143 void releasechanext(int index) {
144 int i;
145 chanindex *cip,*ncip;
146
147 freesstring(extnames[index]);
148 extnames[index]=NULL;
149
150 for (i=0;i<CHANNELHASHSIZE;i++) {
151 for (cip=chantable[i];cip;cip=ncip) {
152 /* CAREFUL: deleting items from chains you're walking is bad */
153 ncip=cip->next;
154 if (cip->exts[index]!=NULL) {
155 cip->exts[index]=NULL;
156 releasechanindex(cip);
157 }
158 }
159 }
160 }
161
162 unsigned int nextchanmarker() {
163 int i;
164 chanindex *cip;
165
166 channelmarker++;
167 if (!channelmarker) {
168 /* If we wrapped to zero, zap the marker on all records */
169 for (i=0;i<CHANNELHASHSIZE;i++)
170 for (cip=chantable[i];cip;cip=cip->next)
171 cip->marker=0;
172 channelmarker++;
173 }
174
175 return channelmarker;
176 }