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("string()
"); }
string cell_value( const path & p ) const { return p.string(); }
} o0;
struct c1 : public column_base
{
string heading() const { return string("generic_
string()
"); }
string cell_value( const path & p ) const { return p.generic_string(); }
} o1;
struct c2 : public column_base
{
string heading() const { return string("Iteration
over
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("root_
path()
"); }
string cell_value( const path & p ) const { return p.root_path().string(); }
} o3;
struct c4 : public column_base
{
string heading() const { return string("root_
name()
"); }
string cell_value( const path & p ) const { return p.root_name().string(); }
} o4;
struct c5 : public column_base
{
string heading() const { return string("root_
directory()
"); }
string cell_value( const path & p ) const { return p.root_directory().string(); }
} o5;
struct c6 : public column_base
{
string heading() const { return string("relative_
path()
"); }
string cell_value( const path & p ) const { return p.relative_path().string(); }
} o6;
struct c7 : public column_base
{
string heading() const { return string("parent_
path()
"); }
string cell_value( const path & p ) const { return p.parent_path().string(); }
} o7;
struct c8 : public column_base
{
string heading() const { return string("filename()
"); }
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 << "";
if (temp.empty())
value = "empty";
else
value = string("") + temp + " ";
if (posix)
posix_outfile << value << '\n';
else
{
std::getline(posix_infile, temp);
if (value != temp) // POSIX and Windows differ
{
value.insert(0, " ");
value.insert(0, temp);
value.insert(0, "");
value += "";
}
outfile << value;
}
outfile << " | \n";
}
// do_row ------------------------------------------------------------------//
void do_row( const string & test_case )
{
outfile << "\n";
if (test_case.empty())
outfile << "empty | \n";
else
outfile << "" << test_case << " | \n";
for ( int i = 0; i < sizeof(column)/sizeof(column_base&); ++i )
{
do_cell( test_case, i );
}
outfile << "
\n";
}
// do_table ----------------------------------------------------------------//
void do_table()
{
outfile <<
"Path Decomposition Table
\n"
"Shaded entries indicate cases where POSIX and Windows\n"
"implementations yield different results. The top value is the\n"
"POSIX result and the bottom value is the Windows result.\n"
"
\n"
"\n"
;
// generate the column headings
outfile << "
Constructor argument | \n";
for ( int i = 0; i < sizeof(column)/sizeof(column_base&); ++i )
{
outfile << "" << column[i]->heading() << " | \n";
}
outfile << "
\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 << "
\n";
}
} // unnamed namespace
// main ------------------------------------------------------------------------------//
#define BOOST_NO_CPP_MAIN_SUCCESS_MESSAGE
#include
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 << "\n"
"\n"
"Path Decomposition Table\n"
"\n"
"\n"
;
do_table();
outfile << "\n"
"\n"
;
return 0;
}