a604e1513efe9179ff931a2f4bf0b2d8edf746d2
[pspp-builds.git] / src / libpspp / string-set.h
1 /* PSPP - a program for statistical analysis.
2    Copyright (C) 2009 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_STRING_SET_H
18 #define LIBPSPP_STRING_SET_H
19
20 /* Set of unique 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 string_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 string_set_node_get_string (const struct string_set_node *node)
38 {
39   return node->string;
40 }
41 \f
42 /* An unordered set of unique strings. */
43 struct string_set
44   {
45     struct hmap hmap;
46   };
47
48 /* Suitable for use as the initializer for a string_set named SET.  Typical
49    usage:
50        struct string_set set = STRING_SET_INITIALIZER (set);
51    STRING_SET_INITIALIZER is an alternative to calling string_set_init. */
52 #define STRING_SET_INITIALIZER(SET) { HMAP_INITIALIZER ((SET).hmap) }
53
54 void string_set_init (struct string_set *);
55 void string_set_clone (struct string_set *, const struct string_set *);
56 void string_set_swap (struct string_set *, struct string_set *);
57 void string_set_destroy (struct string_set *);
58
59 static inline size_t string_set_count (const struct string_set *);
60 static inline bool string_set_is_empty (const struct string_set *);
61
62 bool string_set_contains (const struct string_set *, const char *);
63 struct string_set_node *string_set_find_node (const struct string_set *,
64                                               const char *);
65
66 bool string_set_insert (struct string_set *, const char *);
67 bool string_set_insert_nocopy (struct string_set *, char *);
68 bool string_set_delete (struct string_set *, const char *);
69 void string_set_delete_node (struct string_set *, struct string_set_node *);
70 char *string_set_delete_nofree (struct string_set *, struct string_set_node *);
71
72 void string_set_clear (struct string_set *);
73 void string_set_union (struct string_set *, const struct string_set *);
74 void string_set_union_and_intersection (struct string_set *,
75                                         struct string_set *);
76 void string_set_intersect (struct string_set *, const struct string_set *);
77 void string_set_subtract (struct string_set *, const struct string_set *);
78
79 static inline const struct string_set_node *string_set_first (
80   const struct string_set *);
81 static inline const struct string_set_node *string_set_next (
82   const struct string_set *, const struct string_set_node *);
83
84 /* Macros for conveniently iterating through a string_set, e.g. to print all of
85    the strings in "my_set":
86
87    struct string_set_node *node;
88    const char *string;
89
90    STRING_SET_FOR_EACH (string, node, &my_set)
91      puts (string);
92    */
93 #define STRING_SET_FOR_EACH(STRING, NODE, SET)                  \
94         for ((NODE) = string_set_first (SET);                   \
95              ((NODE) != NULL                                    \
96               ? ((STRING) = string_set_node_get_string (NODE),  \
97                  1)                                             \
98               : 0);                                             \
99              (NODE) = string_set_next (SET, NODE))
100 #define STRING_SET_FOR_EACH_SAFE(STRING, NODE, NEXT, SET)       \
101         for ((NODE) = string_set_first (SET);                   \
102              ((NODE) != NULL                                    \
103               ? ((STRING) = string_set_node_get_string (NODE),  \
104                  (NEXT) = string_set_next (SET, NODE),          \
105                  1)                                             \
106               : 0);                                             \
107              (NODE) = (NEXT))
108 \f
109 /* Returns the number of strings currently in SET. */
110 static inline size_t
111 string_set_count (const struct string_set *set)
112 {
113   return hmap_count (&set->hmap);
114 }
115
116 /* Returns true if SET currently contains no strings, false otherwise. */
117 static inline bool
118 string_set_is_empty (const struct string_set *set)
119 {
120   return hmap_is_empty (&set->hmap);
121 }
122
123 /* Returns the first node in SET, or a null pointer if SET is empty.  See the
124    hmap_first function for information about complexity (O(1) amortized) and
125    ordering (arbitrary).
126
127    The STRING_SET_FOR_EACH and STRING_SET_FOR_EACH_SAFE macros provide
128    convenient ways to iterate over all the nodes in a string set. */
129 static inline const struct string_set_node *
130 string_set_first (const struct string_set *set)
131 {
132   return HMAP_FIRST (struct string_set_node, hmap_node, &set->hmap);
133 }
134
135 /* Returns the next node in SET following NODE, or a null pointer if NODE is
136    the last node in SET.  See the hmap_next function for information about
137    complexity (O(1) amortized) and ordering (arbitrary).
138
139    The STRING_SET_FOR_EACH and STRING_SET_FOR_EACH_SAFE macros provide
140    convenient ways to iterate over all the nodes in a string set. */
141 static inline const struct string_set_node *
142 string_set_next (const struct string_set *set,
143                  const struct string_set_node *node)
144 {
145   return HMAP_NEXT (node, struct string_set_node, hmap_node, &set->hmap);
146 }
147
148 #endif /* libpspp/string-set.h */