NeoMutt  2024-11-14-34-g5aaf0d
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
66struct Slist *slist_add_string(struct Slist *list, const char *str)
67{
68 if (!list)
69 return NULL;
70
71 if (str && (str[0] == '\0'))
72 str = NULL;
73
74 if (!str && !(list->flags & D_SLIST_ALLOW_EMPTY))
75 return list;
76
78 list->count++;
79
80 return list;
81}
82
89bool slist_equal(const struct Slist *a, const struct Slist *b)
90{
91 if (!a && !b) /* both empty */
92 return true;
93 if (!a ^ !b) /* one is empty, but not the other */
94 return false;
95 if (a->count != b->count)
96 return false;
97
98 return mutt_list_equal(&a->head, &b->head);
99}
100
106struct Slist *slist_dup(const struct Slist *list)
107{
108 if (!list)
109 return NULL;
110
111 struct Slist *list_new = slist_new(list->flags);
112
113 mutt_list_copy_tail(&list_new->head, &list->head);
114 list_new->count = list->count;
115 return list_new;
116}
117
122void slist_free(struct Slist **ptr)
123{
124 if (!ptr || !*ptr)
125 return;
126
127 struct Slist *slist = *ptr;
128 mutt_list_free(&slist->head);
129
130 FREE(ptr);
131}
132
138bool slist_is_empty(const struct Slist *list)
139{
140 if (!list)
141 return true;
142
143 return list->count == 0;
144}
145
152bool slist_is_member(const struct Slist *list, const char *str)
153{
154 if (!list)
155 return false;
156
157 if (!str && !(list->flags & D_SLIST_ALLOW_EMPTY))
158 return false;
159
160 struct ListNode *np = NULL;
161 STAILQ_FOREACH(np, &list->head, entries)
162 {
163 if (mutt_str_equal(np->data, str))
164 return true;
165 }
166 return false;
167}
168
175struct Slist *slist_parse(const char *str, uint32_t flags)
176{
177 char *src = mutt_str_dup(str);
178 if (!src && !(flags & D_SLIST_ALLOW_EMPTY))
179 return NULL;
180
181 char sep = ' ';
183 sep = ',';
185 sep = ':';
186
187 struct Slist *list = MUTT_MEM_CALLOC(1, struct Slist);
188 list->flags = flags;
189 STAILQ_INIT(&list->head);
190
191 if (!src)
192 return list;
193
194 char *start = src;
195 for (char *p = start; *p; p++)
196 {
197 if ((p[0] == '\\') && (p[1] != '\0'))
198 {
199 p++;
200 continue;
201 }
202
203 if (p[0] == sep)
204 {
205 p[0] = '\0';
206 if (slist_is_member(list, start))
207 {
208 start = p + 1;
209 continue;
210 }
212 list->count++;
213 start = p + 1;
214 }
215 }
216
217 if (!slist_is_member(list, start))
218 {
220 list->count++;
221 }
222
223 FREE(&src);
224 return list;
225}
226
233struct Slist *slist_remove_string(struct Slist *list, const char *str)
234{
235 if (!list)
236 return NULL;
237 if (!str && !(list->flags & D_SLIST_ALLOW_EMPTY))
238 return list;
239
240 struct ListNode *prev = NULL;
241 struct ListNode *np = NULL;
242 struct ListNode *tmp = NULL;
243 STAILQ_FOREACH_SAFE(np, &list->head, entries, tmp)
244 {
245 if (mutt_str_equal(np->data, str))
246 {
247 if (prev)
248 STAILQ_REMOVE_AFTER(&list->head, prev, entries);
249 else
250 STAILQ_REMOVE_HEAD(&list->head, entries);
251 FREE(&np->data);
252 FREE(&np);
253 list->count--;
254 break;
255 }
256 prev = np;
257 }
258 return list;
259}
260
267int slist_to_buffer(const struct Slist *list, struct Buffer *buf)
268{
269 if (!list || !buf || (list->count == 0))
270 return 0;
271
272 struct ListNode *np = NULL;
273 STAILQ_FOREACH(np, &list->head, entries)
274 {
275 buf_addstr(buf, np->data);
276 if (STAILQ_NEXT(np, entries))
277 {
278 const int sep = (list->flags & D_SLIST_SEP_MASK);
279 if (sep == D_SLIST_SEP_COMMA)
280 buf_addch(buf, ',');
281 else if (sep == D_SLIST_SEP_COLON)
282 buf_addch(buf, ':');
283 else
284 buf_addch(buf, ' ');
285 }
286 }
287
288 return list->count;
289}
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:233
struct Slist * slist_parse(const char *str, uint32_t flags)
Parse a list of strings into a list.
Definition: slist.c:175
bool slist_is_empty(const struct Slist *list)
Is the slist empty?
Definition: slist.c:138
void slist_free(struct Slist **ptr)
Free an Slist object.
Definition: slist.c:122
bool slist_equal(const struct Slist *a, const struct Slist *b)
Compare two string lists.
Definition: slist.c:89
struct Slist * slist_add_string(struct Slist *list, const char *str)
Add a string to a list.
Definition: slist.c:66
bool slist_is_member(const struct Slist *list, const char *str)
Is a string a member of a list?
Definition: slist.c:152
struct Slist * slist_dup(const struct Slist *list)
Create a copy of an Slist object.
Definition: slist.c:106
int slist_to_buffer(const struct Slist *list, struct Buffer *buf)
Export an Slist to a Buffer.
Definition: slist.c:267
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:253
bool mutt_str_equal(const char *a, const char *b)
Compare two strings.
Definition: string.c:660
#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.
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:111
#define D_SLIST_SEP_COLON
Slist items are colon-separated.
Definition: types.h:112
#define D_SLIST_ALLOW_EMPTY
Slist may be empty.
Definition: types.h:116
#define D_SLIST_SEP_MASK
Definition: types.h:113