Read a configuration file: Difference between revisions

→‎C: Added example
(→‎{{header|Perl 6}}: Update to modern code. A little stricter about proto regex syntax)
(→‎C: Added example)
Line 603:
otherfamily(2) = Harry Barber
</pre>
 
=={{header|C}}==
 
{{libheader|libconfini}}
'''optimized'''
 
<lang c>#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <confini.h>
 
#define bool unsigned char
 
#define FALSE 0
#define TRUE 1
 
#define CONFIGS_MEMBERS 5
#define INI_ARRAY_DELIMITER ','
 
/* Assume that the config file represent a struct containing all the parameters to load */
struct configs {
char *fullname;
char *favouritefruit;
bool needspeeling;
bool seedsremoved;
char **otherfamily;
size_t otherfamily_len;
size_t _configs_left_;
};
 
static inline void free_non_null (void * ptr) {
 
if (ptr) { free(ptr); }
 
}
 
static int array_part_handler (char * part, size_t partlen, size_t idx, IniFormat ini_format, void * v_array) {
 
ini_string_parse(part, ini_format); /* Remove all quotes, if any */
((char **) v_array)[idx] = part;
return 0;
 
}
 
static char ** make_array (size_t * arrlen, const char * src, const size_t srclen, IniFormat ini_format) {
 
/* Allocate a new array of strings and populate it from the stringified source */
char ** dest;
*arrlen = ini_array_get_length(src, INI_ARRAY_DELIMITER, ini_format);
dest = (char **) malloc(*arrlen * sizeof(char *) + srclen * sizeof(char));
char * const str_ptr = (char *) dest + *arrlen * sizeof(char *);
memcpy(str_ptr, src, srclen);
ini_array_split(str_ptr, INI_ARRAY_DELIMITER, ini_format, array_part_handler, dest);
 
return dest;
 
}
 
static int configs_member_handler (IniDispatch *this, void *v_confs) {
 
struct configs *confs = (struct configs *) v_confs;
 
if (this->type != INI_KEY) {
 
return 0;
 
}
 
/* Remove all quotes, if any */
this->d_len = ini_string_parse(this->data, this->format);
 
if (ini_string_match_ss("FULLNAME", this->data, this->format)) {
 
this->v_len = ini_string_parse(this->value, this->format); /* Remove all quotes, if any */
confs->fullname = strndup(this->value, this->v_len);
confs->_configs_left_--;
 
} else if (ini_string_match_ss("FAVOURITEFRUIT", this->data, this->format)) {
 
this->v_len = ini_string_parse(this->value, this->format); /* Remove all quotes, if any */
confs->favouritefruit = strndup(this->value, this->v_len);
confs->_configs_left_--;
 
} else if (ini_string_match_ss("NEEDSPEELING", this->data, this->format)) {
 
confs->needspeeling = ini_get_bool(this->value, TRUE);
confs->_configs_left_--;
 
} else if (ini_string_match_ss("SEEDSREMOVED", this->data, this->format)) {
 
confs->seedsremoved = ini_get_bool(this->value, TRUE);
confs->_configs_left_--;
 
} else if (ini_string_match_ss("OTHERFAMILY", this->data, this->format)) {
 
this->v_len = ini_array_collapse(this->value, INI_ARRAY_DELIMITER, this->format); /* Save memory (not strictly needed) */
confs->otherfamily = make_array(&confs->otherfamily_len, this->value, this->v_len + 1, this->format);
confs->_configs_left_--;
 
}
 
/* Optimization: stop reading the INI file when we have all we need */
return !confs->_configs_left_;
 
}
 
static int populate_configs (struct configs * confs) {
 
/* Define the format of the configuration file */
IniFormat config_format = {
.delimiter_symbol = INI_ANY_SPACE,
.semicolon_marker = INI_IGNORE,
.hash_marker = INI_IGNORE,
.multiline_nodes = INI_NO_MULTILINE,
.case_sensitive = TRUE,
.no_spaces_in_names = TRUE,
.no_single_quotes = FALSE,
.no_double_quotes = FALSE,
.implicit_is_not_empty = TRUE,
.do_not_collapse_values = FALSE,
.preserve_empty_quotes = FALSE,
.no_disabled_after_space = FALSE,
.disabled_can_be_implicit = FALSE
};
 
*confs = (struct configs) { NULL, NULL, FALSE, FALSE, NULL, 0, CONFIGS_MEMBERS };
 
if (load_ini_path("rosetta.conf", config_format, NULL, configs_member_handler, confs) & CONFINI_ERROR) {
 
fprintf(stderr, "Sorry, something went wrong :-(\n");
return 1;
 
}
 
return 0;
 
}
 
int main () {
 
struct configs confs;
 
ini_global_set_implicit_value("YES", 0);
populate_configs(&confs);
 
/* Print the configurations parsed */
 
printf(
 
"Full name: %s\n"
"Favorite fruit: %s\n"
"Need spelling: %s\n"
"Seeds removed: %s\n",
 
confs.fullname,
confs.favouritefruit,
confs.needspeeling ? "True" : "False",
confs.seedsremoved ? "True" : "False"
 
);
 
for (size_t idx = 0; idx < confs.otherfamily_len; idx++) {
 
printf("Other family[%d]: %s\n", idx, confs.otherfamily[idx]);
 
}
 
/* Free the allocated memory */
free_non_null(confs.fullname);
free_non_null(confs.favouritefruit);
free_non_null(confs.otherfamily);
 
return 0;
 
}</lang>
 
{{out}}
<pre>Full name: Foo Barber
Favorite fruit: banana
Need spelling: True
Seeds removed: False
Other family[0]: Rhu Barber
Other family[1]: Harry Barber</pre>
 
=={{header|C++}}==
Anonymous user