#include <config.h>
-#include <libpspp/stringi-set.h>
+#include "libpspp/stringi-set.h"
#include <stdlib.h>
#include <string.h>
-#include <libpspp/hash-functions.h>
+#include "libpspp/cast.h"
+#include "libpspp/hash-functions.h"
#include "gl/xalloc.h"
stringi_set_delete__ (a, node->string, node->hmap_node.hash);
}
}
+
+/* Allocates and returns an array that points to each of the strings in SET.
+ The caller must not free or modify any of the strings. Removing a string
+ from SET invalidates the corresponding element of the returned array. The
+ caller it is responsible for freeing the returned array itself (with
+ free()).
+
+ The returned array is in the same order as observed by stringi_set_first()
+ and stringi_set_next(), that is, no particular order. */
+char **
+stringi_set_get_array (const struct stringi_set *set)
+{
+ const struct stringi_set_node *node;
+ const char *s;
+ char **array;
+ size_t i;
+
+ array = xnmalloc (stringi_set_count (set), sizeof *array);
+
+ i = 0;
+ STRINGI_SET_FOR_EACH (s, node, set)
+ array[i++] = CONST_CAST (char *, s);
+
+ return array;
+}
+
+static int
+compare_strings (const void *a_, const void *b_)
+{
+ const char *const *a = a_;
+ const char *const *b = b_;
+ return strcasecmp (*a, *b);
+}
+
+/* Allocates and returns an array that points to each of the strings in SET.
+ The caller must not free or modify any of the strings. Removing a string
+ from SET invalidates the corresponding element of the returned array. The
+ caller it is responsible for freeing the returned array itself (with
+ free()).
+
+ The returned array is ordered according to strcasecmp(). */
+char **
+stringi_set_get_sorted_array (const struct stringi_set *set)
+{
+ char **array = stringi_set_get_array (set);
+ qsort (array, stringi_set_count (set), sizeof *array, compare_strings);
+ return array;
+}
\f
/* Internal functions. */
void stringi_set_intersect (struct stringi_set *, const struct stringi_set *);
void stringi_set_subtract (struct stringi_set *, const struct stringi_set *);
+char **stringi_set_get_array (const struct stringi_set *);
+char **stringi_set_get_sorted_array (const struct stringi_set *);
+
static inline const struct stringi_set_node *stringi_set_first (
const struct stringi_set *);
static inline const struct stringi_set_node *stringi_set_next (
check (stringi_set_find_node (set, "") == NULL);
if (cnt == 0)
- check (stringi_set_first (set) == NULL);
+ {
+ check (stringi_set_first (set) == NULL);
+ free (stringi_set_get_array (set));
+ }
else
{
const struct stringi_set_node *node;
+ char **array;
int *data_copy;
int left;
+ array = stringi_set_get_array (set);
data_copy = xmemdup (data, cnt * sizeof *data);
left = cnt;
for (node = stringi_set_first (set), i = 0; i < cnt;
const char *s = stringi_set_node_get_string (node);
size_t j;
+ check (s == array[i]);
+
for (j = 0; j < left; j++)
if (!strcasecmp (s, make_string (data_copy[j])))
{
}
check (node == NULL);
free (data_copy);
+ free (array);
+
+ array = stringi_set_get_sorted_array (set);
+ for (i = 0; i < cnt; i++)
+ {
+ if (i > 0)
+ check (strcasecmp (array[i - 1], array[i]) < 0);
+ check (stringi_set_contains (set, array[i]));
+ }
+ free (array);
}
}