diff --git a/fhiclcpp/extended_value.h b/fhiclcpp/extended_value.h index 484038d..a974c19 100644 --- a/fhiclcpp/extended_value.h +++ b/fhiclcpp/extended_value.h @@ -11,10 +11,12 @@ #include "fhiclcpp/Protection.h" #include "fhiclcpp/fwd.h" #include "stdmap_shims.h" +#include "fhiclcpp/exception.h" #include #include #include +#include // ---------------------------------------------------------------------- @@ -24,8 +26,66 @@ namespace fhicl { }; } +namespace fhicl { +namespace detail { +using fhicl::exception; +using fhicl::error; + +auto unwrap_value = [](auto value) { + try { + return boost::any_cast>(value).first; + } catch (const boost::bad_any_cast &) { + return value; + } +}; + +auto unwrap_raw_value = [](auto value) { + try { + return boost::any_cast>(value).second; + } catch (const boost::bad_any_cast &) { + return std::string{}; + } +}; + +auto rtrim_whitespace = [](auto const &str) { + constexpr auto double_quote = '\"'; + constexpr auto double_slashes = "//"; + constexpr auto space_char=' '; + constexpr auto skip_chars = "# \n\r\t"; + + if(str.empty()) + return str; + + if (str[0] == double_quote) { + std::size_t pos = str.find(double_quote, 1); + + if (pos == std::string::npos) + throw exception(cant_find, "missing a double quote in str=" + str); + + return str.substr(0, pos + 1); + } + + std::size_t pos = str.find(double_slashes); + + if (pos == std::string::npos) { + pos = str.find_first_of(skip_chars); + + if (pos == std::string::npos) + return str; + } + + while(str[--pos]==space_char && pos!=0); + + return str.substr(0, pos+1); +}; + +auto wrap_value = [](auto value, auto raw_value) { + return std::make_pair(value, rtrim_whitespace(raw_value)); +}; +} // namespace detail +} // namespace fhicl + // ---------------------------------------------------------------------- - class fhicl::extended_value { public: @@ -38,6 +98,7 @@ public: : in_prolog( false ) , tag ( UNKNOWN ) , value () + , raw_value() , src_info () , protection (Protection::NONE) { } @@ -49,9 +110,10 @@ public: std::string const& src = {}) : in_prolog( in_prolog ) , tag ( tag ) - , value ( value ) + , value ( fhicl::detail::unwrap_value(value)) + , raw_value( fhicl::detail::unwrap_raw_value(value)) , src_info ( src ) - , protection (protection) + , protection (protection) { } extended_value(bool in_prolog, @@ -60,7 +122,8 @@ public: std::string const& src = {}) : in_prolog( in_prolog ) , tag ( tag ) - , value ( value ) + , value ( fhicl::detail::unwrap_value(value)) + , raw_value( fhicl::detail::unwrap_raw_value(value)) , src_info ( src ) , protection (Protection::NONE) { } @@ -97,6 +160,7 @@ public: bool in_prolog; value_tag tag; boost::any value; + std::string raw_value; std::string src_info; Protection protection; diff --git a/fhiclcpp/parse.cc b/fhiclcpp/parse.cc index 10a400e..1ea91e4 100644 --- a/fhiclcpp/parse.cc +++ b/fhiclcpp/parse.cc @@ -194,11 +194,13 @@ namespace { xvalue_dp(bool b, value_tag t, boost::any v, - FwdIter pos, + FwdIter first, + FwdIter last, cet::includer const & s) { - std::string const src_info = s.src_whereis(pos); - return extended_value(b, t, v, src_info); + std::string const src_info = s.src_whereis(first); + boost::any wv= fhicl::detail::wrap_value(v,std::string(first,last)); + return extended_value(b, t,wv,src_info); } complex_t @@ -536,7 +538,7 @@ struct fhicl::value_parser value_parser(); // data member: - extended_value v; + extended_value v; // parser rules: atom_token nil, boolean; @@ -731,23 +733,23 @@ fhicl::document_parser::document_parser(cet::includer const & s) #pragma clang diagnostic ignored "-Wunsequenced" #endif value = - ((iter_pos >> vp.nil ) [ _val = phx::bind(&xvalue_dp, ref(in_prolog), NIL , qi::_2, qi::_1, ref(s)) ] | - (iter_pos >> vp.boolean) [ _val = phx::bind(&xvalue_dp, ref(in_prolog), BOOL , qi::_2, qi::_1, ref(s)) ] | - (iter_pos >> vp.number ) [ _val = phx::bind(&xvalue_dp, ref(in_prolog), NUMBER , qi::_2, qi::_1, ref(s)) ] | - (iter_pos >> vp.complex) [ _val = phx::bind(&xvalue_dp, ref(in_prolog), COMPLEX , qi::_2, qi::_1, ref(s)) ] | - (iter_pos >> vp.string ) [ _val = phx::bind(&xvalue_dp, ref(in_prolog), STRING , qi::_2, qi::_1, ref(s)) ] | + ((iter_pos >> vp.nil >> iter_pos) [ _val = phx::bind(&xvalue_dp, ref(in_prolog), NIL , qi::_2, qi::_1, qi::_3, ref(s)) ] | + (iter_pos >> vp.boolean >> iter_pos) [ _val = phx::bind(&xvalue_dp, ref(in_prolog), BOOL , qi::_2, qi::_1, qi::_3, ref(s)) ] | + (iter_pos >> vp.number >> iter_pos) [ _val = phx::bind(&xvalue_dp, ref(in_prolog), NUMBER , qi::_2, qi::_1, qi::_3, ref(s)) ] | + (iter_pos >> vp.complex >> iter_pos) [ _val = phx::bind(&xvalue_dp, ref(in_prolog), COMPLEX , qi::_2, qi::_1, qi::_3, ref(s)) ] | + (iter_pos >> vp.string >> iter_pos) [ _val = phx::bind(&xvalue_dp, ref(in_prolog), STRING , qi::_2, qi::_1, qi::_3, ref(s)) ] | (iter_pos >> localref) - [ _val = phx::bind(&local_lookup, - qi::_2, ref(tbl), ref(in_prolog), - qi::_1, ref(s)) ] | - (iter_pos >> dbref) - [ _val = phx::bind(&database_lookup, - qi::_2, ref(tbl), ref(in_prolog), - qi::_1, ref(s)) ] | - (iter_pos >> vp.id ) [ _val = phx::bind(&xvalue_dp, ref(in_prolog), TABLEID , qi::_2, qi::_1, ref(s)) ] | - (iter_pos >> sequence ) [ _val = phx::bind(&xvalue_dp, ref(in_prolog), SEQUENCE, qi::_2, qi::_1, ref(s)) ] | - (iter_pos >> table ) [ _val = phx::bind(&xvalue_dp, ref(in_prolog), TABLE , qi::_2, qi::_1, ref(s)) ] | - (iter_pos >> vp.catchall ) [ _val = phx::bind(&xvalue_dp, ref(in_prolog), STRING , qi::_2, qi::_1, ref(s)) ] + [ _val = phx::bind(&local_lookup, + qi::_2, ref(tbl), ref(in_prolog), + qi::_1, ref(s)) ] | + (iter_pos >> dbref ) + [ _val = phx::bind(&database_lookup, + qi::_2, ref(tbl), ref(in_prolog), + qi::_1, ref(s)) ] | + (iter_pos >> vp.id >> iter_pos) [ _val = phx::bind(&xvalue_dp, ref(in_prolog), TABLEID , qi::_2, qi::_1, qi::_3, ref(s)) ] | + (iter_pos >> sequence >> iter_pos) [ _val = phx::bind(&xvalue_dp, ref(in_prolog), SEQUENCE, qi::_2, qi::_1, qi::_3, ref(s)) ] | + (iter_pos >> table >>iter_pos) [ _val = phx::bind(&xvalue_dp, ref(in_prolog), TABLE , qi::_2, qi::_1, qi::_3, ref(s)) ] | + (iter_pos >> vp.catchall >> iter_pos) [ _val = phx::bind(&xvalue_dp, ref(in_prolog), STRING , qi::_2, qi::_1, qi::_3, ref(s)) ] ); #ifdef __clang__ #pragma clang diagnostic pop