libwinpr-utils: improve .ini file parser
This commit is contained in:
parent
331209f02d
commit
43031d6b66
3
.gitignore
vendored
3
.gitignore
vendored
@ -42,6 +42,9 @@ include/freerdp/version.h
|
|||||||
*.cproject
|
*.cproject
|
||||||
*.settings
|
*.settings
|
||||||
|
|
||||||
|
nbproject/
|
||||||
|
compile_commands.json
|
||||||
|
|
||||||
# .rdp files
|
# .rdp files
|
||||||
*.rdp
|
*.rdp
|
||||||
*.RDP
|
*.RDP
|
||||||
|
@ -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
|
||||||
}
|
}
|
||||||
|
@ -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()
|
||||||
|
@ -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);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user