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