255 lines
7.0 KiB
C++
255 lines
7.0 KiB
C++
// Generate an HTML table showing path decomposition ---------------------------------//
|
|
|
|
// Copyright Beman Dawes 2005.
|
|
|
|
// Distributed under the Boost Software License, Version 1.0.
|
|
// See http://www.boost.org/LICENSE_1_0.txt
|
|
|
|
// See http://www.boost.org/libs/filesystem for documentation.
|
|
|
|
// For purposes of generating the table, support both POSIX and Windows paths
|
|
|
|
#include "boost/filesystem.hpp"
|
|
#include <iostream>
|
|
#include <fstream>
|
|
|
|
using boost::filesystem::path;
|
|
using std::string;
|
|
using std::cout;
|
|
|
|
namespace {
|
|
std::ifstream infile;
|
|
std::ofstream posix_outfile;
|
|
std::ifstream posix_infile;
|
|
std::ofstream outfile;
|
|
|
|
bool posix;
|
|
|
|
const string empty_string;
|
|
|
|
struct column_base
|
|
{
|
|
virtual string heading() const = 0;
|
|
virtual string cell_value(const path& p) const = 0;
|
|
};
|
|
|
|
struct c0 : public column_base
|
|
{
|
|
string heading() const { return string("<code>string()</code>"); }
|
|
string cell_value(const path& p) const { return p.string(); }
|
|
} o0;
|
|
|
|
struct c1 : public column_base
|
|
{
|
|
string heading() const { return string("<code>generic_<br>string()</code>"); }
|
|
string cell_value(const path& p) const { return p.generic_string(); }
|
|
} o1;
|
|
|
|
struct c2 : public column_base
|
|
{
|
|
string heading() const { return string("Iteration<br>over<br>Elements"); }
|
|
string cell_value(const path& p) const
|
|
{
|
|
string s;
|
|
for (path::iterator i(p.begin()); i != p.end(); ++i)
|
|
{
|
|
if (i != p.begin())
|
|
s += ',';
|
|
s += (*i).string();
|
|
}
|
|
return s;
|
|
}
|
|
} o2;
|
|
|
|
struct c3 : public column_base
|
|
{
|
|
string heading() const { return string("<code>root_<br>path()</code>"); }
|
|
string cell_value(const path& p) const { return p.root_path().string(); }
|
|
} o3;
|
|
|
|
struct c4 : public column_base
|
|
{
|
|
string heading() const { return string("<code>root_<br>name()</code>"); }
|
|
string cell_value(const path& p) const { return p.root_name().string(); }
|
|
} o4;
|
|
|
|
struct c5 : public column_base
|
|
{
|
|
string heading() const { return string("<code>root_<br>directory()</code>"); }
|
|
string cell_value(const path& p) const { return p.root_directory().string(); }
|
|
} o5;
|
|
|
|
struct c6 : public column_base
|
|
{
|
|
string heading() const { return string("<code>relative_<br>path()</code>"); }
|
|
string cell_value(const path& p) const { return p.relative_path().string(); }
|
|
} o6;
|
|
|
|
struct c7 : public column_base
|
|
{
|
|
string heading() const { return string("<code>parent_<br>path()</code>"); }
|
|
string cell_value(const path& p) const { return p.parent_path().string(); }
|
|
} o7;
|
|
|
|
struct c8 : public column_base
|
|
{
|
|
string heading() const { return string("<code>filename()</code>"); }
|
|
string cell_value(const path& p) const { return p.filename().string(); }
|
|
} o8;
|
|
|
|
const column_base* column[] = { &o2, &o0, &o1, &o3, &o4, &o5, &o6, &o7, &o8 };
|
|
|
|
// do_cell ---------------------------------------------------------------//
|
|
|
|
void do_cell(const string& test_case, int i)
|
|
{
|
|
string temp = column[i]->cell_value(path(test_case));
|
|
string value;
|
|
outfile << "<td>";
|
|
if (temp.empty())
|
|
value = "<font size=\"-1\"><i>empty</i></font>";
|
|
else
|
|
value = string("<code>") + temp + "</code>";
|
|
|
|
if (posix)
|
|
posix_outfile << value << '\n';
|
|
else
|
|
{
|
|
std::getline(posix_infile, temp);
|
|
if (value != temp) // POSIX and Windows differ
|
|
{
|
|
value.insert(0, "<br>");
|
|
value.insert(0, temp);
|
|
value.insert(0, "<span style=\"background-color: #CCFFCC\">");
|
|
value += "</span>";
|
|
}
|
|
outfile << value;
|
|
}
|
|
outfile << "</td>\n";
|
|
}
|
|
|
|
// do_row ------------------------------------------------------------------//
|
|
|
|
void do_row(const string& test_case)
|
|
{
|
|
outfile << "<tr>\n";
|
|
|
|
if (test_case.empty())
|
|
outfile << "<td><font size=\"-1\"><i>empty</i></font></td>\n";
|
|
else
|
|
outfile << "<td><code>" << test_case << "</code></td>\n";
|
|
|
|
for (int i = 0; i < sizeof(column) / sizeof(column_base&); ++i)
|
|
{
|
|
do_cell(test_case, i);
|
|
}
|
|
|
|
outfile << "</tr>\n";
|
|
}
|
|
|
|
// do_table ----------------------------------------------------------------//
|
|
|
|
void do_table()
|
|
{
|
|
outfile << "<h1>Path Decomposition Table</h1>\n"
|
|
"<p>Shaded entries indicate cases where <i>POSIX</i> and <i>Windows</i>\n"
|
|
"implementations yield different results. The top value is the\n"
|
|
"<i>POSIX</i> result and the bottom value is the <i>Windows</i> result.\n"
|
|
"<table border=\"1\" cellspacing=\"0\" cellpadding=\"5\">\n"
|
|
"<p>\n";
|
|
|
|
// generate the column headings
|
|
|
|
outfile << "<tr><td><b>Constructor<br>argument</b></td>\n";
|
|
|
|
for (int i = 0; i < sizeof(column) / sizeof(column_base&); ++i)
|
|
{
|
|
outfile << "<td><b>" << column[i]->heading() << "</b></td>\n";
|
|
}
|
|
|
|
outfile << "</tr>\n";
|
|
|
|
// generate a row for each input line
|
|
|
|
string test_case;
|
|
while (std::getline(infile, test_case))
|
|
{
|
|
if (!test_case.empty() && *--test_case.end() == '\r')
|
|
test_case.erase(test_case.size() - 1);
|
|
if (test_case.empty() || test_case[0] != '#')
|
|
do_row(test_case);
|
|
}
|
|
|
|
outfile << "</table>\n";
|
|
}
|
|
|
|
} // unnamed namespace
|
|
|
|
// main ------------------------------------------------------------------------------//
|
|
|
|
#define BOOST_NO_CPP_MAIN_SUCCESS_MESSAGE
|
|
#include <boost/test/included/prg_exec_monitor.hpp>
|
|
|
|
int cpp_main(int argc, char* argv[]) // note name!
|
|
{
|
|
if (argc != 5)
|
|
{
|
|
std::cerr << "Usage: path_table \"POSIX\"|\"Windows\" input-file posix-file output-file\n"
|
|
"Run on POSIX first, then on Windows\n"
|
|
" \"POSIX\" causes POSIX results to be saved in posix-file;\n"
|
|
" \"Windows\" causes POSIX results read from posix-file\n"
|
|
" input-file contains the paths to appear in the table.\n"
|
|
" posix-file will be used for POSIX results\n"
|
|
" output-file will contain the generated HTML.\n";
|
|
return 1;
|
|
}
|
|
|
|
infile.open(argv[2]);
|
|
if (!infile)
|
|
{
|
|
std::cerr << "Could not open input file: " << argv[2] << std::endl;
|
|
return 1;
|
|
}
|
|
|
|
if (string(argv[1]) == "POSIX")
|
|
{
|
|
posix = true;
|
|
posix_outfile.open(argv[3]);
|
|
if (!posix_outfile)
|
|
{
|
|
std::cerr << "Could not open POSIX output file: " << argv[3] << std::endl;
|
|
return 1;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
posix = false;
|
|
posix_infile.open(argv[3]);
|
|
if (!posix_infile)
|
|
{
|
|
std::cerr << "Could not open POSIX input file: " << argv[3] << std::endl;
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
outfile.open(argv[4]);
|
|
if (!outfile)
|
|
{
|
|
std::cerr << "Could not open output file: " << argv[2] << std::endl;
|
|
return 1;
|
|
}
|
|
|
|
outfile << "<html>\n"
|
|
"<head>\n"
|
|
"<title>Path Decomposition Table</title>\n"
|
|
"</head>\n"
|
|
"<body bgcolor=\"#ffffff\" text=\"#000000\">\n";
|
|
|
|
do_table();
|
|
|
|
outfile << "</body>\n"
|
|
"</html>\n";
|
|
|
|
return 0;
|
|
}
|