Line data Source code
1 : /**
2 : * @file
3 : * Type representing an enumeration
4 : *
5 : * @authors
6 : * Copyright (C) 2018 Richard Russon <rich@flatcap.org>
7 : *
8 : * @copyright
9 : * This program is free software: you can redistribute it and/or modify it under
10 : * the terms of the GNU General Public License as published by the Free Software
11 : * Foundation, either version 2 of the License, or (at your option) any later
12 : * version.
13 : *
14 : * This program is distributed in the hope that it will be useful, but WITHOUT
15 : * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
16 : * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
17 : * details.
18 : *
19 : * You should have received a copy of the GNU General Public License along with
20 : * this program. If not, see <http://www.gnu.org/licenses/>.
21 : */
22 :
23 : /**
24 : * @page config_enum Type: Enumeration
25 : *
26 : * Config type representing an enumeration.
27 : *
28 : * - Backed by `unsigned char`
29 : * - Validator is passed `unsigned char`
30 : * - Implementation: #CstEnum
31 : */
32 :
33 : #include "config.h"
34 : #include <stddef.h>
35 : #include <limits.h>
36 : #include <stdint.h>
37 : #include "mutt/lib.h"
38 : #include "enum.h"
39 : #include "set.h"
40 : #include "types.h"
41 :
42 : /**
43 : * enum_string_set - Set an Enumeration by string - Implements ConfigSetType::string_set() - @ingroup cfg_type_string_set
44 : */
45 34 : static int enum_string_set(const struct ConfigSet *cs, void *var, struct ConfigDef *cdef,
46 : const char *value, struct Buffer *err)
47 : {
48 34 : if (!cs || !cdef || !value)
49 : return CSR_ERR_CODE; /* LCOV_EXCL_LINE */
50 :
51 32 : struct EnumDef *ed = (struct EnumDef *) cdef->data;
52 32 : if (!ed || !ed->lookup)
53 2 : return CSR_ERR_CODE;
54 :
55 30 : int num = mutt_map_get_value(value, ed->lookup);
56 30 : if (num < 0)
57 : {
58 4 : mutt_buffer_printf(err, _("Invalid enum value: %s"), value);
59 4 : return (CSR_ERR_INVALID | CSR_INV_TYPE);
60 : }
61 :
62 26 : if (var)
63 : {
64 24 : if (num == (*(unsigned char *) var))
65 2 : return (CSR_SUCCESS | CSR_SUC_NO_CHANGE);
66 :
67 22 : if (cdef->validator)
68 : {
69 8 : int rc = cdef->validator(cs, cdef, (intptr_t) num, err);
70 :
71 8 : if (CSR_RESULT(rc) != CSR_SUCCESS)
72 2 : return (rc | CSR_INV_VALIDATOR);
73 : }
74 :
75 20 : *(unsigned char *) var = num;
76 : }
77 : else
78 : {
79 2 : cdef->initial = num;
80 : }
81 :
82 22 : return CSR_SUCCESS;
83 : }
84 :
85 : /**
86 : * enum_string_get - Get an Enumeration as a string - Implements ConfigSetType::string_get() - @ingroup cfg_type_string_get
87 : */
88 54 : static int enum_string_get(const struct ConfigSet *cs, void *var,
89 : const struct ConfigDef *cdef, struct Buffer *result)
90 : {
91 54 : if (!cs || !cdef)
92 : return CSR_ERR_CODE; /* LCOV_EXCL_LINE */
93 :
94 : unsigned int value;
95 :
96 54 : if (var)
97 44 : value = *(unsigned char *) var;
98 : else
99 10 : value = (int) cdef->initial;
100 :
101 54 : struct EnumDef *ed = (struct EnumDef *) cdef->data;
102 54 : if (!ed || !ed->lookup)
103 2 : return CSR_ERR_CODE;
104 :
105 52 : const char *name = mutt_map_get_name(value, ed->lookup);
106 52 : if (!name)
107 : {
108 4 : mutt_debug(LL_DEBUG1, "Variable has an invalid value: %d\n", value);
109 4 : return (CSR_ERR_INVALID | CSR_INV_TYPE);
110 : }
111 :
112 48 : mutt_buffer_addstr(result, name);
113 48 : return CSR_SUCCESS;
114 : }
115 :
116 : /**
117 : * enum_native_set - Set an Enumeration config item by int - Implements ConfigSetType::native_set() - @ingroup cfg_type_native_set
118 : */
119 56 : static int enum_native_set(const struct ConfigSet *cs, void *var,
120 : const struct ConfigDef *cdef, intptr_t value, struct Buffer *err)
121 : {
122 56 : if (!cs || !var || !cdef)
123 : return CSR_ERR_CODE; /* LCOV_EXCL_LINE */
124 :
125 56 : struct EnumDef *ed = (struct EnumDef *) cdef->data;
126 56 : if (!ed || !ed->lookup)
127 2 : return CSR_ERR_CODE;
128 :
129 54 : const char *name = mutt_map_get_name(value, ed->lookup);
130 54 : if (!name)
131 : {
132 22 : mutt_buffer_printf(err, _("Invalid enum value: %ld"), value);
133 22 : return (CSR_ERR_INVALID | CSR_INV_TYPE);
134 : }
135 :
136 32 : if (value == (*(unsigned char *) var))
137 8 : return (CSR_SUCCESS | CSR_SUC_NO_CHANGE);
138 :
139 24 : if (cdef->validator)
140 : {
141 6 : int rc = cdef->validator(cs, cdef, value, err);
142 :
143 6 : if (CSR_RESULT(rc) != CSR_SUCCESS)
144 2 : return (rc | CSR_INV_VALIDATOR);
145 : }
146 :
147 22 : *(unsigned char *) var = value;
148 22 : return CSR_SUCCESS;
149 : }
150 :
151 : /**
152 : * enum_native_get - Get an int object from an Enumeration config item - Implements ConfigSetType::native_get() - @ingroup cfg_type_native_get
153 : */
154 68 : static intptr_t enum_native_get(const struct ConfigSet *cs, void *var,
155 : const struct ConfigDef *cdef, struct Buffer *err)
156 : {
157 68 : if (!cs || !var || !cdef)
158 : return INT_MIN; /* LCOV_EXCL_LINE */
159 :
160 68 : return *(unsigned char *) var;
161 : }
162 :
163 : /**
164 : * enum_reset - Reset an Enumeration to its initial value - Implements ConfigSetType::reset() - @ingroup cfg_type_reset
165 : */
166 46 : static int enum_reset(const struct ConfigSet *cs, void *var,
167 : const struct ConfigDef *cdef, struct Buffer *err)
168 : {
169 46 : if (!cs || !var || !cdef)
170 : return CSR_ERR_CODE; /* LCOV_EXCL_LINE */
171 :
172 46 : if (cdef->initial == (*(unsigned char *) var))
173 8 : return (CSR_SUCCESS | CSR_SUC_NO_CHANGE);
174 :
175 38 : if (cdef->validator)
176 : {
177 10 : int rc = cdef->validator(cs, cdef, cdef->initial, err);
178 :
179 10 : if (CSR_RESULT(rc) != CSR_SUCCESS)
180 6 : return (rc | CSR_INV_VALIDATOR);
181 : }
182 :
183 32 : *(unsigned char *) var = cdef->initial;
184 32 : return CSR_SUCCESS;
185 : }
186 :
187 : /**
188 : * CstEnum - Config type representing an enumeration
189 : */
190 : const struct ConfigSetType CstEnum = {
191 : DT_ENUM,
192 : "enum",
193 : enum_string_set,
194 : enum_string_get,
195 : enum_native_set,
196 : enum_native_get,
197 : NULL, // string_plus_equals
198 : NULL, // string_minus_equals
199 : enum_reset,
200 : NULL, // destroy
201 : };
|