stringi-set: New functions for not necessarily null terminated strings.
[pspp] / src / libpspp / stringi-set.h
1 /* PSPP - a program for statistical analysis.
2    Copyright (C) 2009, 2010, 2011 Free Software Foundation, Inc.
3
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.
8
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.
13
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/>. */
16
17 #ifndef LIBPSPP_STRINGI_SET_H
18 #define LIBPSPP_STRINGI_SET_H
19
20 /* Set of unique, case-insensitive strings.
21
22    This is a convenient wrapper around a "struct hmap" for storing strings. */
23
24 #include <stdbool.h>
25 #include "libpspp/hmap.h"
26
27 /* A node in the string set. */
28 struct stringi_set_node
29   {
30     struct hmap_node hmap_node;
31     char *string;
32   };
33
34 /* Returns the string within NODE.  The caller must not modify or free the
35    returned string. */
36 static inline const char *
37 stringi_set_node_get_string (const struct stringi_set_node *node)
38 {
39   return node->string;
40 }
41 \f
42 /* An unordered set of unique strings. */
43 struct stringi_set
44   {
45     struct hmap hmap;
46   };
47
48 /* Suitable for use as the initializer for a stringi_set named SET.  Typical
49    usage:
50        struct stringi_set set = STRINGI_SET_INITIALIZER (set);
51    STRINGI_SET_INITIALIZER is an alternative to calling stringi_set_init. */
52 #define STRINGI_SET_INITIALIZER(SET) { HMAP_INITIALIZER ((SET).hmap) }
53
54 void stringi_set_init (struct stringi_set *);
55 void stringi_set_clone (struct stringi_set *, const struct stringi_set *);
56 void stringi_set_swap (struct stringi_set *, struct stringi_set *);
57 void stringi_set_destroy (struct stringi_set *);
58
59 static inline size_t stringi_set_count (const struct stringi_set *);
60 static inline bool stringi_set_is_empty (const struct stringi_set *);
61
62 bool stringi_set_contains (const struct stringi_set *, const char *);
63 bool stringi_set_contains_len (const struct stringi_set *, const char *,
64                                size_t length);
65 struct stringi_set_node *stringi_set_find_node (const struct stringi_set *,
66                                                 const char *);
67 struct stringi_set_node *stringi_set_find_node_len (const struct stringi_set *,
68                                                     const char *,
69                                                     size_t length);
70
71 bool stringi_set_insert (struct stringi_set *, const char *);
72 bool stringi_set_insert_nocopy (struct stringi_set *, char *);
73 bool stringi_set_delete (struct stringi_set *, const char *);
74 void stringi_set_delete_node (struct stringi_set *, struct stringi_set_node *);
75 char *stringi_set_delete_nofree (struct stringi_set *,
76                                  struct stringi_set_node *);
77
78 void stringi_set_clear (struct stringi_set *);
79 void stringi_set_union (struct stringi_set *, const struct stringi_set *);
80 void stringi_set_union_and_intersection (struct stringi_set *,
81                                         struct stringi_set *);
82 void stringi_set_intersect (struct stringi_set *, const struct stringi_set *);
83 void stringi_set_subtract (struct stringi_set *, const struct stringi_set *);
84
85 char **stringi_set_get_array (const struct stringi_set *);
86 char **stringi_set_get_sorted_array (const struct stringi_set *);
87
88 static inline const struct stringi_set_node *stringi_set_first (
89   const struct stringi_set *);
90 static inline const struct stringi_set_node *stringi_set_next (
91   const struct stringi_set *, const struct stringi_set_node *);
92
93 /* Macros for conveniently iterating through a stringi_set, e.g. to print all
94    of the strings in "my_set":
95
96    struct stringi_set_node *node;
97    const char *string;
98
99    STRINGI_SET_FOR_EACH (string, node, &my_set)
100      puts (string);
101    */
102 #define STRINGI_SET_FOR_EACH(STRING, NODE, SET)                 \
103         for ((NODE) = stringi_set_first (SET);                  \
104              ((NODE) != NULL                                    \
105               ? ((STRING) = stringi_set_node_get_string (NODE), \
106                  1)                                             \
107               : 0);                                             \
108              (NODE) = stringi_set_next (SET, NODE))
109 #define STRINGI_SET_FOR_EACH_SAFE(STRING, NODE, NEXT, SET)      \
110         for ((NODE) = stringi_set_first (SET);                  \
111              ((NODE) != NULL                                    \
112               ? ((STRING) = stringi_set_node_get_string (NODE), \
113                  (NEXT) = stringi_set_next (SET, NODE),         \
114                  1)                                             \
115               : 0);                                             \
116              (NODE) = (NEXT))
117 \f
118 /* Returns the number of strings currently in SET. */
119 static inline size_t
120 stringi_set_count (const struct stringi_set *set)
121 {
122   return hmap_count (&set->hmap);
123 }
124
125 /* Returns true if SET currently contains no strings, false otherwise. */
126 static inline bool
127 stringi_set_is_empty (const struct stringi_set *set)
128 {
129   return hmap_is_empty (&set->hmap);
130 }
131
132 /* Returns the first node in SET, or a null pointer if SET is empty.  See the
133    hmap_first function for information about complexity (O(1) amortized) and
134    ordering (arbitrary).
135
136    The STRINGI_SET_FOR_EACH and STRINGI_SET_FOR_EACH_SAFE macros provide
137    convenient ways to iterate over all the nodes in a string set. */
138 static inline const struct stringi_set_node *
139 stringi_set_first (const struct stringi_set *set)
140 {
141   return HMAP_FIRST (struct stringi_set_node, hmap_node, &set->hmap);
142 }
143
144 /* Returns the next node in SET following NODE, or a null pointer if NODE is
145    the last node in SET.  See the hmap_next function for information about
146    complexity (O(1) amortized) and ordering (arbitrary).
147
148    The STRINGI_SET_FOR_EACH and STRINGI_SET_FOR_EACH_SAFE macros provide
149    convenient ways to iterate over all the nodes in a string set. */
150 static inline const struct stringi_set_node *
151 stringi_set_next (const struct stringi_set *set,
152                  const struct stringi_set_node *node)
153 {
154   return HMAP_NEXT (node, struct stringi_set_node, hmap_node, &set->hmap);
155 }
156
157 #endif /* libpspp/string-set.h */