• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //  (C) Copyright Eric Niebler 2006.
2 //  Distributed under the Boost
3 //  Software License, Version 1.0. (See accompanying file
4 //  LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
5 
6 #include <iostream>
7 #include <iomanip>
8 #include <fstream>
9 #include <deque>
10 #include <sstream>
11 #include <stdexcept>
12 #include <iterator>
13 #include "./regex_comparison.hpp"
14 
15 //
16 // globals:
17 //
18 bool time_boost = false;
19 bool time_greta = false;
20 bool time_safe_greta = false;
21 bool time_dynamic_xpressive = false;
22 bool time_static_xpressive = false;
23 //bool time_posix = false;
24 //bool time_pcre = false;
25 
26 bool test_matches = false;
27 bool test_short_twain = false;
28 bool test_long_twain = false;
29 
30 std::string xml_out_file;
31 std::string xml_contents;
32 std::list<results> result_list;
33 
handle_argument(const std::string & what)34 int handle_argument(const std::string& what)
35 {
36     if(what == "-b")
37         time_boost = true;
38     else if(what == "-g")
39         time_greta = true;
40     else if(what == "-gs")
41         time_safe_greta = true;
42     else if(what == "-dx")
43         time_dynamic_xpressive = true;
44     else if(what == "-sx")
45         time_static_xpressive = true;
46     //else if(what == "-posix")
47     //   time_posix = true;
48     //else if(what == "-pcre")
49     //   time_pcre = true;
50     else if(what == "-all")
51     {
52         time_boost = true;
53         time_greta = true;
54         time_safe_greta = true;
55         time_dynamic_xpressive = true;
56         time_static_xpressive = true;
57         //time_posix = true;
58         //time_pcre = true;
59     }
60     else if(what == "-test-matches")
61         test_matches = true;
62     else if(what == "-test-short-twain")
63         test_short_twain = true;
64     else if(what == "-test-long-twain")
65         test_long_twain = true;
66     else if(what == "-test-all")
67     {
68         test_matches = true;
69         test_short_twain = true;
70         test_long_twain = true;
71     }
72     else if((what == "-h") || (what == "--help"))
73         return show_usage();
74     else if((what[0] == '-') || (what[0] == '/'))
75     {
76         std::cerr << "Unknown argument: \"" << what << "\"" << std::endl;
77         return 1;
78     }
79     else if(xml_out_file.size() == 0)
80     {
81         xml_out_file = what;
82     }
83     else
84     {
85         std::cerr << "Unexpected argument: \"" << what << "\"" << std::endl;
86         return 1;
87     }
88     return 0;
89 }
90 
show_usage()91 int show_usage()
92 {
93     std::cout <<
94         "Usage\n"
95         "xprperf [-h] [library options] [test options] [xml_output_file]\n"
96         "   -h        Show help\n\n"
97         "   library options:\n"
98         "      -b     Apply tests to boost library\n"
99         //"      -ba    Apply tests to boost library with a custom allocator\n"
100         //"      -be    Apply tests to experimental boost library\n"
101         //"      -g     Apply tests to GRETA library\n"
102         //"      -gs    Apply tests to GRETA library (in non-recursive mode)\n"
103         "      -dx    Apply tests to dynamic xpressive library\n"
104         "      -sx    Apply tests to static xpressive library\n"
105         //"      -posix Apply tests to POSIX library\n"
106         //"      -pcre  Apply tests to PCRE library\n"
107         "      -all   Apply tests to all libraries\n\n"
108         "   test options:\n"
109         "      -test-matches      Test short matches\n"
110         "      -test-short-twain  Test short searches\n"
111         "      -test-long-twain   Test long searches\n"
112         "      -test-all          Test everthing\n";
113     return 1;
114 }
115 
load_file(std::string & text,const char * file)116 void load_file(std::string& text, const char* file)
117 {
118     std::deque<char> temp_copy;
119     std::ifstream is(file);
120     if(!is.good())
121     {
122         std::string msg("Unable to open file: \"");
123         msg.append(file);
124         msg.append("\"");
125         throw std::runtime_error(msg);
126     }
127     std::istreambuf_iterator<char> it(is);
128     std::copy(it, std::istreambuf_iterator<char>(), std::back_inserter(temp_copy));
129     text.erase();
130     text.reserve(temp_copy.size());
131     text.append(temp_copy.begin(), temp_copy.end());
132 }
133 
134 struct xml_double
135 {
136     double d_;
xml_doublexml_double137     xml_double( double d ) : d_(d) {}
operator <<(std::ostream & out,xml_double const & xd)138     friend std::ostream & operator<<( std::ostream & out, xml_double const & xd )
139     {
140         std::ostringstream tmp;
141         tmp << std::setprecision(out.precision()) << xd.d_;
142         std::string str = tmp.str();
143         std::string::size_type i = str.find( '-' );
144         if( i != std::string::npos )
145             str.replace( i, 1, "&#8209;" );
146         return out << str;
147     }
148 };
149 
print_result(std::ostream & os,double time,double best)150 void print_result(std::ostream& os, double time, double best)
151 {
152     static const char* suffixes[] = {"s", "ms", "us", "ns", "ps", };
153 
154     if(time < 0)
155     {
156         os << "<entry>NA</entry>";
157         return;
158     }
159     double rel = time / best;
160     bool highlight = ((rel > 0) && (rel < 1.1));
161     unsigned suffix = 0;
162     while(time < 0)
163     {
164         time *= 1000;
165         ++suffix;
166     }
167     os << "<entry>";
168     if(highlight)
169         os << "<phrase role=\"highlight\">";
170     if(rel <= 1000)
171         os << std::setprecision(3) << xml_double(rel);
172     else
173         os << (int)rel;
174     os << "<para/>(";
175     if(time <= 1000)
176         os << std::setprecision(3) << xml_double(time);
177     else
178         os << (int)time;
179     os << suffixes[suffix] << ")";
180     if(highlight)
181         os << "</phrase>";
182     os << "</entry>";
183 }
184 
output_xml_results(bool show_description,const std::string & title,const std::string & filename)185 void output_xml_results(bool show_description, const std::string& title, const std::string& filename)
186 {
187     std::stringstream os;
188     // Generate the copyright and license on the output file
189     os << "<!--\n"
190           " Copyright 2004 Eric Niebler.\n"
191           "\n"
192           " Distributed under the Boost Software License, Version 1.0.\n"
193           " (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)\n"
194           "-->\n";
195 
196     if(result_list.size())
197     {
198         // calculate the number of columns in this table
199         int num_cols = 1 + show_description + time_greta + time_safe_greta
200             + time_dynamic_xpressive + time_static_xpressive + time_boost;
201 
202         //
203         // start by outputting the table header:
204         //
205         os << "<informaltable frame=\"all\">\n";
206         os << "<bridgehead renderas=\"sect4\">"
207               "<phrase role=\"table-title\">" << title << "</phrase>"
208               "</bridgehead>\n";
209         os << "<tgroup cols=\"" << num_cols << "\">\n";
210         os << "<thead>\n";
211         os << "<row>\n";
212 
213         if(time_static_xpressive)   os << "<entry>static xpressive</entry>";
214         if(time_dynamic_xpressive)  os << "<entry>dynamic xpressive</entry>";
215         if(time_greta)              os << "<entry>GRETA</entry>";
216         if(time_safe_greta)         os << "<entry>GRETA<para/>(non-recursive mode)</entry>";
217         if(time_boost)              os << "<entry>Boost</entry>";
218         //if(time_posix)              os << "<entry>POSIX</entry>";
219         //if(time_pcre)               os << "<entry>PCRE</entry>";
220         if(show_description)        os << "<entry>Text</entry>";
221         os << "<entry>Expression</entry>";
222         os << "\n</row>\n";
223         os << "</thead>\n";
224         os << "<tbody>\n";
225 
226         //
227         // Now enumerate through all the test results:
228         //
229         std::list<results>::const_iterator first, last;
230         first = result_list.begin();
231         last = result_list.end();
232         while(first != last)
233         {
234             os << "<row>\n";
235             if(time_static_xpressive)   print_result(os, first->static_xpressive_time, first->factor);
236             if(time_dynamic_xpressive)  print_result(os, first->dynamic_xpressive_time, first->factor);
237             if(time_greta)              print_result(os, first->greta_time, first->factor);
238             if(time_safe_greta)         print_result(os, first->safe_greta_time, first->factor);
239             if(time_boost)              print_result(os, first->boost_time, first->factor);
240             //if(time_posix)              print_result(os, first->posix_time, first->factor);
241             //if(time_pcre)               print_result(os, first->pcre_time, first->factor);
242             if(show_description)        os << "<entry>" << first->description << "</entry>";
243             os << "<entry><literal>" << first->expression << "</literal></entry>";
244             os << "\n</row>\n";
245             ++first;
246         }
247 
248         os << "</tbody>\n"
249               "</tgroup>\n"
250               "</informaltable>\n";
251 
252         result_list.clear();
253     }
254     else
255     {
256         os << "<para><emphasis>Results not available...</emphasis></para>\n";
257     }
258 
259     std::ofstream file(filename.c_str());
260     file << os.str();
261 }
262