libwinpr-utils: improve .ini file parser

This commit is contained in:
Marc-André Moreau 2014-03-24 22:41:30 -04:00
parent 331209f02d
commit 43031d6b66
4 changed files with 319 additions and 34 deletions

3
.gitignore vendored
View File

@ -42,6 +42,9 @@ include/freerdp/version.h
*.cproject *.cproject
*.settings *.settings
nbproject/
compile_commands.json
# .rdp files # .rdp files
*.rdp *.rdp
*.RDP *.RDP

View File

@ -58,10 +58,17 @@ typedef struct _wIniFile wIniFile;
extern "C" { extern "C" {
#endif #endif
int IniFile_Parse(wIniFile* ini, const char* filename); WINPR_API int IniFile_Parse(wIniFile* ini, const char* filename);
WINPR_API int IniFile_ParseString(wIniFile* ini, const char* iniString);
wIniFile* IniFile_New(); WINPR_API char** IniFile_GetSectionNames(wIniFile* ini, int* count);
void IniFile_Free(wIniFile* ini); WINPR_API char** IniFile_GetSectionKeyNames(wIniFile* ini, const char* section, int* count);
WINPR_API char* IniFile_GetKeyValueString(wIniFile* ini, const char* section, const char* key);
WINPR_API UINT32 IniFile_GetKeyValueInt(wIniFile* ini, const char* section, const char* key);
WINPR_API wIniFile* IniFile_New();
WINPR_API void IniFile_Free(wIniFile* ini);
#ifdef __cplusplus #ifdef __cplusplus
} }

View File

@ -29,10 +29,49 @@
#include <winpr/ini.h> #include <winpr/ini.h>
void IniFile_Load_Start(wIniFile* ini) int IniFile_Load_String(wIniFile* ini, const char* iniString)
{ {
long int fileSize; long int fileSize;
ini->line = NULL;
ini->nextLine = NULL;
ini->buffer = NULL;
fileSize = strlen(iniString);
if (fileSize < 1)
return -1;
ini->buffer = (char*) malloc(fileSize + 2);
CopyMemory(ini->buffer, iniString, fileSize);
ini->buffer[fileSize] = '\n';
ini->buffer[fileSize + 1] = '\0';
ini->nextLine = strtok(ini->buffer, "\n");
return 1;
}
int IniFile_Load_File(wIniFile* ini, const char* filename)
{
long int fileSize;
if (ini->readOnly)
{
ini->fp = fopen(filename, "r");
}
else
{
ini->fp = fopen(filename, "r+");
if (!ini->fp)
ini->fp = fopen(filename, "w+");
}
if (!ini->fp)
return -1;
fseek(ini->fp, 0, SEEK_END); fseek(ini->fp, 0, SEEK_END);
fileSize = ftell(ini->fp); fileSize = ftell(ini->fp);
fseek(ini->fp, 0, SEEK_SET); fseek(ini->fp, 0, SEEK_SET);
@ -42,7 +81,7 @@ void IniFile_Load_Start(wIniFile* ini)
ini->buffer = NULL; ini->buffer = NULL;
if (fileSize < 1) if (fileSize < 1)
return; return -1;
ini->buffer = (char*) malloc(fileSize + 2); ini->buffer = (char*) malloc(fileSize + 2);
@ -50,13 +89,15 @@ void IniFile_Load_Start(wIniFile* ini)
{ {
free(ini->buffer); free(ini->buffer);
ini->buffer = NULL; ini->buffer = NULL;
return; return -1;
} }
ini->buffer[fileSize] = '\n'; ini->buffer[fileSize] = '\n';
ini->buffer[fileSize + 1] = '\0'; ini->buffer[fileSize + 1] = '\0';
ini->nextLine = strtok(ini->buffer, "\n"); ini->nextLine = strtok(ini->buffer, "\n");
return 1;
} }
void IniFile_Load_Finish(wIniFile* ini) void IniFile_Load_Finish(wIniFile* ini)
@ -150,6 +191,9 @@ int IniFile_AddSection(wIniFile* ini, const char* name)
int IniFile_AddKey(wIniFile* ini, wIniFileSection* section, const char* name, const char* value) int IniFile_AddKey(wIniFile* ini, wIniFileSection* section, const char* name, const char* value)
{ {
if (!section)
return -1;
if ((section->nKeys + 1) >= (section->cKeys)) if ((section->nKeys + 1) >= (section->cKeys))
{ {
section->cKeys *= 2; section->cKeys *= 2;
@ -172,8 +216,6 @@ int IniFile_Load(wIniFile* ini)
wIniFileKey* key = NULL; wIniFileKey* key = NULL;
wIniFileSection* section = NULL; wIniFileSection* section = NULL;
IniFile_Load_Start(ini);
while (IniFile_Load_HasNextLine(ini)) while (IniFile_Load_HasNextLine(ini))
{ {
line = IniFile_Load_GetNextLine(ini); line = IniFile_Load_GetNextLine(ini);
@ -194,8 +236,6 @@ int IniFile_Load(wIniFile* ini)
IniFile_AddSection(ini, beg); IniFile_AddSection(ini, beg);
section = ini->sections[ini->nSections - 1]; section = ini->sections[ini->nSections - 1];
printf("[%s]\n", section->name);
} }
else else
{ {
@ -214,12 +254,21 @@ int IniFile_Load(wIniFile* ini)
while (*beg && ((*beg == ' ') || (*beg == '\t'))) while (*beg && ((*beg == ' ') || (*beg == '\t')))
beg++; beg++;
if (*beg == '"')
beg++;
end = &line[ini->lineLength];
while ((end > beg) && ((end[-1] == ' ') || (end[-1] == '\t')))
end--;
if (end[-1] == '"')
end[-1] = '\0';
value = beg; value = beg;
IniFile_AddKey(ini, section, name, value); IniFile_AddKey(ini, section, name, value);
key = section->keys[section->nKeys - 1]; key = section->keys[section->nKeys - 1];
printf("%s = %s\n", key->name, key->value);
} }
} }
@ -228,36 +277,194 @@ int IniFile_Load(wIniFile* ini)
return 1; return 1;
} }
int IniFile_Open(wIniFile* ini) int IniFile_ParseString(wIniFile* ini, const char* iniString)
{ {
if (ini->readOnly) int status;
{
ini->fp = fopen(ini->filename, "r");
}
else
{
ini->fp = fopen(ini->filename, "r+");
if (!ini->fp) ini->readOnly = TRUE;
ini->fp = fopen(ini->filename, "w+"); ini->filename = NULL;
}
if (!ini->fp) status = IniFile_Load_String(ini, iniString);
return -1;
IniFile_Load(ini); if (status < 0)
return status;
return 1; status = IniFile_Load(ini);
return status;
} }
int IniFile_Parse(wIniFile* ini, const char* filename) int IniFile_Parse(wIniFile* ini, const char* filename)
{ {
int status;
ini->readOnly = TRUE; ini->readOnly = TRUE;
ini->filename = _strdup(filename); ini->filename = _strdup(filename);
IniFile_Open(ini); status = IniFile_Load_File(ini, ini->filename);
return 1; if (status < 0)
return status;
status = IniFile_Load(ini);
return status;
}
wIniFileSection* IniFile_GetSection(wIniFile* ini, const char* name)
{
int index;
wIniFileSection* section = NULL;
for (index = 0; index < ini->nSections; index++)
{
if (_stricmp(name, ini->sections[index]->name) == 0)
{
section = ini->sections[index];
break;
}
}
return section;
}
wIniFileKey* IniFile_GetKey(wIniFile* ini, wIniFileSection* section, const char* name)
{
int index;
wIniFileKey* key = NULL;
for (index = 0; index < section->nKeys; index++)
{
if (_stricmp(name, section->keys[index]->name) == 0)
{
key = section->keys[index];
break;
}
}
return key;
}
char** IniFile_GetSectionNames(wIniFile* ini, int* count)
{
char* p;
int index;
int length;
int nameLength;
char** sectionNames;
wIniFileSection* section = NULL;
length = (sizeof(char*) * ini->nSections) + sizeof(char);
for (index = 0; index < ini->nSections; index++)
{
section = ini->sections[index];
nameLength = strlen(section->name);
length += (nameLength + 1);
}
sectionNames = (char**) malloc(length);
p = (char*) &((BYTE*) sectionNames)[sizeof(char*) * ini->nSections];
for (index = 0; index < ini->nSections; index++)
{
sectionNames[index] = p;
section = ini->sections[index];
nameLength = strlen(section->name);
CopyMemory(p, section->name, nameLength + 1);
p += (nameLength + 1);
}
*p = '\0';
*count = ini->nSections;
return sectionNames;
}
char** IniFile_GetSectionKeyNames(wIniFile* ini, const char* section, int* count)
{
char* p;
int index;
int length;
int nameLength;
char** keyNames;
wIniFileKey* pKey = NULL;
wIniFileSection* pSection = NULL;
pSection = IniFile_GetSection(ini, section);
if (!pSection)
return NULL;
length = (sizeof(char*) * pSection->nKeys) + sizeof(char);
for (index = 0; index < pSection->nKeys; index++)
{
pKey = pSection->keys[index];
nameLength = strlen(pKey->name);
length += (nameLength + 1);
}
keyNames = (char**) malloc(length);
p = (char*) &((BYTE*) keyNames)[sizeof(char*) * pSection->nKeys];
for (index = 0; index < pSection->nKeys; index++)
{
keyNames[index] = p;
pKey = pSection->keys[index];
nameLength = strlen(pKey->name);
CopyMemory(p, pKey->name, nameLength + 1);
p += (nameLength + 1);
}
*p = '\0';
*count = pSection->nKeys;
return keyNames;
}
char* IniFile_GetKeyValueString(wIniFile* ini, const char* section, const char* key)
{
char* value = NULL;
wIniFileKey* pKey = NULL;
wIniFileSection* pSection = NULL;
pSection = IniFile_GetSection(ini, section);
if (!pSection)
return NULL;
pKey = IniFile_GetKey(ini, pSection, key);
if (!pKey)
return NULL;
value = pKey->value;
return value;
}
UINT32 IniFile_GetKeyValueInt(wIniFile* ini, const char* section, const char* key)
{
UINT32 value = 0;
wIniFileKey* pKey = NULL;
wIniFileSection* pSection = NULL;
pSection = IniFile_GetSection(ini, section);
if (!pSection)
return 0;
pKey = IniFile_GetKey(ini, pSection, key);
if (!pKey)
return 0;
value = atoi(pKey->value);
return value;
} }
wIniFile* IniFile_New() wIniFile* IniFile_New()

View File

@ -1,4 +1,6 @@
#include <winpr/crt.h>
#include <winpr/ini.h> #include <winpr/ini.h>
const char TEST_INI_FILE[] = const char TEST_INI_FILE[] =
@ -16,11 +18,77 @@ const char TEST_INI_FILE[] =
int TestIni(int argc, char* argv[]) int TestIni(int argc, char* argv[])
{ {
int i, j;
int nKeys;
int nSections;
char* sValue;
UINT32 iValue;
wIniFile* ini; wIniFile* ini;
char** keyNames;
char** sectionNames;
ini = IniFile_New(); ini = IniFile_New();
IniFile_Parse(ini, "/tmp/sample.ini"); IniFile_ParseString(ini, TEST_INI_FILE);
sectionNames = IniFile_GetSectionNames(ini, &nSections);
for (i = 0; i < nSections; i++)
{
keyNames = IniFile_GetSectionKeyNames(ini, sectionNames[i], &nKeys);
printf("[%s]\n", sectionNames[i]);
for (j = 0; j < nKeys; j++)
{
sValue = IniFile_GetKeyValueString(ini, sectionNames[i], keyNames[j]);
printf("%s = %s\n", keyNames[j], sValue);
}
free(keyNames);
}
free(sectionNames);
iValue = IniFile_GetKeyValueInt(ini, "first_section", "one");
if (iValue != 1)
{
printf("IniFile_GetKeyValueInt failure\n");
return -1;
}
iValue = IniFile_GetKeyValueInt(ini, "first_section", "five");
if (iValue != 5)
{
printf("IniFile_GetKeyValueInt failure\n");
return -1;
}
sValue = IniFile_GetKeyValueString(ini, "first_section", "animal");
if (strcmp(sValue, "BIRD") != 0)
{
printf("IniFile_GetKeyValueString failure\n");
return -1;
}
sValue = IniFile_GetKeyValueString(ini, "second_section", "path");
if (strcmp(sValue, "/usr/local/bin") != 0)
{
printf("IniFile_GetKeyValueString failure\n");
return -1;
}
sValue = IniFile_GetKeyValueString(ini, "second_section", "URL");
if (strcmp(sValue, "http://www.example.com/~username") != 0)
{
printf("IniFile_GetKeyValueString failure\n");
return -1;
}
IniFile_Free(ini); IniFile_Free(ini);