diff --git a/src/xpdev/ini_file.c b/src/xpdev/ini_file.c index bd9ae304c27283a8f6ff893ab233defaa07bf54c..b84aa4466158c5f8919b47289b132969694cf733 100644 --- a/src/xpdev/ini_file.c +++ b/src/xpdev/ini_file.c @@ -44,6 +44,8 @@ #define INI_MAX_LINE_LEN 256 /* Maximum length of entire line, includes '\0' */ +#define NEW_SECTION ((char*)~0) + /****************************************************************************/ /* Truncates white-space chars off end of 'str' */ /****************************************************************************/ @@ -56,10 +58,27 @@ static void truncsp(char *str) str[c]=0; } +static char* section_name(char* p) +{ + char* tp; + + SKIP_WHITESPACE(p); + if(*p!='[') + return(NULL); + p++; + SKIP_WHITESPACE(p); + tp=strchr(p,']'); + if(tp==NULL) + return(NULL); + *tp=0; + truncsp(p); + + return(p); +} + static BOOL find_section(FILE* fp, const char* section) { char* p; - char* tp; char str[INI_MAX_LINE_LEN]; rewind(fp); @@ -67,25 +86,55 @@ static BOOL find_section(FILE* fp, const char* section) while(!feof(fp)) { if(fgets(str,sizeof(str),fp)==NULL) break; - p=str; - while(*p && *p<=' ') p++; - if(*p!='[') + if((p=section_name(str))==NULL) continue; - p++; - tp=strchr(p,']'); - if(tp==NULL) - continue; - *tp=0; if(stricmp(p,section)==0) return(TRUE); } return(FALSE); } +static size_t find_section_index(str_list_t list, const char* section) +{ + char* p; + char str[INI_MAX_VALUE_LEN]; + size_t i; + + for(i=0; list[i]!=NULL; i++) { + SAFECOPY(str,list[i]); + if((p=section_name(str))!=NULL && stricmp(p,section)==0) + return(i+1); + } + + return(i); +} + +static char* key_name(char* p, char** vp) +{ + /* Parse value name */ + SKIP_WHITESPACE(p); + if(*p==';') + return(NULL); + if(*p=='[') + return(NEW_SECTION); + *vp=strchr(p,'='); + if(*vp==NULL) + return(NULL); + *(*vp)=0; + truncsp(p); + + /* Parse value */ + (*vp)++; + SKIP_WHITESPACE(*vp); + truncsp(*vp); + + return(p); +} + static char* get_value(FILE* fp, const char* section, const char* key, char* value) { char* p; - char* tp; + char* vp; char str[INI_MAX_LINE_LEN]; if(fp==NULL) @@ -97,30 +146,151 @@ static char* get_value(FILE* fp, const char* section, const char* key, char* val while(!feof(fp)) { if(fgets(str,sizeof(str),fp)==NULL) break; - p=str; - while(*p && *p<=' ') p++; - if(*p==';') + if((p=key_name(str,&vp))==NULL) continue; - if(*p=='[') + if(p==NEW_SECTION) break; - tp=strchr(p,'='); - if(tp==NULL) - continue; - *tp=0; - truncsp(p); if(stricmp(p,key)!=0) continue; /* key found */ - p=tp+1; - while(*p && *p<=' ') p++; - truncsp(p); - sprintf(value,"%.*s",INI_MAX_VALUE_LEN-1,p); + sprintf(value,"%.*s",INI_MAX_VALUE_LEN-1,vp); return(value); } return(NULL); } +static size_t find_value_index(str_list_t list, const char* section, const char* key) +{ + char str[INI_MAX_LINE_LEN]; + char* p; + char* vp; + size_t i; + + for(i=find_section_index(list, section); list[i]!=NULL; i++) { + SAFECOPY(str, list[i]); + if((p=key_name(str,&vp))==NULL) + continue; + if(p==NEW_SECTION) + break; + if(stricmp(p,key)==0) + return(i); + } + + return(i); +} + +size_t iniAddSection(str_list_t* list, const char* section) +{ + char str[INI_MAX_LINE_LEN]; + size_t i; + + i=find_section_index(*list, section); + if((*list)[i]==NULL) { + sprintf(str,"[%s]",section); + strListAppend(list, str, i); + } + + return(i); +} + +char* iniSetString(str_list_t* list, const char* section, const char* key, const char* value + ,ini_style_t* style) +{ + char str[INI_MAX_LINE_LEN]; + size_t i; + + iniAddSection(list, section); + + if(key==NULL) + return(NULL); + if(style->key_prefix==NULL) + style->key_prefix=""; + if(style->value_separator==NULL) + style->value_separator="="; + sprintf(str, "%s%-*s%s%s", style->key_prefix, style->key_len, key, style->value_separator, value); + i=find_value_index(*list, section, key); + if((*list)[i]==NULL) + return strListInsert(list, str, i); + + return strListReplace(*list, i, str); +} + +char* iniSetInteger(str_list_t* list, const char* section, const char* key, long value + ,ini_style_t* style) +{ + char str[INI_MAX_VALUE_LEN]; + + sprintf(str,"%ld",value); + return iniSetString(list, section, key, str, style); +} + +char* iniSetShortInt(str_list_t* list, const char* section, const char* key, ushort value + ,ini_style_t* style) +{ + char str[INI_MAX_VALUE_LEN]; + + sprintf(str,"%hu",value); + return iniSetString(list, section, key, str, style); +} + +char* iniSetHexInt(str_list_t* list, const char* section, const char* key, ulong value + ,ini_style_t* style) +{ + char str[INI_MAX_VALUE_LEN]; + + sprintf(str,"0x%lx",value); + return iniSetString(list, section, key, str, style); +} + +char* iniSetFloat(str_list_t* list, const char* section, const char* key, double value + ,ini_style_t* style) +{ + char str[INI_MAX_VALUE_LEN]; + + sprintf(str,"%g",value); + return iniSetString(list, section, key, str, style); +} + +char* iniSetIpAddress(str_list_t* list, const char* section, const char* key, ulong value + ,ini_style_t* style) +{ + struct in_addr in_addr; + in_addr.s_addr=value; + return iniSetString(list, section, key, inet_ntoa(in_addr), style); +} + +char* iniSetBool(str_list_t* list, const char* section, const char* key, BOOL value + ,ini_style_t* style) +{ + return iniSetString(list, section, key, value ? "true":"false", style); +} + +char* iniSetBitField(str_list_t* list, const char* section, const char* key, ulong value + ,ini_bitdesc_t* bitdesc, ini_style_t* style) +{ + char str[INI_MAX_VALUE_LEN]; + int i; + + if(style->bit_separator==NULL) + style->bit_separator="|"; + str[0]=0; + for(i=0;bitdesc[i].name;i++) { + if((value&bitdesc[i].bit)==0) + continue; + if(str[0]) + strcat(str,style->bit_separator); + strcat(str,bitdesc[i].name); + value&=~bitdesc[i].bit; + } + if(value) { /* left over bits? */ + if(str[0]) + strcat(str,style->bit_separator); + sprintf(str+strlen(str), "0x%lX", value); + } + return iniSetString(list, section, key, str, style); +} + char* iniGetString(FILE* fp, const char* section, const char* key, const char* deflt, char* value) { if(get_value(fp,section,key,value)==NULL || *value==0 /* blank */) { @@ -188,7 +358,6 @@ void* iniFreeNamedStringList(named_string_t** list) str_list_t iniGetSectionList(FILE* fp, const char* prefix) { char* p; - char* tp; char str[INI_MAX_LINE_LEN]; ulong items=0; str_list_t lp; @@ -204,15 +373,8 @@ str_list_t iniGetSectionList(FILE* fp, const char* prefix) while(!feof(fp)) { if(fgets(str,sizeof(str),fp)==NULL) break; - p=str; - while(*p && *p<=' ') p++; - if(*p!='[') + if((p=section_name(str))==NULL) continue; - p++; - tp=strchr(p,']'); - if(tp==NULL) - continue; - *tp=0; if(prefix!=NULL) if(strnicmp(p,prefix,strlen(prefix))!=0) continue; @@ -226,7 +388,7 @@ str_list_t iniGetSectionList(FILE* fp, const char* prefix) str_list_t iniGetKeyList(FILE* fp, const char* section) { char* p; - char* tp; + char* vp; char str[INI_MAX_LINE_LEN]; ulong items=0; str_list_t lp; @@ -245,17 +407,10 @@ str_list_t iniGetKeyList(FILE* fp, const char* section) while(!feof(fp)) { if(fgets(str,sizeof(str),fp)==NULL) break; - p=str; - while(*p && *p<=' ') p++; - if(*p==';') + if((p=key_name(str,&vp))==NULL) continue; - if(*p=='[') + if(p==NEW_SECTION) break; - tp=strchr(p,'='); - if(tp==NULL) - continue; - *tp=0; - truncsp(p); if(strListAppend(&lp,p,items++)==NULL) break; } @@ -266,10 +421,8 @@ str_list_t iniGetKeyList(FILE* fp, const char* section) named_string_t** iniGetNamedStringList(FILE* fp, const char* section) { - char* p; char* name; char* value; - char* tp; char str[INI_MAX_LINE_LEN]; ulong items=0; named_string_t** lp; @@ -291,22 +444,10 @@ iniGetNamedStringList(FILE* fp, const char* section) while(!feof(fp)) { if(fgets(str,sizeof(str),fp)==NULL) break; - p=str; - while(*p && *p<=' ') p++; - if(*p==';') + if((name=key_name(str,&value))==NULL) continue; - if(*p=='[') + if(name==NEW_SECTION) break; - tp=strchr(p,'='); - if(tp==NULL) - continue; - *tp=0; - truncsp(p); - name=p; - p=tp+1; - while(*p && *p<=' ') p++; - truncsp(p); - value=p; if((np=realloc(lp,sizeof(named_string_t*)*(items+2)))==NULL) break; lp=np; @@ -429,7 +570,7 @@ ulong iniGetBitField(FILE* fp, const char* section, const char* key, break; p=tp+1; - while(*p && *p<=' ') p++; + SKIP_WHITESPACE(p); } return(v); @@ -442,7 +583,7 @@ str_list_t iniReadFile(FILE* fp) rewind(fp); - list = strListReadFile(fp, NULL, INI_MAX_VALUE_LEN, TRUE /* pad */); + list = strListReadFile(fp, NULL, INI_MAX_LINE_LEN, FALSE /* pad */); if(list!=NULL) { /* truncate the white-space off end of strings */ for(i=0; list[i]!=NULL; i++) diff --git a/src/xpdev/ini_file.h b/src/xpdev/ini_file.h index fcc452e69dca840b5af4cc4f4de5d54a00bc41ff..e1d6e329b6a581385ba161c9063f94a2cf6c8e0f 100644 --- a/src/xpdev/ini_file.h +++ b/src/xpdev/ini_file.h @@ -48,6 +48,13 @@ typedef struct { const char* name; } ini_bitdesc_t; +typedef struct { + int key_len; + const char* key_prefix; + const char* value_separator; + const char* bit_separator; +} ini_style_t; + #if defined(__cplusplus) extern "C" { #endif @@ -90,6 +97,24 @@ void* iniFreeNamedStringList(named_string_t** list); str_list_t iniReadFile(FILE* fp); BOOL iniWriteFile(FILE* fp, const str_list_t list); +/* StringList functions */ +size_t iniAddSection(str_list_t* list, const char* section); +char* iniSetString(str_list_t* list, const char* section, const char* key, const char* value + ,ini_style_t*); +char* iniSetInteger(str_list_t* list, const char* section, const char* key, long value + ,ini_style_t*); +char* iniSetShortInt(str_list_t* list, const char* section, const char* key, ushort value + ,ini_style_t*); +char* iniSetHexInt(str_list_t* list, const char* section, const char* key, ulong value + ,ini_style_t*); +char* iniSetFloat(str_list_t* list, const char* section, const char* key, double value + ,ini_style_t*); +char* iniSetIpAddress(str_list_t* list, const char* section, const char* key, ulong value + ,ini_style_t*); +char* iniSetBool(str_list_t* list, const char* section, const char* key, BOOL value + ,ini_style_t*); +char* iniSetBitField(str_list_t* list, const char* section, const char* key, ulong value + ,ini_bitdesc_t*, ini_style_t*); #if defined(__cplusplus) }