NeoMutt  2022-04-29-247-gc6aae8
Teaching an old dog new tricks
DOXYGEN
slist.c
Go to the documentation of this file.
1
29#include "config.h"
30#include <stddef.h>
31#include "slist.h"
32#include "buffer.h"
33#include "list.h"
34#include "memory.h"
35#include "queue.h"
36#include "string2.h"
37
43struct Slist *slist_new(uint32_t flags)
44{
45 struct Slist *list = mutt_mem_calloc(1, sizeof(*list));
46 list->flags = flags;
47 STAILQ_INIT(&list->head);
48
49 return list;
50}
51
58struct Slist *slist_add_list(struct Slist *list, const struct Slist *add)
59{
60 if (!add)
61 return list;
62 if (!list)
63 return slist_dup(add);
64
65 struct ListNode *np = NULL;
66 STAILQ_FOREACH(np, &add->head, entries)
67 {
68 mutt_list_insert_tail(&list->head, mutt_str_dup((char *) np->data));
69 list->count++;
70 }
71 return list;
72}
73
80struct Slist *slist_add_string(struct Slist *list, const char *str)
81{
82 if (!list)
83 return NULL;
84
85 if (str && (str[0] == '\0'))
86 str = NULL;
87
88 if (!str && !(list->flags & SLIST_ALLOW_EMPTY))
89 return list;
90
92 list->count++;
93
94 return list;
95}
96
103bool slist_compare(const struct Slist *a, const struct Slist *b)
104{
105 if (!a && !b) /* both empty */
106 return true;
107 if (!a ^ !b) /* one is empty, but not the other */
108 return false;
109 if (a->count != b->count)
110 return false;
111
112 return mutt_list_compare(&a->head, &b->head);
113}
114
120struct Slist *slist_dup(const struct Slist *list)
121{
122 if (!list)
123 return NULL;
124
125 struct Slist *list_new = slist_new(list->flags);
126
127 struct ListNode *np = NULL;
128 STAILQ_FOREACH(np, &list->head, entries)
129 {
131 }
132 list_new->count = list->count;
133 return list_new;
134}
135
141struct Slist *slist_empty(struct Slist **list)
142{
143 if (!list || !*list)
144 return NULL;
145
146 mutt_list_free(&(*list)->head);
147
148 if ((*list)->flags & SLIST_ALLOW_EMPTY)
149 {
150 (*list)->count = 0;
151 return *list;
152 }
153
154 FREE(list);
155 return NULL;
156}
157
162void slist_free(struct Slist **list)
163{
164 if (!list || !*list)
165 return;
166
167 mutt_list_free(&(*list)->head);
168 FREE(list);
169}
170
177bool slist_is_member(const struct Slist *list, const char *str)
178{
179 if (!list)
180 return false;
181
182 if (!str && !(list->flags & SLIST_ALLOW_EMPTY))
183 return false;
184
185 struct ListNode *np = NULL;
186 STAILQ_FOREACH(np, &list->head, entries)
187 {
188 if (mutt_str_equal(np->data, str))
189 return true;
190 }
191 return false;
192}
193
200struct Slist *slist_parse(const char *str, uint32_t flags)
201{
202 char *src = mutt_str_dup(str);
203 if (!src && !(flags & SLIST_ALLOW_EMPTY))
204 return NULL;
205
206 char sep = ' ';
208 sep = ',';
209 else if ((flags & SLIST_SEP_MASK) == SLIST_SEP_COLON)
210 sep = ':';
211
212 struct Slist *list = mutt_mem_calloc(1, sizeof(struct Slist));
213 list->flags = flags;
214 STAILQ_INIT(&list->head);
215
216 if (!src)
217 return list;
218
219 char *start = src;
220 for (char *p = start; *p; p++)
221 {
222 if ((p[0] == '\\') && (p[1] != '\0'))
223 {
224 p++;
225 continue;
226 }
227
228 if (p[0] == sep)
229 {
230 p[0] = '\0';
231 if (slist_is_member(list, start))
232 {
233 start = p + 1;
234 continue;
235 }
237 list->count++;
238 start = p + 1;
239 }
240 }
241
242 if (!slist_is_member(list, start))
243 {
245 list->count++;
246 }
247
248 FREE(&src);
249 return list;
250}
251
258struct Slist *slist_remove_string(struct Slist *list, const char *str)
259{
260 if (!list)
261 return NULL;
262 if (!str && !(list->flags & SLIST_ALLOW_EMPTY))
263 return list;
264
265 struct ListNode *prev = NULL;
266 struct ListNode *np = NULL;
267 struct ListNode *tmp = NULL;
268 STAILQ_FOREACH_SAFE(np, &list->head, entries, tmp)
269 {
270 if (mutt_str_equal(np->data, str))
271 {
272 if (prev)
273 STAILQ_REMOVE_AFTER(&list->head, prev, entries);
274 else
275 STAILQ_REMOVE_HEAD(&list->head, entries);
276 FREE(&np->data);
277 FREE(&np);
278 list->count--;
279 break;
280 }
281 prev = np;
282 }
283 return list;
284}
285
292int slist_to_buffer(const struct Slist *list, struct Buffer *buf)
293{
294 if (!list || !buf || (list->count == 0))
295 return 0;
296
297 struct ListNode *np = NULL;
298 STAILQ_FOREACH(np, &list->head, entries)
299 {
300 mutt_buffer_addstr(buf, np->data);
301 if (STAILQ_NEXT(np, entries))
302 {
303 const int sep = (list->flags & SLIST_SEP_MASK);
304 if (sep == SLIST_SEP_COMMA)
305 mutt_buffer_addch(buf, ',');
306 else if (sep == SLIST_SEP_COLON)
307 mutt_buffer_addch(buf, ':');
308 else
309 mutt_buffer_addch(buf, ' ');
310 }
311 }
312
313 return list->count;
314}
size_t mutt_buffer_addch(struct Buffer *buf, char c)
Add a single character to a Buffer.
Definition: buffer.c:248
size_t mutt_buffer_addstr(struct Buffer *buf, const char *s)
Add a string to a Buffer.
Definition: buffer.c:233
General purpose object for storing and parsing strings.
struct ListNode * mutt_list_insert_tail(struct ListHead *h, char *s)
Append a string to the end of a List.
Definition: list.c:64
bool mutt_list_compare(const struct ListHead *ah, const struct ListHead *bh)
Compare two string lists.
Definition: list.c:218
void mutt_list_free(struct ListHead *h)
Free a List AND its strings.
Definition: list.c:122
Singly-linked list type.
void * mutt_mem_calloc(size_t nmemb, size_t size)
Allocate zeroed memory on the heap.
Definition: memory.c:50
Memory management wrappers.
#define FREE(x)
Definition: memory.h:43
struct Slist * slist_remove_string(struct Slist *list, const char *str)
Remove a string from a list.
Definition: slist.c:258
struct Slist * slist_empty(struct Slist **list)
Empty out an Slist object.
Definition: slist.c:141
struct Slist * slist_parse(const char *str, uint32_t flags)
Parse a list of strings into a list.
Definition: slist.c:200
struct Slist * slist_add_list(struct Slist *list, const struct Slist *add)
Add a list to another list.
Definition: slist.c:58
bool slist_compare(const struct Slist *a, const struct Slist *b)
Compare two string lists.
Definition: slist.c:103
struct Slist * slist_add_string(struct Slist *list, const char *str)
Add a string to a list.
Definition: slist.c:80
bool slist_is_member(const struct Slist *list, const char *str)
Is a string a member of a list?
Definition: slist.c:177
struct Slist * slist_dup(const struct Slist *list)
Create a copy of an Slist object.
Definition: slist.c:120
int slist_to_buffer(const struct Slist *list, struct Buffer *buf)
Export an Slist to a Buffer.
Definition: slist.c:292
struct Slist * slist_new(uint32_t flags)
Create a new string list.
Definition: slist.c:43
void slist_free(struct Slist **list)
Free an Slist object.
Definition: slist.c:162
char * mutt_str_dup(const char *str)
Copy a string, safely.
Definition: string.c:250
bool mutt_str_equal(const char *a, const char *b)
Compare two strings.
Definition: string.c:807
#define STAILQ_REMOVE_HEAD(head, field)
Definition: queue.h:422
#define STAILQ_INIT(head)
Definition: queue.h:372
#define STAILQ_REMOVE_AFTER(head, elm, field)
Definition: queue.h:416
#define STAILQ_FOREACH(var, head, field)
Definition: queue.h:352
#define STAILQ_FOREACH_SAFE(var, head, field, tvar)
Definition: queue.h:362
#define STAILQ_NEXT(elm, field)
Definition: queue.h:400
A separated list of strings.
#define SLIST_SEP_COMMA
Definition: slist.h:34
#define SLIST_SEP_COLON
Definition: slist.h:35
#define SLIST_SEP_MASK
Definition: slist.h:37
#define SLIST_ALLOW_EMPTY
Definition: slist.h:40
String manipulation functions.
String manipulation buffer.
Definition: buffer.h:34
A List node for strings.
Definition: list.h:35
char * data
String.
Definition: list.h:36
String list.
Definition: slist.h:47
struct ListHead head
List containing values.
Definition: slist.h:48
size_t count
Number of values in list.
Definition: slist.h:49
uint32_t flags
Flags controlling list, e.g. SLIST_SEP_SPACE.
Definition: slist.h:50