1 /* ----------------------------------------------------------------------------
2 libconfig - A library for processing structured configuration files
3 Copyright (C) 2005-2018 Mark A Lindner
4
5 This file is part of libconfig.
6
7 This library is free software; you can redistribute it and/or
8 modify it under the terms of the GNU Lesser General Public License
9 as published by the Free Software Foundation; either version 2.1 of
10 the License, or (at your option) any later version.
11
12 This library is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Lesser General Public License for more details.
16
17 You should have received a copy of the GNU Library General Public
18 License along with this library; if not, see
19 <http://www.gnu.org/licenses/>.
20 ----------------------------------------------------------------------------
21 */
22
23 #include "libconfig.h++"
24
25 #ifdef _MSC_VER
26 #pragma warning (disable: 4996)
27 #endif
28
29 #include "wincompat.h"
30 #include "libconfig.h"
31
32 #include <cstring>
33 #include <cstdlib>
34 #include <sstream>
35
36 namespace libconfig {
37
38 // ---------------------------------------------------------------------------
39
__include_func(config_t * config,const char * include_dir,const char * path,const char ** error)40 static const char **__include_func(config_t *config,
41 const char *include_dir,
42 const char *path,
43 const char **error)
44 {
45 Config *self = reinterpret_cast<Config *>(config_get_hook(config));
46 return(self->evaluateIncludePath(path, error));
47 }
48
49 // ---------------------------------------------------------------------------
50
ParseException(const char * file,int line,const char * error)51 ParseException::ParseException(const char *file, int line, const char *error)
52 : _file(file ? ::strdup(file) : NULL), _line(line), _error(error)
53 {
54 }
55
56 // ---------------------------------------------------------------------------
57
ParseException(const ParseException & other)58 ParseException::ParseException(const ParseException &other)
59 : ConfigException(other),
60 _file(other._file ? ::strdup(other._file) : NULL),
61 _line(other._line),
62 _error(other._error)
63 {
64 }
65
66 // ---------------------------------------------------------------------------
67
~ParseException()68 ParseException::~ParseException() LIBCONFIGXX_NOEXCEPT
69 {
70 ::free((void *)_file);
71 }
72
73 // ---------------------------------------------------------------------------
74
what() const75 const char *ParseException::what() const LIBCONFIGXX_NOEXCEPT
76 {
77 return("ParseException");
78 }
79
80 // ---------------------------------------------------------------------------
81
__toTypeCode(Setting::Type type)82 static int __toTypeCode(Setting::Type type)
83 {
84 int typecode;
85
86 switch(type)
87 {
88 case Setting::TypeGroup:
89 typecode = CONFIG_TYPE_GROUP;
90 break;
91
92 case Setting::TypeInt:
93 typecode = CONFIG_TYPE_INT;
94 break;
95
96 case Setting::TypeInt64:
97 typecode = CONFIG_TYPE_INT64;
98 break;
99
100 case Setting::TypeFloat:
101 typecode = CONFIG_TYPE_FLOAT;
102 break;
103
104 case Setting::TypeString:
105 typecode = CONFIG_TYPE_STRING;
106 break;
107
108 case Setting::TypeBoolean:
109 typecode = CONFIG_TYPE_BOOL;
110 break;
111
112 case Setting::TypeArray:
113 typecode = CONFIG_TYPE_ARRAY;
114 break;
115
116 case Setting::TypeList:
117 typecode = CONFIG_TYPE_LIST;
118 break;
119
120 default:
121 typecode = CONFIG_TYPE_NONE;
122 }
123
124 return(typecode);
125 }
126
127 // ---------------------------------------------------------------------------
128
__constructPath(const Setting & setting,std::stringstream & path)129 static void __constructPath(const Setting &setting,
130 std::stringstream &path)
131 {
132 // head recursion to print path from root to target
133
134 if(! setting.isRoot())
135 {
136 __constructPath(setting.getParent(), path);
137 if(path.tellp() > 0)
138 path << '.';
139
140 const char *name = setting.getName();
141 if(name)
142 path << name;
143 else
144 path << '[' << setting.getIndex() << ']';
145 }
146 }
147
148 // ---------------------------------------------------------------------------
149
SettingException(const Setting & setting)150 SettingException::SettingException(const Setting &setting)
151 {
152 std::stringstream sstr;
153 __constructPath(setting, sstr);
154
155 _path = ::strdup(sstr.str().c_str());
156 }
157
158 // ---------------------------------------------------------------------------
159
SettingException(const Setting & setting,int idx)160 SettingException::SettingException(const Setting &setting, int idx)
161 {
162 std::stringstream sstr;
163 __constructPath(setting, sstr);
164 sstr << ".[" << idx << "]";
165
166 _path = ::strdup(sstr.str().c_str());
167 }
168
169 // ---------------------------------------------------------------------------
170
SettingException(const Setting & setting,const char * name)171 SettingException::SettingException(const Setting &setting, const char *name)
172 {
173 std::stringstream sstr;
174 __constructPath(setting, sstr);
175 sstr << '.' << name;
176
177 _path = ::strdup(sstr.str().c_str());
178 }
179
180 // ---------------------------------------------------------------------------
181
SettingException(const char * path)182 SettingException::SettingException(const char *path)
183 {
184 _path = ::strdup(path);
185 }
186
187 // ---------------------------------------------------------------------------
188
getPath() const189 const char *SettingException::getPath() const
190 {
191 return(_path);
192 }
193
194 // ---------------------------------------------------------------------------
195
SettingException(const SettingException & other)196 SettingException::SettingException(const SettingException &other)
197 : ConfigException(other)
198 {
199 _path = ::strdup(other._path);
200 }
201
202 // ---------------------------------------------------------------------------
203
operator =(const SettingException & other)204 SettingException &SettingException::operator=(const SettingException &other)
205 {
206 ::free(_path);
207 _path = ::strdup(other._path);
208
209 return(*this);
210 }
211
212 // ---------------------------------------------------------------------------
213
what() const214 const char *SettingException::what() const LIBCONFIGXX_NOEXCEPT
215 {
216 return("SettingException");
217 }
218
219 // ---------------------------------------------------------------------------
220
~SettingException()221 SettingException::~SettingException() LIBCONFIGXX_NOEXCEPT
222 {
223 ::free(_path);
224 }
225
226 // ---------------------------------------------------------------------------
227
SettingTypeException(const Setting & setting)228 SettingTypeException::SettingTypeException(const Setting &setting)
229 : SettingException(setting)
230 {
231 }
232
233 // ---------------------------------------------------------------------------
234
SettingTypeException(const Setting & setting,int idx)235 SettingTypeException::SettingTypeException(const Setting &setting, int idx)
236 : SettingException(setting, idx)
237 {
238 }
239
240 // ---------------------------------------------------------------------------
241
SettingTypeException(const Setting & setting,const char * name)242 SettingTypeException::SettingTypeException(const Setting &setting,
243 const char *name)
244 : SettingException(setting, name)
245 {
246 }
247
248 // ---------------------------------------------------------------------------
249
what() const250 const char *SettingTypeException::what() const LIBCONFIGXX_NOEXCEPT
251 {
252 return("SettingTypeException");
253 }
254
255 // ---------------------------------------------------------------------------
256
SettingNotFoundException(const Setting & setting,int idx)257 SettingNotFoundException::SettingNotFoundException(const Setting &setting,
258 int idx)
259 : SettingException(setting, idx)
260 {
261 }
262
263 // ---------------------------------------------------------------------------
264
SettingNotFoundException(const Setting & setting,const char * name)265 SettingNotFoundException::SettingNotFoundException(const Setting &setting,
266 const char *name)
267 : SettingException(setting, name)
268 {
269 }
270
271 // ---------------------------------------------------------------------------
272
SettingNotFoundException(const char * path)273 SettingNotFoundException::SettingNotFoundException(const char *path)
274 : SettingException(path)
275 {
276 }
277
278 // ---------------------------------------------------------------------------
279
what() const280 const char *SettingNotFoundException::what() const LIBCONFIGXX_NOEXCEPT
281 {
282 return("SettingNotFoundException");
283 }
284
285 // ---------------------------------------------------------------------------
286
SettingNameException(const Setting & setting,const char * name)287 SettingNameException::SettingNameException(const Setting &setting,
288 const char *name)
289 : SettingException(setting, name)
290 {
291 }
292
293 // ---------------------------------------------------------------------------
294
what() const295 const char *SettingNameException::what() const LIBCONFIGXX_NOEXCEPT
296 {
297 return("SettingNameException");
298 }
299
300 // ---------------------------------------------------------------------------
301
what() const302 const char *FileIOException::what() const LIBCONFIGXX_NOEXCEPT
303 {
304 return("FileIOException");
305 }
306
307 // ---------------------------------------------------------------------------
308
ConfigDestructor(void * arg)309 void Config::ConfigDestructor(void *arg)
310 {
311 delete reinterpret_cast<Setting *>(arg);
312 }
313
314 // ---------------------------------------------------------------------------
315
Config()316 Config::Config()
317 : _defaultFormat(Setting::FormatDefault)
318 {
319 _config = new config_t;
320 config_init(_config);
321 config_set_hook(_config, reinterpret_cast<void *>(this));
322 config_set_destructor(_config, ConfigDestructor);
323 config_set_include_func(_config, __include_func);
324 }
325
326 // ---------------------------------------------------------------------------
327
~Config()328 Config::~Config()
329 {
330 config_destroy(_config);
331 delete _config;
332 }
333
334 // ---------------------------------------------------------------------------
335
clear()336 void Config::clear()
337 {
338 config_clear(_config);
339 }
340
341 // ---------------------------------------------------------------------------
342
setOptions(int options)343 void Config::setOptions(int options)
344 {
345 config_set_options(_config, options);
346 }
347
348 // ---------------------------------------------------------------------------
349
getOptions() const350 int Config::getOptions() const
351 {
352 return(config_get_options(_config));
353 }
354
355 // ---------------------------------------------------------------------------
356
setOption(Config::Option option,bool flag)357 void Config::setOption(Config::Option option, bool flag)
358 {
359 config_set_option(_config, (int)option, flag ? CONFIG_TRUE : CONFIG_FALSE);
360 }
361
362 // ---------------------------------------------------------------------------
363
getOption(Config::Option option) const364 bool Config::getOption(Config::Option option) const
365 {
366 return(config_get_option(_config, (int)option) == CONFIG_TRUE);
367 }
368
369 // ---------------------------------------------------------------------------
370
setDefaultFormat(Setting::Format format)371 void Config::setDefaultFormat(Setting::Format format)
372 {
373 if(format == Setting::FormatHex)
374 _defaultFormat = Setting::FormatHex;
375 else
376 _defaultFormat = Setting::FormatDefault;
377
378 config_set_default_format(_config, static_cast<short>(_defaultFormat));
379 }
380
381 // ---------------------------------------------------------------------------
382
setTabWidth(unsigned short width)383 void Config::setTabWidth(unsigned short width)
384 {
385 config_set_tab_width(_config, width);
386 }
387
388 // ---------------------------------------------------------------------------
389
getTabWidth() const390 unsigned short Config::getTabWidth() const
391 {
392 return(config_get_tab_width(_config));
393 }
394
395 // ---------------------------------------------------------------------------
396
setFloatPrecision(unsigned short digits)397 void Config::setFloatPrecision(unsigned short digits)
398 {
399 return (config_set_float_precision(_config,digits));
400 }
401
402 // ---------------------------------------------------------------------------
403
getFloatPrecision() const404 unsigned short Config::getFloatPrecision() const
405 {
406 return (config_get_float_precision(_config));
407 }
408
409 // ---------------------------------------------------------------------------
410
setIncludeDir(const char * includeDir)411 void Config::setIncludeDir(const char *includeDir)
412 {
413 config_set_include_dir(_config, includeDir);
414 }
415
416 // ---------------------------------------------------------------------------
417
getIncludeDir() const418 const char *Config::getIncludeDir() const
419 {
420 return(config_get_include_dir(_config));
421 }
422
423 // ---------------------------------------------------------------------------
424
evaluateIncludePath(const char * path,const char ** error)425 const char **Config::evaluateIncludePath(const char *path, const char **error)
426 {
427 return(config_default_include_func(_config, getIncludeDir(), path, error));
428 }
429
430 // ---------------------------------------------------------------------------
431
handleError() const432 void Config::handleError() const
433 {
434 switch(config_error_type(_config))
435 {
436 case CONFIG_ERR_NONE:
437 break;
438
439 case CONFIG_ERR_PARSE:
440 throw ParseException(config_error_file(_config),
441 config_error_line(_config),
442 config_error_text(_config));
443 break;
444
445 case CONFIG_ERR_FILE_IO:
446 default:
447 throw FileIOException();
448 }
449 }
450
451 // ---------------------------------------------------------------------------
452
read(FILE * stream)453 void Config::read(FILE *stream)
454 {
455 if(! config_read(_config, stream))
456 handleError();
457 }
458
459 // ---------------------------------------------------------------------------
460
readString(const char * str)461 void Config::readString(const char *str)
462 {
463 if(! config_read_string(_config, str))
464 handleError();
465 }
466
467 // ---------------------------------------------------------------------------
468
write(FILE * stream) const469 void Config::write(FILE *stream) const
470 {
471 config_write(_config, stream);
472 }
473
474 // ---------------------------------------------------------------------------
475
readFile(const char * filename)476 void Config::readFile(const char *filename)
477 {
478 if(! config_read_file(_config, filename))
479 handleError();
480 }
481
482 // ---------------------------------------------------------------------------
483
writeFile(const char * filename)484 void Config::writeFile(const char *filename)
485 {
486 if(! config_write_file(_config, filename))
487 handleError();
488 }
489
490 // ---------------------------------------------------------------------------
491
lookup(const char * path) const492 Setting & Config::lookup(const char *path) const
493 {
494 config_setting_t *s = config_lookup(_config, path);
495 if(! s)
496 throw SettingNotFoundException(path);
497
498 return(Setting::wrapSetting(s));
499 }
500
501 // ---------------------------------------------------------------------------
502
exists(const char * path) const503 bool Config::exists(const char *path) const
504 {
505 config_setting_t *s = config_lookup(_config, path);
506
507 return(s != NULL);
508 }
509
510 // ---------------------------------------------------------------------------
511
512 #define CONFIG_LOOKUP_NO_EXCEPTIONS(P, T, V) \
513 try \
514 { \
515 Setting &s = lookup(P); \
516 V = (T)s; \
517 return(true); \
518 } \
519 catch(const ConfigException &) \
520 { \
521 return(false); \
522 }
523
524 // ---------------------------------------------------------------------------
525
lookupValue(const char * path,bool & value) const526 bool Config::lookupValue(const char *path, bool &value) const
527 {
528 CONFIG_LOOKUP_NO_EXCEPTIONS(path, bool, value);
529 }
530
531 // ---------------------------------------------------------------------------
532
lookupValue(const char * path,int & value) const533 bool Config::lookupValue(const char *path, int &value) const
534 {
535 CONFIG_LOOKUP_NO_EXCEPTIONS(path, int, value);
536 }
537
538 // ---------------------------------------------------------------------------
539
lookupValue(const char * path,unsigned int & value) const540 bool Config::lookupValue(const char *path, unsigned int &value) const
541 {
542 CONFIG_LOOKUP_NO_EXCEPTIONS(path, unsigned int, value);
543 }
544
545 // ---------------------------------------------------------------------------
546
lookupValue(const char * path,long long & value) const547 bool Config::lookupValue(const char *path, long long &value) const
548 {
549 CONFIG_LOOKUP_NO_EXCEPTIONS(path, long long, value);
550 }
551
552 // ---------------------------------------------------------------------------
553
lookupValue(const char * path,unsigned long long & value) const554 bool Config::lookupValue(const char *path, unsigned long long &value) const
555 {
556 CONFIG_LOOKUP_NO_EXCEPTIONS(path, unsigned long long, value);
557 }
558
559 // ---------------------------------------------------------------------------
560
lookupValue(const char * path,double & value) const561 bool Config::lookupValue(const char *path, double &value) const
562 {
563 CONFIG_LOOKUP_NO_EXCEPTIONS(path, double, value);
564 }
565
566 // ---------------------------------------------------------------------------
567
lookupValue(const char * path,float & value) const568 bool Config::lookupValue(const char *path, float &value) const
569 {
570 CONFIG_LOOKUP_NO_EXCEPTIONS(path, float, value);
571 }
572
573 // ---------------------------------------------------------------------------
574
lookupValue(const char * path,const char * & value) const575 bool Config::lookupValue(const char *path, const char *&value) const
576 {
577 CONFIG_LOOKUP_NO_EXCEPTIONS(path, const char *, value);
578 }
579
580 // ---------------------------------------------------------------------------
581
lookupValue(const char * path,std::string & value) const582 bool Config::lookupValue(const char *path, std::string &value) const
583 {
584 CONFIG_LOOKUP_NO_EXCEPTIONS(path, const char *, value);
585 }
586
587 // ---------------------------------------------------------------------------
588
getRoot() const589 Setting & Config::getRoot() const
590 {
591 return(Setting::wrapSetting(config_root_setting(_config)));
592 }
593
594 // ---------------------------------------------------------------------------
595
Setting(config_setting_t * setting)596 Setting::Setting(config_setting_t *setting)
597 : _setting(setting)
598 {
599 switch(config_setting_type(setting))
600 {
601 case CONFIG_TYPE_GROUP:
602 _type = TypeGroup;
603 break;
604
605 case CONFIG_TYPE_INT:
606 _type = TypeInt;
607 break;
608
609 case CONFIG_TYPE_INT64:
610 _type = TypeInt64;
611 break;
612
613 case CONFIG_TYPE_FLOAT:
614 _type = TypeFloat;
615 break;
616
617 case CONFIG_TYPE_STRING:
618 _type = TypeString;
619 break;
620
621 case CONFIG_TYPE_BOOL:
622 _type = TypeBoolean;
623 break;
624
625 case CONFIG_TYPE_ARRAY:
626 _type = TypeArray;
627 break;
628
629 case CONFIG_TYPE_LIST:
630 _type = TypeList;
631 break;
632
633 case CONFIG_TYPE_NONE:
634 default:
635 _type = TypeNone;
636 break;
637 }
638
639 switch(config_setting_get_format(setting))
640 {
641 case CONFIG_FORMAT_HEX:
642 _format = FormatHex;
643 break;
644
645 case CONFIG_FORMAT_DEFAULT:
646 default:
647 _format = FormatDefault;
648 break;
649 }
650 }
651
652 // ---------------------------------------------------------------------------
653
~Setting()654 Setting::~Setting()
655 {
656 _setting = NULL;
657 }
658
659 // ---------------------------------------------------------------------------
660
setFormat(Format format)661 void Setting::setFormat(Format format)
662 {
663 if((_type == TypeInt) || (_type == TypeInt64))
664 {
665 if(format == FormatHex)
666 _format = FormatHex;
667 else
668 _format = FormatDefault;
669 }
670 else
671 _format = FormatDefault;
672
673 config_setting_set_format(_setting, static_cast<short>(_format));
674 }
675
676 // ---------------------------------------------------------------------------
677
operator bool() const678 Setting::operator bool() const
679 {
680 assertType(TypeBoolean);
681
682 return(config_setting_get_bool(_setting) ? true : false);
683 }
684
685 // ---------------------------------------------------------------------------
686
operator int() const687 Setting::operator int() const
688 {
689 assertType(TypeInt);
690
691 return(config_setting_get_int(_setting));
692 }
693
694 // ---------------------------------------------------------------------------
695
operator unsigned int() const696 Setting::operator unsigned int() const
697 {
698 assertType(TypeInt);
699
700 int v = config_setting_get_int(_setting);
701
702 return(static_cast<unsigned int>(v));
703 }
704
705 // ---------------------------------------------------------------------------
706
operator long() const707 Setting::operator long() const
708 {
709 if(sizeof(long) == sizeof(long long))
710 return operator long long();
711 else
712 return operator int();
713 }
714
715 // ---------------------------------------------------------------------------
716
operator unsigned long() const717 Setting::operator unsigned long() const
718 {
719 if(sizeof(long) == sizeof(long long))
720 return operator unsigned long long();
721 else
722 return operator unsigned int();
723 }
724
725 // ---------------------------------------------------------------------------
726
operator long long() const727 Setting::operator long long() const
728 {
729 assertType(TypeInt64);
730
731 return(config_setting_get_int64(_setting));
732 }
733
734 // ---------------------------------------------------------------------------
735
operator unsigned long long() const736 Setting::operator unsigned long long() const
737 {
738 assertType(TypeInt64);
739
740 long long v = config_setting_get_int64(_setting);
741
742 return(static_cast<unsigned long long>(v));
743 }
744
745 // ---------------------------------------------------------------------------
746
operator double() const747 Setting::operator double() const
748 {
749 assertType(TypeFloat);
750
751 return(config_setting_get_float(_setting));
752 }
753
754 // ---------------------------------------------------------------------------
755
operator float() const756 Setting::operator float() const
757 {
758 assertType(TypeFloat);
759
760 // may cause loss of precision:
761 return(static_cast<float>(config_setting_get_float(_setting)));
762 }
763
764 // ---------------------------------------------------------------------------
765
operator const char*() const766 Setting::operator const char *() const
767 {
768 assertType(TypeString);
769
770 return(config_setting_get_string(_setting));
771 }
772
773 // ---------------------------------------------------------------------------
774
operator std::string() const775 Setting::operator std::string() const
776 {
777 assertType(TypeString);
778
779 const char *s = config_setting_get_string(_setting);
780
781 std::string str;
782 if(s)
783 str = s;
784
785 return(str);
786 }
787
788 // ---------------------------------------------------------------------------
789
operator =(bool value)790 Setting & Setting::operator=(bool value)
791 {
792 assertType(TypeBoolean);
793
794 config_setting_set_bool(_setting, value);
795
796 return(*this);
797 }
798
799 // ---------------------------------------------------------------------------
800
operator =(int value)801 Setting & Setting::operator=(int value)
802 {
803 assertType(TypeInt);
804
805 config_setting_set_int(_setting, value);
806
807 return(*this);
808 }
809
810 // ---------------------------------------------------------------------------
811
operator =(long value)812 Setting & Setting::operator=(long value)
813 {
814 if(sizeof(long) == sizeof(long long))
815 return(operator=(static_cast<long long>(value)));
816 else
817 return(operator=(static_cast<int>(value)));
818 }
819
820 // ---------------------------------------------------------------------------
821
operator =(const long long & value)822 Setting & Setting::operator=(const long long &value)
823 {
824 assertType(TypeInt64);
825
826 config_setting_set_int64(_setting, value);
827
828 return(*this);
829 }
830
831 // ---------------------------------------------------------------------------
832
operator =(const double & value)833 Setting & Setting::operator=(const double &value)
834 {
835 assertType(TypeFloat);
836
837 config_setting_set_float(_setting, value);
838
839 return(*this);
840 }
841
842 // ---------------------------------------------------------------------------
843
operator =(float value)844 Setting & Setting::operator=(float value)
845 {
846 assertType(TypeFloat);
847
848 double cvalue = static_cast<double>(value);
849
850 config_setting_set_float(_setting, cvalue);
851
852 return(*this);
853 }
854
855 // ---------------------------------------------------------------------------
856
operator =(const char * value)857 Setting & Setting::operator=(const char *value)
858 {
859 assertType(TypeString);
860
861 config_setting_set_string(_setting, value);
862
863 return(*this);
864 }
865
866 // ---------------------------------------------------------------------------
867
operator =(const std::string & value)868 Setting & Setting::operator=(const std::string &value)
869 {
870 assertType(TypeString);
871
872 config_setting_set_string(_setting, value.c_str());
873
874 return(*this);
875 }
876
877 // ---------------------------------------------------------------------------
878
lookup(const char * path) const879 Setting & Setting::lookup(const char *path) const
880 {
881 assertType(TypeGroup);
882
883 config_setting_t *setting = config_setting_lookup(_setting, path);
884
885 if(! setting)
886 throw SettingNotFoundException(*this, path);
887
888 return(wrapSetting(setting));
889 }
890
891 // ---------------------------------------------------------------------------
892
operator [](const char * name) const893 Setting & Setting::operator[](const char *name) const
894 {
895 assertType(TypeGroup);
896
897 config_setting_t *setting = config_setting_get_member(_setting, name);
898
899 if(! setting)
900 throw SettingNotFoundException(*this, name);
901
902 return(wrapSetting(setting));
903 }
904
905 // ---------------------------------------------------------------------------
906
operator [](int i) const907 Setting & Setting::operator[](int i) const
908 {
909 if((_type != TypeArray) && (_type != TypeGroup) && (_type != TypeList))
910 throw SettingTypeException(*this, i);
911
912 config_setting_t *setting = config_setting_get_elem(_setting, i);
913
914 if(! setting)
915 throw SettingNotFoundException(*this, i);
916
917 return(wrapSetting(setting));
918 }
919
920 // ---------------------------------------------------------------------------
921
922 #define SETTING_LOOKUP_NO_EXCEPTIONS(K, T, V) \
923 try \
924 { \
925 Setting &s = operator[](K); \
926 V = (T)s; \
927 return(true); \
928 } \
929 catch(const ConfigException &) \
930 { \
931 return(false); \
932 }
933
934 // ---------------------------------------------------------------------------
935
lookupValue(const char * name,bool & value) const936 bool Setting::lookupValue(const char *name, bool &value) const
937 {
938 SETTING_LOOKUP_NO_EXCEPTIONS(name, bool, value);
939 }
940
941 // ---------------------------------------------------------------------------
942
lookupValue(const char * name,int & value) const943 bool Setting::lookupValue(const char *name, int &value) const
944 {
945 SETTING_LOOKUP_NO_EXCEPTIONS(name, int, value);
946 }
947
948 // ---------------------------------------------------------------------------
949
lookupValue(const char * name,unsigned int & value) const950 bool Setting::lookupValue(const char *name, unsigned int &value) const
951 {
952 SETTING_LOOKUP_NO_EXCEPTIONS(name, unsigned int, value);
953 }
954
955 // ---------------------------------------------------------------------------
956
lookupValue(const char * name,long long & value) const957 bool Setting::lookupValue(const char *name, long long &value) const
958 {
959 SETTING_LOOKUP_NO_EXCEPTIONS(name, long long, value);
960 }
961
962 // ---------------------------------------------------------------------------
963
lookupValue(const char * name,unsigned long long & value) const964 bool Setting::lookupValue(const char *name, unsigned long long &value) const
965 {
966 SETTING_LOOKUP_NO_EXCEPTIONS(name, unsigned long long, value);
967 }
968
969 // ---------------------------------------------------------------------------
970
lookupValue(const char * name,double & value) const971 bool Setting::lookupValue(const char *name, double &value) const
972 {
973 SETTING_LOOKUP_NO_EXCEPTIONS(name, double, value);
974 }
975
976 // ---------------------------------------------------------------------------
977
lookupValue(const char * name,float & value) const978 bool Setting::lookupValue(const char *name, float &value) const
979 {
980 SETTING_LOOKUP_NO_EXCEPTIONS(name, float, value);
981 }
982
983 // ---------------------------------------------------------------------------
984
lookupValue(const char * name,const char * & value) const985 bool Setting::lookupValue(const char *name, const char *&value) const
986 {
987 SETTING_LOOKUP_NO_EXCEPTIONS(name, const char *, value);
988 }
989
990 // ---------------------------------------------------------------------------
991
lookupValue(const char * name,std::string & value) const992 bool Setting::lookupValue(const char *name, std::string &value) const
993 {
994 SETTING_LOOKUP_NO_EXCEPTIONS(name, const char *, value);
995 }
996
997 // ---------------------------------------------------------------------------
998
exists(const char * name) const999 bool Setting::exists(const char *name) const
1000 {
1001 if(_type != TypeGroup)
1002 return(false);
1003
1004 config_setting_t *setting = config_setting_get_member(_setting, name);
1005
1006 return(setting != NULL);
1007 }
1008
1009 // ---------------------------------------------------------------------------
1010
getLength() const1011 int Setting::getLength() const
1012 {
1013 return(config_setting_length(_setting));
1014 }
1015
1016 // ---------------------------------------------------------------------------
1017
getName() const1018 const char * Setting::getName() const
1019 {
1020 return(config_setting_name(_setting));
1021 }
1022
1023 // ---------------------------------------------------------------------------
1024
getPath() const1025 std::string Setting::getPath() const
1026 {
1027 std::stringstream path;
1028
1029 __constructPath(*this, path);
1030
1031 return(path.str());
1032 }
1033
1034 // ---------------------------------------------------------------------------
1035
getParent() const1036 const Setting & Setting::getParent() const
1037 {
1038 config_setting_t *setting = config_setting_parent(_setting);
1039
1040 if(! setting)
1041 throw SettingNotFoundException(NULL);
1042
1043 return(wrapSetting(setting));
1044 }
1045
1046 // ---------------------------------------------------------------------------
1047
getParent()1048 Setting & Setting::getParent()
1049 {
1050 config_setting_t *setting = config_setting_parent(_setting);
1051
1052 if(! setting)
1053 throw SettingNotFoundException(NULL);
1054
1055 return(wrapSetting(setting));
1056 }
1057
1058 // ---------------------------------------------------------------------------
1059
getSourceLine() const1060 unsigned int Setting::getSourceLine() const
1061 {
1062 return(config_setting_source_line(_setting));
1063 }
1064
1065 // ---------------------------------------------------------------------------
1066
getSourceFile() const1067 const char *Setting::getSourceFile() const
1068 {
1069 return(config_setting_source_file(_setting));
1070 }
1071
1072 // ---------------------------------------------------------------------------
1073
isRoot() const1074 bool Setting::isRoot() const
1075 {
1076 return(config_setting_is_root(_setting));
1077 }
1078
1079 // ---------------------------------------------------------------------------
1080
getIndex() const1081 int Setting::getIndex() const
1082 {
1083 return(config_setting_index(_setting));
1084 }
1085
1086 // ---------------------------------------------------------------------------
1087
remove(const char * name)1088 void Setting::remove(const char *name)
1089 {
1090 assertType(TypeGroup);
1091
1092 if(! config_setting_remove(_setting, name))
1093 throw SettingNotFoundException(*this, name);
1094 }
1095
1096 // ---------------------------------------------------------------------------
1097
remove(unsigned int idx)1098 void Setting::remove(unsigned int idx)
1099 {
1100 if((_type != TypeArray) && (_type != TypeGroup) && (_type != TypeList))
1101 throw SettingTypeException(*this, idx);
1102
1103 if(! config_setting_remove_elem(_setting, idx))
1104 throw SettingNotFoundException(*this, idx);
1105 }
1106
1107 // ---------------------------------------------------------------------------
1108
add(const char * name,Setting::Type type)1109 Setting & Setting::add(const char *name, Setting::Type type)
1110 {
1111 assertType(TypeGroup);
1112
1113 int typecode = __toTypeCode(type);
1114
1115 if(typecode == CONFIG_TYPE_NONE)
1116 throw SettingTypeException(*this, name);
1117
1118 config_setting_t *setting = config_setting_add(_setting, name, typecode);
1119
1120 if(! setting)
1121 throw SettingNameException(*this, name);
1122
1123 return(wrapSetting(setting));
1124 }
1125
1126 // ---------------------------------------------------------------------------
1127
add(Setting::Type type)1128 Setting & Setting::add(Setting::Type type)
1129 {
1130 if((_type != TypeArray) && (_type != TypeList))
1131 throw SettingTypeException(*this);
1132
1133 if(_type == TypeArray)
1134 {
1135 int idx = getLength();
1136
1137 if(idx > 0)
1138 {
1139 Setting::Type atype = operator[](0).getType();
1140 if(type != atype)
1141 throw SettingTypeException(*this, idx);
1142 }
1143 else
1144 {
1145 if((type != TypeInt) && (type != TypeInt64) && (type != TypeFloat)
1146 && (type != TypeString) && (type != TypeBoolean))
1147 throw SettingTypeException(*this, idx);
1148 }
1149 }
1150
1151 int typecode = __toTypeCode(type);
1152 config_setting_t *s = config_setting_add(_setting, NULL, typecode);
1153
1154 Setting &ns = wrapSetting(s);
1155
1156 switch(type)
1157 {
1158 case TypeInt:
1159 ns = 0;
1160 break;
1161
1162 case TypeInt64:
1163 ns = INT64_CONST(0);
1164 break;
1165
1166 case TypeFloat:
1167 ns = 0.0;
1168 break;
1169
1170 case TypeString:
1171 ns = (char *)NULL;
1172 break;
1173
1174 case TypeBoolean:
1175 ns = false;
1176 break;
1177
1178 default:
1179 // won't happen
1180 break;
1181 }
1182
1183 return(ns);
1184 }
1185
1186 // ---------------------------------------------------------------------------
1187
assertType(Setting::Type type) const1188 void Setting::assertType(Setting::Type type) const
1189 {
1190 if(type != _type)
1191 {
1192 if(!(isNumber() && config_get_auto_convert(_setting->config)
1193 && ((type == TypeInt) || (type == TypeInt64) || (type == TypeFloat))))
1194 throw SettingTypeException(*this);
1195 }
1196 }
1197
1198 // ---------------------------------------------------------------------------
1199
wrapSetting(config_setting_t * s)1200 Setting & Setting::wrapSetting(config_setting_t *s)
1201 {
1202 Setting *setting = NULL;
1203
1204 void *hook = config_setting_get_hook(s);
1205 if(! hook)
1206 {
1207 setting = new Setting(s);
1208 config_setting_set_hook(s, reinterpret_cast<void *>(setting));
1209 }
1210 else
1211 setting = reinterpret_cast<Setting *>(hook);
1212
1213 return(*setting);
1214 }
1215
1216 // ---------------------------------------------------------------------------
1217
begin()1218 Setting::iterator Setting::begin()
1219 { return(iterator(*this)); }
1220
1221 // ---------------------------------------------------------------------------
1222
end()1223 Setting::iterator Setting::end()
1224 { return(iterator(*this, true)); }
1225
1226 // ---------------------------------------------------------------------------
1227
begin() const1228 Setting::const_iterator Setting::begin() const
1229 { return(const_iterator(*this)); }
1230
1231 // ---------------------------------------------------------------------------
1232
end() const1233 Setting::const_iterator Setting::end() const
1234 { return(const_iterator(*this, true)); }
1235
1236 // ---------------------------------------------------------------------------
1237
SettingIterator(Setting & setting,bool endIterator)1238 SettingIterator::SettingIterator(Setting& setting, bool endIterator)
1239 : _setting(&setting),
1240 _count(setting.getLength()),
1241 _idx(endIterator ? _count : 0)
1242 {
1243 if(!setting.isAggregate())
1244 throw SettingTypeException(setting);
1245 }
1246
1247 // ---------------------------------------------------------------------------
1248
SettingIterator(const SettingIterator & other)1249 SettingIterator::SettingIterator(const SettingIterator &other)
1250 : _setting(other._setting),
1251 _count(other._count),
1252 _idx(other._idx)
1253 {
1254 }
1255
1256 // ---------------------------------------------------------------------------
1257
operator =(const SettingIterator & other)1258 SettingIterator& SettingIterator::operator=(const SettingIterator &other)
1259 {
1260 _setting = other._setting;
1261 _count = other._count;
1262 _idx = other._idx;
1263
1264 return(*this);
1265 }
1266
1267 // ---------------------------------------------------------------------------
1268
operator ++()1269 SettingIterator& SettingIterator::operator++()
1270 {
1271 ++_idx;
1272
1273 return(*this);
1274 }
1275
1276 // ---------------------------------------------------------------------------
1277
operator ++(int)1278 SettingIterator SettingIterator::operator++(int)
1279 {
1280 SettingIterator tmp(*this);
1281 ++_idx;
1282
1283 return(tmp);
1284 }
1285
1286 // ---------------------------------------------------------------------------
1287
operator --()1288 SettingIterator& SettingIterator::operator--()
1289 {
1290 --_idx;
1291
1292 return(*this);
1293 }
1294
1295 // ---------------------------------------------------------------------------
1296
operator --(int)1297 SettingIterator SettingIterator::operator--(int)
1298 {
1299 SettingIterator tmp(*this);
1300 --_idx;
1301
1302 return(tmp);
1303 }
1304
1305 // ---------------------------------------------------------------------------
1306
operator +(int offset) const1307 SettingIterator SettingIterator::operator+(int offset) const
1308 {
1309 SettingIterator copy(*this);
1310 copy += offset;
1311
1312 return(copy);
1313 }
1314
1315 // ---------------------------------------------------------------------------
1316
operator +=(int offset)1317 SettingIterator& SettingIterator::operator+=(int offset)
1318 {
1319 _idx += offset;
1320
1321 return(*this);
1322 }
1323
1324 // ---------------------------------------------------------------------------
1325
operator +(int offset,SettingIterator & si)1326 SettingIterator operator+(int offset, SettingIterator& si)
1327 {
1328 SettingIterator copy(si);
1329 copy += offset;
1330
1331 return(copy);
1332 }
1333
1334 // ---------------------------------------------------------------------------
1335
operator -(int offset) const1336 SettingIterator SettingIterator::operator-(int offset) const
1337 {
1338 SettingIterator copy(*this);
1339 copy._idx -= offset;
1340
1341 return(copy);
1342 }
1343
1344 // ---------------------------------------------------------------------------
1345
operator -=(int offset)1346 SettingIterator& SettingIterator::operator-=(int offset)
1347 {
1348 _idx -= offset;
1349
1350 return(*this);
1351 }
1352
1353 // ---------------------------------------------------------------------------
1354
operator -(SettingIterator const & other) const1355 int SettingIterator::operator-(SettingIterator const &other) const
1356 {
1357 return(_idx - other._idx);
1358 }
1359
1360 // ---------------------------------------------------------------------------
1361
SettingConstIterator(const Setting & setting,bool endIterator)1362 SettingConstIterator::SettingConstIterator(const Setting &setting,
1363 bool endIterator)
1364 : _setting(&setting),
1365 _count(setting.getLength()),
1366 _idx(endIterator ? _count : 0)
1367 {
1368 if(!setting.isAggregate())
1369 throw SettingTypeException(setting);
1370 }
1371
1372 // ---------------------------------------------------------------------------
1373
SettingConstIterator(const SettingConstIterator & other)1374 SettingConstIterator::SettingConstIterator(const SettingConstIterator &other)
1375 : _setting(other._setting),
1376 _count(other._count),
1377 _idx(other._idx)
1378 {
1379 }
1380
1381 // ---------------------------------------------------------------------------
1382
operator =(const SettingConstIterator & other)1383 SettingConstIterator& SettingConstIterator::operator=(
1384 const SettingConstIterator &other)
1385 {
1386 _setting = other._setting;
1387 _count = other._count;
1388 _idx = other._idx;
1389 return(*this);
1390 }
1391
1392 // ---------------------------------------------------------------------------
1393
operator ++()1394 SettingConstIterator& SettingConstIterator::operator++()
1395 {
1396 ++_idx;
1397
1398 return(*this);
1399 }
1400
1401 // ---------------------------------------------------------------------------
1402
operator ++(int)1403 SettingConstIterator SettingConstIterator::operator++(int)
1404 {
1405 SettingConstIterator tmp(*this);
1406 ++_idx;
1407
1408 return(tmp);
1409 }
1410
1411 // ---------------------------------------------------------------------------
1412
operator --()1413 SettingConstIterator& SettingConstIterator::operator--()
1414 {
1415 --_idx;
1416
1417 return(*this);
1418 }
1419
1420 // ---------------------------------------------------------------------------
1421
operator --(int)1422 SettingConstIterator SettingConstIterator::operator--(int)
1423 {
1424 SettingConstIterator tmp(*this);
1425 --_idx;
1426
1427 return(tmp);
1428 }
1429
1430 // ---------------------------------------------------------------------------
1431
operator +(int offset) const1432 SettingConstIterator SettingConstIterator::operator+(int offset) const
1433 {
1434 SettingConstIterator copy(*this);
1435 copy += offset;
1436
1437 return(copy);
1438 }
1439
1440 // ---------------------------------------------------------------------------
1441
operator +=(int offset)1442 SettingConstIterator& SettingConstIterator::operator+=(int offset)
1443 {
1444 _idx += offset;
1445
1446 return(*this);
1447 }
1448
1449 // ---------------------------------------------------------------------------
1450
operator +(int offset,SettingConstIterator & si)1451 SettingConstIterator operator+(int offset, SettingConstIterator &si)
1452 {
1453 SettingConstIterator copy(si);
1454 copy += offset;
1455
1456 return(copy);
1457 }
1458
1459 // ---------------------------------------------------------------------------
1460
operator -(int offset) const1461 SettingConstIterator SettingConstIterator::operator-(int offset) const
1462 {
1463 SettingConstIterator copy(*this);
1464 copy -= offset;
1465
1466 return(copy);
1467 }
1468
1469 // ---------------------------------------------------------------------------
1470
operator -=(int offset)1471 SettingConstIterator& SettingConstIterator::operator-=(int offset)
1472 {
1473 _idx -= offset;
1474
1475 return(*this);
1476 }
1477
1478 // ---------------------------------------------------------------------------
1479
operator -(SettingConstIterator const & other) const1480 int SettingConstIterator::operator-(SettingConstIterator const &other) const
1481 {
1482 return(_idx - other._idx);
1483 }
1484
1485
1486 } // namespace libconfig
1487
1488