| 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 | } | 
|---|