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 | |
---|
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 | |
---|
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 | |
---|
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_; |
---|
137 | xml_double( double d ) : d_(d) {} |
---|
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, "‑" ); |
---|
146 | return out << str; |
---|
147 | } |
---|
148 | }; |
---|
149 | |
---|
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 | |
---|
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 | } |
---|