]>
jfr.im git - irc/quakenet/newserv.git/blob - lib/sstring.c
1 /* sstring.h - Declaration of "static strings" functions */
3 #define COMPILING_SSTRING
6 #include "../core/hooks.h"
7 #include "../core/nsmalloc.h"
8 #include "../core/error.h"
19 /* List of free stuff */
20 sstring
*freelist
[SSTRING_MAXLEN
+1];
22 /* Global variables to track allocated memory */
28 /* Statistics counters */
34 /* Internal function */
35 void sstringstats(int hooknum
, void *arg
);
39 for(i
=0;i
<=SSTRING_MAXLEN
;i
++)
47 /* Initialise statistics counters */
53 registerhook(HOOK_CORE_STATSREQUEST
,&sstringstats
);
57 nsfreeall(POOL_SSTRING
);
60 sstring
*getsstring(const char *inputstr
, int maxlen
) {
66 /* getsstring() on a NULL pointer returns a NULL sstring.. */
71 if (inputstr
[0]=='\0') {
75 /* Only count calls that actually did something */
78 length
=strlen(inputstr
)+1;
82 assert(length
<=SSTRING_MAXLEN
);
84 /* Check to see if an approximately correct
85 * sized string is available */
86 for(i
=0;i
<SSTRING_SLACK
;i
++) {
87 if (length
+i
>SSTRING_MAXLEN
)
90 if (freelist
[length
+i
]!=NULL
) {
91 retval
=freelist
[length
+i
];
92 freelist
[length
+i
]=retval
->u
.next
;
93 retval
->u
.l
.alloc
=(length
+i
);
98 /* None found, allocate a new one */
101 if (structfree
< sizeof(sstring
)) {
102 /* We always allocate an exact multiple of these.
103 * Therefore, if there is enough for a partial structure we broke something */
104 assert(structfree
==0);
106 /* Allocate more RAM */
108 structmem
=(sstring
*)nsmalloc(POOL_SSTRING
,SSTRING_STRUCTALLOC
);
109 assert(structmem
!=NULL
);
110 structfree
=SSTRING_STRUCTALLOC
;
115 structfree
-=sizeof(sstring
);
117 if (stringfree
< length
) {
118 /* Not enough left for what we want.
119 * Allocate the remainder of our chunk (if any)
120 * to something and immediately free it.
121 * Decrement the freecalls counter to fix the stats */
122 if (stringfree
> 0) {
123 retval
->content
=stringmem
;
124 retval
->u
.l
.alloc
=stringfree
;
129 /* GOTO GOTO GOTO: We need to allocate
130 * another new struct here. Goto is the cleanest
134 /* Grab some more string space */
136 stringmem
=(char *)nsmalloc(POOL_SSTRING
,SSTRING_DATAALLOC
);
137 assert(stringmem
!=NULL
);
138 stringfree
=SSTRING_DATAALLOC
;
142 retval
->content
=stringmem
;
143 retval
->u
.l
.alloc
=length
;
149 * At this point, retval points to a valid structure which is at
150 * least the right size and has the "alloc" value set correctly
153 retval
->u
.l
.length
=(length
-1);
154 strncpy(retval
->content
,inputstr
,(length
-1));
155 retval
->content
[length
-1]='\0';
160 void freesstring(sstring
*inval
) {
163 /* Allow people to call this with a NULL value */
167 /* Only count calls that actually did something */
170 alloc
=inval
->u
.l
.alloc
;
171 assert(alloc
<=SSTRING_MAXLEN
);
172 inval
->u
.next
=freelist
[alloc
];
173 freelist
[alloc
]=inval
;
176 void sstringstats(int hooknum
, void *arg
) {
180 long statslev
=(long)arg
;
183 for(i
=0,j
=0;i
<=SSTRING_MAXLEN
;i
++) {
184 for(ssp
=freelist
[i
];ssp
;ssp
=ssp
->u
.next
)
188 snprintf(buf
,512,"SString : %7d get calls, %7d free calls, %7d struct allocs, %7d string allocs, %7d strings free",getcalls
,freecalls
,allocstruct
,allocstring
,j
);
189 triggerhook(HOOK_CORE_STATSREPLY
,(void *)buf
);
193 #else /* USE_VALGRIND */
195 typedef struct sstringlist
{
196 struct sstringlist
*prev
;
197 struct sstringlist
*next
;
201 static sstringlist
*head
;
209 /* here we deliberately don't free the pointers so valgrind can tell us where they were allocated, in theory */
216 Error("sstring", ERR_WARNING
, "sstring of length %d still allocated: %s", s
->s
->u
.l
.length
, s
->s
->content
);
222 sstring
*getsstring(const char *inputstr
, int maxlen
) {
230 for(p
=(char *)inputstr
;*p
&&maxlen
;maxlen
--,p
++)
234 s
=(sstringlist
*)malloc(sizeof(sstringlist
) + sizeof(sstring
));
236 s
->s
->u
.l
.length
= len
;
237 s
->s
->content
=(char *)malloc(len
+ 1);
239 memcpy(s
->s
->content
, inputstr
, len
);
240 s
->s
->content
[len
] = '\0';
251 void freesstring(sstring
*inval
) {
256 s
= (sstringlist
*)inval
- 1;
259 s
->prev
->next
= s
->next
;
261 s
->next
->prev
= s
->prev
;
268 free(inval
->content
);
273 int sstringcompare(sstring
*ss1
, sstring
*ss2
) {
274 if (ss1
->u
.l
.length
!= ss2
->u
.l
.length
)
277 return strncmp(ss1
->content
, ss2
->content
, ss1
->u
.l
.length
);