NeoMutt  2025-01-09-81-g753ae0
Teaching an old dog new tricks
DOXYGEN
Loading...
Searching...
No Matches
slist.c
Go to the documentation of this file.
1
36#include "config.h"
37#include <stddef.h>
38#include "config/types.h"
39#include "slist.h"
40#include "buffer.h"
41#include "list.h"
42#include "memory.h"
43#include "queue.h"
44#include "string2.h"
45
51struct Slist *slist_new(uint32_t flags)
52{
53 struct Slist *list = MUTT_MEM_CALLOC(1, struct Slist);
54 list->flags = flags;
55 STAILQ_INIT(&list->head);
56
57 return list;
58}
59
68struct Slist *slist_add_string(struct Slist *list, const char *str)
69{
70 if (!list)
71 return NULL;
72
73 if (str && (str[0] == '\0'))
74 str = NULL;
75
76 if (!str && !(list->flags & D_SLIST_ALLOW_EMPTY))
77 return list;
78
80 list->count++;
81
82 return list;
83}
84
91bool slist_equal(const struct Slist *a, const struct Slist *b)
92{
93 if (!a && !b) /* both empty */
94 return true;
95 if (!a ^ !b) /* one is empty, but not the other */
96 return false;
97 if (a->count != b->count)
98 return false;
99
100 return mutt_list_equal(&a->head, &b->head);
101}
102
108struct Slist *slist_dup(const struct Slist *list)
109{
110 if (!list)
111 return NULL;
112
113 struct Slist *list_new = slist_new(list->flags);
114
115 mutt_list_copy_tail(&list_new->head, &list->head);
116 list_new->count = list->count;
117 return list_new;
118}
119
124void slist_free(struct Slist **ptr)
125{
126 if (!ptr || !*ptr)
127 return;
128
129 struct Slist *slist = *ptr;
130 mutt_list_free(&slist->head);
131
132 FREE(ptr);
133}
134
140bool slist_is_empty(const struct Slist *list)
141{
142 if (!list)
143 return true;
144
145 return list->count == 0;
146}
147
154bool slist_is_member(const struct Slist *list, const char *str)
155{
156 if (!list)
157 return false;
158
159 if (!str && !(list->flags & D_SLIST_ALLOW_EMPTY))
160 return false;
161
162 struct ListNode *np = NULL;
163 STAILQ_FOREACH(np, &list->head, entries)
164 {
165 if (mutt_str_equal(np->data, str))
166 return true;
167 }
168 return false;
169}
170
177struct Slist *slist_parse(const char *str, uint32_t flags)
178{
179 char *src = mutt_str_dup(str);
180 if (!src && !(flags & D_SLIST_ALLOW_EMPTY))
181 return NULL;
182
183 char sep = ' ';
185 sep = ',';
187 sep = ':';
188
189 struct Slist *list = MUTT_MEM_CALLOC(1, struct Slist);
190 list->flags = flags;
191 STAILQ_INIT(&list->head);
192
193 if (!src)
194 return list;
195
196 char *start = src;
197 for (char *p = start; *p; p++)
198 {
199 if ((p[0] == '\\') && (p[1] != '\0'))
200 {
201 p++;
202 continue;
203 }
204
205 if (p[0] == sep)
206 {
207 p[0] = '\0';
208 if (slist_is_member(list, start))
209 {
210 start = p + 1;
211 continue;
212 }
214 list->count++;
215 start = p + 1;
216 }
217 }
218
219 if (!slist_is_member(list, start))
220 {
222 list->count++;
223 }
224
225 FREE(&src);
226 return list;
227}
228
235struct Slist *slist_remove_string(struct Slist *list, const char *str)
236{
237 if (!list)
238 return NULL;
239 if (!str && !(list->flags & D_SLIST_ALLOW_EMPTY))
240 return list;
241
242 struct ListNode *prev = NULL;
243 struct ListNode *np = NULL;
244 struct ListNode *tmp = NULL;
245 STAILQ_FOREACH_SAFE(np, &list->head, entries, tmp)
246 {
247 if (mutt_str_equal(np->data, str))
248 {
249 if (prev)
250 STAILQ_REMOVE_AFTER(&list->head, prev, entries);
251 else
252 STAILQ_REMOVE_HEAD(&list->head, entries);
253 FREE(&np->data);
254 FREE(&np);
255 list->count--;
256 break;
257 }
258 prev = np;
259 }
260 return list;
261}
262
269int slist_to_buffer(const struct Slist *list, struct Buffer *buf)
270{
271 if (!list || !buf || (list->count == 0))
272 return 0;
273
274 struct ListNode *np = NULL;
275 STAILQ_FOREACH(np, &list->head, entries)
276 {
277 buf_addstr(buf, np->data);
278 if (STAILQ_NEXT(np, entries))
279 {
280 const int sep = (list->flags & D_SLIST_SEP_MASK);
281 if (sep == D_SLIST_SEP_COMMA)
282 buf_addch(buf, ',');
283 else if (sep == D_SLIST_SEP_COLON)
284 buf_addch(buf, ':');
285 else
286 buf_addch(buf, ' ');
287 }
288 }
289
290 return list->count;
291}
size_t buf_addch(struct Buffer *buf, char c)
Add a single character to a Buffer.
Definition: buffer.c:241
size_t buf_addstr(struct Buffer *buf, const char *s)
Add a string to a Buffer.
Definition: buffer.c:226
General purpose object for storing and parsing strings.
void mutt_list_copy_tail(struct ListHead *dst, const struct ListHead *src)
Copy a list into another list.
Definition: list.c:275
struct ListNode * mutt_list_insert_tail(struct ListHead *h, char *s)
Append a string to the end of a List.
Definition: list.c:65
bool mutt_list_equal(const struct ListHead *ah, const struct ListHead *bh)
Compare two string lists.
Definition: list.c:217
void mutt_list_free(struct ListHead *h)
Free a List AND its strings.
Definition: list.c:123
Singly-linked list type.
Memory management wrappers.
#define FREE(x)
Definition: memory.h:55
#define MUTT_MEM_CALLOC(n, type)
Definition: memory.h:40
struct Slist * slist_remove_string(struct Slist *list, const char *str)
Remove a string from a list.
Definition: slist.c:235
struct Slist * slist_parse(const char *str, uint32_t flags)
Parse a list of strings into a list.
Definition: slist.c:177
bool slist_is_empty(const struct Slist *list)
Is the slist empty?
Definition: slist.c:140
void slist_free(struct Slist **ptr)
Free an Slist object.
Definition: slist.c:124
bool slist_equal(const struct Slist *a, const struct Slist *b)
Compare two string lists.
Definition: slist.c:91
struct Slist * slist_add_string(struct Slist *list, const char *str)
Add a string to a list.
Definition: slist.c:68
bool slist_is_member(const struct Slist *list, const char *str)
Is a string a member of a list?
Definition: slist.c:154
struct Slist * slist_dup(const struct Slist *list)
Create a copy of an Slist object.
Definition: slist.c:108
int slist_to_buffer(const struct Slist *list, struct Buffer *buf)
Export an Slist to a Buffer.
Definition: slist.c:269
struct Slist * slist_new(uint32_t flags)
Create a new string list.
Definition: slist.c:51
char * mutt_str_dup(const char *str)
Copy a string, safely.
Definition: string.c:254
bool mutt_str_equal(const char *a, const char *b)
Compare two strings.
Definition: string.c:661
#define STAILQ_REMOVE_HEAD(head, field)
Definition: queue.h:461
#define STAILQ_INIT(head)
Definition: queue.h:410
#define STAILQ_REMOVE_AFTER(head, elm, field)
Definition: queue.h:455
#define STAILQ_FOREACH(var, head, field)
Definition: queue.h:390
#define STAILQ_FOREACH_SAFE(var, head, field, tvar)
Definition: queue.h:400
#define STAILQ_NEXT(elm, field)
Definition: queue.h:439
A separated list of strings.
String manipulation functions.
String manipulation buffer.
Definition: buffer.h:36
A List node for strings.
Definition: list.h:37
char * data
String.
Definition: list.h:38
String list.
Definition: slist.h:37
struct ListHead head
List containing values.
Definition: slist.h:38
size_t count
Number of values in list.
Definition: slist.h:39
uint32_t flags
Flags controlling list, e.g. D_SLIST_SEP_SPACE.
Definition: slist.h:40
Constants for all the config types.
#define D_SLIST_SEP_COMMA
Slist items are comma-separated.
Definition: types.h:110
#define D_SLIST_SEP_COLON
Slist items are colon-separated.
Definition: types.h:111
#define D_SLIST_ALLOW_EMPTY
Slist may be empty.
Definition: types.h:115
#define D_SLIST_SEP_MASK
Definition: types.h:112