xref: /freebsd/contrib/elftoolchain/libelftc/libelftc_vstr.c (revision a85fe12e361c14018a24f0f7714663b490206c7f)
1*a85fe12eSEd Maste /*-
2*a85fe12eSEd Maste  * Copyright (c) 2008 Hyogeol Lee <hyogeollee@gmail.com>
3*a85fe12eSEd Maste  * All rights reserved.
4*a85fe12eSEd Maste  *
5*a85fe12eSEd Maste  * Redistribution and use in source and binary forms, with or without
6*a85fe12eSEd Maste  * modification, are permitted provided that the following conditions
7*a85fe12eSEd Maste  * are met:
8*a85fe12eSEd Maste  * 1. Redistributions of source code must retain the above copyright
9*a85fe12eSEd Maste  *    notice, this list of conditions and the following disclaimer
10*a85fe12eSEd Maste  *    in this position and unchanged.
11*a85fe12eSEd Maste  * 2. Redistributions in binary form must reproduce the above copyright
12*a85fe12eSEd Maste  *    notice, this list of conditions and the following disclaimer in the
13*a85fe12eSEd Maste  *    documentation and/or other materials provided with the distribution.
14*a85fe12eSEd Maste  *
15*a85fe12eSEd Maste  * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
16*a85fe12eSEd Maste  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17*a85fe12eSEd Maste  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18*a85fe12eSEd Maste  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19*a85fe12eSEd Maste  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20*a85fe12eSEd Maste  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21*a85fe12eSEd Maste  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22*a85fe12eSEd Maste  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23*a85fe12eSEd Maste  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24*a85fe12eSEd Maste  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25*a85fe12eSEd Maste  */
26*a85fe12eSEd Maste 
27*a85fe12eSEd Maste #include <sys/types.h>
28*a85fe12eSEd Maste #include <assert.h>
29*a85fe12eSEd Maste #include <libelftc.h>
30*a85fe12eSEd Maste #include <stdio.h>
31*a85fe12eSEd Maste #include <stdlib.h>
32*a85fe12eSEd Maste #include <string.h>
33*a85fe12eSEd Maste 
34*a85fe12eSEd Maste #include "_libelftc.h"
35*a85fe12eSEd Maste 
36*a85fe12eSEd Maste ELFTC_VCSID("$Id: libelftc_vstr.c 2065 2011-10-26 15:24:47Z jkoshy $");
37*a85fe12eSEd Maste 
38*a85fe12eSEd Maste /**
39*a85fe12eSEd Maste  * @file vector_str.c
40*a85fe12eSEd Maste  * @brief Dynamic vector data for string implementation.
41*a85fe12eSEd Maste  *
42*a85fe12eSEd Maste  * Resemble to std::vector<std::string> in C++.
43*a85fe12eSEd Maste  */
44*a85fe12eSEd Maste 
45*a85fe12eSEd Maste static size_t	get_strlen_sum(const struct vector_str *v);
46*a85fe12eSEd Maste static bool	vector_str_grow(struct vector_str *v);
47*a85fe12eSEd Maste 
48*a85fe12eSEd Maste static size_t
49*a85fe12eSEd Maste get_strlen_sum(const struct vector_str *v)
50*a85fe12eSEd Maste {
51*a85fe12eSEd Maste 	size_t i, len = 0;
52*a85fe12eSEd Maste 
53*a85fe12eSEd Maste 	if (v == NULL)
54*a85fe12eSEd Maste 		return (0);
55*a85fe12eSEd Maste 
56*a85fe12eSEd Maste 	assert(v->size > 0);
57*a85fe12eSEd Maste 
58*a85fe12eSEd Maste 	for (i = 0; i < v->size; ++i)
59*a85fe12eSEd Maste 		len += strlen(v->container[i]);
60*a85fe12eSEd Maste 
61*a85fe12eSEd Maste 	return (len);
62*a85fe12eSEd Maste }
63*a85fe12eSEd Maste 
64*a85fe12eSEd Maste /**
65*a85fe12eSEd Maste  * @brief Deallocate resource in vector_str.
66*a85fe12eSEd Maste  */
67*a85fe12eSEd Maste void
68*a85fe12eSEd Maste vector_str_dest(struct vector_str *v)
69*a85fe12eSEd Maste {
70*a85fe12eSEd Maste 	size_t i;
71*a85fe12eSEd Maste 
72*a85fe12eSEd Maste 	if (v == NULL)
73*a85fe12eSEd Maste 		return;
74*a85fe12eSEd Maste 
75*a85fe12eSEd Maste 	for (i = 0; i < v->size; ++i)
76*a85fe12eSEd Maste 		free(v->container[i]);
77*a85fe12eSEd Maste 
78*a85fe12eSEd Maste 	free(v->container);
79*a85fe12eSEd Maste }
80*a85fe12eSEd Maste 
81*a85fe12eSEd Maste /**
82*a85fe12eSEd Maste  * @brief Find string in vector_str.
83*a85fe12eSEd Maste  * @param v Destination vector.
84*a85fe12eSEd Maste  * @param o String to find.
85*a85fe12eSEd Maste  * @param l Length of the string.
86*a85fe12eSEd Maste  * @return -1 at failed, 0 at not found, 1 at found.
87*a85fe12eSEd Maste  */
88*a85fe12eSEd Maste int
89*a85fe12eSEd Maste vector_str_find(const struct vector_str *v, const char *o, size_t l)
90*a85fe12eSEd Maste {
91*a85fe12eSEd Maste 	size_t i;
92*a85fe12eSEd Maste 
93*a85fe12eSEd Maste 	if (v == NULL || o == NULL)
94*a85fe12eSEd Maste 		return (-1);
95*a85fe12eSEd Maste 
96*a85fe12eSEd Maste 	for (i = 0; i < v->size; ++i)
97*a85fe12eSEd Maste 		if (strncmp(v->container[i], o, l) == 0)
98*a85fe12eSEd Maste 			return (1);
99*a85fe12eSEd Maste 
100*a85fe12eSEd Maste 	return (0);
101*a85fe12eSEd Maste }
102*a85fe12eSEd Maste 
103*a85fe12eSEd Maste /**
104*a85fe12eSEd Maste  * @brief Get new allocated flat string from vector.
105*a85fe12eSEd Maste  *
106*a85fe12eSEd Maste  * If l is not NULL, return length of the string.
107*a85fe12eSEd Maste  * @param v Destination vector.
108*a85fe12eSEd Maste  * @param l Length of the string.
109*a85fe12eSEd Maste  * @return NULL at failed or NUL terminated new allocated string.
110*a85fe12eSEd Maste  */
111*a85fe12eSEd Maste char *
112*a85fe12eSEd Maste vector_str_get_flat(const struct vector_str *v, size_t *l)
113*a85fe12eSEd Maste {
114*a85fe12eSEd Maste 	ssize_t elem_pos, elem_size, rtn_size;
115*a85fe12eSEd Maste 	size_t i;
116*a85fe12eSEd Maste 	char *rtn;
117*a85fe12eSEd Maste 
118*a85fe12eSEd Maste 	if (v == NULL || v->size == 0)
119*a85fe12eSEd Maste 		return (NULL);
120*a85fe12eSEd Maste 
121*a85fe12eSEd Maste 	if ((rtn_size = get_strlen_sum(v)) == 0)
122*a85fe12eSEd Maste 		return (NULL);
123*a85fe12eSEd Maste 
124*a85fe12eSEd Maste 	if ((rtn = malloc(sizeof(char) * (rtn_size + 1))) == NULL)
125*a85fe12eSEd Maste 		return (NULL);
126*a85fe12eSEd Maste 
127*a85fe12eSEd Maste 	elem_pos = 0;
128*a85fe12eSEd Maste 	for (i = 0; i < v->size; ++i) {
129*a85fe12eSEd Maste 		elem_size = strlen(v->container[i]);
130*a85fe12eSEd Maste 
131*a85fe12eSEd Maste 		memcpy(rtn + elem_pos, v->container[i], elem_size);
132*a85fe12eSEd Maste 
133*a85fe12eSEd Maste 		elem_pos += elem_size;
134*a85fe12eSEd Maste 	}
135*a85fe12eSEd Maste 
136*a85fe12eSEd Maste 	rtn[rtn_size] = '\0';
137*a85fe12eSEd Maste 
138*a85fe12eSEd Maste 	if (l != NULL)
139*a85fe12eSEd Maste 		*l = rtn_size;
140*a85fe12eSEd Maste 
141*a85fe12eSEd Maste 	return (rtn);
142*a85fe12eSEd Maste }
143*a85fe12eSEd Maste 
144*a85fe12eSEd Maste static bool
145*a85fe12eSEd Maste vector_str_grow(struct vector_str *v)
146*a85fe12eSEd Maste {
147*a85fe12eSEd Maste 	size_t i, tmp_cap;
148*a85fe12eSEd Maste 	char **tmp_ctn;
149*a85fe12eSEd Maste 
150*a85fe12eSEd Maste 	if (v == NULL)
151*a85fe12eSEd Maste 		return (false);
152*a85fe12eSEd Maste 
153*a85fe12eSEd Maste 	assert(v->capacity > 0);
154*a85fe12eSEd Maste 
155*a85fe12eSEd Maste 	tmp_cap = v->capacity * BUFFER_GROWFACTOR;
156*a85fe12eSEd Maste 
157*a85fe12eSEd Maste 	assert(tmp_cap > v->capacity);
158*a85fe12eSEd Maste 
159*a85fe12eSEd Maste 	if ((tmp_ctn = malloc(sizeof(char *) * tmp_cap)) == NULL)
160*a85fe12eSEd Maste 		return (false);
161*a85fe12eSEd Maste 
162*a85fe12eSEd Maste 	for (i = 0; i < v->size; ++i)
163*a85fe12eSEd Maste 		tmp_ctn[i] = v->container[i];
164*a85fe12eSEd Maste 
165*a85fe12eSEd Maste 	free(v->container);
166*a85fe12eSEd Maste 
167*a85fe12eSEd Maste 	v->container = tmp_ctn;
168*a85fe12eSEd Maste 	v->capacity = tmp_cap;
169*a85fe12eSEd Maste 
170*a85fe12eSEd Maste 	return (true);
171*a85fe12eSEd Maste }
172*a85fe12eSEd Maste 
173*a85fe12eSEd Maste /**
174*a85fe12eSEd Maste  * @brief Initialize vector_str.
175*a85fe12eSEd Maste  * @return false at failed, true at success.
176*a85fe12eSEd Maste  */
177*a85fe12eSEd Maste bool
178*a85fe12eSEd Maste vector_str_init(struct vector_str *v)
179*a85fe12eSEd Maste {
180*a85fe12eSEd Maste 
181*a85fe12eSEd Maste 	if (v == NULL)
182*a85fe12eSEd Maste 		return (false);
183*a85fe12eSEd Maste 
184*a85fe12eSEd Maste 	v->size = 0;
185*a85fe12eSEd Maste 	v->capacity = VECTOR_DEF_CAPACITY;
186*a85fe12eSEd Maste 
187*a85fe12eSEd Maste 	assert(v->capacity > 0);
188*a85fe12eSEd Maste 
189*a85fe12eSEd Maste 	if ((v->container = malloc(sizeof(char *) * v->capacity)) == NULL)
190*a85fe12eSEd Maste 		return (false);
191*a85fe12eSEd Maste 
192*a85fe12eSEd Maste 	assert(v->container != NULL);
193*a85fe12eSEd Maste 
194*a85fe12eSEd Maste 	return (true);
195*a85fe12eSEd Maste }
196*a85fe12eSEd Maste 
197*a85fe12eSEd Maste /**
198*a85fe12eSEd Maste  * @brief Remove last element in vector_str.
199*a85fe12eSEd Maste  * @return false at failed, true at success.
200*a85fe12eSEd Maste  */
201*a85fe12eSEd Maste bool
202*a85fe12eSEd Maste vector_str_pop(struct vector_str *v)
203*a85fe12eSEd Maste {
204*a85fe12eSEd Maste 
205*a85fe12eSEd Maste 	if (v == NULL)
206*a85fe12eSEd Maste 		return (false);
207*a85fe12eSEd Maste 
208*a85fe12eSEd Maste 	if (v->size == 0)
209*a85fe12eSEd Maste 		return (true);
210*a85fe12eSEd Maste 
211*a85fe12eSEd Maste 	--v->size;
212*a85fe12eSEd Maste 
213*a85fe12eSEd Maste 	free(v->container[v->size]);
214*a85fe12eSEd Maste 	v->container[v->size] = NULL;
215*a85fe12eSEd Maste 
216*a85fe12eSEd Maste 	return (true);
217*a85fe12eSEd Maste }
218*a85fe12eSEd Maste 
219*a85fe12eSEd Maste /**
220*a85fe12eSEd Maste  * @brief Push back string to vector.
221*a85fe12eSEd Maste  * @return false at failed, true at success.
222*a85fe12eSEd Maste  */
223*a85fe12eSEd Maste bool
224*a85fe12eSEd Maste vector_str_push(struct vector_str *v, const char *str, size_t len)
225*a85fe12eSEd Maste {
226*a85fe12eSEd Maste 
227*a85fe12eSEd Maste 	if (v == NULL || str == NULL)
228*a85fe12eSEd Maste 		return (false);
229*a85fe12eSEd Maste 
230*a85fe12eSEd Maste 	if (v->size == v->capacity && vector_str_grow(v) == false)
231*a85fe12eSEd Maste 		return (false);
232*a85fe12eSEd Maste 
233*a85fe12eSEd Maste 	if ((v->container[v->size] = malloc(sizeof(char) * (len + 1))) == NULL)
234*a85fe12eSEd Maste 		return (false);
235*a85fe12eSEd Maste 
236*a85fe12eSEd Maste 	snprintf(v->container[v->size], len + 1, "%s", str);
237*a85fe12eSEd Maste 
238*a85fe12eSEd Maste 	++v->size;
239*a85fe12eSEd Maste 
240*a85fe12eSEd Maste 	return (true);
241*a85fe12eSEd Maste }
242*a85fe12eSEd Maste 
243*a85fe12eSEd Maste /**
244*a85fe12eSEd Maste  * @brief Push front org vector to det vector.
245*a85fe12eSEd Maste  * @return false at failed, true at success.
246*a85fe12eSEd Maste  */
247*a85fe12eSEd Maste bool
248*a85fe12eSEd Maste vector_str_push_vector_head(struct vector_str *dst, struct vector_str *org)
249*a85fe12eSEd Maste {
250*a85fe12eSEd Maste 	size_t i, j, tmp_cap;
251*a85fe12eSEd Maste 	char **tmp_ctn;
252*a85fe12eSEd Maste 
253*a85fe12eSEd Maste 	if (dst == NULL || org == NULL)
254*a85fe12eSEd Maste 		return (false);
255*a85fe12eSEd Maste 
256*a85fe12eSEd Maste 	tmp_cap = (dst->size + org->size) * BUFFER_GROWFACTOR;
257*a85fe12eSEd Maste 
258*a85fe12eSEd Maste 	if ((tmp_ctn = malloc(sizeof(char *) * tmp_cap)) == NULL)
259*a85fe12eSEd Maste 		return (false);
260*a85fe12eSEd Maste 
261*a85fe12eSEd Maste 	for (i = 0; i < org->size; ++i)
262*a85fe12eSEd Maste 		if ((tmp_ctn[i] = strdup(org->container[i])) == NULL) {
263*a85fe12eSEd Maste 			for (j = 0; j < i; ++j)
264*a85fe12eSEd Maste 				free(tmp_ctn[j]);
265*a85fe12eSEd Maste 
266*a85fe12eSEd Maste 			free(tmp_ctn);
267*a85fe12eSEd Maste 
268*a85fe12eSEd Maste 			return (false);
269*a85fe12eSEd Maste 		}
270*a85fe12eSEd Maste 
271*a85fe12eSEd Maste 	for (i = 0; i < dst->size; ++i)
272*a85fe12eSEd Maste 		tmp_ctn[i + org->size] = dst->container[i];
273*a85fe12eSEd Maste 
274*a85fe12eSEd Maste 	free(dst->container);
275*a85fe12eSEd Maste 
276*a85fe12eSEd Maste 	dst->container = tmp_ctn;
277*a85fe12eSEd Maste 	dst->capacity = tmp_cap;
278*a85fe12eSEd Maste 	dst->size += org->size;
279*a85fe12eSEd Maste 
280*a85fe12eSEd Maste 	return (true);
281*a85fe12eSEd Maste }
282*a85fe12eSEd Maste 
283*a85fe12eSEd Maste /**
284*a85fe12eSEd Maste  * @brief Get new allocated flat string from vector between begin and end.
285*a85fe12eSEd Maste  *
286*a85fe12eSEd Maste  * If r_len is not NULL, string length will be returned.
287*a85fe12eSEd Maste  * @return NULL at failed or NUL terminated new allocated string.
288*a85fe12eSEd Maste  */
289*a85fe12eSEd Maste char *
290*a85fe12eSEd Maste vector_str_substr(const struct vector_str *v, size_t begin, size_t end,
291*a85fe12eSEd Maste     size_t *r_len)
292*a85fe12eSEd Maste {
293*a85fe12eSEd Maste 	size_t cur, i, len;
294*a85fe12eSEd Maste 	char *rtn;
295*a85fe12eSEd Maste 
296*a85fe12eSEd Maste 	if (v == NULL || begin > end)
297*a85fe12eSEd Maste 		return (NULL);
298*a85fe12eSEd Maste 
299*a85fe12eSEd Maste 	len = 0;
300*a85fe12eSEd Maste 	for (i = begin; i < end + 1; ++i)
301*a85fe12eSEd Maste 		len += strlen(v->container[i]);
302*a85fe12eSEd Maste 
303*a85fe12eSEd Maste 	if ((rtn = malloc(sizeof(char) * (len + 1))) == NULL)
304*a85fe12eSEd Maste 		return (NULL);
305*a85fe12eSEd Maste 
306*a85fe12eSEd Maste 	if (r_len != NULL)
307*a85fe12eSEd Maste 		*r_len = len;
308*a85fe12eSEd Maste 
309*a85fe12eSEd Maste 	cur = 0;
310*a85fe12eSEd Maste 	for (i = begin; i < end + 1; ++i) {
311*a85fe12eSEd Maste 		len = strlen(v->container[i]);
312*a85fe12eSEd Maste 		memcpy(rtn + cur, v->container[i], len);
313*a85fe12eSEd Maste 		cur += len;
314*a85fe12eSEd Maste 	}
315*a85fe12eSEd Maste 	rtn[cur] = '\0';
316*a85fe12eSEd Maste 
317*a85fe12eSEd Maste 	return (rtn);
318*a85fe12eSEd Maste }
319