From: Enblend <enb...@li...> - 2012-01-19 15:30:00
|
branch: details: http://enblend.hg.sourceforge.net/hgweb/enblend/enblend/hgrepo/e/en/enblend/enblend/rev/f5b1322d8fc8 changeset: 774:f5b1322d8fc8 user: Chris <cs...@us...> date: Thu Jan 19 16:06:47 2012 +0100 description: Introduce an command-line option called "--parameter" that takes key-value pairs. The new option is mainly intended for debugging and development as it facilitates playing with different configurations and settings without recompiling all binaries. diffstat: NEWS | 9 + VERSION | 2 +- doc/enblend.info | 0 doc/enblend.texi | 15 +++ doc/enfuse.info | 0 doc/enfuse.texi | 14 ++ doc/versenblend.texi | 2 +- doc/versenfuse.texi | 2 +- src/common.h | 240 ++++++++++++++++++++++++++++++++++++++++++++++++++- src/enblend.1 | 3 + src/enblend.cc | 62 ++++++++++++- src/enfuse.1 | 3 + src/enfuse.cc | 62 ++++++++++++- src/global.h | 232 ++++++++++++++++++++++++++++++++++++++++++++++++- 14 files changed, 636 insertions(+), 10 deletions(-) diffs (truncated from 851 to 500 lines): diff -r e7aff4a93c41 -r f5b1322d8fc8 NEWS --- a/NEWS Fri Jan 13 13:27:59 2012 +0100 +++ b/NEWS Thu Jan 19 16:06:47 2012 +0100 @@ -99,6 +99,15 @@ means all necessary DTDs must be available locally and all catalogs must be set up correctly to build the XHTML documentation. +- The option "--parameter" allows developers to pass arbitrary + key-value pairs to Enblend and Enfuse. The keys must match the + regular expression [A-Za-z][A-Za-z0-9_-]*; the values can be almost + any string. No further checking or validation is performed. + + For more explanations on how to use parameters in the source code, + see the block-comment within "namespace parameter" in file + "common.h". + * Version 4.0 diff -r e7aff4a93c41 -r f5b1322d8fc8 VERSION --- a/VERSION Fri Jan 13 13:27:59 2012 +0100 +++ b/VERSION Thu Jan 19 16:06:47 2012 +0100 @@ -1,1 +1,1 @@ -4.1-c97a3bcb81ef +4.1-e7aff4a93c41 diff -r e7aff4a93c41 -r f5b1322d8fc8 doc/enblend.info Binary file doc/enblend.info has changed diff -r e7aff4a93c41 -r f5b1322d8fc8 doc/enblend.texi --- a/doc/enblend.texi Fri Jan 13 13:27:59 2012 +0100 +++ b/doc/enblend.texi Thu Jan 19 16:06:47 2012 +0100 @@ -576,6 +576,21 @@ If @option{--output} is not specified, the default is to put the resulting image in @file{@value{src::default-output-filename}}. +@item --parameter=@var{KEY}[=@var{VALUE}]:@dots{} +@opindex --parameter +Set a @var{KEY}-@var{VALUE} pair, where @var{VALUE} is optional. This +option is cumulative. Separate multiple pairs with the usual numeric +delimiters. + +This option has the negated form @option{--no-parameter}, +@opindex --no-parameter +which takes one or more @var{KEY}s and removes them from the list of +defined parameters. The special key@tie{}@samp{*} deletes all +parameters at once. + +Parameters allow the developers to change the internal workings of +Enblend without the need to recompile. + @item -v @itemx --verbose[=@var{LEVEL}] @opindex -v diff -r e7aff4a93c41 -r f5b1322d8fc8 doc/enfuse.info Binary file doc/enfuse.info has changed diff -r e7aff4a93c41 -r f5b1322d8fc8 doc/enfuse.texi --- a/doc/enfuse.texi Fri Jan 13 13:27:59 2012 +0100 +++ b/doc/enfuse.texi Thu Jan 19 16:06:47 2012 +0100 @@ -689,6 +689,20 @@ If @option{--output} is not specified, the default is to put the resulting image in @file{@value{src::default-output-filename}}. +@item --parameter=@var{KEY}[=@var{VALUE}]:@dots{} +Set a @var{KEY}-@var{VALUE} pair, where @var{VALUE} is optional. This +option is cumulative. Separate multiple pairs with the usual numeric +delimiters. + +This option has the negated form @option{--no-parameter}, +@opindex --no-parameter +which takes one or more @var{KEY}s and removes them from the list of +defined parameters. The special key@tie{}@samp{*} deletes all +parameters at once. + +Parameters allow the developers to change the internal +workings of Enfuse without the need to recompile. + @item -v @itemx --verbose[=@var{LEVEL}] @opindex -v diff -r e7aff4a93c41 -r f5b1322d8fc8 doc/versenblend.texi --- a/doc/versenblend.texi Fri Jan 13 13:27:59 2012 +0100 +++ b/doc/versenblend.texi Thu Jan 19 16:06:47 2012 +0100 @@ -1,4 +1,4 @@ -@set UPDATED 2 January 2012 +@set UPDATED 16 January 2012 @set UPDATED-MONTH January 2012 @set EDITION 4.1-cf8082d24ef7 @set VERSION 4.1-cf8082d24ef7 diff -r e7aff4a93c41 -r f5b1322d8fc8 doc/versenfuse.texi --- a/doc/versenfuse.texi Fri Jan 13 13:27:59 2012 +0100 +++ b/doc/versenfuse.texi Thu Jan 19 16:06:47 2012 +0100 @@ -1,4 +1,4 @@ -@set UPDATED 2 January 2012 +@set UPDATED 16 January 2012 @set UPDATED-MONTH January 2012 @set EDITION 4.1-cf8082d24ef7 @set VERSION 4.1-cf8082d24ef7 diff -r e7aff4a93c41 -r f5b1322d8fc8 src/common.h --- a/src/common.h Fri Jan 13 13:27:59 2012 +0100 +++ b/src/common.h Thu Jan 19 16:06:47 2012 +0100 @@ -25,7 +25,6 @@ #endif #include <algorithm> -#include <cerrno> #include <fstream> #include <iomanip> #include <limits> @@ -34,7 +33,6 @@ #include <string> #include <vector> -#include <boost/algorithm/string/case_conv.hpp> #include <boost/algorithm/string/trim.hpp> #include <boost/assign/list_inserter.hpp> #include <boost/assign/list_of.hpp> @@ -48,6 +46,7 @@ #define NUMERIC_OPTION_DELIMITERS ";:/" #define PATH_OPTION_DELIMITERS ",;:" +#define ASSIGNMENT_CHARACTERS "=" #define MASK_COMPRESSION "DEFLATE" @@ -861,6 +860,243 @@ return profileInfo(profile, cmsInfoModel); } + +namespace parameter +{ + // Identifier: [A-Za-z][A-Za-z0-9_-]* + inline bool + is_valid_identifier(const std::string& identifier) + { + if (identifier.size() == 0) + { + return false; + } + else if (!isalpha(identifier[0])) + { + return false; + } + else + { + for (std::string::const_iterator x = identifier.begin(); x != identifier.end(); ++x) + { + if (!(isalnum(*x) || *x == '_' || *x == '-')) + { + return false; + } + } + } + + return true; + } + + + struct not_found : public std::runtime_error + { + not_found(const std::string& a_message) : std::runtime_error(a_message) {} + }; + + + // Notes: + // + // * The access of parameters through enblend::parameter::as_* is + // reasonable fast. For time-critical parts of the code, the + // parameter's value can always be copied into a local variable. + // + // * The map from parameter keys to values is meant to be constant + // after the command line was parsed, i.e. neither the map + // itself, nor one of its values should be modified. Following + // this convention makes all enblend::parameter::as_* functions + // thread safe. + // + // Some examples how to use parameters: + // + // (1) Check whether a parameter has been set. + // if (enblend::parameter::exists("foobar")) {...} + // else {...} + // + // (2) Use a parameter that is known to exist. + // std::string s = enblend::parameter::as_string("foobar"); + // int i = enblend::parameter::as_integer("foobar"); + // unsigned u = enblend::parameter::as_unsigned("foobar"); + // double x = enblend::parameter::as_floating_point("foobar"); + // bool b = enblend::parameter::as_boolean("foobar"); + // + // (3) Substitute parameter value if it exists; otherwise go with + // the default. + // std::string s = enblend::parameter::as_string("foobar", "baz"); + // int i = enblend::parameter::as_integer("foobar", 123); + // unsigned u = enblend::parameter::as_unsigned("foobar", 42U); + // double x = enblend::parameter::as_floating_point("foobar", 0.577215665); + // bool b = enblend::parameter::as_boolean("foobar", true); + // + // (4) React on parameter with a non-local change of control flow + // int i; + // try {i = enblend::parameter::as_integer("foobar");} + // catch (enblend::parameter::not_found&) {...} + // + // A parameter always can be retrieved as string with function + // as_string(). All other as_* functions throw the exception + // conversion_error, if the parameter's value cannot be + // represented. See class ParameterValue in file "global.h" for + // the details on conversion especially for as_boolean(). + + inline bool + exists(const std::string& key) + { + return Parameter.find(key) != Parameter.end(); + } + + + inline std::string + as_string(const std::string& key) + { + parameter_map::const_iterator x = Parameter.find(key); + if (x == Parameter.end()) + { + throw not_found(key); + } + else + { + return x->second.as_string(); + } + } + + + inline std::string + as_string(const std::string& key, const std::string& default_value) + { + parameter_map::const_iterator x = Parameter.find(key); + if (x == Parameter.end()) + { + return default_value; + } + else + { + return x->second.as_string(); + } + } + + + inline int + as_integer(const std::string& key) + { + parameter_map::iterator x = Parameter.find(key); + if (x == Parameter.end()) + { + throw not_found(key); + } + else + { + return x->second.as_integer(); + } + } + + + inline int + as_integer(const std::string& key, int default_value) + { + parameter_map::iterator x = Parameter.find(key); + if (x == Parameter.end()) + { + return default_value; + } + else + { + return x->second.as_integer(); + } + } + + + inline unsigned + as_unsigned(const std::string& key) + { + parameter_map::iterator x = Parameter.find(key); + if (x == Parameter.end()) + { + throw not_found(key); + } + else + { + return x->second.as_unsigned(); + } + } + + + inline unsigned + as_unsigned(const std::string& key, unsigned default_value) + { + parameter_map::iterator x = Parameter.find(key); + if (x == Parameter.end()) + { + return default_value; + } + else + { + return x->second.as_unsigned(); + } + } + + + inline double + as_double(const std::string& key) + { + parameter_map::iterator x = Parameter.find(key); + if (x == Parameter.end()) + { + throw not_found(key); + } + else + { + return x->second.as_double(); + } + } + + + inline double + as_double(const std::string& key, double default_value) + { + parameter_map::iterator x = Parameter.find(key); + if (x == Parameter.end()) + { + return default_value; + } + else + { + return x->second.as_double(); + } + } + + + inline bool + as_boolean(const std::string& key) + { + parameter_map::iterator x = Parameter.find(key); + if (x == Parameter.end()) + { + throw not_found(key); + } + else + { + return x->second.as_boolean(); + } + } + + + inline bool + as_boolean(const std::string& key, bool default_value) + { + parameter_map::iterator x = Parameter.find(key); + if (x == Parameter.end()) + { + return default_value; + } + else + { + return x->second.as_boolean(); + } + } +} // namespace parameter + } // namespace enblend #endif /* __COMMON_H__ */ diff -r e7aff4a93c41 -r f5b1322d8fc8 src/enblend.1 --- a/src/enblend.1 Fri Jan 13 13:27:59 2012 +0100 +++ b/src/enblend.1 Thu Jan 19 16:06:47 2012 +0100 @@ -53,6 +53,9 @@ "first\-layer": select only first layer in each multi\-layer image; "largest\-layer": select largest layer in each multi\-layer image; "no\-layer": do not select any layer from any image; +.TP +\fB\-\-parameter\fR=\fIKEY1[=VALUE1][\fR:KEY2[=VALUE2][:...]] +set one or more KEY\-VALUE pairs .SS "Extended options:" .TP \fB\-b\fR BLOCKSIZE diff -r e7aff4a93c41 -r f5b1322d8fc8 src/enblend.cc --- a/src/enblend.cc Fri Jan 13 13:27:59 2012 +0100 +++ b/src/enblend.cc Thu Jan 19 16:06:47 2012 +0100 @@ -161,6 +161,8 @@ TiffResolution ImageResolution; bool OutputIsValid = true; +parameter_map Parameter; + // Globals related to catching SIGINT #ifndef _WIN32 sigset_t SigintMask; @@ -488,6 +490,8 @@ cout << " \"" << (*i)->name() << "\": " << (*i)->description() << "\n"; } cout << + " --parameter=KEY1[=VALUE1][:KEY2[=VALUE2][:...]]\n" << + " set one or more KEY-VALUE pairs\n" << "\n" << "Extended options:\n" << " -b BLOCKSIZE image cache BLOCKSIZE in kilobytes; default: " << @@ -860,7 +864,9 @@ FallbackProfileId, LayerSelectorId, MainAlgoId, - ImageDifferenceId + ImageDifferenceId, + ParameterId, + NoParameterId }; static struct option long_options[] = { @@ -893,6 +899,8 @@ {"layer-selector", required_argument, 0, LayerSelectorId}, {"primary-seam-generator", required_argument, 0, MainAlgoId}, {"image-difference", required_argument, 0, ImageDifferenceId}, + {"parameter", required_argument, 0, ParameterId}, + {"no-parameter", required_argument, 0, NoParameterId}, {0, 0, 0, 0} }; @@ -1526,6 +1534,58 @@ break; } + case ParameterId: { + boost::scoped_ptr<char> s(new char[strlen(optarg) + 1]); + strcpy(s.get(), optarg); + char* save_ptr = NULL; + char* token = enblend::strtoken_r(s.get(), NUMERIC_OPTION_DELIMITERS, &save_ptr); + + while (token != NULL) { + std::string key; + std::string value; + char* delimiter = strpbrk(token, ASSIGNMENT_CHARACTERS); + + if (delimiter == NULL) { + key = token; + } else { + key = std::string(token, delimiter); + value = delimiter + 1; + } + + if (enblend::parameter::is_valid_identifier(key)) { + Parameter.insert(parameter_map::value_type(key, ParameterValue(value))); + } else { + cerr << command << ": warning: key \"" << key << "\" of pair \"" << token << + "\" is not a valid identifier; ignoring\n"; + } + + token = enblend::strtoken_r(NULL, NUMERIC_OPTION_DELIMITERS, &save_ptr); + } + + break; + } + + case NoParameterId: { + boost::scoped_ptr<char> s(new char[strlen(optarg) + 1]); + strcpy(s.get(), optarg); + char* save_ptr = NULL; + char* token = enblend::strtoken_r(s.get(), NUMERIC_OPTION_DELIMITERS, &save_ptr); + + while (token != NULL) { + if (strcmp(token, "*") == 0) { + Parameter.clear(); + } else if (enblend::parameter::is_valid_identifier(token)) { + Parameter.erase(token); + } else { + cerr << command << ": warning: key \"" << token << + "\" is not a valid identifier; ignoring\n"; + } + token = enblend::strtoken_r(NULL, NUMERIC_OPTION_DELIMITERS, &save_ptr); + } + + break; + } + case '?': switch (optopt) { case 0: // unknown long option diff -r e7aff4a93c41 -r f5b1322d8fc8 src/enfuse.1 --- a/src/enfuse.1 Fri Jan 13 13:27:59 2012 +0100 +++ b/src/enfuse.1 Thu Jan 19 16:06:47 2012 +0100 @@ -47,6 +47,9 @@ "first\-layer": select only first layer in each multi\-layer image; "largest\-layer": select largest layer in each multi\-layer image; "no\-layer": do not select any layer from any image; +.TP +\fB\-\-parameter\fR=\fIKEY1[=VALUE1][\fR:KEY2[=VALUE2][:...]] +set one or more KEY\-VALUE pairs .SS "Extended options:" .TP \fB\-b\fR BLOCKSIZE diff -r e7aff4a93c41 -r f5b1322d8fc8 src/enfuse.cc --- a/src/enfuse.cc Fri Jan 13 13:27:59 2012 +0100 +++ b/src/enfuse.cc Thu Jan 19 16:06:47 2012 +0100 @@ -127,6 +127,8 @@ TiffResolution ImageResolution; bool OutputIsValid = true; |