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