TORCS  1.3.10
The Open Racing Car Simulator
Loading...
Searching...
No Matches
params.cpp
Go to the documentation of this file.
1/***************************************************************************
2 params.cpp -- configuration parameters management
3 -------------------
4 created : Fri Aug 13 22:27:57 CEST 1999
5 copyright : (C) 1999-2026 by Eric EspiƩ, Bernhard Wymann
6 email : berniw@bluewin.ch
7 ***************************************************************************/
8
9/***************************************************************************
10 * *
11 * This program is free software; you can redistribute it and/or modify *
12 * it under the terms of the GNU General Public License as published by *
13 * the Free Software Foundation; either version 2 of the License, or *
14 * (at your option) any later version. *
15 * *
16 ***************************************************************************/
17
22
23#include <stdlib.h>
24#include <stdio.h>
25#include <stdarg.h>
26#include <sys/stat.h>
27#ifndef _WIN32
28#include <unistd.h>
29#endif
30#include <math.h>
31
32#include <xmlparse.h>
33#ifdef WIN32
34#include <windows.h>
35#endif
36#include <tgf.h>
37#include <assert.h>
38#include <portability.h>
39
40
41#define LINE_SZ 1024
42#define PARAM_CREATE 0x01
43
44#define P_NUM 0
45#define P_STR 1
46
48struct within
49{
50 char *val;
51 GF_TAILQ_ENTRY (struct within) linkWithin;
52};
53
54GF_TAILQ_HEAD (withinHead, struct within);
55
56
57
62struct param
63{
64 char *name;
65 char *fullName;
66 char *value;
68 int type;
69 char *unit;
72 struct withinHead withinList;
73 GF_TAILQ_ENTRY (struct param) linkParam;
74};
75
76GF_TAILQ_HEAD (paramHead, struct param);
77struct section;
78GF_TAILQ_HEAD (sectionHead, struct section);
79
80
82struct section
83{
84 char *fullName;
85 struct paramHead paramList;
86 GF_TAILQ_ENTRY (struct section) linkSection;
87 struct sectionHead subSectionList;
89 struct section *parent;
90};
91
92
93#define PARM_MAGIC 0x20030815
94
97{
98 char *filename;
99 char *name;
100 char *dtd;
101 char *header;
104 void *paramHash;
106};
107
108#define PARM_HANDLE_FLAG_PRIVATE 0x01
109#define PARM_HANDLE_FLAG_PARSE_ERROR 0x02
110
111
114{
115 int state;
117 struct param *curParam;
118 char *filename;
119 int indent;
120};
121
122
134
135
136GF_TAILQ_HEAD (parmHead, struct parmHandle);
137
138static struct parmHead parmHandleList;
139
140static char *getFullName(const char *sectionName, const char *paramName);
141static struct param *getParamByName (struct parmHeader *conf, const char *sectionName, const char *paramName, int flag);
142static void removeParamByName (struct parmHeader *conf, const char *sectionName, const char *paramName);
143static void removeParam (struct parmHeader *conf, struct section *section, struct param *param);
144static struct param *addParam (struct parmHeader *conf, struct section *section, const char *paramName, const char *value);
145static void removeSection (struct parmHeader *conf, struct section *section);
146static struct section *addSection (struct parmHeader *conf, const char *sectionName);
147static void parmClean (struct parmHeader *conf);
148static void parmReleaseHandle (struct parmHandle *parmHandle);
149static void parmReleaseHeader (struct parmHeader *conf);
150static struct section *getParent (struct parmHeader *conf, const char *sectionName);
151static void cleanUnusedSection (struct parmHeader *conf, struct section *section);
152
153
160void GfParmInit (void)
161{
163}
164
165
172void GfParmShutdown (void)
173{
174 struct parmHandle *parmHandle;
175
178 }
179}
180
181
192static char *getFullName (const char *sectionName, const char *paramName)
193{
194 char *fullName;
195 unsigned long len = strlen (sectionName) + strlen (paramName) + 2;
196
197 fullName = (char *) malloc(strlen (sectionName) + strlen (paramName) + 2);
198 if (!fullName) {
199 GfError ("getFullName: malloc (%lu) failed", len);
200 return NULL;
201 }
202 snprintf(fullName, len, "%s/%s", sectionName, paramName);
203
204 return fullName;
205}
206
207
218static struct param* getParamByName(struct parmHeader *conf, const char *sectionName, const char *paramName, int flag)
219{
220 char *fullName;
221 struct param *param;
222 struct section *section;
223
224 fullName = getFullName (sectionName, paramName);
225 if (!fullName) {
226 GfError ("getParamByName: getFullName failed\n");
227 return NULL;
228 }
229
230 param = (struct param *)GfHashGetStr (conf->paramHash, fullName);
231 free (fullName);
232 if (param || ((flag & PARAM_CREATE) == 0)) {
233 return param;
234 }
235
236 /* Parameter not found CREATE it */
237 section = (struct section *)GfHashGetStr (conf->sectionHash, sectionName);
238 if (!section) {
239 section = addSection (conf, sectionName);
240 if (!section) {
241 GfError ("getParamByName: addSection failed\n");
242 return NULL;
243 }
244 }
245 param = addParam (conf, section, paramName, "");
246
247 return param;
248}
249
250
259static void removeParamByName(struct parmHeader *conf, const char *sectionName, const char *paramName)
260{
261 char *fullName;
262 struct param *param;
263 struct section *section;
264
265 section = (struct section *)GfHashGetStr (conf->sectionHash, sectionName);
266 if (!section) {
267 return;
268 }
269
270 fullName = getFullName (sectionName, paramName);
271 if (!fullName) {
272 GfError("removeParamByName: getFullName failed\n");
273 return;
274 }
275
276 param = (struct param *)GfHashGetStr (conf->paramHash, fullName);
277 freez (fullName);
278 if (param) {
279 removeParam(conf, section, param);
280 }
281
283}
284
285
296static void cleanUnusedSection(struct parmHeader *conf, struct section *section)
297{
298 struct section *parent;
299
300 if (
301 !section->fullName ||
303 ) {
305 removeSection (conf, section);
306 if (parent) {
307 /* check if the parent is unused */
309 }
310 }
311}
312
313
321static void removeParam(struct parmHeader *conf, struct section *section, struct param *param)
322{
324 GF_TAILQ_REMOVE (&(section->paramList), param, linkParam);
325
326 struct within *within;
328 GF_TAILQ_REMOVE (&param->withinList, within, linkWithin);
329 freez(within->val);
330 free(within);
331 }
332
333 freez (param->name);
335 freez (param->value);
336 freez (param->unit);
337 freez (param);
338}
339
340
351static struct param *addParam(struct parmHeader *conf, struct section *section, const char *paramName, const char *value)
352{
353 char *fullName;
354 struct param *param = NULL;
355 char *tmpVal = NULL;
356 const unsigned long len = sizeof (struct param);
357
358 tmpVal = strdup (value);
359 if (!tmpVal) {
360 GfError ("addParam: strdup (%s) failed\n", value);
361 goto bailout;
362 }
363
364 param = (struct param *) calloc (1, len);
365 if (!param) {
366 GfError ("addParam: calloc (1, %lu) failed\n", len);
367 goto bailout;
368 }
369
370 param->name = strdup (paramName);
371 if (!param->name) {
372 GfError ("addParam: strdup (%s) failed\n", paramName);
373 goto bailout;
374 }
375
376 fullName = getFullName (section->fullName, paramName);
377 if (!fullName) {
378 GfError ("addParam: getFullName failed\n");
379 goto bailout;
380 }
381
383 if (GfHashAddStr (conf->paramHash, param->fullName, param)) {
384 goto bailout;
385 }
386
388
389 /* Attach to section */
391
392 freez (param->value);
393 param->value = tmpVal;
394
395 return param;
396
397 bailout:
398 if (param) {
399 freez (param->name);
401 freez (param->value);
402 free (param);
403 }
404 freez (tmpVal);
405
406 return NULL;
407}
408
409
416static void removeSection(struct parmHeader *conf, struct section *section)
417{
418 struct param *param;
419 struct section *subSection;
420
421 while ((subSection = GF_TAILQ_FIRST (&(section->subSectionList))) != NULL) {
422 removeSection (conf, subSection);
423 }
424
425 if (section->fullName) {
426 /* not the root section */
430 removeParam (conf, section, param);
431 }
433 }
434 freez (section);
435}
436
437
446static struct section *getParent(struct parmHeader *conf, const char *sectionName)
447{
448 struct section *section;
449 char *tmpName;
450 char *s;
451
452 tmpName = strdup (sectionName);
453 if (!tmpName) {
454 GfError ("getParent: strdup (\"%s\") failed\n", sectionName);
455 return NULL;
456 }
457
458 s = strrchr (tmpName, '/');
459 if (s) {
460 *s = '\0';
461 section = (struct section *)GfHashGetStr (conf->sectionHash, tmpName);
462 if (section) {
463 goto end;
464 }
465 section = addSection (conf, tmpName);
466 goto end;
467 } else {
468 section = conf->rootSection;
469 goto end;
470 }
471
472end:
473 free (tmpName);
474 return section;
475}
476
477
486static struct section *addSection(struct parmHeader *conf, const char *sectionName)
487{
488 struct section *section;
489 struct section *parent;
490 const unsigned long len = sizeof (struct section);
491
492 if (GfHashGetStr (conf->sectionHash, sectionName)) {
493 GfError ("addSection: duplicate section [%s]\n", sectionName);
494 return NULL;
495 }
496
497 parent = getParent(conf, sectionName);
498 if (!parent) {
499 GfError ("addSection: Problem with getParent for section [%s]\n", sectionName);
500 return NULL;
501 }
502
503 section = (struct section *) calloc (1, len);
504 if (!section) {
505 GfError ("addSection: calloc (1, %lu) failed\n", len);
506 return NULL;
507 }
508
509 section->fullName = strdup(sectionName);
510 if (!section->fullName) {
511 GfError ("addSection: strdup (%s) failed\n", sectionName);
512 goto bailout;
513 }
514
515 if (GfHashAddStr (conf->sectionHash, sectionName, section)) {
516 GfError ("addSection: GfHashAddStr failed\n");
517 goto bailout;
518 }
519
520 /* no more bailout call */
525
526 return section;
527
528bailout:
530 freez (section);
531 return NULL;
532}
533
534
551 static struct parmHeader *getSharedHeader(const char *file, int mode)
552{
553 struct parmHeader *conf = NULL;
554 struct parmHandle *parmHandle;
555
556 /* Search for existing conf */
557 if ((mode & GFPARM_RMODE_PRIVATE) == 0) {
558 for (
561 parmHandle = GF_TAILQ_NEXT (parmHandle, linkHandle)
562 ) {
565 if (!strcmp(conf->filename, file)) {
566 if (mode & GFPARM_RMODE_REREAD) {
567 parmClean (conf);
568 }
569 conf->refcount++;
570 return conf;
571 }
572 }
573 }
574 }
575
576 return NULL;
577}
578
579
587static struct parmHeader* createParmHeader (const char *file)
588{
589 struct parmHeader *conf = NULL;
590 const unsigned long parmheadersize = sizeof (struct parmHeader);
591 const unsigned long sectionsize = sizeof (struct section);
592
593 conf = (struct parmHeader *) calloc (1, parmheadersize);
594 if (!conf) {
595 GfError ("gfParmReadFile: calloc (1, %lu) failed\n", parmheadersize);
596 return NULL;
597 }
598
599 conf->refcount = 1;
600
601 conf->rootSection = (struct section *) calloc (1, sectionsize);
602 if (!conf->rootSection) {
603 GfError ("gfParmReadFile: calloc (1, %lu) failed\n", sectionsize);
604 goto bailout;
605 }
606
609
611 if (!conf->paramHash) {
612 GfError ("gfParmReadFile: GfHashCreate (paramHash) failed\n");
613 goto bailout;
614 }
615
617 if (!conf->sectionHash) {
618 GfError ("gfParmReadFile: GfHashCreate (sectionHash) failed\n");
619 goto bailout;
620 }
621
622 conf->filename = strdup (file);
623 if (!conf->filename) {
624 GfError ("gfParmReadFile: strdup (%s) failed\n", file);
625 goto bailout;
626 }
627
628 return conf;
629
630 bailout:
631 freez (conf->rootSection);
632 if (conf->paramHash) {
633 GfHashRelease (conf->paramHash, NULL);
634 }
635
636 if (conf->sectionHash) {
637 GfHashRelease (conf->sectionHash, NULL);
638 }
639
640 freez (conf->filename);
641 freez (conf);
642
643 return NULL;
644}
645
646
653static void addWithin (struct param *curParam, char *s1)
654{
655 struct within *curWithin;
656
657 if (!s1 || ! strlen (s1)) {
658 return;
659 }
660
661 curWithin = (struct within *) calloc (1, sizeof (struct within));
662 curWithin->val = strdup (s1);
663 GF_TAILQ_INSERT_TAIL (&(curParam->withinList), curWithin, linkWithin);
664}
665
666
667static int myStrcmp(const void *s1, const void * s2)
668{
669 return strcmp((const char *)s1, (const char *)s2);
670}
671
672
679static tdble getValNumFromStr (const char *str)
680{
681 tdble val;
682
683 if (!str || !strlen (str)) {
684 return 0.0;
685 }
686
687 if (strncmp (str, "0x", 2) == 0) {
688 return (tdble)strtol(str, NULL, 0);
689 }
690
691 sscanf (str, "%g", &val);
692 return val;
693}
694
695
703static void xmlStartElement (void *userData , const char *name, const char **atts)
704{
705 struct parmHandle *parmHandle = (struct parmHandle *)userData;
706 struct parmHeader *conf = parmHandle->conf;
707 struct param *curParam;
708
709 int nAtts;
710 int len;
711 const char **p;
712 const char *s1, *s2;
713 char *fullName;
714 const char *shortName;
715 const char *val;
716 const char *min;
717 const char *max;
718 const char *unit;
719 char *within;
720 char *sa, *sb;
721
723 // parse error occured, ignore.
724 return;
725 }
726
727 p = atts;
728 while (*p) {
729 ++p;
730 }
731
732 nAtts = (p - atts) >> 1;
733 if (nAtts > 1) {
734 qsort ((void *)atts, nAtts, sizeof(char *) * 2, myStrcmp);
735 }
736
737 if (!strcmp(name, "params")) {
738
740 parmHandle->curSection->fullName = strdup ("");
741
743 GfError ("xmlStartElement: strdup (\"\") failed\n");
744 goto bailout;
745 }
746
747 while (*atts) {
748 s1 = *atts++;
749 s2 = *atts++;
750 if (!strcmp(s1, "name")) {
751 FREEZ (conf->name);
752 conf->name = strdup(s2);
753 if (!conf->name) {
754 GfError ("xmlStartElement: strdup (\"%s\") failed\n", s2);
755 goto bailout;
756 }
757 break;
758 }
759 }
760
761 if (!conf->name) {
762 GfOut ("xmlStartElement: Syntax error, missing \"name\" field in params definition\n");
763 goto bailout;
764 }
765
766 } else if (!strcmp(name, "section")) {
767
768 if (!parmHandle->curSection) {
769 GfError ("xmlStartElement: Syntax error, missing \"params\" tag\n");
770 goto bailout;
771 }
772
773 shortName = NULL;
774
775 while (*atts) {
776 s1 = *atts++;
777 s2 = *atts++;
778 if (!strcmp(s1, "name")) {
779 shortName = s2;
780 break;
781 }
782 }
783
784 if (!shortName) {
785 GfError ("xmlStartElement: Syntax error, missing \"name\" field in section definition\n");
786 goto bailout;
787 }
788
789 if (strlen(parmHandle->curSection->fullName)) {
790 len = strlen (shortName) + strlen (parmHandle->curSection->fullName) + 2;
791 fullName = (char *) malloc (len);
792 if (!fullName) {
793 GfError ("xmlStartElement: malloc (%d) failed\n", len);
794 goto bailout;
795 }
796 snprintf (fullName, len, "%s/%s", parmHandle->curSection->fullName, shortName);
797 } else {
798 fullName = strdup (shortName);
799 }
800
802 free(fullName);
803
804 if (!parmHandle->curSection) {
805 GfError ("xmlStartElement: addSection failed\n");
806 goto bailout;
807 }
808
809 } else if (!strcmp(name, "attnum")) {
810
811 if ((!parmHandle->curSection) || (!strlen (parmHandle->curSection->fullName))) {
812 GfError ("xmlStartElement: Syntax error, missing \"section\" tag\n");
813 goto bailout;
814 }
815
816 shortName = NULL;
817 val = NULL;
818 min = max = unit = NULL;
819
820 while (*atts) {
821 s1 = *atts++;
822 s2 = *atts++;
823 if (!strcmp(s1, "name")) {
824 shortName = s2;
825 } else if (!strcmp(s1, "val")) {
826 val = s2;
827 } else if (!strcmp(s1, "min")) {
828 min = s2;
829 } else if (!strcmp(s1, "max")) {
830 max = s2;
831 } else if (!strcmp(s1, "unit")) {
832 unit = s2;
833 }
834 }
835
836 if (!shortName) {
837 GfError ("xmlStartElement: Syntax error, missing \"name\" field in %s definition\n", name);
838 goto bailout;
839 }
840
841 if (!val) {
842 GfError ("xmlStartElement: Syntax error, missing \"val\" field in %s definition\n", name);
843 goto bailout;
844 }
845
846 if (!min) {
847 min = val;
848 }
849
850 if (!max) {
851 max = val;
852 }
853
854 curParam = addParam (conf, parmHandle->curSection, shortName, val);
855 if (!curParam) {
856 GfError ("xmlStartElement: addParam failed\n");
857 goto bailout;
858 }
859
860 curParam->type = P_NUM;
861 curParam->valnum = getValNumFromStr (val);
862 curParam->min = getValNumFromStr (min);
863 curParam->max = getValNumFromStr (max);
864
865 if (curParam->min > curParam->valnum) {
866 curParam->min = curParam->valnum;
867 }
868
869 if (curParam->max < curParam->valnum) {
870 curParam->max = curParam->valnum;
871 }
872
873 if (unit) {
874 curParam->unit = strdup (unit);
875 curParam->valnum = GfParmUnit2SI ((char*)unit, curParam->valnum);
876 curParam->min = GfParmUnit2SI ((char*)unit, curParam->min);
877 curParam->max = GfParmUnit2SI ((char*)unit, curParam->max);
878 }
879
880 } else if (!strcmp(name, "attstr")) {
881
882 if ((!parmHandle->curSection) || (!strlen (parmHandle->curSection->fullName))) {
883 GfError ("xmlStartElement: Syntax error, missing \"section\" tag\n");
884 goto bailout;
885 }
886
887 shortName = NULL;
888 val = NULL;
889 within = NULL;
890
891 while (*atts) {
892 s1 = *atts++;
893 s2 = *atts++;
894 if (!strcmp(s1, "name")) {
895 shortName = s2;
896 } else if (!strcmp(s1, "val")) {
897 val = s2;
898 } else if (!strcmp(s1, "in")) {
899 within = (char *)s2;
900 }
901 }
902
903 if (!shortName) {
904 GfError ("xmlStartElement: Syntax error, missing \"name\" field in %s definition\n", name);
905 goto bailout;
906 }
907
908 if (!val) {
909 GfError ("xmlStartElement: Syntax error, missing \"val\" field in %s definition\n", name);
910 goto bailout;
911 }
912
913 curParam = addParam (conf, parmHandle->curSection, shortName, val);
914 if (!curParam) {
915 GfError ("xmlStartElement: addParam failed\n");
916 goto bailout;
917 }
918
919 curParam->type = P_STR;
920 if (within) {
921 sa = within;
922 sb = strchr (sa, ',');
923 while (sb) {
924 *sb = 0;
925 addWithin (curParam, sa);
926 sa = sb + 1;
927 sb = strchr (sa, ',');
928 }
929 addWithin (curParam, sa);
930 }
931
932 }
933
934 return;
935
936 bailout:
938 return;
939}
940
941
948static void xmlEndElement (void *userData, const XML_Char *name)
949{
950 struct parmHandle *parmHandle = (struct parmHandle *)userData;
951
953 /* parse error occured, ignore */
954 return;
955 }
956
957 if (!strcmp(name, "section")) {
959 GfError ("xmlEndElement: Syntax error in \"%s\"\n", name);
960 return;
961 }
963 }
964}
965
966
979 XML_Parser mainparser,
980 const XML_Char *openEntityNames,
981 const XML_Char *base,
982 const XML_Char *systemId,
983 const XML_Char *publicId)
984{
985 FILE *in;
986 char buf[BUFSIZ];
988 int done;
989 char fin[LINE_SZ];
990 char *s;
991 struct parmHandle *parmHandle;
992 struct parmHeader *conf;
993
994 parmHandle = (struct parmHandle *)XML_GetUserData (mainparser);
996
997 parser = XML_ExternalEntityParserCreate (mainparser, openEntityNames, (const XML_Char *)NULL);
998
999 if (systemId[0] == '/') {
1000 strncpy (fin, systemId, sizeof (fin));
1001 fin[LINE_SZ - 1] = 0;
1002 } else {
1003 /* relative path */
1004 strncpy (fin, conf->filename, sizeof (fin));
1005 fin[LINE_SZ - 1] = 0;
1006 s = strrchr (fin, '/');
1007 if (s) {
1008 s++;
1009 } else {
1010 s = fin;
1011 }
1012 strncpy (s, systemId, sizeof (fin) - (s - fin));
1013 fin[LINE_SZ - 1] = 0;
1014 }
1015
1016 in = fopen (fin, "r");
1017 if (in == NULL) {
1018 perror (fin);
1019 GfError ("GfReadParmFile: file %s has pb\n", systemId);
1020 return 0;
1021 }
1022
1024 do {
1025 size_t len = fread (buf, 1, sizeof(buf), in);
1026 done = len < sizeof (buf);
1027 if (!XML_Parse (parser, buf, len, done)) {
1028 GfError ("file: %s -> %s at line %d\n",
1029 systemId,
1032 fclose (in);
1033 return 0;
1034 }
1035 } while (!done);
1036
1038 fclose(in);
1039
1040 return 1; /* ok (0 for failure) */
1041}
1042
1043
1054static int parseXml(struct parmHandle *parmHandle, char *buf, int len, int done)
1055{
1056 if (!XML_Parse(parmHandle->parser, buf, len, done)) {
1057 GfError ("parseXml: %s at line %d\n",
1060 return 1;
1061 }
1062
1063 if (done) {
1065 parmHandle->parser = 0;
1066 }
1067
1068 return 0;
1069}
1070
1071
1086
1087
1099void* GfParmReadBuf (char *buffer)
1100{
1101 struct parmHeader *conf;
1102 struct parmHandle *parmHandle = NULL;
1103 const unsigned long parmhandlesize = sizeof (struct parmHandle);
1104
1105 /* Conf Header creation */
1106 conf = createParmHeader ("");
1107 if (!conf) {
1108 GfError ("gfParmReadBuf: conf header creation failed\n");
1109 goto bailout;
1110 }
1111
1112 /* Handle creation */
1113 parmHandle = (struct parmHandle *) calloc (1, parmhandlesize);
1114 if (!parmHandle) {
1115 GfError ("gfParmReadBuf: calloc (1, %lu) failed\n", parmhandlesize);
1116 goto bailout;
1117 }
1118
1120 parmHandle->conf = conf;
1122
1123 /* Parsers Initialization */
1124 if (parserXmlInit (parmHandle)) {
1125 GfError ("gfParmReadBuf: parserInit failed\n");
1126 goto bailout;
1127 }
1128
1129 /* Parameters reading in buffer */
1130 if (parseXml (parmHandle, buffer, strlen (buffer), 1)) {
1131 GfError ("gfParmReadBuf: Parse failed for buffer\n");
1132 goto bailout;
1133 }
1134
1136
1137 return parmHandle;
1138
1139 bailout:
1140 if (parmHandle && parmHandle->parser) {
1142 }
1143 freez (parmHandle);
1144 if (conf) {
1146 }
1147
1148 return NULL;
1149}
1150
1151
1173void* GfParmReadFile(const char *file, int mode)
1174{
1175 FILE *in = NULL;
1176 struct parmHeader *conf;
1177 struct parmHandle *parmHandle = NULL;
1178 char buf[LINE_SZ];
1179 int len;
1180 int done;
1181 const unsigned long parmHandleSize = sizeof (struct parmHandle);
1182
1183 /* search for an already openned header & clean the conf if necessary */
1184 conf = getSharedHeader (file, mode);
1185
1186 /* Conf Header creation */
1187 if (conf == NULL) {
1188 conf = createParmHeader (file);
1189 if (!conf) {
1190 GfError ("gfParmReadFile: conf header creation failed\n");
1191 goto bailout;
1192 }
1193 mode |= GFPARM_RMODE_REREAD;
1194 }
1195
1196 /* Handle creation */
1197 parmHandle = (struct parmHandle *) calloc (1, parmHandleSize);
1198 if (!parmHandle) {
1199 GfError ("gfParmReadFile: calloc (1, %lu) failed\n", parmHandleSize);
1200 goto bailout;
1201 }
1202
1204 parmHandle->conf = conf;
1205 if (mode & GFPARM_RMODE_PRIVATE) {
1207 }
1208
1209 /* File opening */
1210 if (mode & GFPARM_RMODE_REREAD) {
1211 in = fopen (file, "r");
1212 if (!in && ((mode & GFPARM_RMODE_CREAT) == 0)) {
1213 GfOut ("gfParmReadFile: fopen \"%s\" failed\n", file);
1214 goto bailout;
1215 }
1216
1217 if (in) {
1218 /* Parsers Initialization */
1219 if (parserXmlInit (parmHandle)) {
1220 GfError ("gfParmReadBuf: parserInit failed for file \"%s\"\n", file);
1221 goto bailout;
1222 }
1223 /* Parameters reading */
1224 do {
1225 len = fread (buf, 1, sizeof(buf), in);
1226 done = len < (int)sizeof(buf);
1227 if (parseXml (parmHandle, buf, len, done)) {
1228 GfError ("gfParmReadFile: Parse failed in file \"%s\"\n", file);
1229 goto bailout;
1230 }
1232 /* parse error occured, ignore */
1233 GfError ("gfParmReadFile: Parse failed in file \"%s\"\n", file);
1234 goto bailout;
1235 }
1236 } while (!done);
1237
1238 fclose (in);
1239 in = NULL;
1240 }
1241 }
1242
1244
1245 GfOut ("GfParmReadFile: Opening \"%s\" (%p)\n", file, parmHandle);
1246
1247 return parmHandle;
1248
1249 bailout:
1250 if (in) {
1251 fclose (in);
1252 }
1253 if (parmHandle && parmHandle->parser) {
1255 }
1256 freez (parmHandle);
1257 if (conf) {
1259 }
1260
1261 return NULL;
1262}
1263
1264
1274static int formatXmlBuffer(char *buf, const int size, const char *format, ...)
1275{
1276 va_list args;
1277 int len;
1278
1279 if (size <= 0) {
1280 GfError("formatXmlBuffer: invalid buffer size\n");
1281 return -1;
1282 }
1283
1284 va_start(args, format);
1285 len = vsnprintf(buf, size, format, args);
1286 va_end(args);
1287
1288 if ((len < 0) || (len >= size)) {
1289 buf[0] = '\0';
1290 GfError("formatXmlBuffer: buffer too small for XML output\n");
1291 return -1;
1292 }
1293
1294 return 0;
1295}
1296
1297
1307static int handleEntities(char *buf, const int BUFSIZE, const char* val)
1308{
1309 int i = 0;
1310 int len = strlen(val);
1311 const char *replacement;
1312 char *pos = buf;
1313 int rlen;
1314
1315 if (BUFSIZE <= 0) {
1316 GfError("handleEntities: invalid buffer size\n");
1317 return -1;
1318 }
1319
1320 for (i = 0; i < len; i++) {
1321 switch (val[i]) {
1322 case '<':
1323 replacement = "&lt;"; break;
1324 case '>':
1325 replacement = "&gt;"; break;
1326 case '&':
1327 replacement = "&amp;"; break;
1328 case '\'':
1329 replacement = "&apos;"; break;
1330 case '"':
1331 replacement = "&quot;"; break;
1332 default:
1333 replacement = 0;
1334 }
1335
1336 if (replacement == 0) {
1337 replacement = &val[i];
1338 rlen = 1;
1339 } else {
1340 rlen = strlen(replacement);
1341 }
1342
1343 if (pos-buf < BUFSIZE - rlen) {
1344 memcpy(pos, replacement, rlen*sizeof(char));
1345 pos += rlen;
1346 } else {
1347 buf[0] = '\0';
1348 GfError("handleEntities: buffer too small to convert %s\n", val);
1349 return -1;
1350 }
1351 }
1352
1353 *pos = '\0';
1354
1355 return 0;
1356}
1357
1358
1368static int createIndent(char *buf, const int BUFSIZE, const int blanks)
1369{
1370 int pos = 0;
1371 if ((BUFSIZE <= 0) || (blanks < 0) || (blanks >= BUFSIZE)) {
1372 if (BUFSIZE > 0) {
1373 buf[0] = '\0';
1374 }
1375 GfError("createIndent: buffer too small for XML indentation\n");
1376 return -1;
1377 }
1378
1379 while (pos < blanks) {
1380 *buf++ = ' ';
1381 pos++;
1382 }
1383 *buf = '\0';
1384
1385 return 0;
1386}
1387
1388
1398static int createIn(char *buf, const int BUFSIZE, withinHead* head)
1399{
1400 const char* s = " in=\"";
1401 struct within* curWithin = GF_TAILQ_FIRST(head);
1402 int pos = 0;
1403 bool separator = false;
1404
1405 if (BUFSIZE <= 0) {
1406 GfError("createIn: invalid buffer size\n");
1407 return -1;
1408 }
1409
1410 *buf = '\0'; // Terminate for empty content
1411
1412 while (curWithin != 0) {
1413 int len = strlen(s);
1414 if (pos < BUFSIZE - len - 1) {
1415 memcpy(buf, s, len*sizeof(char));
1416 buf += len;
1417 pos += len;
1418 } else {
1419 GfError("createIn: buffer too small for XML within attribute\n");
1420 return -1;
1421 }
1422
1423 if (separator) {
1424 curWithin = GF_TAILQ_NEXT(curWithin, linkWithin);
1425 if (curWithin != 0) {
1426 s = ",";
1427 separator = false;
1428 }
1429 } else {
1430 s = curWithin->val;
1431 separator = true;
1432 }
1433 }
1434
1435 // Just terminate if we have written something
1436 if (pos > 0) {
1437 memcpy(buf, "\"", 2*sizeof(char));
1438 }
1439
1440 return 0;
1441}
1442
1443
1456static int xmlGetOuputLine(struct parmHandle *parmHandle, char *buffer, int size)
1457{
1458 struct parmOutput *outCtrl = &(parmHandle->outCtrl);
1459 struct parmHeader *conf = parmHandle->conf;
1460 struct section *curSection;
1461 struct param *curParam;
1462 char *s;
1463 const int BUFSIZE = 1024;
1464 char buf[BUFSIZE];
1465 const int INDENTSIZE = 1024;
1466 char indent[INDENTSIZE];
1467 const int INSIZE = 1024;
1468 char in[INSIZE];
1469 const int NUMVALUE = 1024;
1470 char numvalue[NUMVALUE];
1471
1472 while (1) {
1473 switch (outCtrl->state) {
1474 case 0:
1475 if (formatXmlBuffer(buffer, size, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n") != 0) {
1476 return -1;
1477 }
1478 outCtrl->indent = 0;
1479 outCtrl->state = 1;
1480 return 1;
1481
1482 case 1:
1483 if (conf->dtd == NULL) {
1484 conf->dtd = strdup("params.dtd");
1485 }
1486 if (conf->header == NULL) {
1487 conf->header = strdup("");
1488 }
1489 if (formatXmlBuffer(buffer, size, "<!DOCTYPE params SYSTEM \"%s\">\n%s\n", conf->dtd, conf->header) != 0) {
1490 return -1;
1491 }
1492 outCtrl->indent = 0;
1493 outCtrl->state = 2;
1494 return 1;
1495
1496 case 2: /* Start Params */
1498 if (formatXmlBuffer(buffer, size, "\n<params name=\"%s\">\n", parmHandle->conf->name) != 0) {
1499 return -1;
1500 }
1501 curSection = GF_TAILQ_FIRST (&(outCtrl->curSection->subSectionList));
1502 if (curSection) {
1503 outCtrl->curSection = curSection;
1504 outCtrl->indent += 2;
1505 outCtrl->state = 4;
1506 } else {
1507 outCtrl->state = 3;
1508 }
1509 return 1;
1510
1511 case 3: /* End Params */
1512 if (formatXmlBuffer(buffer, size, "</params>\n") != 0) {
1513 return -1;
1514 }
1515 outCtrl->state = 9;
1516 return 1;
1517
1518 case 4: /* Parse section attributes list */
1519 outCtrl->curParam = GF_TAILQ_FIRST (&(outCtrl->curSection->paramList));
1520 s = strrchr (outCtrl->curSection->fullName, '/');
1521 if (!s) {
1522 s = outCtrl->curSection->fullName;
1523 } else {
1524 s++;
1525 }
1526
1527 if ((createIndent(indent, INDENTSIZE, outCtrl->indent) != 0)
1528 || (handleEntities(buf, BUFSIZE, s) != 0)
1529 || (formatXmlBuffer(buffer, size, "%s<section name=\"%s\">\n", indent, buf) != 0)) {
1530 return -1;
1531 }
1532
1533 outCtrl->indent += 2;
1534 outCtrl->state = 5;
1535 return 1;
1536
1537 case 5: /* Parse one attribute */
1538 if (!outCtrl->curParam) {
1539 outCtrl->state = 6;
1540 break;
1541 }
1542
1543 curParam = outCtrl->curParam;
1544 if (curParam->type == P_STR) {
1545 if ((createIndent(indent, INDENTSIZE, outCtrl->indent) != 0)
1546 || (createIn(in, INSIZE, &(curParam->withinList)) != 0)
1547 || (handleEntities(buf, BUFSIZE, curParam->value) != 0)
1548 || (formatXmlBuffer(buffer, size, "%s<attstr name=\"%s\"%s val=\"%s\"/>\n", indent, curParam->name, in, buf) != 0)) {
1549 return -1;
1550 }
1551
1552 outCtrl->curParam = GF_TAILQ_NEXT (curParam, linkParam);
1553 return 1;
1554 } else {
1555 if (curParam->unit) {
1556 if ((curParam->min != curParam->valnum) || (curParam->max != curParam->valnum)) {
1557 if (formatXmlBuffer(numvalue, NUMVALUE, " min=\"%g\" max=\"%g\" unit=\"%s\" val=\"%g\"/>\n",
1558 GfParmSI2Unit (curParam->unit, curParam->min),
1559 GfParmSI2Unit (curParam->unit, curParam->max),
1560 curParam->unit,
1561 GfParmSI2Unit (curParam->unit, curParam->valnum)
1562 ) != 0) {
1563 return -1;
1564 }
1565 } else {
1566 if (formatXmlBuffer(numvalue, NUMVALUE, " unit=\"%s\" val=\"%g\"/>\n",
1567 curParam->unit,
1568 GfParmSI2Unit (curParam->unit, curParam->valnum)
1569 ) != 0) {
1570 return -1;
1571 }
1572 }
1573 } else {
1574 if ((curParam->min != curParam->valnum) || (curParam->max != curParam->valnum)) {
1575 if (formatXmlBuffer(numvalue, NUMVALUE, " min=\"%g\" max=\"%g\" val=\"%g\"/>\n",
1576 curParam->min,
1577 curParam->max,
1578 curParam->valnum
1579 ) != 0) {
1580 return -1;
1581 }
1582 } else {
1583 if (formatXmlBuffer(numvalue, NUMVALUE, " val=\"%g\"/>\n", curParam->valnum) != 0) {
1584 return -1;
1585 }
1586 }
1587 }
1588
1589 if ((createIndent(indent, INDENTSIZE, outCtrl->indent) != 0)
1590 || (formatXmlBuffer(buffer, size, "%s<attnum name=\"%s\"%s", indent, curParam->name, numvalue) != 0)) {
1591 return -1;
1592 }
1593
1594 outCtrl->curParam = GF_TAILQ_NEXT (curParam, linkParam);
1595 return 1;
1596 }
1597
1598 case 6: /* Parse sub-section list */
1599 curSection = GF_TAILQ_FIRST (&(outCtrl->curSection->subSectionList));
1600 if (curSection) {
1601 outCtrl->curSection = curSection;
1602 outCtrl->state = 4;
1603 break;
1604 }
1605 outCtrl->state = 7;
1606 break;
1607
1608 case 7: /* End Section */
1609 outCtrl->indent -= 2;
1610 if ((createIndent(indent, INDENTSIZE, outCtrl->indent) != 0)
1611 || (formatXmlBuffer(buffer, size, "%s</section>\n\n", indent) != 0)) {
1612 return -1;
1613 }
1614 outCtrl->state = 8;
1615 return 1;
1616
1617 case 8: /* Parse next section at the same level */
1618 curSection = GF_TAILQ_NEXT (outCtrl->curSection, linkSection);
1619 if (curSection) {
1620 outCtrl->curSection = curSection;
1621 outCtrl->state = 4;
1622 break;
1623 }
1624 curSection = outCtrl->curSection->parent;
1625 outCtrl->indent -= 2;
1626 if (curSection->parent) {
1627 outCtrl->curSection = curSection;
1628 if ((createIndent(indent, INDENTSIZE, outCtrl->indent) != 0)
1629 || (formatXmlBuffer(buffer, size, "%s</section>\n\n", indent) != 0)) {
1630 return -1;
1631 }
1632 return 1;
1633 }
1634 outCtrl->state = 3;
1635 break;
1636 case 9:
1637 return 0;
1638 }
1639 }
1640}
1641
1642
1656int GfParmWriteBuf(void *handle, char *buf, int size)
1657{
1658 struct parmHandle *parmHandle = (struct parmHandle *)handle;
1659 char line[LINE_SZ];
1660 int len;
1661 int curSize;
1662 int status = 0;
1663 char *s;
1664
1665 if (parmHandle->magic != PARM_MAGIC) {
1666 GfFatal ("gfParmWriteBuf: bad handle (%p)\n", parmHandle);
1667 return 1;
1668 }
1669 if (size <= 0) {
1670 return 1;
1671 }
1672
1675 parmHandle->outCtrl.curParam = NULL;
1676 curSize = size;
1677 s = buf;
1678
1679 while (curSize && ((status = xmlGetOuputLine (parmHandle, line, sizeof (line))) > 0)) {
1680 len = strlen (line);
1681 if (len > curSize) {
1682 len = curSize;
1683 }
1684 memcpy (s, line, len);
1685 s += len;
1686 curSize -= len;
1687 }
1688 buf [size - 1] = 0;
1689 if (status < 0) {
1690 return 1;
1691 }
1692
1693 return 0;
1694}
1695
1696
1704void GfParmSetDTD(void *parmHandle, char *dtd, char*header)
1705{
1706 struct parmHandle *handle = (struct parmHandle *)parmHandle;
1707 struct parmHeader *conf = handle->conf;
1708
1709 if (dtd) {
1710 FREEZ(conf->dtd);
1711 conf->dtd = strdup(dtd);
1712 }
1713
1714 if (header) {
1715 FREEZ(conf->header);
1716 conf->header = strdup(header);
1717 }
1718}
1719
1720
1732int GfParmWriteFile(const char *file, void *parmHandle, const char *name)
1733{
1734 struct parmHandle *handle = (struct parmHandle *)parmHandle;
1735 struct parmHeader *conf = handle->conf;
1736 char line[LINE_SZ];
1737 int status;
1738 FILE *fout;
1739
1740 if (handle->magic != PARM_MAGIC) {
1741 GfFatal ("gfParmWriteFile: bad handle (%p)\n", parmHandle);
1742 return 1;
1743 }
1744
1745 if (!file) {
1746 file = conf->filename;
1747 if (!file) {
1748 GfError ("gfParmWriteFile: bad file name\n");
1749 return 1;
1750 }
1751 }
1752
1753 fout = fopen (file, "wb");
1754 if (!fout) {
1755 GfError ("gfParmSetStr: fopen (%s, \"wb\") failed\n", file);
1756 return 1;
1757 }
1758
1759 if (name) {
1760 FREEZ (conf->name);
1761 conf->name = strdup (name);
1762 }
1763
1764 handle->outCtrl.state = 0;
1765 handle->outCtrl.curSection = NULL;
1766 handle->outCtrl.curParam = NULL;
1767
1768 while ((status = xmlGetOuputLine (handle, line, sizeof (line))) > 0) {
1769 fputs (line, fout);
1770 }
1771 if (status < 0) {
1772 fclose (fout);
1773 return 1;
1774 }
1775
1776 GfOut ("GfParmWriteFile: %s file written\n", file);
1777
1778 fclose (fout);
1779
1780 return 0;
1781}
1782
1783
1793int GfParmCreateDirectory(const char *file, void *parmHandle)
1794{
1795 struct parmHandle *handle = (struct parmHandle *)parmHandle;
1796 struct parmHeader *conf = handle->conf;
1797
1798 if (handle->magic != PARM_MAGIC) {
1799 GfFatal ("GfParmCreateDirectory: bad handle (%p)\n", parmHandle);
1800 return 1;
1801 }
1802
1803 if (!file) {
1804 file = conf->filename;
1805 if (!file) {
1806 GfError ("GfParmCreateDirectory: bad file name\n");
1807 return 1;
1808 }
1809 }
1810
1811 if (GfCreateDirForFile(file) != GF_DIR_CREATED) {
1812 return 1;
1813 }
1814
1815 return 0;
1816}
1817
1818
1829void GfParmRemove(void *parmHandle, char *sectionName, char *paramName)
1830{
1831 struct parmHandle *handle = (struct parmHandle *)parmHandle;
1832 struct parmHeader *conf;
1833
1834 conf = handle->conf;
1835
1836 if (handle->magic != PARM_MAGIC) {
1837 GfFatal ("gfParmRemove: bad handle (%p)\n", parmHandle);
1838 return;
1839 }
1840
1841 removeParamByName(conf, sectionName, paramName);
1842}
1843
1844
1850static void parmClean(struct parmHeader *conf)
1851{
1852 struct section *section;
1853
1854 while ((section = GF_TAILQ_FIRST (&(conf->rootSection->subSectionList))) !=
1856 {
1857 removeSection (conf, section);
1858 }
1859}
1860
1861
1871{
1872 struct parmHandle *handle = (struct parmHandle *)parmHandle;
1873 struct parmHeader *conf;
1874
1875 conf = handle->conf;
1876
1877 if (handle->magic != PARM_MAGIC) {
1878 GfFatal ("gfParmClean: bad handle (%p)\n", parmHandle);
1879 return;
1880 }
1881
1882 parmClean (conf);
1883}
1884
1885
1894static void parmReleaseHeader(struct parmHeader *conf)
1895{
1896 conf->refcount--;
1897 if (conf->refcount > 0) {
1898 return;
1899 }
1900
1901 GfOut ("parmReleaseHeader: refcount null free \"%s\"\n", conf->filename);
1902
1903 parmClean (conf);
1904
1905 freez (conf->filename);
1906 if (conf->paramHash) {
1907 GfHashRelease (conf->paramHash, NULL);
1908 }
1909
1910 if (conf->sectionHash) {
1911 GfHashRelease (conf->sectionHash, NULL);
1912 }
1913
1914 freez (conf->rootSection->fullName);
1915 freez (conf->rootSection);
1916 freez (conf->dtd);
1917 freez (conf->name);
1918 freez (conf->header);
1919 freez (conf);
1920}
1921
1922
1932{
1933 struct parmHeader *conf = parmHandle->conf;
1934
1935 GfOut ("parmReleaseHandle: release \"%s\" (%p)\n", conf->filename, parmHandle);
1936
1938 parmHandle->magic = 0;
1939 freez (parmHandle);
1940
1941 parmReleaseHeader(conf);
1942}
1943
1944
1964{
1965 struct parmHandle *handle = (struct parmHandle *)parmHandle;
1966
1967 if (handle->magic != PARM_MAGIC) {
1968 GfFatal ("gfParmReleaseHandle: bad handle (%p)\n", parmHandle);
1969 return;
1970 }
1971
1972 parmReleaseHandle(handle);
1973}
1974
1975
1988static void evalUnit(char *unit, tdble *dest, int flg)
1989{
1990 tdble coeff = 1.0;
1991
1992 if (strcmp(unit, "m") == 0) return;
1993 if (strcmp(unit, "kg") == 0) return;
1994 if (strcmp(unit, "s") == 0) return;
1995 if (strcmp(unit, "rad") == 0) return;
1996 if (strcmp(unit, "Pa") == 0) return;
1997
1998 if ((strcmp(unit, "feet") == 0) || (strcmp(unit, "ft") == 0)) {
1999 coeff = 0.304801f; /* m */
2000 } else if (strcmp(unit, "deg") == 0) {
2001 coeff = (float) (M_PI/180.0); /* rad */
2002 } else if ((strcmp(unit, "h") == 0) || (strcmp(unit, "hour") == 0) || (strcmp(unit, "hours") == 0)) {
2003 coeff = 3600.0; /* s */
2004 } else if ((strcmp(unit, "day") == 0) || (strcmp(unit, "days") == 0)) {
2005 coeff = 24*3600.0; /* s */
2006 } else if (strcmp(unit, "km") == 0) {
2007 coeff = 1000.0; /* m */
2008 } else if (strcmp(unit, "mm") == 0) {
2009 coeff = 0.001f; /* m */
2010 } else if (strcmp(unit, "cm") == 0) {
2011 coeff = 0.01f; /* m */
2012 } else if ((strcmp(unit, "in") == 0) || (strcmp(unit, "inch") == 0) || (strcmp(unit, "inches") == 0)) {
2013 coeff = 0.0254f; /* m */
2014 } else if ((strcmp(unit, "lbs") == 0) || (strcmp(unit, "lb") == 0)) {
2015 coeff = 0.45359237f; /* kg */
2016 } else if (strcmp(unit, "lbf") == 0) {
2017 coeff = 0.45359237f*G; /* N (kg*m/s^2) */
2018 } else if ((strcmp(unit, "slug") == 0) || (strcmp(unit, "slugs") == 0)) {
2019 coeff = 14.59484546f; /* kg */
2020 } else if (strcmp(unit, "kPa") == 0) {
2021 coeff = 1000.0; /* Pa */
2022 } else if (strcmp(unit, "MPa") == 0) {
2023 coeff = 1000000.0; /* Pa */
2024 } else if ((strcmp(unit, "PSI") == 0) || (strcmp(unit, "psi") == 0)){
2025 coeff = 6894.76f; /* Pa */
2026 } else if ((strcmp(unit, "rpm") == 0) || (strcmp(unit, "RPM") == 0)) {
2027 coeff = 0.104719755f; /* rad/s */
2028 } else if ((strcmp(unit, "percent") == 0) || (strcmp(unit, "%") == 0)) {
2029 coeff = 0.01f;
2030 } else if ((strcmp(unit, "mph") == 0) || (strcmp(unit, "MPH") == 0)) {
2031 coeff = 0.44704f; /* m/s */
2032 }
2033
2034 if (flg) {
2035 *dest /= coeff;
2036 } else {
2037 *dest *= coeff;
2038 }
2039
2040 return;
2041}
2042
2043
2079tdble GfParmUnit2SI(const char *unit, tdble val)
2080{
2081 char buf[256];
2082 int idx;
2083 const char *s;
2084 int inv;
2085 tdble dest = val;
2086
2087 if ((unit == NULL) || (strlen(unit) == 0)) return dest;
2088
2089 s = unit;
2090 buf[0] = 0;
2091 inv = 0;
2092 idx = 0;
2093
2094 while (*s != 0) {
2095 switch (*s) {
2096 case '.':
2097 evalUnit(buf, &dest, inv);
2098 buf[0] = 0;
2099 idx = 0;
2100 break;
2101 case '/':
2102 evalUnit(buf, &dest, inv);
2103 buf[0] = 0;
2104 idx = 0;
2105 inv = 1;
2106 break;
2107 case '2':
2108 evalUnit(buf, &dest, inv);
2109 evalUnit(buf, &dest, inv);
2110 buf[0] = 0;
2111 idx = 0;
2112 break;
2113 default:
2114 buf[idx++] = *s;
2115 buf[idx] = 0;
2116 break;
2117 }
2118 s++;
2119 }
2120
2121 evalUnit(buf, &dest, inv);
2122 return dest;
2123}
2124
2125
2133tdble GfParmSI2Unit(const char *unit, tdble val)
2134{
2135 char buf[256];
2136 int idx;
2137 const char *s;
2138 int inv;
2139 tdble dest = val;
2140
2141 if ((unit == NULL) || (strlen(unit) == 0)) return dest;
2142
2143 s = unit;
2144 buf[0] = 0;
2145 inv = 1;
2146 idx = 0;
2147
2148 while (*s != 0) {
2149 switch (*s) {
2150 case '.':
2151 evalUnit(buf, &dest, inv);
2152 buf[0] = 0;
2153 idx = 0;
2154 break;
2155 case '/':
2156 evalUnit(buf, &dest, inv);
2157 buf[0] = 0;
2158 idx = 0;
2159 inv = 0;
2160 break;
2161 case '2':
2162 evalUnit(buf, &dest, inv);
2163 evalUnit(buf, &dest, inv);
2164 buf[0] = 0;
2165 idx = 0;
2166 break;
2167 default:
2168 buf[idx++] = *s;
2169 buf[idx] = 0;
2170 break;
2171 }
2172 s++;
2173 }
2174
2175 evalUnit(buf, &dest, inv);
2176 return dest;
2177}
2178
2179
2180
2192char* GfParmGetName(void *handle)
2193{
2194 struct parmHandle *parmHandle = (struct parmHandle *)handle;
2195 struct parmHeader *conf = parmHandle->conf;
2196
2197 if (parmHandle->magic != PARM_MAGIC) {
2198 GfFatal ("GfParmGetName: bad handle (%p)\n", parmHandle);
2199 return NULL;
2200 }
2201
2202 return conf->name;
2203}
2204
2205
2218char* GfParmGetFileName(void *handle)
2219{
2220 struct parmHandle *parmHandle = (struct parmHandle *)handle;
2221 struct parmHeader *conf = parmHandle->conf;
2222
2223 if (parmHandle->magic != PARM_MAGIC) {
2224 GfFatal ("GfParmGetFileName: bad handle (%p)\n", parmHandle);
2225 return NULL;
2226 }
2227
2228 return conf->filename;
2229}
2230
2231
2243int GfParmGetEltNb(void *handle, const char *path)
2244{
2245 struct parmHandle *parmHandle = (struct parmHandle *)handle;
2246 struct parmHeader *conf = parmHandle->conf;
2247 struct section *section;
2248 int count;
2249
2250 if (parmHandle->magic != PARM_MAGIC) {
2251 GfFatal ("GfParmGetEltNb: bad handle (%p)\n", parmHandle);
2252 return 0;
2253 }
2254
2255 section = (struct section *)GfHashGetStr (conf->sectionHash, path);
2256 if (!section) {
2257 return 0;
2258 }
2259
2260 count = 0;
2262 while (section) {
2263 count++;
2264 section = GF_TAILQ_NEXT (section, linkSection);
2265 }
2266
2267 return count;
2268}
2269
2270
2271
2286int GfParmListSeekFirst(void *handle, const char *path)
2287{
2288 struct parmHandle *parmHandle = (struct parmHandle *)handle;
2289 struct parmHeader *conf = parmHandle->conf;
2290 struct section *section;
2291
2292 if (parmHandle->magic != PARM_MAGIC) {
2293 GfFatal ("GfParmListSeekFirst: bad handle (%p)\n", parmHandle);
2294 return -1;
2295 }
2296
2297 section = (struct section *)GfHashGetStr (conf->sectionHash, path);
2298 if (!section) {
2299 return -1;
2300 }
2301
2303
2304 return 0;
2305}
2306
2307
2323int GfParmListSeekNext(void *handle, const char *path)
2324{
2325 struct parmHandle *parmHandle = (struct parmHandle *)handle;
2326 struct parmHeader *conf = parmHandle->conf;
2327 struct section *section;
2328
2329 if (parmHandle->magic != PARM_MAGIC) {
2330 GfFatal ("GfParmListSeekNext: bad handle (%p)\n", parmHandle);
2331 return -1;
2332 }
2333
2334 section = (struct section *)GfHashGetStr (conf->sectionHash, path);
2335 if ((!section) || (!section->curSubSection)) {
2336 return -1;
2337 }
2338
2340
2341 if (section->curSubSection) {
2342 return 0;
2343 }
2344
2345 return 1;
2346}
2347
2348
2362int GfParmListClean(void *handle, const char *path)
2363{
2364 struct parmHandle *parmHandle = (struct parmHandle *)handle;
2365 struct parmHeader *conf = parmHandle->conf;
2366 struct section *listSection;
2367 struct section *section;
2368
2369 if (parmHandle->magic != PARM_MAGIC) {
2370 GfFatal ("GfParmListSeekNext: bad handle (%p)\n", parmHandle);
2371 return -1;
2372 }
2373
2374 listSection = (struct section *)GfHashGetStr (conf->sectionHash, path);
2375 if (!listSection) {
2376 GfOut ("GfParmListClean: \"%s\" not found\n", path);
2377 return -1;
2378 }
2379
2380 while ((section = GF_TAILQ_FIRST (&(listSection->subSectionList))) != NULL) {
2381 removeSection (conf, section);
2382 }
2383
2384 return 0;
2385}
2386
2387
2410char* GfParmListGetCurEltName(void *handle, const char *path)
2411{
2412 struct parmHandle *parmHandle = (struct parmHandle *)handle;
2413 struct parmHeader *conf = parmHandle->conf;
2414 struct section *section;
2415 char *s;
2416
2417 if (parmHandle->magic != PARM_MAGIC) {
2418 GfFatal ("GfParmListGetCurEltName: bad handle (%p)\n", parmHandle);
2419 return NULL;
2420 }
2421
2422 section = (struct section *)GfHashGetStr (conf->sectionHash, path);
2423 if ((!section) || (!section->curSubSection)) {
2424 return NULL;
2425 }
2426
2427 s = strrchr(section->curSubSection->fullName, '/');
2428 if (s) {
2429 s++;
2430 return s;
2431 }
2432
2434}
2435
2436
2453const char* GfParmGetStr(void *parmHandle, const char *path, const char *key, const char *deflt)
2454{
2455 struct param *param;
2456 struct parmHandle *handle = (struct parmHandle *)parmHandle;
2457 struct parmHeader *conf = handle->conf;
2458
2459 if (handle->magic != PARM_MAGIC) {
2460 GfFatal ("gfParmGetStr: bad handle (%p)\n", parmHandle);
2461 return deflt;
2462 }
2463
2464 param = getParamByName (conf, path, key, 0);
2465 if (!param || !(param->value) || !strlen (param->value) || (param->type != P_STR)) {
2466 return deflt;
2467 }
2468
2469 return param->value;
2470}
2471
2472
2496const char* GfParmGetCurStr(void *handle, const char *path, const char *key, const char *deflt)
2497{
2498 struct parmHandle *parmHandle = (struct parmHandle *)handle;
2499 struct parmHeader *conf = parmHandle->conf;
2500 struct section *section;
2501 struct param *param;
2502
2503 if (parmHandle->magic != PARM_MAGIC) {
2504 GfFatal ("GfParmGetCurStr: bad handle (%p)\n", parmHandle);
2505 return deflt;
2506 }
2507
2508 section = (struct section *)GfHashGetStr (conf->sectionHash, path);
2509 if ((!section) || (!section->curSubSection)) {
2510 return deflt;
2511 }
2512
2514 if (!param || !(param->value) || !strlen (param->value) || (param->type != P_STR)) {
2515 return deflt;
2516 }
2517
2518 return param->value;
2519}
2520
2521
2534tdble GfParmGetNum(void *handle, const char *path, const char *key, const char *unit, tdble deflt)
2535{
2536 struct parmHandle *parmHandle = (struct parmHandle *)handle;
2537 struct parmHeader *conf = parmHandle->conf;
2538 struct param *param;
2539
2540 if (parmHandle->magic != PARM_MAGIC) {
2541 GfFatal ("GfParmGetNum: bad handle (%p)\n", parmHandle);
2542 return deflt;
2543 }
2544
2545 param = getParamByName (conf, path, key, 0);
2546 if (!param || (param->type != P_NUM)) {
2547 return deflt;
2548 }
2549
2550 if (unit) {
2551 return GfParmSI2Unit(unit, param->valnum);
2552 }
2553
2554 return param->valnum;
2555}
2556
2557
2578tdble GfParmGetCurNum(void *handle, const char *path, const char *key, const char *unit, tdble deflt)
2579{
2580 struct parmHandle *parmHandle = (struct parmHandle *)handle;
2581 struct parmHeader *conf = parmHandle->conf;
2582 struct section *section;
2583 struct param *param;
2584
2585 if (parmHandle->magic != PARM_MAGIC) {
2586 GfFatal ("GfParmGetCurNum: bad handle (%p)\n", parmHandle);
2587 return deflt;
2588 }
2589
2590 section = (struct section *)GfHashGetStr (conf->sectionHash, path);
2591 if ((!section) || (!section->curSubSection)) {
2592 return deflt;
2593 }
2594
2596 if (!param || (param->type != P_NUM)) {
2597 return deflt;
2598 }
2599
2600 if (unit) {
2601 return GfParmSI2Unit(unit, param->valnum);
2602 }
2603
2604 return param->valnum;
2605}
2606
2607
2623int GfParmSetStr(void *handle, const char *path, const char *key, const char *val)
2624{
2625 struct parmHandle *parmHandle = (struct parmHandle *)handle;
2626 struct parmHeader *conf = parmHandle->conf;
2627 struct param *param;
2628
2629 if (parmHandle->magic != PARM_MAGIC) {
2630 GfFatal ("GfParmSetStr: bad handle (%p)\n", parmHandle);
2631 return -1;
2632 }
2633
2634 if (!val || !strlen (val)) {
2635 /* Remove the entry */
2636 removeParamByName (conf, path, key);
2637 return 0;
2638 }
2639
2640 param = getParamByName (conf, path, key, PARAM_CREATE);
2641 if (!param) {
2642 return -1;
2643 }
2644
2645 param->type = P_STR;
2646 freez (param->value);
2647 param->value = strdup (val);
2648
2649 if (!param->value) {
2650 GfError ("gfParmSetStr: strdup (%s) failed\n", val);
2651 removeParamByName (conf, path, key);
2652 return -1;
2653 }
2654
2655 return 0;
2656}
2657
2658
2682int GfParmSetCurStr(void *handle, const char *path, const char *key, const char *val)
2683{
2684 struct parmHandle *parmHandle = (struct parmHandle *)handle;
2685 struct parmHeader *conf = parmHandle->conf;
2686 struct section *section;
2687 struct param *param;
2688
2689 if (parmHandle->magic != PARM_MAGIC) {
2690 GfFatal ("GfParmSetCurStr: bad handle (%p)\n", parmHandle);
2691 return -1;
2692 }
2693
2694 section = (struct section *)GfHashGetStr (conf->sectionHash, path);
2695 if ((!section) || (!section->curSubSection)) {
2696 return -1;
2697 }
2698
2699 if (!val || !strlen (val)) {
2700 /* Remove the entry */
2702 return 0;
2703 }
2704
2706 if (!param) {
2707 return -1;
2708 }
2709
2710 param->type = P_STR;
2711 freez (param->value);
2712 param->value = strdup (val);
2713 if (!param->value) {
2714 GfError ("gfParmSetStr: strdup (%s) failed\n", val);
2716 return -1;
2717 }
2718
2719 return 0;
2720}
2721
2722
2737int GfParmSetNum(void *handle, const char *path, const char *key, const char *unit, tdble val)
2738{
2739 struct parmHandle *parmHandle = (struct parmHandle *)handle;
2740 struct parmHeader *conf = parmHandle->conf;
2741 struct param *param;
2742
2743 if (parmHandle->magic != PARM_MAGIC) {
2744 GfFatal ("GfParmSetNum: bad handle (%p)\n", parmHandle);
2745 return -1;
2746 }
2747
2748 param = getParamByName (conf, path, key, PARAM_CREATE);
2749 if (!param) {
2750 return -11;
2751 }
2752
2753 param->type = P_NUM;
2754 FREEZ (param->unit);
2755 if (unit) {
2756 param->unit = strdup (unit);
2757 }
2758
2759 val = GfParmUnit2SI (unit, val);
2760 param->valnum = val;
2761 param->min = val;
2762 param->max = val;
2763
2764 return 0;
2765}
2766
2767
2783int GfParmSetNumEx(void *handle, const char *path, const char *key, const char *unit, tdble val, tdble min, tdble max)
2784{
2785 struct parmHandle *parmHandle = (struct parmHandle *)handle;
2786 struct parmHeader *conf = parmHandle->conf;
2787 struct param *param;
2788
2789 if (parmHandle->magic != PARM_MAGIC) {
2790 GfFatal ("GfParmSetNumEx: bad handle (%p)\n", parmHandle);
2791 return -1;
2792 }
2793
2794 param = getParamByName (conf, path, key, PARAM_CREATE);
2795 if (!param) {
2796 return -1;
2797 }
2798
2799 param->type = P_NUM;
2800 FREEZ (param->unit);
2801 if (unit) {
2802 param->unit = strdup (unit);
2803 }
2804
2805 param->valnum = GfParmUnit2SI (unit, val);
2808
2809 return 0;
2810}
2811
2812
2834int GfParmSetCurNum(void *handle, const char *path, const char *key, const char *unit, tdble val)
2835{
2836 struct parmHandle *parmHandle = (struct parmHandle *)handle;
2837 struct parmHeader *conf = parmHandle->conf;
2838 struct section *section;
2839 struct param *param;
2840
2841 if (parmHandle->magic != PARM_MAGIC) {
2842 GfFatal ("GfParmSetCurNum: bad handle (%p)\n", parmHandle);
2843 return -1;
2844 }
2845
2846 section = (struct section *)GfHashGetStr (conf->sectionHash, path);
2847 if ((!section) || (!section->curSubSection)) {
2848 return -1;
2849 }
2850
2852 if (!param) {
2853 return -1;
2854 }
2855
2856 param->type = P_NUM;
2857 FREEZ (param->unit);
2858 if (unit) {
2859 param->unit = strdup (unit);
2860 }
2861
2862 val = GfParmUnit2SI (unit, val);
2863 param->valnum = val;
2864 param->min = val;
2865 param->max = val;
2866
2867 return 0;
2868}
2869
2870
2871
2885int GfParmCheckHandle(void *ref, void *tgt)
2886{
2887 struct parmHandle *parmHandleRef = (struct parmHandle *)ref;
2888 struct parmHandle *parmHandle = (struct parmHandle *)tgt;
2889 struct parmHeader *confRef = parmHandleRef->conf;
2890 struct parmHeader *conf = parmHandle->conf;
2891 struct section *curSectionRef;
2892 struct section *nextSectionRef;
2893 struct param *curParamRef;
2894 struct param *curParam;
2895 struct within *curWithinRef;
2896 int found;
2897 int error = 0;
2898
2899 if ((parmHandleRef->magic != PARM_MAGIC) || (parmHandle->magic != PARM_MAGIC)) {
2900 GfFatal ("GfParmCheckHandle: bad handle (%p)\n", parmHandle);
2901 return -1;
2902 }
2903
2904 /* Traverse all the reference tree */
2905 curSectionRef = GF_TAILQ_FIRST (&(confRef->rootSection->subSectionList));
2906 while (curSectionRef) {
2907 curParamRef = GF_TAILQ_FIRST (&(curSectionRef->paramList));
2908 while (curParamRef) {
2909 /* compare params */
2910 curParam = getParamByName (conf, curSectionRef->fullName, curParamRef->name, 0);
2911 if (curParam) {
2912 if (curParamRef->type != curParam->type) {
2913 GfError("GfParmCheckHandle: type mismatch for parameter \"%s\" in (\"%s\" - \"%s\")\n",
2914 curParamRef->fullName, conf->name, conf->filename);
2915 error = -1;
2916 } else if (curParamRef->type == P_NUM) {
2917 if ((curParam->valnum < curParamRef->min) || (curParam->valnum > curParamRef->max)) {
2918 GfError("GfParmCheckHandle: parameter \"%s\" out of bounds: min:%g max:%g val:%g in (\"%s\" - \"%s\")\n",
2919 curParamRef->fullName, curParamRef->min, curParamRef->max, curParam->valnum, conf->name, conf->filename);
2920 }
2921 } else {
2922 curWithinRef = GF_TAILQ_FIRST (&(curParamRef->withinList));
2923 found = 0;
2924 while (!found && curWithinRef) {
2925 if (!strcmp (curWithinRef->val, curParam->value)) {
2926 found = 1;
2927 } else {
2928 curWithinRef = GF_TAILQ_NEXT (curWithinRef, linkWithin);
2929 }
2930 }
2931 if (!found && strcmp (curParamRef->value, curParam->value)) {
2932 GfError("GfParmCheckHandle: parameter \"%s\" value:\"%s\" not allowed in (\"%s\" - \"%s\")\n",
2933 curParamRef->fullName, curParam->value, conf->name, conf->filename);
2934 }
2935 }
2936 }
2937 curParamRef = GF_TAILQ_NEXT (curParamRef, linkParam);
2938 }
2939
2940 nextSectionRef = GF_TAILQ_NEXT (curSectionRef, linkSection);
2941 while (!nextSectionRef) {
2942 nextSectionRef = curSectionRef->parent;
2943 if (!nextSectionRef) {
2944 /* Reached the root */
2945 break;
2946 }
2947 curSectionRef = nextSectionRef;
2948 nextSectionRef = GF_TAILQ_NEXT (curSectionRef, linkSection);
2949 }
2950 curSectionRef = nextSectionRef;
2951 }
2952
2953 return error;
2954}
2955
2956
2971static void insertParamMerge(struct parmHandle *parmHandle, char *path, struct param *paramRef, struct param *param)
2972{
2973 struct parmHeader *conf = parmHandle->conf;
2974 struct param *paramNew;
2975 struct within *withinRef;
2976 struct within *within;
2977 tdble num;
2978 char *str;
2979
2980 paramNew = getParamByName (conf, path, param->name, PARAM_CREATE);
2981 if (!paramNew) {
2982 return;
2983 }
2984
2985 if (param->type == P_NUM) {
2986 paramNew->type = P_NUM;
2987 FREEZ (paramNew->unit);
2988 if (param->unit) {
2989 paramNew->unit = strdup (param->unit);
2990 }
2991
2992 if (param->min < paramRef->min) {
2993 num = paramRef->min;
2994 } else {
2995 num = param->min;
2996 }
2997 paramNew->min = num;
2998
2999 if (param->max > paramRef->max) {
3000 num = paramRef->max;
3001 } else {
3002 num = param->max;
3003 }
3004 paramNew->max = num;
3005 num = param->valnum;
3006
3007 if (num < paramNew->min) {
3008 num = paramNew->min;
3009 }
3010
3011 if (num > paramNew->max) {
3012 num = paramNew->max;
3013 }
3014 paramNew->valnum = num;
3015 } else {
3016 paramNew->type = P_STR;
3017 FREEZ (paramNew->value);
3019
3020 while (within) {
3021 withinRef = GF_TAILQ_FIRST (&(paramRef->withinList));
3022 while (withinRef) {
3023 if (!strcmp (withinRef->val, within->val)) {
3024 addWithin (paramNew, within->val);
3025 break;
3026 }
3027 withinRef = GF_TAILQ_NEXT (withinRef, linkWithin);
3028 }
3029 within = GF_TAILQ_NEXT (within, linkWithin);
3030 }
3031 str = NULL;
3032 withinRef = GF_TAILQ_FIRST (&(paramRef->withinList));
3033
3034 while (withinRef) {
3035 if (!strcmp (withinRef->val, param->value)) {
3036 str = param->value;
3037 break;
3038 }
3039 withinRef = GF_TAILQ_NEXT (withinRef, linkWithin);
3040 }
3041
3042 if (!str) {
3043 str = paramRef->value;
3044 }
3045
3046 paramNew->value = strdup (str);
3047 }
3048}
3049
3050
3063static void insertParam(struct parmHandle *parmHandle, char *path, struct param *param)
3064{
3065 struct parmHeader *conf = parmHandle->conf;
3066 struct param *paramNew;
3067 struct within *within;
3068
3069 paramNew = getParamByName (conf, path, param->name, PARAM_CREATE);
3070 if (!paramNew) {
3071 return;
3072 }
3073
3074 if (param->type == P_NUM) {
3075 paramNew->type = P_NUM;
3076 FREEZ (paramNew->unit);
3077 if (param->unit) {
3078 paramNew->unit = strdup (param->unit);
3079 }
3080 paramNew->valnum = param->valnum;
3081 paramNew->min = param->min;
3082 paramNew->max = param->max;
3083 } else {
3084 paramNew->type = P_STR;
3085 FREEZ (paramNew->value);
3086 paramNew->value = strdup (param->value);
3088 while (within) {
3089 addWithin (paramNew, within->val);
3090 within = GF_TAILQ_NEXT (within, linkWithin);
3091 }
3092 }
3093}
3094
3095
3129void *GfParmMergeHandles(void *ref, void *tgt, int mode)
3130{
3131 struct parmHandle *parmHandleRef = (struct parmHandle *)ref;
3132 struct parmHandle *parmHandleTgt = (struct parmHandle *)tgt;
3133 struct parmHandle *parmHandleOut;
3134 struct parmHeader *confRef = parmHandleRef->conf;
3135 struct parmHeader *confTgt = parmHandleTgt->conf;
3136 struct parmHeader *confOut;
3137 struct section *curSectionRef;
3138 struct section *nextSectionRef;
3139 struct section *curSectionTgt;
3140 struct section *nextSectionTgt;
3141 struct param *curParamRef;
3142 struct param *curParamTgt;
3143 const unsigned long parmHandleSize = sizeof (struct parmHandle);
3144
3145 GfOut ("Merging \"%s\" and \"%s\" (%s - %s)\n", confRef->filename, confTgt->filename, ((mode & GFPARM_MMODE_SRC) ? "SRC" : ""), ((mode & GFPARM_MMODE_DST) ? "DST" : ""));
3146
3147 if (parmHandleRef->magic != PARM_MAGIC) {
3148 GfFatal ("GfParmMergeHandles: bad handle (%p)\n", parmHandleRef);
3149 return NULL;
3150 }
3151 if (parmHandleTgt->magic != PARM_MAGIC) {
3152 GfFatal ("GfParmMergeHandles: bad handle (%p)\n", parmHandleTgt);
3153 return NULL;
3154 }
3155
3156 /* Conf Header creation */
3157 confOut = createParmHeader ("");
3158 if (!confOut) {
3159 GfError ("gfParmReadBuf: conf header creation failed\n");
3160 return NULL;
3161 }
3162
3163 /* Handle creation */
3164 parmHandleOut = (struct parmHandle *) calloc (1, parmHandleSize);
3165 if (!parmHandleOut) {
3166 GfError ("gfParmReadBuf: calloc (1, %lu) failed\n", parmHandleSize);
3167 parmReleaseHeader (confOut);
3168 return NULL;
3169 }
3170
3171 parmHandleOut->magic = PARM_MAGIC;
3172 parmHandleOut->conf = confOut;
3173 parmHandleOut->flag = PARM_HANDLE_FLAG_PRIVATE;
3174
3175 if (mode & GFPARM_MMODE_SRC) {
3176 /* Traverse all the reference tree */
3177 curSectionRef = GF_TAILQ_FIRST (&(confRef->rootSection->subSectionList));
3178 while (curSectionRef) {
3179 curParamRef = GF_TAILQ_FIRST (&(curSectionRef->paramList));
3180 while (curParamRef) {
3181 /* compare params */
3182 curParamTgt = getParamByName (confTgt, curSectionRef->fullName, curParamRef->name, 0);
3183 if (curParamTgt) {
3184 insertParamMerge (parmHandleOut, curSectionRef->fullName, curParamRef, curParamTgt);
3185 } else {
3186 insertParam (parmHandleOut, curSectionRef->fullName, curParamRef);
3187 }
3188 curParamRef = GF_TAILQ_NEXT (curParamRef, linkParam);
3189 }
3190 nextSectionRef = GF_TAILQ_FIRST (&(curSectionRef->subSectionList));
3191 if (nextSectionRef) {
3192 curSectionRef = nextSectionRef;
3193 } else {
3194 nextSectionRef = GF_TAILQ_NEXT (curSectionRef, linkSection);
3195 while (!nextSectionRef) {
3196 nextSectionRef = curSectionRef->parent;
3197 if (!nextSectionRef) {
3198 /* Reached the root */
3199 break;
3200 }
3201 curSectionRef = nextSectionRef;
3202 nextSectionRef = GF_TAILQ_NEXT (curSectionRef, linkSection);
3203 }
3204 curSectionRef = nextSectionRef;
3205 }
3206 }
3207 }
3208
3209 if (mode & GFPARM_MMODE_DST) {
3210 /* Traverse all the target tree */
3211 curSectionTgt = GF_TAILQ_FIRST (&(confTgt->rootSection->subSectionList));
3212 while (curSectionTgt) {
3213 curParamTgt = GF_TAILQ_FIRST (&(curSectionTgt->paramList));
3214 while (curParamTgt) {
3215 /* compare params */
3216 curParamRef = getParamByName (confRef, curSectionTgt->fullName, curParamTgt->name, 0);
3217 if (curParamRef) {
3218 insertParamMerge (parmHandleOut, curSectionTgt->fullName, curParamRef, curParamTgt);
3219 } else {
3220 insertParam (parmHandleOut, curSectionTgt->fullName, curParamTgt);
3221 }
3222 curParamTgt = GF_TAILQ_NEXT (curParamTgt, linkParam);
3223 }
3224
3225 nextSectionTgt = GF_TAILQ_FIRST (&(curSectionTgt->subSectionList));
3226 if (nextSectionTgt) {
3227 curSectionTgt = nextSectionTgt;
3228 } else {
3229 nextSectionTgt = GF_TAILQ_NEXT (curSectionTgt, linkSection);
3230 while (!nextSectionTgt) {
3231 nextSectionTgt = curSectionTgt->parent;
3232 if (!nextSectionTgt) {
3233 /* Reached the root */
3234 break;
3235 }
3236 curSectionTgt = nextSectionTgt;
3237 nextSectionTgt = GF_TAILQ_NEXT (curSectionTgt, linkSection);
3238 }
3239 curSectionTgt = nextSectionTgt;
3240 }
3241 }
3242 }
3243
3244 if (mode & GFPARM_MMODE_RELSRC) {
3246 }
3247
3248 if (mode & GFPARM_MMODE_RELDST) {
3250 }
3251
3252 GF_TAILQ_INSERT_HEAD (&parmHandleList, parmHandleOut, linkHandle);
3253
3254 return (void*)parmHandleOut;
3255}
3256
3257
3268int GfParmGetNumBoundaries(void *handle, const char *path, const char *key, tdble *min, tdble *max)
3269{
3270 struct parmHandle *parmHandle = (struct parmHandle *)handle;
3271 struct parmHeader *conf = parmHandle->conf;
3272 struct param *param;
3273
3274 if (parmHandle->magic != PARM_MAGIC) {
3275 GfFatal ("GfParmGetNumBoundaries: bad handle (%p)\n", parmHandle);
3276 return -1;
3277 }
3278
3279 param = getParamByName (conf, path, key, 0);
3280 if (!param || (param->type != P_NUM)) {
3281 return -1;
3282 }
3283
3284 *min = param->min;
3285 *max = param->max;
3286
3287 return 0;
3288}
3289
3290
Scalar min(Scalar x, Scalar y)
Definition Basic.h:49
Scalar max(Scalar x, Scalar y)
Definition Basic.h:50
static Point p[4]
Definition Convex.cpp:54
void GfParmShutdown(void)
Parameter set library API shutdown, removes parameter set handle cache.
Definition params.cpp:172
void GfParmInit(void)
Parameter set library API initialization, set up parameter set handle cache.
Definition params.cpp:160
float tdble
Floating point type used in TORCS.
Definition tgf.h:47
const void * GfHashRemStr(void *hash, char *key)
Remove an element with a string key from a hash table.
Definition hash.cpp:219
void GfHashRelease(void *hash, tfHashFree hashFree)
Release a hash table.
Definition hash.cpp:353
int GfHashAddStr(void *hash, const char *key, const void *data)
Add an element with a string key to a hash table.
Definition hash.cpp:170
const void * GfHashGetStr(void *hash, const char *key)
Get the user data associated with a string key.
Definition hash.cpp:245
void * GfHashCreate(int type)
Create a new hash table.
Definition hash.cpp:98
int GfParmSetNumEx(void *handle, const char *path, const char *key, const char *unit, tdble val, tdble min, tdble max)
Set a numerical parameter and its bounds, creating it if necessary.
Definition params.cpp:2783
const char * GfParmGetStr(void *parmHandle, const char *path, const char *key, const char *deflt)
Get a string parameter from the parameter set handle.
Definition params.cpp:2453
int GfParmSetStr(void *handle, const char *path, const char *key, const char *val)
Set a string parameter in the parameter set handle.
Definition params.cpp:2623
tdble GfParmGetNum(void *handle, const char *path, const char *key, const char *unit, tdble deflt)
Get a numerical parameter from the parameter set handle.
Definition params.cpp:2534
tdble GfParmUnit2SI(const char *unit, tdble val)
Convert a value given in unit to SI.
Definition params.cpp:2079
char * GfParmGetName(void *handle)
Get the name property of the parameter set handle.
Definition params.cpp:2192
tdble GfParmSI2Unit(const char *unit, tdble val)
Convert a value from SI to given unit.
Definition params.cpp:2133
int GfParmGetNumBoundaries(void *handle, const char *path, const char *key, tdble *min, tdble *max)
Get the min and max of a numerical parameter from the parameter set handle.
Definition params.cpp:3268
int GfParmSetNum(void *handle, const char *path, const char *key, const char *unit, tdble val)
Set a numerical parameter in the parameter set handle.
Definition params.cpp:2737
void GfParmRemove(void *parmHandle, char *sectionName, char *paramName)
Remove a parameter from a parameter set.
Definition params.cpp:1829
void GfParmReleaseHandle(void *parmHandle)
Release given parameter set handle parmHandle.
Definition params.cpp:1963
int GfParmCreateDirectory(const char *file, void *parmHandle)
Create directory for parameter set handle if it does not yet exist.
Definition params.cpp:1793
char * GfParmGetFileName(void *handle)
Get the filename property of the parameter set handle.
Definition params.cpp:2218
void GfParmClean(void *parmHandle)
Clean all the parameters of a parameter set.
Definition params.cpp:1870
int GfParmWriteFile(const char *file, void *parmHandle, const char *name)
Write parameter set into file.
Definition params.cpp:1732
int GfParmWriteBuf(void *handle, char *buf, int size)
Write a parameter set into a memory buffer.
Definition params.cpp:1656
int GfParmCheckHandle(void *ref, void *tgt)
Check the values in the parameter set tgt against the min/max/within definitions in the ref parameter...
Definition params.cpp:2885
void * GfParmMergeHandles(void *ref, void *tgt, int mode)
Merge two parameter sets into a new private set.
Definition params.cpp:3129
void GfParmSetDTD(void *parmHandle, char *dtd, char *header)
Set the dtd path and header.
Definition params.cpp:1704
void * GfParmReadBuf(char *buffer)
Read parameter set from memory buffer and return handle to parameter set.
Definition params.cpp:1099
void * GfParmReadFile(const char *file, int mode)
Read parameter set from file and return handle to parameter set.
Definition params.cpp:1173
static struct parmHeader * getSharedHeader(const char *file, int mode)
Helper function for looking up parameter sets in the cache.
Definition params.cpp:551
static void removeParamByName(struct parmHeader *conf, const char *sectionName, const char *paramName)
Helper function to remove a parameter with given name paramName.
Definition params.cpp:259
static int handleEntities(char *buf, const int BUFSIZE, const char *val)
Helper function to convert the input line given in val into proper XML notation, the output goes into...
Definition params.cpp:1307
static void parmReleaseHeader(struct parmHeader *conf)
Helper function to release the parameter set if the reference counter is 0.
Definition params.cpp:1894
static int createIndent(char *buf, const int BUFSIZE, const int blanks)
Helper function for indentation in the XML.
Definition params.cpp:1368
static tdble getValNumFromStr(const char *str)
Helper function to parse number.
Definition params.cpp:679
static void addWithin(struct param *curParam, char *s1)
Helper function to add "within" options to parameter curParam.
Definition params.cpp:653
static int xmlGetOuputLine(struct parmHandle *parmHandle, char *buffer, int size)
Helper function to output one line of XML generated from the given parameter set.
Definition params.cpp:1456
static void xmlStartElement(void *userData, const char *name, const char **atts)
Helper function to process opening XML elements.
Definition params.cpp:703
static void xmlEndElement(void *userData, const XML_Char *name)
Helper function to process closing XML elements.
Definition params.cpp:948
static struct section * addSection(struct parmHeader *conf, const char *sectionName)
Helper function to add a section to a parameter set.
Definition params.cpp:486
static void cleanUnusedSection(struct parmHeader *conf, struct section *section)
Helper function to clean up unused (empty) sections starting with given section.
Definition params.cpp:296
static struct section * getParent(struct parmHeader *conf, const char *sectionName)
Helper function to get (or create if not found) parent section of section given in sectionName.
Definition params.cpp:446
static void insertParam(struct parmHandle *parmHandle, char *path, struct param *param)
Helper function to insert a parameter into a parameter set.
Definition params.cpp:3063
static void removeParam(struct parmHeader *conf, struct section *section, struct param *param)
Helper function to remove given parameter.
Definition params.cpp:321
static void evalUnit(char *unit, tdble *dest, int flg)
Support function to multiply or divide dest with unit conversion factor.
Definition params.cpp:1988
static struct parmHeader * createParmHeader(const char *file)
Helper function to create header for parameter set handle.
Definition params.cpp:587
static int formatXmlBuffer(char *buf, const int size, const char *format,...)
Helper function to format text without truncating the output.
Definition params.cpp:1274
static void parmClean(struct parmHeader *conf)
Helper function to release the parameter set content.
Definition params.cpp:1850
static int xmlExternalEntityRefHandler(XML_Parser mainparser, const XML_Char *openEntityNames, const XML_Char *base, const XML_Char *systemId, const XML_Char *publicId)
Helper function to handle external XML entities (XML referencing over multiple files/URI's).
Definition params.cpp:978
static void removeSection(struct parmHeader *conf, struct section *section)
Helper function to remove a section and its contents (subsections, elements).
Definition params.cpp:416
static int parserXmlInit(struct parmHandle *parmHandle)
Helper function to set up XML parser in parmHandle.
Definition params.cpp:1077
static int createIn(char *buf, const int BUFSIZE, withinHead *head)
Helper function to support the serialization into the XML of the "within" attribute.
Definition params.cpp:1398
static struct param * getParamByName(struct parmHeader *conf, const char *sectionName, const char *paramName, int flag)
Helper function to get (or create) a parameter by name.
Definition params.cpp:218
static void parmReleaseHandle(struct parmHandle *parmHandle)
Helper function to release the handle and eventually the referenced parameter set (if the reference c...
Definition params.cpp:1931
static void insertParamMerge(struct parmHandle *parmHandle, char *path, struct param *paramRef, struct param *param)
Helper function to merge a parameter into a parameter set.
Definition params.cpp:2971
static char * getFullName(const char *sectionName, const char *paramName)
Helper function to get the full name of a parameter (full name: "sectionName/paramName").
Definition params.cpp:192
static struct param * addParam(struct parmHeader *conf, struct section *section, const char *paramName, const char *value)
Helper function to add parameter, does not check for duplicated name.
Definition params.cpp:351
static int parseXml(struct parmHandle *parmHandle, char *buf, int len, int done)
Helper function to parse one line of XML.
Definition params.cpp:1054
char * GfParmListGetCurEltName(void *handle, const char *path)
Get current subsection name of the parameter set handle during subsection iteration.
Definition params.cpp:2410
int GfParmListSeekNext(void *handle, const char *path)
Advance to the next immediate subsection.
Definition params.cpp:2323
int GfParmListClean(void *handle, const char *path)
Remove all the subsections in a section in the parameter set handle.
Definition params.cpp:2362
int GfParmListSeekFirst(void *handle, const char *path)
Select the first immediate subsection of a section.
Definition params.cpp:2286
int GfParmGetEltNb(void *handle, const char *path)
Count the number of subsections in a section in the parameter set handle.
Definition params.cpp:2243
int GfParmSetCurNum(void *handle, const char *path, const char *key, const char *unit, tdble val)
Set a numerical parameter in the parameter set handle based on subsection iteration.
Definition params.cpp:2834
int GfParmSetCurStr(void *handle, const char *path, const char *key, const char *val)
Set a string parameter in the parameter set handle based on subsection iteration.
Definition params.cpp:2682
tdble GfParmGetCurNum(void *handle, const char *path, const char *key, const char *unit, tdble deflt)
Get a numerical parameter from the parameter set handle based on subsection iteration.
Definition params.cpp:2578
const char * GfParmGetCurStr(void *handle, const char *path, const char *key, const char *deflt)
Get a string parameter from the parameter set handle based on subsection iteration.
Definition params.cpp:2496
#define GF_TAILQ_INSERT_TAIL(head, elm, field)
Insert an element at the tail.
Definition tgf.h:510
#define GF_TAILQ_INIT(head)
Head initialization (Mandatory)
Definition tgf.h:484
#define GF_TAILQ_HEAD(name, type)
Head type definition.
Definition tgf.h:447
#define GF_TAILQ_END(head)
End of a TAILQ.
Definition tgf.h:469
#define GF_TAILQ_NEXT(elm, field)
Next element of a TAILQ.
Definition tgf.h:466
#define GF_TAILQ_REMOVE(head, elm, field)
Remove an element.
Definition tgf.h:540
#define GF_TAILQ_FIRST(head)
First element of a TAILQ.
Definition tgf.h:463
#define GF_TAILQ_INSERT_HEAD(head, elm, field)
Insert an element at the head.
Definition tgf.h:498
#define PARM_MAGIC
Definition params.cpp:93
#define PARM_HANDLE_FLAG_PRIVATE
Definition params.cpp:108
#define LINE_SZ
Definition params.cpp:41
#define P_NUM
Definition params.cpp:44
#define P_STR
Definition params.cpp:45
#define PARAM_CREATE
Definition params.cpp:42
#define PARM_HANDLE_FLAG_PARSE_ERROR
Definition params.cpp:109
static struct parmHead parmHandleList
Definition params.cpp:138
static int myStrcmp(const void *s1, const void *s2)
Definition params.cpp:667
Parameter header structure, a parameter can either carry a numeric or a string value,...
Definition params.cpp:63
tdble min
Minimum for numeric value.
Definition params.cpp:70
char * unit
Unit, see GfParmUnit2SI for supported units.
Definition params.cpp:69
int type
Type, either P_NUM or P_STR.
Definition params.cpp:68
tdble max
Maximum for numeric value.
Definition params.cpp:71
tdble valnum
Numeric value of the parameter.
Definition params.cpp:67
char * fullName
Name of the parameter including the full section name ('/' separated)
Definition params.cpp:65
GF_TAILQ_ENTRY(struct param) linkParam
Next parameter in the same section.
char * name
Name of the parameter.
Definition params.cpp:64
char * value
String value of the parameter.
Definition params.cpp:66
struct withinHead withinList
Linked list containing the options for legal string values.
Definition params.cpp:72
Parameter set handle structure, multiple handles can reference the same parameter set.
Definition params.cpp:125
GF_TAILQ_ENTRY(struct parmHandle) linkHandle
Next configuration handle.
int magic
Magic number (to detect wrong type casts and such)
Definition params.cpp:126
struct section * curSection
Current section, for iterations, see GfParmListSeekFirst and GfParmListSeekNext.
Definition params.cpp:130
XML_Parser parser
Parser.
Definition params.cpp:129
struct parmHeader * conf
Header of the parameter set.
Definition params.cpp:127
struct parmOutput outCtrl
Ouput control structure used for serializing parameter set into XML.
Definition params.cpp:131
int flag
Flag (PARM_HANDLE_FLAG_PARSE_ERROR, PARM_HANDLE_FLAG_PRIVATE)
Definition params.cpp:128
Configuration header structure.
Definition params.cpp:97
char * name
Name of the data.
Definition params.cpp:99
char * filename
Name of the configuration file.
Definition params.cpp:98
char * dtd
Optional DTD location.
Definition params.cpp:100
void * sectionHash
Hash table for section access.
Definition params.cpp:105
int refcount
Use counter (number of conf handle)
Definition params.cpp:102
void * paramHash
Hash table for parameter access.
Definition params.cpp:104
struct section * rootSection
List of sections at the first level.
Definition params.cpp:103
char * header
Optional header (comment, xsl...)
Definition params.cpp:101
Ouput control structure used for serializing parameter set into XML.
Definition params.cpp:114
int state
Internal state.
Definition params.cpp:115
int indent
Keep track of indentation.
Definition params.cpp:119
struct param * curParam
Current parameter.
Definition params.cpp:117
struct section * curSection
Current section.
Definition params.cpp:116
char * filename
Name of the output file.
Definition params.cpp:118
Section header structure.
Definition params.cpp:83
struct section * parent
Parent section.
Definition params.cpp:89
struct paramHead paramList
List of the parameters in this section.
Definition params.cpp:85
struct section * curSubSection
Current subsection, for iterations, see GfParmListSeekFirst and GfParmListSeekNext.
Definition params.cpp:88
char * fullName
Name of the section including full path ('/' separated)
Definition params.cpp:84
struct sectionHead subSectionList
List of sub-sections (linked by linkSection)
Definition params.cpp:87
GF_TAILQ_ENTRY(struct section) linkSection
Next section at the same level.
Structure to hold linked list of within options.
Definition params.cpp:49
char * val
Value of within option.
Definition params.cpp:50
GF_TAILQ_ENTRY(struct within) linkWithin
Link to next entry.
int GfCreateDirForFile(const char *filenameandpath)
Create directory for given file path recursively, so all missing parent directories are created as we...
Definition tgf.cpp:368
The Gaming Framework API.
#define GfOut
Definition tgf.h:372
#define GFPARM_RMODE_CREAT
Allow an empty in-memory set on file-open failure; does not write a file.
Definition tgf.h:266
#define GFPARM_MMODE_RELSRC
release ref after the merge
Definition tgf.h:314
#define GFPARM_MMODE_RELDST
release tgt after the merge
Definition tgf.h:315
const tdble G
m/s/s
Definition tgf.h:69
#define GFPARM_MMODE_SRC
Include ref attributes; merge common attributes using ref restrictions and tgt values.
Definition tgf.h:312
#define GFPARM_RMODE_REREAD
Clear shared cached data and reread the file.
Definition tgf.h:265
#define GF_HASH_TYPE_STR
String key based hash table.
Definition tgf.h:605
static void GfFatal(const char *fmt,...)
Definition tgf.h:338
#define GFPARM_MMODE_DST
Include tgt attributes; merge common attributes using ref restrictions and tgt values.
Definition tgf.h:313
#define GF_DIR_CREATED
Definition tgf.h:622
#define freez
Definition tgf.h:66
#define FREEZ(x)
Definition tgf.h:59
#define GfError
Definition tgf.h:350
#define GFPARM_RMODE_PRIVATE
Private means the handle is not shared/cached.
Definition tgf.h:267
void XMLPARSEAPI XML_SetExternalEntityRefHandler(XML_Parser parser, XML_ExternalEntityRefHandler handler)
enum XML_Error XMLPARSEAPI XML_GetErrorCode(XML_Parser parser)
char XML_Char
Definition xmlparse.h:60
void XMLPARSEAPI XML_SetElementHandler(XML_Parser parser, XML_StartElementHandler start, XML_EndElementHandler end)
#define XML_GetUserData(parser)
Definition xmlparse.h:276
int XMLPARSEAPI XML_Parse(XML_Parser parser, const char *s, int len, int isFinal)
XML_Parser XMLPARSEAPI XML_ExternalEntityParserCreate(XML_Parser parser, const XML_Char *openEntityNames, const XML_Char *encoding)
void XMLPARSEAPI XML_SetUserData(XML_Parser parser, void *userData)
const XML_LChar XMLPARSEAPI * XML_ErrorString(int code)
void * XML_Parser
Definition xmlparse.h:33
void XMLPARSEAPI XML_ParserFree(XML_Parser parser)
XML_Parser XMLPARSEAPI XML_ParserCreate(const XML_Char *encoding)
int XMLPARSEAPI XML_GetCurrentLineNumber(XML_Parser parser)