Freeciv-3.3
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
53 return nullptr;
54}
55
56/**********************************************************************/
59struct strvec *strvec_new(void)
60{
61 struct strvec *psv = fc_malloc(sizeof(struct strvec));
62
63 psv->vec = nullptr;
64 psv->size = 0;
65
66 return psv;
67}
68
69/**********************************************************************/
73{
75 free(psv);
76}
77
78/**********************************************************************/
81void strvec_reserve(struct strvec *psv, size_t reserve)
82{
83 if (reserve == psv->size) {
84 return;
85 } else if (reserve == 0) {
87 return;
88 } else if (!psv->vec) {
89 /* Initial reserve */
90 psv->vec = fc_calloc(reserve, sizeof(char *));
91 } else if (reserve > psv->size) {
92 /* Expand the vector. */
93 psv->vec = fc_realloc(psv->vec, reserve * sizeof(char *));
94 memset(psv->vec + psv->size, 0, (reserve - psv->size) * sizeof(char *));
95 } else {
96 /* Shrink the vector: free the extra strings. */
97 size_t i;
98
99 for (i = psv->size - 1; i >= reserve; i--) {
100 string_free(psv->vec[i]);
101 }
102 psv->vec = fc_realloc(psv->vec, reserve * sizeof(char *));
103 }
104 psv->size = reserve;
105}
106
107/**********************************************************************/
111void strvec_store(struct strvec *psv, const char *const *vec, size_t size)
112{
113 if (size == (size_t) -1) {
115 for (; *vec; vec++) {
117 }
118 } else {
119 size_t i;
120
122 for (i = 0; i < size; i++, vec++) {
123 strvec_set(psv, i, *vec);
124 }
125 }
126}
127
128/**********************************************************************/
137void strvec_from_str(struct strvec *psv, char separator, const char *str)
138{
139 const char *p;
140 char *new_str;
141
143 while ((p = strchr(str, separator))) {
144 new_str = fc_malloc(p - str + 1);
145 memcpy(new_str, str, p - str);
146 new_str[p - str] = '\0';
147 psv->size++;
148 psv->vec = fc_realloc(psv->vec, psv->size * sizeof(char *));
149 psv->vec[psv->size - 1] = new_str;
150 str = p + 1;
151 }
152 if ('\0' != *str) {
154 }
155}
156
157/**********************************************************************/
161{
162 size_t i;
163 char **p;
164
165 if (!psv->vec) {
166 return;
167 }
168
169 for (i = 0, p = psv->vec; i < psv->size; i++, p++) {
170 string_free(*p);
171 }
172 free(psv->vec);
173 psv->vec = nullptr;
174 psv->size = 0;
175}
176
177/**********************************************************************/
181 int (*cmp_func) (const char *, const char *))
182{
183 size_t i, j;
184 const char *str1, *str2;
185
186 if (!psv->vec || 1 == psv->size) {
187 return;
188 }
189
190 for (i = 1; i < psv->size; i++) {
191 if ((str1 = psv->vec[i])) {
192 for (j = 0; j < i; j++) {
193 if ((str2 = psv->vec[j])
194 && 0 == cmp_func(str2, str1)) {
196 i--;
197 break;
198 }
199 }
200 }
201 }
202}
203
204/**********************************************************************/
209{
210 size_t i;
211 char *str;
212
213 if (!psv->vec) {
214 return;
215 }
216
217 for (i = 0; i < psv->size;) {
218 str = psv->vec[i];
219
220 if (!str) {
222 continue;
223 }
224
226 if (str[0] == '\0') {
228 continue;
229 }
230
231 i++;
232 }
233}
234
235/**********************************************************************/
238void strvec_copy(struct strvec *dest, const struct strvec *src)
239{
240 size_t i;
241 char **p;
242 char *const *l;
243
244 if (!src->vec) {
245 strvec_clear(dest);
246 return;
247 }
248
249 strvec_reserve(dest, src->size);
250 for (i = 0, p = dest->vec, l = src->vec; i < dest->size; i++, p++, l++) {
251 string_free(*p);
252 *p = string_duplicate(*l);
253 }
254}
255
256/**********************************************************************/
259void strvec_sort(struct strvec *psv, int (*sort_func) (const char *const *,
260 const char *const *))
261{
262 qsort(psv->vec, psv->size, sizeof(const char *),
263 (int (*) (const void *, const void *)) sort_func);
264}
265
266/**********************************************************************/
269void strvec_prepend(struct strvec *psv, const char *string)
270{
271 strvec_reserve(psv, psv->size + 1);
272 memmove(psv->vec + 1, psv->vec, (psv->size - 1) * sizeof(char *));
273 psv->vec[0] = string_duplicate(string);
274}
275
276/**********************************************************************/
279void strvec_append(struct strvec *psv, const char *string)
280{
281 strvec_reserve(psv, psv->size + 1);
282 psv->vec[psv->size - 1] = string_duplicate(string);
283}
284
285/**********************************************************************/
288void strvec_insert(struct strvec *psv, size_t svindex, const char *string)
289{
290 if (svindex <= 0) {
291 strvec_prepend(psv, string);
292 } else if (svindex >= psv->size) {
293 strvec_append(psv, string);
294 } else {
295 strvec_reserve(psv, psv->size + 1);
296 memmove(psv->vec + svindex + 1, psv->vec + svindex,
297 (psv->size - svindex - 1) * sizeof(char *));
298 psv->vec[svindex] = string_duplicate(string);
299 }
300}
301
302/**********************************************************************/
306bool strvec_set(struct strvec *psv, size_t svindex, const char *string)
307{
309 string_free(psv->vec[svindex]);
310 psv->vec[svindex] = string_duplicate(string);
311 return TRUE;
312 }
313 return FALSE;
314}
315
316/**********************************************************************/
320bool strvec_remove(struct strvec *psv, size_t svindex)
321{
323 return FALSE;
324 }
325
326 if (psv->size == 1) {
327 /* It is the last. */
329 return TRUE;
330 }
331
332 string_free(psv->vec[svindex]);
333 memmove(psv->vec + svindex, psv->vec + svindex + 1,
334 (psv->size - svindex - 1) * sizeof(char *));
335 psv->vec[psv->size - 1] = nullptr; /* Do not attempt to free this data. */
336 strvec_reserve(psv, psv->size - 1);
337
338 return TRUE;
339}
340
341/**********************************************************************/
344size_t strvec_size(const struct strvec *psv)
345{
346 return psv->size;
347}
348
349/**********************************************************************/
352bool are_strvecs_equal(const struct strvec *stv1,
353 const struct strvec *stv2)
354{
355 int i;
356
357 if (strvec_size(stv1) != strvec_size(stv2)) {
358 return FALSE;
359 }
360
361 for (i = 0; i < strvec_size(stv1); i++) {
362 if (0 != strcmp(stv1->vec[i], stv2->vec[i])) {
363 return FALSE;
364 }
365 }
366
367 return TRUE;
368}
369
370/**********************************************************************/
373const char *const *strvec_data(const struct strvec *psv)
374{
375 return (const char **) psv->vec;
376}
377
378/**********************************************************************/
381bool strvec_index_valid(const struct strvec *psv, size_t svindex)
382{
383 return svindex < psv->size;
384}
385
386/**********************************************************************/
389const char *strvec_get(const struct strvec *psv, size_t svindex)
390{
391 return strvec_index_valid(psv, svindex) ? psv->vec[svindex] : nullptr;
392}
393
394/**********************************************************************/
401void strvec_to_str(const struct strvec *psv, char separator,
402 char *buf, size_t buf_len)
403{
404 int len;
405
407 len = fc_snprintf(buf, buf_len, "%s", str) + 1;
408 if (1 >= len) {
409 /* Truncated. */
410 return;
411 }
412
413 buf += len;
414 buf_len -= len;
415 if (0 < buf_len) {
416 *(buf - 1) = separator;
417 }
419
420 buf[0] = '\0';
421}
422
423/**********************************************************************/
429const char *strvec_to_or_list(const struct strvec *psv,
430 struct astring *astr)
431{
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{
444 return astr_build_and_list(astr, (const char **) psv->vec, psv->size);
445}
const char * astr_build_or_list(struct astring *astr, const char *const *items, size_t number)
Definition astring.c:313
const char * astr_build_and_list(struct astring *astr, const char *const *items, size_t number)
Definition astring.c:351
#define str
Definition astring.c:76
char * incite_cost
Definition comments.c:76
static gint cmp_func(gconstpointer a_p, gconstpointer b_p)
Definition repodlgs.c:368
#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:960
#define TRUE
Definition support.h:46
#define FALSE
Definition support.h:47