NeoMutt  2022-04-29-145-g9b6a0e
Teaching an old dog new tricks
DOXYGEN
number.c
Go to the documentation of this file.
1 
33 #include "config.h"
34 #include <stddef.h>
35 #include <limits.h>
36 #include <stdint.h>
37 #include "mutt/lib.h"
38 #include "set.h"
39 #include "types.h"
40 
44 static int number_string_set(const struct ConfigSet *cs, void *var, struct ConfigDef *cdef,
45  const char *value, struct Buffer *err)
46 {
47  if (!value || (value[0] == '\0'))
48  {
49  mutt_buffer_printf(err, _("Option %s may not be empty"), cdef->name);
51  }
52 
53  int num = 0;
54  if (!mutt_str_atoi_full(value, &num))
55  {
56  mutt_buffer_printf(err, _("Invalid number: %s"), value);
58  }
59 
60  if ((num < SHRT_MIN) || (num > SHRT_MAX))
61  {
62  mutt_buffer_printf(err, _("Number is too big: %s"), value);
64  }
65 
66  if ((num < 0) && (cdef->type & DT_NOT_NEGATIVE))
67  {
68  mutt_buffer_printf(err, _("Option %s may not be negative"), cdef->name);
70  }
71 
72  if (var)
73  {
74  if (num == (*(short *) var))
76 
77  if (cdef->validator)
78  {
79  int rc = cdef->validator(cs, cdef, (intptr_t) num, err);
80 
81  if (CSR_RESULT(rc) != CSR_SUCCESS)
82  return rc | CSR_INV_VALIDATOR;
83  }
84 
85  *(short *) var = num;
86  }
87  else
88  {
89  cdef->initial = num;
90  }
91 
92  return CSR_SUCCESS;
93 }
94 
98 static int number_string_get(const struct ConfigSet *cs, void *var,
99  const struct ConfigDef *cdef, struct Buffer *result)
100 {
101  int value;
102 
103  if (var)
104  value = *(short *) var;
105  else
106  value = (int) cdef->initial;
107 
108  mutt_buffer_printf(result, "%d", value);
109  return CSR_SUCCESS;
110 }
111 
115 static int number_native_set(const struct ConfigSet *cs, void *var,
116  const struct ConfigDef *cdef, intptr_t value,
117  struct Buffer *err)
118 {
119  if ((value < SHRT_MIN) || (value > SHRT_MAX))
120  {
121  mutt_buffer_printf(err, _("Invalid number: %ld"), value);
122  return CSR_ERR_INVALID | CSR_INV_TYPE;
123  }
124 
125  if ((value < 0) && (cdef->type & DT_NOT_NEGATIVE))
126  {
127  mutt_buffer_printf(err, _("Option %s may not be negative"), cdef->name);
129  }
130 
131  if (value == (*(short *) var))
133 
134  if (cdef->validator)
135  {
136  int rc = cdef->validator(cs, cdef, value, err);
137 
138  if (CSR_RESULT(rc) != CSR_SUCCESS)
139  return rc | CSR_INV_VALIDATOR;
140  }
141 
142  *(short *) var = value;
143  return CSR_SUCCESS;
144 }
145 
149 static intptr_t number_native_get(const struct ConfigSet *cs, void *var,
150  const struct ConfigDef *cdef, struct Buffer *err)
151 {
152  return *(short *) var;
153 }
154 
158 static int number_string_plus_equals(const struct ConfigSet *cs, void *var,
159  const struct ConfigDef *cdef,
160  const char *value, struct Buffer *err)
161 {
162  int num = 0;
163  if (!mutt_str_atoi_full(value, &num))
164  {
165  mutt_buffer_printf(err, _("Invalid number: %s"), NONULL(value));
166  return CSR_ERR_INVALID | CSR_INV_TYPE;
167  }
168 
169  int result = *((short *) var) + num;
170  if ((result < SHRT_MIN) || (result > SHRT_MAX))
171  {
172  mutt_buffer_printf(err, _("Number is too big: %s"), value);
173  return CSR_ERR_INVALID | CSR_INV_TYPE;
174  }
175 
176  if ((result < 0) && (cdef->type & DT_NOT_NEGATIVE))
177  {
178  mutt_buffer_printf(err, _("Option %s may not be negative"), cdef->name);
180  }
181 
182  if (cdef->validator)
183  {
184  int rc = cdef->validator(cs, cdef, (intptr_t) result, err);
185 
186  if (CSR_RESULT(rc) != CSR_SUCCESS)
187  return rc | CSR_INV_VALIDATOR;
188  }
189 
190  *(short *) var = result;
191  return CSR_SUCCESS;
192 }
193 
197 static int number_string_minus_equals(const struct ConfigSet *cs, void *var,
198  const struct ConfigDef *cdef,
199  const char *value, struct Buffer *err)
200 {
201  int num = 0;
202  if (!mutt_str_atoi(value, &num))
203  {
204  mutt_buffer_printf(err, _("Invalid number: %s"), NONULL(value));
205  return CSR_ERR_INVALID | CSR_INV_TYPE;
206  }
207 
208  int result = *((short *) var) - num;
209  if ((result < SHRT_MIN) || (result > SHRT_MAX))
210  {
211  mutt_buffer_printf(err, _("Number is too big: %s"), value);
212  return CSR_ERR_INVALID | CSR_INV_TYPE;
213  }
214 
215  if ((result < 0) && (cdef->type & DT_NOT_NEGATIVE))
216  {
217  mutt_buffer_printf(err, _("Option %s may not be negative"), cdef->name);
219  }
220 
221  if (cdef->validator)
222  {
223  int rc = cdef->validator(cs, cdef, (intptr_t) result, err);
224 
225  if (CSR_RESULT(rc) != CSR_SUCCESS)
226  return rc | CSR_INV_VALIDATOR;
227  }
228 
229  *(short *) var = result;
230  return CSR_SUCCESS;
231 }
232 
236 static int number_reset(const struct ConfigSet *cs, void *var,
237  const struct ConfigDef *cdef, struct Buffer *err)
238 {
239  if (cdef->initial == (*(short *) var))
241 
242  if (cdef->validator)
243  {
244  int rc = cdef->validator(cs, cdef, cdef->initial, err);
245 
246  if (CSR_RESULT(rc) != CSR_SUCCESS)
247  return rc | CSR_INV_VALIDATOR;
248  }
249 
250  *(short *) var = cdef->initial;
251  return CSR_SUCCESS;
252 }
253 
257 const struct ConfigSetType CstNumber = {
258  DT_NUMBER,
259  "number",
266  number_reset,
267  NULL, // destroy
268 };
const char * mutt_str_atoi(const char *str, int *dst)
Convert ASCII string to an integer.
Definition: atoi.c:178
int mutt_buffer_printf(struct Buffer *buf, const char *fmt,...)
Format a string overwriting a Buffer.
Definition: buffer.c:158
static intptr_t number_native_get(const struct ConfigSet *cs, void *var, const struct ConfigDef *cdef, struct Buffer *err)
Get an int from a Number config item - Implements ConfigSetType::native_get() -.
Definition: number.c:149
static int number_native_set(const struct ConfigSet *cs, void *var, const struct ConfigDef *cdef, intptr_t value, struct Buffer *err)
Set a Number config item by int - Implements ConfigSetType::native_set() -.
Definition: number.c:115
static int number_reset(const struct ConfigSet *cs, void *var, const struct ConfigDef *cdef, struct Buffer *err)
Reset a Number to its initial value - Implements ConfigSetType::reset() -.
Definition: number.c:236
static int number_string_get(const struct ConfigSet *cs, void *var, const struct ConfigDef *cdef, struct Buffer *result)
Get a Number as a string - Implements ConfigSetType::string_get() -.
Definition: number.c:98
static int number_string_minus_equals(const struct ConfigSet *cs, void *var, const struct ConfigDef *cdef, const char *value, struct Buffer *err)
Subtract from a Number by string - Implements ConfigSetType::string_minus_equals() -.
Definition: number.c:197
static int number_string_plus_equals(const struct ConfigSet *cs, void *var, const struct ConfigDef *cdef, const char *value, struct Buffer *err)
Add to a Number by string - Implements ConfigSetType::string_plus_equals() -.
Definition: number.c:158
static int number_string_set(const struct ConfigSet *cs, void *var, struct ConfigDef *cdef, const char *value, struct Buffer *err)
Set a Number by string - Implements ConfigSetType::string_set() -.
Definition: number.c:44
Convenience wrapper for the library headers.
#define _(a)
Definition: message.h:28
const struct ConfigSetType CstNumber
Config type representing a number.
Definition: number.c:257
A collection of config items.
#define CSR_ERR_INVALID
Value hasn't been set.
Definition: set.h:38
#define CSR_INV_TYPE
Value is not valid for the type.
Definition: set.h:47
#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_SUCCESS
Action completed successfully.
Definition: set.h:35
#define NONULL(x)
Definition: string2.h:37
String manipulation buffer.
Definition: buffer.h:34
Definition: set.h:64
const char * name
User-visible name.
Definition: set.h:65
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:260
Constants for all the config types.
#define DT_NOT_NEGATIVE
Negative numbers are not allowed.
Definition: types.h:47
#define DT_NUMBER
a number
Definition: types.h:35