Skip to content

Instantly share code, notes, and snippets.

@randrew
Last active January 27, 2020 16:23
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save randrew/9e56bd3b64c269022b75d62c543c48a8 to your computer and use it in GitHub Desktop.
Save randrew/9e56bd3b64c269022b75d62c543c48a8 to your computer and use it in GitHub Desktop.
typedef enum {
Ezconf_w_ok = 0,
Ezconf_w_bad_conf_name,
Ezconf_w_oom,
Ezconf_w_no_home,
Ezconf_w_mkdir_failed,
Ezconf_w_conf_dir_not_dir,
Ezconf_w_old_temp_file_stuck,
Ezconf_w_temp_file_perm_denied,
Ezconf_w_temp_open_failed,
Ezconf_w_temp_fsync_failed,
Ezconf_w_temp_close_failed,
Ezconf_w_rename_failed,
Ezconf_w_line_too_long,
Ezconf_w_existing_read_error,
Ezconf_w_unknown_error,
} Ezconf_w_error;
char const *ezconf_w_errorstring(Ezconf_w_error error);
typedef struct {
char const *name;
intptr_t id;
uint8_t flags;
} Ezconf_opt;
typedef struct {
Conf_save save; // 4 ptrs (FILE* and path strings)
Ezconf_opt *opts;
size_t optscount, optscap;
intptr_t optid;
FILE *file;
Ezconf_w_error error;
uint32_t stateflags;
} Ezconf_w;
void ezconf_w_start(Ezconf_w *ezcw, Ezconf_opt *optsbuffer,
size_t buffercap, char const *confname);
void ezconf_w_addopt(Ezconf_w *ezcw, char const *key, intptr_t id);
bool ezconf_w_step(Ezconf_w *ezcw);
// example
void write_my_conf(char const *username, int pickles, int expiration_year) {
enum { Username, Coolpref, Pickles };
Ezconf_opt optsbuff[32];
Ezconf_w w;
ezconf_w_start(&w, optsbuff, sizeof optsbuff / sizeof optsbuff[0],
"myprog.conf");
ezconf_w_addopt(&w, "user_name", Username);
ezconf_w_addopt(&w, "my_cool_pref", Coolpref);
if (pickles > 0)
ezconf_w_addopt(&w, "pickles", Pickles);
while (ezconf_w_step(&w)) {
switch (w.optid) {
case Username:
fputs(username, w.file);
break;
case Coolpref:
fputs("some value", w.file);
break;
case Pickles:
fprintf(w.file, "%d (expiring %d)", pickles, expiration_year);
break;
}
}
if (w.error)
fprintf(stderr, "Conf writing error: %s\n", ezconf_w_errorstring(w.error));
}
#if 0
~/.config/myprog.conf (before)
user_name = Dudeguy
#some comment in this file
random junk line, who knows
user_name = Dudebro
pickles = 3 (expiring 2019)
my_cool_pref = some value
~/.config/myprog.conf (after)
user_name = Dudeguy
#some comment in this file
random junk line, who knows
#user_name = Dudebro
pickles = 5 (expiring 2020)
my_cool_pref = some value
~/.config replaced with $XDG_CONFIG_HOME if present.
Directory automatically created, if necessary.
Configuration file is first written to a temp file, and then moved onto existing.
#endif
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment