1 : #define VSTR_EXPORT_C
2 : /*
3 : * Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004 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 : /* functions for exporting data out of the Vstr -- see also vstr_cstr.c */
22 : #include "main.h"
23 :
24 :
25 : size_t vstr_export_iovec_ptr_all(const Vstr_base *base,
26 : struct iovec **iovs, unsigned int *ret_num)
27 96828 : {
28 96828 : ASSERT(base);
29 :
30 96828 : if (!base->num)
31 5 : return (0);
32 :
33 96823 : if (!vstr__cache_iovec_valid((Vstr_base *)base))
34 80 : return (0);
35 :
36 96743 : if (iovs)
37 96228 : *iovs = VSTR__CACHE(base)->vec->v + VSTR__CACHE(base)->vec->off;
38 :
39 96743 : if (ret_num)
40 96228 : *ret_num = base->num;
41 :
42 96743 : return (base->len);
43 : }
44 :
45 : size_t vstr_export_iovec_cpy_buf(const Vstr_base *base,
46 : size_t pos, size_t len,
47 : struct iovec *iovs, unsigned int num_max,
48 : unsigned int *real_ret_num)
49 25 : {
50 25 : Vstr_iter iter[1];
51 25 : size_t ret_len = 0;
52 25 : unsigned int dummy_ret_num = 0;
53 25 : unsigned int ret_num = 0;
54 25 : size_t used = 0;
55 :
56 25 : assert(iovs || !num_max);
57 :
58 25 : if (!num_max)
59 5 : return (0);
60 :
61 20 : if (!real_ret_num)
62 10 : real_ret_num = &dummy_ret_num;
63 :
64 20 : if (!vstr_iter_fwd_beg(base, pos, len, iter))
65 5 : return (0);
66 :
67 45 : do
68 : {
69 45 : size_t tmp = iter->len;
70 :
71 45 : assert(tmp);
72 45 : assert(iovs[ret_num].iov_len);
73 45 : assert(iovs[ret_num].iov_len > used);
74 :
75 45 : if (tmp > (iovs[ret_num].iov_len - used))
76 35 : tmp = (iovs[ret_num].iov_len - used);
77 :
78 45 : if (iter->node->type != VSTR_TYPE_NODE_NON)
79 45 : vstr_wrap_memcpy(((char *)iovs[ret_num].iov_base) + used, iter->ptr, tmp);
80 :
81 45 : used += tmp;
82 45 : iter->ptr += tmp;
83 45 : iter->len -= tmp;
84 45 : ret_len += tmp;
85 :
86 45 : if (iovs[ret_num].iov_len == used)
87 : {
88 35 : used = 0;
89 :
90 35 : if (++ret_num >= num_max)
91 5 : break;
92 : }
93 40 : } while (iter->len || vstr_iter_fwd_nxt(iter));
94 :
95 15 : if (used)
96 : {
97 10 : iovs[ret_num].iov_len = used;
98 10 : ++ret_num;
99 : }
100 :
101 15 : *real_ret_num = ret_num;
102 :
103 15 : return (ret_len);
104 : }
105 :
106 : size_t vstr_export_iovec_cpy_ptr(const Vstr_base *base,
107 : size_t pos, size_t len,
108 : struct iovec *iovs, unsigned int num_max,
109 : unsigned int *real_ret_num)
110 45 : {
111 45 : size_t orig_len = len;
112 45 : Vstr_iter iter[1];
113 45 : size_t ret_len = 0;
114 45 : unsigned int dummy_ret_num = 0;
115 45 : unsigned int ret_num = 0;
116 :
117 45 : assert(iovs || !num_max);
118 :
119 45 : if (!num_max)
120 5 : return (0);
121 :
122 40 : if (!real_ret_num)
123 10 : real_ret_num = &dummy_ret_num;
124 :
125 40 : if (!vstr_iter_fwd_beg(base, pos, len, iter))
126 5 : return (0);
127 :
128 126 : do
129 : {
130 126 : iovs[ret_num].iov_len = iter->len;
131 126 : iovs[ret_num].iov_base = (void *)iter->ptr;
132 126 : ret_len += iter->len;
133 :
134 126 : } while ((++ret_num < num_max) && vstr_iter_fwd_nxt(iter));
135 35 : assert((ret_len == orig_len) || (ret_num == num_max));
136 :
137 35 : *real_ret_num = ret_num;
138 :
139 35 : return (ret_len);
140 : }
141 :
142 : size_t vstr_export_buf(const Vstr_base *base, size_t pos, size_t len,
143 : void *buf, size_t buf_len)
144 16054 : {
145 16054 : Vstr_iter iter[1];
146 :
147 16054 : ASSERT_RET(buf, 0);
148 :
149 16050 : if (!buf_len)
150 5 : return (0);
151 :
152 16045 : if (len > buf_len)
153 10 : len = buf_len;
154 :
155 16045 : if (!vstr_iter_fwd_beg(base, pos, len, iter))
156 16 : return (0);
157 :
158 41359 : ASSERT(len == vstr_iter_len(iter));
159 :
160 47896 : do
161 : {
162 47896 : if (iter->node->type != VSTR_TYPE_NODE_NON)
163 47723 : vstr_wrap_memcpy(buf, iter->ptr, iter->len);
164 :
165 47896 : buf = ((char *)buf) + iter->len;
166 47896 : } while (vstr_iter_fwd_nxt(iter));
167 :
168 16029 : return (len);
169 : }
170 :
171 : static Vstr_ref *vstr__export_buf_ref(const Vstr_base *base,
172 : size_t pos, size_t len)
173 414 : {
174 414 : Vstr_ref *ref = NULL;
175 :
176 414 : ASSERT(len);
177 :
178 414 : if (!(ref = vstr_ref_make_malloc(len)))
179 : {
180 43 : base->conf->malloc_bad = TRUE;
181 43 : return (NULL);
182 : }
183 :
184 371 : assert(((Vstr__buf_ref *)ref)->buf == ref->ptr);
185 :
186 371 : vstr_export_buf(base, pos, len, ref->ptr, len);
187 :
188 371 : return (ref);
189 : }
190 :
191 : Vstr_ref *vstr_export_ref(const Vstr_base *base, size_t pos, size_t len,
192 : size_t *ret_off)
193 1899 : {
194 1899 : Vstr_node **scan = NULL;
195 1899 : unsigned int num = 0;
196 1899 : Vstr_ref *ref = NULL;
197 1899 : size_t orig_pos = pos;
198 :
199 1899 : assert(base && pos && len && ((pos + len - 1) <= base->len));
200 1899 : assert(ret_off);
201 :
202 1899 : if (base->cache_available)
203 : { /* use cstr cache if available */
204 1879 : Vstr__cache_data_cstr *data = NULL;
205 1879 : unsigned int off = base->conf->cache_pos_cb_cstr;
206 :
207 1879 : if ((data = vstr_cache_get(base, off)) && data->ref && data->len)
208 : {
209 194 : if (pos >= data->pos)
210 : {
211 68 : size_t tmp = (pos - data->pos);
212 68 : if (data->len <= (len - tmp))
213 : {
214 5 : *ret_off = tmp;
215 5 : return (vstr_ref_add(data->ref));
216 : }
217 : }
218 : }
219 : }
220 :
221 1894 : scan = vstr__base_ptr_pos(base, &pos, &num);
222 1894 : --pos;
223 :
224 1894 : if (((*scan)->len - pos) >= len)
225 : {
226 1480 : if (0)
227 : { /* do nothing */; }
228 1480 : else if ((*scan)->type == VSTR_TYPE_NODE_REF)
229 : {
230 133 : *ret_off = pos + ((Vstr_node_ref *)*scan)->off;
231 133 : return (vstr_ref_add(((Vstr_node_ref *)*scan)->ref));
232 : }
233 1347 : else if ((*scan)->type == VSTR_TYPE_NODE_PTR)
234 : {
235 1294 : void *ptr = ((char *)((Vstr_node_ptr *)*scan)->ptr) + pos;
236 :
237 1294 : if (!base->conf->ref_grp_ptr)
238 : {
239 12 : Vstr_ref_grp_ptr *tmp = NULL;
240 :
241 12 : if (!(tmp = vstr__ref_grp_make(vstr_ref_cb_free_nothing, 0)))
242 : {
243 1 : base->conf->malloc_bad = TRUE;
244 1 : return (NULL);
245 : }
246 :
247 11 : base->conf->ref_grp_ptr = tmp;
248 : }
249 :
250 1293 : if (!(ref = vstr__ref_grp_add(&base->conf->ref_grp_ptr, ptr)))
251 : {
252 1 : base->conf->malloc_bad = TRUE;
253 1 : return (NULL);
254 : }
255 :
256 1292 : *ret_off = 0;
257 :
258 1292 : return (ref);
259 : }
260 53 : else if ((*scan)->type == VSTR_TYPE_NODE_BUF)
261 : {
262 53 : if (!vstr__chg_node_buf_ref(base, scan, num))
263 1 : return (NULL);
264 :
265 : /* NOTE: pos can include ->used stuff, which is now gone */
266 52 : assert(pos >= ((Vstr_node_ref *)*scan)->off);
267 52 : *ret_off = pos;
268 52 : return (vstr_ref_add(((Vstr_node_ref *)*scan)->ref));
269 : }
270 : }
271 :
272 414 : *ret_off = 0;
273 414 : if (!(ref = vstr__export_buf_ref(base, orig_pos, len)))
274 43 : return (NULL);
275 :
276 371 : return (ref);
277 : }
|