1260684Skaiw/*- 2260684Skaiw * Copyright (c) 2008 Hyogeol Lee <hyogeollee@gmail.com> 3260684Skaiw * All rights reserved. 4260684Skaiw * 5260684Skaiw * Redistribution and use in source and binary forms, with or without 6260684Skaiw * modification, are permitted provided that the following conditions 7260684Skaiw * are met: 8260684Skaiw * 1. Redistributions of source code must retain the above copyright 9260684Skaiw * notice, this list of conditions and the following disclaimer 10260684Skaiw * in this position and unchanged. 11260684Skaiw * 2. Redistributions in binary form must reproduce the above copyright 12260684Skaiw * notice, this list of conditions and the following disclaimer in the 13260684Skaiw * documentation and/or other materials provided with the distribution. 14260684Skaiw * 15260684Skaiw * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR 16260684Skaiw * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17260684Skaiw * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18260684Skaiw * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 19260684Skaiw * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 20260684Skaiw * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21260684Skaiw * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22260684Skaiw * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23260684Skaiw * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24260684Skaiw * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25260684Skaiw */ 26260684Skaiw 27260684Skaiw#include <sys/types.h> 28260684Skaiw#include <assert.h> 29260684Skaiw#include <libelftc.h> 30260684Skaiw#include <stdio.h> 31260684Skaiw#include <stdlib.h> 32260684Skaiw#include <string.h> 33260684Skaiw 34260684Skaiw#include "_libelftc.h" 35260684Skaiw 36260684SkaiwELFTC_VCSID("$Id: libelftc_vstr.c 2065 2011-10-26 15:24:47Z jkoshy $"); 37260684Skaiw 38260684Skaiw/** 39260684Skaiw * @file vector_str.c 40260684Skaiw * @brief Dynamic vector data for string implementation. 41260684Skaiw * 42260684Skaiw * Resemble to std::vector<std::string> in C++. 43260684Skaiw */ 44260684Skaiw 45260684Skaiwstatic size_t get_strlen_sum(const struct vector_str *v); 46260684Skaiwstatic bool vector_str_grow(struct vector_str *v); 47260684Skaiw 48260684Skaiwstatic size_t 49260684Skaiwget_strlen_sum(const struct vector_str *v) 50260684Skaiw{ 51260684Skaiw size_t i, len = 0; 52260684Skaiw 53260684Skaiw if (v == NULL) 54260684Skaiw return (0); 55260684Skaiw 56260684Skaiw assert(v->size > 0); 57260684Skaiw 58260684Skaiw for (i = 0; i < v->size; ++i) 59260684Skaiw len += strlen(v->container[i]); 60260684Skaiw 61260684Skaiw return (len); 62260684Skaiw} 63260684Skaiw 64260684Skaiw/** 65260684Skaiw * @brief Deallocate resource in vector_str. 66260684Skaiw */ 67260684Skaiwvoid 68260684Skaiwvector_str_dest(struct vector_str *v) 69260684Skaiw{ 70260684Skaiw size_t i; 71260684Skaiw 72260684Skaiw if (v == NULL) 73260684Skaiw return; 74260684Skaiw 75260684Skaiw for (i = 0; i < v->size; ++i) 76260684Skaiw free(v->container[i]); 77260684Skaiw 78260684Skaiw free(v->container); 79260684Skaiw} 80260684Skaiw 81260684Skaiw/** 82260684Skaiw * @brief Find string in vector_str. 83260684Skaiw * @param v Destination vector. 84260684Skaiw * @param o String to find. 85260684Skaiw * @param l Length of the string. 86260684Skaiw * @return -1 at failed, 0 at not found, 1 at found. 87260684Skaiw */ 88260684Skaiwint 89260684Skaiwvector_str_find(const struct vector_str *v, const char *o, size_t l) 90260684Skaiw{ 91260684Skaiw size_t i; 92260684Skaiw 93260684Skaiw if (v == NULL || o == NULL) 94260684Skaiw return (-1); 95260684Skaiw 96260684Skaiw for (i = 0; i < v->size; ++i) 97260684Skaiw if (strncmp(v->container[i], o, l) == 0) 98260684Skaiw return (1); 99260684Skaiw 100260684Skaiw return (0); 101260684Skaiw} 102260684Skaiw 103260684Skaiw/** 104260684Skaiw * @brief Get new allocated flat string from vector. 105260684Skaiw * 106260684Skaiw * If l is not NULL, return length of the string. 107260684Skaiw * @param v Destination vector. 108260684Skaiw * @param l Length of the string. 109260684Skaiw * @return NULL at failed or NUL terminated new allocated string. 110260684Skaiw */ 111260684Skaiwchar * 112260684Skaiwvector_str_get_flat(const struct vector_str *v, size_t *l) 113260684Skaiw{ 114260684Skaiw ssize_t elem_pos, elem_size, rtn_size; 115260684Skaiw size_t i; 116260684Skaiw char *rtn; 117260684Skaiw 118260684Skaiw if (v == NULL || v->size == 0) 119260684Skaiw return (NULL); 120260684Skaiw 121260684Skaiw if ((rtn_size = get_strlen_sum(v)) == 0) 122260684Skaiw return (NULL); 123260684Skaiw 124260684Skaiw if ((rtn = malloc(sizeof(char) * (rtn_size + 1))) == NULL) 125260684Skaiw return (NULL); 126260684Skaiw 127260684Skaiw elem_pos = 0; 128260684Skaiw for (i = 0; i < v->size; ++i) { 129260684Skaiw elem_size = strlen(v->container[i]); 130260684Skaiw 131260684Skaiw memcpy(rtn + elem_pos, v->container[i], elem_size); 132260684Skaiw 133260684Skaiw elem_pos += elem_size; 134260684Skaiw } 135260684Skaiw 136260684Skaiw rtn[rtn_size] = '\0'; 137260684Skaiw 138260684Skaiw if (l != NULL) 139260684Skaiw *l = rtn_size; 140260684Skaiw 141260684Skaiw return (rtn); 142260684Skaiw} 143260684Skaiw 144260684Skaiwstatic bool 145260684Skaiwvector_str_grow(struct vector_str *v) 146260684Skaiw{ 147260684Skaiw size_t i, tmp_cap; 148260684Skaiw char **tmp_ctn; 149260684Skaiw 150260684Skaiw if (v == NULL) 151260684Skaiw return (false); 152260684Skaiw 153260684Skaiw assert(v->capacity > 0); 154260684Skaiw 155260684Skaiw tmp_cap = v->capacity * BUFFER_GROWFACTOR; 156260684Skaiw 157260684Skaiw assert(tmp_cap > v->capacity); 158260684Skaiw 159260684Skaiw if ((tmp_ctn = malloc(sizeof(char *) * tmp_cap)) == NULL) 160260684Skaiw return (false); 161260684Skaiw 162260684Skaiw for (i = 0; i < v->size; ++i) 163260684Skaiw tmp_ctn[i] = v->container[i]; 164260684Skaiw 165260684Skaiw free(v->container); 166260684Skaiw 167260684Skaiw v->container = tmp_ctn; 168260684Skaiw v->capacity = tmp_cap; 169260684Skaiw 170260684Skaiw return (true); 171260684Skaiw} 172260684Skaiw 173260684Skaiw/** 174260684Skaiw * @brief Initialize vector_str. 175260684Skaiw * @return false at failed, true at success. 176260684Skaiw */ 177260684Skaiwbool 178260684Skaiwvector_str_init(struct vector_str *v) 179260684Skaiw{ 180260684Skaiw 181260684Skaiw if (v == NULL) 182260684Skaiw return (false); 183260684Skaiw 184260684Skaiw v->size = 0; 185260684Skaiw v->capacity = VECTOR_DEF_CAPACITY; 186260684Skaiw 187260684Skaiw assert(v->capacity > 0); 188260684Skaiw 189260684Skaiw if ((v->container = malloc(sizeof(char *) * v->capacity)) == NULL) 190260684Skaiw return (false); 191260684Skaiw 192260684Skaiw assert(v->container != NULL); 193260684Skaiw 194260684Skaiw return (true); 195260684Skaiw} 196260684Skaiw 197260684Skaiw/** 198260684Skaiw * @brief Remove last element in vector_str. 199260684Skaiw * @return false at failed, true at success. 200260684Skaiw */ 201260684Skaiwbool 202260684Skaiwvector_str_pop(struct vector_str *v) 203260684Skaiw{ 204260684Skaiw 205260684Skaiw if (v == NULL) 206260684Skaiw return (false); 207260684Skaiw 208260684Skaiw if (v->size == 0) 209260684Skaiw return (true); 210260684Skaiw 211260684Skaiw --v->size; 212260684Skaiw 213260684Skaiw free(v->container[v->size]); 214260684Skaiw v->container[v->size] = NULL; 215260684Skaiw 216260684Skaiw return (true); 217260684Skaiw} 218260684Skaiw 219260684Skaiw/** 220260684Skaiw * @brief Push back string to vector. 221260684Skaiw * @return false at failed, true at success. 222260684Skaiw */ 223260684Skaiwbool 224260684Skaiwvector_str_push(struct vector_str *v, const char *str, size_t len) 225260684Skaiw{ 226260684Skaiw 227260684Skaiw if (v == NULL || str == NULL) 228260684Skaiw return (false); 229260684Skaiw 230260684Skaiw if (v->size == v->capacity && vector_str_grow(v) == false) 231260684Skaiw return (false); 232260684Skaiw 233260684Skaiw if ((v->container[v->size] = malloc(sizeof(char) * (len + 1))) == NULL) 234260684Skaiw return (false); 235260684Skaiw 236260684Skaiw snprintf(v->container[v->size], len + 1, "%s", str); 237260684Skaiw 238260684Skaiw ++v->size; 239260684Skaiw 240260684Skaiw return (true); 241260684Skaiw} 242260684Skaiw 243260684Skaiw/** 244260684Skaiw * @brief Push front org vector to det vector. 245260684Skaiw * @return false at failed, true at success. 246260684Skaiw */ 247260684Skaiwbool 248260684Skaiwvector_str_push_vector_head(struct vector_str *dst, struct vector_str *org) 249260684Skaiw{ 250260684Skaiw size_t i, j, tmp_cap; 251260684Skaiw char **tmp_ctn; 252260684Skaiw 253260684Skaiw if (dst == NULL || org == NULL) 254260684Skaiw return (false); 255260684Skaiw 256260684Skaiw tmp_cap = (dst->size + org->size) * BUFFER_GROWFACTOR; 257260684Skaiw 258260684Skaiw if ((tmp_ctn = malloc(sizeof(char *) * tmp_cap)) == NULL) 259260684Skaiw return (false); 260260684Skaiw 261260684Skaiw for (i = 0; i < org->size; ++i) 262260684Skaiw if ((tmp_ctn[i] = strdup(org->container[i])) == NULL) { 263260684Skaiw for (j = 0; j < i; ++j) 264260684Skaiw free(tmp_ctn[j]); 265260684Skaiw 266260684Skaiw free(tmp_ctn); 267260684Skaiw 268260684Skaiw return (false); 269260684Skaiw } 270260684Skaiw 271260684Skaiw for (i = 0; i < dst->size; ++i) 272260684Skaiw tmp_ctn[i + org->size] = dst->container[i]; 273260684Skaiw 274260684Skaiw free(dst->container); 275260684Skaiw 276260684Skaiw dst->container = tmp_ctn; 277260684Skaiw dst->capacity = tmp_cap; 278260684Skaiw dst->size += org->size; 279260684Skaiw 280260684Skaiw return (true); 281260684Skaiw} 282260684Skaiw 283260684Skaiw/** 284260684Skaiw * @brief Get new allocated flat string from vector between begin and end. 285260684Skaiw * 286260684Skaiw * If r_len is not NULL, string length will be returned. 287260684Skaiw * @return NULL at failed or NUL terminated new allocated string. 288260684Skaiw */ 289260684Skaiwchar * 290260684Skaiwvector_str_substr(const struct vector_str *v, size_t begin, size_t end, 291260684Skaiw size_t *r_len) 292260684Skaiw{ 293260684Skaiw size_t cur, i, len; 294260684Skaiw char *rtn; 295260684Skaiw 296260684Skaiw if (v == NULL || begin > end) 297260684Skaiw return (NULL); 298260684Skaiw 299260684Skaiw len = 0; 300260684Skaiw for (i = begin; i < end + 1; ++i) 301260684Skaiw len += strlen(v->container[i]); 302260684Skaiw 303260684Skaiw if ((rtn = malloc(sizeof(char) * (len + 1))) == NULL) 304260684Skaiw return (NULL); 305260684Skaiw 306260684Skaiw if (r_len != NULL) 307260684Skaiw *r_len = len; 308260684Skaiw 309260684Skaiw cur = 0; 310260684Skaiw for (i = begin; i < end + 1; ++i) { 311260684Skaiw len = strlen(v->container[i]); 312260684Skaiw memcpy(rtn + cur, v->container[i], len); 313260684Skaiw cur += len; 314260684Skaiw } 315260684Skaiw rtn[cur] = '\0'; 316260684Skaiw 317260684Skaiw return (rtn); 318260684Skaiw} 319