]> mj.ucw.cz Git - libucw.git/blobdiff - lib/conf-test.c
Merge with git+ssh://cvs.ucw.cz/projects/sherlock/GIT/sherlock.git
[libucw.git] / lib / conf-test.c
index a2242be2d0389136a63c6c41a5865cee9572670d..f4ca15fdb7fba7022eb8da4ad34c876df3e853e9 100644 (file)
-/* Test for configuration parser */
-
-#include <stdio.h>
-#include <string.h>
-#include <getopt.h>
+/*
+ *     Insane tester of reading configuration files
+ *
+ *     (c) 2006 Robert Spalek <robert@ucw.cz>
+ */
 
 #include "lib/lib.h"
 #include "lib/conf.h"
 
 #include "lib/lib.h"
 #include "lib/conf.h"
+#include "lib/getopt.h"
+#include "lib/clists.h"
+#include "lib/fastbuf.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <time.h>
 
 
-static int robert=14;
-static int spalek=-3;
-static char *heslo="prazdne";
-static int nastaveni1=0,nastaveni2=1;
+static int verbose;
 
 
-static byte *set_nastaveni(struct cfitem *item, byte *value)
+struct sub_sect_1 {
+  cnode n;
+  byte *name;
+  time_t t;
+  byte *level;
+  int confidence[2];
+  double *list;
+};
+
+static struct sub_sect_1 sec1 = { {}, "Charlie", 0, "WBAFC", { 0, -1}, DARY_ALLOC(double, 3, 1e4, -1e-4, 8) };
+
+static byte *
+init_sec_1(struct sub_sect_1 *s)
 {
 {
-       int id;
-       if(!strcasecmp(value,"one"))
-               id=1;
-       else if(!strcasecmp(value,"two"))
-               id=2;
-       else if(!strcasecmp(value,"three"))
-               id=3;
-       else if(!strcasecmp(value,"four"))
-               id=4;
-       else
-               return "Invalid value of nastaveni";
-       if(!strcasecmp(item->name,"nastaveni1"))
-               nastaveni1=id;
-       else if(!strcasecmp(item->name,"nastaveni2"))
-               nastaveni2=id;
-       else
-               return "Internal error of nastaveni";
-       return NULL;
+  if (s == &sec1)                      // this is a static variable; skip clearing
+    return NULL;
+  s->name = "unknown";
+  s->level = "default";
+  s->confidence[0] = 5;
+  s->confidence[1] = 6;
+  // leave s->list==NULL
+  return NULL;
 }
 
 }
 
-static struct cfitem jmeno[]={
-       {"jmeno",       CT_SECTION,     NULL},
-       {"robert",      CT_INT,         &robert},
-       {"spalek",      CT_INT,         &spalek},
-       {"heslo",       CT_STRING,      &heslo},
-       {"nastaveni1",  CT_FUNCTION,    &set_nastaveni},
-       {"nastaveni2",  CT_FUNCTION,    &set_nastaveni},
-       {NULL,          CT_STOP,        NULL}
+static byte *
+commit_sec_1(struct sub_sect_1 *s)
+{
+  if (s->confidence[0] < 0 || s->confidence[0] > 10)
+    return "Well, this can't be";
+  return NULL;
+}
+
+static byte *
+time_parser(uns number, byte **pars, time_t *ptr)
+{
+  *ptr = number ? atoi(pars[0]) : time(NULL);
+  return NULL;
+}
+
+static struct cf_section cf_sec_1 = {
+  CF_TYPE(struct sub_sect_1),
+  CF_INIT(init_sec_1),
+  CF_COMMIT(commit_sec_1),
+#define F(x)   PTR_TO(struct sub_sect_1, x)
+  CF_ITEMS {
+    CF_STRING("name", F(name)),
+    //CF_PARSER("t", F(t), time_parser, 0),
+    CF_STRING("level", F(level)),
+    CF_INT_ARY("confidence", F(confidence[0]), 2),             // XXX: the [0] is needed for the sake of type checking
+    CF_DOUBLE_DYN("list", F(list), 100),
+    CF_END
+  }
+#undef F
 };
 
 };
 
-static int vek=22;
-static int vyska=178;
-static int vaha=66;
+static uns nr1 = 15;
+static int *nrs1 = DARY_ALLOC(int, 5, 5, 4, 3, 2, 1);
+static int nrs2[5];
+static byte *str1 = "no worries";
+static byte **str2 = DARY_ALLOC(byte *, 2, "Alice", "Bob");
+static u64 u1 = 0xCafeBeefDeadC00ll;
+static double d1 = -1.1;
+static clist secs;
+static time_t t1, t2;
+static u32 ip;
+static int *look = DARY_ALLOC(int, 2, 2, 1);
+static u16 numbers[10] = { 2, 100, 1, 5 };
+static u32 bitmap1 = 0xff;
+static u32 bitmap2 = 3;
+
+static byte *
+parse_u16(byte *string, u16 *ptr)
+{
+  uns a;
+  byte *msg = cf_parse_int(string, &a);
+  if (msg)
+    return msg;
+  if (a >= (1<<16))
+    return "Come on, man, this doesn't fit to 16 bits";
+  *ptr = a;
+  return NULL;
+}
 
 
-static struct cfitem telo[]={
-       {"telo",        CT_SECTION,     NULL},
-       {"vek",         CT_INT,         &vek},
-       {"vyska",       CT_INT,         &vyska},
-       {"vaha",        CT_INT,         &vaha},
-       {NULL,          CT_STOP,        NULL}
+static void
+dump_u16(struct fastbuf *fb, u16 *ptr)
+{
+  bprintf(fb, "%d ", *ptr);
+}
+
+static struct cf_user_type u16_type = {
+  .size = sizeof(u16),
+  .name = "u16",
+  .parser = (cf_parser1*) parse_u16,
+  .dumper = (cf_dumper1*) dump_u16
 };
 
 };
 
-static byte shortopts[] = CF_SHORT_OPTS "abcp:q:r::";
-static struct option longopts[] =
+static byte *
+init_top(void *ptr UNUSED)
 {
 {
+  for (uns i=0; i<5; i++)
+  {
+    struct sub_sect_1 *s = xmalloc(sizeof(struct sub_sect_1)); // XXX: cannot by cf_malloc(), because it's deleted when cf_reload()'ed
+    cf_init_section("slaves", &cf_sec_1, s, 1);
+    s->confidence[1] = i;
+    clist_add_tail(&secs, &s->n);
+  }
+  return NULL;
+}
+
+static byte *
+commit_top(void *ptr UNUSED)
+{
+  if (nr1 != 15)
+    return "Don't touch my variable!";
+  return NULL;
+}
+
+static byte *alphabet[] = { "alpha", "beta", "gamma", "delta", NULL };
+static struct cf_section cf_top = {
+  CF_INIT(init_top),
+  CF_COMMIT(commit_top),
+  CF_ITEMS {
+    CF_UNS("nr1", &nr1),
+    CF_INT_DYN("nrs1", &nrs1, 1000),
+    CF_INT_ARY("nrs2", nrs2, 5),
+    CF_STRING("str1", &str1),
+    CF_STRING_DYN("str2", &str2, 20),
+    CF_U64("u1", &u1),
+    CF_DOUBLE("d1", &d1),
+    CF_PARSER("FirstTime", &t1, time_parser, -1),
+    CF_PARSER("SecondTime", &t2, time_parser, 1),
+    CF_SECTION("master", &sec1, &cf_sec_1),
+    CF_LIST("slaves", &secs, &cf_sec_1),
+    CF_IP("ip", &ip),
+    CF_LOOKUP_DYN("look", &look, alphabet, 1000),
+    CF_USER_ARY("numbers", numbers, &u16_type, 10),
+    CF_BITMAP_INT("bitmap1", &bitmap1),
+    CF_BITMAP_LOOKUP("bitmap2", &bitmap2, ((byte*[]) {
+         "one", "two", "three", "four", "five", "six", "seven", "eight", 
+         "nine", "ten", "eleven", "twelve", "thirteen", "fourteen", "fifteen", "seventeen", 
+         "eighteen", "nineteen", "twenty", NULL        // hidden joke here
+         })),
+    CF_END
+  }
+};
+
+static byte short_opts[] = CF_SHORT_OPTS "v";
+static struct option long_opts[] = {
        CF_LONG_OPTS
        CF_LONG_OPTS
-       {"ahoj",        0, 0, 'a'},
-       {"bida",        0, 0, 'b'},
-       {"citron",      0, 0, 'c'},
-       {"pivo",        1, 0, 'p'},
-       {"qwerty",      1, 0, 'q'},
-       {"rada",        2, 0, 'r'},
+       {"verbose",     0, 0, 'v'},
        {NULL,          0, 0, 0}
 };
 
        {NULL,          0, 0, 0}
 };
 
-int main(int argc, char *argv[])
+static char *help = "\
+Usage: conf-test <options>\n\
+\n\
+Options:\n"
+CF_USAGE
+"-v\t\t\tBe verbose\n\
+";
+
+static void NONRET
+usage(byte *msg, ...)
+{
+  va_list va;
+  va_start(va, msg);
+  if (msg)
+    vfprintf(stderr, msg, va);
+  fputs(help, stderr);
+  exit(1);
+}
+
+int
+main(int argc, char *argv[])
 {
 {
-       int c;
-
-       log_init(argv[0]);
-
-       cf_register(jmeno);
-       cf_register(telo);
-
-       while(1){
-               c=cf_getopt(argc,argv,shortopts,longopts,NULL);
-               if(c==-1)
-                       break;
-               else switch(c){
-                       case 'a':
-                       case 'b':
-                       case 'c':
-                               printf("option %c\n",c);
-                               break;
-
-                       case 'p':
-                       case 'q':
-                               printf("option %c with parameter %s\n",c,optarg);
-                               break;
-                       case 'r':
-                               if(optarg)
-                                       printf("option r with optional parameter %s\n",optarg);
-                               else
-                                       printf("option r without optional parameter\n");
-                               break;
-                       case '?':
-                               //printf("invalid parameter %d: %s\n",optind,argv[optind]);
-                               break;
-                       case ':':
-                               //printf("missing parameter for %d: %s\n",optind,argv[optind]);
-                               break;
-                       default:
-                               printf("getopt is confused, it returns %c\n",c);
-                               break;
-               }
-       }
-
-       if (optind < argc)
-       {
-               printf ("non-option ARGV-elements: ");
-               while (optind < argc)
-                       printf ("%s ", argv[optind++]);
-               printf ("\n");
-       }
-
-       printf("robert=%d, spalek=%d, heslo=%s, nastaveni1/2=%d/%d\n",
-                       robert,spalek,heslo,nastaveni1,nastaveni2);
-       printf("vek=%d, vyska=%d, vaha=%d\n",
-                       vek,vyska,vaha);
-
-       return 0;
+  log_init(argv[0]);
+  cf_declare_section("top", &cf_top, 0);
+  cf_def_file = "lib/conf-test.cf";
+
+  int opt;
+  while ((opt = cf_getopt(argc, argv, short_opts, long_opts, NULL)) >= 0)
+    switch (opt) {
+      case 'v': verbose++; break;
+      default: usage("unknown option %c\n", opt);
+    }
+  if (optind < argc)
+    usage("too many parameters (%d more)\n", argc-optind);
+
+  /*
+  cf_load("non-existent file");
+  //cf_reload("non-existent file");
+  cf_load("non-existent file");
+  cf_set("top.d1 -1.1; top.master b");
+  */
+
+  struct fastbuf *out = bfdopen(1, 1<<14);
+  cf_dump_sections(out);
+  bclose(out);
+
+  return 0;
 }
 }