aboutsummaryrefslogtreecommitdiff
path: root/src/ini.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/ini.c')
-rw-r--r--src/ini.c164
1 files changed, 154 insertions, 10 deletions
diff --git a/src/ini.c b/src/ini.c
index 6ce54ac..bddfdcd 100644
--- a/src/ini.c
+++ b/src/ini.c
@@ -122,7 +122,27 @@ int ini_getval(struct INIFILE *ini, char *section_name, char *key, int type, uni
result->as_char_p = NULL;
return -1;
}
+
+ char *render = tpl_render(data->value);
+ if (render) {
+ guard_free(data->value);
+ data->value = render;
+ }
+ lstrip(data->value);
+
switch (type) {
+ case INIVAL_TYPE_CHAR:
+ result->as_char = (char) strtol(data->value, NULL, 10);
+ break;
+ case INIVAL_TYPE_UCHAR:
+ result->as_uchar = (unsigned char) strtoul(data->value, NULL, 10);
+ break;
+ case INIVAL_TYPE_SHORT:
+ result->as_short = (short) strtol(data->value, NULL, 10);
+ break;
+ case INIVAL_TYPE_USHORT:
+ result->as_ushort = (unsigned short) strtoul(data->value, NULL, 10);
+ break;
case INIVAL_TYPE_INT:
result->as_int = (int) strtol(data->value, NULL, 10);
break;
@@ -148,17 +168,26 @@ int ini_getval(struct INIFILE *ini, char *section_name, char *key, int type, uni
result->as_float = (float) strtod(data->value, NULL);
break;
case INIVAL_TYPE_STR:
- result->as_char_p = lstrip(data->value);
+ result->as_char_p = strdup(data->value);
+ if (!result->as_char_p) {
+ return -1;
+ }
+ lstrip(result->as_char_p);
break;
case INIVAL_TYPE_STR_ARRAY:
strcpy(tbufp, data->value);
- *data->value = '\0';
+ char *value = NULL;
+ size_t lines = num_chars(tbufp, '\n');
+ value = calloc(strlen(tbufp) + lines + 1, sizeof(*value));
+ if (!value) {
+ return -1;
+ }
while ((token = strsep(&tbufp, "\n")) != NULL) {
lstrip(token);
- strcat(data->value, token);
- strcat(data->value, "\n");
+ strcat(value, token);
+ strcat(value, "\n");
}
- result->as_char_p = data->value;
+ result->as_char_p = value;
break;
case INIVAL_TYPE_BOOL:
result->as_bool = false;
@@ -175,6 +204,107 @@ int ini_getval(struct INIFILE *ini, char *section_name, char *key, int type, uni
return 0;
}
+#define getval_returns(t) return result.t
+#define getval_setup(t) \
+ union INIVal result; \
+ int state_local = 0; \
+ state_local = ini_getval(ini, section_name, key, t, &result); \
+ if (state != NULL) { \
+ *state = state_local; \
+ }
+
+int ini_getval_int(struct INIFILE *ini, char *section_name, char *key, int *state) {
+ getval_setup(INIVAL_TYPE_INT)
+ getval_returns(as_int);
+}
+
+unsigned int ini_getval_uint(struct INIFILE *ini, char *section_name, char *key, int *state) {
+ getval_setup(INIVAL_TYPE_UINT)
+ getval_returns(as_uint);
+}
+
+long ini_getval_long(struct INIFILE *ini, char *section_name, char *key, int *state) {
+ getval_setup(INIVAL_TYPE_LONG)
+ getval_returns(as_long);
+}
+
+unsigned long ini_getval_ulong(struct INIFILE *ini, char *section_name, char *key, int *state) {
+ getval_setup(INIVAL_TYPE_ULONG)
+ getval_returns(as_ulong);
+}
+
+long long ini_getval_llong(struct INIFILE *ini, char *section_name, char *key, int *state) {
+ getval_setup(INIVAL_TYPE_LLONG)
+ getval_returns(as_llong);
+}
+
+unsigned long long ini_getval_ullong(struct INIFILE *ini, char *section_name, char *key, int *state) {
+ getval_setup(INIVAL_TYPE_ULLONG)
+ getval_returns(as_ullong);
+}
+
+float ini_getval_float(struct INIFILE *ini, char *section_name, char *key, int *state) {
+ getval_setup(INIVAL_TYPE_FLOAT)
+ getval_returns(as_float);
+}
+
+double ini_getval_double(struct INIFILE *ini, char *section_name, char *key, int *state) {
+ getval_setup(INIVAL_TYPE_DOUBLE)
+ getval_returns(as_double);
+}
+
+bool ini_getval_bool(struct INIFILE *ini, char *section_name, char *key, int *state) {
+ getval_setup(INIVAL_TYPE_BOOL)
+ getval_returns(as_bool);
+}
+
+short ini_getval_short(struct INIFILE *ini, char *section_name, char *key, int *state) {
+ getval_setup(INIVAL_TYPE_SHORT)
+ getval_returns(as_short);
+}
+
+unsigned short ini_getval_ushort(struct INIFILE *ini, char *section_name, char *key, int *state) {
+ getval_setup(INIVAL_TYPE_USHORT)
+ getval_returns(as_ushort);
+}
+
+char ini_getval_char(struct INIFILE *ini, char *section_name, char *key, int *state) {
+ getval_setup(INIVAL_TYPE_CHAR)
+ getval_returns(as_char);
+}
+
+unsigned char ini_getval_uchar(struct INIFILE *ini, char *section_name, char *key, int *state) {
+ getval_setup(INIVAL_TYPE_UCHAR)
+ getval_returns(as_uchar);
+}
+
+char *ini_getval_char_p(struct INIFILE *ini, char *section_name, char *key, int *state) {
+ getval_setup(INIVAL_TYPE_STR)
+ getval_returns(as_char_p);
+}
+
+char *ini_getval_str(struct INIFILE *ini, char *section_name, char *key, int *state) {
+ return ini_getval_char_p(ini, section_name, key, state);
+}
+
+char **ini_getval_char_array_p(struct INIFILE *ini, char *section_name, char *key, int *state) {
+ getval_setup(INIVAL_TYPE_STR_ARRAY)
+ getval_returns(as_char_array_p);
+}
+
+char **ini_getval_str_array(struct INIFILE *ini, char *section_name, char *key, int *state) {
+ return ini_getval_char_array_p(ini, section_name, key, state);
+}
+
+struct StrList *ini_getval_strlist(struct INIFILE *ini, char *section_name, char *key, char *tok, int *state) {
+ getval_setup(INIVAL_TYPE_STR_ARRAY)
+ struct StrList *list;
+ list = strlist_init();
+ strlist_append_tokenize(list, result.as_char_p, tok);
+ guard_free(result.as_char_p);
+ return list;
+}
+
int ini_data_append(struct INIFILE **ini, char *section_name, char *key, char *value) {
struct INISection *section = ini_section_search(ini, INI_SEARCH_EXACT, section_name);
if (section == NULL) {
@@ -292,13 +422,18 @@ int ini_write(struct INIFILE *ini, FILE **stream, unsigned mode) {
char *render = NULL;
if (mode == INI_WRITE_PRESERVE) {
render = tpl_render(parts[p]);
+ replace_text(render, "\n", "\n ", 0);
} else {
render = parts[p];
}
if (p == 0) {
sprintf(outvalue, "%s" LINE_SEP, render);
} else {
- sprintf(outvalue + strlen(outvalue), " %s" LINE_SEP, render);
+ if (!isspace(render[0])) {
+ sprintf(outvalue + strlen(outvalue), " %s" LINE_SEP, render);
+ } else {
+ sprintf(outvalue + strlen(outvalue), "%s" LINE_SEP, render);
+ }
}
if (mode == INI_WRITE_PRESERVE) {
guard_free(render);
@@ -307,9 +442,9 @@ int ini_write(struct INIFILE *ini, FILE **stream, unsigned mode) {
GENERIC_ARRAY_FREE(parts);
strip(outvalue);
strcat(outvalue, LINE_SEP);
- fprintf(*stream, "%s=%s%s", ini->section[x]->data[y]->key, parts_total > 1 ? LINE_SEP " " : "", outvalue);
+ fprintf(*stream, "%s = %s%s", ini->section[x]->data[y]->key, ini->section[x]->data[y]->type_hint || parts_total > 1 ? LINE_SEP " " : "", outvalue);
} else {
- fprintf(*stream, "%s=%s", ini->section[x]->data[y]->key, ini->section[x]->data[y]->value);
+ fprintf(*stream, "%s = %s", ini->section[x]->data[y]->key, ini->section[x]->data[y]->value);
}
}
fprintf(*stream, LINE_SEP);
@@ -352,6 +487,13 @@ void ini_free(struct INIFILE **ini) {
guard_free((*ini));
}
+static void ini_data_set_hint(struct INIFILE **ini, char *section_name, char *key, int hint) {
+ struct INIData *data = ini_data_get(*ini, section_name, key);
+ if (data) {
+ data->type_hint = hint;
+ }
+}
+
struct INIFILE *ini_open(const char *filename) {
FILE *fp;
char line[STASIS_BUFSIZ] = {0};
@@ -440,8 +582,10 @@ struct INIFILE *ini_open(const char *filename) {
ini_section_create(&ini, section_name);
// Record the name of the section. This is used until another section is found.
+ memset(current_section, 0, sizeof(current_section));
strcpy(current_section, section_name);
guard_free(section_name);
+ memset(line, 0, sizeof(line));
continue;
}
@@ -473,6 +617,7 @@ struct INIFILE *ini_open(const char *filename) {
}
if (isempty(value)) {
//printf("%s is probably long raw data\n", key);
+ ini_data_set_hint(&ini, current_section, key, INIVAL_TYPE_STR_ARRAY);
multiline_data = 1;
no_data = 1;
} else {
@@ -484,15 +629,14 @@ struct INIFILE *ini_open(const char *filename) {
strcpy(key, key_last);
strcpy(value, line);
}
+ memset(line, 0, sizeof(line));
// Store key value pair in section's data array
if (strlen(key)) {
lstrip(key);
strip(key);
unquote(value);
- lstrip(value);
if (!multiline_data) {
- strip(value);
reading_value = 0;
ini_data_append(&ini, current_section, key, value);
continue;