11 #include <drift/dslcore.h>
12 #include <drift/config.h>
13 #include <drift/GenLib.h>
16 Universal_Config::Universal_Config() {
22 Universal_Config::~Universal_Config() {
31 if (ValScan->value.type == DS_TYPE_STRING || ValScan->value.type == DS_TYPE_BINARY) {
35 ValScan = ValScan->Next;
40 Scan->sections = NULL;
53 void Universal_Config::FreeConfig() {
68 if (!stricmp(Scan->name,name)) {
return Scan; }
76 if (!sec) {
return NULL; }
80 if (!stricmp(Scan->name,name)) {
89 if (!sec) {
return NULL; }
90 DS_VALUE * eval = GetSectionValue(sec,name);
93 if (eval->type == DS_TYPE_STRING || eval->type == DS_TYPE_BINARY) {
97 if (eval->type == DS_TYPE_STRING) {
98 eval->pString = dsl_strdup(val->pString);
101 printf(
"Universal_Config() -> You must never pass a DS_VALUE to SetSectionValue that was returned from GetSectionValue\n");
103 MessageBoxA(0,
"Universal_Config() -> You must never pass a DS_VALUE to SetSectionValue that was returned from GetSectionValue",
"Error", 0);
113 Scan->Next->Next=NULL;
114 Scan->Next->Prev = Scan;
116 strcpy(Scan->name,name);
122 strcpy(Scan->name,name);
125 memcpy(&Scan->value,val,
sizeof(
DS_VALUE));
126 if (Scan->value.type == DS_TYPE_STRING) {
127 Scan->value.pString = dsl_strdup(val->pString);
135 bool Universal_Config::IsLong(
const char * buf) {
136 if (buf[0] == 0) {
return false; }
143 if (l == 0 && strcmp(buf,
"0")) {
147 if (l == 2147483647 && stricmp(buf,
"2147483647")) {
150 if (l == -2147483647 && stricmp(buf,
"-2147483647")) {
155 for(
int i=0; buf[i] != 0; i++) {
156 if (buf[i] ==
'-' && i == 0 && buf[1] != 0) {
159 if(buf[i] < 48 || buf[i] > 57) {
166 bool Universal_Config::IsFloat(
const char * buf) {
167 if (buf[0] == 0) {
return false; }
169 double l = atof(buf);
170 if (l == 0.0 && strcmp(buf,
"0.0") && strcmp(buf,
"0.00")) {
174 if (l == HUGE_VAL || l == -HUGE_VAL) {
179 for(
int i=0; buf[i] != 0; i++) {
180 if (buf[i] ==
'-' && i == 0 && buf[1] != 0) {
185 if (periodCnt == 1) {
continue; }
188 if(buf[i] < 48 || buf[i] > 57) {
193 return (periodCnt == 1) ?
true:
false;
204 lSection->Next = ret;
205 ret->Prev = lSection;
212 if (parent->sections) {
214 while (Scan->Next != NULL) {
218 Scan->Next->Prev = Scan;
220 parent->sections = ret;
224 ret->Parent = parent;
225 strcpy(ret->name,name);
232 scanStack.pop_back();
237 scanStack.push_back(section);
240 bool Universal_Config::LoadConfig(FILE * fp,
const char * fn,
DS_CONFIG_SECTION * Scan) {
241 if (!fp) {
return false; }
247 bool long_comment=
false;
249 memset(buf, 0,
sizeof(buf));
251 while (fgets(buf,
sizeof(buf),fp)) {
254 if (strlen(buf) < 2) {
260 while (strstr(buf,
" ")) {
266 if (stristr(buf,
"#include")) {
267 char * p = stristr(buf,
"#include");
271 char *q = strchr(p,
'\"');
274 if (LoadConfig(p, Scan)) {
277 printf(
"ERROR: Error loading #included file '%s'\n", p);
281 printf(
"ERROR: Syntax is #include \"filename\"\n");
285 printf(
"ERROR: Syntax is #include \"filename\"\n");
291 if (buf[0] ==
'#' || !strncmp(buf,
"//",2)) {
295 if (!strncmp(buf,
"/*",2)) {
301 if (!strcmp(buf,
"*/")) {
302 long_comment =
false;
307 char *p = (
char *)&buf+(strlen(buf) - 2);
308 if (!strcmp(p,
" {")) {
311 Scan = FindOrAddSection(Scan,buf);
315 if (!strcmp(buf,
"};")) {
319 printf(
"ERROR: You have one too many }; near line %d of %s\n", line, fn);
326 unsigned long num = tok->NumTok();
331 char * name = tok->GetSingleTok(1);
332 char * value = tok->GetTok(2,num);
333 if (IsFloat(value)) {
334 sVal->type = DS_TYPE_FLOAT;
335 sVal->lFloat = atof(value);
336 }
else if (IsLong(value)) {
337 sVal->type = DS_TYPE_INT;
338 sVal->lLong = atol(value);
340 sVal->type = DS_TYPE_STRING;
341 sVal->pString = dsl_strdup(value);
344 SetSectionValue(Scan, name, sVal);
346 if (sVal->type == DS_TYPE_STRING) {
357 printf(
"Unrecognized line at %s:%d -> %s\n",fn,line,buf);
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);
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'; }
379 sprintf(buf,
"%s%s {\n",pref,sec->name);
380 fwrite(buf,strlen(buf),1,fp);
384 WriteSection(fp,Scan,level+1);
390 switch(val->value.type) {
392 sprintf(buf,
"\t%s%s %d\n",pref,val->name,val->value.lLong);
393 fwrite(buf,strlen(buf),1,fp);
396 sprintf(buf,
"\t%s%s %f\n", pref, val->name, val->value.lFloat);
397 fwrite(buf, strlen(buf), 1, fp);
400 sprintf(buf,
"\t%s%s %s\n",pref,val->name,val->value.pString);
401 fwrite(buf,strlen(buf),1,fp);
409 sprintf(buf,
"%s};\n",pref);
410 fwrite(buf,strlen(buf),1,fp);
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; }
420 WriteSection(fp,Scan,0);
436 for (
int i=0; i < level; i++) {
440 printf(
"%sSection: %s\n",buf,Scan->name);
444 switch(ValScan->value.type) {
446 printf(
"%s[%s] = %d\n",buf,ValScan->name,ValScan->value.lLong);
449 printf(
"%s[%s] = %f\n", buf, ValScan->name, ValScan->value.lFloat);
452 printf(
"%s[%s] = %s\n",buf,ValScan->name,ValScan->value.pString);
455 printf(
"%s[%s] = Binary Data @ %p\n",buf,ValScan->name,ValScan->value.pBinary);
458 ValScan = ValScan->Next;
463 PrintSection(Scan2,level+1);
468 void Universal_Config::PrintConfigTree() {
471 PrintSection(Scan,0);
478 unsigned long magic1;
479 unsigned long magic2;
480 unsigned char version;
485 UC_ENTRY_TYPE_SECTION,
491 bool Universal_Config::LoadBinaryConfig(
const char * filename) {
492 FILE * fp = fopen(filename,
"rb");
493 if (!fp) {
return false; }
494 bool ret = LoadBinaryConfig(fp);
499 bool Universal_Config::LoadBinaryConfig(FILE * fp) {
500 if (!fp) {
return false; }
502 memset(&head, 0,
sizeof(head));
503 if (fread(&head,
sizeof(head), 1, fp) != 1) {
504 printf(
"Error reading file header!\n");
507 if (head.magic1 != 0x54465244 || head.magic2 != 0x464E4F43) {
508 printf(
"Invalid magic in Dynamic Config file!\n");
512 if (head.version > 0) {
513 printf(
"Unknown version in Dynamic Config file!\n");
523 while (fread(&type, 1, 1, fp) == 1 && !berror) {
524 memset(buf, 0,
sizeof(buf));
526 case UC_ENTRY_TYPE_SECTION:
527 if (fread(&type, 1, 1, fp) != 1) {
530 if (fread(buf, type, 1, fp) != 1) {
534 sec = FindOrAddSection(sec, buf);
537 case UC_ENTRY_TYPE_UP:
541 case UC_ENTRY_TYPE_VALUE:
542 fread(&type, 1, 1, fp);
543 fread(buf, type, 1, fp);
545 name = dsl_strdup(buf);
546 memset(buf, 0,
sizeof(buf));
547 fread(&type, 1, 1, fp);
548 val.type = (DS_VALUE_TYPE)type;
551 fread(&val.lLong,4,1,fp);
555 fread(&val.lFloat,
sizeof(
double),1,fp);
560 fread(&len,
sizeof(len),1,fp);
566 this->SetSectionValue(sec, name, &val);
569 case UC_ENTRY_TYPE_EOF:
570 fseek(fp, 0, SEEK_END);
573 printf(
"ERROR: Unknown entry type at offset 0x%08X\n", (
unsigned int)ftell(fp));
585 buf[0] = UC_ENTRY_TYPE_SECTION;
587 buf[0] = (char)strlen(sec->name);
589 fwrite(sec->name,buf[0],1,fp);
593 WriteBinarySection(fp,Scan);
599 buf[0] = UC_ENTRY_TYPE_VALUE;
600 fwrite(&buf[0],1,1,fp);
602 buf[0] = (char)strlen(val->name);
603 fwrite(&buf[0],1,1,fp);
604 fwrite(val->name,buf[0],1,fp);
606 buf[0] = val->value.type;
607 fwrite(&buf[0],1,1,fp);
609 switch(val->value.type) {
611 fwrite(&val->value.lLong,4,1,fp);
614 fwrite(&val->value.lFloat,
sizeof(
double),1,fp);
618 len = (
unsigned short)strlen(val->value.pString);
619 fwrite(&len,
sizeof(len),1,fp);
620 fwrite(val->value.pString,len,1,fp);
628 buf[0] = UC_ENTRY_TYPE_UP;
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; }
637 head.magic1 = 0x54465244;
638 head.magic2 = 0x464E4F43;
640 fwrite(&head,
sizeof(head), 1, fp);
644 WriteBinarySection(fp,Scan);
652 unsigned type = UC_ENTRY_TYPE_EOF;
653 fwrite(&type,1,1,fp);
665 DS_CONFIG_SECTION * Universal_Config::GetSectionFromString(
const char * sec,
bool create) {
666 if (*sec ==
'/') { sec++; }
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);
676 if (!ret) {
return NULL; }
682 DS_VALUE * Universal_Config::GetValue(
const char * ssec,
const char * name) {
685 return GetSectionValue(sec, name);
690 const char * Universal_Config::GetValueString(
const char * sec,
const char * name) {
692 if (v && v->type == DS_TYPE_STRING) {
698 int32 Universal_Config::GetValueLong(
const char * sec,
const char * name) {
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;
711 double Universal_Config::GetValueFloat(
const char * sec,
const char * name) {
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) {
725 void Universal_Config::SetValue(
const char * ssec,
const char * name,
DS_VALUE * val) {
727 SetSectionValue(sec, name, val);
729 void Universal_Config::SetValueString(
const char * ssec,
const char * name,
const char * str) {
732 val.type = DS_TYPE_STRING;
733 val.pString = (
char *)str;
734 SetSectionValue(sec, name, &val);
736 void Universal_Config::SetValueLong(
const char * ssec,
const char * name, int32 lval) {
739 val.type = DS_TYPE_INT;
741 SetSectionValue(sec, name, &val);
743 void Universal_Config::SetValueFloat(
const char * ssec,
const char * name,
double lval) {
746 val.type = DS_TYPE_FLOAT;
748 SetSectionValue(sec, name, &val);
void FreeString(char *buf)
You must call this on any string returned by GetTok/GetSingleTok.
DSL_API void DSL_CC dsl_free(void *ptr)
DSL_API_CLASS int DSL_CC str_replaceA(char *Str, size_t BufSize, const char *FindStr, const char *ReplStr)
Simple string replacement.
DSL_API char *DSL_CC strtrim(char *buf, const char *trim="\r\n\t ", uint8 sides=TRIM_BOTH)