⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 process_jam_log.cpp

📁 Boost provides free peer-reviewed portable C++ source libraries. We emphasize libraries that work
💻 CPP
📖 第 1 页 / 共 2 页
字号:
//  process jam regression test output into XML  -----------------------------////  Copyright Beman Dawes 2002.  Distributed under the Boost//  Software License, Version 1.0. (See accompanying file//  LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)//  See http://www.boost.org/tools/regression for documentation.#include "detail/tiny_xml.hpp"#include "boost/filesystem/operations.hpp"#include "boost/filesystem/fstream.hpp"#include "boost/filesystem/exception.hpp"#include "boost/filesystem/convenience.hpp"#include <iostream>#include <string>#include <cstring>#include <map>#include <utility>  // for make_pair#include <ctime>#include <cctype>   // for tolower#include <cstdlib>  // for exitusing std::string;namespace xml = boost::tiny_xml;namespace fs = boost::filesystem;// options static bool echo = false;static bool create_dirs = false;static bool boost_build_v2 = true;namespace{  struct test_info  {    string      file_path; // relative boost-root    string      type;    bool        always_show_run_output;  };  typedef std::map< string, test_info > test2info_map;  // key is test-name  test2info_map test2info;  fs::path boost_root;  fs::path locate_root; // ALL_LOCATE_TARGET (or boost_root if none)  //  set_boost_root  --------------------------------------------------------//  void set_boost_root()  {        boost_root = fs::initial_path();    for(;;)    {      if ( fs::exists( boost_root / "libs" ) )      {        fs::current_path( fs::initial_path() ); // restore initial path        return;      }      fs::current_path( ".." );      if ( boost_root == fs::current_path() )      {        fs::current_path( fs::initial_path() ); // restore initial path        std::cout <<          "Abort: process_jam_log must be run from within a boost directory tree\n";        std::exit(1);      }      boost_root = fs::current_path();    }  }  //  append_html  -------------------------------------------------------------//  void append_html( const string & src, string & target )  {    // there are a few lines we want to ignore    if ( src.find( "th target..." ) != string::npos      || src.find( "cc1plus.exe: warning: changing search order for system directory" ) != string::npos      || src.find( "cc1plus.exe: warning:   as it has already been specified as a non-system directory" ) != string::npos      ) return;    // on some platforms (e.g. tru64cxx) the following line is a real performance boost    target.reserve(src.size() * 2 + target.size());    for ( string::size_type pos = 0; pos < src.size(); ++pos )    {      if ( src[pos] == '<' ) target += "&lt;";      else if ( src[pos] == '>' ) target += "&gt;";      else if ( src[pos] == '&' ) target += "&amp;";      else target += src[pos];    }  } //  timestamp  ---------------------------------------------------------------//  string timestamp()  {    char run_date[128];    std::time_t tod;    std::time( &tod );    std::strftime( run_date, sizeof(run_date),      "%Y-%m-%d %X UTC", std::gmtime( &tod ) );    return string( run_date );  }//  convert path separators to forward slashes  ------------------------------//  void convert_path_separators( string & s )  {    for ( string::iterator itr = s.begin(); itr != s.end(); ++itr )      if ( *itr == '\\' || *itr == '!' ) *itr = '/';  }//  trim_left ----------------------------------------------------------------//  std::string trim_left( std::string const& s )  {    std::string::size_type const pos( s.find_first_not_of(' ') );    return pos != std::string::npos        ? s.substr( pos, s.size() - pos + 1 )        : ""        ;  }  //  split --------------------------------------------------------------------//  std::vector<std::string> split( std::string const& s )  {    std::string::size_type const pos( s.find_first_of(' ') );    std::vector<std::string> result( 1, s.substr( 0, pos ) );    if ( pos == std::string::npos )        return result;    std::vector<std::string> const rest( split( trim_left( s.substr( pos, s.size() - pos + 1 ) ) ) );    result.insert( result.end(), rest.begin(), rest.end() );        return result;  }//  extract a target directory path from a jam target string  ----------------////  s may be relative to the initial_path://    ..\..\..\libs\foo\build\bin\libfoo.lib\vc7\debug\runtime-link-dynamic\boo.obj//  s may be absolute://    d:\myboost\libs\foo\build\bin\libfoo.lib\vc7\debug\runtime-link-dynamic\boo.obj//  return path is always relative to the boost directory tree://    libs/foo/build/bin/libfs.lib/vc7/debug/runtime-link-dynamic  string target_directory( const string & s )  {    string temp( s );    convert_path_separators( temp );    temp.erase( temp.find_last_of( "/" ) ); // remove leaf    temp = split( trim_left( temp ) ).back();    if ( temp[0] == '.' ) temp.erase( 0, temp.find_first_not_of( "./" ) );     else temp.erase( 0, locate_root.string().size()+1 );    if ( echo )        std::cout << "\ttarget_directory( \"" << s << "\") -> \"" << temp << "\"" << std::endl;    return temp;  }  string::size_type target_name_end( const string & s )  {    string::size_type pos = s.find( ".test/" );    if ( pos == string::npos ) pos = s.find( ".dll/" );    if ( pos == string::npos ) pos = s.find( ".so/" );    if ( pos == string::npos ) pos = s.find( ".lib/" );    if ( pos == string::npos ) pos = s.find( ".pyd/" );    if ( pos == string::npos ) pos = s.find( ".a/" );    return pos;  }  string toolset( const string & s )  {    string::size_type pos = target_name_end( s );    if ( pos == string::npos ) pos = s.find( "build/" );    if ( pos == string::npos ) return "";    pos = s.find( "/", pos ) + 1;    return s.substr( pos, s.find( "/", pos ) - pos );  }  string test_name( const string & s )  {    string::size_type pos = target_name_end( s );    if ( pos == string::npos ) return "";    string::size_type pos_start = s.rfind( '/', pos ) + 1;    return s.substr( pos_start,      (s.find( ".test/" ) != string::npos        ? pos : s.find( "/", pos )) - pos_start );  }  // Take a path to a target directory of test, and  // returns library name corresponding to that path.  string test_path_to_library_name( string const& path )  {    std::string result;    string::size_type start_pos( path.find( "libs/" ) );    if ( start_pos != string::npos )    {      // The path format is ...libs/functional/hash/test/something.test/....            // So, the part between "libs" and "test/something.test" can be considered      // as library name. But, for some libraries tests are located too deep,      // say numeric/ublas/test/test1 directory, and some libraries have tests      // in several subdirectories (regex/example and regex/test). So, nested      // directory may belong to several libraries.      // To disambituate, it's possible to place a 'sublibs' file in      // a directory. It means that child directories are separate libraries.      // It's still possible to have tests in the directory that has 'sublibs'      // file.      std::string interesting;      start_pos += 5;      string::size_type end_pos( path.find( ".test/", start_pos ) );      end_pos = path.rfind('/', end_pos);      if (path.substr(end_pos - 5, 5) == "/test")        interesting = path.substr( start_pos, end_pos - 5 - start_pos );      else        interesting = path.substr( start_pos, end_pos - start_pos );      // Take slash separate elements until we have corresponding 'sublibs'.      end_pos = 0;      for(;;)      {        end_pos = interesting.find('/', end_pos);        if (end_pos == string::npos) {          result = interesting;          break;        }        result = interesting.substr(0, end_pos);        if ( fs::exists( ( boost_root / "libs" ) / result / "sublibs" ) )        {          end_pos = end_pos + 1;        }        else          break;      }    }    return result;  }  // Tries to find target name in the string 'msg', starting from   // position start.  // If found, extract the directory name from the target name and  // stores it in 'dir', and return the position after the target name.  // Otherwise, returns string::npos.  string::size_type parse_skipped_msg_aux(const string& msg,                                          string::size_type start,                                          string& dir)  {    dir.clear();    string::size_type start_pos = msg.find( '<', start );    if ( start_pos == string::npos ) return string::npos;    ++start_pos;    string::size_type end_pos = msg.find( '>', start_pos );    dir += msg.substr( start_pos, end_pos - start_pos );    if ( boost_build_v2 )    {        // The first letter is a magic value indicating        // the type of grist.        convert_path_separators( dir );        dir.erase( 0, 1 );        // We need path from root, not from 'status' dir.        if (dir.find("../") == 0)          dir.erase(0,3);        else // dir is always relative to the boost directory tree          dir.erase( 0, locate_root.string().size()+1 );    }    else    {      if ( dir[0] == '@' )      {        // new style build path, rooted build tree        convert_path_separators( dir );        dir.replace( 0, 1, "bin/" );      }      else      {        // old style build path, integrated build tree        start_pos = dir.rfind( '!' );        convert_path_separators( dir );        string::size_type path_sep_pos = dir.find( '/', start_pos + 1 );        if ( path_sep_pos != string::npos )           dir.insert( path_sep_pos, "/bin" );        else        {          // see http://article.gmane.org/gmane.comp.lib.boost.devel/146688;          // the following code assumes that: a) 'dir' is not empty,          // b) 'end_pos != string::npos' and c) 'msg' always ends with '...'          if ( dir[dir.size() - 1] == '@' )            dir += "/" + msg.substr( end_pos + 1, msg.size() - end_pos - 1 - 3 );        }      }    }    return end_pos;  }    // the format of paths is really kinky, so convert to normal form  //   first path is missing the leading "..\".  //   first path is missing "\bin" after "status".  //   second path is missing the leading "..\".  //   second path is missing "\bin" after "build".  //   second path uses "!" for some separators.  void parse_skipped_msg( const string & msg,    string & first_dir, string & second_dir )  {    string::size_type pos = parse_skipped_msg_aux(msg, 0, first_dir);    if (pos == string::npos)      return;    parse_skipped_msg_aux(msg, pos, second_dir);  }//  test_log hides database details  -----------------------------------------//  class test_log    : boost::noncopyable  {    const string & m_target_directory;    xml::element_ptr m_root;  public:    test_log( const string & target_directory,              const string & test_name,              const string & toolset,              bool force_new_file )      : m_target_directory( target_directory )    {      if ( !force_new_file )      {        fs::path pth( locate_root / target_directory / "test_log.xml" );        fs::ifstream file( pth  );        if ( file )   // existing file        {          try          {            m_root = xml::parse( file, pth.string() );            return;          }          catch(...)          {            // unable to parse existing XML file, fall through          }        }      }      string library_name( test_path_to_library_name( target_directory ) );      test_info info;      test2info_map::iterator itr( test2info.find( library_name + "/" + test_name ) );      if ( itr != test2info.end() )        info = itr->second;            if ( !info.file_path.empty() )        library_name = test_path_to_library_name( info.file_path );            if ( info.type.empty() )      {        if ( target_directory.find( ".lib/" ) != string::npos          || target_directory.find( ".dll/" ) != string::npos           || target_directory.find( ".so/" ) != string::npos           || target_directory.find( ".dylib/" ) != string::npos           || target_directory.find( "/build/" ) != string::npos           )        {          info.type = "lib";        }        else if ( target_directory.find( ".pyd/" ) != string::npos )          info.type = "pyd";      }        m_root.reset( new xml::element( "test-log" ) );      m_root->attributes.push_back(        xml::attribute( "library", library_name ) );      m_root->attributes.push_back(        xml::attribute( "test-name", test_name ) );      m_root->attributes.push_back(        xml::attribute( "test-type", info.type ) );      m_root->attributes.push_back(        xml::attribute( "test-program", info.file_path ) );      m_root->attributes.push_back(        xml::attribute( "target-directory", target_directory ) );      m_root->attributes.push_back(        xml::attribute( "toolset", toolset ) );      m_root->attributes.push_back(        xml::attribute( "show-run-output",          info.always_show_run_output ? "true" : "false" ) );    }    ~test_log()    {      fs::path pth( locate_root / m_target_directory / "test_log.xml" );      if ( create_dirs && !fs::exists( pth.branch_path() ) )          fs::create_directories( pth.branch_path() );      fs::ofstream file( pth );      if ( !file )      {        std::cout << "*****Warning - can't open output file: "          << pth.string() << "\n";      }      else xml::write( *m_root, file );    }    const string & target_directory() const { return m_target_directory; }    void remove_action( const string & action_name )    // no effect if action_name not found    {      xml::element_list::iterator itr;      for ( itr = m_root->elements.begin();            itr != m_root->elements.end() && (*itr)->name != action_name;            ++itr ) {}      if ( itr != m_root->elements.end() ) m_root->elements.erase( itr );    }

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -