diff --git a/utils/nsoption.c b/utils/nsoption.c index 7306dee1b..6fd3518de 100644 --- a/utils/nsoption.c +++ b/utils/nsoption.c @@ -208,7 +208,7 @@ static void nsoption_validate(struct nsoption_s *opts, struct nsoption_s *defs) opts[NSOPTION_curl_fetch_timeout].value.u = 60; while (((opts[NSOPTION_curl_fetch_timeout].value.u * opts[NSOPTION_max_retried_fetches].value.u) > 60) && - (opts[NSOPTION_max_retried_fetches].value.u > 1)) + (opts[NSOPTION_max_retried_fetches].value.u > 1)) opts[NSOPTION_max_retried_fetches].value.u--; /* We ignore the result because we can't fail to validate. Yay */ @@ -278,69 +278,48 @@ nsoption_is_set(const struct nsoption_s *opts, } /** - * Output choices to file stream + * Output an option value into a file stream, in plain text format. * + * @param option The option to output the value of. * @param fp The file stream to write to. - * @param opts The options table to write. - * @param defs The default value table to compare with. - * @param all Output all entries not just ones changed from defaults + * @return The number of bytes written to string or -1 on error */ -static nserror -nsoption_output(FILE *fp, - struct nsoption_s *opts, - struct nsoption_s *defs, - bool all) +static size_t nsoption_output_value_file(struct nsoption_s *option, void *ctx) { - unsigned int entry; /* index to option being output */ + FILE *fp = ctx; + size_t slen = 0; /* length added to stream */ colour rgbcolour; /* RRGGBB */ - for (entry = 0; entry < NSOPTION_LISTEND; entry++) { - if ((all == false) && - (nsoption_is_set(opts, defs, entry) == false)) { - continue; - } + switch (option->type) { + case OPTION_BOOL: + slen = fprintf(fp, "%s:%c\n", option->key, option->value.b ? '1' : '0'); + break; - switch (opts[entry].type) { - case OPTION_BOOL: - fprintf(fp, "%s:%c\n", - opts[entry].key, - opts[entry].value.b ? '1' : '0'); - break; + case OPTION_INTEGER: + slen = fprintf(fp, "%s:%i\n", option->key, option->value.i); - case OPTION_INTEGER: - fprintf(fp, "%s:%i\n", - opts[entry].key, - opts[entry].value.i); + break; - break; + case OPTION_UINT: + slen = fprintf(fp, "%s:%u\n", option->key, option->value.u); + break; - case OPTION_UINT: - fprintf(fp, "%s:%u\n", - opts[entry].key, - opts[entry].value.u); - break; + case OPTION_COLOUR: + rgbcolour = (((0x000000FF & option->value.c) << 16) | + ((0x0000FF00 & option->value.c) << 0) | + ((0x00FF0000 & option->value.c) >> 16)); + slen = fprintf(fp, "%s:%06"PRIx32"\n", option->key, rgbcolour); + break; - case OPTION_COLOUR: - rgbcolour = (((0x000000FF & opts[entry].value.c) << 16) | - ((0x0000FF00 & opts[entry].value.c) << 0) | - ((0x00FF0000 & opts[entry].value.c) >> 16)); - fprintf(fp, "%s:%06"PRIx32"\n", - opts[entry].key, - rgbcolour); - - break; - - case OPTION_STRING: - fprintf(fp, "%s:%s\n", - opts[entry].key, - ((opts[entry].value.s == NULL) || - (*opts[entry].value.s == 0)) ? "" : opts[entry].value.s); - - break; - } + case OPTION_STRING: + slen = fprintf(fp, "%s:%s\n", + option->key, + ((option->value.s == NULL) || + (*option->value.s == 0)) ? "" : option->value.s); + break; } - return NSERROR_OK; + return slen; } /** @@ -388,12 +367,12 @@ nsoption_output_value_html(struct nsoption_s *option, slen = snprintf(string + pos, size - pos, "" - "#%06"PRIX32 + "#%06"PRIX32 " " "" + "border: 1px solid #%06"PRIx32"; " + "display: inline-block; " + "width: 1em; height: 1em;\">" "", rgbcolour, rgbcolour, @@ -758,7 +737,51 @@ nsoption_read(const char *path, struct nsoption_s *opts) } -/* exported interface documented in utils/nsoption.h */ +/* + * Generate options via callback. + * + * exported interface documented in utils/nsoption.h + */ +nserror +nsoption_generate(nsoption_generate_cb *generate_cb, + void *generate_ctx, + enum nsoption_generate_flags flags, + struct nsoption_s *opts, + struct nsoption_s *defs) +{ + unsigned int entry; /* index to option being output */ + + /* check to see if global table selected */ + if (opts == NULL) { + opts = nsoptions; + } + + /* check to see if global table selected */ + if (defs == NULL) { + defs = nsoptions_default; + } + + if ((opts == NULL) || (defs == NULL)) { + return NSERROR_BAD_PARAMETER; + } + + for (entry = 0; entry < NSOPTION_LISTEND; entry++) { + if (((flags & NSOPTION_GENERATE_CHANGED) != 0) && + (nsoption_is_set(opts, defs, entry) == false)) { + continue; + } + generate_cb(opts + entry, generate_ctx); + } + + return NSERROR_OK; +} + + +/* + * Write options that have changed from the defaults to a file. + * + * exported interface documented in utils/nsoption.h + */ nserror nsoption_write(const char *path, struct nsoption_s *opts, @@ -792,13 +815,18 @@ nsoption_write(const char *path, return NSERROR_NOT_FOUND; } - ret = nsoption_output(fp, opts, defs, false); + ret = nsoption_generate(nsoption_output_value_file, + fp, + NSOPTION_GENERATE_CHANGED, + opts, + defs); fclose(fp); return ret; } + /* exported interface documented in utils/nsoption.h */ nserror nsoption_dump(FILE *outf, struct nsoption_s *opts) @@ -815,7 +843,11 @@ nsoption_dump(FILE *outf, struct nsoption_s *opts) return NSERROR_BAD_PARAMETER; } - return nsoption_output(outf, opts, NULL, true); + return nsoption_generate(nsoption_output_value_file, + outf, + NSOPTION_GENERATE_ALL, + opts, + nsoptions_default); } diff --git a/utils/nsoption.h b/utils/nsoption.h index e60ebd114..7ab65b5ef 100644 --- a/utils/nsoption.h +++ b/utils/nsoption.h @@ -161,17 +161,36 @@ enum nsoption_e { */ extern struct nsoption_s *nsoptions; + /** * global default option table. */ extern struct nsoption_s *nsoptions_default; + /** * default setting callback. */ typedef nserror(nsoption_set_default_t)(struct nsoption_s *defaults); +/** + * option generate callback + */ +typedef size_t(nsoption_generate_cb)(struct nsoption_s *option, void *ctx); + + +/** + * flags to control option output in the generate call + */ +enum nsoption_generate_flags { + /** Generate output for all options */ + NSOPTION_GENERATE_ALL = 0, + /** Generate output for options which differ from the default */ + NSOPTION_GENERATE_CHANGED = 1, +}; + + /** * Initialise option system. * @@ -206,6 +225,21 @@ nserror nsoption_finalise(struct nsoption_s *opts, struct nsoption_s *defs); nserror nsoption_read(const char *path, struct nsoption_s *opts); +/** + * Generate options via acallback. + * + * iterates options controlled by flags calling a method for each matched option. + * + * @param cb Function called for each option to be output. + * @param ctx The context for the callback. + * @param flags Flags controlling option matching. + * @param opts The options table to enerate values from or NULL to use global. + * @param defs The default table to use or NULL to use global. + * @return The error status. + */ +nserror nsoption_generate(nsoption_generate_cb *cb, void *ctx, enum nsoption_generate_flags flags, struct nsoption_s *opts, struct nsoption_s *defs); + + /** * Write options that have changed from the defaults to a file. *