1 : #define VSTR_CSTR_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 : /* Functions to allow export of a "C string" like interface */
22 : #include "main.h"
23 :
24 : static Vstr_ref *vstr__export_cstr_ref(const Vstr_base *base,
25 : size_t pos, size_t len)
26 344 : {
27 344 : Vstr_ref *ref = NULL;
28 :
29 344 : if (!(ref = vstr_ref_make_malloc(len + 1)))
30 : {
31 2 : base->conf->malloc_bad = TRUE;
32 2 : return (NULL);
33 : }
34 :
35 342 : assert(((Vstr__buf_ref *)ref)->buf == ref->ptr);
36 :
37 342 : vstr_export_cstr_buf(base, pos, len, ref->ptr, len + 1);
38 :
39 342 : return (ref);
40 : }
41 :
42 : static Vstr__cache_data_cstr *vstr__export_cstr_cache(const Vstr_base *base,
43 : size_t pos, size_t len,
44 : size_t *ret_off)
45 14349 : {
46 14349 : Vstr_ref *ref = NULL;
47 14349 : Vstr__cache_data_cstr *data = NULL;
48 14349 : unsigned int off = 3;
49 :
50 14349 : ASSERT(base && pos && ((pos + len - 1) <= base->len) && ret_off);
51 14349 : ASSERT(len || (!base->len && (pos == 1)));
52 :
53 14349 : ASSERT(off == base->conf->cache_pos_cb_cstr);
54 :
55 14349 : if (!(data = vstr_cache_get(base, off)))
56 : {
57 207 : int ret = FALSE;
58 :
59 207 : ASSERT(base->grpalloc_cache < VSTR_TYPE_CNTL_CONF_GRPALLOC_CSTR);
60 :
61 207 : if (!vstr_cache_set(base, off, NULL))
62 40 : return (NULL);
63 :
64 167 : if (!(data = VSTR__MK(sizeof(Vstr__cache_data_cstr))))
65 : {
66 1 : base->conf->malloc_bad = TRUE;
67 1 : return (NULL);
68 : }
69 166 : data->ref = NULL;
70 :
71 166 : ret = vstr_cache_set(base, off, data);
72 11481 : ASSERT(ret);
73 : }
74 :
75 14308 : if (data->ref && data->len)
76 : {
77 1009 : ASSERT(data->sz);
78 1009 : ASSERT(((Vstr__buf_ref *)data->ref)->buf == data->ref->ptr);
79 :
80 1009 : *ret_off = data->off;
81 :
82 1009 : if (pos >= data->pos)
83 : {
84 949 : size_t tmp = (pos - data->pos);
85 949 : if ((data->len - tmp) == len)
86 : {
87 92 : *ret_off += tmp;
88 92 : return (data);
89 : }
90 : }
91 : }
92 14216 : if (data->ref)
93 : {
94 14016 : if ((data->sz <= len) || (data->ref->ref != 1))
95 : {
96 137 : vstr_ref_del(data->ref);
97 137 : data->ref = NULL;
98 : }
99 : else
100 : { /* can overwrite previous cache entry */
101 13879 : ref = data->ref;
102 13879 : vstr_export_cstr_buf(base, pos, len, ref->ptr, len + 1);
103 :
104 13879 : goto export_new_cstr;
105 : }
106 : }
107 :
108 337 : if (!(ref = vstr__export_cstr_ref(base, pos, len)))
109 1 : return (NULL);
110 336 : data->sz = len + 1;
111 :
112 : export_new_cstr:
113 14215 : data->ref = ref;
114 14215 : data->off = 0;
115 14215 : data->pos = pos;
116 14215 : data->len = len;
117 :
118 14215 : *ret_off = 0;
119 14215 : return (data);
120 : }
121 :
122 : const char *vstr_export_cstr_ptr(const Vstr_base *base, size_t pos, size_t len)
123 14321 : {
124 14321 : Vstr__cache_data_cstr *data = NULL;
125 14321 : size_t off = 0;
126 :
127 14321 : if (!(data = vstr__export_cstr_cache(base, pos, len, &off)))
128 40 : return (NULL);
129 :
130 14281 : ASSERT(vstr__check_real_nodes(base));
131 :
132 14281 : return (((char *)data->ref->ptr) + off);
133 : }
134 :
135 : char *vstr_export_cstr_malloc(const Vstr_base *base, size_t pos, size_t len)
136 259 : {
137 259 : void *ptr = malloc(len + 1);
138 :
139 259 : if (!ptr)
140 : {
141 5 : base->conf->malloc_bad = TRUE;
142 5 : return (NULL);
143 : }
144 :
145 254 : vstr_export_cstr_buf(base, pos, len, ptr, len + 1);
146 :
147 254 : return (ptr);
148 : }
149 :
150 : Vstr_ref *vstr_export_cstr_ref(const Vstr_base *base, size_t pos, size_t len,
151 : size_t *ret_off)
152 35 : {
153 35 : Vstr__cache_data_cstr *data = NULL;
154 :
155 35 : ASSERT(ret_off);
156 :
157 35 : if (!base->cache_available)
158 : {
159 7 : Vstr_ref *ref = vstr__export_cstr_ref(base, pos, len);
160 :
161 7 : if (!ref)
162 1 : return (NULL);
163 :
164 6 : *ret_off = 0;
165 6 : return (ref);
166 : }
167 :
168 28 : if (!(data = vstr__export_cstr_cache(base, pos, len, ret_off)))
169 2 : return (NULL);
170 :
171 26 : return (vstr_ref_add(data->ref));
172 : }
173 :
174 : size_t vstr_export_cstr_buf(const Vstr_base *base, size_t pos, size_t len,
175 : void *buf, size_t buf_len)
176 14535 : {
177 14535 : size_t cpy_len = len;
178 :
179 14535 : if (!buf_len)
180 5 : return (0);
181 :
182 14530 : if (cpy_len >= buf_len)
183 5 : cpy_len = (buf_len - 1);
184 :
185 14530 : vstr_export_buf(base, pos, len, buf, cpy_len);
186 14530 : ((char *)buf)[cpy_len] = 0;
187 :
188 14530 : return (cpy_len + 1);
189 : }
|