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