From 377cec303eea81fb18b294eb47a54587643dbd01 Mon Sep 17 00:00:00 2001 From: Karen Arutyunov Date: Thu, 10 Sep 2020 19:05:23 +0300 Subject: Add support for arguments in default options files helpers --- libbutl/default-options.ixx | 11 ++++++++++ libbutl/default-options.mxx | 50 +++++++++++++++++++++++++++++--------------- libbutl/default-options.txx | 51 ++++++++++++++++++++++++++++++++++++++++----- 3 files changed, 90 insertions(+), 22 deletions(-) (limited to 'libbutl') diff --git a/libbutl/default-options.ixx b/libbutl/default-options.ixx index 7e4c378..4a551ac 100644 --- a/libbutl/default-options.ixx +++ b/libbutl/default-options.ixx @@ -12,4 +12,15 @@ LIBBUTL_MODEXPORT namespace butl //@@ MOD Clang needs this for some reason. cmd_ops, [] (const default_options_entry&, const O&) {}); } + + template + inline AS + merge_default_arguments (const default_options& def_ops, + const AS& cmd_args) + { + return merge_default_arguments ( + def_ops, + cmd_args, + [] (const default_options_entry&, const AS&) {}); + } } diff --git a/libbutl/default-options.mxx b/libbutl/default-options.mxx index e9f92d3..aeb246d 100644 --- a/libbutl/default-options.mxx +++ b/libbutl/default-options.mxx @@ -6,6 +6,7 @@ #endif #ifndef __cpp_lib_modules_ts +#include #include #include // move(), forward(), make_pair() @@ -50,17 +51,21 @@ LIBBUTL_MODEXPORT namespace butl template struct default_options_entry { - path file; - O options; - bool remote; + path file; + O options; + small_vector arguments; + bool remote; }; template using default_options = small_vector, 4>; - // Search for and load (using scanner S and parsing in the U::fail mode for - // both options and arguments) the specified list of options files in the - // specified directories returning a vector of option class instances (O). + // Search for and load the specified list of options files in the specified + // directories returning a vector of option class instances (O). If args is + // false, only options are allowed and are parsed using scanner S in the + // U::fail mode. If args is true, then both options and arguments are + // allowed in any order with options parsed in the U::stop mode. + // // Pass each default options file path to the specified function prior to // load (can be used for tracing, etc). The function signature is: // @@ -106,33 +111,44 @@ LIBBUTL_MODEXPORT namespace butl const optional& home_dir, const optional& extra_dir, const default_options_files&, - F&&); + F&&, + bool args = false); - // Merge the default options and the command line options. + // Merge the default options/arguments and the command line + // options/arguments. // - // Note that this is the default implementation and in some cases you may + // Note that these are the default implementations and in some cases you may // want to provide an options class-specific version that verifies/sanitizes - // the default options (e.g., you may not want to allow certain options to - // be specified in the default options files) or warns/prompts about - // potentially dangerous options if they came from the remote options files. + // the default options/arguments (e.g., you may not want to allow certain + // options to be specified in the default options files) or warns/prompts + // about potentially dangerous options if they came from the remote options + // files. // template O merge_default_options (const default_options&, const O& cmd_ops); - // As above but pass each default option to the specified function prior to - // merging. The function signature is: + template + AS + merge_default_arguments (const default_options&, const AS& cmd_args); + + // As above but pass each default option/argument entry to the specified + // function prior to merging. The function signature is: // // void (const default_options_entry&, const O& cmd_ops) // - // This version can be used to verify the default options. For example, you - // may want to disallow certain options from being specified in the default - // options files. + // This version can be used to verify the default options/arguments. For + // example, you may want to disallow certain options/arguments from being + // specified in the default options files. // template O merge_default_options (const default_options&, const O&, F&&); + template + AS + merge_default_arguments (const default_options&, const AS&, F&&); + // Find a common start (parent) directory stopping at home or root // (excluding). // diff --git a/libbutl/default-options.txx b/libbutl/default-options.txx index 730d588..5245bd6 100644 --- a/libbutl/default-options.txx +++ b/libbutl/default-options.txx @@ -31,6 +31,7 @@ LIBBUTL_MODEXPORT namespace butl //@@ MOD Clang needs this for some reason. template bool load_default_options_files (const dir_path& d, + bool args, bool remote, const small_vector& fs, F&& fn, @@ -42,7 +43,7 @@ LIBBUTL_MODEXPORT namespace butl //@@ MOD Clang needs this for some reason. bool r (true); - auto load = [&fs, &fn, &def_ops, &r] (const dir_path& d, bool remote) + auto load = [args, &fs, &fn, &def_ops, &r] (const dir_path& d, bool rem) { using namespace std; @@ -54,7 +55,7 @@ LIBBUTL_MODEXPORT namespace butl //@@ MOD Clang needs this for some reason. { if (file_exists (p)) // Follows symlinks. { - fn (p, remote, false /* overwrite */); + fn (p, rem, false /* overwrite */); S s (p.string ()); @@ -65,14 +66,26 @@ LIBBUTL_MODEXPORT namespace butl //@@ MOD Clang needs this for some reason. // this in CLI. // O o; - o.parse (s, U::fail, U::fail); + small_vector as; + + if (args) + { + while (s.more ()) + { + if (!o.parse (s, U::fail, U::stop)) + as.push_back (s.next ()); + } + } + else + o.parse (s, U::fail, U::fail); if (o.no_default_options ()) r = false; def_ops.push_back (default_options_entry {move (p), move (o), - remote}); + move (as), + rem}); } } catch (std::system_error& e) @@ -102,7 +115,8 @@ LIBBUTL_MODEXPORT namespace butl //@@ MOD Clang needs this for some reason. const optional& home_dir, const optional& extra_dir, const default_options_files& ofs, - F&& fn) + F&& fn, + bool args) { if (sys_dir) assert (sys_dir->absolute () && sys_dir->normalized ()); @@ -192,6 +206,7 @@ LIBBUTL_MODEXPORT namespace butl //@@ MOD Clang needs this for some reason. if (load_extra && extra_dir->sub (d)) { load = load_default_options_files (*extra_dir, + args, false /* remote */, ofs.files, std::forward (fn), @@ -204,6 +219,7 @@ LIBBUTL_MODEXPORT namespace butl //@@ MOD Clang needs this for some reason. if (load && options_dir_exists (od)) load = load_default_options_files (od, + args, remote, ofs.files, std::forward (fn), @@ -219,6 +235,7 @@ LIBBUTL_MODEXPORT namespace butl //@@ MOD Clang needs this for some reason. if (load && load_extra) load = load_default_options_files (*extra_dir, + args, false /* remote */, ofs.files, std::forward (fn), @@ -230,6 +247,7 @@ LIBBUTL_MODEXPORT namespace butl //@@ MOD Clang needs this for some reason. if (options_dir_exists (d)) load = load_default_options_files (d, + args, false /* remote */, ofs.files, std::forward (fn), @@ -238,6 +256,7 @@ LIBBUTL_MODEXPORT namespace butl //@@ MOD Clang needs this for some reason. if (load && sys_dir && options_dir_exists (*sys_dir)) load_default_options_files (*sys_dir, + args, false /* remote */, ofs.files, std::forward (fn), @@ -269,4 +288,26 @@ LIBBUTL_MODEXPORT namespace butl //@@ MOD Clang needs this for some reason. r.merge (cmd_ops); return r; } + + template + AS + merge_default_arguments (const default_options& def_ops, + const AS& cmd_args, + F&& fn) + { + AS r; + for (const default_options_entry& e: def_ops) + { + fn (e, cmd_args); + r.insert (r.end (), e.arguments.begin (), e.arguments.end ()); + } + + // Optimize for the common case. + // + if (r.empty ()) + return cmd_args; + + r.insert (r.end (), cmd_args.begin (), cmd_args.end ()); + return r; + } } -- cgit v1.1