DSL
config.cpp
1 //@AUTOHEADER@BEGIN@
2 /***********************************************************************\
3 | Drift Standard Libraries v1.01 |
4 | Copyright 2010-2023 Drift Solutions / Indy Sams |
5 | Docs and more information available at https://www.driftsolutions.dev |
6 | This file released under the 3-clause BSD license, |
7 | see included DSL.LICENSE.TXT file for details. |
8 \***********************************************************************/
9 //@AUTOHEADER@END@
10 
11 #include <drift/dslcore.h>
12 #include <drift/config.h>
13 #include <drift/GenLib.h>
14 #include <math.h>
15 
16 Universal_Config::Universal_Config() {
17  fSection = NULL; // make sure section list is empty
18  lSection = NULL;
19  //memset(LastScan,0,sizeof(LastScan));
20 }
21 
22 Universal_Config::~Universal_Config() {
23  FreeConfig();
24 }
25 
26 void Universal_Config::ClearSection(DS_CONFIG_SECTION * Scan) {
27  DS_CONFIG_VALUE * ValScan = Scan->values;
28  Scan->values = NULL;
29  while (ValScan) {
30  DS_CONFIG_VALUE * ValDel = ValScan;
31  if (ValScan->value.type == DS_TYPE_STRING || ValScan->value.type == DS_TYPE_BINARY) {
32  //printf("free(): %s\n", ValScan->value.pString);
33  dsl_free(ValScan->value.pBinary);
34  }
35  ValScan = ValScan->Next;
36  dsl_free(ValDel);
37  }
38 
39  DS_CONFIG_SECTION * Scan2 = Scan->sections;
40  Scan->sections = NULL;
41  while (Scan2) {
42  DS_CONFIG_SECTION * toDel=Scan2;
43  Scan2=Scan2->Next;
44  FreeSection(toDel);
45  }
46 }
47 
48 void Universal_Config::FreeSection(DS_CONFIG_SECTION * Scan) {
49  ClearSection(Scan);
50  dsl_free(Scan);
51 };
52 
53 void Universal_Config::FreeConfig() {
54  DS_CONFIG_SECTION * Scan = fSection;
55  while (Scan) {
56  DS_CONFIG_SECTION * toDel=Scan;
57  Scan=Scan->Next;
58  FreeSection(toDel);
59  }
60  fSection=NULL;
61  lSection=NULL;
62 }
63 
64 DS_CONFIG_SECTION * Universal_Config::GetSection(DS_CONFIG_SECTION * parent, const char * name) {
65  DS_CONFIG_SECTION * Scan = parent ? parent->sections:fSection;
66 
67  while(Scan) {
68  if (!stricmp(Scan->name,name)) { return Scan; }
69  Scan=Scan->Next;
70  }
71 
72  return NULL;
73 }
74 
75 DS_VALUE * Universal_Config::GetSectionValue(DS_CONFIG_SECTION * sec, const char * name) {
76  if (!sec) { return NULL; }
77 
78  DS_CONFIG_VALUE * Scan = sec->values;
79  while (Scan) {
80  if (!stricmp(Scan->name,name)) {
81  return &Scan->value;
82  }
83  Scan=Scan->Next;
84  }
85  return NULL;
86 }
87 
88 DS_VALUE * Universal_Config::SetSectionValue(DS_CONFIG_SECTION * sec, const char * name, DS_VALUE * val) {
89  if (!sec) { return NULL; }
90  DS_VALUE * eval = GetSectionValue(sec,name);
91  if (eval) {
92  if (val != eval) {
93  if (eval->type == DS_TYPE_STRING || eval->type == DS_TYPE_BINARY) {
94  dsl_free(eval->pString);
95  }
96  memcpy(eval,val,sizeof(DS_VALUE));
97  if (eval->type == DS_TYPE_STRING) {
98  eval->pString = dsl_strdup(val->pString);
99  }
100  } else {
101  printf("Universal_Config() -> You must never pass a DS_VALUE to SetSectionValue that was returned from GetSectionValue\n");
102 #if defined(WIN32)
103  MessageBoxA(0, "Universal_Config() -> You must never pass a DS_VALUE to SetSectionValue that was returned from GetSectionValue", "Error", 0);
104 #endif
105  }
106  } else {
107  DS_CONFIG_VALUE * Scan = sec->values;
108  if (Scan) {
109  while (Scan->Next) {
110  Scan=Scan->Next;
111  }
112  Scan->Next = (DS_CONFIG_VALUE *)dsl_malloc(sizeof(DS_CONFIG_VALUE));
113  Scan->Next->Next=NULL;
114  Scan->Next->Prev = Scan;
115  Scan=Scan->Next;
116  strcpy(Scan->name,name);
117  } else {
118  Scan = (DS_CONFIG_VALUE *)dsl_malloc(sizeof(DS_CONFIG_VALUE));
119  Scan->Next=NULL;
120  Scan->Prev = NULL;
121  sec->values = Scan;
122  strcpy(Scan->name,name);
123  }
124 
125  memcpy(&Scan->value,val,sizeof(DS_VALUE));
126  if (Scan->value.type == DS_TYPE_STRING) {
127  Scan->value.pString = dsl_strdup(val->pString);
128  }
129  eval = &Scan->value;
130  }
131 
132  return eval;
133 }
134 
135 bool Universal_Config::IsLong(const char * buf) {
136  if (buf[0] == 0) { return false; } // null string
137 
138  // these next 2 lines detect numbers that would be out of range of a long
139  //if (buf[0] == '-' && strlen(buf) > 11) { return false; }
140  //if (strlen(buf) > 10) { return false; }
141 
142  int32 l = atoi(buf);
143  if (l == 0 && strcmp(buf,"0")) {
144  return false;
145  }
146 
147  if (l == 2147483647 && stricmp(buf, "2147483647")) {
148  return false;
149  }
150  if (l == -2147483647 && stricmp(buf, "-2147483647")) {
151  return false;
152  }
153 
154  //int periodCnt=0;
155  for(int i=0; buf[i] != 0; i++) {
156  if (buf[i] == '-' && i == 0 && buf[1] != 0) {
157  continue;
158  }
159  if(buf[i] < 48 || buf[i] > 57) { // not a number
160  return false;
161  }
162  }
163 
164  return true;
165 }
166 bool Universal_Config::IsFloat(const char * buf) {
167  if (buf[0] == 0) { return false; } // null string
168 
169  double l = atof(buf);
170  if (l == 0.0 && strcmp(buf,"0.0") && strcmp(buf,"0.00")) {
171  return false;
172  }
173 
174  if (l == HUGE_VAL || l == -HUGE_VAL) {
175  return false;
176  }
177 
178  int periodCnt=0;
179  for(int i=0; buf[i] != 0; i++) {
180  if (buf[i] == '-' && i == 0 && buf[1] != 0) {
181  continue;
182  }
183  if (buf[i] == '.') {
184  periodCnt++;
185  if (periodCnt == 1) { continue; }
186  return false;
187  }
188  if(buf[i] < 48 || buf[i] > 57) { // not a number
189  return false;
190  }
191  }
192 
193  return (periodCnt == 1) ? true:false;
194 }
195 
196 DS_CONFIG_SECTION * Universal_Config::FindOrAddSection(DS_CONFIG_SECTION * parent, const char * name) {
197  DS_CONFIG_SECTION * ret = GetSection(parent,name);
198  if (!ret) {
199  ret = (DS_CONFIG_SECTION *)dsl_malloc(sizeof(DS_CONFIG_SECTION));//DS_CONFIG_SECTION;
200  memset(ret,0,sizeof(DS_CONFIG_SECTION));
201 
202  if (!parent) {
203  if (fSection) {
204  lSection->Next = ret;
205  ret->Prev = lSection;
206  lSection = ret;
207  } else {
208  fSection=ret;
209  lSection=ret;
210  }
211  } else {
212  if (parent->sections) {
213  DS_CONFIG_SECTION * Scan = parent->sections;
214  while (Scan->Next != NULL) {
215  Scan = Scan->Next;
216  }
217  Scan->Next = ret;
218  Scan->Next->Prev = Scan;
219  } else {
220  parent->sections = ret;
221  }
222  }
223 
224  ret->Parent = parent;
225  strcpy(ret->name,name);
226  }
227  return ret;
228 }
229 
230 DS_CONFIG_SECTION * Universal_Config::PopScan() {
231  DS_CONFIG_SECTION * ret = scanStack.back(); // LastScan[0];
232  scanStack.pop_back();
233  return ret;
234 }
235 
236 void Universal_Config::PushScan(DS_CONFIG_SECTION * section) {
237  scanStack.push_back(section);
238 }
239 
240 bool Universal_Config::LoadConfig(FILE * fp, const char * fn, DS_CONFIG_SECTION * Scan) {
241  if (!fp) { return false; }
242 
243  char buf[256];
244  //char * p=NULL;
245 
246  int line=0;
247  bool long_comment=false;
248 
249  memset(buf, 0, sizeof(buf));
250 
251  while (fgets(buf,sizeof(buf),fp)) {
252  line++;
253  strtrim(buf," \t\r\n "); // first, trim the string of unwanted chars
254  if (strlen(buf) < 2) {
255  // the minimum meaningful line would be 2 chars long, specifically };
256  continue;
257  }
258 
259  str_replaceA(buf,sizeof(buf),"\t"," "); // turn tabs into spaces
260  while (strstr(buf, " ")) {
261  str_replaceA(buf,sizeof(buf)," "," "); // turn double-spaces into spaces
262  }
263 
264 // printf("line: %s\n",buf);
265 
266  if (stristr(buf, "#include")) {
267  char * p = stristr(buf, "#include");
268  p = strchr(p, '\"');
269  if (p) {
270  p++;
271  char *q = strchr(p, '\"');
272  if (q) {
273  q[0]=0;
274  if (LoadConfig(p, Scan)) {
275  Scan = PopScan();
276  } else {
277  printf("ERROR: Error loading #included file '%s'\n", p);
278  break;
279  }
280  } else {
281  printf("ERROR: Syntax is #include \"filename\"\n");
282  break;
283  }
284  } else {
285  printf("ERROR: Syntax is #include \"filename\"\n");
286  break;
287  }
288  continue;
289  }
290 
291  if (buf[0] == '#' || !strncmp(buf,"//",2)) {
292  continue;
293  }
294 
295  if (!strncmp(buf,"/*",2)) {
296  long_comment = true;
297  continue;
298  }
299 
300  if (long_comment) {
301  if (!strcmp(buf,"*/")) {
302  long_comment = false;
303  }
304  continue;
305  }
306 
307  char *p = (char *)&buf+(strlen(buf) - 2); // will be " {" if beginning a section
308  if (!strcmp(p," {")) { // open a new section
309  p[0]=0;
310  PushScan(Scan);
311  Scan = FindOrAddSection(Scan,buf);
312  continue;
313  }
314 
315  if (!strcmp(buf,"};")) { // close section
316  if (Scan != NULL) {
317  Scan = PopScan();
318  } else {
319  printf("ERROR: You have one too many }; near line %d of %s\n", line, fn);
320  break;
321  }
322  continue;
323  }
324 
325  StrTokenizer * tok = new StrTokenizer(buf,' ');
326  unsigned long num = tok->NumTok();
327  if (num > 1) {
328  DS_VALUE * sVal = (DS_VALUE *)dsl_malloc(sizeof(DS_VALUE));
329  memset(sVal, 0, sizeof(DS_VALUE));
330 
331  char * name = tok->GetSingleTok(1);
332  char * value = tok->GetTok(2,num);
333  if (IsFloat(value)) { // number
334  sVal->type = DS_TYPE_FLOAT;
335  sVal->lFloat = atof(value);
336  } else if (IsLong(value)) { // number
337  sVal->type = DS_TYPE_INT;
338  sVal->lLong = atol(value);
339  } else { // string
340  sVal->type = DS_TYPE_STRING;
341  sVal->pString = dsl_strdup(value);
342  }
343  if (Scan) {
344  SetSectionValue(Scan, name, sVal);
345  }
346  if (sVal->type == DS_TYPE_STRING) {
347  dsl_free(sVal->pString);
348  }
349  dsl_free(sVal);
350  tok->FreeString(name);
351  tok->FreeString(value);
352  delete tok;
353  continue;
354  }
355  delete tok;
356 
357  printf("Unrecognized line at %s:%d -> %s\n",fn,line,buf);
358  // some unknown line here
359  }
360 
361  PushScan(Scan);
362  return true;
363 }
364 
365 bool Universal_Config::LoadConfig(const char * filename, DS_CONFIG_SECTION * Scan) {
366  FILE * fp = fopen(filename, "rb");
367  if (!fp) { return false; }
368  bool ret = LoadConfig(fp, filename, Scan);
369  fclose(fp);
370  return ret;
371 }
372 
373 void Universal_Config::WriteSection(FILE * fp, DS_CONFIG_SECTION * sec, int level) {
374  char * pref = (char *)dsl_malloc(level+1);
375  for(int i=0; i<level; i++) { pref[i] = '\t'; }
376  pref[level]=0;
377 
378  char buf[1024];
379  sprintf(buf,"%s%s {\n",pref,sec->name);
380  fwrite(buf,strlen(buf),1,fp);
381 
382  DS_CONFIG_SECTION * Scan = sec->sections;
383  while (Scan) {
384  WriteSection(fp,Scan,level+1);
385  Scan = Scan->Next;
386  }
387 
388  DS_CONFIG_VALUE * val = sec->values;
389  while (val) {
390  switch(val->value.type) {
391  case DS_TYPE_INT:
392  sprintf(buf,"\t%s%s %d\n",pref,val->name,val->value.lLong);
393  fwrite(buf,strlen(buf),1,fp);
394  break;
395  case DS_TYPE_FLOAT:
396  sprintf(buf, "\t%s%s %f\n", pref, val->name, val->value.lFloat);
397  fwrite(buf, strlen(buf), 1, fp);
398  break;
399  case DS_TYPE_STRING:
400  sprintf(buf,"\t%s%s %s\n",pref,val->name,val->value.pString);
401  fwrite(buf,strlen(buf),1,fp);
402  break;
403  default:
404  break;
405  }
406  val = val->Next;
407  };
408 
409  sprintf(buf,"%s};\n",pref);
410  fwrite(buf,strlen(buf),1,fp);
411  dsl_free(pref);
412 }
413 
414 bool Universal_Config::WriteConfig(const char * filename, DS_CONFIG_SECTION * Start, bool Single) {
415  FILE * fp = fopen(filename,"wb");
416  if (!fp) { return false; }
417 
418  DS_CONFIG_SECTION * Scan = Start ? Start:this->fSection;
419  while (Scan) {
420  WriteSection(fp,Scan,0);
421  fwrite("\n",1,1,fp);
422  if (!Single) {
423  Scan = Scan->Next;
424  } else {
425  Scan = NULL;
426  }
427  }
428 
429  fclose(fp);
430  return true;
431 }
432 
433 
434 void Universal_Config::PrintSection(DS_CONFIG_SECTION * Scan, int level) {
435  char buf[32]={0};
436  for (int i=0; i < level; i++) {
437  strcat(buf,"\t");
438  }
439 
440  printf("%sSection: %s\n",buf,Scan->name);
441  strcat(buf,"\t");
442  DS_CONFIG_VALUE * ValScan = Scan->values;
443  while (ValScan) {
444  switch(ValScan->value.type) {
445  case DS_TYPE_INT:
446  printf("%s[%s] = %d\n",buf,ValScan->name,ValScan->value.lLong);
447  break;
448  case DS_TYPE_FLOAT:
449  printf("%s[%s] = %f\n", buf, ValScan->name, ValScan->value.lFloat);
450  break;
451  case DS_TYPE_STRING:
452  printf("%s[%s] = %s\n",buf,ValScan->name,ValScan->value.pString);
453  break;
454  default:
455  printf("%s[%s] = Binary Data @ %p\n",buf,ValScan->name,ValScan->value.pBinary);
456  break;
457  }
458  ValScan = ValScan->Next;
459  }
460 
461  DS_CONFIG_SECTION * Scan2 = Scan->sections;
462  while (Scan2) {
463  PrintSection(Scan2,level+1);
464  Scan2=Scan2->Next;
465  }
466 };
467 
468 void Universal_Config::PrintConfigTree() {
469  DS_CONFIG_SECTION * Scan = fSection;
470  while (Scan) {
471  PrintSection(Scan,0);
472  Scan=Scan->Next;
473  }
474 }
475 
476 #pragma pack(1)
477 struct UC_HEADER {
478  unsigned long magic1;
479  unsigned long magic2;
480  unsigned char version;
481 };
482 #pragma pack()
483 
484 enum UC_ENTRY_TYPE {
485  UC_ENTRY_TYPE_SECTION,
486  UC_ENTRY_TYPE_UP,
487  UC_ENTRY_TYPE_VALUE,
488  UC_ENTRY_TYPE_EOF
489 };
490 
491 bool Universal_Config::LoadBinaryConfig(const char * filename) {
492  FILE * fp = fopen(filename, "rb");
493  if (!fp) { return false; }
494  bool ret = LoadBinaryConfig(fp);
495  fclose(fp);
496  return ret;
497 }
498 
499 bool Universal_Config::LoadBinaryConfig(FILE * fp) {
500  if (!fp) { return false; }
501  UC_HEADER head;
502  memset(&head, 0, sizeof(head));
503  if (fread(&head, sizeof(head), 1, fp) != 1) {
504  printf("Error reading file header!\n");
505  return false;
506  }
507  if (head.magic1 != 0x54465244 || head.magic2 != 0x464E4F43) {
508  printf("Invalid magic in Dynamic Config file!\n");
509  return false;
510  }
511 
512  if (head.version > 0) {
513  printf("Unknown version in Dynamic Config file!\n");
514  return false;
515  }
516 
517  char buf[1024];
518  unsigned char type;
519 
520  DS_CONFIG_SECTION * sec = NULL;
521  DS_VALUE val;
522  bool berror = false;
523  while (fread(&type, 1, 1, fp) == 1 && !berror) {
524  memset(buf, 0, sizeof(buf));
525  switch(type) {
526  case UC_ENTRY_TYPE_SECTION:
527  if (fread(&type, 1, 1, fp) != 1) {
528  return false;
529  }
530  if (fread(buf, type, 1, fp) != 1) {
531  return false;
532  }
533  PushScan(sec);
534  sec = FindOrAddSection(sec, buf);
535  //printf("New section: %X (%s)\n", sec, sec ? sec->name : "N/A");
536  break;
537  case UC_ENTRY_TYPE_UP:
538  sec = PopScan();
539  //printf("Up to %X", sec);
540  break;
541  case UC_ENTRY_TYPE_VALUE:
542  fread(&type, 1, 1, fp);
543  fread(buf, type, 1, fp);
544  char * name;
545  name = dsl_strdup(buf);
546  memset(buf, 0, sizeof(buf));
547  fread(&type, 1, 1, fp);
548  val.type = (DS_VALUE_TYPE)type;
549  switch(type) {
550  case DS_TYPE_INT:
551  fread(&val.lLong,4,1,fp);
552  //printf("Got long for %s: %d\n", name, val.lLong);
553  break;
554  case DS_TYPE_FLOAT:
555  fread(&val.lFloat,sizeof(double),1,fp);
556  //printf("Got long for %s: %d\n", name, val.lLong);
557  break;
558  case DS_TYPE_STRING:
559  unsigned short len;
560  fread(&len,sizeof(len),1,fp);
561  fread(buf,len,1,fp);
562  val.pString = buf;
563  //printf("Got str for %s: %s\n", name, buf);
564  break;
565  }
566  this->SetSectionValue(sec, name, &val);
567  dsl_free(name);
568  break;
569  case UC_ENTRY_TYPE_EOF:
570  fseek(fp, 0, SEEK_END);
571  break;
572  default:
573  printf("ERROR: Unknown entry type at offset 0x%08X\n", (unsigned int)ftell(fp));
574  berror = true;
575  break;
576  }
577  }
578 
579  return true;
580 }
581 
582 void Universal_Config::WriteBinarySection(FILE * fp, DS_CONFIG_SECTION * sec) {
583 
584  char buf[1024];
585  buf[0] = UC_ENTRY_TYPE_SECTION;
586  fwrite(buf,1,1,fp);
587  buf[0] = (char)strlen(sec->name);
588  fwrite(buf,1,1,fp);
589  fwrite(sec->name,buf[0],1,fp);
590 
591  DS_CONFIG_SECTION * Scan = sec->sections;
592  while (Scan) {
593  WriteBinarySection(fp,Scan);
594  Scan = Scan->Next;
595  }
596 
597  DS_CONFIG_VALUE * val = sec->values;
598  while (val) {
599  buf[0] = UC_ENTRY_TYPE_VALUE;
600  fwrite(&buf[0],1,1,fp);
601 
602  buf[0] = (char)strlen(val->name);
603  fwrite(&buf[0],1,1,fp);
604  fwrite(val->name,buf[0],1,fp);
605 
606  buf[0] = val->value.type;
607  fwrite(&buf[0],1,1,fp);
608 
609  switch(val->value.type) {
610  case DS_TYPE_INT:
611  fwrite(&val->value.lLong,4,1,fp);
612  break;
613  case DS_TYPE_FLOAT:
614  fwrite(&val->value.lFloat,sizeof(double),1,fp);
615  break;
616  case DS_TYPE_STRING:
617  unsigned short len;
618  len = (unsigned short)strlen(val->value.pString);
619  fwrite(&len,sizeof(len),1,fp);
620  fwrite(val->value.pString,len,1,fp);
621  break;
622  default:
623  break;
624  }
625  val = val->Next;
626  };
627 
628  buf[0] = UC_ENTRY_TYPE_UP;
629  fwrite(buf,1,1,fp);
630 }
631 
632 bool Universal_Config::WriteBinaryConfig(const char * filename, DS_CONFIG_SECTION * Start, bool Single) {
633  FILE * fp = fopen(filename,"wb");
634  if (!fp) { return false; }
635 
636  UC_HEADER head;
637  head.magic1 = 0x54465244;
638  head.magic2 = 0x464E4F43;
639  head.version = 0;
640  fwrite(&head, sizeof(head), 1, fp);
641 
642  DS_CONFIG_SECTION * Scan = Start ? Start:this->fSection;
643  while (Scan) {
644  WriteBinarySection(fp,Scan);
645  if (!Single) {
646  Scan = Scan->Next;
647  } else {
648  Scan = NULL;
649  }
650  }
651 
652  unsigned type = UC_ENTRY_TYPE_EOF;
653  fwrite(&type,1,1,fp);
654  fclose(fp);
655  return true;
656 }
657 
658 Universal_Config * NewUniversalConfig() {
659  return new Universal_Config;
660 }
661 void FreeUniversalConfig(Universal_Config * cfg) {
662  delete cfg;
663 }
664 
665 DS_CONFIG_SECTION * Universal_Config::GetSectionFromString(const char * sec, bool create) {
666  if (*sec == '/') { sec++; }
667  StrTokenizer st((char *)sec, '/');
668  DS_CONFIG_SECTION * ret = NULL;
669 
670  int num = st.NumTok();
671  for (int i=1; i <= num; i++) {
672  char * str = st.GetSingleTok(i);
673  if (strcmp(str, "")) {
674  ret = create ? FindOrAddSection(ret, str) : GetSection(ret, str);
675  st.FreeString(str);
676  if (!ret) { return NULL; }
677  }
678  }
679  return ret;
680 }
681 
682 DS_VALUE * Universal_Config::GetValue(const char * ssec, const char * name) {
683  DS_CONFIG_SECTION * sec = GetSectionFromString(ssec);
684  if (sec) {
685  return GetSectionValue(sec, name);
686  }
687  return NULL;
688 }
689 
690 const char * Universal_Config::GetValueString(const char * sec, const char * name) {
691  DS_VALUE * v = GetValue(sec, name);
692  if (v && v->type == DS_TYPE_STRING) {
693  return v->pString;
694  }
695  return NULL;
696 }
697 
698 int32 Universal_Config::GetValueLong(const char * sec, const char * name) {
699  DS_VALUE * v = GetValue(sec, name);
700  if (v) {
701  if (v->type == DS_TYPE_STRING || v->type == DS_TYPE_BINARY) {
702  return atol(v->pString);
703  } else if (v->type == DS_TYPE_FLOAT) {
704  return (int32)v->lFloat;
705  } else {
706  return v->lLong;
707  }
708  }
709  return 0;
710 }
711 double Universal_Config::GetValueFloat(const char * sec, const char * name) {
712  DS_VALUE * v = GetValue(sec, name);
713  if (v) {
714  if (v->type == DS_TYPE_STRING || v->type == DS_TYPE_BINARY) {
715  return atof(v->pString);
716  } else if (v->type == DS_TYPE_FLOAT) {
717  return v->lFloat;
718  } else {
719  return v->lLong;
720  }
721  }
722  return 0;
723 }
724 
725 void Universal_Config::SetValue(const char * ssec, const char * name, DS_VALUE * val) {
726  DS_CONFIG_SECTION * sec = GetSectionFromString(ssec, true);
727  SetSectionValue(sec, name, val);
728 }
729 void Universal_Config::SetValueString(const char * ssec, const char * name, const char * str) {
730  DS_CONFIG_SECTION * sec = GetSectionFromString(ssec, true);
731  DS_VALUE val;
732  val.type = DS_TYPE_STRING;
733  val.pString = (char *)str;
734  SetSectionValue(sec, name, &val);
735 }
736 void Universal_Config::SetValueLong(const char * ssec, const char * name, int32 lval) {
737  DS_CONFIG_SECTION * sec = GetSectionFromString(ssec, true);
738  DS_VALUE val;
739  val.type = DS_TYPE_INT;
740  val.lLong = lval;
741  SetSectionValue(sec, name, &val);
742 }
743 void Universal_Config::SetValueFloat(const char * ssec, const char * name, double lval) {
744  DS_CONFIG_SECTION * sec = GetSectionFromString(ssec, true);
745  DS_VALUE val;
746  val.type = DS_TYPE_FLOAT;
747  val.lFloat = lval;
748  SetSectionValue(sec, name, &val);
749 }
void FreeString(char *buf)
You must call this on any string returned by GetTok/GetSingleTok.
Definition: GenLib.cpp:103
DSL_API void DSL_CC dsl_free(void *ptr)
Definition: dsl.cpp:345
DSL_API_CLASS int DSL_CC str_replaceA(char *Str, size_t BufSize, const char *FindStr, const char *ReplStr)
Simple string replacement.
Definition: GenLib.cpp:592
DSL_API char *DSL_CC strtrim(char *buf, const char *trim="\r\n\t ", uint8 sides=TRIM_BOTH)
Definition: GenLib.cpp:294