Path: blob/main/contrib/elftoolchain/libelftc/libelftc_vstr.c
39483 views
/*-1* Copyright (c) 2008 Hyogeol Lee <[email protected]>2* All rights reserved.3*4* Redistribution and use in source and binary forms, with or without5* modification, are permitted provided that the following conditions6* are met:7* 1. Redistributions of source code must retain the above copyright8* notice, this list of conditions and the following disclaimer9* in this position and unchanged.10* 2. Redistributions in binary form must reproduce the above copyright11* notice, this list of conditions and the following disclaimer in the12* documentation and/or other materials provided with the distribution.13*14* THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR15* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES16* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.17* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,18* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT19* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,20* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY21* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT22* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF23* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.24*/2526#include <sys/types.h>27#include <assert.h>28#include <libelftc.h>29#include <stdio.h>30#include <stdlib.h>31#include <string.h>3233#include "_libelftc.h"3435ELFTC_VCSID("$Id: libelftc_vstr.c 3531 2017-06-05 05:08:43Z kaiwang27 $");3637/**38* @file vector_str.c39* @brief Dynamic vector data for string implementation.40*41* Resemble to std::vector<std::string> in C++.42*/4344static size_t get_strlen_sum(const struct vector_str *v);45static bool vector_str_grow(struct vector_str *v);4647static size_t48get_strlen_sum(const struct vector_str *v)49{50size_t i, len = 0;5152if (v == NULL)53return (0);5455assert(v->size > 0);5657for (i = 0; i < v->size; ++i)58len += strlen(v->container[i]);5960return (len);61}6263/**64* @brief Deallocate resource in vector_str.65*/66void67vector_str_dest(struct vector_str *v)68{69size_t i;7071if (v == NULL)72return;7374for (i = 0; i < v->size; ++i)75free(v->container[i]);7677free(v->container);78}7980/**81* @brief Find string in vector_str.82* @param v Destination vector.83* @param o String to find.84* @param l Length of the string.85* @return -1 at failed, 0 at not found, 1 at found.86*/87int88vector_str_find(const struct vector_str *v, const char *o, size_t l)89{90size_t i;9192if (v == NULL || o == NULL)93return (-1);9495for (i = 0; i < v->size; ++i)96if (strncmp(v->container[i], o, l) == 0)97return (1);9899return (0);100}101102/**103* @brief Get new allocated flat string from vector.104*105* If l is not NULL, return length of the string.106* @param v Destination vector.107* @param l Length of the string.108* @return NULL at failed or NUL terminated new allocated string.109*/110char *111vector_str_get_flat(const struct vector_str *v, size_t *l)112{113ssize_t elem_pos, elem_size, rtn_size;114size_t i;115char *rtn;116117if (v == NULL || v->size == 0)118return (NULL);119120if ((rtn_size = get_strlen_sum(v)) == 0)121return (NULL);122123if ((rtn = malloc(sizeof(char) * (rtn_size + 1))) == NULL)124return (NULL);125126elem_pos = 0;127for (i = 0; i < v->size; ++i) {128elem_size = strlen(v->container[i]);129130memcpy(rtn + elem_pos, v->container[i], elem_size);131132elem_pos += elem_size;133}134135rtn[rtn_size] = '\0';136137if (l != NULL)138*l = rtn_size;139140return (rtn);141}142143static bool144vector_str_grow(struct vector_str *v)145{146size_t i, tmp_cap;147char **tmp_ctn;148149if (v == NULL)150return (false);151152assert(v->capacity > 0);153154tmp_cap = BUFFER_GROW(v->capacity);155156assert(tmp_cap > v->capacity);157158if ((tmp_ctn = malloc(sizeof(char *) * tmp_cap)) == NULL)159return (false);160161for (i = 0; i < v->size; ++i)162tmp_ctn[i] = v->container[i];163164free(v->container);165166v->container = tmp_ctn;167v->capacity = tmp_cap;168169return (true);170}171172/**173* @brief Initialize vector_str.174* @return false at failed, true at success.175*/176bool177vector_str_init(struct vector_str *v)178{179180if (v == NULL)181return (false);182183v->size = 0;184v->capacity = VECTOR_DEF_CAPACITY;185186assert(v->capacity > 0);187188if ((v->container = malloc(sizeof(char *) * v->capacity)) == NULL)189return (false);190191assert(v->container != NULL);192193return (true);194}195196/**197* @brief Remove last element in vector_str.198* @return false at failed, true at success.199*/200bool201vector_str_pop(struct vector_str *v)202{203204if (v == NULL)205return (false);206207if (v->size == 0)208return (true);209210--v->size;211212free(v->container[v->size]);213v->container[v->size] = NULL;214215return (true);216}217218/**219* @brief Push back string to vector.220* @return false at failed, true at success.221*/222bool223vector_str_push(struct vector_str *v, const char *str, size_t len)224{225226if (v == NULL || str == NULL)227return (false);228229if (v->size == v->capacity && vector_str_grow(v) == false)230return (false);231232if ((v->container[v->size] = malloc(sizeof(char) * (len + 1))) == NULL)233return (false);234235snprintf(v->container[v->size], len + 1, "%s", str);236237++v->size;238239return (true);240}241242/**243* @brief Push front org vector to det vector.244* @return false at failed, true at success.245*/246bool247vector_str_push_vector_head(struct vector_str *dst, struct vector_str *org)248{249size_t i, j, tmp_cap;250char **tmp_ctn;251252if (dst == NULL || org == NULL)253return (false);254255tmp_cap = BUFFER_GROW(dst->size + org->size);256257if ((tmp_ctn = malloc(sizeof(char *) * tmp_cap)) == NULL)258return (false);259260for (i = 0; i < org->size; ++i)261if ((tmp_ctn[i] = strdup(org->container[i])) == NULL) {262for (j = 0; j < i; ++j)263free(tmp_ctn[j]);264265free(tmp_ctn);266267return (false);268}269270for (i = 0; i < dst->size; ++i)271tmp_ctn[i + org->size] = dst->container[i];272273free(dst->container);274275dst->container = tmp_ctn;276dst->capacity = tmp_cap;277dst->size += org->size;278279return (true);280}281282/**283* @brief Push org vector to the tail of det vector.284* @return false at failed, true at success.285*/286bool287vector_str_push_vector(struct vector_str *dst, struct vector_str *org)288{289size_t i, j, tmp_cap;290char **tmp_ctn;291292if (dst == NULL || org == NULL)293return (false);294295tmp_cap = BUFFER_GROW(dst->size + org->size);296297if ((tmp_ctn = malloc(sizeof(char *) * tmp_cap)) == NULL)298return (false);299300for (i = 0; i < dst->size; ++i)301tmp_ctn[i] = dst->container[i];302303for (i = 0; i < org->size; ++i)304if ((tmp_ctn[i + dst->size] = strdup(org->container[i])) ==305NULL) {306for (j = 0; j < i + dst->size; ++j)307free(tmp_ctn[j]);308309free(tmp_ctn);310311return (false);312}313314free(dst->container);315316dst->container = tmp_ctn;317dst->capacity = tmp_cap;318dst->size += org->size;319320return (true);321}322323/**324* @brief Get new allocated flat string from vector between begin and end.325*326* If r_len is not NULL, string length will be returned.327* @return NULL at failed or NUL terminated new allocated string.328*/329char *330vector_str_substr(const struct vector_str *v, size_t begin, size_t end,331size_t *r_len)332{333size_t cur, i, len;334char *rtn;335336if (v == NULL || begin > end)337return (NULL);338339len = 0;340for (i = begin; i < end + 1; ++i)341len += strlen(v->container[i]);342343if ((rtn = malloc(sizeof(char) * (len + 1))) == NULL)344return (NULL);345346if (r_len != NULL)347*r_len = len;348349cur = 0;350for (i = begin; i < end + 1; ++i) {351len = strlen(v->container[i]);352memcpy(rtn + cur, v->container[i], len);353cur += len;354}355rtn[cur] = '\0';356357return (rtn);358}359360361