Path: blob/main/contrib/atf/atf-c/detail/dynstr.c
109451 views
/* Copyright (c) 2008 The NetBSD Foundation, Inc.1* All rights reserved.2*3* Redistribution and use in source and binary forms, with or without4* modification, are permitted provided that the following conditions5* are met:6* 1. Redistributions of source code must retain the above copyright7* notice, this list of conditions and the following disclaimer.8* 2. Redistributions in binary form must reproduce the above copyright9* notice, this list of conditions and the following disclaimer in the10* documentation and/or other materials provided with the distribution.11*12* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND13* CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,14* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF15* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.16* IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY17* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL18* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE19* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS20* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER21* IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR22* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN23* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */2425#include "atf-c/detail/dynstr.h"2627#include <errno.h>28#include <stdarg.h>29#include <stdint.h>30#include <stdio.h>31#include <stdlib.h>32#include <string.h>3334#include "atf-c/detail/sanity.h"35#include "atf-c/detail/text.h"36#include "atf-c/error.h"3738/* ---------------------------------------------------------------------39* Auxiliary functions.40* --------------------------------------------------------------------- */4142static43atf_error_t44resize(atf_dynstr_t *ad, size_t newsize)45{46char *newdata;47atf_error_t err;4849PRE(newsize > ad->m_datasize);5051newdata = (char *)malloc(newsize);52if (newdata == NULL) {53err = atf_no_memory_error();54} else {55strcpy(newdata, ad->m_data);56free(ad->m_data);57ad->m_data = newdata;58ad->m_datasize = newsize;59err = atf_no_error();60}6162return err;63}6465static66atf_error_t67prepend_or_append(atf_dynstr_t *ad, const char *fmt, va_list ap,68bool prepend)69{70char *aux;71atf_error_t err;72size_t newlen;73va_list ap2;7475va_copy(ap2, ap);76err = atf_text_format_ap(&aux, fmt, ap2);77va_end(ap2);78if (atf_is_error(err))79goto out;80newlen = ad->m_length + strlen(aux);8182if (newlen + sizeof(char) > ad->m_datasize) {83err = resize(ad, newlen + sizeof(char));84if (atf_is_error(err))85goto out_free;86}8788if (prepend) {89memmove(ad->m_data + strlen(aux), ad->m_data, ad->m_length + 1);90memcpy(ad->m_data, aux, strlen(aux));91} else92strcpy(ad->m_data + ad->m_length, aux);93ad->m_length = newlen;94err = atf_no_error();9596out_free:97free(aux);98out:99return err;100}101102/* ---------------------------------------------------------------------103* The "atf_dynstr" type.104* --------------------------------------------------------------------- */105106/*107* Constants.108*/109110const size_t atf_dynstr_npos = SIZE_MAX;111112/*113* Constructors and destructors.114*/115116atf_error_t117atf_dynstr_init(atf_dynstr_t *ad)118{119atf_error_t err;120121ad->m_data = (char *)malloc(sizeof(char));122if (ad->m_data == NULL) {123err = atf_no_memory_error();124goto out;125}126127ad->m_data[0] = '\0';128ad->m_datasize = 1;129ad->m_length = 0;130err = atf_no_error();131132out:133return err;134}135136atf_error_t137atf_dynstr_init_ap(atf_dynstr_t *ad, const char *fmt, va_list ap)138{139atf_error_t err;140141ad->m_datasize = strlen(fmt) + 1;142ad->m_length = 0;143144do {145va_list ap2;146int ret;147148ad->m_datasize *= 2;149ad->m_data = (char *)malloc(ad->m_datasize);150if (ad->m_data == NULL) {151err = atf_no_memory_error();152goto out;153}154155va_copy(ap2, ap);156ret = vsnprintf(ad->m_data, ad->m_datasize, fmt, ap2);157va_end(ap2);158if (ret < 0) {159free(ad->m_data);160err = atf_libc_error(errno, "Cannot format string");161goto out;162}163164INV(ret >= 0);165if ((size_t)ret >= ad->m_datasize) {166free(ad->m_data);167ad->m_data = NULL;168}169ad->m_length = ret;170} while (ad->m_length >= ad->m_datasize);171172err = atf_no_error();173out:174POST(atf_is_error(err) || ad->m_data != NULL);175return err;176}177178atf_error_t179atf_dynstr_init_fmt(atf_dynstr_t *ad, const char *fmt, ...)180{181va_list ap;182atf_error_t err;183184va_start(ap, fmt);185err = atf_dynstr_init_ap(ad, fmt, ap);186va_end(ap);187188return err;189}190191atf_error_t192atf_dynstr_init_raw(atf_dynstr_t *ad, const void *mem, size_t memlen)193{194atf_error_t err;195196if (memlen >= SIZE_MAX - 1) {197err = atf_no_memory_error();198goto out;199}200201ad->m_data = (char *)malloc(memlen + 1);202if (ad->m_data == NULL) {203err = atf_no_memory_error();204goto out;205}206207ad->m_datasize = memlen + 1;208memcpy(ad->m_data, mem, memlen);209ad->m_data[memlen] = '\0';210ad->m_length = strlen(ad->m_data);211INV(ad->m_length <= memlen);212err = atf_no_error();213214out:215return err;216}217218atf_error_t219atf_dynstr_init_rep(atf_dynstr_t *ad, size_t len, char ch)220{221atf_error_t err;222223if (len == SIZE_MAX) {224err = atf_no_memory_error();225goto out;226}227228ad->m_datasize = (len + 1) * sizeof(char);229ad->m_data = (char *)malloc(ad->m_datasize);230if (ad->m_data == NULL) {231err = atf_no_memory_error();232goto out;233}234235memset(ad->m_data, ch, len);236ad->m_data[len] = '\0';237ad->m_length = len;238err = atf_no_error();239240out:241return err;242}243244atf_error_t245atf_dynstr_init_substr(atf_dynstr_t *ad, const atf_dynstr_t *src,246size_t beg, size_t end)247{248if (beg > src->m_length)249beg = src->m_length;250251if (end == atf_dynstr_npos || end > src->m_length)252end = src->m_length;253254return atf_dynstr_init_raw(ad, src->m_data + beg, end - beg);255}256257atf_error_t258atf_dynstr_copy(atf_dynstr_t *dest, const atf_dynstr_t *src)259{260atf_error_t err;261262dest->m_data = (char *)malloc(src->m_datasize);263if (dest->m_data == NULL)264err = atf_no_memory_error();265else {266memcpy(dest->m_data, src->m_data, src->m_datasize);267dest->m_datasize = src->m_datasize;268dest->m_length = src->m_length;269err = atf_no_error();270}271272return err;273}274275void276atf_dynstr_fini(atf_dynstr_t *ad)277{278INV(ad->m_data != NULL);279free(ad->m_data);280}281282char *283atf_dynstr_fini_disown(atf_dynstr_t *ad)284{285INV(ad->m_data != NULL);286return ad->m_data;287}288289/*290* Getters.291*/292293const char *294atf_dynstr_cstring(const atf_dynstr_t *ad)295{296return ad->m_data;297}298299size_t300atf_dynstr_length(const atf_dynstr_t *ad)301{302return ad->m_length;303}304305size_t306atf_dynstr_rfind_ch(const atf_dynstr_t *ad, char ch)307{308size_t pos;309310for (pos = ad->m_length; pos > 0 && ad->m_data[pos - 1] != ch; pos--)311;312313return pos == 0 ? atf_dynstr_npos : pos - 1;314}315316/*317* Modifiers.318*/319320atf_error_t321atf_dynstr_append_ap(atf_dynstr_t *ad, const char *fmt, va_list ap)322{323atf_error_t err;324va_list ap2;325326va_copy(ap2, ap);327err = prepend_or_append(ad, fmt, ap2, false);328va_end(ap2);329330return err;331}332333atf_error_t334atf_dynstr_append_fmt(atf_dynstr_t *ad, const char *fmt, ...)335{336va_list ap;337atf_error_t err;338339va_start(ap, fmt);340err = prepend_or_append(ad, fmt, ap, false);341va_end(ap);342343return err;344}345346void347atf_dynstr_clear(atf_dynstr_t *ad)348{349ad->m_data[0] = '\0';350ad->m_length = 0;351}352353atf_error_t354atf_dynstr_prepend_ap(atf_dynstr_t *ad, const char *fmt, va_list ap)355{356atf_error_t err;357va_list ap2;358359va_copy(ap2, ap);360err = prepend_or_append(ad, fmt, ap2, true);361va_end(ap2);362363return err;364}365366atf_error_t367atf_dynstr_prepend_fmt(atf_dynstr_t *ad, const char *fmt, ...)368{369va_list ap;370atf_error_t err;371372va_start(ap, fmt);373err = prepend_or_append(ad, fmt, ap, true);374va_end(ap);375376return err;377}378379/*380* Operators.381*/382383bool384atf_equal_dynstr_cstring(const atf_dynstr_t *ad, const char *str)385{386return strcmp(ad->m_data, str) == 0;387}388389bool390atf_equal_dynstr_dynstr(const atf_dynstr_t *s1, const atf_dynstr_t *s2)391{392return strcmp(s1->m_data, s2->m_data) == 0;393}394395396