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