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