xref: /aosp_15_r20/external/libconfig/lib/libconfigcpp.c++ (revision 2e9d491483b805f09ea864149eadd5680efcc72a)
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