// -*- C++ -*- (c) 2007, 2008, 2009 Petr Rockai // (c) 2013 Vladimír Štill #include #include #include #include #include #include #include #include #include #include #ifndef DIVINE_REPORT_H #define DIVINE_REPORT_H namespace divine { struct Report { Report() : _signal( 0 ), _finished( false ), _dumped( false ) { } virtual void signal( int s ) { _finished = false; _signal = s; } virtual void finished() { _finished = true; } void final( const Meta &meta ) { if ( _dumped ) return; _dumped = true; doFinal( meta ); } virtual void execCommand( const std::string &ec ) { _execCommand = ec; } virtual void doFinal( const Meta & ) = 0; struct Merged : WithReport { const Report &r; const Meta &m; Merged( const Report &r, const Meta &m ) : r( r ), m( m ) { } std::vector< ReportLine > report() const override; }; Merged mergedReport( const Meta &meta ) const { return Merged( *this, meta ); } static std::string mangle( std::string str ); template< typename Rep, typename... Ts > static std::shared_ptr< Report > get( Ts &&... ts ) { return _get< Rep >( brick::types::Preferred(), std::forward< Ts >( ts )... ); } private: sysinfo::Info _sysinfo; std::string _execCommand; int _signal; bool _finished, _dumped; template< typename Rep > static std::shared_ptr< Rep > declcheck( std::shared_ptr< Rep > ) { static_assert( std::is_base_of< Report, Rep >::value, "Required report does not inherit from Report." ); ASSERT_UNREACHABLE( "declcheck" ); } template< typename Rep, typename... Ts > static auto _get( brick::types::Preferred, Ts &&... ts ) -> decltype( declcheck( Rep::get( std::forward< Ts >( ts )... ) ) ) { return Rep::get( std::forward< Ts >( ts )... ); } template< typename Rep, typename... Ts > static std::shared_ptr< Report > _get( brick::types::NotPreferred, Ts &&... ts ) { return std::make_shared< Rep >( std::forward< Ts >( ts )... ); } }; template< typename Out > struct TextReportBase : Report { Out output; template< typename... Ts > TextReportBase( Ts &&...ts ) : output( std::forward< Ts >( ts )... ) { } void doFinal( const Meta &meta ) override { output << mergedReport( meta ); } }; struct TextReport : TextReportBase< std::ostream & > { TextReport( std::ostream &o ) : TextReportBase< std::ostream & >( o ) { } }; struct TextFileReport : TextReportBase< std::ofstream > { TextFileReport( std::string name ) : TextReportBase< std::ofstream >( name ) { } }; template< typename Out > struct PlainReportBase : Report { Out output; template< typename... Ts > PlainReportBase( Ts &&...ts ) : output( std::forward< Ts >( ts )... ) { } void doFinal( const Meta &meta ) override { auto merged = mergedReport( meta ).report(); for ( auto x : merged ) { if ( x.key != "" ) output << x.key << ": " << x.value << std::endl; } } }; struct PlainReport : PlainReportBase< std::ostream & > { PlainReport( std::ostream &o ) : PlainReportBase< std::ostream & >( o ) { } }; struct PlainFileReport : PlainReportBase< std::ofstream > { PlainFileReport( std::string name ) : PlainReportBase< std::ofstream >( name ) { } }; template< typename Out > struct YAMLReportBase : Report { Out output; template< typename... Ts > YAMLReportBase( Ts &&...ts ) : output( std::forward< Ts >( ts )... ) { } void doFinal( const Meta &meta ) override { auto merged = mergedReport( meta ).report(); for ( auto x : merged ) { if ( x.key != "" ) { std::string k = x.key; for ( char &c : k ) { c = std::tolower( c ); if ( c == '-' || c == '_' ) c = ' '; } auto f = keyfilt( k, x.value ); output << f.first << ": " << f.second << std::endl; } } } std::pair< std::string, std::string > keyfilt( std::string key, std::string val ) { if ( val == "-" || val == "none" || val == "None" || val == "n/a" ) val = "null"; if ( key == "property" ) { for ( auto it = val.begin(); std::next( it ) != val.end(); ++it ) if ( *it == ' ' && *std::next( it ) == '+' ) { it = val.erase( it ); *it = ','; } } else if ( key == "compile flags" ) { for ( auto it = std::next( val.begin() ); std::next( it ) != val.end(); ++it ) if ( *it == ' ' ) it = std::next( val.insert( it, ',' ) ); val = "[" + val + " ]"; } else if ( key == "states visited" ) { key = "states count"; } return { key, val }; } }; struct YAMLReport : YAMLReportBase< std::ostream & > { YAMLReport( std::ostream &o ) : YAMLReportBase< std::ostream & >( o ) { } }; struct YAMLFileReport : YAMLReportBase< std::ofstream > { YAMLFileReport( std::string name ) : YAMLReportBase< std::ofstream >( name ) { } }; struct SqlReport : Report { SqlReport( const std::string &db, const std::string &connstr ); void doFinal( const Meta &meta ) override; #if !OPT_SQL template< typename... X > static std::shared_ptr< Report > get( X &&... ) { return nullptr; } #endif private: std::string _connstr; std::string _db; }; struct AggregateReport : Report { void signal( int s ) override { for ( auto r : _reports ) r->signal( s ); } void finished() override { for ( auto r : _reports ) r->finished(); } void execCommand( const std::string &ec ) override { for ( auto r : _reports ) r->execCommand( ec ); } void doFinal( const Meta &meta ) override { for ( auto r : _reports ) r->doFinal( meta ); } void addReport( std::shared_ptr< Report > rep ) { _reports.push_back( rep ); } private: std::vector< std::shared_ptr< Report > > _reports; }; struct NoReport : Report { void doFinal( const Meta & ) override { } void signal( int ) override { } void finished() override { } }; } #endif