]> jfr.im git - irc/quakenet/newserv.git/blame - lib/sstring.c
Add jupe support
[irc/quakenet/newserv.git] / lib / sstring.c
CommitLineData
c86edd1d
Q
1/* sstring.h - Declaration of "static strings" functions */
2
3#define COMPILING_SSTRING
4#include "sstring.h"
5
6#include "../core/hooks.h"
7
8#include <stdio.h>
9
10#include <assert.h>
11#include <stdlib.h>
12#define __USE_GNU
13#include <string.h>
14
15/* List of free stuff */
16sstring *freelist[SSTRING_MAXLEN+1];
17
18/* Global variables to track allocated memory */
19sstring *structmem;
20char *stringmem;
21int structfree;
22int stringfree;
23
24/* Statistics counters */
25int getcalls;
26int freecalls;
27int allocstruct;
28int allocstring;
29
30/* Internal function */
31void sstringstats(int hooknum, void *arg);
32
33void initsstring() {
34 int i;
35 for(i=0;i<=SSTRING_MAXLEN;i++)
36 freelist[i]=NULL;
37
38 structfree=0;
39 stringfree=0;
40 structmem=NULL;
41 stringmem=NULL;
42
43 /* Initialise statistics counters */
44 getcalls=0;
45 freecalls=0;
46 allocstruct=0;
47 allocstring=0;
48
49 registerhook(HOOK_CORE_STATSREQUEST,&sstringstats);
50}
51
52sstring *getsstring(const char *inputstr, int maxlen) {
53 int i;
54 sstring *retval=NULL;
55 int length;
56
57
58 /* getsstring() on a NULL pointer returns a NULL sstring.. */
59 if (inputstr==NULL) {
60 return NULL;
61 }
62
63 if (inputstr[0]=='\0') {
64 return NULL;
65 }
66
67 /* Only count calls that actually did something */
68 getcalls++;
69
70 length=strlen(inputstr)+1;
71 if (length>maxlen) {
72 length=maxlen+1;
73 }
74 assert(length<=SSTRING_MAXLEN);
75
76 /* Check to see if an approximately correct
77 * sized string is available */
78 for(i=0;i<SSTRING_SLACK;i++) {
79 if (length+i>SSTRING_MAXLEN)
80 break;
81
82 if (freelist[length+i]!=NULL) {
83 retval=freelist[length+i];
84 freelist[length+i]=retval->u.next;
85 retval->u.l.alloc=(length+i);
86 break;
87 }
88 }
89
90 /* None found, allocate a new one */
91 if (retval==NULL) {
92getstruct:
93 if (structfree < sizeof(sstring)) {
94 /* We always allocate an exact multiple of these.
95 * Therefore, if there is enough for a partial structure we broke something */
96 assert(structfree==0);
97
98 /* Allocate more RAM */
99 allocstruct++;
100 structmem=(sstring *)malloc(SSTRING_STRUCTALLOC);
101 assert(structmem!=NULL);
102 structfree=SSTRING_STRUCTALLOC;
103 }
104
105 retval=structmem;
106 structmem++;
107 structfree-=sizeof(sstring);
108
109 if (stringfree < length) {
110 /* Not enough left for what we want.
111 * Allocate the remainder of our chunk (if any)
112 * to something and immediately free it.
113 * Decrement the freecalls counter to fix the stats */
114 if (stringfree > 0) {
115 retval->content=stringmem;
116 retval->u.l.alloc=stringfree;
117 stringfree=0;
118 freecalls--;
119 freesstring(retval);
120
121 /* GOTO GOTO GOTO: We need to allocate
122 * another new struct here. Goto is the cleanest
123 * way to do this */
124 goto getstruct;
125 } else {
126 /* Grab some more string space */
127 allocstring++;
128 stringmem=(char *)malloc(SSTRING_DATAALLOC);
129 assert(stringmem!=NULL);
130 stringfree=SSTRING_DATAALLOC;
131 }
132 }
133
134 retval->content=stringmem;
135 retval->u.l.alloc=length;
136 stringfree-=length;
137 stringmem+=length;
138 }
139
140 /*
141 * At this point, retval points to a valid structure which is at
142 * least the right size and has the "alloc" value set correctly
143 */
144
145 retval->u.l.length=(length-1);
146 strncpy(retval->content,inputstr,(length-1));
147 retval->content[length-1]='\0';
148
149 return retval;
150}
151
152void freesstring(sstring *inval) {
153 int alloc;
154
155
156 /* Allow people to call this with a NULL value */
157 if (inval==NULL)
158 return;
159
160 /* Only count calls that actually did something */
161 freecalls++;
162
163 alloc=inval->u.l.alloc;
164 assert(alloc<=SSTRING_MAXLEN);
165 inval->u.next=freelist[alloc];
166 freelist[alloc]=inval;
167}
168
169void sstringstats(int hooknum, void *arg) {
170 char buf[512];
171 int i,j;
172 sstring *ssp;
173 int statslev=(int)arg;
174
175 if (statslev>10) {
176 for(i=0,j=0;i<=SSTRING_MAXLEN;i++) {
177 for(ssp=freelist[i];ssp;ssp=ssp->u.next)
178 j++;
179 }
180
181 snprintf(buf,512,"SString : %7d get calls, %7d free calls, %7d struct allocs, %7d string allocs, %7d strings free",getcalls,freecalls,allocstruct,allocstring,j);
182 triggerhook(HOOK_CORE_STATSREPLY,(void *)buf);
183 }
184}
185
186int sstringcompare(sstring *ss1, sstring *ss2) {
187 if (ss1->u.l.length != ss2->u.l.length)
188 return -1;
189
190 return strncmp(ss1->content, ss2->content, ss1->u.l.length);
191}