1 : /* Copyright (c) 2007 Paul Rosenfeld
2 : James Antill -- See LICENSE file for terms. */
3 : #ifndef USTR_INS_H
4 : #error " Include ustr-ins.h before this file."
5 : #endif
6 :
7 :
8 : USTR_CONF_I_PROTO
9 : int ustrp__ins_undef(struct Ustr_pool*p,struct Ustr **ps1,size_t pos,size_t len)
10 432 : { /* basically the opposite of ustr_del_subustr() */
11 432 : struct Ustr *s1 = USTR_NULL;
12 432 : struct Ustr *ret = USTR_NULL;
13 432 : size_t clen = 0;
14 432 : size_t nlen = 0;
15 432 : size_t sz = 0;
16 432 : size_t oh = 0;
17 432 : size_t osz = 0;
18 432 : size_t nsz = 0;
19 432 : int alloc = USTR_FALSE;
20 432 : const char *ocstr = 0;
21 :
22 234 : USTR_ASSERT(ps1 && ustrp__assert_valid(!!p, *ps1));
23 :
24 432 : if (!len)
25 20 : return (USTR_TRUE);
26 :
27 412 : s1 = *ps1;
28 300 : clen = ustr_len(s1);
29 412 : USTR_ASSERT_RET(pos <= clen, USTR_FALSE);
30 412 : if (pos == clen) /* inserting at the end */
31 20 : return (ustrp__add_undef(p, ps1, len));
32 :
33 392 : if ((nlen = clen + len) < clen) /* overflow */
34 12 : goto fail_enomem;
35 :
36 380 : if (ustr__rw_mod(*ps1, nlen, &sz, &oh, &osz, &nsz, &alloc))
37 : {
38 : char *ptr;
39 :
40 184 : if (!ustrp__add_undef(p, ps1, len))
41 12 : return (USTR_FALSE);
42 :
43 172 : ptr = ustr_wstr(*ps1);
44 172 : memmove(ptr + pos + len, ptr + pos, (clen - pos));
45 :
46 86 : USTR_ASSERT(ustrp__assert_valid(!!p, *ps1));
47 172 : return (USTR_TRUE);
48 : }
49 :
50 660 : if (!(ret = ustrp__dupx_undef(p, USTR__DUPX_FROM(s1), nlen)))
51 144 : goto fail_enomem;
52 :
53 39 : ocstr = ustr_cstr(s1);
54 :
55 26 : USTR_ASSERT(pos || (clen - pos)); /* can be both */
56 :
57 52 : ustr__memcpy(ret, 0, ocstr, pos);
58 52 : ustr__memcpy(ret, pos + len, ocstr + pos, clen - pos);
59 :
60 52 : ustrp__sc_free2(p, ps1, ret);
61 :
62 26 : USTR_ASSERT(ustrp__assert_valid(!!p, *ps1));
63 52 : return (USTR_TRUE);
64 :
65 156 : fail_enomem:
66 156 : ustr_setf_enomem_err(s1);
67 156 : return (USTR_FALSE);
68 : }
69 : USTR_CONF_I_PROTO int ustr_ins_undef(struct Ustr **ps1, size_t pos, size_t len)
70 144 : { return (ustrp__ins_undef(0, ps1, pos, len)); }
71 : USTR_CONF_I_PROTO
72 : int ustrp_ins_undef(struct Ustr_pool *p,struct Ustrp**ps1,size_t pos,size_t len)
73 4 : {
74 4 : struct Ustr *tmp = &(*ps1)->s;
75 4 : int ret = ustrp__ins_undef(p, &tmp, pos, len);
76 4 : *ps1 = USTRP(tmp);
77 4 : return (ret);
78 : }
79 :
80 : USTR_CONF_i_PROTO int ustrp__ins_buf(struct Ustr_pool *p, struct Ustr **ps1,
81 : size_t pos, const void *buf, size_t len)
82 84 : {
83 84 : if (!ustrp__ins_undef(p, ps1, pos, len))
84 8 : return (USTR_FALSE);
85 :
86 76 : ustr__memcpy(*ps1, pos, buf, len);
87 :
88 76 : return (USTR_TRUE);
89 : }
90 : USTR_CONF_I_PROTO
91 : int ustr_ins_buf(struct Ustr **ps1, size_t pos, const void *buf, size_t len)
92 12 : { return (ustrp__ins_buf(0, ps1, pos, buf, len)); }
93 : USTR_CONF_I_PROTO int ustrp_ins_buf(struct Ustr_pool *p, struct Ustrp **ps1,
94 : size_t pos, const void *buf, size_t len)
95 8 : {
96 8 : struct Ustr *tmp = &(*ps1)->s;
97 8 : int ret = ustrp__ins_buf(p, &tmp, pos, buf, len);
98 8 : *ps1 = USTRP(tmp);
99 8 : return (ret);
100 : }
101 :
102 : USTR_CONF_i_PROTO int ustrp__ins(struct Ustr_pool *p, struct Ustr **ps1,
103 : size_t pos, const struct Ustr *s2)
104 64 : {
105 80 : if (pos == ustr_len(*ps1))
106 20 : return (ustrp__add(p, ps1, s2));
107 :
108 44 : if ((*ps1 == s2) && ustr_owner(*ps1))
109 : {
110 32 : size_t len = ustr_len(*ps1);
111 32 : size_t blen = 0;
112 32 : size_t pos2 = 0;
113 :
114 32 : if (!ustrp__ins_undef(p, ps1, pos, len))
115 4 : return (USTR_FALSE);
116 :
117 28 : blen = pos;
118 35 : ustr__memcpy(*ps1, pos, ustr_cstr(*ps1), blen);
119 28 : pos += blen;
120 28 : pos2 += len;
121 28 : pos2 += blen;
122 28 : len -= blen;
123 35 : ustr__memcpy(*ps1, pos, ustr_cstr(*ps1) + pos2, len);
124 14 : USTR_ASSERT(ustrp__assert_valid(!!p, *ps1));
125 :
126 28 : return (USTR_TRUE);
127 : }
128 :
129 12 : return (ustrp__ins_buf(p, ps1, pos, ustr_cstr(s2), ustr_len(s2)));
130 : }
131 : USTR_CONF_I_PROTO
132 : int ustr_ins(struct Ustr **ps1, size_t pos, const struct Ustr *s2)
133 32 : { return (ustrp__ins(0, ps1, pos, s2)); }
134 : USTR_CONF_I_PROTO int ustrp_ins(struct Ustr_pool *p, struct Ustrp **ps1,
135 : size_t pos, const struct Ustrp *s2)
136 16 : {
137 16 : struct Ustr *tmp = &(*ps1)->s;
138 16 : int ret = ustrp__ins(p, &tmp, pos, &s2->s);
139 16 : *ps1 = USTRP(tmp);
140 16 : return (ret);
141 : }
142 :
143 : USTR_CONF_i_PROTO
144 : int ustrp__ins_subustr(struct Ustr_pool *p, struct Ustr **ps1, size_t pos1,
145 : const struct Ustr *s2, size_t pos2, size_t len2)
146 136 : {
147 136 : size_t clen2 = 0;
148 :
149 136 : if (!len2)
150 20 : return (USTR_TRUE);
151 :
152 116 : if (!(clen2 = ustrp__assert_valid_subustr(!!p, s2, pos2, len2)))
153 8 : return (USTR_FALSE);
154 :
155 108 : if (clen2 == len2)
156 12 : return (ustrp__ins(p, ps1, pos1, s2));
157 :
158 96 : if (pos1 == clen2)
159 12 : return (ustrp__add_subustr(p, ps1, s2, pos2, len2));
160 :
161 84 : if ((*ps1 == s2) && ustr_owner(*ps1))
162 : {
163 68 : if (!ustrp__ins_undef(p, ps1, pos1, len2))
164 4 : return (USTR_FALSE);
165 :
166 64 : if (pos2 > pos1)
167 12 : pos2 += len2;
168 52 : else if ((pos2 + len2 - 1) > pos1)
169 : {
170 12 : size_t blen = (pos1 - pos2) + 1;
171 :
172 15 : ustr__memcpy(*ps1, pos1, ustr_cstr(*ps1) + pos2 - 1, blen);
173 12 : pos1 += blen;
174 12 : pos2 += len2;
175 12 : pos2 += blen;
176 12 : len2 -= blen;
177 : }
178 80 : ustr__memcpy(*ps1, pos1, ustr_cstr(*ps1) + pos2 - 1, len2);
179 :
180 32 : USTR_ASSERT(ustrp__assert_valid(!!p, *ps1));
181 64 : return (USTR_TRUE);
182 : }
183 :
184 16 : --pos2;
185 16 : return (ustrp__ins_buf(p, ps1, pos1, ustr_cstr(s2) + pos2, len2));
186 : }
187 : USTR_CONF_I_PROTO
188 : int ustr_ins_subustr(struct Ustr **ps1, size_t pos1,
189 : const struct Ustr *s2, size_t pos2, size_t len2)
190 88 : { return (ustrp__ins_subustr(0, ps1, pos1, s2, pos2, len2)); }
191 : USTR_CONF_I_PROTO
192 : int ustrp_ins_subustrp(struct Ustr_pool *p, struct Ustrp **ps1, size_t pos1,
193 : const struct Ustrp *s2, size_t pos2, size_t len2)
194 4 : {
195 4 : struct Ustr *tmp = &(*ps1)->s;
196 4 : int ret = ustrp__ins_subustr(p, &tmp, pos1, &s2->s, pos2, len2);
197 4 : *ps1 = USTRP(tmp);
198 4 : return (ret);
199 : }
200 :
201 : USTR_CONF_i_PROTO int ustrp__ins_rep_chr(struct Ustr_pool *p, struct Ustr **ps1,
202 : size_t pos, char chr, size_t len)
203 20 : {
204 20 : if (!ustrp__ins_undef(p, ps1, pos, len))
205 4 : return (USTR_FALSE);
206 :
207 16 : ustr__memset(*ps1, pos, chr, len);
208 :
209 16 : return (USTR_TRUE);
210 : }
211 : USTR_CONF_I_PROTO
212 : int ustr_ins_rep_chr(struct Ustr **ps1, size_t pos, char chr, size_t len)
213 16 : { return (ustrp__ins_rep_chr(0, ps1, pos, chr, len)); }
214 : USTR_CONF_I_PROTO int ustrp_ins_rep_chr(struct Ustr_pool *p, struct Ustrp **ps1,
215 : size_t pos, char chr, size_t len)
216 :
217 4 : {
218 4 : struct Ustr *tmp = &(*ps1)->s;
219 4 : int ret = ustrp__ins_rep_chr(p, &tmp, pos, chr, len);
220 4 : *ps1 = USTRP(tmp);
221 4 : return (ret);
222 : }
223 :
224 : #ifdef USTR_FMT_H
225 : # if USTR_CONF_HAVE_VA_COPY
226 : USTR_CONF_i_PROTO
227 : int ustrp__ins_vfmt_lim(struct Ustr_pool *p, struct Ustr **ps1, size_t pos,
228 : size_t lim, const char *fmt, va_list ap)
229 48 : { /* NOTE: Copy and pasted so we can use ustrp_set_undef() */
230 : va_list nap;
231 48 : int rc = -1;
232 : char buf[USTR__SNPRINTF_LOCAL];
233 : char *ptr;
234 : char save_end;
235 :
236 48 : USTR__VA_COPY(nap, ap);
237 48 : rc = USTR_CONF_VSNPRINTF_BEG(buf, sizeof(buf), fmt, nap);
238 48 : va_end(nap);
239 :
240 48 : if ((rc == -1) && ((rc = ustr__retard_vfmt_ret(fmt, ap)) == -1))
241 4 : return (USTR_FALSE);
242 :
243 44 : if (lim && ((size_t)rc > lim))
244 8 : rc = lim;
245 :
246 44 : if ((size_t)rc < sizeof(buf)) /* everything is done */
247 36 : return (ustrp__ins_buf(p, ps1, pos, buf, rc));
248 :
249 8 : if (!ustrp__ins_undef(p, ps1, pos, rc))
250 4 : return (USTR_FALSE);
251 :
252 4 : ptr = ustr_wstr(*ps1);
253 :
254 4 : save_end = ptr[pos + rc]; /* might be NIL, might be a char */
255 4 : USTR_CONF_VSNPRINTF_END(ptr + pos, rc + 1, fmt, ap);
256 4 : ptr[pos + rc] = save_end;
257 :
258 2 : USTR_ASSERT(ustrp__assert_valid(!!p, *ps1));
259 :
260 4 : return (USTR_TRUE);
261 : }
262 : USTR_CONF_I_PROTO int ustr_ins_vfmt_lim(struct Ustr **ps1,size_t pos,size_t lim,
263 : const char *fmt, va_list ap)
264 36 : { return (ustrp__ins_vfmt_lim(0, ps1, pos, lim, fmt, ap)); }
265 : USTR_CONF_I_PROTO
266 : int ustrp_ins_vfmt_lim(struct Ustr_pool *p,struct Ustrp **ps1, size_t pos,
267 : size_t lim, const char *fmt, va_list ap)
268 12 : {
269 12 : struct Ustr *tmp = &(*ps1)->s;
270 12 : int ret = ustrp__ins_vfmt_lim(p, &tmp, pos, lim, fmt, ap);
271 12 : *ps1 = USTRP(tmp);
272 12 : return (ret);
273 : }
274 :
275 : USTR_CONF_I_PROTO int ustr_ins_fmt_lim(struct Ustr **ps1, size_t pos,
276 : size_t lim, const char *fmt, ...)
277 16 : {
278 : va_list ap;
279 16 : int ret = USTR_FALSE;
280 :
281 16 : va_start(ap, fmt);
282 16 : ret = ustr_ins_vfmt_lim(ps1, pos, lim, fmt, ap);
283 16 : va_end(ap);
284 :
285 16 : return (ret);
286 : }
287 :
288 : USTR_CONF_I_PROTO
289 : int ustrp_ins_fmt_lim(struct Ustr_pool *p, struct Ustrp **ps1, size_t pos,
290 : size_t lim, const char*fmt, ...)
291 4 : {
292 : va_list ap;
293 4 : int ret = USTR_FALSE;
294 :
295 4 : va_start(ap, fmt);
296 4 : ret = ustrp_ins_vfmt_lim(p, ps1, pos, lim, fmt, ap);
297 4 : va_end(ap);
298 :
299 4 : return (ret);
300 : }
301 :
302 : USTR_CONF_I_PROTO int ustr_ins_vfmt(struct Ustr **ps1, size_t pos,
303 : const char *fmt, va_list ap)
304 20 : { return (ustr_ins_vfmt_lim(ps1, pos, 0, fmt, ap)); }
305 :
306 : USTR_CONF_I_PROTO int ustrp_ins_vfmt(struct Ustr_pool *p, struct Ustrp **ps1,
307 : size_t pos, const char *fmt, va_list ap)
308 8 : { return (ustrp_ins_vfmt_lim(p, ps1, pos, 0, fmt, ap)); }
309 :
310 : USTR_CONF_I_PROTO
311 : int ustr_ins_fmt(struct Ustr **ps1, size_t pos, const char *fmt, ...)
312 20 : {
313 : va_list ap;
314 20 : int ret = USTR_FALSE;
315 :
316 20 : va_start(ap, fmt);
317 20 : ret = ustr_ins_vfmt(ps1, pos, fmt, ap);
318 20 : va_end(ap);
319 :
320 20 : return (ret);
321 : }
322 :
323 : USTR_CONF_I_PROTO int ustrp_ins_fmt(struct Ustr_pool *p, struct Ustrp **ps1,
324 : size_t pos, const char *fmt, ...)
325 8 : {
326 : va_list ap;
327 8 : int ret = USTR_FALSE;
328 :
329 8 : va_start(ap, fmt);
330 8 : ret = ustrp_ins_vfmt(p, ps1, pos, fmt, ap);
331 8 : va_end(ap);
332 :
333 8 : return (ret);
334 : }
335 : # endif
336 : #endif
|