root/branches/libffado-2.0/external/libconfig/libconfig.c

Revision 1304, 31.0 kB (checked in by ppalmers, 14 years ago)

more forgotten files

Line 
1 /* ----------------------------------------------------------------------------
2    libconfig - A library for processing structured configuration files
3    Copyright (C) 2005-2008  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 #ifdef WIN32
24 #define WIN32_LEAN_AND_MEAN
25 #include <windows.h>
26 #endif
27
28 #ifdef _MSC_VER
29 #pragma warning (disable: 4996)
30 #endif
31
32 #include "libconfig.h"
33 #include "grammar.h"
34 #include "scanner.h"
35 #include "private.h"
36 #include "wincompat.h"
37
38 #include <stdlib.h>
39 #include <ctype.h>
40
41 #define PATH_TOKENS ":./"
42 #define CHUNK_SIZE 10
43 #define FLOAT_PRECISION 10
44
45 #define _new(T) (T *)calloc(sizeof(T), 1) /* zeroed */
46 #define _delete(P) free((void *)(P))
47
48 /* ------------------------------------------------------------------------- */
49
50 #ifdef WIN32
51
52 BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
53 {
54   return(TRUE);
55 }
56
57 #endif
58
59 /* ------------------------------------------------------------------------- */
60
61 static const char *__io_error = "file I/O error";
62
63 static void __config_list_destroy(config_list_t *list);
64 static void __config_write_setting(const config_setting_t *setting,
65                                    FILE *stream, int depth);
66
67 extern int libconfig_yyparse(void *scanner, struct parse_context *ctx);
68
69 /* ------------------------------------------------------------------------- */
70
71 static int __config_name_compare(const char *a, const char *b)
72 {
73   const char *p, *q;
74
75   for(p = a, q = b; ; p++, q++)
76   {
77     int pd = ((! *p) || strchr(PATH_TOKENS, *p));
78     int qd = ((! *q) || strchr(PATH_TOKENS, *q));
79
80     if(pd && qd)
81       break;
82     else if(pd)
83       return(-1);
84     else if(qd)
85       return(1);
86     else if(*p < *q)
87       return(-1);
88     else if(*p > *q)
89       return(1);
90   }
91  
92   return(0);
93 }
94
95 /* ------------------------------------------------------------------------- */
96
97 static void __config_write_value(const config_value_t *value, int type,
98                                  int format, int depth, FILE *stream)
99 {
100   char fbuf[64];
101  
102   switch(type)
103   {
104     /* boolean */
105     case CONFIG_TYPE_BOOL:
106       fputs(value->ival ? "true" : "false", stream);
107       break;
108
109     /* int */
110     case CONFIG_TYPE_INT:
111       switch(format)
112       {
113         case CONFIG_FORMAT_HEX:
114           fprintf(stream, "0x%lX", value->ival);
115           break;
116          
117         case CONFIG_FORMAT_DEFAULT:
118         default:
119           fprintf(stream, "%ld", value->ival);
120           break;
121       }
122       break;
123
124     /* 64-bit int */
125     case CONFIG_TYPE_INT64:
126       switch(format)
127       {
128         case CONFIG_FORMAT_HEX:
129           fprintf(stream, "0x" INT64_HEX_FMT "L", value->llval);
130           break;
131
132         case CONFIG_FORMAT_DEFAULT:
133         default:
134           fprintf(stream, INT64_FMT "L", value->llval);
135           break;
136       }
137       break;
138      
139     /* float */
140     case CONFIG_TYPE_FLOAT:
141     {
142       char *q;
143      
144       snprintf(fbuf, sizeof(fbuf) - 3, "%.*g", FLOAT_PRECISION, value->fval);
145
146       q = strchr(fbuf, 'e');
147       if(! q)
148       {
149         /* no exponent */
150      
151         if(! strchr(fbuf, '.')) /* no decimal point */
152           strcat(fbuf, ".0");
153         else
154         {
155           /* has decimal point */
156          
157           char *p;
158          
159           for(p = fbuf + strlen(fbuf) - 1; p > fbuf; --p)
160           {
161             if(*p != '0')
162             {
163               *(++p) = '\0';
164               break;
165             }
166           }
167         }
168       }
169      
170       fputs(fbuf, stream);
171       break;
172     }
173      
174     /* string */
175     case CONFIG_TYPE_STRING:
176     {
177       char *p;
178
179       fputc('\"', stream);
180
181       if(value->sval)
182       {
183         for(p = value->sval; *p; p++)
184         {
185           switch(*p)
186           {
187             case '\"':
188             case '\\':
189               fputc('\\', stream);
190               fputc(*p, stream);
191               break;
192              
193             case '\n':
194               fputs("\\n", stream);
195               break;
196              
197             case '\r':
198               fputs("\\r", stream);
199               break;
200              
201             case '\f':
202               fputs("\\f", stream);
203               break;
204              
205             case '\t':
206               fputs("\\t", stream);
207               break;
208              
209             default:
210               fputc(*p, stream);
211           }
212         }
213       }
214       fputc('\"', stream);
215       break;
216     }
217      
218     /* list */
219     case CONFIG_TYPE_LIST:
220     {
221       config_list_t *list = value->list;
222        
223       fprintf(stream, "( ");
224
225       if(list)
226       {
227         int len = list->length;
228         config_setting_t **s;
229
230         for(s = list->elements; len--; s++)
231         {
232           __config_write_value(&((*s)->value), (*s)->type, (*s)->format,
233                                depth + 1, stream);
234
235           if(len)
236             fputc(',', stream);
237          
238           fputc(' ', stream);
239         }
240       }
241      
242       fputc(')', stream);
243       break;
244     }
245
246     /* array */
247     case CONFIG_TYPE_ARRAY:
248     {
249       config_list_t *list = value->list;
250        
251       fprintf(stream, "[ ");
252
253       if(list)
254       {
255         int len = list->length;
256         config_setting_t **s;
257
258         for(s = list->elements; len--; s++)
259         {
260           __config_write_value(&((*s)->value), (*s)->type, (*s)->format,
261                                depth + 1, stream);
262
263           if(len)
264             fputc(',', stream);
265          
266           fputc(' ', stream);
267         }
268       }
269      
270       fputc(']', stream);
271       break;
272     }
273
274     /* group */
275     case CONFIG_TYPE_GROUP:
276     {
277       config_list_t *list = value->list;
278
279       if(depth > 0)
280       {
281         fputc('\n', stream);
282        
283         if(depth > 1)
284           fprintf(stream, "%*s", (depth - 1) * 2, " ");
285         fprintf(stream, "{\n");
286       }
287      
288       if(list)
289       {
290         int len = list->length;
291         config_setting_t **s;
292        
293         for(s = list->elements; len--; s++)
294           __config_write_setting(*s, stream, depth + 1);
295       }
296      
297       if(depth > 1)
298         fprintf(stream, "%*s", (depth - 1) * 2, " ");
299      
300       if(depth > 0)
301         fputc('}', stream);
302      
303       break;
304     }
305    
306     default:
307       /* this shouldn't happen, but handle it gracefully... */
308       fputs("???", stream);
309       break;
310   }
311 }
312
313 /* ------------------------------------------------------------------------- */
314
315 static void __config_list_add(config_list_t *list, config_setting_t *setting)
316 {
317   if(list->length == list->capacity)
318   {
319     list->capacity += CHUNK_SIZE;
320     list->elements = (config_setting_t **)realloc(
321       list->elements, list->capacity * sizeof(config_setting_t *));
322   }
323
324   list->elements[list->length] = setting;
325   list->length++;
326 }
327
328 /* ------------------------------------------------------------------------- */
329
330 static config_setting_t *__config_list_search(config_list_t *list,
331                                               const char *name,
332                                               unsigned int *idx)
333 {
334   config_setting_t **found = NULL;
335   unsigned int i;
336
337   if(! list)
338     return(NULL);
339  
340   for(i = 0, found = list->elements; i < list->length; i++, found++)
341   {
342     if(! (*found)->name)
343       continue;
344    
345     if(! __config_name_compare(name, (*found)->name))
346     {
347       if(idx)
348         *idx = i;
349      
350       return(*found);
351     }
352   }
353  
354   return(NULL);
355 }
356
357 /* ------------------------------------------------------------------------- */
358
359 static void __config_list_remove(config_list_t *list, int idx)
360 {
361   int offset = (idx * sizeof(config_setting_t *));
362   int len = list->length - 1 - idx;
363   char *base = (char *)list->elements + offset;
364
365   memmove(base, base + sizeof(config_setting_t *),
366           len * sizeof(config_setting_t *));
367
368   list->length--;
369
370   if((list->capacity - list->length) >= CHUNK_SIZE)
371   {
372     /* realloc smaller? */
373   }
374 }
375
376 /* ------------------------------------------------------------------------- */
377
378 static void __config_setting_destroy(config_setting_t *setting)
379 {
380   if(setting)
381   {
382     if(setting->name)
383       _delete(setting->name);
384
385     if(setting->type == CONFIG_TYPE_STRING)
386       _delete(setting->value.sval);
387    
388     else if((setting->type == CONFIG_TYPE_GROUP)
389             || (setting->type == CONFIG_TYPE_ARRAY)
390             || (setting->type == CONFIG_TYPE_LIST))
391     {
392       if(setting->value.list)
393         __config_list_destroy(setting->value.list);
394     }
395
396     if(setting->hook && setting->config->destructor)
397       setting->config->destructor(setting->hook);
398    
399     _delete(setting);
400   }
401 }
402
403 /* ------------------------------------------------------------------------- */
404
405 static void __config_list_destroy(config_list_t *list)
406 {
407   config_setting_t **p;
408   unsigned int i;
409
410   if(! list)
411     return;
412
413   if(list->elements)
414   {
415     for(p = list->elements, i = 0; i < list->length; p++, i++)
416       __config_setting_destroy(*p);
417    
418     _delete(list->elements);
419   }
420
421   _delete(list);
422 }
423
424 /* ------------------------------------------------------------------------- */
425
426 static int __config_vector_checktype(const config_setting_t *vector, int type)
427 {
428   /* if the array is empty, then it has no type yet */
429  
430   if(! vector->value.list)
431     return(CONFIG_TRUE);
432  
433   if(vector->value.list->length == 0)
434     return(CONFIG_TRUE);
435
436   /* if it's a list, any type is allowed */
437
438   if(vector->type == CONFIG_TYPE_LIST)
439     return(CONFIG_TRUE);
440  
441   /* otherwise the first element added determines the type of the array */
442  
443   return((vector->value.list->elements[0]->type == type)
444          ? CONFIG_TRUE : CONFIG_FALSE);
445 }
446
447 /* ------------------------------------------------------------------------- */
448
449 static int __config_validate_name(const char *name)
450 {
451   const char *p = name;
452
453   if(*p == '\0')
454     return(CONFIG_FALSE);
455
456   if(! isalpha(*p) && (*p != '*'))
457     return(CONFIG_FALSE);
458
459   for(++p; *p; ++p)
460   {
461     if(! (isalpha(*p) || isdigit(*p) || strchr("*_-", (int)*p)))
462       return(CONFIG_FALSE);
463   }
464
465   return(CONFIG_TRUE);
466 }
467
468 /* ------------------------------------------------------------------------- */
469
470 int config_read(config_t *config, FILE *stream)
471 {
472   yyscan_t scanner;
473   struct parse_context ctx;
474   int r;
475  
476   /* Reinitialize the config (keep the destructor) */
477   void (*destructor)(void *) = config->destructor;
478   config_destroy(config);
479   config_init(config);
480   config->destructor = destructor;
481
482   ctx.config = config;
483   ctx.parent = config->root;
484   ctx.setting = config->root;
485
486   libconfig_yylex_init(&scanner);
487   libconfig_yyrestart(stream, scanner);
488   r = libconfig_yyparse(scanner, &ctx);
489   libconfig_yylex_destroy(scanner);
490
491   return(r == 0 ? CONFIG_TRUE : CONFIG_FALSE);
492 }
493
494 /* ------------------------------------------------------------------------- */
495
496 static void __config_write_setting(const config_setting_t *setting,
497                                    FILE *stream, int depth)
498 {
499   if(depth > 1)
500     fprintf(stream, "%*s", (depth - 1) * 2, " ");
501
502   if(setting->name)
503   {
504     fputs(setting->name, stream);
505     fprintf(stream, " %c ", (setting->type == CONFIG_TYPE_GROUP ? ':' : '='));
506   }
507  
508   __config_write_value(&(setting->value), setting->type, setting->format,
509                        depth, stream);
510  
511   if(depth > 0)
512   {
513     fputc(';', stream);
514     fputc('\n', stream);
515   }
516 }
517
518 /* ------------------------------------------------------------------------- */
519
520 void config_write(const config_t *config, FILE *stream)
521 {
522   __config_write_setting(config->root, stream, 0);
523 }
524
525 /* ------------------------------------------------------------------------- */
526
527 int config_read_file(config_t *config, const char *filename)
528 {
529   int ret;
530   FILE *f = fopen(filename, "rt");
531   if(! f)
532   {
533     config->error_text = __io_error;
534     return(CONFIG_FALSE);
535   }
536  
537   ret = config_read(config, f);
538   fclose(f);
539   return(ret);
540 }
541
542 /* ------------------------------------------------------------------------- */
543
544 int config_write_file(config_t *config, const char *filename)
545 {
546   FILE *f = fopen(filename, "wt");
547   if(! f)
548   {
549     config->error_text = __io_error;
550     return(CONFIG_FALSE);
551   }
552  
553   config_write(config, f);
554   fclose(f);
555   return(CONFIG_TRUE);
556 }
557
558 /* ------------------------------------------------------------------------- */
559
560 void config_destroy(config_t *config)
561 {
562   __config_setting_destroy(config->root);
563
564   memset((void *)config, 0, sizeof(config_t));
565 }
566
567 /* ------------------------------------------------------------------------- */
568
569 void config_init(config_t *config)
570 {
571   memset((void *)config, 0, sizeof(config_t));
572
573   config->root = _new(config_setting_t);
574   config->root->type = CONFIG_TYPE_GROUP;
575   config->root->config = config;
576 }
577
578 /* ------------------------------------------------------------------------- */
579
580 void config_set_auto_convert(config_t *config, int flag)
581 {
582   if(flag)
583     config->flags |= CONFIG_OPTION_AUTOCONVERT;
584   else
585     config->flags &= ~CONFIG_OPTION_AUTOCONVERT;
586 }
587
588 /* ------------------------------------------------------------------------- */
589
590 int config_get_auto_convert(const config_t *config)
591 {
592   return((config->flags & CONFIG_OPTION_AUTOCONVERT) != 0);
593 }
594
595 /* ------------------------------------------------------------------------- */
596
597 static config_setting_t *config_setting_create(config_setting_t *parent,
598                                                const char *name, int type)
599 {
600   config_setting_t *setting;
601   config_list_t *list;
602
603   if((parent->type != CONFIG_TYPE_GROUP)
604      && (parent->type != CONFIG_TYPE_ARRAY)
605      && (parent->type != CONFIG_TYPE_LIST))
606     return(NULL);
607
608   setting = _new(config_setting_t);
609   setting->parent = parent;
610   setting->name = (name == NULL) ? NULL : strdup(name);
611   setting->type = type;
612   setting->config = parent->config;
613   setting->hook = NULL;
614   setting->line = 0;
615
616   list = parent->value.list;
617  
618   if(! list)
619     list = parent->value.list = _new(config_list_t);
620
621   __config_list_add(list, setting);
622
623   return(setting);
624 }
625
626 /* ------------------------------------------------------------------------- */
627
628 long config_setting_get_int(const config_setting_t *setting)
629 {
630   switch(setting->type)
631   {
632     case CONFIG_TYPE_INT:
633       return(setting->value.ival);
634
635     case CONFIG_TYPE_INT64:
636       if((setting->value.llval > INT32_MAX)
637          || (setting->value.llval < INT32_MIN))
638         return(0);
639       else
640         return((long)setting->value.llval);
641      
642     case CONFIG_TYPE_FLOAT:
643       if((setting->config->flags & CONFIG_OPTION_AUTOCONVERT) != 0)
644         return((long)(setting->value.fval));
645       else
646         /* fall through */;
647      
648     default:
649       return(0);
650   }
651 }
652
653 /* ------------------------------------------------------------------------- */
654
655 long long config_setting_get_int64(const config_setting_t *setting)
656 {
657   switch(setting->type)
658   {
659     case CONFIG_TYPE_INT64:
660       return(setting->value.llval);
661      
662     case CONFIG_TYPE_INT:
663       return((long long)setting->value.ival);
664
665     case CONFIG_TYPE_FLOAT:
666       if((setting->config->flags & CONFIG_OPTION_AUTOCONVERT) != 0)
667         return((long long)(setting->value.fval));
668       else
669         /* fall through */;
670      
671     default:
672       return(0);
673   }
674 }
675
676 /* ------------------------------------------------------------------------- */
677
678 int config_setting_set_int(config_setting_t *setting, long value)
679 {
680   switch(setting->type)
681   {
682     case CONFIG_TYPE_NONE:
683       setting->type = CONFIG_TYPE_INT;
684       /* fall through */
685
686     case CONFIG_TYPE_INT:
687       setting->value.ival = value;
688       return(CONFIG_TRUE);
689
690     case CONFIG_TYPE_FLOAT:
691       if(config_get_auto_convert(setting->config))
692       {
693         setting->value.fval = (float)value;
694         return(CONFIG_TRUE);
695       }
696       else
697         return(CONFIG_FALSE);
698
699     default:
700       return(CONFIG_FALSE);
701   }
702 }
703
704 /* ------------------------------------------------------------------------- */
705
706 int config_setting_set_int64(config_setting_t *setting, long long value)
707 {
708   switch(setting->type)
709   {
710     case CONFIG_TYPE_NONE:
711       setting->type = CONFIG_TYPE_INT64;
712       /* fall through */
713
714     case CONFIG_TYPE_INT64:
715       setting->value.llval = value;
716       return(CONFIG_TRUE);
717
718     case CONFIG_TYPE_INT:
719       if((value > INT32_MAX) || (value < INT32_MIN))
720         setting->value.ival = 0;
721       else
722         setting->value.ival = (long)value;
723       return(CONFIG_TRUE);
724
725     case CONFIG_TYPE_FLOAT:
726       if(config_get_auto_convert(setting->config))
727       {
728         setting->value.fval = (float)value;
729         return(CONFIG_TRUE);
730       }
731       else
732         return(CONFIG_FALSE);
733
734     default:
735       return(CONFIG_FALSE);
736   }
737 }
738
739 /* ------------------------------------------------------------------------- */
740
741 double config_setting_get_float(const config_setting_t *setting)
742 {
743   switch(setting->type)
744   {
745     case CONFIG_TYPE_FLOAT:
746       return(setting->value.fval);
747
748     case CONFIG_TYPE_INT:
749       if(config_get_auto_convert(setting->config))
750         return((double)(setting->value.ival));
751       else
752         return(0.0);
753
754     case CONFIG_TYPE_INT64:
755       if(config_get_auto_convert(setting->config))
756         return((double)(setting->value.llval));
757       else
758         return(0.0);
759
760     default:
761       return(0.0);
762   }
763 }
764
765 /* ------------------------------------------------------------------------- */
766
767 int config_setting_set_float(config_setting_t *setting, double value)
768 {
769   switch(setting->type)
770   {
771     case CONFIG_TYPE_NONE:
772       setting->type = CONFIG_TYPE_FLOAT;
773       /* fall through */
774
775     case CONFIG_TYPE_FLOAT:
776       setting->value.fval = value;
777       return(CONFIG_TRUE);
778
779     case CONFIG_TYPE_INT:
780       if((setting->config->flags & CONFIG_OPTION_AUTOCONVERT) != 0)
781       {
782         setting->value.ival = (long)value;
783         return(CONFIG_TRUE);
784       }
785       else
786         return(CONFIG_FALSE);
787
788     case CONFIG_TYPE_INT64:
789       if((setting->config->flags & CONFIG_OPTION_AUTOCONVERT) != 0)
790       {
791         setting->value.llval = (long long)value;
792         return(CONFIG_TRUE);
793       }
794       else
795         return(CONFIG_FALSE);
796
797     default:
798       return(CONFIG_FALSE);
799   }
800 }
801
802 /* ------------------------------------------------------------------------- */
803
804 int config_setting_get_bool(const config_setting_t *setting)
805 {
806   return((setting->type == CONFIG_TYPE_BOOL) ? setting->value.ival : 0);
807 }
808
809 /* ------------------------------------------------------------------------- */
810
811 int config_setting_set_bool(config_setting_t *setting, int value)
812 {
813   if(setting->type == CONFIG_TYPE_NONE)
814     setting->type = CONFIG_TYPE_BOOL;
815   else if(setting->type != CONFIG_TYPE_BOOL)
816     return(CONFIG_FALSE);
817  
818   setting->value.ival = value;
819   return(CONFIG_TRUE);
820 }
821
822 /* ------------------------------------------------------------------------- */
823
824 const char *config_setting_get_string(const config_setting_t *setting)
825 {
826   return((setting->type == CONFIG_TYPE_STRING) ? setting->value.sval : NULL);
827 }
828
829 /* ------------------------------------------------------------------------- */
830
831 int config_setting_set_string(config_setting_t *setting, const char *value)
832 {
833   if(setting->type == CONFIG_TYPE_NONE)
834     setting->type = CONFIG_TYPE_STRING;
835   else if(setting->type != CONFIG_TYPE_STRING)
836     return(CONFIG_FALSE);
837  
838   if(setting->value.sval)
839     _delete(setting->value.sval);
840    
841   setting->value.sval = (value == NULL) ? NULL : strdup(value);
842   return(CONFIG_TRUE);
843 }
844
845 /* ------------------------------------------------------------------------- */
846
847 int config_setting_set_format(config_setting_t *setting, short format)
848 {
849   if(((setting->type != CONFIG_TYPE_INT)
850       && (setting->type != CONFIG_TYPE_INT64))
851      || ((format != CONFIG_FORMAT_DEFAULT) && (format != CONFIG_FORMAT_HEX)))
852     return(CONFIG_FALSE);
853
854   setting->format = format;
855  
856   return(CONFIG_TRUE);
857 }
858
859 /* ------------------------------------------------------------------------- */
860
861 short config_setting_get_format(config_setting_t *setting)
862 {
863   return(setting->format);
864 }
865
866 /* ------------------------------------------------------------------------- */
867
868 config_setting_t *config_lookup(const config_t *config, const char *path)
869 {
870   const char *p = path;
871   config_setting_t *setting = config->root, *found;
872
873   for(;;)
874   {
875     while(*p && strchr(PATH_TOKENS, *p))
876       p++;
877
878     if(! *p)
879       break;
880
881     if(*p == '[')
882       found = config_setting_get_elem(setting, atoi(++p));
883     else
884       found = config_setting_get_member(setting, p);
885
886     if(! found)
887       break;
888
889     setting = found;
890
891     while(! strchr(PATH_TOKENS, *p))
892       p++;   
893   }
894      
895   return(*p ? NULL : setting);
896 }
897
898 /* ------------------------------------------------------------------------- */
899
900 const char *config_lookup_string(const config_t *config, const char *path)
901 {
902   const config_setting_t *s = config_lookup(config, path);
903   if(! s)
904     return(NULL);
905
906   return(config_setting_get_string(s));
907 }
908
909 /* ------------------------------------------------------------------------- */
910
911 long config_lookup_int(const config_t *config, const char *path)
912 {
913   const config_setting_t *s = config_lookup(config, path);
914   if(! s)
915     return(0);
916
917   return(config_setting_get_int(s));
918 }
919
920 /* ------------------------------------------------------------------------- */
921
922 long long config_lookup_int64(const config_t *config, const char *path)
923 {
924   const config_setting_t *s = config_lookup(config, path);
925   if(! s)
926     return(INT64_CONST(0));
927
928   return(config_setting_get_int64(s));
929 }
930
931 /* ------------------------------------------------------------------------- */
932
933 double config_lookup_float(const config_t *config, const char *path)
934 {
935   const config_setting_t *s = config_lookup(config, path);
936   if(! s)
937     return(0.0);
938
939   return(config_setting_get_float(s));
940 }
941
942 /* ------------------------------------------------------------------------- */
943
944 int config_lookup_bool(const config_t *config, const char *path)
945 {
946   const config_setting_t *s = config_lookup(config, path);
947   if(! s)
948     return(0);
949
950   return(config_setting_get_bool(s));
951 }
952
953 /* ------------------------------------------------------------------------- */
954
955 long config_setting_get_int_elem(const config_setting_t *vector, int idx)
956 {
957   const config_setting_t *element = config_setting_get_elem(vector, idx);
958
959   return(element ? config_setting_get_int(element) : 0);
960 }
961
962 /* ------------------------------------------------------------------------- */
963
964 config_setting_t *config_setting_set_int_elem(config_setting_t *vector,
965                                               int idx, long value)
966 {
967   config_setting_t *element = NULL;
968
969   if((vector->type != CONFIG_TYPE_ARRAY) && (vector->type != CONFIG_TYPE_LIST))
970     return(NULL);
971  
972   if(idx < 0)
973   {
974     if(! __config_vector_checktype(vector, CONFIG_TYPE_INT))
975       return(NULL);
976    
977     element = config_setting_create(vector, NULL, CONFIG_TYPE_INT);
978   }
979   else
980   {
981     element = config_setting_get_elem(vector, idx);
982
983     if(! element)
984       return(NULL);
985   }
986
987   if(! config_setting_set_int(element, value))
988     return(NULL);
989
990   return(element);
991 }
992
993 /* ------------------------------------------------------------------------- */
994
995 long long config_setting_get_int64_elem(const config_setting_t *vector,
996                                         int idx)
997 {
998   const config_setting_t *element = config_setting_get_elem(vector, idx);
999
1000   return(element ? config_setting_get_int64(element) : 0);
1001 }
1002
1003 /* ------------------------------------------------------------------------- */
1004
1005 config_setting_t *config_setting_set_int64_elem(config_setting_t *vector,
1006                                                 int idx, long long value)
1007 {
1008   config_setting_t *element = NULL;
1009
1010   if((vector->type != CONFIG_TYPE_ARRAY) && (vector->type != CONFIG_TYPE_LIST))
1011     return(NULL);
1012  
1013   if(idx < 0)
1014   {
1015     if(! __config_vector_checktype(vector, CONFIG_TYPE_INT64))
1016       return(NULL);
1017    
1018     element = config_setting_create(vector, NULL, CONFIG_TYPE_INT64);
1019   }
1020   else
1021   {
1022     element = config_setting_get_elem(vector, idx);
1023
1024     if(! element)
1025       return(NULL);
1026   }
1027
1028   if(! config_setting_set_int64(element, value))
1029     return(NULL);
1030
1031   return(element);
1032 }
1033
1034 /* ------------------------------------------------------------------------- */
1035
1036 double config_setting_get_float_elem(const config_setting_t *vector, int idx)
1037 {
1038   config_setting_t *element = config_setting_get_elem(vector, idx);
1039
1040   return(element ? config_setting_get_float(element) : 0.0);
1041 }
1042
1043 /* ------------------------------------------------------------------------- */
1044
1045 config_setting_t *config_setting_set_float_elem(config_setting_t *vector,
1046                                                 int idx, double value)
1047 {
1048   config_setting_t *element = NULL;
1049
1050   if((vector->type != CONFIG_TYPE_ARRAY) && (vector->type != CONFIG_TYPE_LIST))
1051     return(NULL);
1052
1053   if(idx < 0)
1054   {
1055     if(! __config_vector_checktype(vector, CONFIG_TYPE_FLOAT))
1056       return(NULL);
1057    
1058     element = config_setting_create(vector, NULL, CONFIG_TYPE_FLOAT);
1059   }
1060   else
1061     element = config_setting_get_elem(vector, idx);
1062
1063   if(! element)
1064     return(NULL);
1065
1066   if(! config_setting_set_float(element, value))
1067     return(NULL);
1068  
1069   return(element);
1070 }
1071
1072 /* ------------------------------------------------------------------------- */
1073
1074 int config_setting_get_bool_elem(const config_setting_t *vector, int idx)
1075 {
1076   config_setting_t *element = config_setting_get_elem(vector, idx);
1077
1078   if(! element)
1079     return(CONFIG_FALSE);
1080  
1081   if(element->type != CONFIG_TYPE_BOOL)
1082     return(CONFIG_FALSE);
1083
1084   return(element->value.ival);
1085 }
1086
1087 /* ------------------------------------------------------------------------- */
1088
1089 config_setting_t *config_setting_set_bool_elem(config_setting_t *vector,
1090                                                int idx, int value)
1091 {
1092   config_setting_t *element = NULL;
1093
1094   if((vector->type != CONFIG_TYPE_ARRAY) && (vector->type != CONFIG_TYPE_LIST))
1095     return(NULL);
1096
1097   if(idx < 0)
1098   {
1099     if(! __config_vector_checktype(vector, CONFIG_TYPE_BOOL))
1100       return(NULL);
1101    
1102     element = config_setting_create(vector, NULL, CONFIG_TYPE_BOOL);
1103   }
1104   else
1105     element = config_setting_get_elem(vector, idx);
1106
1107   if(! element)
1108     return(NULL);
1109
1110   if(! config_setting_set_bool(element, value))
1111     return(NULL);
1112  
1113   return(element);
1114 }
1115
1116 /* ------------------------------------------------------------------------- */
1117
1118 const char *config_setting_get_string_elem(const config_setting_t *vector,
1119                                            int idx)
1120 {
1121   config_setting_t *element = config_setting_get_elem(vector, idx);
1122
1123   if(! element)
1124     return(NULL);
1125  
1126   if(element->type != CONFIG_TYPE_STRING)
1127     return(NULL);
1128
1129   return(element->value.sval);
1130 }
1131
1132 /* ------------------------------------------------------------------------- */
1133
1134 config_setting_t *config_setting_set_string_elem(config_setting_t *vector,
1135                                                  int idx, const char *value)
1136 {
1137   config_setting_t *element = NULL;
1138
1139   if((vector->type != CONFIG_TYPE_ARRAY) && (vector->type != CONFIG_TYPE_LIST))
1140     return(NULL);
1141
1142   if(idx < 0)
1143   {
1144     if(! __config_vector_checktype(vector, CONFIG_TYPE_STRING))
1145       return(NULL);
1146    
1147     element = config_setting_create(vector, NULL, CONFIG_TYPE_STRING);
1148   }
1149   else
1150     element = config_setting_get_elem(vector, idx);
1151
1152   if(! element)
1153     return(NULL);
1154
1155   if(! config_setting_set_string(element, value))
1156     return(NULL);
1157  
1158   return(element);
1159 }
1160
1161 /* ------------------------------------------------------------------------- */
1162
1163 config_setting_t *config_setting_get_elem(const config_setting_t *vector,
1164                                           unsigned int idx)
1165 {
1166   config_list_t *list = vector->value.list;
1167  
1168   if(((vector->type != CONFIG_TYPE_ARRAY)
1169       && (vector->type != CONFIG_TYPE_LIST)
1170       && (vector->type != CONFIG_TYPE_GROUP)) || ! list)
1171     return(NULL);
1172
1173   if(idx >= list->length)
1174     return(NULL);
1175
1176   return(list->elements[idx]);
1177 }
1178
1179 /* ------------------------------------------------------------------------- */
1180
1181 config_setting_t *config_setting_get_member(const config_setting_t *setting,
1182                                             const char *name)
1183 {
1184   if(setting->type != CONFIG_TYPE_GROUP)
1185     return(NULL);
1186
1187   return(__config_list_search(setting->value.list, name, NULL));
1188 }
1189
1190 /* ------------------------------------------------------------------------- */
1191
1192 void config_set_destructor(config_t *config, void (*destructor)(void *))
1193 {
1194   config->destructor = destructor;
1195 }
1196
1197 /* ------------------------------------------------------------------------- */
1198
1199 int config_setting_length(const config_setting_t *setting)
1200 {
1201   if((setting->type != CONFIG_TYPE_GROUP)
1202      && (setting->type != CONFIG_TYPE_ARRAY)
1203      && (setting->type != CONFIG_TYPE_LIST))
1204     return(0);
1205  
1206   if(! setting->value.list)
1207     return(0);
1208
1209   return(setting->value.list->length);
1210 }
1211
1212 /* ------------------------------------------------------------------------- */
1213
1214 void config_setting_set_hook(config_setting_t *setting, void *hook)
1215 {
1216   setting->hook = hook;
1217 }
1218
1219 /* ------------------------------------------------------------------------- */
1220
1221 config_setting_t *config_setting_add(config_setting_t *parent,
1222                                      const char *name, int type)
1223 {
1224   if((type < CONFIG_TYPE_NONE) || (type > CONFIG_TYPE_LIST))
1225     return(NULL);
1226
1227   if(! parent)
1228     return(NULL);
1229
1230   if((parent->type == CONFIG_TYPE_ARRAY) || (parent->type == CONFIG_TYPE_LIST))
1231     name = NULL;
1232
1233   if(name)
1234   {
1235     if(! __config_validate_name(name))
1236       return(NULL);
1237   }
1238    
1239   if(config_setting_get_member(parent, name) != NULL)
1240     return(NULL); /* already exists */
1241
1242   return(config_setting_create(parent, name, type));
1243 }
1244
1245 /* ------------------------------------------------------------------------- */
1246
1247 int config_setting_remove(config_setting_t *parent, const char *name)
1248 {
1249   unsigned int idx;
1250   config_setting_t *setting;
1251  
1252   if(! parent)
1253     return(CONFIG_FALSE);
1254
1255   if(parent->type != CONFIG_TYPE_GROUP)
1256     return(CONFIG_FALSE);
1257
1258   if(! (setting = __config_list_search(parent->value.list, name, &idx)))
1259     return(CONFIG_FALSE);
1260
1261   __config_setting_destroy(setting);
1262  
1263   __config_list_remove(parent->value.list, idx);
1264
1265   return(CONFIG_TRUE);
1266 }
1267
1268 /* ------------------------------------------------------------------------- */
1269
1270 int config_setting_remove_elem(config_setting_t *parent, unsigned int idx)
1271 {
1272   config_list_t *list = parent->value.list;
1273
1274   if(((parent->type != CONFIG_TYPE_ARRAY)
1275       && (parent->type != CONFIG_TYPE_LIST)
1276       && (parent->type != CONFIG_TYPE_GROUP)) || ! list)
1277     return(CONFIG_FALSE);
1278  
1279   if(idx >= list->length)
1280     return(CONFIG_FALSE);
1281
1282   __config_list_remove(list, idx);
1283
1284   return(CONFIG_TRUE);
1285 }
1286
1287 /* ------------------------------------------------------------------------- */
1288
1289 int config_setting_index(const config_setting_t *setting)
1290 {
1291   config_setting_t **found = NULL;
1292   config_list_t *list;
1293   int i;
1294
1295   if(! setting->parent)
1296     return(-1);
1297
1298   list = setting->parent->value.list;
1299
1300   for(i = 0, found = list->elements; i < list->length; ++i, ++found)
1301   {
1302     if(*found == setting)
1303       return(i);
1304   }
1305
1306   return(-1);
1307 }
1308
1309 /* ------------------------------------------------------------------------- */
1310 /* eof */
Note: See TracBrowser for help on using the browser.