1 /* PSPP - a program for statistical analysis.
2 Copyright (C) 2010 Free Software Foundation, Inc.
4 This program is free software: you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation, either version 3 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program. If not, see <http://www.gnu.org/licenses/>. */
19 #include "libpspp/string-array.h"
25 #include "libpspp/array.h"
26 #include "libpspp/i18n.h"
27 #include "libpspp/str.h"
29 #include "gl/xalloc.h"
31 /* Initializes SA as an initially empty array of strings. */
33 string_array_init (struct string_array *sa)
40 /* Initializes DST as an array of strings whose contents are initially copies
41 of the strings in SRC. */
43 string_array_clone (struct string_array *dst, const struct string_array *src)
47 dst->strings = xmalloc (sizeof *dst->strings * src->n);
48 for (i = 0; i < src->n; i++)
49 dst->strings[i] = xstrdup (src->strings[i]);
51 dst->allocated = src->n;
54 /* Exchanges the contents of A and B. */
56 string_array_swap (struct string_array *a, struct string_array *b)
58 struct string_array tmp = *a;
63 /* Frees the strings in SA. SA must be reinitialized (with
64 string_array_init()) before it is used again. */
66 string_array_destroy (struct string_array *sa)
70 string_array_clear (sa);
75 /* Returns true if SA contains at least one copy of STRING, otherwise false.
77 This function runs in O(n) time in the number of strings in SA. */
79 string_array_contains (const struct string_array *sa, const char *string)
81 return string_array_find (sa, string) != SIZE_MAX;
84 /* If SA contains at least one copy of STRING, returns the smallest index of
85 any of those copies. If SA does not contain STRING, returns SIZE_MAX.
87 This function runs in O(n) time in the number of strings in SA. */
89 string_array_find (const struct string_array *sa, const char *string)
93 for (i = 0; i < sa->n; i++)
94 if (!strcmp (sa->strings[i], string))
99 /* Appends a copy of STRING to SA. The caller retains ownership of STRING. */
101 string_array_append (struct string_array *sa, const char *string)
103 string_array_insert (sa, string, sa->n);
106 /* Appends STRING to SA. Ownership of STRING transfers to SA. */
108 string_array_append_nocopy (struct string_array *sa, char *string)
110 string_array_insert_nocopy (sa, string, sa->n);
113 /* Inserts a copy of STRING in SA just before the string with index BEFORE,
114 which must be less than or equal to the number of strings in SA. The caller
115 retains ownership of STRING.
117 In general, this function runs in O(n) time in the number of strings that
118 must be shifted to higher indexes; if BEFORE is the number of strings in SA,
119 it runs in amortized constant time. */
121 string_array_insert (struct string_array *sa,
122 const char *string, size_t before)
124 string_array_insert_nocopy (sa, xstrdup (string), before);
128 string_array_expand__ (struct string_array *sa)
130 if (sa->n >= sa->allocated)
131 sa->strings = x2nrealloc (sa->strings, &sa->allocated,
132 sizeof *sa->strings);
135 /* Inserts STRING in SA just before the string with index BEFORE, which must be
136 less than or equal to the number of strings in SA. Ownership of STRING
139 In general, this function runs in O(n) time in the number of strings that
140 must be shifted to higher indexes; if BEFORE is the number of strings in SA,
141 it runs in amortized constant time. */
143 string_array_insert_nocopy (struct string_array *sa, char *string,
146 string_array_expand__ (sa);
148 insert_element (sa->strings, sa->n, sizeof *sa->strings, before);
150 sa->strings[before] = string;
154 /* Deletes from SA the string with index IDX, which must be less than the
155 number of strings in SA, and shifts down the strings with higher indexes.
158 In general, this function runs in O(n) time in the number of strings that
159 must be shifted to lower indexes. If IDX is the last string in SA, it runs
160 in amortized constant time. */
162 string_array_delete (struct string_array *sa, size_t idx)
164 free (string_array_delete_nofree (sa, idx));
167 /* Deletes from SA the string with index IDX, which must be less than the
168 number of strings in SA. Returns the string, which the caller is
169 responsible for freeing with free().
171 In general, this function runs in O(n) time in the number of strings that
172 must be shifted to lower indexes. If IDX is the last string in SA, it runs
173 in amortized constant time. */
175 string_array_delete_nofree (struct string_array *sa, size_t idx)
177 char *s = sa->strings[idx];
178 if (idx != sa->n - 1)
179 remove_element (sa->strings, sa->n, sizeof *sa->strings, idx);
184 /* Deletes all of the strings from SA and frees them. */
186 string_array_clear (struct string_array *sa)
190 for (i = 0; i < sa->n; i++)
191 free (sa->strings[i]);
195 /* Ensures that 'sa->strings[sa->n]' is a null pointer (until SA is modified
198 string_array_terminate_null (struct string_array *sa)
200 string_array_expand__ (sa);
201 sa->strings[sa->n] = NULL;
204 /* Reduces the amount of memory allocated for SA's strings to the minimum
207 string_array_shrink (struct string_array *sa)
209 if (sa->allocated > sa->n)
212 sa->strings = xrealloc (sa->strings, sa->n * sizeof *sa->strings);
218 sa->allocated = sa->n;
223 compare_strings (const void *a_, const void *b_)
225 const void *const *a = a_;
226 const void *const *b = b_;
228 return strcmp (*a, *b);
231 /* Sorts the strings in SA into order according to strcmp(). */
233 string_array_sort (struct string_array *sa)
235 qsort (sa->strings, sa->n, sizeof *sa->strings, compare_strings);
238 /* Removes all but one of any series of adjacent duplicate strings in SA. */
240 string_array_uniq (struct string_array *sa)
246 for (size_t i = 1; i < sa->n; i++)
248 char *s = sa->strings[i];
249 if (strcmp (sa->strings[n - 1], s))
250 sa->strings[n++] = s;
257 /* Returns true if A and B contain the same strings in the same order,
260 string_array_equal (const struct string_array *a,
261 const struct string_array *b)
266 for (size_t i = 0; i < a->n; i++)
267 if (strcmp (a->strings[i], b->strings[i]))
272 /* Returns true if A and B contain the same strings in the same order,
275 string_array_equal_case (const struct string_array *a,
276 const struct string_array *b)
281 for (size_t i = 0; i < a->n; i++)
282 if (utf8_strcasecmp (a->strings[i], b->strings[i]))
287 /* Divides STRING into tokens at DELIMITERS and adds each token to SA. */
289 string_array_parse (struct string_array *sa, struct substring string,
290 struct substring delimiters)
293 struct substring token;
294 while (ss_tokenize (string, delimiters, &save_idx, &token))
295 string_array_append_nocopy (sa, ss_xstrdup (token));
298 /* Returns a single string that consists of each of the strings in SA
299 concatenated, separated from each other with SEPARATOR.
301 The caller is responsible for freeing the returned string with free(). */
303 string_array_join (const struct string_array *sa, const char *separator)
309 ds_init_empty (&dst);
310 STRING_ARRAY_FOR_EACH (s, i, sa)
313 ds_put_cstr (&dst, separator);
314 ds_put_cstr (&dst, s);
316 return ds_steal_cstr (&dst);