root/library/bdm/base/libconfig/libconfig.c @ 638

Revision 303, 32.3 kB (checked in by suzdalev, 15 years ago)

cmake mac Os X configuration

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