crawlserv++  [under development]
Application for crawling and analyzing textual content of websites.
Config.hpp
Go to the documentation of this file.
1 /*
2  *
3  * ---
4  *
5  * Copyright (C) 2020 Anselm Schmidt (ans[ät]ohai.su)
6  *
7  * This program is free software: you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation, either version 3 of the License, or
10  * (at your option) any later version in addition to the terms of any
11  * licences already herein identified.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program. If not, see <https://www.gnu.org/licenses/>.
20  *
21  * ---
22  *
23  * Config.hpp
24  *
25  * Abstract class as base for module-specific configuration classes.
26  *
27  * Created on: Jan 7, 2019
28  * Author: ans
29  */
30 
31 #ifndef MODULE_CONFIG_HPP_
32 #define MODULE_CONFIG_HPP_
33 
34 // hard-coded debugging constant
35 #define MODULE_CONFIG_DEBUG
36 
37 #include "../Helper/Json.hpp"
38 #include "../Helper/Strings.hpp"
39 #include "../Main/Exception.hpp"
40 #include "../Struct/ConfigItem.hpp"
41 
42 #include "../_extern/rapidjson/include/rapidjson/document.h"
43 
44 #ifdef MODULE_CONFIG_DEBUG
45 #include <algorithm> // std::adjacent_find, std::sort
46 #endif
47 
48 #include <array> // std::array
49 #include <cctype> // ::isascii
50 #include <cstdint> // std::int16_t, std::int32_t, std::int64_t, std::uint<8|16|32|64>_t
51 #include <limits> // std::numeric_limits
52 #include <queue> // std::queue
53 #include <stdexcept> // std::logic_error
54 #include <string> // std::string
55 #include <string_view> // std::string_view, std::string_view_literals
56 #include <vector> // std::vector
57 
59 namespace crawlservpp::Module {
60 
61  /*
62  * CONSTANTS
63  */
64 
65  using std::string_view_literals::operator""sv;
66 
69 
71  inline constexpr std::array protocols{
72  "ftp://"sv,
73  "scp://"sv,
74  "smb://"sv,
75  "http://"sv,
76  "ftps://"sv,
77  "sftp://"sv,
78  "file://"sv,
79  "dict://"sv,
80  "imap://"sv,
81  "ldap://"sv,
82  "pop3://"sv,
83  "rtmp://"sv,
84  "rtsp://"sv,
85  "smbs://"sv,
86  "smtp://"sv,
87  "tftp://"sv,
88  "https://"sv,
89  "imaps://"sv,
90  "ldaps://"sv,
91  "pop3s://"sv,
92  "smtps://"sv,
93  "gopher://"sv,
94  "telnet://"sv
95  };
96 
98 
99  /*
100  * DECLARATION
101  */
102 
104 
122  class Config {
123  // for convenience
125 
127 
128  using LogQueue = std::queue<std::string>&;
129  using LogPtr = std::queue<std::string> *;
130 
131  public:
134 
136  Config() = default;
137 
139  virtual ~Config() = default;
140 
144 
145  void loadConfig(const std::string& configJson, LogQueue& warningsTo);
146 
148 
151 
155 
158  Config(Config&) = delete;
159 
161  Config& operator=(Config&) = delete;
162 
164  Config(Config&&) = delete;
165 
167  Config& operator=(Config&&) = delete;
168 
170 
171 protected:
174 
178  Default = 0,
179 
182 
185 
188 
191  };
192 
197 
199 
205  };
206 
210 
211  void category(const std::string& category);
212 
213  void option(const std::string& name, bool& target);
214  void option(const std::string& name, std::vector<bool>& target);
215  void option(const std::string& name, char& target, CharParsingOption opt);
216  void option(const std::string& name, std::vector<char>& target, CharParsingOption opt);
217  void option(const std::string& name, std::int16_t& target);
218  void option(const std::string& name, std::vector<std::int16_t>& target);
219  void option(const std::string& name, std::int32_t& target);
220  void option(const std::string& name, std::vector<std::int32_t>& target);
221  void option(const std::string& name, std::int64_t& target);
222  void option(const std::string& name, std::vector<std::int64_t>& target);
223  void option(const std::string& name, std::uint8_t& target);
224  void option(const std::string& name, std::vector<std::uint8_t>& target);
225  void option(const std::string& name, std::uint16_t& target);
226  void option(const std::string& name, std::vector<std::uint16_t>& target);
227  void option(const std::string& name, std::uint32_t& target);
228  void option(const std::string& name, std::vector<std::uint32_t>& target);
229  void option(const std::string& name, std::uint64_t& target);
230  void option(const std::string& name, std::vector<std::uint64_t>& target);
231  void option(const std::string& name, float& target);
232  void option(const std::string& name, std::vector<float>& target);
233 
234  //NOLINTNEXTLINE(fuchsia-default-arguments-declarations)
235  void option(const std::string& name, std::string &target, StringParsingOption opt = Default);
236 
237  //NOLINTNEXTLINE(fuchsia-default-arguments-declarations)
238  void option(const std::string& name, std::vector<std::string>& target, StringParsingOption opt = Default);
239 
240  void warning(const std::string& warning);
241 
245 
246  virtual void parseBasicOption();
247  virtual void resetBase();
248 
250 
254  virtual void parseOption() = 0;
255 
257 
261  virtual void checkOptions() = 0;
262 
264 
268  virtual void reset() = 0;
269 
271 
272  private:
273  // temporary variables for configuration parsing
274  ConfigItem currentItem; // current configuration item
275  bool setCategory{false}; // category has been set
276  bool foundCategory{false}; // category has been found
277  bool currentCategory{false}; // category equals current category
278  bool finished{false}; // item has been found
279  LogPtr logPtr{nullptr}; // pointer to the logging queue
280 
281 #ifdef MODULE_CONFIG_DEBUG
282  bool debug{true}; // options have been debugged
283  std::string categoryString; // category to check as string
284  std::vector<std::string> list; // container to check for duplicates
285 #endif
286 
287  // internal helper function
288  void logQueue(const std::string& entry);
289 
290  // internal static helper functions
291  static void makeSubUrl(std::string& s);
292  static void makeUrl(std::string& s);
293  };
294 
295  /*
296  * IMPLEMENTATION
297  */
298 
299  /*
300  * CONFIGURATION LOADER
301  */
302 
304 
317  inline void Config::loadConfig(
318  const std::string& configJson,
319  std::queue<std::string>& warningsTo
320  ) {
321  // save pointer to logging queue
322  this->logPtr = &warningsTo;
323 
324  // parse JSON
325  rapidjson::Document json;
326 
327  try {
328  json = Helper::Json::parseRapid(configJson);
329  }
330  catch(const JsonException& e) {
331  throw Exception(
332  "Module::Config::loadConfig():"
333  " Could not parse configuration JSON - "
334  + std::string(e.view())
335  );
336  }
337 
338  if(!json.IsArray()) {
339  throw Exception(
340  "Module::Config::loadConfig():"
341  " Invalid configuration JSON (is no array)."
342  );
343  }
344 
345  // parse configuration entries
346  for(const auto& entry : json.GetArray()) {
347  // check whether configuration item is a JSON object
348  if(!entry.IsObject()) {
349  warningsTo.emplace(
350  "Configuration entry that is no object ignored."
351  );
352 
353  return;
354  }
355 
356  // go through all members of the JSON object, find its properties (name, category, value)
357  bool empty{true};
358  bool ignore{false};
359 
360  for(const auto& member : entry.GetObject()) {
361  // check the name of the current item member
362  if(member.name.IsString()) {
363  const std::string memberName(
364  member.name.GetString(),
365  member.name.GetStringLength()
366  );
367 
368  if(memberName == "cat") {
369  // found the category of the configuration item
370  if(member.value.IsString()) {
371  this->currentItem.category = std::string(
372  member.value.GetString(),
373  member.value.GetStringLength()
374  );
375  }
376  else {
377  warningsTo.emplace(
378  "Configuration entry with invalid category name ignored."
379  );
380 
381  ignore = true;
382 
383  break;
384  }
385  }
386  else if(memberName == "name") {
387  // found the name of the configuration item
388  if(member.value.IsString()) {
389  this->currentItem.name = std::string(
390  member.value.GetString(),
391  member.value.GetStringLength()
392  );
393  }
394  else {
395  warningsTo.emplace(
396  "Configuration entry with invalid option name ignored."
397  );
398 
399  ignore = true;
400 
401  break;
402  }
403 
404  }
405  else if(memberName == "value") {
406  // found the value of the configuration item
407  this->currentItem.value = &(member.value);
408 
409  empty = false;
410  }
411  else {
412  // found an unknown member of the configuration member
413  if(memberName.empty()) {
414  warningsTo.emplace(
415  "Unnamed configuration entry member ignored."
416  );
417  }
418  else {
419  warningsTo.emplace(
420  "Unknown configuration entry member '"
421  + memberName
422  + "' ignored."
423  );
424  }
425 
426  continue;
427  }
428  }
429  else {
430  // member has an invalid name (no string)
431  warningsTo.emplace(
432  "Configuration entry member with invalid name ignored."
433  );
434  }
435  }
436 
437  // check whether configuration entry should be ignored
438  if(ignore) {
439  continue;
440  }
441 
442  // check configuration item
443  if(this->currentItem.category.empty()) {
444  if(this->currentItem.name != "_algo") { // ignore algorithm ID
445  this->logQueue("Configuration item without category ignored");
446  }
447 
448  continue;
449  }
450 
451  if(this->currentItem.name.empty()) {
452  this->logQueue("Configuration item without name ignored.");
453 
454  continue;
455  }
456 
457  if(empty) {
458  this->logQueue("Configuration entry without value ignored.");
459 
460  continue;
461  }
462 
463  // parse option by child class
464  this->parseBasicOption();
465 
466 #ifdef MODULE_CONFIG_DEBUG
467  if(this->debug) {
468  // debug options
469  std::sort(this->list.begin(), this->list.end());
470 
471  const auto it{
472  std::adjacent_find(this->list.cbegin(), this->list.cend())
473  };
474 
475  if(it != this->list.cend()) {
476  throw Exception("Duplicate option '" + *it + "'");
477  }
478 
479  this->list.clear();
480 
481  this->debug = false;
482  }
483 #endif
484 
485  // check whether category and item were found
486  if(!this->finished) {
487  if(this->foundCategory) {
488  this->logQueue(
489  "Unknown configuration entry '"
490  + this->currentItem.str()
491  + "' ignored."
492  );
493  }
494  else {
495  this->logQueue(
496  "Configuration entry with unknown category '"
497  + this->currentItem.category
498  + "' ignored."
499  );
500  }
501  }
502 
503  // update parsing status
504  this->currentItem = ConfigItem();
505  this->foundCategory = false;
506  this->currentCategory = false;
507  this->finished = false;
508  }
509 
510  // check options
511  this->checkOptions();
512 
513  // unset logging queue
514  this->logPtr = nullptr;
515  }
516 
517  /*
518  * CONFIGURATION PARSING (protected)
519  */
520 
522 
527  inline void Config::category(const std::string& category) {
528 #ifdef MODULE_CONFIG_DEBUG
529  if(this->debug) {
530  this->categoryString = category;
531  }
532 #endif
533 
534  // check parsing state
535  if(this->finished) {
536  return;
537  }
538 
539  // update parsing state
540  this->setCategory = true;
541 
542  // compare category with current configuration item
543  if(this->currentItem.category == category) {
544  this->foundCategory = true;
545  this->currentCategory = true;
546  }
547  else {
548  this->currentCategory = false;
549  }
550  }
551 
553 
573  inline void Config::option(const std::string& name, bool& target) {
574 #ifdef MODULE_CONFIG_DEBUG
575  if(this->debug) {
576  this->list.emplace_back(this->categoryString + "." + name);
577  }
578 #endif
579 
580  // check parsing state
581  if(!(this->setCategory)) {
582  throw Exception(
583  "Module::Config::option():"
584  " No category has been set"
585  );
586  }
587 
588  if(this->finished || !(this->currentCategory)) {
589  return;
590  }
591 
592  // compare current configuration item with defined option
593  if(this->currentItem.name != name) {
594  return;
595  }
596 
597  // check value type
598  if(this->currentItem.value->IsBool()) {
599  target = this->currentItem.value->GetBool();
600  }
601  else if(this->currentItem.value->IsNull()) {
602  target = false;
603  }
604  else {
605  this->logQueue(
606  "'"
607  + this->currentItem.str()
608  + "' ignored because of wrong type (not bool)."
609  );
610  }
611 
612  // current item is parsed
613  this->finished = true;
614  }
615 
617 
637  inline void Config::option(const std::string& name, std::vector<bool>& target) {
638 #ifdef MODULE_CONFIG_DEBUG
639  if(this->debug) {
640  this->list.emplace_back(this->categoryString + "." + name);
641  }
642 #endif
643 
644  // check parsing state
645  if(!(this->setCategory)) {
646  throw Exception(
647  "Module::Config::option():"
648  " No category has been set"
649  );
650  }
651 
652  if(this->finished || !(this->currentCategory)) {
653  return;
654  }
655 
656  // compare current configuration item with defined option
657  if(this->currentItem.name != name) {
658  return;
659  }
660 
661  // check value type
662  if(this->currentItem.value->IsArray()) {
663  // clear target and reserve memory
664  target.clear();
665 
666  target.reserve(this->currentItem.value->Size());
667 
668  // check and copy array items
669  for(const auto& item : this->currentItem.value->GetArray()) {
670  if(item.IsBool()) {
671  target.push_back(item.GetBool());
672  }
673  else {
674  target.push_back(false);
675 
676  if(!item.IsNull()) {
677  this->logQueue(
678  "Value in '"
679  + this->currentItem.str()
680  + "' ignored because of wrong type (not bool)."
681  );
682  }
683  }
684  }
685  }
686  else {
687  this->logQueue(
688  "'"
689  + this->currentItem.str()
690  + "' ignored because of wrong type (not array)."
691  );
692  }
693 
694  // current item is finished
695  this->finished = true;
696  }
697 
699 
721  inline void Config::option(const std::string& name, char& target, CharParsingOption opt) {
722 #ifdef MODULE_CONFIG_DEBUG
723  if(this->debug) {
724  this->list.emplace_back(this->categoryString + "." + name);
725  }
726 #endif
727 
728  // check parsing state
729  if(!(this->setCategory)) {
730  throw Exception(
731  "Module::Config::option():"
732  " No category has been set"
733  );
734  }
735 
736  if(this->finished || !(this->currentCategory)) {
737  return;
738  }
739 
740  // compare current configuration item with defined option
741  if(this->currentItem.name != name) {
742  return;
743  }
744 
745  switch(opt) {
746  case FromNumber:
747  // get from number
748  if(this->currentItem.value->IsInt()) {
749  const auto value{this->currentItem.value->GetInt()};
750 
751  if(value > std::numeric_limits<char>::max()) {
752  this->logQueue(
753  "'"
754  + this->currentItem.str()
755  + "' ignored because the number is too large."
756  );
757  }
758  else {
759  target = value;
760  }
761  }
762  else if(this->currentItem.value->IsNull()) {
763  target = 0;
764  }
765  else {
766  this->logQueue(
767  "'"
768  + this->currentItem.str()
769  + "' ignored because of wrong type (not int)."
770  );
771  }
772 
773  break;
774 
775  case FromString:
776  // get from string
777  if(this->currentItem.value->IsString()) {
779  std::string(
780  this->currentItem.value->GetString(),
781  this->currentItem.value->GetStringLength()
782  )
783  );
784  }
785  else {
786  this->logQueue(
787  "'"
788  + this->currentItem.str()
789  + "' ignored because of wrong type (not string)."
790  );
791  }
792 
793  break;
794 
795  default:
796  throw Exception("Config::option(): Invalid string parsing option");
797  }
798 
799  // current item is parsed
800  this->finished = true;
801  }
802 
804 
826  inline void Config::option(const std::string& name, std::vector<char>& target, CharParsingOption opt) {
827 #ifdef MODULE_CONFIG_DEBUG
828  if(this->debug) {
829  this->list.emplace_back(this->categoryString + "." + name);
830  }
831 #endif
832 
833  // check parsing state
834  if(!(this->setCategory)) {
835  throw Exception(
836  "Module::Config::option():"
837  " No category has been set"
838  );
839  }
840 
841  if(this->finished || !(this->currentCategory)) {
842  return;
843  }
844 
845  // compare current configuration item with defined option
846  if(this->currentItem.name != name) {
847  return;
848  }
849 
850  // check value type
851  if(this->currentItem.value->IsArray()) {
852  // clear target and reserve memory
853  target.clear();
854 
855  target.reserve(this->currentItem.value->Size());
856 
857  // check and copy array items
858  for(const auto& item : this->currentItem.value->GetArray()) {
859  switch(opt) {
860  case FromNumber:
861  // get from number
862  if(item.IsInt()) {
863  const auto value{item.GetInt()};
864 
865  if(value > std::numeric_limits<char>::max()) {
866  this->logQueue(
867  "Value in '"
868  + this->currentItem.str()
869  + "' ignored because the number is too large."
870  );
871  }
872  else {
873  target.push_back(value);
874  }
875  }
876  else {
877  target.push_back(0);
878 
879  if(!item.IsNull()) {
880  this->logQueue(
881  "Value in '"
882  + this->currentItem.str()
883  + "' ignored because of wrong type (not int)."
884  );
885  }
886  }
887 
888  break;
889 
890  case FromString:
891  // get from string
892  if(item.IsString()) {
893  target.push_back(
895  std::string(
896  item.GetString(),
897  item.GetStringLength()
898  )
899  )
900  );
901 
902  // check for valid ASCII
903  if(::isascii(target.back()) == 0) {
904  this->logQueue(
905  "First character of string in '"
906  + this->currentItem.str()
907  + "' is no ASCII character: "
908  + std::string(
909  item.GetString(),
910  item.GetStringLength()
911  )
912  );
913  }
914  }
915  else {
916  target.push_back(0);
917 
918  if(!item.IsNull()) {
919  this->logQueue(
920  "Value in '"
921  + this->currentItem.str()
922  + "' ignored because of wrong type (not string)."
923  );
924  }
925  }
926 
927  break;
928 
929  default:
930  throw Exception("Config::option(): Invalid string parsing option");
931  }
932  }
933  }
934  else {
935  this->logQueue(
936  "'"
937  + this->currentItem.str()
938  + "' ignored because of wrong type (not array)."
939  );
940  }
941 
942  // current item is finished
943  this->finished = true;
944  }
945 
947 
967  inline void Config::option(const std::string& name, std::int16_t& target) {
968 #ifdef MODULE_CONFIG_DEBUG
969  if(this->debug) {
970  this->list.emplace_back(this->categoryString + "." + name);
971  }
972 #endif
973 
974  // check parsing state
975  if(!(this->setCategory)) {
976  throw Exception(
977  "Module::Config::option():"
978  " No category has been set"
979  );
980  }
981 
982  if(this->finished || !(this->currentCategory)) {
983  return;
984  }
985 
986  // compare current configuration item with defined option
987  if(this->currentItem.name != name) {
988  return;
989  }
990 
991  // check value type
992  if(this->currentItem.value->IsInt()) {
993  const auto value{this->currentItem.value->GetInt()};
994 
995  if(value > std::numeric_limits<std::int16_t>::max()) {
996  this->logQueue(
997  "'"
998  + this->currentItem.str()
999  + "' ignored because the number is too large."
1000  );
1001  }
1002  else {
1003  target = value;
1004  }
1005  }
1006  else if(this->currentItem.value->IsNull()) {
1007  target = 0;
1008  }
1009  else {
1010  this->logQueue(
1011  "'"
1012  + this->currentItem.str()
1013  + "' ignored because of wrong type (not integer)."
1014  );
1015  }
1016 
1017  // current item is parsed
1018  this->finished = true;
1019  }
1020 
1022 
1042  inline void Config::option(const std::string& name, std::vector<std::int16_t>& target) {
1043 #ifdef MODULE_CONFIG_DEBUG
1044  if(this->debug) {
1045  this->list.emplace_back(this->categoryString + "." + name);
1046  }
1047 #endif
1048 
1049  // check parsing state
1050  if(!(this->setCategory)) {
1051  throw Exception(
1052  "Module::Config::option():"
1053  " No category has been set"
1054  );
1055  }
1056 
1057  if(this->finished || !(this->currentCategory)) {
1058  return;
1059  }
1060 
1061  // compare current configuration item with defined option
1062  if(this->currentItem.name != name) {
1063  return;
1064  }
1065 
1066  // check value type
1067  if(this->currentItem.value->IsArray()) {
1068  // clear target and reserve memory
1069  target.clear();
1070 
1071  target.reserve(this->currentItem.value->Size());
1072 
1073  // check and copy array items
1074  for(const auto& item : this->currentItem.value->GetArray()) {
1075  if(item.IsInt()) {
1076  const auto value{item.GetInt()};
1077 
1078  if(value > std::numeric_limits<std::int16_t>::max()) {
1079  this->logQueue(
1080  "Value in '"
1081  + this->currentItem.str()
1082  + "' ignored because the number is too large."
1083  );
1084  }
1085  else {
1086  target.push_back(value);
1087  }
1088  }
1089  else {
1090  target.push_back(0);
1091 
1092  if(!item.IsNull()) {
1093  this->logQueue(
1094  "Value in '"
1095  + this->currentItem.str()
1096  + "' ignored because of wrong type (not integer)."
1097  );
1098  }
1099  }
1100  }
1101  }
1102  else {
1103  this->logQueue(
1104  "'"
1105  + this->currentItem.str()
1106  + "' ignored because of wrong type (not array)."
1107  );
1108  }
1109 
1110  // current item is finished
1111  this->finished = true;
1112  }
1113 
1115 
1135  inline void Config::option(const std::string& name, std::int32_t& target) {
1136 #ifdef MODULE_CONFIG_DEBUG
1137  if(this->debug) {
1138  this->list.emplace_back(this->categoryString + "." + name);
1139  }
1140 #endif
1141 
1142  // check parsing state
1143  if(!(this->setCategory)) {
1144  throw Exception(
1145  "Module::Config::option():"
1146  " No category has been set"
1147  );
1148  }
1149 
1150  if(this->finished || !(this->currentCategory)) {
1151  return;
1152  }
1153 
1154  // compare current configuration item with defined option
1155  if(this->currentItem.name != name) {
1156  return;
1157  }
1158 
1159  // check value type
1160  if(this->currentItem.value->IsInt()) {
1161  target = this->currentItem.value->GetInt();
1162  }
1163  else if(this->currentItem.value->IsNull()) {
1164  target = 0;
1165  }
1166  else {
1167  this->logQueue(
1168  "'"
1169  + this->currentItem.str()
1170  + "' ignored because of wrong type (not integer)."
1171  );
1172  }
1173 
1174  // current item is parsed
1175  this->finished = true;
1176  }
1177 
1179 
1199  inline void Config::option(const std::string& name, std::vector<std::int32_t>& target) {
1200 #ifdef MODULE_CONFIG_DEBUG
1201  if(this->debug) {
1202  this->list.emplace_back(this->categoryString + "." + name);
1203  }
1204 #endif
1205 
1206  // check parsing state
1207  if(!(this->setCategory)) {
1208  throw Exception(
1209  "Module::Config::option():"
1210  " No category has been set"
1211  );
1212  }
1213 
1214  if(this->finished || !(this->currentCategory)) {
1215  return;
1216  }
1217 
1218  // compare current configuration item with defined option
1219  if(this->currentItem.name != name) {
1220  return;
1221  }
1222 
1223  // check value type
1224  if(this->currentItem.value->IsArray()) {
1225  // clear target and reserve memory
1226  target.clear();
1227 
1228  target.reserve(this->currentItem.value->Size());
1229 
1230  // check and copy array items
1231  for(const auto& item : this->currentItem.value->GetArray()) {
1232  if(item.IsInt()) {
1233  target.push_back(item.GetInt());
1234  }
1235  else {
1236  target.push_back(0);
1237 
1238  if(!item.IsNull()) {
1239  this->logQueue(
1240  "Value in '"
1241  + this->currentItem.str()
1242  + "' ignored because of wrong type (not integer)."
1243  );
1244  }
1245  }
1246  }
1247  }
1248  else {
1249  this->logQueue(
1250  "'"
1251  + this->currentItem.str()
1252  + "' ignored because of wrong type (not array)."
1253  );
1254  }
1255 
1256  // current item is finished
1257  this->finished = true;
1258  }
1259 
1261 
1281  inline void Config::option(const std::string& name, std::int64_t& target) {
1282 #ifdef MODULE_CONFIG_DEBUG
1283  if(this->debug) {
1284  this->list.emplace_back(this->categoryString + "." + name);
1285  }
1286 #endif
1287 
1288  // check parsing state
1289  if(!(this->setCategory)) {
1290  throw Exception(
1291  "Module::Config::option():"
1292  " No category has been set"
1293  );
1294  }
1295 
1296  if(this->finished || !(this->currentCategory)) {
1297  return;
1298  }
1299 
1300  // compare current configuration item with defined option
1301  if(this->currentItem.name != name) {
1302  return;
1303  }
1304 
1305  // check value type
1306  if(this->currentItem.value->IsInt64()) {
1307  target = this->currentItem.value->GetInt64();
1308  }
1309  else if(this->currentItem.value->IsNull()) {
1310  target = 0;
1311  }
1312  else {
1313  this->logQueue(
1314  "'"
1315  + this->currentItem.str()
1316  + "' ignored because of wrong type (not 64-bit integer)."
1317  );
1318  }
1319 
1320  // current item is parsed
1321  this->finished = true;
1322  }
1323 
1325 
1345  inline void Config::option(const std::string& name, std::vector<std::int64_t>& target) {
1346  // check parsing state
1347  if(!(this->setCategory)) {
1348  throw Exception(
1349  "Module::Config::option():"
1350  " No category has been set"
1351  );
1352  }
1353 
1354  if(this->finished || !(this->currentCategory)) {
1355  return;
1356  }
1357 
1358  // compare current configuration item with defined option
1359  if(this->currentItem.name != name) {
1360  return;
1361  }
1362 
1363  // check value type
1364  if(this->currentItem.value->IsArray()) {
1365  // clear target and reserve memory
1366  target.clear();
1367 
1368  target.reserve(this->currentItem.value->Size());
1369 
1370  // check and copy array items
1371  for(const auto& item : this->currentItem.value->GetArray()) {
1372  if(item.IsInt64()) {
1373  target.push_back(item.GetInt64());
1374  }
1375  else {
1376  target.push_back(0);
1377 
1378  if(!item.IsNull()) {
1379  this->logQueue(
1380  "Value in '"
1381  + this->currentItem.str()
1382  + "' ignored because of wrong type (not 64-bit integer)."
1383  );
1384  }
1385  }
1386  }
1387  }
1388  else {
1389  this->logQueue(
1390  "'"
1391  + this->currentItem.str()
1392  + "' ignored because of wrong type (not array)."
1393  );
1394  }
1395 
1396  // current item is finished
1397  this->finished = true;
1398  }
1399 
1401 
1421  inline void Config::option(const std::string& name, std::uint8_t& target) {
1422 #ifdef MODULE_CONFIG_DEBUG
1423  if(this->debug) {
1424  this->list.emplace_back(this->categoryString + "." + name);
1425  }
1426 #endif
1427 
1428  // check parsing state
1429  if(!(this->setCategory)) {
1430  throw Exception(
1431  "Module::Config::option():"
1432  " No category has been set"
1433  );
1434  }
1435 
1436  if(this->finished || !(this->currentCategory)) {
1437  return;
1438  }
1439 
1440  // compare current configuration item with defined option
1441  if(this->currentItem.name != name) {
1442  return;
1443  }
1444 
1445  // check value type
1446  if(this->currentItem.value->IsUint()) {
1447  const auto value{this->currentItem.value->GetUint()};
1448 
1449  if(value > std::numeric_limits<std::uint8_t>::max()) {
1450  this->logQueue(
1451  "'"
1452  + this->currentItem.str()
1453  + "' ignored because the number is too large."
1454  );
1455  }
1456  else {
1457  target = value;
1458  }
1459  }
1460  else if(this->currentItem.value->IsNull()) {
1461  target = 0;
1462  }
1463  else {
1464  this->logQueue(
1465  "'"
1466  + this->currentItem.str()
1467  + "' ignored because of wrong type (not unsigned integer)."
1468  );
1469  }
1470 
1471  // current item is parsed
1472  this->finished = true;
1473  }
1474 
1476 
1496  inline void Config::option(const std::string& name, std::vector<std::uint8_t>& target) {
1497 #ifdef MODULE_CONFIG_DEBUG
1498  if(this->debug) {
1499  this->list.emplace_back(this->categoryString + "." + name);
1500  }
1501 #endif
1502 
1503  // check parsing state
1504  if(!(this->setCategory)) {
1505  throw Exception(
1506  "Module::Config::option():"
1507  " No category has been set");
1508  }
1509 
1510  if(this->finished || !(this->currentCategory)) {
1511  return;
1512  }
1513 
1514  // compare current configuration item with defined option
1515  if(this->currentItem.name != name) {
1516  return;
1517  }
1518 
1519  // check value type
1520  if(this->currentItem.value->IsArray()) {
1521  // clear target and reserve memory
1522  target.clear();
1523 
1524  target.reserve(this->currentItem.value->Size());
1525 
1526  // check and copy array items
1527  for(const auto& item : this->currentItem.value->GetArray()) {
1528  if(item.IsUint()) {
1529  const auto value{item.GetUint()};
1530 
1531  if(value > std::numeric_limits<std::uint8_t>::max()) {
1532  this->logQueue(
1533  "Value in '"
1534  + this->currentItem.str()
1535  + "' ignored because the number is too large."
1536  );
1537  }
1538  else {
1539  target.push_back(value);
1540  }
1541  }
1542  else {
1543  target.push_back(0);
1544 
1545  if(!item.IsNull()) {
1546  this->logQueue(
1547  "Value in '"
1548  + this->currentItem.str()
1549  + "' ignored because of wrong type (not unsigned integer)."
1550  );
1551  }
1552  }
1553  }
1554  }
1555  else {
1556  this->logQueue(
1557  "'"
1558  + this->currentItem.str()
1559  + "' ignored because of wrong type (not array)."
1560  );
1561  }
1562 
1563  // current item is finished
1564  this->finished = true;
1565  }
1566 
1568 
1588  inline void Config::option(const std::string& name, std::uint16_t& target) {
1589 #ifdef MODULE_CONFIG_DEBUG
1590  if(this->debug) {
1591  this->list.emplace_back(this->categoryString + "." + name);
1592  }
1593 #endif
1594 
1595  // check parsing state
1596  if(!(this->setCategory)) {
1597  throw Exception(
1598  "Module::Config::option():"
1599  " No category has been set"
1600  );
1601  }
1602 
1603  if(this->finished || !(this->currentCategory)) {
1604  return;
1605  }
1606 
1607  // compare current configuration item with defined option
1608  if(this->currentItem.name != name) {
1609  return;
1610  }
1611 
1612  // check value type
1613  if(this->currentItem.value->IsUint()) {
1614  const auto value{this->currentItem.value->GetUint()};
1615 
1616  if(value > std::numeric_limits<std::uint16_t>::max()) {
1617  this->logQueue(
1618  "'"
1619  + this->currentItem.str()
1620  + "' ignored because the number is too large."
1621  );
1622  }
1623  else {
1624  target = value;
1625  }
1626  }
1627  else if(this->currentItem.value->IsNull()) {
1628  target = 0;
1629  }
1630  else {
1631  this->logQueue(
1632  "'"
1633  + this->currentItem.str()
1634  + "' ignored because of wrong type (not unsigned integer)."
1635  );
1636  }
1637 
1638  // current item is parsed
1639  this->finished = true;
1640  }
1641 
1643 
1663  inline void Config::option(const std::string& name, std::vector<std::uint16_t>& target) {
1664 #ifdef MODULE_CONFIG_DEBUG
1665  if(this->debug) {
1666  this->list.emplace_back(this->categoryString + "." + name);
1667  }
1668 #endif
1669 
1670  // check parsing state
1671  if(!(this->setCategory)) {
1672  throw Exception(
1673  "Module::Config::option():"
1674  " No category has been set"
1675  );
1676  }
1677 
1678  if(this->finished || !(this->currentCategory)) {
1679  return;
1680  }
1681 
1682  // compare current configuration item with defined option
1683  if(this->currentItem.name != name) {
1684  return;
1685  }
1686 
1687  // check value type
1688  if(this->currentItem.value->IsArray()) {
1689  // clear target and reserve memory
1690  target.clear();
1691 
1692  target.reserve(this->currentItem.value->Size());
1693 
1694  // check and copy array items
1695  for(const auto& item : this->currentItem.value->GetArray()) {
1696  if(item.IsUint()) {
1697  const auto value{item.GetUint()};
1698 
1699  if(value > std::numeric_limits<std::uint16_t>::max()) {
1700  this->logQueue(
1701  "Value in '"
1702  + this->currentItem.str()
1703  + "' ignored because the number is too large."
1704  );
1705  }
1706  else {
1707  target.push_back(value);
1708  }
1709  }
1710  else {
1711  target.push_back(0);
1712 
1713  if(!item.IsNull()) {
1714  this->logQueue(
1715  "Value in '"
1716  + this->currentItem.str()
1717  + "' ignored because of wrong type (not unsigned integer)."
1718  );
1719  }
1720  }
1721  }
1722  }
1723  else {
1724  this->logQueue(
1725  "'"
1726  + this->currentItem.str()
1727  + "' ignored because of wrong type (not array)."
1728  );
1729  }
1730 
1731  // current item is finished
1732  this->finished = true;
1733  }
1734 
1736 
1756  inline void Config::option(const std::string& name, std::uint32_t& target) {
1757 #ifdef MODULE_CONFIG_DEBUG
1758  if(this->debug) {
1759  this->list.emplace_back(this->categoryString + "." + name);
1760  }
1761 #endif
1762 
1763  // check parsing state
1764  if(!(this->setCategory)) {
1765  throw Exception("Module::Config::option(): No category has been set");
1766  }
1767 
1768  if(this->finished || !(this->currentCategory)) {
1769  return;
1770  }
1771 
1772  // compare current configuration item with defined option
1773  if(this->currentItem.name != name) {
1774  return;
1775  }
1776 
1777  // check value type
1778  if(this->currentItem.value->IsUint()) {
1779  target = this->currentItem.value->GetUint();
1780  }
1781  else if(this->currentItem.value->IsNull()) {
1782  target = 0;
1783  }
1784  else {
1785  this->logQueue(
1786  "'"
1787  + this->currentItem.str()
1788  + "' ignored because of wrong type (not unsigned integer)."
1789  );
1790  }
1791 
1792  // current item is parsed
1793  this->finished = true;
1794  }
1795 
1797 
1817  inline void Config::option(const std::string& name, std::vector<std::uint32_t>& target) {
1818 #ifdef MODULE_CONFIG_DEBUG
1819  if(this->debug) {
1820  this->list.emplace_back(this->categoryString + "." + name);
1821  }
1822 #endif
1823 
1824  // check parsing state
1825  if(!(this->setCategory)) {
1826  throw Exception("Module::Config::option(): No category has been set");
1827  }
1828 
1829  if(this->finished || !(this->currentCategory)) {
1830  return;
1831  }
1832 
1833  // compare current configuration item with defined option
1834  if(this->currentItem.name != name) {
1835  return;
1836  }
1837 
1838  // check value type
1839  if(this->currentItem.value->IsArray()) {
1840  // clear target and reserve memory
1841  target.clear();
1842 
1843  target.reserve(this->currentItem.value->Size());
1844 
1845  // check and copy array items
1846  for(const auto& item : this->currentItem.value->GetArray()) {
1847  if(item.IsUint()) {
1848  target.push_back(item.GetUint());
1849  }
1850  else {
1851  target.push_back(0);
1852 
1853  if(!item.IsNull()) {
1854  this->logQueue(
1855  "Value in '"
1856  + this->currentItem.str()
1857  + "' ignored because of wrong type (not unsigned integer)."
1858  );
1859  }
1860  }
1861  }
1862  }
1863  else {
1864  this->logQueue(
1865  "'"
1866  + this->currentItem.str()
1867  + "' ignored because of wrong type (not array)."
1868  );
1869  }
1870 
1871  // current item is finished
1872  this->finished = true;
1873  }
1874 
1876 
1896  inline void Config::option(const std::string& name, std::uint64_t& target) {
1897 #ifdef MODULE_CONFIG_DEBUG
1898  if(this->debug) {
1899  this->list.emplace_back(this->categoryString + "." + name);
1900  }
1901 #endif
1902 
1903  // check parsing state
1904  if(!(this->setCategory)) {
1905  throw Exception("Module::Config::option(): No category has been set");
1906  }
1907 
1908  if(this->finished || !(this->currentCategory)) {
1909  return;
1910  }
1911 
1912  // compare current configuration item with defined option
1913  if(this->currentItem.name != name) {
1914  return;
1915  }
1916 
1917  // check value type
1918  if(this->currentItem.value->IsUint64()) {
1919  target = this->currentItem.value->GetUint64();
1920  }
1921  else if(this->currentItem.value->IsNull()) {
1922  target = 0;
1923  }
1924  else {
1925  this->logQueue(
1926  "'"
1927  + this->currentItem.str()
1928  + "' ignored because of wrong type (not unsigned 64-bit integer)."
1929  );
1930  }
1931 
1932  // current item is parsed
1933  this->finished = true;
1934  }
1935 
1937 
1957  inline void Config::option(const std::string& name, std::vector<std::uint64_t>& target) {
1958 #ifdef MODULE_CONFIG_DEBUG
1959  if(this->debug) {
1960  this->list.emplace_back(this->categoryString + "." + name);
1961  }
1962 #endif
1963 
1964  // check parsing state
1965  if(!(this->setCategory)) {
1966  throw Exception("Module::Config::option(): No category has been set");
1967  }
1968 
1969  if(this->finished || !(this->currentCategory)) {
1970  return;
1971  }
1972 
1973  // compare current configuration item with defined option
1974  if(this->currentItem.name != name) {
1975  return;
1976  }
1977 
1978  // check value type
1979  if(this->currentItem.value->IsArray()) {
1980  // clear target and reserve memory
1981  target.clear();
1982 
1983  target.reserve(this->currentItem.value->Size());
1984 
1985  // check and copy array items
1986  for(const auto& item : this->currentItem.value->GetArray()) {
1987  if(item.IsUint64()) {
1988  target.push_back(item.GetUint64());
1989  }
1990  else {
1991  target.push_back(0);
1992 
1993  if(!item.IsNull()) {
1994  this->logQueue(
1995  "Value in '"
1996  + this->currentItem.str()
1997  + "' ignored because of wrong type (not unsigned 64-bit integer)."
1998  );
1999  }
2000  }
2001  }
2002  }
2003  else {
2004  this->logQueue(
2005  "'"
2006  + this->currentItem.str()
2007  + "' ignored because of wrong type (not array)."
2008  );
2009  }
2010 
2011  // current item is finished
2012  this->finished = true;
2013  }
2014 
2016 
2036  inline void Config::option(const std::string& name, float& target) {
2037 #ifdef MODULE_CONFIG_DEBUG
2038  if(this->debug) {
2039  this->list.emplace_back(this->categoryString + "." + name);
2040  }
2041 #endif
2042 
2043  // check parsing state
2044  if(!(this->setCategory)) {
2045  throw Exception("Module::Config::option(): No category has been set");
2046  }
2047 
2048  if(this->finished || !(this->currentCategory)) {
2049  return;
2050  }
2051 
2052  // compare current configuration item with defined option
2053  if(this->currentItem.name != name) {
2054  return;
2055  }
2056 
2057  // check value type
2058  if(this->currentItem.value->IsFloat()) {
2059  target = this->currentItem.value->GetFloat();
2060  }
2061  else if(this->currentItem.value->IsNull()) {
2062  target = 0.F;
2063  }
2064  else {
2065  this->logQueue(
2066  "'"
2067  + this->currentItem.str()
2068  + "' ignored because of wrong type (not floating-point number)."
2069  );
2070  }
2071 
2072  // current item is parsed
2073  this->finished = true;
2074  }
2075 
2077 
2097  inline void Config::option(const std::string& name, std::vector<float>& target) {
2098 #ifdef MODULE_CONFIG_DEBUG
2099  if(this->debug) {
2100  this->list.emplace_back(this->categoryString + "." + name);
2101  }
2102 #endif
2103 
2104  // check parsing state
2105  if(!(this->setCategory)) {
2106  throw Exception("Module::Config::option(): No category has been set");
2107  }
2108 
2109  if(this->finished || !(this->currentCategory)) {
2110  return;
2111  }
2112 
2113  // compare current configuration item with defined option
2114  if(this->currentItem.name != name) {
2115  return;
2116  }
2117 
2118  // check value type
2119  if(this->currentItem.value->IsArray()) {
2120  // clear target and reserve memory
2121  target.clear();
2122 
2123  target.reserve(this->currentItem.value->Size());
2124 
2125  // check and copy array items
2126  for(const auto& item : this->currentItem.value->GetArray()) {
2127  if(item.IsFloat()) {
2128  target.push_back(item.GetFloat());
2129  }
2130  else {
2131  target.push_back(0);
2132 
2133  if(!item.IsNull()) {
2134  this->logQueue(
2135  "Value in '"
2136  + this->currentItem.str()
2137  + "' ignored because of wrong type (not floating-point number)."
2138  );
2139  }
2140  }
2141  }
2142  }
2143  else {
2144  this->logQueue(
2145  "'"
2146  + this->currentItem.str()
2147  + "' ignored because of wrong type (not array)."
2148  );
2149  }
2150 
2151  // current item is finished
2152  this->finished = true;
2153  }
2154 
2156 
2178  inline void Config::option(const std::string& name, std::string &target, StringParsingOption opt) {
2179 #ifdef MODULE_CONFIG_DEBUG
2180  if(this->debug) {
2181  this->list.emplace_back(this->categoryString + "." + name);
2182  }
2183 #endif
2184 
2185  // check parsing state
2186  if(!(this->setCategory)) {
2187  throw Exception(
2188  "Module::Config::option():"
2189  " No category has been set"
2190  );
2191  }
2192 
2193  if(this->finished || !(this->currentCategory)) {
2194  return;
2195  }
2196 
2197  // compare current configuration item with defined option
2198  if(this->currentItem.name != name) {
2199  return;
2200  }
2201 
2202  // check value type
2203  if(this->currentItem.value->IsString()) {
2204  std::string str(
2205  this->currentItem.value->GetString(),
2206  this->currentItem.value->GetStringLength()
2207  );
2208 
2209  switch(opt) {
2210  case Default:
2211  // get simple string
2212  target.swap(str);
2213 
2214  break;
2215 
2216  case SQL:
2217  // check for SQL compatibility
2219  target.swap(str);
2220  }
2221  else {
2222  this->logQueue(
2223  "'"
2224  + str
2225  + "' in '"
2226  + this->currentItem.str()
2227  + "' ignored because it contains invalid characters."
2228  );
2229  }
2230 
2231  break;
2232 
2233  case SubURL:
2234  // convert to sub-URL
2235  Config::makeSubUrl(str);
2236 
2237  target.swap(str);
2238 
2239  break;
2240 
2241  case URL:
2242  // convert to URL
2243  Config::makeUrl(str);
2244 
2245  target.swap(str);
2246 
2247  break;
2248 
2249  case Trim:
2250  // trim string
2251  Helper::Strings::trim(str);
2252 
2253  target.swap(str);
2254 
2255  break;
2256 
2257  default:
2258  throw Exception("Config::option(): Invalid string parsing option");
2259  }
2260  }
2261  else if(this->currentItem.value->IsNull()) {
2262  target.clear();
2263  }
2264  else {
2265  this->logQueue(
2266  "'"
2267  + this->currentItem.str()
2268  + "' ignored because of wrong type (not string)."
2269  );
2270  }
2271 
2272  // current item is parsed
2273  this->finished = true;
2274  }
2275 
2277 
2299  inline void Config::option(
2300  const std::string& name,
2301  std::vector<std::string>& target,
2303  ) {
2304 #ifdef MODULE_CONFIG_DEBUG
2305  if(this->debug) {
2306  this->list.emplace_back(this->categoryString + "." + name);
2307  }
2308 #endif
2309 
2310  // check parsing state
2311  if(!(this->setCategory)) {
2312  throw Exception(
2313  "Module::Config::option():"
2314  " No category has been set"
2315  );
2316  }
2317 
2318  if(this->finished || !(this->currentCategory)) {
2319  return;
2320  }
2321 
2322  // compare current configuration item with defined option
2323  if(this->currentItem.name != name) {
2324  return;
2325  }
2326 
2327  // check value type
2328  if(this->currentItem.value->IsArray()) {
2329  // clear target and reserve memory
2330  target.clear();
2331 
2332  target.reserve(this->currentItem.value->Size());
2333 
2334  // check and copy array items
2335  for(const auto& item : this->currentItem.value->GetArray()) {
2336  if(item.IsString()) {
2337  std::string str(item.GetString(), item.GetStringLength());
2338 
2339  switch(opt) {
2340  case Default:
2341  // get simple string
2342  target.emplace_back(str);
2343 
2344  break;
2345 
2346  case SQL:
2347  // check for SQL compatibility
2349  target.emplace_back(str);
2350  }
2351  else {
2352  this->logQueue(
2353  "'"
2354  + str
2355  + "' in '"
2356  + this->currentItem.str()
2357  + "' ignored because it contains invalid characters."
2358  );
2359  }
2360 
2361  break;
2362 
2363  case SubURL:
2364  // convert to sub-URL
2365  Config::makeSubUrl(str);
2366 
2367  target.emplace_back(str);
2368 
2369  break;
2370 
2371  case URL:
2372  // convert to URL
2373  Config::makeUrl(str);
2374 
2375  target.emplace_back(str);
2376 
2377  break;
2378 
2379  case Trim:
2380  // trim string
2381  Helper::Strings::trim(str);
2382 
2383  target.emplace_back(str);
2384 
2385  break;
2386 
2387  default:
2388  throw Exception("Config::option(): Invalid string parsing option");
2389  }
2390  }
2391  else {
2392  target.emplace_back();
2393 
2394  if(!item.IsNull()) {
2395  this->logQueue(
2396  "Value in '"
2397  + this->currentItem.str()
2398  + "' ignored because of wrong type (not string)."
2399  );
2400  }
2401  }
2402  }
2403  }
2404  else {
2405  this->logQueue(
2406  "'"
2407  + this->currentItem.str()
2408  + "' ignored because of wrong type (not array)."
2409  );
2410  }
2411 
2412  // current item is parsed
2413  this->finished = true;
2414  }
2415 
2417 
2427  inline void Config::warning(const std::string& warning) {
2428  if(this->logPtr == nullptr) {
2429  throw Exception(
2430  "Config::warning(): No log queue is active."
2431  " Do not use this function outside of Config::loadConfig()!"
2432  );
2433  }
2434 
2435  this->logPtr->emplace(warning);
2436  }
2437 
2438  /*
2439  * MODULE-SPECIFIC CONFIGURASTION PARSING (protected)
2440  */
2441 
2443 
2458  this->parseOption();
2459  }
2460 
2462 
2476  inline void Config::resetBase() {
2477  this->reset();
2478  }
2479 
2480  /*
2481  * INTERNAL HELPER FUNCTION (private)
2482  */
2483 
2484  // add an entry to the logging queue, if available.
2485  inline void Config::logQueue(const std::string& entry) {
2486  if(this->logPtr != nullptr) {
2487  this->logPtr->emplace(entry);
2488  }
2489  }
2490 
2491  /*
2492  * INTERNAL STATIC HELPER FUNCTIONS (private)
2493  */
2494 
2495  // check for sub-URL (starting with /) or libcurl-supported URL protocol
2496  // adds a slash in the beginning if no protocol was found
2497  inline void Config::makeSubUrl(std::string& s) {
2498  if(!s.empty()) {
2499  if(s.at(0) == '/') {
2500  return;
2501  }
2502 
2503  for(const auto protocol : protocols) {
2504  if(s.length() >= protocol.length()) {
2505  if(s.substr(0, protocol.length()) == protocol) {
2506  return;
2507  }
2508  }
2509  }
2510  }
2511 
2512  s.insert(0, "/");
2513  }
2514 
2515  // check for URL
2516  // adds a slash in the end if none was found after protocol
2517  inline void Config::makeUrl(std::string& s) {
2518  if(!s.empty()) {
2519  auto pos{s.find("://")};
2520 
2521  if(pos == std::string::npos) {
2522  pos = 0;
2523  }
2524  else {
2525  pos += 3;
2526  }
2527 
2528  pos = s.find('/', pos);
2529 
2530  if(pos != std::string::npos) {
2531  return;
2532  }
2533  }
2534 
2535  s.append(1, '/');
2536  }
2537 
2538 } /* namespace crawlservpp::Module */
2539 
2540 #endif /* MODULE_CONFIG_HPP_ */
CharParsingOption
Options for parsing char&#39;s.
Definition: Config.hpp:194
Uses a string as it is.
Definition: Config.hpp:178
void option(const std::string &name, bool &target)
Checks for a configuration option of type bool.
Definition: Config.hpp:573
const rapidjson::Value * value
JSON value of the configuration item, or nullptr if not initialized.
Definition: ConfigItem.hpp:52
Get char by its numeric value.
Definition: Config.hpp:196
std::string category
Category of the configuration item.
Definition: ConfigItem.hpp:46
virtual void reset()=0
Resets the module-specific configuration.
Abstract class as base for module-specific configurations.
Definition: Config.hpp:122
virtual void resetBase()
Resets basic options.
Definition: Config.hpp:2476
virtual void checkOptions()=0
Checks the module-specific configuration after parsing.
rapidjson::Document parseRapid(std::string_view json)
Parses JSON code using RapidJSON.
Definition: Json.hpp:575
#define MAIN_EXCEPTION_CLASS()
Macro used to easily define classes for general exceptions.
Definition: Exception.hpp:50
Config()=default
Default constructor.
Class for JSON exceptions.
Definition: Json.hpp:136
void trim(std::string &stringToTrim)
Removes whitespaces around a string.
Definition: Strings.hpp:360
std::string name
Name of the configuration item.
Definition: ConfigItem.hpp:49
StringParsingOption
Options for parsing strings.
Definition: Config.hpp:176
Class for configuration exceptions.
Definition: Config.hpp:150
virtual void parseBasicOption()
Parses a basic option.
Definition: Config.hpp:2457
constexpr std::array protocols
Protocols supported by the libcurl library.
Definition: Config.hpp:71
Get char from the beginning of a string.
Definition: Config.hpp:204
Config & operator=(Config &)=delete
Deleted copy assignment operator.
char getFirstOrEscapeChar(std::string_view from)
Gets the first character or an escaped character from the beginning of the given string.
Definition: Strings.hpp:948
void category(const std::string &category)
Sets the category of the subsequent configuration items to be checked for.
Definition: Config.hpp:527
Converts a string to a URL (without the protocol).
Definition: Config.hpp:187
void loadConfig(const std::string &configJson, LogQueue &warningsTo)
Loads a configuration.
Definition: Config.hpp:317
std::string_view view() const noexcept
Gets the description of the exception as a view to the underlying string.
Definition: Exception.hpp:158
std::string str() const
Combines category and name into one string.
Definition: ConfigItem.hpp:63
virtual ~Config()=default
Default destructor.
bool checkSQLName(std::string_view name)
Checks whether the given string is a valid name for MySQL tables and fields.
Definition: Strings.hpp:1079
Requires a SQL-compatible string.
Definition: Config.hpp:181
virtual void parseOption()=0
Parses a module-specific configuration option.
Trims a string.
Definition: Config.hpp:190
Converts a string to a sub-URL.
Definition: Config.hpp:184
Namespace for the different modules run by threads.
void warning(const std::string &warning)
Adds a warning to the logging queue.
Definition: Config.hpp:2427
Configuration item containing its category, name, and JSON value.
Definition: ConfigItem.hpp:41