From f8677f8bfaa68e6714f4af7b030d0f365e60b918 Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Mon, 29 Oct 2012 10:03:36 +0200 Subject: Add support for database prefixes in command line interface --- odb/option-parsers.hxx | 201 ++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 156 insertions(+), 45 deletions(-) (limited to 'odb/option-parsers.hxx') diff --git a/odb/option-parsers.hxx b/odb/option-parsers.hxx index a8fc1f5..a974a7c 100644 --- a/odb/option-parsers.hxx +++ b/odb/option-parsers.hxx @@ -5,6 +5,7 @@ #ifndef ODB_OPTION_PARSERS_HXX #define ODB_OPTION_PARSERS_HXX +#include #include #include @@ -12,72 +13,183 @@ namespace cli { + // Return true if there is a database prefix. + // + template + bool + parse_option_value (std::string const& o, std::string const& ov, + database& k, V& v) + { + bool r (false); + std::string::size_type p = ov.find (':'); + + std::string vstr; + if (p != std::string::npos) + { + std::string kstr (ov, 0, p); + + // See if this prefix resolves to the database name. If not, + // assume there is no prefix. + // + std::istringstream ks (kstr); + + if (ks >> k && ks.eof ()) + { + r = true; + vstr.assign (ov, p + 1, std::string::npos); + } + } + + if (!r) + vstr = ov; // Use the whole value. + + if (!vstr.empty ()) + { + std::istringstream vs (vstr); + + if (!(vs >> v && vs.eof ())) + throw invalid_value (o, ov); + } + else + v = V (); + + return r; + } + + // Specialization for std::string. + // + bool + parse_option_value (std::string const&, std::string const& ov, + database& k, std::string& v) + { + bool r (false); + std::string::size_type p = ov.find (':'); + + if (p != std::string::npos) + { + std::string kstr (ov, 0, p); + + // See if this prefix resolves to the database name. If not, + // assume there is no prefix. + // + std::istringstream ks (kstr); + + if (ks >> k && ks.eof ()) + { + r = true; + v.assign (ov, p + 1, std::string::npos); + } + } + + if (!r) + v = ov; // Use the whole value. + + return r; + } + template struct parser > { + typedef database_map map; + static void - parse (database_map& m, bool& xs, scanner& s) + parse (map& m, bool& xs, scanner& s) { - typedef database_map map; - xs = true; std::string o (s.next ()); if (s.more ()) { - std::string ov (s.next ()); - std::string::size_type p = ov.find (':'); + database k; + V v; - if (p != std::string::npos) + if (parse_option_value (o, s.next (), k, v)) + m[k] = v; // Override any old value. + else { - std::string kstr (ov, 0, p); - std::string vstr (ov, p + 1); - - // See if this prefix resolves to the database name. If not, - // assume there is no prefix. + // No database prefix is specified which means it applies to + // all the databases. We also don't want to override database- + // specific values, so use insert(). // - database k; - std::istringstream ks (kstr); + m.insert (typename map::value_type (database::common, v)); + m.insert (typename map::value_type (database::mssql, v)); + m.insert (typename map::value_type (database::mysql, v)); + m.insert (typename map::value_type (database::oracle, v)); + m.insert (typename map::value_type (database::pgsql, v)); + m.insert (typename map::value_type (database::sqlite, v)); + } + } + else + throw missing_value (o); + } + }; - if (ks >> k && ks.eof ()) - { - V v = V (); + template + struct parser > > + { + typedef database_map > map; - if (!vstr.empty ()) - { - std::istringstream vs (vstr); + static void + parse (map& m, bool& xs, scanner& s) + { + xs = true; + std::string o (s.next ()); - if (!(vs >> v && vs.eof ())) - throw invalid_value (o, ov); - } + if (s.more ()) + { + database k; + V v; - m[k] = v; // Override any old value. - return; - } + if (parse_option_value (o, s.next (), k, v)) + m[k].push_back (v); + else + { + // No database prefix is specified which means it applies to + // all the databases. + // + m[database::common].push_back (v); + m[database::mssql].push_back (v); + m[database::mysql].push_back (v); + m[database::oracle].push_back (v); + m[database::pgsql].push_back (v); + m[database::sqlite].push_back (v); } + } + else + throw missing_value (o); + } + }; - // No database prefix is specified which means it applies to - // all the databases. - // - V v = V (); + template + struct parser > > + { + typedef database_map > map; - if (!ov.empty ()) - { - std::istringstream vs (ov); + static void + parse (map& m, bool& xs, scanner& s) + { + xs = true; + std::string o (s.next ()); - if (!(vs >> v && vs.eof ())) - throw invalid_value (o, ov); - } + if (s.more ()) + { + database k; + V v; - // We don't want to override database-specific values, so use - // insert(). - // - m.insert (typename map::value_type (database::common, v)); - m.insert (typename map::value_type (database::mssql, v)); - m.insert (typename map::value_type (database::mysql, v)); - m.insert (typename map::value_type (database::oracle, v)); - m.insert (typename map::value_type (database::pgsql, v)); - m.insert (typename map::value_type (database::sqlite, v)); + if (parse_option_value (o, s.next (), k, v)) + m[k].insert (v); + else + { + // No database prefix is specified which means it applies to + // all the databases. + // + m[database::common].insert (v); + m[database::mssql].insert (v); + m[database::mysql].insert (v); + m[database::oracle].insert (v); + m[database::pgsql].insert (v); + m[database::sqlite].insert (v); + } } else throw missing_value (o); @@ -85,5 +197,4 @@ namespace cli }; } - #endif // ODB_OPTION_PARSERS_HXX -- cgit v1.1