00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00042 #include "dnxCfgParser.h"
00043
00044 #include "dnxLogging.h"
00045 #include "dnxError.h"
00046 #include "dnxDebug.h"
00047
00048 #include <stdio.h>
00049 #include <stdlib.h>
00050 #include <stdint.h>
00051 #include <string.h>
00052 #include <ctype.h>
00053 #include <assert.h>
00054 #include <errno.h>
00055
00056 #define elemcount(x) (sizeof(x)/sizeof(*(x)))
00057
00058 #define DNX_MAX_CFG_LINE 2048
00059
00060
00065 typedef struct iDnxCfgParser
00066 {
00067 char * cfgfile;
00068 char ** cfgdefs;
00069 char ** cmdover;
00070 DnxCfgDict * dict;
00071 unsigned dictsz;
00072 DnxCfgValidator_t * vfp;
00073 char * curcfg;
00074 size_t ccsize;
00075 } iDnxCfgParser;
00076
00078 typedef int DnxVarParser_t(char * val, DnxCfgType type, void * prval);
00079
00081 typedef char * DnxVarFormatter_t(char * var, DnxCfgType type, void * prval);
00082
00083
00084
00085
00086
00095 static char ** strToStrArray(char * str, char delim)
00096 {
00097 int cnt;
00098 size_t strsz;
00099 char * p, ** sap;
00100
00101
00102 if (!str) return 0;
00103
00104
00105 (cnt = 1), p = str;
00106 while ((p = strchr(p, delim)) != 0)
00107 p++, cnt++;
00108
00109
00110 strsz = strlen(str) + 1;
00111 if ((sap = (char **)xmalloc((cnt + 1) * sizeof *sap + strsz)) == 0)
00112 return 0;
00113
00114
00115 p = (char *)&sap[cnt + 1];
00116 memcpy(p, str, strsz);
00117
00118
00119 (cnt = 0), sap[cnt++] = p;
00120 while ((p = strchr(p, delim)) != 0)
00121 (*p++ = 0), sap[cnt++] = p;
00122 sap[cnt] = 0;
00123
00124 return sap;
00125 }
00126
00127
00128
00141 static DnxCfgDict * copyDictionary(DnxCfgDict * dict, unsigned * dictszp)
00142 {
00143 DnxCfgDict * cpy;
00144 size_t bufsz = 0;
00145 unsigned cnt = 0;
00146 char * sptr;
00147
00148 assert(dict);
00149
00150
00151 while (dict[cnt].varname)
00152 bufsz += strlen(dict[cnt++].varname) + 1;
00153 cnt++;
00154
00155
00156 if ((cpy = (DnxCfgDict *)xmalloc(cnt * sizeof *dict + bufsz)) == 0)
00157 return 0;
00158
00159
00160 sptr = (char *)&cpy[cnt];
00161
00162
00163 *dictszp = --cnt;
00164
00165
00166 cpy[cnt].varname = 0;
00167 while (cnt--)
00168 {
00169 size_t strsz = strlen(dict[cnt].varname) + 1;
00170 memcpy(sptr, dict[cnt].varname, strsz);
00171 cpy[cnt].varname = sptr;
00172 cpy[cnt].type = dict[cnt].type;
00173 cpy[cnt].valptr = dict[cnt].valptr;
00174 if (cpy[cnt].type != DNX_CFG_INT && cpy[cnt].type != DNX_CFG_UNSIGNED
00175 && cpy[cnt].type != DNX_CFG_BOOL)
00176 *(void **)cpy[cnt].valptr = 0;
00177 else
00178 *(unsigned *)cpy[cnt].valptr = 0;
00179 sptr += strsz;
00180 }
00181 return cpy;
00182 }
00183
00184
00185
00194 static int validateURL(char * url) { return 0; }
00195
00196
00197
00206 static int validateFSPath(char * path) { return 0; }
00207
00208
00209
00223 static int parseString(char * val, DnxCfgType type, char ** prval)
00224 {
00225 int ret;
00226 char * str;
00227 assert(type == DNX_CFG_URL || type == DNX_CFG_FSPATH || type == DNX_CFG_STRING);
00228 if (type == DNX_CFG_URL && (ret = validateURL(val)) != 0)
00229 return ret;
00230 if (type == DNX_CFG_FSPATH && (ret = validateFSPath(val)) != 0)
00231 return ret;
00232 if ((str = xstrdup(val)) == 0)
00233 return DNX_ERR_MEMORY;
00234 xfree(*prval);
00235 *prval = str;
00236 return DNX_OK;
00237 }
00238
00239
00240
00251 static char * strtrim(char * s)
00252 {
00253 assert(s);
00254 while (isspace(*s)) s++;
00255 if (*s)
00256 {
00257 size_t l = strlen(s);
00258 while (l && isspace(s[l - 1])) l--;
00259 s[l] = 0;
00260 }
00261 return s;
00262 }
00263
00264
00265
00279 static int parseStringArray(char * val, DnxCfgType type, char *** prval)
00280 {
00281 char ** array;
00282 int i;
00283
00284 assert(type == DNX_CFG_STRING_ARRAY);
00285
00286
00287 if ((array = strToStrArray(val, ',')) == 0)
00288 return DNX_ERR_MEMORY;
00289
00290
00291 for (i = 0; array[i]; i++)
00292 array[i] = strtrim(array[i]);
00293
00294 xfree(*prval);
00295 *prval = array;
00296 return DNX_OK;
00297 }
00298
00299
00300
00309 static int parseIntOrUnsigned(char * val, DnxCfgType type, int * prval)
00310 {
00311 char * ep;
00312 long (*str2num)(char*, char**, int) =
00313 (type == DNX_CFG_INT? (void*)strtol: (void*)strtoul);
00314 long n = str2num(val, &ep, 0);
00315 assert(type == DNX_CFG_INT || type == DNX_CFG_UNSIGNED);
00316 if (*ep != 0) return DNX_ERR_SYNTAX;
00317 *prval = (int)n;
00318 return DNX_OK;
00319 }
00320
00321
00322
00339 static int parseIntOrUnsignedArray(char * val, DnxCfgType type, int ** prval)
00340 {
00341 int * array;
00342 char ** sa;
00343 int i;
00344
00345 assert(type == DNX_CFG_INT_ARRAY || type == DNX_CFG_UNSIGNED_ARRAY);
00346
00347
00348 if ((sa = strToStrArray(val, ',')) == 0)
00349 return DNX_ERR_MEMORY;
00350
00351
00352 for (i = 0; sa[i]; i++)
00353 sa[i] = strtrim(sa[i]);
00354
00355
00356 if ((array = (int *)xmalloc((i + 1) * sizeof *array)) == 0)
00357 {
00358 xfree(sa);
00359 return DNX_ERR_MEMORY;
00360 }
00361
00362 type = (type == DNX_CFG_INT_ARRAY)? DNX_CFG_INT : DNX_CFG_UNSIGNED;
00363
00364
00365 array[0] = i;
00366 for (i = 0; sa[i]; i++)
00367 {
00368 int ret;
00369 if ((ret = parseIntOrUnsigned(sa[i], type, &array[i + 1])) != 0)
00370 {
00371 xfree(array);
00372 xfree(sa);
00373 return ret;
00374 }
00375 }
00376 xfree(sa);
00377 xfree(*prval);
00378 *prval = array;
00379 return DNX_OK;
00380 }
00381
00382
00383
00395 static int parseBool(char * val, DnxCfgType type, unsigned * prval)
00396 {
00397 assert(type == DNX_CFG_BOOL);
00398 if (strcasecmp(val, "YES") == 0 || strcasecmp(val, "TRUE") == 0
00399 || strcasecmp(val, "ON") == 0 || strtoul(val, 0, 0) != 0)
00400 *prval = 1;
00401 else if (strcasecmp(val, "NO") == 0 || strcasecmp(val, "FALSE") == 0
00402 || strcasecmp(val, "OFF") == 0 || (val[0] == '0' && val[1] == 0))
00403 *prval = 0;
00404 else
00405 return DNX_ERR_SYNTAX;
00406 return DNX_OK;
00407 }
00408
00409
00410
00426 static int dnxParseCfgVar(char * var, char * val, DnxCfgDict * dict, void ** vptrs)
00427 {
00428 static DnxVarParser_t * parsetbl[] =
00429 {
00430 (DnxVarParser_t *)parseString,
00431 (DnxVarParser_t *)parseStringArray,
00432 (DnxVarParser_t *)parseIntOrUnsigned,
00433 (DnxVarParser_t *)parseIntOrUnsignedArray,
00434 (DnxVarParser_t *)parseIntOrUnsigned,
00435 (DnxVarParser_t *)parseIntOrUnsignedArray,
00436 (DnxVarParser_t *)parseString,
00437 (DnxVarParser_t *)parseString,
00438 (DnxVarParser_t *)parseBool,
00439 };
00440
00441 unsigned i;
00442
00443 for (i = 0; dict[i].varname; i++)
00444 if (strcmp(dict[i].varname, var) == 0)
00445 {
00446 assert(dict[i].type >= 0 && dict[i].type < elemcount(parsetbl));
00447 return parsetbl[dict[i].type](val, dict[i].type, &vptrs[i]);
00448 }
00449
00450 return DNX_ERR_INVALID;
00451 }
00452
00453
00454
00467 static int dnxParseCfgLine(char * s, DnxCfgDict * dict, void ** vptrs)
00468 {
00469 char * cpy, * val;
00470 int ret;
00471
00472
00473 if ((val = strchr(s, '#')) != 0) *val = 0;
00474
00475
00476 if (*(s = strtrim(s)) == 0) return 0;
00477
00478
00479 if (*s == '=' || (val = strchr(s, '=')) == 0 || val[1] == 0)
00480 return DNX_ERR_SYNTAX;
00481
00482
00483 if ((cpy = xstrdup(s)) == 0)
00484 return DNX_ERR_MEMORY;
00485
00486
00487 val = &cpy[val - s];
00488 *val++ = 0;
00489
00490
00491 strtrim(cpy);
00492 val = strtrim(val);
00493
00494
00495 ret = dnxParseCfgVar(cpy, val, dict, vptrs);
00496
00497 xfree(cpy);
00498
00499 return ret;
00500 }
00501
00502
00503
00519 static int applyCfgSetString(char ** sap, DnxCfgDict * dict, void ** vptrs)
00520 {
00521 assert(dict && vptrs);
00522
00523 if (!sap)
00524 return DNX_OK;
00525
00526 while (*sap)
00527 {
00528 int ret;
00529 if ((ret = dnxParseCfgLine(*sap++, dict, vptrs)) != 0)
00530 return ret;
00531 }
00532 return DNX_OK;
00533 }
00534
00535
00536
00548 static void freeArrayPtrs(DnxCfgDict * dict, void ** vptrs)
00549 {
00550 unsigned i, j;
00551
00552 assert(dict);
00553
00554 for (i = 0; dict[i].varname; i++)
00555 if (dict[i].type != DNX_CFG_INT && dict[i].type != DNX_CFG_UNSIGNED
00556 && dict[i].type != DNX_CFG_BOOL)
00557 xfree(vptrs? vptrs[i]: *(void **)dict[i].valptr);
00558 }
00559
00560
00561
00572 static char * formatString(char * var, DnxCfgType type, char * prval)
00573 {
00574 size_t len = prval? strlen(prval): 0;
00575 char * cfg;
00576
00577 assert(var);
00578 assert(type == DNX_CFG_STRING || type == DNX_CFG_URL || type == DNX_CFG_FSPATH);
00579
00580
00581 if ((cfg = (char *)xmalloc(strlen(var) + 1 + len + 2)) != 0)
00582 sprintf(cfg, "%s=%s\n", var, prval? prval: "");
00583
00584 return cfg;
00585 }
00586
00587
00588
00599 static char * formatStringArray(char * var, DnxCfgType type, char ** prval)
00600 {
00601 char ** cp = prval;
00602 size_t len = 0;
00603 char * cfg;
00604
00605 assert(var && type == DNX_CFG_STRING_ARRAY);
00606
00607 if (cp)
00608 while (*cp)
00609 len += strlen(*cp++) + 1;
00610
00611
00612 if ((cfg = (char *)xmalloc(strlen(var) + 1 + len + 1)) != 0)
00613 {
00614 char * cp = cfg;
00615 cp += sprintf(cp, "%s=", var);
00616 if (prval)
00617 while (*prval)
00618 cp += sprintf(cp, "%s,", *prval++);
00619 if (cp[-1] == ',') cp--;
00620 *cp++ = '\n';
00621 *cp = 0;
00622 }
00623 return cfg;
00624 }
00625
00626
00627
00638 static char * formatIntOrUnsigned(char * var, DnxCfgType type, int prval)
00639 {
00640 char intbuf[16];
00641 size_t len;
00642 char * cfg;
00643
00644 assert(var && (type == DNX_CFG_INT || type == DNX_CFG_UNSIGNED));
00645
00646 len = sprintf(intbuf, type == DNX_CFG_INT? "%d": "%u", prval);
00647
00648
00649 if ((cfg = (char *)xmalloc(strlen(var) + 1 + len + 2)) != 0)
00650 sprintf(cfg, "%s=%s\n", var, intbuf);
00651
00652 return cfg;
00653 }
00654
00655
00656
00668 static char * formatIntOrUnsignedArray(char * var, DnxCfgType type, int * prval)
00669 {
00670 size_t len = prval? prval[0] * 16: 0;
00671 char * cfg;
00672
00673 assert(var);
00674 assert(type == DNX_CFG_INT_ARRAY || type == DNX_CFG_UNSIGNED_ARRAY);
00675
00676
00677 if ((cfg = (char *)xmalloc(strlen(var) + 1 + len + 2)) != 0)
00678 {
00679 int i;
00680 char * cp = cfg;
00681 cp += sprintf(cp, "%s=", var);
00682 if (prval)
00683 for (i = 1; i <= prval[0]; i++)
00684 cp += sprintf(cp, type == DNX_CFG_INT_ARRAY? "%d,": "%u,", prval[i]);
00685 if (cp[-1] == ',') cp--;
00686 *cp++ = '\n';
00687 *cp = 0;
00688 }
00689 return cfg;
00690 }
00691
00692
00693
00704 static char * formatBool(char * var, DnxCfgType type, unsigned prval)
00705 {
00706 char * cfg;
00707
00708 assert(var);
00709 assert(type == DNX_CFG_BOOL);
00710
00711
00712 if ((cfg = (char *)xmalloc(strlen(var) + 1 + 3 + 2)) != 0)
00713 sprintf(cfg, "%s=%s\n", var, prval? "YES" : "NO");
00714
00715 return cfg;
00716 }
00717
00718
00719
00729 static char * buildCurrentCfgCache(DnxCfgDict * dict, size_t * ccsizep)
00730 {
00731 static DnxVarFormatter_t * fmttbl[] =
00732 {
00733 (DnxVarFormatter_t *)formatString,
00734 (DnxVarFormatter_t *)formatStringArray,
00735 (DnxVarFormatter_t *)formatIntOrUnsigned,
00736 (DnxVarFormatter_t *)formatIntOrUnsignedArray,
00737 (DnxVarFormatter_t *)formatIntOrUnsigned,
00738 (DnxVarFormatter_t *)formatIntOrUnsignedArray,
00739 (DnxVarFormatter_t *)formatString,
00740 (DnxVarFormatter_t *)formatString,
00741 (DnxVarFormatter_t *)formatBool,
00742 };
00743
00744 char * cfg = 0;
00745 size_t cfgsz = 1;
00746 unsigned i;
00747
00748 assert(dict && ccsizep);
00749
00750 for (i = 0; dict[i].varname; i++)
00751 {
00752 char * str, * newcfg;
00753 size_t len;
00754
00755 if ((str = fmttbl[dict[i].type](dict[i].varname,
00756 dict[i].type, *(void **)dict[i].valptr)) == 0
00757 || (newcfg = (char *)xrealloc(cfg, cfgsz + (len = strlen(str)))) == 0)
00758 {
00759 xfree(str);
00760 xfree(cfg);
00761 return 0;
00762 }
00763 cfg = newcfg;
00764 memcpy(&cfg[cfgsz - 1], str, len);
00765 xfree(str);
00766 cfgsz += len;
00767 cfg[cfgsz - 1] = 0;
00768 }
00769
00770
00771 if (cfgsz > 1 && cfg[cfgsz - 2] == '\n')
00772 cfg[--cfgsz - 1] = 0;
00773
00774 *ccsizep = cfgsz;
00775
00776 return cfg;
00777 }
00778
00779
00780
00781
00782
00783 int dnxCfgParserCreate(char * cfgdefs, char * cfgfile, char * cmdover,
00784 DnxCfgDict * dict, DnxCfgValidator_t * vfp, DnxCfgParser ** cpp)
00785 {
00786 iDnxCfgParser * icp;
00787
00788 assert(dict && cpp);
00789
00790
00791 if ((icp = (iDnxCfgParser *)xmalloc(sizeof *icp)) == 0)
00792 return DNX_ERR_MEMORY;
00793 memset(icp, 0, sizeof *icp);
00794
00795
00796 if (cfgfile && (icp->cfgfile = xstrdup(cfgfile)) == 0
00797 || cfgdefs && (icp->cfgdefs = strToStrArray(cfgdefs, '\n')) == 0
00798 || cmdover && (icp->cmdover = strToStrArray(cmdover, '\n')) == 0
00799 || (icp->dict = copyDictionary(dict, &icp->dictsz)) == 0)
00800 {
00801 xfree(icp->cmdover);
00802 xfree(icp->cfgdefs);
00803 xfree(icp->cfgfile);
00804 xfree(icp);
00805 return DNX_ERR_MEMORY;
00806 }
00807 icp->vfp = vfp;
00808 *cpp = (DnxCfgParser *)icp;
00809 return DNX_OK;
00810 }
00811
00812
00813
00814 int dnxCfgParserParse(DnxCfgParser * cp, void * passthru)
00815 {
00816 iDnxCfgParser * icp = (iDnxCfgParser *)cp;
00817 void ** vptrs;
00818 int ret;
00819
00820 assert(cp);
00821
00822
00823 if ((vptrs = (void **)xmalloc(icp->dictsz * sizeof *vptrs)) == 0)
00824 return DNX_ERR_MEMORY;
00825 memset(vptrs, 0, icp->dictsz * sizeof *vptrs);
00826
00827
00828 if ((ret = applyCfgSetString(icp->cfgdefs, icp->dict, vptrs)) != 0)
00829 {
00830 xfree(vptrs);
00831 return ret;
00832 }
00833
00834
00835 if (icp->cfgfile)
00836 {
00837 FILE * fp;
00838 if ((fp = fopen(icp->cfgfile, "r")) == 0)
00839 ret = errno == EACCES? DNX_ERR_ACCESS : DNX_ERR_NOTFOUND;
00840 else
00841 {
00842 int line = 0;
00843 char buf[DNX_MAX_CFG_LINE];
00844
00845 while (fgets(buf, sizeof buf, fp) != 0)
00846 {
00847 int err;
00848 line++;
00849
00850
00851 if ((err = dnxParseCfgLine(buf, icp->dict, vptrs)) != 0
00852 && err != DNX_ERR_INVALID)
00853 {
00854 dnxLog("cfgParser [%s]: Syntax error on line %d: %s.",
00855 icp->cfgfile, line, dnxErrorString(err));
00856 if (!ret) ret = err;
00857 }
00858 }
00859 fclose(fp);
00860 }
00861 }
00862
00863 #define INTSWAP(a,b) do { int n = (a); (a) = (int)(intptr_t)(b); (b) = (void *)(intptr_t)n; } while(0)
00864 #define PTRSWAP(a,b) do { void * p = (a); (a) = (b); (b) = p; } while (0)
00865
00866
00867 if (!ret && (ret = applyCfgSetString(icp->cmdover, icp->dict, vptrs)) == 0
00868 && (!icp->vfp || (ret = icp->vfp(icp->dict, vptrs, passthru)) == 0))
00869 {
00870 unsigned i;
00871
00872
00873 for (i = 0; i < icp->dictsz; i++)
00874 if (icp->dict[i].type == DNX_CFG_INT
00875 || icp->dict[i].type == DNX_CFG_UNSIGNED
00876 || icp->dict[i].type == DNX_CFG_BOOL)
00877 INTSWAP(*(int *)icp->dict[i].valptr, vptrs[i]);
00878 else
00879 PTRSWAP(*(void **)icp->dict[i].valptr, vptrs[i]);
00880
00881
00882 xfree(icp->curcfg);
00883 icp->curcfg = 0;
00884 icp->ccsize = 0;
00885 }
00886
00887
00888 freeArrayPtrs(icp->dict, vptrs);
00889 xfree(vptrs);
00890
00891 return ret;
00892 }
00893
00894
00895
00896 int dnxCfgParserGetCfg(DnxCfgParser * cp, char * buf, size_t * bufszp)
00897 {
00898 iDnxCfgParser * icp = (iDnxCfgParser *)cp;
00899
00900 assert(cp && bufszp && (buf || !*bufszp));
00901
00902
00903 if (icp->curcfg == 0
00904 && (icp->curcfg = buildCurrentCfgCache(icp->dict, &icp->ccsize)) == 0)
00905 return DNX_ERR_MEMORY;
00906
00907
00908 if (buf && *bufszp)
00909 {
00910 size_t cpysz = *bufszp > icp->ccsize? icp->ccsize: *bufszp;
00911 memcpy(buf, icp->curcfg, cpysz - 1);
00912 buf[cpysz - 1] = 0;
00913 }
00914 *bufszp = icp->ccsize;
00915
00916 return 0;
00917 }
00918
00919
00920
00921 void dnxCfgParserDestroy(DnxCfgParser * cp)
00922 {
00923 iDnxCfgParser * icp = (iDnxCfgParser *)cp;
00924
00925 assert(cp);
00926
00927 freeArrayPtrs(icp->dict, 0);
00928
00929 xfree(icp->dict);
00930 xfree(icp->cmdover);
00931 xfree(icp->cfgdefs);
00932 xfree(icp->cfgfile);
00933 xfree(icp->curcfg);
00934 xfree(icp);
00935 }
00936
00937
00938
00939
00940
00941
00942
00943
00944
00945
00946
00947
00948
00949
00950
00951
00952 #ifdef DNX_CFGPARSER_TEST
00953
00954 #include "utesthelp.h"
00955
00956 #define TEST_FILE_NAME "cfgtest.cfg"
00957 #define TEST_FILE_CONTENTS \
00958 "# Test Configuration File\n\n" \
00959 " testCfgString = some string\n" \
00960 "testCfgStringArray = This is,a test, of the , string array. \n" \
00961 "testCfgInt1 = -10024\n" \
00962 "testCfgInt3 = -57\n" \
00963 "testCfgInt4 = 100\n" \
00964 "testCfgIntArray=-1, 87,3 ,2, 32,3,1,-23, -112,2,234\n" \
00965 "testCfgUnsigned = 332245235\r\n" \
00966 "testCfgUnsignedArray = 2342, 234,234,4, 2342 ,2342 ,234234 \n" \
00967 "testCfgUrl = http://www.example.com\n" \
00968 "testCfgFSPath = /some/path\n" \
00969 "testCfgBool = YES\n"
00970
00971 #define TEST_CFG_CONTENTS \
00972 "testCfgString=some string\n" \
00973 "testCfgStringArray=This is,a test,of the,string array.\n" \
00974 "testCfgInt1=-10024\n" \
00975 "testCfgInt2=82\n" \
00976 "testCfgInt3=-57\n" \
00977 "testCfgInt4=102\n" \
00978 "testCfgIntArray=-1,87,3,2,32,3,1,-23,-112,2,234\n" \
00979 "testCfgUnsigned=332245235\n" \
00980 "testCfgUnsignedArray=2342,234,234,4,2342,2342,234234\n" \
00981 "testCfgUrl=http://www.example.com\n" \
00982 "testCfgFSPath=/some/path\n" \
00983 "testCfgBool=YES"
00984
00985 static int verbose;
00986
00987 IMPLEMENT_DNX_SYSLOG(verbose);
00988 IMPLEMENT_DNX_DEBUG(verbose);
00989
00990 int main(int argc, char ** argv)
00991 {
00992 char * testCfgString;
00993 char ** testCfgStringArray;
00994 int testCfgInt1;
00995 int testCfgInt2;
00996 int testCfgInt3;
00997 int testCfgInt4;
00998 int * testCfgIntArray;
00999 unsigned testCfgUnsigned;
01000 unsigned * testCfgUnsignedArray;
01001 char * testCfgUrl;
01002 char * testCfgFSPath;
01003 unsigned testCfgBool;
01004
01005 DnxCfgDict dict[] =
01006 {
01007 { "testCfgString", DNX_CFG_STRING, &testCfgString },
01008 { "testCfgStringArray", DNX_CFG_STRING_ARRAY, &testCfgStringArray },
01009 { "testCfgInt1", DNX_CFG_INT, &testCfgInt1 },
01010 { "testCfgInt2", DNX_CFG_INT, &testCfgInt2 },
01011 { "testCfgInt3", DNX_CFG_INT, &testCfgInt3 },
01012 { "testCfgInt4", DNX_CFG_INT, &testCfgInt4 },
01013 { "testCfgIntArray", DNX_CFG_INT_ARRAY, &testCfgIntArray },
01014 { "testCfgUnsigned", DNX_CFG_UNSIGNED, &testCfgUnsigned },
01015 { "testCfgUnsignedArray",DNX_CFG_UNSIGNED_ARRAY, &testCfgUnsignedArray },
01016 { "testCfgUrl", DNX_CFG_URL, &testCfgUrl },
01017 { "testCfgFSPath", DNX_CFG_FSPATH, &testCfgFSPath },
01018 { "testCfgBool", DNX_CFG_BOOL, &testCfgBool },
01019 { 0 },
01020 };
01021 char * defs = "testCfgInt2 = 82\ntestCfgInt3 = -67\ntestCfgInt4 = 101";
01022 char * cmds = "testCfgInt4 = 102\n";
01023
01024 char * StrArray_cmp[] = {"This is","a test","of the","string array."};
01025 int IntArray_cmp[] = {11,-1,87,3,2,32,3,1,-23,-112,2,234};
01026 int UnsignedArray_cmp[] = {7,2342,234,234,4,2342,2342,234234};
01027
01028 char test_cfg[] = TEST_CFG_CONTENTS;
01029
01030 int i;
01031 FILE * fp;
01032 DnxCfgParser * cp;
01033 char * cfg;
01034 size_t bufsz;
01035
01036 verbose = argc > 1 ? 1 : 0;
01037
01038 CHECK_TRUE((fp = fopen(TEST_FILE_NAME, "w")) != 0);
01039 fputs(TEST_FILE_CONTENTS, fp);
01040 fclose(fp);
01041
01042 CHECK_ZERO(dnxCfgParserCreate(defs, TEST_FILE_NAME, cmds, dict, 0, &cp));
01043 CHECK_ZERO(dnxCfgParserParse(cp, 0));
01044
01045 CHECK_TRUE(strcmp(testCfgString, "some string") == 0);
01046
01047 for (i = 0; i < elemcount(StrArray_cmp); i++)
01048 CHECK_TRUE(strcmp(testCfgStringArray[i], StrArray_cmp[i]) == 0);
01049
01050 CHECK_TRUE(testCfgInt1 == -10024);
01051 CHECK_TRUE(testCfgInt2 == 82);
01052 CHECK_TRUE(testCfgInt3 == -57);
01053 CHECK_TRUE(testCfgInt4 == 102);
01054
01055 for (i = 0; i < elemcount(IntArray_cmp); i++)
01056 CHECK_TRUE(testCfgIntArray[i] == IntArray_cmp[i]);
01057
01058 CHECK_TRUE(testCfgUnsigned == 332245235);
01059
01060 for (i = 0; i < elemcount(UnsignedArray_cmp); i++)
01061 CHECK_TRUE(testCfgUnsignedArray[i] == UnsignedArray_cmp[i]);
01062
01063 CHECK_ZERO(strcmp(testCfgUrl, "http://www.example.com"));
01064 CHECK_ZERO(strcmp(testCfgFSPath, "/some/path"));
01065
01066 CHECK_TRUE(testCfgBool != 0);
01067
01068
01069 bufsz = 0;
01070 CHECK_ZERO(dnxCfgParserGetCfg(cp, 0, &bufsz));
01071 CHECK_NONZERO(cfg = (char *)xmalloc(bufsz));
01072 CHECK_ZERO(dnxCfgParserGetCfg(cp, cfg, &bufsz));
01073 CHECK_TRUE(memcmp(cfg, test_cfg, bufsz) == 0);
01074 CHECK_TRUE(bufsz == sizeof test_cfg);
01075 xfree(cfg);
01076
01077
01078
01079 dnxCfgParserDestroy(cp);
01080
01081 remove(TEST_FILE_NAME);
01082
01083 #ifdef DEBUG_HEAP
01084 CHECK_ZERO(dnxCheckHeap());
01085 #endif
01086
01087 return 0;
01088 }
01089
01090 #endif
01091
01092
01093