Expand PMF_FN_* macros.
[netbsd-mini2440.git] / external / bsd / atf / dist / atf-c / dynstr.c
blobcb659ead69f6f561abce675136039773bef3eb62
1 /*
2 * Automated Testing Framework (atf)
4 * Copyright (c) 2008, 2009 The NetBSD Foundation, Inc.
5 * All rights reserved.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
16 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND
17 * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
18 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
19 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY
21 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
23 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
25 * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
26 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
27 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 #include <errno.h>
31 #include <stdarg.h>
32 #include <stdio.h>
33 #include <stdlib.h>
34 #include <string.h>
36 #include "atf-c/dynstr.h"
37 #include "atf-c/error.h"
38 #include "atf-c/sanity.h"
39 #include "atf-c/text.h"
41 /* ---------------------------------------------------------------------
42 * Auxiliary functions.
43 * --------------------------------------------------------------------- */
45 static
46 atf_error_t
47 resize(atf_dynstr_t *ad, size_t newsize)
49 char *newdata;
50 atf_error_t err;
52 PRE(newsize > ad->m_datasize);
54 newdata = (char *)malloc(newsize);
55 if (newdata == NULL) {
56 err = atf_no_memory_error();
57 } else {
58 strcpy(newdata, ad->m_data);
59 free(ad->m_data);
60 ad->m_data = newdata;
61 ad->m_datasize = newsize;
62 err = atf_no_error();
65 return err;
68 static
69 atf_error_t
70 prepend_or_append(atf_dynstr_t *ad, const char *fmt, va_list ap,
71 bool prepend)
73 char *aux;
74 atf_error_t err;
75 size_t newlen;
76 va_list ap2;
78 va_copy(ap2, ap);
79 err = atf_text_format_ap(&aux, fmt, ap2);
80 va_end(ap2);
81 if (atf_is_error(err))
82 goto out;
83 newlen = ad->m_length + strlen(aux);
85 if (newlen + sizeof(char) > ad->m_datasize) {
86 err = resize(ad, newlen + sizeof(char));
87 if (atf_is_error(err))
88 goto out_free;
91 if (prepend) {
92 memmove(ad->m_data + strlen(aux), ad->m_data, ad->m_length + 1);
93 memcpy(ad->m_data, aux, strlen(aux));
94 } else
95 strcpy(ad->m_data + ad->m_length, aux);
96 ad->m_length = newlen;
97 err = atf_no_error();
99 out_free:
100 free(aux);
101 out:
102 return err;
105 /* ---------------------------------------------------------------------
106 * The "atf_dynstr" type.
107 * --------------------------------------------------------------------- */
110 * Constants.
113 const size_t atf_dynstr_npos = SIZE_MAX;
116 * Constructors and destructors.
119 atf_error_t
120 atf_dynstr_init(atf_dynstr_t *ad)
122 atf_error_t err;
124 atf_object_init(&ad->m_object);
126 ad->m_data = (char *)malloc(sizeof(char));
127 if (ad->m_data == NULL) {
128 err = atf_no_memory_error();
129 goto err_object;
132 ad->m_data[0] = '\0';
133 ad->m_datasize = 1;
134 ad->m_length = 0;
135 err = atf_no_error();
136 goto out;
138 err_object:
139 atf_object_fini(&ad->m_object);
140 out:
141 return err;
144 atf_error_t
145 atf_dynstr_init_ap(atf_dynstr_t *ad, const char *fmt, va_list ap)
147 atf_error_t err;
149 atf_object_init(&ad->m_object);
151 ad->m_datasize = strlen(fmt) + 1;
152 ad->m_length = 0;
154 do {
155 va_list ap2;
156 int ret;
158 ad->m_datasize *= 2;
159 ad->m_data = (char *)malloc(ad->m_datasize);
160 if (ad->m_data == NULL) {
161 err = atf_no_memory_error();
162 goto err_object;
165 va_copy(ap2, ap);
166 ret = vsnprintf(ad->m_data, ad->m_datasize, fmt, ap2);
167 va_end(ap2);
168 if (ret < 0) {
169 free(ad->m_data);
170 err = atf_libc_error(errno, "Cannot format string");
171 goto err_object;
174 INV(ret >= 0);
175 if ((size_t)ret >= ad->m_datasize) {
176 free(ad->m_data);
177 ad->m_data = NULL;
179 ad->m_length = ret;
180 } while (ad->m_length >= ad->m_datasize);
182 err = atf_no_error();
183 goto out;
185 err_object:
186 atf_object_fini(&ad->m_object);
187 out:
188 POST(atf_is_error(err) || ad->m_data != NULL);
189 return err;
192 atf_error_t
193 atf_dynstr_init_fmt(atf_dynstr_t *ad, const char *fmt, ...)
195 va_list ap;
196 atf_error_t err;
198 va_start(ap, fmt);
199 err = atf_dynstr_init_ap(ad, fmt, ap);
200 va_end(ap);
202 return err;
205 atf_error_t
206 atf_dynstr_init_raw(atf_dynstr_t *ad, const void *mem, size_t memlen)
208 atf_error_t err;
210 atf_object_init(&ad->m_object);
212 if (memlen >= SIZE_MAX - 1) {
213 err = atf_no_memory_error();
214 goto err_object;
217 ad->m_data = (char *)malloc(memlen + 1);
218 if (ad->m_data == NULL) {
219 err = atf_no_memory_error();
220 goto err_object;
223 ad->m_datasize = memlen + 1;
224 memcpy(ad->m_data, mem, memlen);
225 ad->m_data[memlen] = '\0';
226 ad->m_length = strlen(ad->m_data);
227 INV(ad->m_length <= memlen);
228 err = atf_no_error();
229 goto out;
231 err_object:
232 atf_object_fini(&ad->m_object);
233 out:
234 return err;
237 atf_error_t
238 atf_dynstr_init_rep(atf_dynstr_t *ad, size_t len, char ch)
240 atf_error_t err;
242 atf_object_init(&ad->m_object);
244 if (len == SIZE_MAX) {
245 err = atf_no_memory_error();
246 goto err_object;
249 ad->m_datasize = (len + 1) * sizeof(char);
250 ad->m_data = (char *)malloc(ad->m_datasize);
251 if (ad->m_data == NULL) {
252 err = atf_no_memory_error();
253 goto err_object;
256 memset(ad->m_data, ch, len);
257 ad->m_data[len] = '\0';
258 ad->m_length = len;
259 err = atf_no_error();
260 goto out;
262 err_object:
263 atf_object_fini(&ad->m_object);
264 out:
265 return err;
268 atf_error_t
269 atf_dynstr_init_substr(atf_dynstr_t *ad, const atf_dynstr_t *src,
270 size_t beg, size_t end)
272 if (beg > src->m_length)
273 beg = src->m_length;
275 if (end == atf_dynstr_npos || end > src->m_length)
276 end = src->m_length;
278 return atf_dynstr_init_raw(ad, src->m_data + beg, end - beg);
281 atf_error_t
282 atf_dynstr_copy(atf_dynstr_t *dest, const atf_dynstr_t *src)
284 atf_error_t err;
286 atf_object_copy(&dest->m_object, &src->m_object);
288 dest->m_data = (char *)malloc(src->m_datasize);
289 if (dest->m_data == NULL)
290 err = atf_no_memory_error();
291 else {
292 memcpy(dest->m_data, src->m_data, src->m_datasize);
293 dest->m_datasize = src->m_datasize;
294 dest->m_length = src->m_length;
295 err = atf_no_error();
298 return err;
301 void
302 atf_dynstr_fini(atf_dynstr_t *ad)
304 INV(ad->m_data != NULL);
305 free(ad->m_data);
307 atf_object_fini(&ad->m_object);
310 char *
311 atf_dynstr_fini_disown(atf_dynstr_t *ad)
313 atf_object_fini(&ad->m_object);
315 INV(ad->m_data != NULL);
316 return ad->m_data;
320 * Getters.
323 const char *
324 atf_dynstr_cstring(const atf_dynstr_t *ad)
326 return ad->m_data;
329 size_t
330 atf_dynstr_length(const atf_dynstr_t *ad)
332 return ad->m_length;
335 size_t
336 atf_dynstr_rfind_ch(const atf_dynstr_t *ad, char ch)
338 size_t pos;
340 for (pos = ad->m_length; pos > 0 && ad->m_data[pos - 1] != ch; pos--)
343 return pos == 0 ? atf_dynstr_npos : pos - 1;
347 * Modifiers.
350 atf_error_t
351 atf_dynstr_append_ap(atf_dynstr_t *ad, const char *fmt, va_list ap)
353 atf_error_t err;
354 va_list ap2;
356 va_copy(ap2, ap);
357 err = prepend_or_append(ad, fmt, ap2, false);
358 va_end(ap2);
360 return err;
363 atf_error_t
364 atf_dynstr_append_fmt(atf_dynstr_t *ad, const char *fmt, ...)
366 va_list ap;
367 atf_error_t err;
369 va_start(ap, fmt);
370 err = prepend_or_append(ad, fmt, ap, false);
371 va_end(ap);
373 return err;
376 void
377 atf_dynstr_clear(atf_dynstr_t *ad)
379 ad->m_data[0] = '\0';
380 ad->m_length = 0;
383 atf_error_t
384 atf_dynstr_prepend_ap(atf_dynstr_t *ad, const char *fmt, va_list ap)
386 atf_error_t err;
387 va_list ap2;
389 va_copy(ap2, ap);
390 err = prepend_or_append(ad, fmt, ap2, true);
391 va_end(ap2);
393 return err;
396 atf_error_t
397 atf_dynstr_prepend_fmt(atf_dynstr_t *ad, const char *fmt, ...)
399 va_list ap;
400 atf_error_t err;
402 va_start(ap, fmt);
403 err = prepend_or_append(ad, fmt, ap, true);
404 va_end(ap);
406 return err;
410 * Operators.
413 bool
414 atf_equal_dynstr_cstring(const atf_dynstr_t *ad, const char *str)
416 return strcmp(ad->m_data, str) == 0;
419 bool
420 atf_equal_dynstr_dynstr(const atf_dynstr_t *s1, const atf_dynstr_t *s2)
422 return strcmp(s1->m_data, s2->m_data) == 0;