NeoMutt  2023-11-03-85-g512e01
Teaching an old dog new tricks
DOXYGEN
Loading...
Searching...
No Matches
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
50bool mbtable_equal(const struct MbTable *a, const struct MbTable *b)
51{
52 if (!a && !b) /* both empty */
53 return true;
54 if (!a ^ !b) /* one is empty, but not the other */
55 return false;
56
57 return mutt_str_equal(a->orig_str, b->orig_str);
58}
59
65struct MbTable *mbtable_parse(const char *s)
66{
67 struct MbTable *t = NULL;
68 size_t slen, k;
69 mbstate_t mbstate = { 0 };
70 char *d = NULL;
71
72 slen = mutt_str_len(s);
73 if (!slen)
74 return NULL;
75
76 t = mutt_mem_calloc(1, sizeof(struct MbTable));
77
78 t->orig_str = mutt_str_dup(s);
79 /* This could be more space efficient. However, being used on tiny
80 * strings (`$to_chars` and `$status_chars`), the overhead is not great. */
81 t->chars = mutt_mem_calloc(slen, sizeof(char *));
82 t->segmented_str = mutt_mem_calloc(slen * 2, sizeof(char));
83 d = t->segmented_str;
84
85 while (slen && (k = mbrtowc(NULL, s, slen, &mbstate)))
86 {
87 if ((k == ICONV_ILLEGAL_SEQ) || (k == ICONV_BUF_TOO_SMALL))
88 {
89 /* XXX put message in err buffer; fail? warning? */
90 mutt_debug(LL_DEBUG1, "mbrtowc returned %zd converting %s in %s\n", k, s, t->orig_str);
91 if (k == ICONV_ILLEGAL_SEQ)
92 memset(&mbstate, 0, sizeof(mbstate));
93 k = (k == ICONV_ILLEGAL_SEQ) ? 1 : slen;
94 }
95
96 slen -= k;
97 t->chars[t->len++] = d;
98 while (k--)
99 *d++ = *s++;
100 *d++ = '\0';
101 }
102
103 return t;
104}
105
109static void mbtable_destroy(const struct ConfigSet *cs, void *var, const struct ConfigDef *cdef)
110{
111 struct MbTable **m = var;
112 if (!*m)
113 return;
114
115 mbtable_free(m);
116}
117
121static int mbtable_string_set(const struct ConfigSet *cs, void *var, struct ConfigDef *cdef,
122 const char *value, struct Buffer *err)
123{
124 /* Store empty mbtables as NULL */
125 if (value && (value[0] == '\0'))
126 value = NULL;
127
128 struct MbTable *table = NULL;
129
130 int rc = CSR_SUCCESS;
131
132 if (var)
133 {
134 struct MbTable *curval = *(struct MbTable **) var;
135 if (curval && mutt_str_equal(value, curval->orig_str))
137
138 if (startup_only(cdef, err))
140
141 table = mbtable_parse(value);
142
143 if (cdef->validator)
144 {
145 rc = cdef->validator(cs, cdef, (intptr_t) table, err);
146
147 if (CSR_RESULT(rc) != CSR_SUCCESS)
148 {
149 mbtable_free(&table);
150 return rc | CSR_INV_VALIDATOR;
151 }
152 }
153
154 mbtable_destroy(cs, var, cdef);
155
156 *(struct MbTable **) var = table;
157
158 if (!table)
159 rc |= CSR_SUC_EMPTY;
160 }
161 else
162 {
163 if (cdef->type & DT_INITIAL_SET)
164 FREE(&cdef->initial);
165
166 cdef->type |= DT_INITIAL_SET;
167 cdef->initial = (intptr_t) mutt_str_dup(value);
168 }
169
170 return rc;
171}
172
176static int mbtable_string_get(const struct ConfigSet *cs, void *var,
177 const struct ConfigDef *cdef, struct Buffer *result)
178{
179 const char *str = NULL;
180
181 if (var)
182 {
183 struct MbTable *table = *(struct MbTable **) var;
184 if (!table || !table->orig_str)
185 return CSR_SUCCESS | CSR_SUC_EMPTY; /* empty string */
186 str = table->orig_str;
187 }
188 else
189 {
190 str = (char *) cdef->initial;
191 }
192
193 buf_addstr(result, str);
194 return CSR_SUCCESS;
195}
196
202static struct MbTable *mbtable_dup(struct MbTable *table)
203{
204 if (!table)
205 return NULL; /* LCOV_EXCL_LINE */
206
207 struct MbTable *m = mutt_mem_calloc(1, sizeof(*m));
208 m->orig_str = mutt_str_dup(table->orig_str);
209 return m;
210}
211
215static int mbtable_native_set(const struct ConfigSet *cs, void *var,
216 const struct ConfigDef *cdef, intptr_t value,
217 struct Buffer *err)
218{
219 int rc;
220
221 if (mbtable_equal(*(struct MbTable **) var, (struct MbTable *) value))
223
224 if (startup_only(cdef, err))
226
227 if (cdef->validator)
228 {
229 rc = cdef->validator(cs, cdef, value, err);
230
231 if (CSR_RESULT(rc) != CSR_SUCCESS)
232 return rc | CSR_INV_VALIDATOR;
233 }
234
235 mbtable_free(var);
236
237 struct MbTable *table = mbtable_dup((struct MbTable *) value);
238
239 rc = CSR_SUCCESS;
240 if (!table)
241 rc |= CSR_SUC_EMPTY;
242
243 *(struct MbTable **) var = table;
244 return rc;
245}
246
250static intptr_t mbtable_native_get(const struct ConfigSet *cs, void *var,
251 const struct ConfigDef *cdef, struct Buffer *err)
252{
253 struct MbTable *table = *(struct MbTable **) var;
254
255 return (intptr_t) table;
256}
257
261static int mbtable_reset(const struct ConfigSet *cs, void *var,
262 const struct ConfigDef *cdef, struct Buffer *err)
263{
264 struct MbTable *table = NULL;
265 const char *initial = (const char *) cdef->initial;
266
267 struct MbTable *curtable = *(struct MbTable **) var;
268 const char *curval = curtable ? curtable->orig_str : NULL;
269
270 int rc = CSR_SUCCESS;
271 if (!curtable)
272 rc |= CSR_SUC_EMPTY;
273
274 if (mutt_str_equal(initial, curval))
275 return rc | CSR_SUC_NO_CHANGE;
276
277 if (startup_only(cdef, err))
279
280 if (initial)
281 table = mbtable_parse(initial);
282
283 if (cdef->validator)
284 {
285 rc = cdef->validator(cs, cdef, (intptr_t) table, err);
286
287 if (CSR_RESULT(rc) != CSR_SUCCESS)
288 {
289 mbtable_destroy(cs, &table, cdef);
290 return rc | CSR_INV_VALIDATOR;
291 }
292 }
293
294 if (!table)
295 rc |= CSR_SUC_EMPTY;
296
297 mbtable_destroy(cs, var, cdef);
298
299 *(struct MbTable **) var = table;
300 return rc;
301}
302
307void mbtable_free(struct MbTable **ptr)
308{
309 if (!ptr || !*ptr)
310 return;
311
312 struct MbTable *table = *ptr;
313 FREE(&table->orig_str);
314 FREE(&table->chars);
315 FREE(&table->segmented_str);
316
317 FREE(ptr);
318}
319
330const char *mbtable_get_nth_wchar(const struct MbTable *table, int index)
331{
332 if (!table || !table->chars || (index < 0) || (index >= table->len))
333 return " ";
334
335 if (table->chars[index][0] == '\r')
336 return "";
337
338 return table->chars[index];
339}
340
344const struct ConfigSetType CstMbtable = {
346 "mbtable",
351 NULL, // string_plus_equals
352 NULL, // string_minus_equals
355};
size_t buf_addstr(struct Buffer *buf, const char *s)
Add a string to a Buffer.
Definition: buffer.c:238
static bool startup_only(const struct ConfigDef *cdef, struct Buffer *err)
Validator function for DT_ON_STARTUP.
Definition: set.h:301
#define CSR_ERR_INVALID
Value hasn't been set.
Definition: set.h:38
#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:109
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:250
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:215
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:261
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:176
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:121
#define mutt_debug(LEVEL,...)
Definition: logging2.h:89
@ LL_DEBUG1
Log at debug level 1.
Definition: logging2.h:43
bool mbtable_equal(const struct MbTable *a, const struct MbTable *b)
Compare two MbTables.
Definition: mbtable.c:50
static struct MbTable * mbtable_dup(struct MbTable *table)
Create a copy of an MbTable object.
Definition: mbtable.c:202
struct MbTable * mbtable_parse(const char *s)
Parse a multibyte string into a table.
Definition: mbtable.c:65
const char * mbtable_get_nth_wchar(const struct MbTable *table, int index)
Extract one char from a multi-byte table.
Definition: mbtable.c:330
void mbtable_free(struct MbTable **ptr)
Free an MbTable object.
Definition: mbtable.c:307
const struct ConfigSetType CstMbtable
Config type representing a multi-byte table.
Definition: mbtable.c:344
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:45
#define ICONV_BUF_TOO_SMALL
Error value for iconv() - Buffer too small.
Definition: charset.h:105
#define ICONV_ILLEGAL_SEQ
Error value for iconv() - Illegal sequence.
Definition: charset.h:103
Convenience wrapper for the library headers.
char * mutt_str_dup(const char *str)
Copy a string, safely.
Definition: string.c:251
bool mutt_str_equal(const char *a, const char *b)
Compare two strings.
Definition: string.c:798
size_t mutt_str_len(const char *a)
Calculate the length of a string, safely.
Definition: string.c:568
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:36
char * orig_str
Original string used to generate this object.
Definition: mbtable.h:37
int len
Number of characters.
Definition: mbtable.h:38
char ** chars
The array of multibyte character strings.
Definition: mbtable.h:39
char * segmented_str
Each chars entry points inside this string.
Definition: mbtable.h:40
Constants for all the config types.
#define DT_INITIAL_SET
Config item must have its initial value freed.
Definition: types.h:80
#define DT_MBTABLE
multibyte char table
Definition: types.h:34