Freeciv-3.2
Loading...
Searching...
No Matches
string_vector.c
Go to the documentation of this file.
1/***********************************************************************
2 Freeciv - Copyright (C) 1996 - A Kjeldberg, L Gregersen, P Unold
3 This program is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
5 the Free Software Foundation; either version 2, or (at your option)
6 any later version.
7
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
12***********************************************************************/
13#ifdef HAVE_CONFIG_H
14#include <fc_config.h>
15#endif
16
17#include <stdlib.h> /* qsort() */
18#include <string.h>
19
20/* utility */
21#include "astring.h"
22#include "mem.h"
23#include "shared.h"
24#include "support.h"
25
26#include "string_vector.h"
27
28/* The string vector structure. */
29struct strvec {
30 char **vec;
31 size_t size;
32};
33
34/**********************************************************************/
37static void string_free(char *string)
38{
39 if (string) {
40 free(string);
41 }
42}
43
44/**********************************************************************/
47static char *string_duplicate(const char *string)
48{
49 if (string) {
50 return fc_strdup(string);
51 }
52 return NULL;
53}
54
55/**********************************************************************/
58struct strvec *strvec_new(void)
59{
60 struct strvec *psv = fc_malloc(sizeof(struct strvec));
61
62 psv->vec = NULL;
63 psv->size = 0;
64
65 return psv;
66}
67
68/**********************************************************************/
72{
74 free(psv);
75}
76
77/**********************************************************************/
80void strvec_reserve(struct strvec *psv, size_t reserve)
81{
82 if (reserve == psv->size) {
83 return;
84 } else if (reserve == 0) {
86 return;
87 } else if (!psv->vec) {
88 /* Initial reserve */
89 psv->vec = fc_calloc(reserve, sizeof(char *));
90 } else if (reserve > psv->size) {
91 /* Expand the vector. */
92 psv->vec = fc_realloc(psv->vec, reserve * sizeof(char *));
93 memset(psv->vec + psv->size, 0, (reserve - psv->size) * sizeof(char *));
94 } else {
95 /* Shrink the vector: free the extra strings. */
96 size_t i;
97
98 for (i = psv->size - 1; i >= reserve; i--) {
99 string_free(psv->vec[i]);
100 }
101 psv->vec = fc_realloc(psv->vec, reserve * sizeof(char *));
102 }
103 psv->size = reserve;
104}
105
106/**********************************************************************/
110void strvec_store(struct strvec *psv, const char *const *vec, size_t size)
111{
112 if (size == (size_t) -1) {
114 for (; *vec; vec++) {
116 }
117 } else {
118 size_t i;
119
121 for (i = 0; i < size; i++, vec++) {
122 strvec_set(psv, i, *vec);
123 }
124 }
125}
126
127/**********************************************************************/
136void strvec_from_str(struct strvec *psv, char separator, const char *str)
137{
138 const char *p;
139 char *new_str;
140
142 while ((p = strchr(str, separator))) {
143 new_str = fc_malloc(p - str + 1);
144 memcpy(new_str, str, p - str);
145 new_str[p - str] = '\0';
146 psv->size++;
147 psv->vec = fc_realloc(psv->vec, psv->size * sizeof(char *));
148 psv->vec[psv->size - 1] = new_str;
149 str = p + 1;
150 }
151 if ('\0' != *str) {
153 }
154}
155
156/**********************************************************************/
160{
161 size_t i;
162 char **p;
163
164 if (!psv->vec) {
165 return;
166 }
167
168 for (i = 0, p = psv->vec; i < psv->size; i++, p++) {
169 string_free(*p);
170 }
171 free(psv->vec);
172 psv->vec = NULL;
173 psv->size = 0;
174}
175
176/**********************************************************************/
180 int (*cmp_func) (const char *, const char *))
181{
182 size_t i, j;
183 const char *str1, *str2;
184
185 if (!psv->vec || 1 == psv->size) {
186 return;
187 }
188
189 for (i = 1; i < psv->size; i++) {
190 if ((str1 = psv->vec[i])) {
191 for (j = 0; j < i; j++) {
192 if ((str2 = psv->vec[j])
193 && 0 == cmp_func(str2, str1)) {
195 i--;
196 break;
197 }
198 }
199 }
200 }
201}
202
203/**********************************************************************/
208{
209 size_t i;
210 char *str;
211
212 if (!psv->vec) {
213 return;
214 }
215
216 for (i = 0; i < psv->size;) {
217 str = psv->vec[i];
218
219 if (!str) {
221 continue;
222 }
223
225 if (str[0] == '\0') {
227 continue;
228 }
229
230 i++;
231 }
232}
233
234/**********************************************************************/
237void strvec_copy(struct strvec *dest, const struct strvec *src)
238{
239 size_t i;
240 char **p;
241 char *const *l;
242
243 if (!src->vec) {
244 strvec_clear(dest);
245 return;
246 }
247
248 strvec_reserve(dest, src->size);
249 for (i = 0, p = dest->vec, l = src->vec; i < dest->size; i++, p++, l++) {
250 string_free(*p);
251 *p = string_duplicate(*l);
252 }
253}
254
255/**********************************************************************/
258void strvec_sort(struct strvec *psv, int (*sort_func) (const char *const *,
259 const char *const *))
260{
261 qsort(psv->vec, psv->size, sizeof(const char *),
262 (int (*) (const void *, const void *)) sort_func);
263}
264
265/**********************************************************************/
268void strvec_prepend(struct strvec *psv, const char *string)
269{
270 strvec_reserve(psv, psv->size + 1);
271 memmove(psv->vec + 1, psv->vec, (psv->size - 1) * sizeof(char *));
272 psv->vec[0] = string_duplicate(string);
273}
274
275/**********************************************************************/
278void strvec_append(struct strvec *psv, const char *string)
279{
280 strvec_reserve(psv, psv->size + 1);
281 psv->vec[psv->size - 1] = string_duplicate(string);
282}
283
284/**********************************************************************/
287void strvec_insert(struct strvec *psv, size_t svindex, const char *string)
288{
289 if (svindex <= 0) {
290 strvec_prepend(psv, string);
291 } else if (svindex >= psv->size) {
292 strvec_append(psv, string);
293 } else {
294 strvec_reserve(psv, psv->size + 1);
295 memmove(psv->vec + svindex + 1, psv->vec + svindex,
296 (psv->size - svindex - 1) * sizeof(char *));
297 psv->vec[svindex] = string_duplicate(string);
298 }
299}
300
301/**********************************************************************/
305bool strvec_set(struct strvec *psv, size_t svindex, const char *string)
306{
308 string_free(psv->vec[svindex]);
309 psv->vec[svindex] = string_duplicate(string);
310 return TRUE;
311 }
312 return FALSE;
313}
314
315/**********************************************************************/
319bool strvec_remove(struct strvec *psv, size_t svindex)
320{
322 return FALSE;
323 }
324
325 if (psv->size == 1) {
326 /* It is the last. */
328 return TRUE;
329 }
330
331 string_free(psv->vec[svindex]);
332 memmove(psv->vec + svindex, psv->vec + svindex + 1,
333 (psv->size - svindex - 1) * sizeof(char *));
334 psv->vec[psv->size - 1] = NULL; /* Do not attempt to free this data. */
335 strvec_reserve(psv, psv->size - 1);
336
337 return TRUE;
338}
339
340/**********************************************************************/
343size_t strvec_size(const struct strvec *psv)
344{
345 return psv->size;
346}
347
348/**********************************************************************/
351bool are_strvecs_equal(const struct strvec *stv1,
352 const struct strvec *stv2)
353{
354 int i;
355
356 if (strvec_size(stv1) != strvec_size(stv2)) {
357 return FALSE;
358 }
359
360 for (i = 0; i < strvec_size(stv1); i++) {
361 if (0 != strcmp(stv1->vec[i], stv2->vec[i])) {
362 return FALSE;
363 }
364 }
365
366 return TRUE;
367}
368
369/**********************************************************************/
372const char *const *strvec_data(const struct strvec *psv)
373{
374 return (const char **) psv->vec;
375}
376
377/**********************************************************************/
380bool strvec_index_valid(const struct strvec *psv, size_t svindex)
381{
382 return svindex < psv->size;
383}
384
385/**********************************************************************/
388const char *strvec_get(const struct strvec *psv, size_t svindex)
389{
390 return strvec_index_valid(psv, svindex) ? psv->vec[svindex] : NULL;
391}
392
393/**********************************************************************/
400void strvec_to_str(const struct strvec *psv, char separator,
401 char *buf, size_t buf_len)
402{
403 int len;
404
406 len = fc_snprintf(buf, buf_len, "%s", str) + 1;
407 if (1 >= len) {
408 /* Truncated. */
409 return;
410 }
411
412 buf += len;
413 buf_len -= len;
414 if (0 < buf_len) {
415 *(buf - 1) = separator;
416 }
418
419 buf[0] = '\0';
420}
421
422/**********************************************************************/
428const char *strvec_to_or_list(const struct strvec *psv,
429 struct astring *astr)
430{
432 return astr_build_or_list(astr, (const char **) psv->vec, psv->size);
433}
434
435/**********************************************************************/
441const char *strvec_to_and_list(const struct strvec *psv,
442 struct astring *astr)
443{
445 return astr_build_and_list(astr, (const char **) psv->vec, psv->size);
446}
const char * astr_build_or_list(struct astring *astr, const char *const *items, size_t number)
Definition astring.c:329
const char * astr_build_and_list(struct astring *astr, const char *const *items, size_t number)
Definition astring.c:367
#define str
Definition astring.c:76
char * incite_cost
Definition comments.c:75
static gint cmp_func(gconstpointer a_p, gconstpointer b_p)
Definition repodlgs.c:368
#define fc_assert_ret_val(condition, val)
Definition log.h:194
#define fc_calloc(n, esz)
Definition mem.h:38
#define fc_strdup(str)
Definition mem.h:43
#define fc_realloc(ptr, sz)
Definition mem.h:36
#define fc_malloc(sz)
Definition mem.h:34
int len
Definition packhand.c:127
void remove_leading_trailing_spaces(char *s)
Definition shared.c:444
size_t size
Definition specvec.h:72
void strvec_destroy(struct strvec *psv)
void strvec_sort(struct strvec *psv, int(*sort_func)(const char *const *, const char *const *))
void strvec_to_str(const struct strvec *psv, char separator, char *buf, size_t buf_len)
bool strvec_set(struct strvec *psv, size_t svindex, const char *string)
bool strvec_index_valid(const struct strvec *psv, size_t svindex)
const char *const * strvec_data(const struct strvec *psv)
void strvec_store(struct strvec *psv, const char *const *vec, size_t size)
static void string_free(char *string)
void strvec_append(struct strvec *psv, const char *string)
void strvec_from_str(struct strvec *psv, char separator, const char *str)
void strvec_reserve(struct strvec *psv, size_t reserve)
const char * strvec_to_or_list(const struct strvec *psv, struct astring *astr)
static char * string_duplicate(const char *string)
const char * strvec_get(const struct strvec *psv, size_t svindex)
void strvec_prepend(struct strvec *psv, const char *string)
void strvec_copy(struct strvec *dest, const struct strvec *src)
struct strvec * strvec_new(void)
void strvec_clear(struct strvec *psv)
size_t strvec_size(const struct strvec *psv)
const char * strvec_to_and_list(const struct strvec *psv, struct astring *astr)
void strvec_remove_duplicate(struct strvec *psv, int(*cmp_func)(const char *, const char *))
bool are_strvecs_equal(const struct strvec *stv1, const struct strvec *stv2)
bool strvec_remove(struct strvec *psv, size_t svindex)
void strvec_remove_empty(struct strvec *psv)
void strvec_insert(struct strvec *psv, size_t svindex, const char *string)
#define strvec_iterate(psv, str)
#define strvec_iterate_end
char ** vec
size_t size
int fc_snprintf(char *str, size_t n, const char *format,...)
Definition support.c:974
#define TRUE
Definition support.h:46
#define FALSE
Definition support.h:47