MiKTeX 26.5-next
A scalable TeX distribution
Loading...
Searching...
No Matches
ConfigValue.h
Go to the documentation of this file.
1
13
14#pragma once
15
16#include <miktex/Configuration/config.h>
17
18#include <climits>
19#include <ctime>
20
21#include <exception>
22#include <string>
23#include <vector>
24
25#include <miktex/Util/PathNameUtil>
26#include <miktex/Util/StringUtil>
27
28#include "TriState.h"
29
30MIKTEX_CONFIG_BEGIN_NAMESPACE;
31
32class Exception :
33 public std::exception
34{
35
36public:
37
38 Exception(const std::string& msg) :
39 msg(msg)
40 {
41 }
42
43 const char* what() const noexcept override
44 {
45 return msg.c_str();
46 }
47
48private:
49
50 std::string msg;
51};
52
53class ConfigurationError :
55{
56
57public:
58
59 ConfigurationError(const std::string& msg) :
60 Exception("Configuration error: " + msg)
61 {
62 }
63};
64
65
67class ConfigValue
68{
69
70public:
71
72 ConfigValue()
73 {
74 };
75
76 ConfigValue(const ConfigValue& other)
77 {
78 switch (other.type)
79 {
80 case Type::String:
81 new (&this->s) std::string(other.s);
82 break;
83 case Type::Int:
84 this->i = other.i;
85 break;
86 case Type::Bool:
87 this->b = other.b;
88 break;
89 case Type::Tri:
90 this->t = other.t;
91 break;
92 case Type::Char:
93 this->c = other.c;
94 break;
95 case Type::StringArray:
96 new (&this->sa) std::vector<std::string>(other.sa);
97 break;
98 case Type::None:
99 break;
100 }
101 this->type = other.type;
102 this->section = other.section;
103 this->description = other.description;
104 }
105
106 ConfigValue& operator=(const ConfigValue& other) = delete;
107
108 ConfigValue(ConfigValue&& other) noexcept
109 {
110 switch (other.type)
111 {
112 case Type::String:
113 new (&this->s) std::string(other.s);
114 this->s = std::move(other.s);
115 break;
116 case Type::Int:
117 this->i = other.i;
118 break;
119 case Type::Bool:
120 this->b = other.b;
121 break;
122 case Type::Tri:
123 this->t = other.t;
124 break;
125 case Type::Char:
126 this->c = other.c;
127 break;
128 case Type::StringArray:
129 new (&this->sa) std::vector<std::string>(other.sa);
130 this->sa = std::move(other.sa);
131 break;
132 case Type::None:
133 break;
134 }
135 this->type = other.type;
136 this->section = other.section;
137 }
138
139 ConfigValue& operator=(ConfigValue&& other) noexcept
140 {
141 if (this->type == Type::String && other.type != Type::String)
142 {
143 this->s.~basic_string();
144 }
145 else if (this->type == Type::StringArray && other.type != Type::StringArray)
146 {
147 this->sa.~vector();
148 }
149 switch (other.type)
150 {
151 case Type::String:
152 if (this->type != Type::String)
153 {
154 new (&this->s) std::string(other.s);
155 }
156 this->s = std::move(other.s);
157 break;
158 case Type::Int:
159 this->i = other.i;
160 break;
161 case Type::Bool:
162 this->b = other.b;
163 break;
164 case Type::Tri:
165 this->t = other.t;
166 break;
167 case Type::Char:
168 this->c = other.c;
169 break;
170 case Type::StringArray:
171 if (this->type != Type::StringArray)
172 {
173 new (&this->sa) std::vector<std::string>(other.sa);
174 }
175 this->sa = std::move(other.sa);
176 break;
177 case Type::None:
178 break;
179 }
180 this->type = other.type;
181 this->section = other.section;
182 return *this;
183 }
184
185 virtual ~ConfigValue() noexcept
186 {
187 if (type == Type::String)
188 {
189 this->s.~basic_string();
190 }
191 else if (type == Type::StringArray)
192 {
193 this->sa.~vector();
194 }
195 type = Type::None;
196 }
197
198 explicit ConfigValue(const std::string& s)
199 {
200 new(&this->s) std::string(s);
201 type = Type::String;
202 }
203
204 explicit ConfigValue(const char* lpsz)
205 {
206 new(&this->s) std::string(lpsz == nullptr ? "" : lpsz);
207 type = Type::String;
208 }
209
210 explicit ConfigValue(int i)
211 {
212 this->i = i;
213 type = Type::Int;
214 }
215
216 explicit ConfigValue(bool b)
217 {
218 this->b = b;
219 type = Type::Bool;
220 }
221
222 explicit ConfigValue(TriState t)
223 {
224 this->t = t;
225 type = Type::Tri;
226 }
227
228 explicit ConfigValue(char c)
229 {
230 this->c = c;
231 type = Type::Char;
232 }
233
234 explicit ConfigValue(const std::vector<std::string>& sa)
235 {
236 new(&this->sa) std::vector<std::string>(sa);
237 type = Type::StringArray;
238 }
239
242 std::string GetString() const
243 {
244 switch (type)
245 {
246 case Type::String:
247 return this->s;
248 case Type::Int:
249 return std::to_string(this->i);
250 case Type::Bool:
251 return this->b ? "true" : "false";
252 case Type::Tri:
253 return this->t == TriState::Undetermined ? "undetermined" : this->t == TriState::False ? "false" : "true";
254 case Type::Char:
255 return std::string(1, this->c);
256 case Type::StringArray:
257 return MiKTeX::Util::StringUtil::Flatten(this->sa, MiKTeX::Util::PathNameUtil::PathNameDelimiter);
258 case Type::None:
259 throw ConfigurationError("no conversion from undefined configuration value to string.");
260 default:
261 throw ConfigurationError("no conversion to string from type: " + std::to_string(static_cast<int>(this->type)));
262 }
263 }
264
267 int GetInt() const
268 {
269 switch (type)
270 {
271 case Type::String:
272 return std::stoi(this->s);
273 case Type::Int:
274 return this->i;
275 case Type::Bool:
276 return (int)this->b;
277 case Type::Tri:
278 return (int)this->t;
279 case Type::Char:
280 return (int)this->c;
281 case Type::None:
282 throw ConfigurationError("no conversion from undefined configuration value to integer.");
283 default:
284 throw ConfigurationError("no conversion to integer from type: " + std::to_string(static_cast<int>(this->type)));
285 }
286 }
287
290 bool GetBool() const
291 {
292 switch (type)
293 {
294 case Type::String:
295 if (this->s == "0"
296 || this->s == "disable"
297 || this->s == "off"
298 || this->s == "f"
299 || this->s == "false"
300 || this->s == "n"
301 || this->s == "no")
302 {
303 return false;
304 }
305 else if (this->s == "1"
306 || this->s == "enable"
307 || this->s == "on"
308 || this->s == "t"
309 || this->s == "true"
310 || this->s == "y"
311 || this->s == "yes")
312 {
313 return true;
314 }
315 else
316 {
317 throw ConfigurationError("cannot convert to boolean from string: " + this->s);
318 }
319 case Type::Int:
320 if (this->i == 0)
321 {
322 return false;
323 }
324 else if (this->i == 1)
325 {
326 return true;
327 }
328 else
329 {
330 throw ConfigurationError("cannot convert to boolean from int: " + std::to_string(this->i));
331 }
332 case Type::Bool:
333 return this->b;
334 case Type::Tri:
335 if (this->t == TriState::False)
336 {
337 return false;
338 }
339 else if (this->t == TriState::True)
340 {
341 return true;
342 }
343 else
344 {
345 throw ConfigurationError("cannot convert to boolean from tri-state: " + std::to_string(static_cast<int>(this->t)));
346 }
347 case Type::Char:
348 if (this->c == '0'
349 || this->c == 'f'
350 || this->c == 'n')
351 {
352 return false;
353 }
354 else if (this->c == '1'
355 || this->c == 't'
356 || this->c == 'y')
357 {
358 return true;
359 }
360 else
361 {
362 throw ConfigurationError("cannot convert to boolean from char: " + std::string(1, this->c));
363 }
364 case Type::None:
365 throw ConfigurationError("no conversion from undefined configuration value to boolean.");
366 default:
367 throw ConfigurationError("no conversion to boolean from type: " + std::to_string(static_cast<int>(this->type)));
368 }
369 }
370
374 {
375 switch (type)
376 {
377 case Type::String:
378 if (this->s == "0"
379 || this->s == "disable"
380 || this->s == "off"
381 || this->s == "f"
382 || this->s == "false"
383 || this->s == "n"
384 || this->s == "no")
385 {
386 return TriState::False;
387 }
388 else if (this->s == "1"
389 || this->s == "enable"
390 || this->s == "on"
391 || this->s == "t"
392 || this->s == "true"
393 || this->s == "y"
394 || this->s == "yes")
395 {
396 return TriState::True;
397 }
398 else if (this->s == ""
399 || this->s == "2"
400 || this->s == "?"
401 || this->s == "undetermined")
402 {
404 }
405 else
406 {
407 throw ConfigurationError("cannot convert to tri-state from string: " + this->s);
408 }
409 case Type::Int:
410 if (this->i == 0)
411 {
412 return TriState::False;
413 }
414 else if (this->i == 1)
415 {
416 return TriState::True;
417 }
418 else if (this->i == 2)
419 {
421 }
422 else
423 {
424 throw ConfigurationError("cannot convert to tri-state from int: " + std::to_string(this->i));
425 }
426 case Type::Bool:
427 return this->b ? TriState::True : TriState::False;
428 case Type::Tri:
429 return this->t;
430 case Type::Char:
431 if (this->c == '0'
432 || this->c == 'f'
433 || this->c == 'n')
434 {
435 return TriState::False;
436 }
437 else if (this->c == '1'
438 || this->c == 't'
439 || this->c == 'y')
440 {
441 return TriState::True;
442 }
443 else if (this->c == '2'
444 || this->c == '?')
445 {
447 }
448 else
449 {
450 throw ConfigurationError("cannot convert to tri-state from char: " + std::string(1, this->c));
451 }
452 case Type::None:
453 throw ConfigurationError("no conversion from undefined configuration value to tri-state.");
454 default:
455 throw ConfigurationError("no conversion to tri-state from type: " + std::to_string(static_cast<int>(this->type)));
456 }
457 }
458
461 char GetChar() const
462 {
463 switch (type)
464 {
465 case Type::String:
466 if (this->s.length() != 1)
467 {
468 throw ConfigurationError("cannot convert to char from string: " + this->s);
469 }
470 return this->s[0];
471 case Type::Int:
472 if (this->i < CHAR_MIN || this->i > CHAR_MAX)
473 {
474 throw ConfigurationError("cannot convert to char from int: " + std::to_string(this->i));
475 }
476 return (char)this->i;
477 case Type::Bool:
478 return this->b ? 't' : 'f';
479 case Type::Tri:
480 return this->t == TriState::Undetermined ? '?' : this->t == TriState::False ? 'f' : 't';
481 case Type::Char:
482 return this->c;
483 case Type::None:
484 throw ConfigurationError("no conversion from undefined configuration value to char.");
485 default:
486 throw ConfigurationError("no conversion from type to char from type: " + std::to_string(static_cast<int>(this->type)));
487 }
488 }
489
492 std::time_t GetTimeT() const
493 {
494 switch (type)
495 {
496 case Type::String:
497 return std::stoll(this->s);
498 case Type::Int:
499 return (std::time_t)this->i;
500 case Type::None:
501 throw ConfigurationError("no conversion from undefined configuration value to time_t.");
502 default:
503 throw ConfigurationError("no conversion from time_t from type: " + std::to_string(static_cast<int>(this->type)));
504 }
505 }
506
509 std::vector<std::string> GetStringArray() const
510 {
511 switch (type)
512 {
513 case Type::String:
514 return MiKTeX::Util::StringUtil::Split(this->s, MiKTeX::Util::PathNameUtil::PathNameDelimiter);
515 case Type::StringArray:
516 return this->sa;
517 case Type::None:
518 throw ConfigurationError("no conversion from undefined configuration value to string array.");
519 default:
520 throw ConfigurationError("no conversion from to string array from type: " + std::to_string(static_cast<int>(this->type)));
521 }
522 }
523
525 enum class Type
526 {
527 None,
528 String,
529 Int,
530 Bool,
531 Tri,
532 Char,
533 StringArray
534 };
535
536 Type type = Type::None;
537
540 Type GetType() const;
541
544 bool HasValue() const
545 {
546 return type != Type::None;
547 }
548
551 std::string GetSection() const;
552
555 std::string GetDescription() const;
556
557private:
558 union
559 {
560 bool b;
561 char c;
562 int i;
563 std::string s;
564 std::vector<std::string> sa;
565 TriState t;
566 };
567
568 std::string description;
569 std::string section;
570};
571
573{
574 return type;
575}
576
577inline std::string ConfigValue::GetSection() const
578{
579 return section;
580}
581
582inline std::string ConfigValue::GetDescription() const
583{
584 return description;
585}
586
587MIKTEX_CONFIG_END_NAMESPACE;
Tri state.
TriState
Tri-state enum class.
Definition TriState.h:22
@ Undetermined
Undetermined.
Definition TriState.h:28
@ True
True (yes, on, enabled).
Definition TriState.h:26
@ False
False (no, off, disabled).
Definition TriState.h:24
bool HasValue() const
Definition ConfigValue.h:544
Type
Value type.
Definition ConfigValue.h:526
std::vector< std::string > GetStringArray() const
Definition ConfigValue.h:509
Type GetType() const
Definition ConfigValue.h:572
std::string GetDescription() const
Definition ConfigValue.h:582
int GetInt() const
Definition ConfigValue.h:267
TriState GetTriState() const
Definition ConfigValue.h:373
std::string GetSection() const
Definition ConfigValue.h:577
std::time_t GetTimeT() const
Definition ConfigValue.h:492
bool GetBool() const
Definition ConfigValue.h:290
char GetChar() const
Definition ConfigValue.h:461
std::string GetString() const
Definition ConfigValue.h:242
Definition ConfigValue.h:34