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/str.h"
28 #include "gl/xalloc.h"
30 /* Initializes SA as an initially empty array of strings. */
32 string_array_init (struct string_array *sa)
39 /* Initializes DST as an array of strings whose contents are initially copies
40 of the strings in SRC. */
42 string_array_clone (struct string_array *dst, const struct string_array *src)
46 dst->strings = xmalloc (sizeof *dst->strings * src->n);
47 for (i = 0; i < src->n; i++)
48 dst->strings[i] = xstrdup (src->strings[i]);
50 dst->allocated = src->n;
53 /* Exchanges the contents of A and B. */
55 string_array_swap (struct string_array *a, struct string_array *b)
57 struct string_array tmp = *a;
62 /* Frees the strings in SA. SA must be reinitialized (with
63 string_array_init()) before it is used again. */
65 string_array_destroy (struct string_array *sa)
69 string_array_clear (sa);
74 /* Returns true if SA contains at least one copy of STRING, otherwise false.
76 This function runs in O(n) time in the number of strings in SA. */
78 string_array_contains (const struct string_array *sa, const char *string)
80 return string_array_find (sa, string) != SIZE_MAX;
83 /* If SA contains at least one copy of STRING, returns the smallest index of
84 any of those copies. If SA does not contain STRING, returns SIZE_MAX.
86 This function runs in O(n) time in the number of strings in SA. */
88 string_array_find (const struct string_array *sa, const char *string)
92 for (i = 0; i < sa->n; i++)
93 if (!strcmp (sa->strings[i], string))
98 /* Appends a copy of STRING to SA. The caller retains ownership of STRING. */
100 string_array_append (struct string_array *sa, const char *string)
102 string_array_insert (sa, string, sa->n);
105 /* Appends STRING to SA. Ownership of STRING transfers to SA. */
107 string_array_append_nocopy (struct string_array *sa, char *string)
109 string_array_insert_nocopy (sa, string, sa->n);
112 /* Inserts a copy of STRING in SA just before the string with index BEFORE,
113 which must be less than or equal to the number of strings in SA. The caller
114 retains ownership of STRING.
116 In general, this function runs in O(n) time in the number of strings that
117 must be shifted to higher indexes; if BEFORE is the number of strings in SA,
118 it runs in amortized constant time. */
120 string_array_insert (struct string_array *sa,
121 const char *string, size_t before)
123 string_array_insert_nocopy (sa, xstrdup (string), before);
127 string_array_expand__ (struct string_array *sa)
129 if (sa->n >= sa->allocated)
130 sa->strings = x2nrealloc (sa->strings, &sa->allocated,
131 sizeof *sa->strings);
134 /* Inserts STRING in SA just before the string with index BEFORE, which must be
135 less than or equal to the number of strings in SA. Ownership of STRING
138 In general, this function runs in O(n) time in the number of strings that
139 must be shifted to higher indexes; if BEFORE is the number of strings in SA,
140 it runs in amortized constant time. */
142 string_array_insert_nocopy (struct string_array *sa, char *string,
145 string_array_expand__ (sa);
147 insert_element (sa->strings, sa->n, sizeof *sa->strings, before);
149 sa->strings[before] = string;
153 /* Deletes from SA the string with index IDX, which must be less than the
154 number of strings in SA, and shifts down the strings with higher indexes.
157 In general, this function runs in O(n) time in the number of strings that
158 must be shifted to lower indexes. If IDX is the last string in SA, it runs
159 in amortized constant time. */
161 string_array_delete (struct string_array *sa, size_t idx)
163 free (string_array_delete_nofree (sa, idx));
166 /* Deletes from SA the string with index IDX, which must be less than the
167 number of strings in SA. Returns the string, which the caller is
168 responsible for freeing with free().
170 In general, this function runs in O(n) time in the number of strings that
171 must be shifted to lower indexes. If IDX is the last string in SA, it runs
172 in amortized constant time. */
174 string_array_delete_nofree (struct string_array *sa, size_t idx)
176 char *s = sa->strings[idx];
177 if (idx != sa->n - 1)
178 remove_element (sa->strings, sa->n, sizeof *sa->strings, idx);
183 /* Deletes all of the strings from SA and frees them. */
185 string_array_clear (struct string_array *sa)
189 for (i = 0; i < sa->n; i++)
190 free (sa->strings[i]);
194 /* Ensures that 'sa->strings[sa->n]' is a null pointer (until SA is modified
197 string_array_terminate_null (struct string_array *sa)
199 string_array_expand__ (sa);
200 sa->strings[sa->n] = NULL;
203 /* Reduces the amount of memory allocated for SA's strings to the minimum
206 string_array_shrink (struct string_array *sa)
208 if (sa->allocated > sa->n)
211 sa->strings = xrealloc (sa->strings, sa->n * sizeof *sa->strings);
217 sa->allocated = sa->n;
222 compare_strings (const void *a_, const void *b_)
224 const void *const *a = a_;
225 const void *const *b = b_;
227 return strcmp (*a, *b);
230 /* Sorts the strings in SA into order according to strcmp(). */
232 string_array_sort (struct string_array *sa)
234 qsort (sa->strings, sa->n, sizeof *sa->strings, compare_strings);
237 /* Returns a single string that consists of each of the strings in SA
238 concatenated, separated from each other with SEPARATOR.
240 The caller is responsible for freeing the returned string with free(). */
242 string_array_join (const struct string_array *sa, const char *separator)
248 ds_init_empty (&dst);
249 STRING_ARRAY_FOR_EACH (s, i, sa)
252 ds_put_cstr (&dst, separator);
253 ds_put_cstr (&dst, s);
255 return ds_steal_cstr (&dst);