Inconsistent string handling with empty and quoted values
Closed this issue · 1 comments
laenion commented
Handling empty values is currently highly inconsistent, if not completely broken:
Assume the following contents of test.ini
[test]
test=
test2=""
test3="string"
test4=string
test5=" string "
test6= string
and the following C application (simpified - see https://gist.github.com/laenion/874e4794af1c7f004ccae5157ea0c185 for a version with error handling):
#include <libeconf.h>
#include <stdio.h>
int main(void) {
char *val;
// Create new econf_file
econf_file *kf_freshini;
econf_newIniFile(&kf_freshini);
econf_setStringValue(kf_freshini, "test", "test", NULL);
econf_getStringValue(kf_freshini, "test", "test", &val);
printf("Reading 'test' from freshly created object: %s\n", val);
// Result: empty string
// Read empty value from INI
econf_file *kf_fromfile;
econf_readFile(&kf_fromfile, "test.ini", "=", "#");
econf_getStringValue(kf_fromfile, "test", "test", &val);
printf("Reading empty 'test' from file: %s\n", val);
// Result: real NULL value, which glibc outputs as "(null)"
// Test what happens with quoted and unquoted strings
econf_getStringValue(kf_fromfile, "test", "test2", &val);
printf("Reading 'test2' from file: %s\n", val);
econf_getStringValue(kf_fromfile, "test", "test3", &val);
printf("Reading 'test3' from file: %s\n", val);
econf_getStringValue(kf_fromfile, "test", "test4", &val);
printf("Reading 'test4' from file: %s\n", val);
econf_getStringValue(kf_fromfile, "test", "test5", &val);
printf("Reading 'test5' from file: %s\n", val);
econf_getStringValue(kf_fromfile, "test", "test6", &val);
printf("Reading 'test6' from file: %s\n", val);
// Result: Horrible things are happening here:
// - The empty value is detected as a single quotation mark
// - Everything is stored without quotation marks now. In case of " test "
// when writing the value out to a file in the next step the spaces are
// lost due to that when reading the file again.
// Rewrite file to disk
econf_writeFile(kf_fromfile, ".", "out.ini");
// Result: The value is stored as a literal "(null)"
// Merge the two econf_files
econf_file *kf_merged;
econf_mergeFiles(&kf_merged, kf_freshini, kf_fromfile);
// Result: Segmentation fault due to the NULL value
}
From what I understand the following should be happening:
- If no value is assigned, then the value should always be
NULL
; the behavior ofeconf_readFile
is thus correct. - Quoted strings must be considered as literals when reading, minus the quotes.
- If a string to be written out is empty or begins with a space it has to be written out in quotes.
- A
NULL
value mustn't be converted to an empty string.
Or, as a general rule of thumb: When reading a file, writing it back and reading it again the values should still be the same ones...
schubi2 commented
Thanks for the report. I have (hopefully) fixed it with version 0.4.2.