2003-05-24 11:13:26 +00:00
|
|
|
/*
|
|
|
|
*
|
|
|
|
* Copyright (c) 2002-2003
|
2005-01-21 17:28:42 +00:00
|
|
|
* John Maddock
|
2003-05-24 11:13:26 +00:00
|
|
|
*
|
2003-10-04 11:29:20 +00:00
|
|
|
* Use, modification and distribution are subject to the
|
2003-09-30 13:02:51 +00:00
|
|
|
* Boost Software License, Version 1.0. (See accompanying file
|
|
|
|
* LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
2003-05-24 11:13:26 +00:00
|
|
|
*
|
|
|
|
*/
|
2003-05-17 11:55:51 +00:00
|
|
|
|
|
|
|
#include <iostream>
|
|
|
|
#include <iomanip>
|
|
|
|
#include <fstream>
|
|
|
|
#include <deque>
|
|
|
|
#include <sstream>
|
|
|
|
#include <stdexcept>
|
|
|
|
#include <iterator>
|
|
|
|
#include <boost/regex.hpp>
|
|
|
|
#include <boost/version.hpp>
|
|
|
|
#include "regex_comparison.hpp"
|
|
|
|
|
|
|
|
#ifdef BOOST_HAS_PCRE
|
|
|
|
#include "pcre.h" // for pcre version number
|
|
|
|
#endif
|
|
|
|
|
|
|
|
//
|
|
|
|
// globals:
|
|
|
|
//
|
|
|
|
bool time_boost = false;
|
|
|
|
bool time_localised_boost = false;
|
|
|
|
bool time_greta = false;
|
|
|
|
bool time_safe_greta = false;
|
|
|
|
bool time_posix = false;
|
|
|
|
bool time_pcre = false;
|
2005-01-13 17:06:21 +00:00
|
|
|
bool time_xpressive = false;
|
2003-05-17 11:55:51 +00:00
|
|
|
|
|
|
|
bool test_matches = false;
|
|
|
|
bool test_code = false;
|
|
|
|
bool test_html = false;
|
|
|
|
bool test_short_twain = false;
|
|
|
|
bool test_long_twain = false;
|
|
|
|
|
|
|
|
|
|
|
|
std::string html_template_file;
|
|
|
|
std::string html_out_file;
|
|
|
|
std::string html_contents;
|
|
|
|
std::list<results> result_list;
|
|
|
|
|
|
|
|
// the following let us compute averages:
|
|
|
|
double greta_total = 0;
|
|
|
|
double safe_greta_total = 0;
|
|
|
|
double boost_total = 0;
|
|
|
|
double locale_boost_total = 0;
|
|
|
|
double posix_total = 0;
|
|
|
|
double pcre_total = 0;
|
2005-09-18 09:25:14 +00:00
|
|
|
double xpressive_total = 0;
|
2003-05-17 11:55:51 +00:00
|
|
|
unsigned greta_test_count = 0;
|
|
|
|
unsigned safe_greta_test_count = 0;
|
|
|
|
unsigned boost_test_count = 0;
|
|
|
|
unsigned locale_boost_test_count = 0;
|
|
|
|
unsigned posix_test_count = 0;
|
|
|
|
unsigned pcre_test_count = 0;
|
2005-09-18 09:25:14 +00:00
|
|
|
unsigned xpressive_test_count = 0;
|
2003-05-17 11:55:51 +00:00
|
|
|
|
|
|
|
int handle_argument(const std::string& what)
|
|
|
|
{
|
|
|
|
if(what == "-b")
|
|
|
|
time_boost = true;
|
|
|
|
else if(what == "-bl")
|
|
|
|
time_localised_boost = true;
|
|
|
|
#ifdef BOOST_HAS_GRETA
|
|
|
|
else if(what == "-g")
|
|
|
|
time_greta = true;
|
|
|
|
else if(what == "-gs")
|
|
|
|
time_safe_greta = true;
|
|
|
|
#endif
|
|
|
|
#ifdef BOOST_HAS_POSIX
|
|
|
|
else if(what == "-posix")
|
|
|
|
time_posix = true;
|
|
|
|
#endif
|
|
|
|
#ifdef BOOST_HAS_PCRE
|
|
|
|
else if(what == "-pcre")
|
|
|
|
time_pcre = true;
|
2005-01-13 17:06:21 +00:00
|
|
|
#endif
|
|
|
|
#ifdef BOOST_HAS_XPRESSIVE
|
2005-09-18 16:31:56 +00:00
|
|
|
else if(what == "-xpressive" || what == "-dxpr")
|
2005-01-13 17:06:21 +00:00
|
|
|
time_xpressive = true;
|
2003-05-17 11:55:51 +00:00
|
|
|
#endif
|
|
|
|
else if(what == "-all")
|
|
|
|
{
|
|
|
|
time_boost = true;
|
|
|
|
time_localised_boost = true;
|
|
|
|
#ifdef BOOST_HAS_GRETA
|
|
|
|
time_greta = true;
|
|
|
|
time_safe_greta = true;
|
|
|
|
#endif
|
|
|
|
#ifdef BOOST_HAS_POSIX
|
|
|
|
time_posix = true;
|
|
|
|
#endif
|
|
|
|
#ifdef BOOST_HAS_PCRE
|
|
|
|
time_pcre = true;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
else if(what == "-test-matches")
|
|
|
|
test_matches = true;
|
|
|
|
else if(what == "-test-code")
|
|
|
|
test_code = true;
|
|
|
|
else if(what == "-test-html")
|
|
|
|
test_html = true;
|
|
|
|
else if(what == "-test-short-twain")
|
|
|
|
test_short_twain = true;
|
|
|
|
else if(what == "-test-long-twain")
|
|
|
|
test_long_twain = true;
|
|
|
|
else if(what == "-test-all")
|
|
|
|
{
|
|
|
|
test_matches = true;
|
|
|
|
test_code = true;
|
|
|
|
test_html = true;
|
|
|
|
test_short_twain = true;
|
|
|
|
test_long_twain = true;
|
|
|
|
}
|
|
|
|
else if((what == "-h") || (what == "--help"))
|
|
|
|
return show_usage();
|
|
|
|
else if((what[0] == '-') || (what[0] == '/'))
|
|
|
|
{
|
|
|
|
std::cerr << "Unknown argument: \"" << what << "\"" << std::endl;
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
else if(html_template_file.size() == 0)
|
|
|
|
{
|
|
|
|
html_template_file = what;
|
|
|
|
load_file(html_contents, what.c_str());
|
|
|
|
}
|
|
|
|
else if(html_out_file.size() == 0)
|
|
|
|
html_out_file = what;
|
|
|
|
else
|
|
|
|
{
|
|
|
|
std::cerr << "Unexpected argument: \"" << what << "\"" << std::endl;
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int show_usage()
|
|
|
|
{
|
|
|
|
std::cout <<
|
|
|
|
"Usage\n"
|
|
|
|
"regex_comparison [-h] [library options] [test options] [html_template html_output_file]\n"
|
|
|
|
" -h Show help\n\n"
|
|
|
|
" library options:\n"
|
|
|
|
" -b Apply tests to boost library\n"
|
|
|
|
" -bl Apply tests to boost library with C++ locale\n"
|
|
|
|
#ifdef BOOST_HAS_GRETA
|
|
|
|
" -g Apply tests to GRETA library\n"
|
|
|
|
" -gs Apply tests to GRETA library (in non-recursive mode)\n"
|
|
|
|
#endif
|
|
|
|
#ifdef BOOST_HAS_POSIX
|
|
|
|
" -posix Apply tests to POSIX library\n"
|
|
|
|
#endif
|
|
|
|
#ifdef BOOST_HAS_PCRE
|
|
|
|
" -pcre Apply tests to PCRE library\n"
|
2005-09-18 16:31:56 +00:00
|
|
|
#endif
|
|
|
|
#ifdef BOOST_HAS_XPRESSIVE
|
|
|
|
" -dxpr Apply tests to dynamic xpressive library\n"
|
2003-05-17 11:55:51 +00:00
|
|
|
#endif
|
|
|
|
" -all Apply tests to all libraries\n\n"
|
|
|
|
" test options:\n"
|
|
|
|
" -test-matches Test short matches\n"
|
|
|
|
" -test-code Test c++ code examples\n"
|
|
|
|
" -test-html Test c++ code examples\n"
|
|
|
|
" -test-short-twain Test short searches\n"
|
|
|
|
" -test-long-twain Test long searches\n"
|
|
|
|
" -test-all Test everthing\n";
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
void load_file(std::string& text, const char* file)
|
|
|
|
{
|
|
|
|
std::deque<char> temp_copy;
|
|
|
|
std::ifstream is(file);
|
|
|
|
if(!is.good())
|
|
|
|
{
|
|
|
|
std::string msg("Unable to open file: \"");
|
|
|
|
msg.append(file);
|
|
|
|
msg.append("\"");
|
|
|
|
throw std::runtime_error(msg);
|
|
|
|
}
|
|
|
|
is.seekg(0, std::ios_base::end);
|
|
|
|
std::istream::pos_type pos = is.tellg();
|
|
|
|
is.seekg(0, std::ios_base::beg);
|
|
|
|
text.erase();
|
|
|
|
text.reserve(pos);
|
|
|
|
std::istreambuf_iterator<char> it(is);
|
|
|
|
std::copy(it, std::istreambuf_iterator<char>(), std::back_inserter(text));
|
|
|
|
}
|
|
|
|
|
|
|
|
void print_result(std::ostream& os, double time, double best)
|
|
|
|
{
|
|
|
|
static const char* suffixes[] = {"s", "ms", "us", "ns", "ps", };
|
|
|
|
|
|
|
|
if(time < 0)
|
|
|
|
{
|
|
|
|
os << "<td>NA</td>";
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
double rel = time / best;
|
|
|
|
bool highlight = ((rel > 0) && (rel < 1.1));
|
|
|
|
unsigned suffix = 0;
|
|
|
|
while(time < 0)
|
|
|
|
{
|
|
|
|
time *= 1000;
|
|
|
|
++suffix;
|
|
|
|
}
|
|
|
|
os << "<td>";
|
|
|
|
if(highlight)
|
|
|
|
os << "<font color=\"#008000\">";
|
|
|
|
if(rel <= 1000)
|
|
|
|
os << std::setprecision(3) << rel;
|
|
|
|
else
|
|
|
|
os << (int)rel;
|
|
|
|
os << "<BR>(";
|
|
|
|
if(time <= 1000)
|
|
|
|
os << std::setprecision(3) << time;
|
|
|
|
else
|
|
|
|
os << (int)time;
|
|
|
|
os << suffixes[suffix] << ")";
|
|
|
|
if(highlight)
|
|
|
|
os << "</font>";
|
|
|
|
os << "</td>";
|
|
|
|
}
|
|
|
|
|
|
|
|
std::string html_quote(const std::string& in)
|
|
|
|
{
|
|
|
|
static const boost::regex e("(<)|(>)|(&)|(\")");
|
|
|
|
static const std::string format("(?1<)(?2>)(?3&)(?4")");
|
|
|
|
return regex_replace(in, e, format, boost::match_default | boost::format_all);
|
|
|
|
}
|
|
|
|
|
|
|
|
void output_html_results(bool show_description, const std::string& tagname)
|
|
|
|
{
|
|
|
|
std::stringstream os;
|
|
|
|
if(result_list.size())
|
|
|
|
{
|
|
|
|
//
|
|
|
|
// start by outputting the table header:
|
|
|
|
//
|
|
|
|
os << "<table border=\"1\" cellspacing=\"1\">\n";
|
|
|
|
os << "<tr><td><strong>Expression</strong></td>";
|
|
|
|
if(show_description)
|
|
|
|
os << "<td><strong>Text</strong></td>";
|
|
|
|
#if defined(BOOST_HAS_GRETA)
|
|
|
|
if(time_greta == true)
|
|
|
|
os << "<td><strong>GRETA</strong></td>";
|
|
|
|
if(time_safe_greta == true)
|
|
|
|
os << "<td><strong>GRETA<BR>(non-recursive mode)</strong></td>";
|
|
|
|
#endif
|
|
|
|
if(time_boost == true)
|
|
|
|
os << "<td><strong>Boost</strong></td>";
|
|
|
|
if(time_localised_boost == true)
|
|
|
|
os << "<td><strong>Boost + C++ locale</strong></td>";
|
|
|
|
#if defined(BOOST_HAS_POSIX)
|
|
|
|
if(time_posix == true)
|
|
|
|
os << "<td><strong>POSIX</strong></td>";
|
|
|
|
#endif
|
|
|
|
#ifdef BOOST_HAS_PCRE
|
|
|
|
if(time_pcre == true)
|
|
|
|
os << "<td><strong>PCRE</strong></td>";
|
2005-09-18 09:25:14 +00:00
|
|
|
#endif
|
|
|
|
#ifdef BOOST_HAS_XPRESSIVE
|
|
|
|
if(time_xpressive == true)
|
|
|
|
os << "<td><strong>Dynamic Xpressive</strong></td>";
|
2003-05-17 11:55:51 +00:00
|
|
|
#endif
|
|
|
|
os << "</tr>\n";
|
|
|
|
|
|
|
|
//
|
|
|
|
// Now enumerate through all the test results:
|
|
|
|
//
|
|
|
|
std::list<results>::const_iterator first, last;
|
|
|
|
first = result_list.begin();
|
|
|
|
last = result_list.end();
|
|
|
|
while(first != last)
|
|
|
|
{
|
|
|
|
os << "<tr><td><code>" << html_quote(first->expression) << "</code></td>";
|
|
|
|
if(show_description)
|
|
|
|
os << "<td>" << html_quote(first->description) << "</td>";
|
|
|
|
#if defined(BOOST_HAS_GRETA)
|
|
|
|
if(time_greta == true)
|
|
|
|
{
|
|
|
|
print_result(os, first->greta_time, first->factor);
|
|
|
|
if(first->greta_time > 0)
|
|
|
|
{
|
|
|
|
greta_total += first->greta_time / first->factor;
|
|
|
|
++greta_test_count;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if(time_safe_greta == true)
|
|
|
|
{
|
|
|
|
print_result(os, first->safe_greta_time, first->factor);
|
|
|
|
if(first->safe_greta_time > 0)
|
|
|
|
{
|
|
|
|
safe_greta_total += first->safe_greta_time / first->factor;
|
|
|
|
++safe_greta_test_count;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
#if defined(BOOST_HAS_POSIX)
|
|
|
|
if(time_boost == true)
|
|
|
|
{
|
|
|
|
print_result(os, first->boost_time, first->factor);
|
|
|
|
if(first->boost_time > 0)
|
|
|
|
{
|
|
|
|
boost_total += first->boost_time / first->factor;
|
|
|
|
++boost_test_count;
|
|
|
|
}
|
|
|
|
}
|
2005-09-18 09:25:14 +00:00
|
|
|
#endif
|
2003-05-17 11:55:51 +00:00
|
|
|
if(time_localised_boost == true)
|
|
|
|
{
|
|
|
|
print_result(os, first->localised_boost_time, first->factor);
|
|
|
|
if(first->localised_boost_time > 0)
|
|
|
|
{
|
|
|
|
locale_boost_total += first->localised_boost_time / first->factor;
|
|
|
|
++locale_boost_test_count;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if(time_posix == true)
|
|
|
|
{
|
|
|
|
print_result(os, first->posix_time, first->factor);
|
|
|
|
if(first->posix_time > 0)
|
|
|
|
{
|
|
|
|
posix_total += first->posix_time / first->factor;
|
|
|
|
++posix_test_count;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#if defined(BOOST_HAS_PCRE)
|
|
|
|
if(time_pcre == true)
|
|
|
|
{
|
|
|
|
print_result(os, first->pcre_time, first->factor);
|
|
|
|
if(first->pcre_time > 0)
|
|
|
|
{
|
|
|
|
pcre_total += first->pcre_time / first->factor;
|
|
|
|
++pcre_test_count;
|
|
|
|
}
|
|
|
|
}
|
2005-09-18 09:25:14 +00:00
|
|
|
#endif
|
|
|
|
#if defined(BOOST_HAS_XPRESSIVE)
|
|
|
|
if(time_xpressive == true)
|
|
|
|
{
|
|
|
|
print_result(os, first->xpressive_time, first->factor);
|
|
|
|
if(first->xpressive_time > 0)
|
|
|
|
{
|
|
|
|
xpressive_total += first->xpressive_time / first->factor;
|
|
|
|
++xpressive_test_count;
|
|
|
|
}
|
|
|
|
}
|
2003-05-17 11:55:51 +00:00
|
|
|
#endif
|
|
|
|
os << "</tr>\n";
|
|
|
|
++first;
|
|
|
|
}
|
|
|
|
os << "</table>\n";
|
|
|
|
result_list.clear();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
os << "<P><I>Results not available...</I></P>\n";
|
|
|
|
}
|
|
|
|
|
|
|
|
std::string result = os.str();
|
|
|
|
|
|
|
|
std::string::size_type pos = html_contents.find(tagname);
|
|
|
|
if(pos != std::string::npos)
|
|
|
|
{
|
|
|
|
html_contents.replace(pos, tagname.size(), result);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
std::string get_boost_version()
|
|
|
|
{
|
|
|
|
std::stringstream os;
|
|
|
|
os << (BOOST_VERSION / 100000) << '.' << ((BOOST_VERSION / 100) % 1000) << '.' << (BOOST_VERSION % 100);
|
|
|
|
return os.str();
|
|
|
|
}
|
|
|
|
|
|
|
|
std::string get_averages_table()
|
|
|
|
{
|
|
|
|
std::stringstream os;
|
|
|
|
//
|
|
|
|
// start by outputting the table header:
|
|
|
|
//
|
|
|
|
os << "<table border=\"1\" cellspacing=\"1\">\n";
|
|
|
|
os << "<tr>";
|
|
|
|
#if defined(BOOST_HAS_GRETA)
|
|
|
|
if(time_greta == true)
|
|
|
|
{
|
|
|
|
os << "<td><strong>GRETA</strong></td>";
|
|
|
|
}
|
|
|
|
if(time_safe_greta == true)
|
|
|
|
{
|
|
|
|
os << "<td><strong>GRETA<BR>(non-recursive mode)</strong></td>";
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif
|
|
|
|
if(time_boost == true)
|
|
|
|
{
|
|
|
|
os << "<td><strong>Boost</strong></td>";
|
|
|
|
}
|
|
|
|
if(time_localised_boost == true)
|
|
|
|
{
|
|
|
|
os << "<td><strong>Boost + C++ locale</strong></td>";
|
|
|
|
}
|
|
|
|
#if defined(BOOST_HAS_POSIX)
|
|
|
|
if(time_posix == true)
|
|
|
|
{
|
|
|
|
os << "<td><strong>POSIX</strong></td>";
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
#ifdef BOOST_HAS_PCRE
|
|
|
|
if(time_pcre == true)
|
|
|
|
{
|
|
|
|
os << "<td><strong>PCRE</strong></td>";
|
|
|
|
}
|
2005-09-18 09:25:14 +00:00
|
|
|
#endif
|
|
|
|
#ifdef BOOST_HAS_XPRESSIVE
|
|
|
|
if(time_xpressive == true)
|
|
|
|
{
|
|
|
|
os << "<td><strong>Dynamic Xpressive</strong></td>";
|
|
|
|
}
|
2003-05-17 11:55:51 +00:00
|
|
|
#endif
|
|
|
|
os << "</tr>\n";
|
|
|
|
|
|
|
|
//
|
|
|
|
// Now enumerate through all averages:
|
|
|
|
//
|
|
|
|
os << "<tr>";
|
|
|
|
#if defined(BOOST_HAS_GRETA)
|
|
|
|
if(time_greta == true)
|
|
|
|
os << "<td>" << (greta_total / greta_test_count) << "</td>\n";
|
|
|
|
if(time_safe_greta == true)
|
|
|
|
os << "<td>" << (safe_greta_total / safe_greta_test_count) << "</td>\n";
|
|
|
|
#endif
|
|
|
|
#if defined(BOOST_HAS_POSIX)
|
|
|
|
if(time_boost == true)
|
|
|
|
os << "<td>" << (boost_total / boost_test_count) << "</td>\n";
|
2005-09-18 09:25:14 +00:00
|
|
|
#endif
|
2003-05-17 11:55:51 +00:00
|
|
|
if(time_localised_boost == true)
|
|
|
|
os << "<td>" << (locale_boost_total / locale_boost_test_count) << "</td>\n";
|
|
|
|
if(time_posix == true)
|
|
|
|
os << "<td>" << (posix_total / posix_test_count) << "</td>\n";
|
|
|
|
#if defined(BOOST_HAS_PCRE)
|
|
|
|
if(time_pcre == true)
|
|
|
|
os << "<td>" << (pcre_total / pcre_test_count) << "</td>\n";
|
2005-09-18 09:25:14 +00:00
|
|
|
#endif
|
|
|
|
#if defined(BOOST_HAS_XPRESSIVE)
|
|
|
|
if(time_xpressive == true)
|
|
|
|
os << "<td>" << (xpressive_total / xpressive_test_count) << "</td>\n";
|
2003-05-17 11:55:51 +00:00
|
|
|
#endif
|
|
|
|
os << "</tr>\n";
|
|
|
|
os << "</table>\n";
|
|
|
|
return os.str();
|
|
|
|
}
|
|
|
|
|
|
|
|
void output_final_html()
|
|
|
|
{
|
|
|
|
if(html_out_file.size())
|
|
|
|
{
|
|
|
|
//
|
|
|
|
// start with search and replace ops:
|
|
|
|
//
|
|
|
|
std::string::size_type pos;
|
|
|
|
pos = html_contents.find("%compiler%");
|
|
|
|
if(pos != std::string::npos)
|
|
|
|
{
|
|
|
|
html_contents.replace(pos, 10, BOOST_COMPILER);
|
|
|
|
}
|
|
|
|
pos = html_contents.find("%library%");
|
|
|
|
if(pos != std::string::npos)
|
|
|
|
{
|
|
|
|
html_contents.replace(pos, 9, BOOST_STDLIB);
|
|
|
|
}
|
|
|
|
pos = html_contents.find("%os%");
|
|
|
|
if(pos != std::string::npos)
|
|
|
|
{
|
|
|
|
html_contents.replace(pos, 4, BOOST_PLATFORM);
|
|
|
|
}
|
|
|
|
pos = html_contents.find("%boost%");
|
|
|
|
if(pos != std::string::npos)
|
|
|
|
{
|
|
|
|
html_contents.replace(pos, 7, get_boost_version());
|
|
|
|
}
|
|
|
|
pos = html_contents.find("%pcre%");
|
|
|
|
if(pos != std::string::npos)
|
|
|
|
{
|
|
|
|
#ifdef PCRE_MINOR
|
|
|
|
html_contents.replace(pos, 6, BOOST_STRINGIZE(PCRE_MAJOR.PCRE_MINOR));
|
|
|
|
#else
|
|
|
|
html_contents.replace(pos, 6, "N/A");
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
pos = html_contents.find("%averages%");
|
|
|
|
if(pos != std::string::npos)
|
|
|
|
{
|
|
|
|
html_contents.replace(pos, 10, get_averages_table());
|
|
|
|
}
|
|
|
|
//
|
|
|
|
// now right the output to file:
|
|
|
|
//
|
|
|
|
std::ofstream os(html_out_file.c_str());
|
|
|
|
os << html_contents;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
std::cout << html_contents;
|
|
|
|
}
|
2003-09-30 13:02:51 +00:00
|
|
|
}
|