Coverage Report

Created: 2023-06-07 06:15

/src/neomutt/config/bool.c
Line
Count
Source (jump to first uncovered line)
1
/**
2
 * @file
3
 * Type representing a boolean
4
 *
5
 * @authors
6
 * Copyright (C) 2017-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_bool Type: Boolean
25
 *
26
 * Config type representing a boolean.
27
 *
28
 * - Backed by `bool`
29
 * - Validator is passed `bool`
30
 * - Valid user entry: #BoolValues
31
 * - Implementation: #CstBool
32
 */
33
34
#include "config.h"
35
#include <stddef.h>
36
#include <limits.h>
37
#include <stdbool.h>
38
#include <stdint.h>
39
#include "mutt/lib.h"
40
#include "bool.h"
41
#include "set.h"
42
#include "subset.h"
43
#include "types.h"
44
45
/**
46
 * BoolValues - Valid strings for creating a Bool
47
 *
48
 * These strings are case-insensitive.
49
 */
50
const char *BoolValues[] = {
51
  "no", "yes", "n", "y", "false", "true", "0", "1", "off", "on", NULL,
52
};
53
54
/**
55
 * bool_string_set - Set a Bool by string - Implements ConfigSetType::string_set() - @ingroup cfg_type_string_set
56
 */
57
static int bool_string_set(const struct ConfigSet *cs, void *var, struct ConfigDef *cdef,
58
                           const char *value, struct Buffer *err)
59
0
{
60
0
  if (!value)
61
0
    return CSR_ERR_CODE; /* LCOV_EXCL_LINE */
62
63
0
  int num = -1;
64
0
  for (size_t i = 0; BoolValues[i]; i++)
65
0
  {
66
0
    if (mutt_istr_equal(BoolValues[i], value))
67
0
    {
68
0
      num = i % 2;
69
0
      break;
70
0
    }
71
0
  }
72
73
0
  if (num < 0)
74
0
  {
75
0
    buf_printf(err, _("Invalid boolean value: %s"), value);
76
0
    return CSR_ERR_INVALID | CSR_INV_TYPE;
77
0
  }
78
79
0
  if (var)
80
0
  {
81
0
    if (num == (*(bool *) var))
82
0
      return CSR_SUCCESS | CSR_SUC_NO_CHANGE;
83
84
0
    if (cdef->validator)
85
0
    {
86
0
      int rc = cdef->validator(cs, cdef, (intptr_t) num, err);
87
88
0
      if (CSR_RESULT(rc) != CSR_SUCCESS)
89
0
        return rc | CSR_INV_VALIDATOR;
90
0
    }
91
92
0
    *(bool *) var = num;
93
0
  }
94
0
  else
95
0
  {
96
0
    cdef->initial = num;
97
0
  }
98
99
0
  return CSR_SUCCESS;
100
0
}
101
102
/**
103
 * bool_string_get - Get a Bool as a string - Implements ConfigSetType::string_get() - @ingroup cfg_type_string_get
104
 */
105
static int bool_string_get(const struct ConfigSet *cs, void *var,
106
                           const struct ConfigDef *cdef, struct Buffer *result)
107
0
{
108
0
  int index;
109
110
0
  if (var)
111
0
    index = *(bool *) var;
112
0
  else
113
0
    index = (int) cdef->initial;
114
115
0
  if (index > 1)
116
0
    return CSR_ERR_INVALID | CSR_INV_TYPE; /* LCOV_EXCL_LINE */
117
118
0
  buf_addstr(result, BoolValues[index]);
119
0
  return CSR_SUCCESS;
120
0
}
121
122
/**
123
 * bool_native_set - Set a Bool config item by bool - Implements ConfigSetType::native_set() - @ingroup cfg_type_native_set
124
 */
125
static int bool_native_set(const struct ConfigSet *cs, void *var,
126
                           const struct ConfigDef *cdef, intptr_t value, struct Buffer *err)
127
0
{
128
0
  if ((value < 0) || (value > 1))
129
0
  {
130
0
    buf_printf(err, _("Invalid boolean value: %ld"), value);
131
0
    return CSR_ERR_INVALID | CSR_INV_TYPE;
132
0
  }
133
134
0
  if (value == (*(bool *) var))
135
0
    return CSR_SUCCESS | CSR_SUC_NO_CHANGE;
136
137
0
  if (cdef->validator)
138
0
  {
139
0
    int rc = cdef->validator(cs, cdef, value, err);
140
141
0
    if (CSR_RESULT(rc) != CSR_SUCCESS)
142
0
      return rc | CSR_INV_VALIDATOR;
143
0
  }
144
145
0
  *(bool *) var = value;
146
0
  return CSR_SUCCESS;
147
0
}
148
149
/**
150
 * bool_native_get - Get a bool from a Bool config item - Implements ConfigSetType::native_get() - @ingroup cfg_type_native_get
151
 */
152
static intptr_t bool_native_get(const struct ConfigSet *cs, void *var,
153
                                const struct ConfigDef *cdef, struct Buffer *err)
154
78.5k
{
155
78.5k
  return *(bool *) var;
156
78.5k
}
157
158
/**
159
 * bool_reset - Reset a Bool to its initial value - Implements ConfigSetType::reset() - @ingroup cfg_type_reset
160
 */
161
static int bool_reset(const struct ConfigSet *cs, void *var,
162
                      const struct ConfigDef *cdef, struct Buffer *err)
163
1.82M
{
164
1.82M
  if (cdef->initial == (*(bool *) var))
165
1.82M
    return CSR_SUCCESS | CSR_SUC_NO_CHANGE;
166
167
83
  if (cdef->validator)
168
0
  {
169
0
    int rc = cdef->validator(cs, cdef, cdef->initial, err);
170
171
0
    if (CSR_RESULT(rc) != CSR_SUCCESS)
172
0
      return rc | CSR_INV_VALIDATOR;
173
0
  }
174
175
83
  *(bool *) var = cdef->initial;
176
83
  return CSR_SUCCESS;
177
83
}
178
179
/**
180
 * bool_he_toggle - Toggle the value of a bool
181
 * @param sub Config Subset
182
 * @param he  HashElem representing config item
183
 * @param err Buffer for error messages
184
 * @retval num Result, e.g. #CSR_SUCCESS
185
 */
186
int bool_he_toggle(struct ConfigSubset *sub, struct HashElem *he, struct Buffer *err)
187
0
{
188
0
  if (!sub || !he || !he->data)
189
0
    return CSR_ERR_CODE;
190
191
0
  struct HashElem *he_base = cs_get_base(he);
192
0
  if (DTYPE(he_base->type) != DT_BOOL)
193
0
    return CSR_ERR_CODE;
194
195
0
  intptr_t value = cs_he_native_get(sub->cs, he, err);
196
0
  if (value == INT_MIN)
197
0
    return CSR_ERR_CODE;
198
199
0
  int rc = cs_he_native_set(sub->cs, he, !value, err);
200
201
0
  if ((CSR_RESULT(rc) == CSR_SUCCESS) && !(rc & CSR_SUC_NO_CHANGE))
202
0
    cs_subset_notify_observers(sub, he, NT_CONFIG_SET);
203
204
0
  return rc;
205
0
}
206
207
/**
208
 * bool_str_toggle - Toggle the value of a bool
209
 * @param sub  Config Subset
210
 * @param name Name of config item
211
 * @param err  Buffer for error messages
212
 * @retval num Result, e.g. #CSR_SUCCESS
213
 */
214
int bool_str_toggle(struct ConfigSubset *sub, const char *name, struct Buffer *err)
215
0
{
216
0
  struct HashElem *he = cs_subset_create_inheritance(sub, name);
217
218
0
  return bool_he_toggle(sub, he, err);
219
0
}
220
221
/**
222
 * CstBool - Config type representing an boolean
223
 */
224
const struct ConfigSetType CstBool = {
225
  DT_BOOL,
226
  "boolean",
227
  bool_string_set,
228
  bool_string_get,
229
  bool_native_set,
230
  bool_native_get,
231
  NULL, // string_plus_equals
232
  NULL, // string_minus_equals
233
  bool_reset,
234
  NULL, // destroy
235
};