127b27ec6Sopenharmony_ci/* 227b27ec6Sopenharmony_ciCopyright (c) 2016-present, Przemyslaw Skibinski 327b27ec6Sopenharmony_ciAll rights reserved. 427b27ec6Sopenharmony_ci 527b27ec6Sopenharmony_ciBSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php) 627b27ec6Sopenharmony_ci 727b27ec6Sopenharmony_ciRedistribution and use in source and binary forms, with or without 827b27ec6Sopenharmony_cimodification, are permitted provided that the following conditions are 927b27ec6Sopenharmony_cimet: 1027b27ec6Sopenharmony_ci 1127b27ec6Sopenharmony_ci* Redistributions of source code must retain the above copyright 1227b27ec6Sopenharmony_cinotice, this list of conditions and the following disclaimer. 1327b27ec6Sopenharmony_ci* Redistributions in binary form must reproduce the above 1427b27ec6Sopenharmony_cicopyright notice, this list of conditions and the following disclaimer 1527b27ec6Sopenharmony_ciin the documentation and/or other materials provided with the 1627b27ec6Sopenharmony_cidistribution. 1727b27ec6Sopenharmony_ci 1827b27ec6Sopenharmony_ciTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 1927b27ec6Sopenharmony_ci"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 2027b27ec6Sopenharmony_ciLIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 2127b27ec6Sopenharmony_ciA PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 2227b27ec6Sopenharmony_ciOWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 2327b27ec6Sopenharmony_ciSPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 2427b27ec6Sopenharmony_ciLIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 2527b27ec6Sopenharmony_ciDATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 2627b27ec6Sopenharmony_ciTHEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 2727b27ec6Sopenharmony_ci(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 2827b27ec6Sopenharmony_ciOF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 2927b27ec6Sopenharmony_ci 3027b27ec6Sopenharmony_ciYou can contact the author at : 3127b27ec6Sopenharmony_ci- LZ4 homepage : http://www.lz4.org 3227b27ec6Sopenharmony_ci- LZ4 source repository : https://github.com/lz4/lz4 3327b27ec6Sopenharmony_ci*/ 3427b27ec6Sopenharmony_ci 3527b27ec6Sopenharmony_ci#include <iostream> 3627b27ec6Sopenharmony_ci#include <fstream> 3727b27ec6Sopenharmony_ci#include <sstream> 3827b27ec6Sopenharmony_ci#include <vector> 3927b27ec6Sopenharmony_ciusing namespace std; 4027b27ec6Sopenharmony_ci 4127b27ec6Sopenharmony_ci 4227b27ec6Sopenharmony_ci/* trim string at the beginning and at the end */ 4327b27ec6Sopenharmony_civoid trim(string& s, string characters) 4427b27ec6Sopenharmony_ci{ 4527b27ec6Sopenharmony_ci size_t p = s.find_first_not_of(characters); 4627b27ec6Sopenharmony_ci s.erase(0, p); 4727b27ec6Sopenharmony_ci 4827b27ec6Sopenharmony_ci p = s.find_last_not_of(characters); 4927b27ec6Sopenharmony_ci if (string::npos != p) 5027b27ec6Sopenharmony_ci s.erase(p+1); 5127b27ec6Sopenharmony_ci} 5227b27ec6Sopenharmony_ci 5327b27ec6Sopenharmony_ci 5427b27ec6Sopenharmony_ci/* trim C++ style comments */ 5527b27ec6Sopenharmony_civoid trim_comments(string &s) 5627b27ec6Sopenharmony_ci{ 5727b27ec6Sopenharmony_ci size_t spos, epos; 5827b27ec6Sopenharmony_ci 5927b27ec6Sopenharmony_ci spos = s.find("/*"); 6027b27ec6Sopenharmony_ci epos = s.find("*/"); 6127b27ec6Sopenharmony_ci s = s.substr(spos+3, epos-(spos+3)); 6227b27ec6Sopenharmony_ci} 6327b27ec6Sopenharmony_ci 6427b27ec6Sopenharmony_ci 6527b27ec6Sopenharmony_ci/* get lines until a given terminator */ 6627b27ec6Sopenharmony_civector<string> get_lines(vector<string>& input, int& linenum, string terminator) 6727b27ec6Sopenharmony_ci{ 6827b27ec6Sopenharmony_ci vector<string> out; 6927b27ec6Sopenharmony_ci string line; 7027b27ec6Sopenharmony_ci 7127b27ec6Sopenharmony_ci while ((size_t)linenum < input.size()) { 7227b27ec6Sopenharmony_ci line = input[linenum]; 7327b27ec6Sopenharmony_ci 7427b27ec6Sopenharmony_ci if (terminator.empty() && line.empty()) { linenum--; break; } 7527b27ec6Sopenharmony_ci 7627b27ec6Sopenharmony_ci size_t const epos = line.find(terminator); 7727b27ec6Sopenharmony_ci if (!terminator.empty() && epos!=string::npos) { 7827b27ec6Sopenharmony_ci out.push_back(line); 7927b27ec6Sopenharmony_ci break; 8027b27ec6Sopenharmony_ci } 8127b27ec6Sopenharmony_ci out.push_back(line); 8227b27ec6Sopenharmony_ci linenum++; 8327b27ec6Sopenharmony_ci } 8427b27ec6Sopenharmony_ci return out; 8527b27ec6Sopenharmony_ci} 8627b27ec6Sopenharmony_ci 8727b27ec6Sopenharmony_ci 8827b27ec6Sopenharmony_ci/* print line with LZ4LIB_API removed and C++ comments not bold */ 8927b27ec6Sopenharmony_civoid print_line(stringstream &sout, string line) 9027b27ec6Sopenharmony_ci{ 9127b27ec6Sopenharmony_ci size_t spos, epos; 9227b27ec6Sopenharmony_ci 9327b27ec6Sopenharmony_ci if (line.substr(0,11) == "LZ4LIB_API ") line = line.substr(11); 9427b27ec6Sopenharmony_ci if (line.substr(0,12) == "LZ4FLIB_API ") line = line.substr(12); 9527b27ec6Sopenharmony_ci spos = line.find("/*"); 9627b27ec6Sopenharmony_ci epos = line.find("*/"); 9727b27ec6Sopenharmony_ci if (spos!=string::npos && epos!=string::npos) { 9827b27ec6Sopenharmony_ci sout << line.substr(0, spos); 9927b27ec6Sopenharmony_ci sout << "</b>" << line.substr(spos) << "<b>" << '\n'; 10027b27ec6Sopenharmony_ci } else { 10127b27ec6Sopenharmony_ci sout << line << '\n'; 10227b27ec6Sopenharmony_ci } 10327b27ec6Sopenharmony_ci} 10427b27ec6Sopenharmony_ci 10527b27ec6Sopenharmony_ci 10627b27ec6Sopenharmony_ciint main(int argc, char *argv[]) { 10727b27ec6Sopenharmony_ci char exclam; 10827b27ec6Sopenharmony_ci int linenum, chapter = 1; 10927b27ec6Sopenharmony_ci vector<string> input, lines, comments, chapters; 11027b27ec6Sopenharmony_ci string line, version; 11127b27ec6Sopenharmony_ci size_t spos, l; 11227b27ec6Sopenharmony_ci stringstream sout; 11327b27ec6Sopenharmony_ci ifstream istream; 11427b27ec6Sopenharmony_ci ofstream ostream; 11527b27ec6Sopenharmony_ci 11627b27ec6Sopenharmony_ci if (argc < 4) { 11727b27ec6Sopenharmony_ci cout << "usage: " << argv[0] << " [lz4_version] [input_file] [output_html]" << endl; 11827b27ec6Sopenharmony_ci return 1; 11927b27ec6Sopenharmony_ci } 12027b27ec6Sopenharmony_ci 12127b27ec6Sopenharmony_ci version = string(argv[1]) + " Manual"; 12227b27ec6Sopenharmony_ci 12327b27ec6Sopenharmony_ci istream.open(argv[2], ifstream::in); 12427b27ec6Sopenharmony_ci if (!istream.is_open()) { 12527b27ec6Sopenharmony_ci cout << "Error opening file " << argv[2] << endl; 12627b27ec6Sopenharmony_ci return 1; 12727b27ec6Sopenharmony_ci } 12827b27ec6Sopenharmony_ci 12927b27ec6Sopenharmony_ci ostream.open(argv[3], ifstream::out); 13027b27ec6Sopenharmony_ci if (!ostream.is_open()) { 13127b27ec6Sopenharmony_ci cout << "Error opening file " << argv[3] << endl; 13227b27ec6Sopenharmony_ci return 1; 13327b27ec6Sopenharmony_ci } 13427b27ec6Sopenharmony_ci 13527b27ec6Sopenharmony_ci while (getline(istream, line)) { 13627b27ec6Sopenharmony_ci input.push_back(line); 13727b27ec6Sopenharmony_ci } 13827b27ec6Sopenharmony_ci 13927b27ec6Sopenharmony_ci for (linenum=0; (size_t)linenum < input.size(); linenum++) { 14027b27ec6Sopenharmony_ci line = input[linenum]; 14127b27ec6Sopenharmony_ci 14227b27ec6Sopenharmony_ci /* typedefs are detected and included even if uncommented */ 14327b27ec6Sopenharmony_ci if (line.substr(0,7) == "typedef" && line.find("{")!=string::npos) { 14427b27ec6Sopenharmony_ci lines = get_lines(input, linenum, "}"); 14527b27ec6Sopenharmony_ci sout << "<pre><b>"; 14627b27ec6Sopenharmony_ci for (l=0; l<lines.size(); l++) { 14727b27ec6Sopenharmony_ci print_line(sout, lines[l]); 14827b27ec6Sopenharmony_ci } 14927b27ec6Sopenharmony_ci sout << "</b></pre><BR>" << endl; 15027b27ec6Sopenharmony_ci continue; 15127b27ec6Sopenharmony_ci } 15227b27ec6Sopenharmony_ci 15327b27ec6Sopenharmony_ci /* comments of type / * * < and / * ! < are detected, and only function declaration is highlighted (bold) */ 15427b27ec6Sopenharmony_ci if ((line.find("/**<")!=string::npos || line.find("/*!<")!=string::npos) 15527b27ec6Sopenharmony_ci && line.find("*/")!=string::npos) { 15627b27ec6Sopenharmony_ci sout << "<pre><b>"; 15727b27ec6Sopenharmony_ci print_line(sout, line); 15827b27ec6Sopenharmony_ci sout << "</b></pre><BR>" << endl; 15927b27ec6Sopenharmony_ci continue; 16027b27ec6Sopenharmony_ci } 16127b27ec6Sopenharmony_ci 16227b27ec6Sopenharmony_ci spos = line.find("/**="); 16327b27ec6Sopenharmony_ci if (spos==string::npos) { 16427b27ec6Sopenharmony_ci spos = line.find("/*!"); 16527b27ec6Sopenharmony_ci if (spos==string::npos) 16627b27ec6Sopenharmony_ci spos = line.find("/**"); 16727b27ec6Sopenharmony_ci if (spos==string::npos) 16827b27ec6Sopenharmony_ci spos = line.find("/*-"); 16927b27ec6Sopenharmony_ci if (spos==string::npos) 17027b27ec6Sopenharmony_ci spos = line.find("/*="); 17127b27ec6Sopenharmony_ci if (spos==string::npos) 17227b27ec6Sopenharmony_ci continue; 17327b27ec6Sopenharmony_ci exclam = line[spos+2]; 17427b27ec6Sopenharmony_ci } 17527b27ec6Sopenharmony_ci else exclam = '='; 17627b27ec6Sopenharmony_ci 17727b27ec6Sopenharmony_ci comments = get_lines(input, linenum, "*/"); 17827b27ec6Sopenharmony_ci if (!comments.empty()) comments[0] = line.substr(spos+3); 17927b27ec6Sopenharmony_ci if (!comments.empty()) 18027b27ec6Sopenharmony_ci comments[comments.size()-1] = comments[comments.size()-1].substr(0, comments[comments.size()-1].find("*/")); 18127b27ec6Sopenharmony_ci for (l=0; l<comments.size(); l++) { 18227b27ec6Sopenharmony_ci if (comments[l].compare(0, 2, " *") == 0) 18327b27ec6Sopenharmony_ci comments[l] = comments[l].substr(2); 18427b27ec6Sopenharmony_ci else if (comments[l].compare(0, 3, " *") == 0) 18527b27ec6Sopenharmony_ci comments[l] = comments[l].substr(3); 18627b27ec6Sopenharmony_ci trim(comments[l], "*-="); 18727b27ec6Sopenharmony_ci } 18827b27ec6Sopenharmony_ci while (!comments.empty() && comments[comments.size()-1].empty()) comments.pop_back(); // remove empty line at the end 18927b27ec6Sopenharmony_ci while (!comments.empty() && comments[0].empty()) comments.erase(comments.begin()); // remove empty line at the start 19027b27ec6Sopenharmony_ci 19127b27ec6Sopenharmony_ci /* comments of type / * ! mean: this is a function declaration; switch comments with declarations */ 19227b27ec6Sopenharmony_ci if (exclam == '!') { 19327b27ec6Sopenharmony_ci if (!comments.empty()) comments.erase(comments.begin()); /* remove first line like "LZ4_XXX() :" */ 19427b27ec6Sopenharmony_ci linenum++; 19527b27ec6Sopenharmony_ci lines = get_lines(input, linenum, ""); 19627b27ec6Sopenharmony_ci 19727b27ec6Sopenharmony_ci sout << "<pre><b>"; 19827b27ec6Sopenharmony_ci for (l=0; l<lines.size(); l++) { 19927b27ec6Sopenharmony_ci print_line(sout, lines[l]); 20027b27ec6Sopenharmony_ci } 20127b27ec6Sopenharmony_ci sout << "</b><p>"; 20227b27ec6Sopenharmony_ci for (l=0; l<comments.size(); l++) { 20327b27ec6Sopenharmony_ci print_line(sout, comments[l]); 20427b27ec6Sopenharmony_ci } 20527b27ec6Sopenharmony_ci sout << "</p></pre><BR>" << endl << endl; 20627b27ec6Sopenharmony_ci } else if (exclam == '=') { /* comments of type / * = and / * * = mean: use a <H3> header and show also all functions until first empty line */ 20727b27ec6Sopenharmony_ci trim(comments[0], " "); 20827b27ec6Sopenharmony_ci sout << "<h3>" << comments[0] << "</h3><pre>"; 20927b27ec6Sopenharmony_ci for (l=1; l<comments.size(); l++) { 21027b27ec6Sopenharmony_ci print_line(sout, comments[l]); 21127b27ec6Sopenharmony_ci } 21227b27ec6Sopenharmony_ci sout << "</pre><b><pre>"; 21327b27ec6Sopenharmony_ci lines = get_lines(input, ++linenum, ""); 21427b27ec6Sopenharmony_ci for (l=0; l<lines.size(); l++) { 21527b27ec6Sopenharmony_ci print_line(sout, lines[l]); 21627b27ec6Sopenharmony_ci } 21727b27ec6Sopenharmony_ci sout << "</pre></b><BR>" << endl; 21827b27ec6Sopenharmony_ci } else { /* comments of type / * * and / * - mean: this is a comment; use a <H2> header for the first line */ 21927b27ec6Sopenharmony_ci if (comments.empty()) continue; 22027b27ec6Sopenharmony_ci 22127b27ec6Sopenharmony_ci trim(comments[0], " "); 22227b27ec6Sopenharmony_ci sout << "<a name=\"Chapter" << chapter << "\"></a><h2>" << comments[0] << "</h2><pre>"; 22327b27ec6Sopenharmony_ci chapters.push_back(comments[0]); 22427b27ec6Sopenharmony_ci chapter++; 22527b27ec6Sopenharmony_ci 22627b27ec6Sopenharmony_ci for (l=1; l<comments.size(); l++) { 22727b27ec6Sopenharmony_ci print_line(sout, comments[l]); 22827b27ec6Sopenharmony_ci } 22927b27ec6Sopenharmony_ci if (comments.size() > 1) 23027b27ec6Sopenharmony_ci sout << "<BR></pre>" << endl << endl; 23127b27ec6Sopenharmony_ci else 23227b27ec6Sopenharmony_ci sout << "</pre>" << endl << endl; 23327b27ec6Sopenharmony_ci } 23427b27ec6Sopenharmony_ci } 23527b27ec6Sopenharmony_ci 23627b27ec6Sopenharmony_ci ostream << "<html>\n<head>\n<meta http-equiv=\"Content-Type\" content=\"text/html; charset=ISO-8859-1\">\n<title>" << version << "</title>\n</head>\n<body>" << endl; 23727b27ec6Sopenharmony_ci ostream << "<h1>" << version << "</h1>\n"; 23827b27ec6Sopenharmony_ci 23927b27ec6Sopenharmony_ci ostream << "<hr>\n<a name=\"Contents\"></a><h2>Contents</h2>\n<ol>\n"; 24027b27ec6Sopenharmony_ci for (size_t i=0; i<chapters.size(); i++) 24127b27ec6Sopenharmony_ci ostream << "<li><a href=\"#Chapter" << i+1 << "\">" << chapters[i].c_str() << "</a></li>\n"; 24227b27ec6Sopenharmony_ci ostream << "</ol>\n<hr>\n"; 24327b27ec6Sopenharmony_ci 24427b27ec6Sopenharmony_ci ostream << sout.str(); 24527b27ec6Sopenharmony_ci ostream << "</html>" << endl << "</body>" << endl; 24627b27ec6Sopenharmony_ci 24727b27ec6Sopenharmony_ci return 0; 24827b27ec6Sopenharmony_ci} 249