Home | History | Annotate | Line # | Download | only in detail
      1 /*
      2  * Automated Testing Framework (atf)
      3  *
      4  * Copyright (c) 2008 The NetBSD Foundation, Inc.
      5  * All rights reserved.
      6  *
      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.
     15  *
     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.
     28  */
     29 
     30 #include <errno.h>
     31 #include <stdarg.h>
     32 #include <stdint.h>
     33 #include <stdio.h>
     34 #include <stdlib.h>
     35 #include <string.h>
     36 
     37 #include "atf-c/error.h"
     38 
     39 #include "dynstr.h"
     40 #include "sanity.h"
     41 #include "text.h"
     42 
     43 /* ---------------------------------------------------------------------
     44  * Auxiliary functions.
     45  * --------------------------------------------------------------------- */
     46 
     47 static
     48 atf_error_t
     49 resize(atf_dynstr_t *ad, size_t newsize)
     50 {
     51     char *newdata;
     52     atf_error_t err;
     53 
     54     PRE(newsize > ad->m_datasize);
     55 
     56     newdata = (char *)malloc(newsize);
     57     if (newdata == NULL) {
     58         err = atf_no_memory_error();
     59     } else {
     60         strcpy(newdata, ad->m_data);
     61         free(ad->m_data);
     62         ad->m_data = newdata;
     63         ad->m_datasize = newsize;
     64         err = atf_no_error();
     65     }
     66 
     67     return err;
     68 }
     69 
     70 ATF_DEFS_ATTRIBUTE_FORMAT_PRINTF(2, 0)
     71 static
     72 atf_error_t
     73 prepend_or_append(atf_dynstr_t *ad, const char *fmt, va_list ap,
     74                   bool prepend)
     75 {
     76     char *aux;
     77     atf_error_t err;
     78     size_t newlen;
     79     va_list ap2;
     80 
     81     va_copy(ap2, ap);
     82     err = atf_text_format_ap(&aux, fmt, ap2);
     83     va_end(ap2);
     84     if (atf_is_error(err))
     85         goto out;
     86     newlen = ad->m_length + strlen(aux);
     87 
     88     if (newlen + sizeof(char) > ad->m_datasize) {
     89         err = resize(ad, newlen + sizeof(char));
     90         if (atf_is_error(err))
     91             goto out_free;
     92     }
     93 
     94     if (prepend) {
     95         memmove(ad->m_data + strlen(aux), ad->m_data, ad->m_length + 1);
     96         memcpy(ad->m_data, aux, strlen(aux));
     97     } else
     98         strcpy(ad->m_data + ad->m_length, aux);
     99     ad->m_length = newlen;
    100     err = atf_no_error();
    101 
    102 out_free:
    103     free(aux);
    104 out:
    105     return err;
    106 }
    107 
    108 /* ---------------------------------------------------------------------
    109  * The "atf_dynstr" type.
    110  * --------------------------------------------------------------------- */
    111 
    112 /*
    113  * Constants.
    114  */
    115 
    116 const size_t atf_dynstr_npos = SIZE_MAX;
    117 
    118 /*
    119  * Constructors and destructors.
    120  */
    121 
    122 atf_error_t
    123 atf_dynstr_init(atf_dynstr_t *ad)
    124 {
    125     atf_error_t err;
    126 
    127     ad->m_data = (char *)malloc(sizeof(char));
    128     if (ad->m_data == NULL) {
    129         err = atf_no_memory_error();
    130         goto out;
    131     }
    132 
    133     ad->m_data[0] = '\0';
    134     ad->m_datasize = 1;
    135     ad->m_length = 0;
    136     err = atf_no_error();
    137 
    138 out:
    139     return err;
    140 }
    141 
    142 atf_error_t
    143 atf_dynstr_init_ap(atf_dynstr_t *ad, const char *fmt, va_list ap)
    144 {
    145     atf_error_t err;
    146 
    147     ad->m_datasize = strlen(fmt) + 1;
    148     ad->m_length = 0;
    149 
    150     do {
    151         va_list ap2;
    152         int ret;
    153 
    154         ad->m_datasize *= 2;
    155         ad->m_data = (char *)malloc(ad->m_datasize);
    156         if (ad->m_data == NULL) {
    157             err = atf_no_memory_error();
    158             goto out;
    159         }
    160 
    161         va_copy(ap2, ap);
    162         ret = vsnprintf(ad->m_data, ad->m_datasize, fmt, ap2);
    163         va_end(ap2);
    164         if (ret < 0) {
    165             free(ad->m_data);
    166             err = atf_libc_error(errno, "Cannot format string");
    167             goto out;
    168         }
    169 
    170         INV(ret >= 0);
    171         if ((size_t)ret >= ad->m_datasize) {
    172             free(ad->m_data);
    173             ad->m_data = NULL;
    174         }
    175         ad->m_length = ret;
    176     } while (ad->m_length >= ad->m_datasize);
    177 
    178     err = atf_no_error();
    179 out:
    180     POST(atf_is_error(err) || ad->m_data != NULL);
    181     return err;
    182 }
    183 
    184 atf_error_t
    185 atf_dynstr_init_fmt(atf_dynstr_t *ad, const char *fmt, ...)
    186 {
    187     va_list ap;
    188     atf_error_t err;
    189 
    190     va_start(ap, fmt);
    191     err = atf_dynstr_init_ap(ad, fmt, ap);
    192     va_end(ap);
    193 
    194     return err;
    195 }
    196 
    197 atf_error_t
    198 atf_dynstr_init_raw(atf_dynstr_t *ad, const void *mem, size_t memlen)
    199 {
    200     atf_error_t err;
    201 
    202     if (memlen >= SIZE_MAX - 1) {
    203         err = atf_no_memory_error();
    204         goto out;
    205     }
    206 
    207     ad->m_data = (char *)malloc(memlen + 1);
    208     if (ad->m_data == NULL) {
    209         err = atf_no_memory_error();
    210         goto out;
    211     }
    212 
    213     ad->m_datasize = memlen + 1;
    214     memcpy(ad->m_data, mem, memlen);
    215     ad->m_data[memlen] = '\0';
    216     ad->m_length = strlen(ad->m_data);
    217     INV(ad->m_length <= memlen);
    218     err = atf_no_error();
    219 
    220 out:
    221     return err;
    222 }
    223 
    224 atf_error_t
    225 atf_dynstr_init_rep(atf_dynstr_t *ad, size_t len, char ch)
    226 {
    227     atf_error_t err;
    228 
    229     if (len == SIZE_MAX) {
    230         err = atf_no_memory_error();
    231         goto out;
    232     }
    233 
    234     ad->m_datasize = (len + 1) * sizeof(char);
    235     ad->m_data = (char *)malloc(ad->m_datasize);
    236     if (ad->m_data == NULL) {
    237         err = atf_no_memory_error();
    238         goto out;
    239     }
    240 
    241     memset(ad->m_data, ch, len);
    242     ad->m_data[len] = '\0';
    243     ad->m_length = len;
    244     err = atf_no_error();
    245 
    246 out:
    247     return err;
    248 }
    249 
    250 atf_error_t
    251 atf_dynstr_init_substr(atf_dynstr_t *ad, const atf_dynstr_t *src,
    252                        size_t beg, size_t end)
    253 {
    254     if (beg > src->m_length)
    255         beg = src->m_length;
    256 
    257     if (end == atf_dynstr_npos || end > src->m_length)
    258         end = src->m_length;
    259 
    260     return atf_dynstr_init_raw(ad, src->m_data + beg, end - beg);
    261 }
    262 
    263 atf_error_t
    264 atf_dynstr_copy(atf_dynstr_t *dest, const atf_dynstr_t *src)
    265 {
    266     atf_error_t err;
    267 
    268     dest->m_data = (char *)malloc(src->m_datasize);
    269     if (dest->m_data == NULL)
    270         err = atf_no_memory_error();
    271     else {
    272         memcpy(dest->m_data, src->m_data, src->m_datasize);
    273         dest->m_datasize = src->m_datasize;
    274         dest->m_length = src->m_length;
    275         err = atf_no_error();
    276     }
    277 
    278     return err;
    279 }
    280 
    281 void
    282 atf_dynstr_fini(atf_dynstr_t *ad)
    283 {
    284     INV(ad->m_data != NULL);
    285     free(ad->m_data);
    286 }
    287 
    288 char *
    289 atf_dynstr_fini_disown(atf_dynstr_t *ad)
    290 {
    291     INV(ad->m_data != NULL);
    292     return ad->m_data;
    293 }
    294 
    295 /*
    296  * Getters.
    297  */
    298 
    299 const char *
    300 atf_dynstr_cstring(const atf_dynstr_t *ad)
    301 {
    302     return ad->m_data;
    303 }
    304 
    305 size_t
    306 atf_dynstr_length(const atf_dynstr_t *ad)
    307 {
    308     return ad->m_length;
    309 }
    310 
    311 size_t
    312 atf_dynstr_rfind_ch(const atf_dynstr_t *ad, char ch)
    313 {
    314     size_t pos;
    315 
    316     for (pos = ad->m_length; pos > 0 && ad->m_data[pos - 1] != ch; pos--)
    317         ;
    318 
    319     return pos == 0 ? atf_dynstr_npos : pos - 1;
    320 }
    321 
    322 /*
    323  * Modifiers.
    324  */
    325 
    326 atf_error_t
    327 atf_dynstr_append_ap(atf_dynstr_t *ad, const char *fmt, va_list ap)
    328 {
    329     atf_error_t err;
    330     va_list ap2;
    331 
    332     va_copy(ap2, ap);
    333     err = prepend_or_append(ad, fmt, ap2, false);
    334     va_end(ap2);
    335 
    336     return err;
    337 }
    338 
    339 atf_error_t
    340 atf_dynstr_append_fmt(atf_dynstr_t *ad, const char *fmt, ...)
    341 {
    342     va_list ap;
    343     atf_error_t err;
    344 
    345     va_start(ap, fmt);
    346     err = prepend_or_append(ad, fmt, ap, false);
    347     va_end(ap);
    348 
    349     return err;
    350 }
    351 
    352 void
    353 atf_dynstr_clear(atf_dynstr_t *ad)
    354 {
    355     ad->m_data[0] = '\0';
    356     ad->m_length = 0;
    357 }
    358 
    359 atf_error_t
    360 atf_dynstr_prepend_ap(atf_dynstr_t *ad, const char *fmt, va_list ap)
    361 {
    362     atf_error_t err;
    363     va_list ap2;
    364 
    365     va_copy(ap2, ap);
    366     err = prepend_or_append(ad, fmt, ap2, true);
    367     va_end(ap2);
    368 
    369     return err;
    370 }
    371 
    372 atf_error_t
    373 atf_dynstr_prepend_fmt(atf_dynstr_t *ad, const char *fmt, ...)
    374 {
    375     va_list ap;
    376     atf_error_t err;
    377 
    378     va_start(ap, fmt);
    379     err = prepend_or_append(ad, fmt, ap, true);
    380     va_end(ap);
    381 
    382     return err;
    383 }
    384 
    385 /*
    386  * Operators.
    387  */
    388 
    389 bool
    390 atf_equal_dynstr_cstring(const atf_dynstr_t *ad, const char *str)
    391 {
    392     return strcmp(ad->m_data, str) == 0;
    393 }
    394 
    395 bool
    396 atf_equal_dynstr_dynstr(const atf_dynstr_t *s1, const atf_dynstr_t *s2)
    397 {
    398     return strcmp(s1->m_data, s2->m_data) == 0;
    399 }
    400