NeoMutt  2023-03-22-27-g3cb248
Teaching an old dog new tricks
DOXYGEN
mbtable.c
Go to the documentation of this file.
1
35#include "config.h"
36#include <stdint.h>
37#include <string.h>
38#include <wchar.h>
39#include "mutt/lib.h"
40#include "mbtable.h"
41#include "set.h"
42#include "types.h"
43
49struct MbTable *mbtable_parse(const char *s)
50{
51 struct MbTable *t = NULL;
52 size_t slen, k;
53 mbstate_t mbstate = { 0 };
54 char *d = NULL;
55
56 slen = mutt_str_len(s);
57 if (!slen)
58 return NULL;
59
60 t = mutt_mem_calloc(1, sizeof(struct MbTable));
61
62 t->orig_str = mutt_str_dup(s);
63 /* This could be more space efficient. However, being used on tiny
64 * strings (`$to_chars` and `$status_chars`), the overhead is not great. */
65 t->chars = mutt_mem_calloc(slen, sizeof(char *));
66 t->segmented_str = mutt_mem_calloc(slen * 2, sizeof(char));
67 d = t->segmented_str;
68
69 while (slen && (k = mbrtowc(NULL, s, slen, &mbstate)))
70 {
71 if ((k == (size_t) (-1)) || (k == (size_t) (-2)))
72 {
73 /* XXX put message in err buffer; fail? warning? */
74 mutt_debug(LL_DEBUG1, "mbrtowc returned %d converting %s in %s\n",
75 (k == (size_t) (-1)) ? -1 : -2, s, t->orig_str);
76 if (k == (size_t) (-1))
77 memset(&mbstate, 0, sizeof(mbstate));
78 k = (k == (size_t) (-1)) ? 1 : slen;
79 }
80
81 slen -= k;
82 t->chars[t->len++] = d;
83 while (k--)
84 *d++ = *s++;
85 *d++ = '\0';
86 }
87
88 return t;
89}
90
94static void mbtable_destroy(const struct ConfigSet *cs, void *var, const struct ConfigDef *cdef)
95{
96 struct MbTable **m = var;
97 if (!*m)
98 return;
99
100 mbtable_free(m);
101}
102
106static int mbtable_string_set(const struct ConfigSet *cs, void *var, struct ConfigDef *cdef,
107 const char *value, struct Buffer *err)
108{
109 /* Store empty mbtables as NULL */
110 if (value && (value[0] == '\0'))
111 value = NULL;
112
113 struct MbTable *table = NULL;
114
115 int rc = CSR_SUCCESS;
116
117 if (var)
118 {
119 struct MbTable *curval = *(struct MbTable **) var;
120 if (curval && mutt_str_equal(value, curval->orig_str))
122
123 table = mbtable_parse(value);
124
125 if (cdef->validator)
126 {
127 rc = cdef->validator(cs, cdef, (intptr_t) table, err);
128
129 if (CSR_RESULT(rc) != CSR_SUCCESS)
130 {
131 mbtable_free(&table);
132 return rc | CSR_INV_VALIDATOR;
133 }
134 }
135
136 mbtable_destroy(cs, var, cdef);
137
138 *(struct MbTable **) var = table;
139
140 if (!table)
141 rc |= CSR_SUC_EMPTY;
142 }
143 else
144 {
145 if (cdef->type & DT_INITIAL_SET)
146 FREE(&cdef->initial);
147
148 cdef->type |= DT_INITIAL_SET;
149 cdef->initial = (intptr_t) mutt_str_dup(value);
150 }
151
152 return rc;
153}
154
158static int mbtable_string_get(const struct ConfigSet *cs, void *var,
159 const struct ConfigDef *cdef, struct Buffer *result)
160{
161 const char *str = NULL;
162
163 if (var)
164 {
165 struct MbTable *table = *(struct MbTable **) var;
166 if (!table || !table->orig_str)
167 return CSR_SUCCESS | CSR_SUC_EMPTY; /* empty string */
168 str = table->orig_str;
169 }
170 else
171 {
172 str = (char *) cdef->initial;
173 }
174
175 mutt_buffer_addstr(result, str);
176 return CSR_SUCCESS;
177}
178
184static struct MbTable *mbtable_dup(struct MbTable *table)
185{
186 if (!table)
187 return NULL; /* LCOV_EXCL_LINE */
188
189 struct MbTable *m = mutt_mem_calloc(1, sizeof(*m));
190 m->orig_str = mutt_str_dup(table->orig_str);
191 return m;
192}
193
197static int mbtable_native_set(const struct ConfigSet *cs, void *var,
198 const struct ConfigDef *cdef, intptr_t value,
199 struct Buffer *err)
200{
201 int rc;
202
203 if (cdef->validator)
204 {
205 rc = cdef->validator(cs, cdef, value, err);
206
207 if (CSR_RESULT(rc) != CSR_SUCCESS)
208 return rc | CSR_INV_VALIDATOR;
209 }
210
211 mbtable_free(var);
212
213 struct MbTable *table = mbtable_dup((struct MbTable *) value);
214
215 rc = CSR_SUCCESS;
216 if (!table)
217 rc |= CSR_SUC_EMPTY;
218
219 *(struct MbTable **) var = table;
220 return rc;
221}
222
226static intptr_t mbtable_native_get(const struct ConfigSet *cs, void *var,
227 const struct ConfigDef *cdef, struct Buffer *err)
228{
229 struct MbTable *table = *(struct MbTable **) var;
230
231 return (intptr_t) table;
232}
233
237static int mbtable_reset(const struct ConfigSet *cs, void *var,
238 const struct ConfigDef *cdef, struct Buffer *err)
239{
240 struct MbTable *table = NULL;
241 const char *initial = (const char *) cdef->initial;
242
243 struct MbTable *curtable = *(struct MbTable **) var;
244 const char *curval = curtable ? curtable->orig_str : NULL;
245
246 int rc = CSR_SUCCESS;
247 if (!curtable)
248 rc |= CSR_SUC_EMPTY;
249
250 if (mutt_str_equal(initial, curval))
251 return rc | CSR_SUC_NO_CHANGE;
252
253 if (initial)
254 table = mbtable_parse(initial);
255
256 if (cdef->validator)
257 {
258 rc = cdef->validator(cs, cdef, (intptr_t) table, err);
259
260 if (CSR_RESULT(rc) != CSR_SUCCESS)
261 {
262 mbtable_destroy(cs, &table, cdef);
263 return rc | CSR_INV_VALIDATOR;
264 }
265 }
266
267 if (!table)
268 rc |= CSR_SUC_EMPTY;
269
270 mbtable_destroy(cs, var, cdef);
271
272 *(struct MbTable **) var = table;
273 return rc;
274}
275
280void mbtable_free(struct MbTable **table)
281{
282 if (!table || !*table)
283 return;
284
285 FREE(&(*table)->orig_str);
286 FREE(&(*table)->chars);
287 FREE(&(*table)->segmented_str);
288 FREE(table);
289}
290
294const struct ConfigSetType CstMbtable = {
296 "mbtable",
301 NULL, // string_plus_equals
302 NULL, // string_minus_equals
305};
size_t mutt_buffer_addstr(struct Buffer *buf, const char *s)
Add a string to a Buffer.
Definition: buffer.c:233
#define CSR_INV_VALIDATOR
Value was rejected by the validator.
Definition: set.h:48
#define CSR_SUC_NO_CHANGE
The value hasn't changed.
Definition: set.h:44
#define CSR_RESULT(x)
Definition: set.h:52
#define CSR_SUC_EMPTY
Value is empty/unset.
Definition: set.h:42
#define CSR_SUCCESS
Action completed successfully.
Definition: set.h:35
static void mbtable_destroy(const struct ConfigSet *cs, void *var, const struct ConfigDef *cdef)
Destroy an MbTable object - Implements ConfigSetType::destroy() -.
Definition: mbtable.c:94
static intptr_t mbtable_native_get(const struct ConfigSet *cs, void *var, const struct ConfigDef *cdef, struct Buffer *err)
Get an MbTable object from a MbTable config item - Implements ConfigSetType::native_get() -.
Definition: mbtable.c:226
static int mbtable_native_set(const struct ConfigSet *cs, void *var, const struct ConfigDef *cdef, intptr_t value, struct Buffer *err)
Set an MbTable config item by MbTable object - Implements ConfigSetType::native_set() -.
Definition: mbtable.c:197
static int mbtable_reset(const struct ConfigSet *cs, void *var, const struct ConfigDef *cdef, struct Buffer *err)
Reset an MbTable to its initial value - Implements ConfigSetType::reset() -.
Definition: mbtable.c:237
static int mbtable_string_get(const struct ConfigSet *cs, void *var, const struct ConfigDef *cdef, struct Buffer *result)
Get a MbTable as a string - Implements ConfigSetType::string_get() -.
Definition: mbtable.c:158
static int mbtable_string_set(const struct ConfigSet *cs, void *var, struct ConfigDef *cdef, const char *value, struct Buffer *err)
Set an MbTable by string - Implements ConfigSetType::string_set() -.
Definition: mbtable.c:106
#define mutt_debug(LEVEL,...)
Definition: logging.h:84
@ LL_DEBUG1
Log at debug level 1.
Definition: logging.h:40
void mbtable_free(struct MbTable **table)
Free an MbTable object.
Definition: mbtable.c:280
static struct MbTable * mbtable_dup(struct MbTable *table)
Create a copy of an MbTable object.
Definition: mbtable.c:184
struct MbTable * mbtable_parse(const char *s)
Parse a multibyte string into a table.
Definition: mbtable.c:49
const struct ConfigSetType CstMbtable
Config type representing a multi-byte table.
Definition: mbtable.c:294
Type representing a multibyte character table.
void * mutt_mem_calloc(size_t nmemb, size_t size)
Allocate zeroed memory on the heap.
Definition: memory.c:50
#define FREE(x)
Definition: memory.h:43
Convenience wrapper for the library headers.
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
size_t mutt_str_len(const char *a)
Calculate the length of a string, safely.
Definition: string.c:567
Parse the 'set' command.
String manipulation buffer.
Definition: buffer.h:34
Definition: set.h:64
int(* validator)(const struct ConfigSet *cs, const struct ConfigDef *cdef, intptr_t value, struct Buffer *err)
Definition: set.h:82
intptr_t initial
Initial value.
Definition: set.h:67
uint32_t type
Variable type, e.g. DT_STRING.
Definition: set.h:66
Container for lots of config items.
Definition: set.h:252
Multibyte character table.
Definition: mbtable.h:34
char * orig_str
Original string used to generate this object.
Definition: mbtable.h:35
int len
Number of characters.
Definition: mbtable.h:36
char ** chars
The array of multibyte character strings.
Definition: mbtable.h:37
char * segmented_str
Each chars entry points inside this string.
Definition: mbtable.h:38
Constants for all the config types.
#define DT_INITIAL_SET
Config item must have its initial value freed.
Definition: types.h:77
#define DT_MBTABLE
multibyte char table
Definition: types.h:34