diff options
author | Joseph Hunkeler <jhunkeler@users.noreply.github.com> | 2024-08-07 13:52:10 -0400 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-08-07 13:52:10 -0400 |
commit | 1d5e5f26014ceefd824382acec732f326d8d6ce2 (patch) | |
tree | 2d329c1a76e1bb5a13a84659465a60d2c6e99cd2 /src/ini.c | |
parent | 202e69c8951a38187489c66e994dd593755d62cb (diff) | |
download | stasis-1d5e5f26014ceefd824382acec732f326d8d6ce2.tar.gz |
Refactor ini getter and setter usage (#19)
* Add handler for space-delimited lists
* This needs attention, however. The INI writer has no way to know a list with spaces is a list; this happens in the value conversion functions.
* Add type_hint member to INIData structure. At some point support with be added for all INIVAL_TYPE_* defines. Right now it's only used with arrays.
* Zero out line buffer in ini_open after each iteration
* Do not strip raw INI data. Let the conversion functions handle it
* Add spaces to key value pairs in rendered INI output.
* Add ini_getvar_TYPE() functions
* These replace the functionality of static conv_TYPE() functions in delivery.c
* Add support for missing types: U/CHAR, U/SHORT, STRLIST
* ini_getval: expand template variables immediately before processing the output
* Strip leading space to avoid issues with string comparisons against the result
* ini_getval: Return copies, not the original.
* This forces one to use ini_setval to replace/append values to the data array(s). It's safer this way.
* fix_tox_conf(): Use ini_getval and ini_setval instead of modifying the original pointers directly
* Tests: Free resources
* Replace ini_getval(), ini_getval_required() and conv_*() usage
* Now using ini_getval_TYPE() functions and ini_setval()
* Remove unused helper functions and variables
* download() returns long, not int
* actions: update apt cache
Diffstat (limited to 'src/ini.c')
-rw-r--r-- | src/ini.c | 164 |
1 files changed, 154 insertions, 10 deletions
@@ -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; |