path_table.cpp 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260
  1. // Generate an HTML table showing path decomposition ---------------------------------//
  2. // Copyright Beman Dawes 2005.
  3. // Distributed under the Boost Software License, Version 1.0.
  4. // See http://www.boost.org/LICENSE_1_0.txt
  5. // See http://www.boost.org/libs/filesystem for documentation.
  6. // For purposes of generating the table, support both POSIX and Windows paths
  7. #include "boost/filesystem.hpp"
  8. #include <iostream>
  9. #include <fstream>
  10. using boost::filesystem::path;
  11. using std::string;
  12. using std::cout;
  13. namespace
  14. {
  15. std::ifstream infile;
  16. std::ofstream posix_outfile;
  17. std::ifstream posix_infile;
  18. std::ofstream outfile;
  19. bool posix;
  20. const string empty_string;
  21. struct column_base
  22. {
  23. virtual string heading() const = 0;
  24. virtual string cell_value( const path & p ) const = 0;
  25. };
  26. struct c0 : public column_base
  27. {
  28. string heading() const { return string("<code>string()</code>"); }
  29. string cell_value( const path & p ) const { return p.string(); }
  30. } o0;
  31. struct c1 : public column_base
  32. {
  33. string heading() const { return string("<code>generic_<br>string()</code>"); }
  34. string cell_value( const path & p ) const { return p.generic_string(); }
  35. } o1;
  36. struct c2 : public column_base
  37. {
  38. string heading() const { return string("Iteration<br>over<br>Elements"); }
  39. string cell_value( const path & p ) const
  40. {
  41. string s;
  42. for( path::iterator i(p.begin()); i != p.end(); ++i )
  43. {
  44. if ( i != p.begin() ) s += ',';
  45. s += (*i).string();
  46. }
  47. return s;
  48. }
  49. } o2;
  50. struct c3 : public column_base
  51. {
  52. string heading() const { return string("<code>root_<br>path()</code>"); }
  53. string cell_value( const path & p ) const { return p.root_path().string(); }
  54. } o3;
  55. struct c4 : public column_base
  56. {
  57. string heading() const { return string("<code>root_<br>name()</code>"); }
  58. string cell_value( const path & p ) const { return p.root_name().string(); }
  59. } o4;
  60. struct c5 : public column_base
  61. {
  62. string heading() const { return string("<code>root_<br>directory()</code>"); }
  63. string cell_value( const path & p ) const { return p.root_directory().string(); }
  64. } o5;
  65. struct c6 : public column_base
  66. {
  67. string heading() const { return string("<code>relative_<br>path()</code>"); }
  68. string cell_value( const path & p ) const { return p.relative_path().string(); }
  69. } o6;
  70. struct c7 : public column_base
  71. {
  72. string heading() const { return string("<code>parent_<br>path()</code>"); }
  73. string cell_value( const path & p ) const { return p.parent_path().string(); }
  74. } o7;
  75. struct c8 : public column_base
  76. {
  77. string heading() const { return string("<code>filename()</code>"); }
  78. string cell_value( const path & p ) const { return p.filename().string(); }
  79. } o8;
  80. const column_base * column[] = { &o2, &o0, &o1, &o3, &o4, &o5, &o6, &o7, &o8 };
  81. // do_cell ---------------------------------------------------------------//
  82. void do_cell( const string & test_case, int i )
  83. {
  84. string temp = column[i]->cell_value(path(test_case));
  85. string value;
  86. outfile << "<td>";
  87. if (temp.empty())
  88. value = "<font size=\"-1\"><i>empty</i></font>";
  89. else
  90. value = string("<code>") + temp + "</code>";
  91. if (posix)
  92. posix_outfile << value << '\n';
  93. else
  94. {
  95. std::getline(posix_infile, temp);
  96. if (value != temp) // POSIX and Windows differ
  97. {
  98. value.insert(0, "<br>");
  99. value.insert(0, temp);
  100. value.insert(0, "<span style=\"background-color: #CCFFCC\">");
  101. value += "</span>";
  102. }
  103. outfile << value;
  104. }
  105. outfile << "</td>\n";
  106. }
  107. // do_row ------------------------------------------------------------------//
  108. void do_row( const string & test_case )
  109. {
  110. outfile << "<tr>\n";
  111. if (test_case.empty())
  112. outfile << "<td><font size=\"-1\"><i>empty</i></font></td>\n";
  113. else
  114. outfile << "<td><code>" << test_case << "</code></td>\n";
  115. for ( int i = 0; i < sizeof(column)/sizeof(column_base&); ++i )
  116. {
  117. do_cell( test_case, i );
  118. }
  119. outfile << "</tr>\n";
  120. }
  121. // do_table ----------------------------------------------------------------//
  122. void do_table()
  123. {
  124. outfile <<
  125. "<h1>Path Decomposition Table</h1>\n"
  126. "<p>Shaded entries indicate cases where <i>POSIX</i> and <i>Windows</i>\n"
  127. "implementations yield different results. The top value is the\n"
  128. "<i>POSIX</i> result and the bottom value is the <i>Windows</i> result.\n"
  129. "<table border=\"1\" cellspacing=\"0\" cellpadding=\"5\">\n"
  130. "<p>\n"
  131. ;
  132. // generate the column headings
  133. outfile << "<tr><td><b>Constructor<br>argument</b></td>\n";
  134. for ( int i = 0; i < sizeof(column)/sizeof(column_base&); ++i )
  135. {
  136. outfile << "<td><b>" << column[i]->heading() << "</b></td>\n";
  137. }
  138. outfile << "</tr>\n";
  139. // generate a row for each input line
  140. string test_case;
  141. while ( std::getline( infile, test_case ) )
  142. {
  143. if (!test_case.empty() && *--test_case.end() == '\r')
  144. test_case.erase(test_case.size()-1);
  145. if (test_case.empty() || test_case[0] != '#')
  146. do_row( test_case );
  147. }
  148. outfile << "</table>\n";
  149. }
  150. } // unnamed namespace
  151. // main ------------------------------------------------------------------------------//
  152. #define BOOST_NO_CPP_MAIN_SUCCESS_MESSAGE
  153. #include <boost/test/included/prg_exec_monitor.hpp>
  154. int cpp_main( int argc, char * argv[] ) // note name!
  155. {
  156. if ( argc != 5 )
  157. {
  158. std::cerr <<
  159. "Usage: path_table \"POSIX\"|\"Windows\" input-file posix-file output-file\n"
  160. "Run on POSIX first, then on Windows\n"
  161. " \"POSIX\" causes POSIX results to be saved in posix-file;\n"
  162. " \"Windows\" causes POSIX results read from posix-file\n"
  163. " input-file contains the paths to appear in the table.\n"
  164. " posix-file will be used for POSIX results\n"
  165. " output-file will contain the generated HTML.\n"
  166. ;
  167. return 1;
  168. }
  169. infile.open( argv[2] );
  170. if ( !infile )
  171. {
  172. std::cerr << "Could not open input file: " << argv[2] << std::endl;
  173. return 1;
  174. }
  175. if (string(argv[1]) == "POSIX")
  176. {
  177. posix = true;
  178. posix_outfile.open( argv[3] );
  179. if ( !posix_outfile )
  180. {
  181. std::cerr << "Could not open POSIX output file: " << argv[3] << std::endl;
  182. return 1;
  183. }
  184. }
  185. else
  186. {
  187. posix = false;
  188. posix_infile.open( argv[3] );
  189. if ( !posix_infile )
  190. {
  191. std::cerr << "Could not open POSIX input file: " << argv[3] << std::endl;
  192. return 1;
  193. }
  194. }
  195. outfile.open( argv[4] );
  196. if ( !outfile )
  197. {
  198. std::cerr << "Could not open output file: " << argv[2] << std::endl;
  199. return 1;
  200. }
  201. outfile << "<html>\n"
  202. "<head>\n"
  203. "<title>Path Decomposition Table</title>\n"
  204. "</head>\n"
  205. "<body bgcolor=\"#ffffff\" text=\"#000000\">\n"
  206. ;
  207. do_table();
  208. outfile << "</body>\n"
  209. "</html>\n"
  210. ;
  211. return 0;
  212. }