1 : #define VSTR_REF_C
2 : /*
3 : * Copyright (C) 1999, 2000, 2001, 2002, 2003 James Antill
4 : *
5 : * This library is free software; you can redistribute it and/or
6 : * modify it under the terms of the GNU Lesser General Public
7 : * License as published by the Free Software Foundation; either
8 : * version 2 of the License, or (at your option) any later version.
9 : *
10 : * This library is distributed in the hope that it will be useful,
11 : * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 : * Lesser General Public License for more details.
14 : *
15 : * You should have received a copy of the GNU Lesser General Public
16 : * License along with this library; if not, write to the Free Software
17 : * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 : *
19 : * email: james@and.org
20 : */
21 : /* contains all the base functions related to vstr_ref objects
22 : * including callbacks */
23 : #include "main.h"
24 :
25 : void vstr_ref_cb_free_nothing(Vstr_ref *VSTR__ATTR_UNUSED(ref))
26 1354 : {
27 : }
28 :
29 : void vstr_ref_cb_free_ref(Vstr_ref *ref)
30 24423 : {
31 24423 : free(ref);
32 : }
33 :
34 : void vstr_ref_cb_free_ptr(Vstr_ref *ref)
35 10 : {
36 10 : if (ref)
37 10 : free(ref->ptr);
38 : }
39 :
40 : void vstr_ref_cb_free_ptr_ref(Vstr_ref *ref)
41 5 : {
42 5 : vstr_ref_cb_free_ptr(ref);
43 5 : vstr_ref_cb_free_ref(ref);
44 : }
45 :
46 : Vstr_ref *vstr_ref_make_ptr(const void *ptr, void (*func)(struct Vstr_ref *))
47 65 : {
48 65 : Vstr_ref *ref = malloc(sizeof(Vstr_ref));
49 :
50 65 : if (!ref)
51 5 : return (NULL);
52 :
53 60 : ref->ref = 1;
54 60 : ref->ptr = (void *)ptr;
55 60 : ref->func = func;
56 :
57 60 : return (ref);
58 : }
59 :
60 : #ifndef NDEBUG
61 : static void vstr__ref_cb_free_ref(Vstr_ref *ref)
62 4912 : {
63 4912 : VSTR__F(ref);
64 : }
65 : #else
66 : #define vstr__ref_cb_free_ref vstr_ref_cb_free_ref
67 : #endif
68 :
69 : Vstr_ref *vstr_ref_make_malloc(size_t len)
70 30240 : {
71 30240 : struct Vstr__buf_ref *ref = VSTR__MK(sizeof(Vstr__buf_ref) + len);
72 :
73 30240 : if (!ref)
74 60 : return (NULL);
75 :
76 30180 : ref->ref.ref = 1;
77 30180 : ref->ref.ptr = ref->buf;
78 30180 : ref->ref.func = vstr__ref_cb_free_ref;
79 :
80 30180 : assert(&ref->ref == (Vstr_ref *)ref);
81 :
82 30180 : return (&ref->ref);
83 : }
84 :
85 : Vstr_ref *vstr_ref_make_memdup(const void *ptr, size_t len)
86 28110 : {
87 28110 : Vstr_ref *ref = vstr_ref_make_malloc(len);
88 :
89 28110 : if (ref)
90 28099 : vstr_wrap_memcpy(ref->ptr, ptr, len);
91 :
92 28110 : return (ref);
93 : }
94 :
95 : static void vstr__ref_cb_free_vstr_base(Vstr_ref *ref)
96 5 : {
97 5 : vstr_free_base(ref->ptr);
98 5 : free(ref);
99 : }
100 :
101 : Vstr_ref *vstr_ref_make_vstr_base(Vstr_base *base)
102 5 : {
103 5 : return (vstr_ref_make_ptr(base, vstr__ref_cb_free_vstr_base));
104 : }
105 :
106 : static void vstr__ref_cb_free_vstr_conf(Vstr_ref *ref)
107 5 : {
108 5 : vstr_free_conf(ref->ptr);
109 5 : free(ref);
110 : }
111 :
112 : Vstr_ref *vstr_ref_make_vstr_conf(Vstr_conf *conf)
113 5 : {
114 5 : return (vstr_ref_make_ptr(conf, vstr__ref_cb_free_vstr_conf));
115 : }
116 :
117 : static void vstr__ref_cb_free_vstr_sects(Vstr_ref *ref)
118 5 : {
119 5 : vstr_sects_free(ref->ptr);
120 5 : free(ref);
121 : }
122 :
123 : Vstr_ref *vstr_ref_make_vstr_sects(Vstr_sects *sects)
124 5 : {
125 5 : return (vstr_ref_make_ptr(sects, vstr__ref_cb_free_vstr_sects));
126 : }
127 :
128 : static void vstr__ref_cb_free_grp_main(Vstr_ref_grp_ptr *parent,
129 : Vstr_ref *ref, unsigned int off)
130 19499 : {
131 19499 : ASSERT(&parent->refs[off] == ref);
132 :
133 19499 : parent->func(ref);
134 :
135 19499 : ref->func = NULL;
136 :
137 19499 : ASSERT(parent->free_num < parent->make_num);
138 19499 : ASSERT(parent->make_num <= VSTR__REF_GRP_MAKE_SZ);
139 :
140 19499 : if (++parent->free_num == parent->make_num)
141 : {
142 3199 : if (!(parent->flags & VSTR__FLAG_REF_GRP_REF))
143 2543 : VSTR__F(parent);
144 : else
145 : {
146 656 : parent->free_num = 0;
147 656 : parent->make_num = 0;
148 : }
149 : }
150 : else
151 : {
152 16300 : unsigned int scan = parent->make_num - 1;
153 :
154 16828 : ASSERT(parent->free_num < parent->make_num);
155 :
156 16893 : while (!parent->refs[scan].func)
157 : {
158 593 : ASSERT(parent->free_num > 0);
159 :
160 593 : --parent->make_num;
161 593 : --parent->free_num;
162 593 : --scan;
163 : }
164 : }
165 : }
166 :
167 : #define VSTR__REF_GRP_CB(x) \
168 : static void vstr__ref_cb_free_grp_ref_ ## x (Vstr_ref *ref) \
169 : { \
170 : unsigned int off = (x); \
171 : Vstr_ref_grp_ptr *parent = NULL; \
172 : char *ptr = (char *)(ref - off); \
173 : \
174 : ptr -= offsetof(Vstr_ref_grp_ptr, refs); \
175 : parent = (Vstr_ref_grp_ptr *)ptr; \
176 : \
177 : vstr__ref_cb_free_grp_main(parent, ref, off); \
178 : }
179 :
180 : #include "vstr-ref_grp-data.h"
181 :
182 : #undef VSTR__REF_GRP_CB
183 :
184 : Vstr_ref_grp_ptr *vstr__ref_grp_make(void (*func) (Vstr_ref *),
185 : unsigned int flags)
186 3098 : {
187 3098 : Vstr_ref_grp_ptr *parent = NULL;
188 :
189 3098 : if (!(parent = VSTR__MK(sizeof(Vstr_ref_grp_ptr) +
190 : (VSTR__REF_GRP_MAKE_SZ * sizeof(Vstr_ref)))))
191 22 : return (NULL);
192 :
193 3076 : parent->make_num = 0;
194 3076 : parent->free_num = 0;
195 :
196 3076 : parent->func = func;
197 3076 : parent->flags = flags | VSTR__FLAG_REF_GRP_REF;
198 :
199 3076 : return (parent);
200 : }
201 :
202 : void vstr__ref_grp_free(Vstr_ref_grp_ptr *parent)
203 14642 : {
204 14642 : if (!parent)
205 11581 : return;
206 :
207 3061 : if (!parent->make_num)
208 : {
209 533 : ASSERT(!parent->free_num);
210 533 : VSTR__F(parent);
211 533 : return;
212 : }
213 :
214 2528 : parent->flags &= ~VSTR__FLAG_REF_GRP_REF;
215 :
216 12600 : ASSERT(parent->make_num == VSTR__REF_GRP_MAKE_SZ);
217 12600 : ASSERT(parent->free_num < VSTR__REF_GRP_MAKE_SZ);
218 : }
219 :
220 : /* needs to be reset each time, so we can tell which are free */
221 : #define VSTR__REF_GRP_CB(x) \
222 : case (x): ref->func = vstr__ref_cb_free_grp_ref_ ## x; break;
223 :
224 : Vstr_ref *vstr__ref_grp_add(Vstr_ref_grp_ptr **parent, const void *ptr)
225 19508 : {
226 19508 : Vstr_ref *ref = NULL;
227 :
228 19508 : ASSERT(parent && *parent);
229 :
230 19508 : if ((*parent)->make_num == VSTR__REF_GRP_MAKE_SZ)
231 : {
232 2537 : Vstr_ref_grp_ptr *tmp = NULL;
233 :
234 2537 : if (!(tmp = vstr__ref_grp_make((*parent)->func, (*parent)->flags)))
235 9 : return (NULL);
236 :
237 2528 : vstr__ref_grp_free(*parent);
238 2528 : *parent = tmp;
239 : }
240 :
241 19499 : ref = &(*parent)->refs[(*parent)->make_num];
242 :
243 19499 : ref->ref = 1;
244 19499 : ref->ptr = (void *)ptr; /* get rid of const */
245 19499 : switch ((*parent)->make_num++)
246 : {
247 : #include "vstr-ref_grp-data.h"
248 : }
249 :
250 19499 : return (ref);
251 : }
252 : #undef VSTR__REF_GRP_CB
253 :
|