Read a configuration file: Difference between revisions

Content added Content deleted
(→‎{{header|Perl 6}}: Update to modern code. A little stricter about proto regex syntax)
(→‎C: Added example)
Line 603: Line 603:
otherfamily(2) = Harry Barber
otherfamily(2) = Harry Barber
</pre>
</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++}}==
=={{header|C++}}==