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