LCOV - code coverage report
Current view: top level - tests - json_to_string.cpp (source / functions) Hit Total Coverage
Test: coverage.info Lines: 81 118 68.6 %
Date: 2023-07-29 22:00:24 Functions: 2 3 66.7 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : // Copyright (c) 2011-2023  Made to Order Software Corp.  All Rights Reserved
       2             : //
       3             : // https://snapwebsites.org/project/as2js
       4             : // contact@m2osw.com
       5             : //
       6             : // This program is free software: you can redistribute it and/or modify
       7             : // it under the terms of the GNU General Public License as published by
       8             : // the Free Software Foundation, either version 3 of the License, or
       9             : // (at your option) any later version.
      10             : //
      11             : // This program is distributed in the hope that it will be useful,
      12             : // but WITHOUT ANY WARRANTY; without even the implied warranty of
      13             : // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      14             : // GNU General Public License for more details.
      15             : //
      16             : // You should have received a copy of the GNU General Public License
      17             : // along with this program.  If not, see <https://www.gnu.org/licenses/>.
      18             : 
      19             : // self
      20             : //
      21             : #include    <tests/license.h>
      22             : 
      23             : 
      24             : // snapdev
      25             : //
      26             : #include    <snapdev/pathinfo.h>
      27             : #include    <snapdev/stringize.h>
      28             : 
      29             : 
      30             : // as2js
      31             : //
      32             : #include    <as2js/json.h>
      33             : #include    <as2js/message.h>
      34             : #include    <as2js/version.h>
      35             : 
      36             : 
      37             : // C
      38             : //
      39             : #include    <string.h>
      40             : #include    <unistd.h>
      41             : 
      42             : 
      43             : // last include
      44             : //
      45             : #include    <snapdev/poison.h>
      46             : 
      47             : 
      48             : 
      49             : 
      50             : 
      51             : class messages
      52             :     : public as2js::message_callback
      53             : {
      54             : public:
      55          32 :     messages()
      56          32 :     {
      57          32 :         as2js::set_message_callback(this);
      58          32 :     }
      59             : 
      60             :     // implementation of the output
      61           0 :     virtual void output(
      62             :           as2js::message_level_t message_level
      63             :         , as2js::err_code_t error_code
      64             :         , as2js::position const & pos
      65             :         , std::string const & message)
      66             :     {
      67           0 :         std::cerr << "error:" << static_cast<int>(message_level)
      68           0 :                        << ":" << static_cast<int>(error_code)
      69           0 :                        << ":" << pos
      70           0 :                        << ":" << message << std::endl;
      71           0 :     }
      72             : };
      73             : 
      74             : 
      75             : 
      76             : #pragma GCC diagnostic ignored "-Wpedantic"
      77          32 : int main(int argc, char **argv)
      78             : {
      79          32 :     int err(0);
      80          32 :     bool newlines(false);
      81          32 :     bool keep_comments(false);
      82         224 :     std::string const progname(snapdev::pathinfo::basename(std::string(argv[0])));
      83          32 :     std::string output_filename;
      84          32 :     std::vector<std::string> input_filenames;
      85             : 
      86         128 :     for(int i(1); i < argc; ++i)
      87             :     {
      88          96 :         if(strcmp(argv[i], "--license") == 0)
      89             :         {
      90           0 :             std::cout << as2js_tools::license;
      91           0 :             return 1;
      92             :         }
      93          96 :         if(strcmp(argv[i], "--help") == 0
      94          96 :         || strcmp(argv[i], "-h") == 0)
      95             :         {
      96             :             std::cout << "Usage: " << progname << " [--opt ...] <input> ...\n"
      97             :                 "where --opt is one of:\n"
      98             :                 "  --copyright               print this tool copyright notice\n"
      99             :                 "  --help | -h               print out the help screen\n"
     100             :                 "  --license                 show the license\n"
     101             :                 "  --keep-comments           keep comments in output\n"
     102             :                 "  --newlines                insert newlines in the output\n"
     103             :                 "  --version                 print the version of the as2js project\n"
     104           0 :                 "  --output | -o <filename>  the name of the output file\n"
     105             :                 ;
     106           0 :             return 1;
     107             :         }
     108          96 :         if(strcmp(argv[i], "--version") == 0)
     109             :         {
     110           0 :             std::cout << AS2JS_VERSION_STRING << std::endl;
     111           0 :             return 1;
     112             :         }
     113          96 :         if(strcmp(argv[i], "--copyright") == 0)
     114             :         {
     115             :             std::cout << "Copyright (c) 2005-"
     116             :                            SNAPDEV_STRINGIZE(UTC_BUILD_YEAR)
     117           0 :                            " by Made to Order Software Corporation, All Rights Reserved";
     118           0 :             return 1;
     119             :         }
     120             : 
     121          96 :         if(strcmp(argv[i], "--newlines") == 0)
     122             :         {
     123          32 :             newlines = true;
     124             :         }
     125          64 :         else if(strcmp(argv[i], "--keep-comments") == 0)
     126             :         {
     127           0 :             keep_comments = true;
     128             :         }
     129          64 :         else if(strcmp(argv[i], "--output") == 0
     130          64 :         || strcmp(argv[i], "-o") == 0)
     131             :         {
     132          32 :             ++i;
     133          32 :             if(i >= argc)
     134             :             {
     135           0 :                 std::cerr << "json-to-string:error: --output must be followed by a filename.\n";
     136           0 :                 return 1;
     137             :             }
     138          32 :             if(!output_filename.empty())
     139             :             {
     140           0 :                 std::cerr << "json-to-string:error: --output can only be used once.\n";
     141           0 :                 return 1;
     142             :             }
     143          32 :             output_filename = argv[i];
     144             :         }
     145          32 :         else if(argv[i][0] == '-')
     146             :         {
     147             :             std::cerr
     148             :                 << "json-to-string:error: unknown command line option \""
     149           0 :                 << argv[i]
     150           0 :                 << "\".\n";
     151           0 :             return 1;
     152             :         }
     153          32 :         else if(argv[i][0] == '\0')
     154             :         {
     155           0 :             std::cerr << "json-to-string:error: a filename must be specified (an empty parameter is not acceptable).\n";
     156           0 :             return 1;
     157             :         }
     158             :         else
     159             :         {
     160          32 :             input_filenames.push_back(argv[i]);
     161             :         }
     162             :     }
     163             : 
     164          32 :     as2js::output_stream<std::ofstream>::pointer_t out(std::make_shared<as2js::output_stream<std::ofstream>>());
     165          32 :     out->open(output_filename);
     166          32 :     if(!out->is_open())
     167             :     {
     168             :         std::cerr
     169             :             << "error: could not open output file \""
     170             :             << output_filename
     171           0 :             << "\" for writing.\n";
     172           0 :         return 1;
     173             :     }
     174             : 
     175          32 :     messages msg;
     176          32 :     std::size_t max_filenames(input_filenames.size());
     177          64 :     for(std::size_t idx(0); idx < max_filenames; ++idx)
     178             :     {
     179             :         // first we use JSON to load the file, if we detect an
     180             :         // error return 1 instead of 0
     181             :         //
     182          32 :         std::string filename(input_filenames[idx]);
     183          32 :         as2js::json::pointer_t load_json(std::make_shared<as2js::json>());
     184          32 :         as2js::json::json_value::pointer_t loaded_value(load_json->load(filename));
     185          32 :         if(loaded_value != nullptr)
     186             :         {
     187          32 :             as2js::input_stream<std::ifstream>::pointer_t in(std::make_shared<as2js::input_stream<std::ifstream>>());
     188          32 :             in->open(filename);
     189          32 :             if(in->is_open())
     190             :             {
     191          32 :                 char32_t c(0);
     192       39706 :                 while(c != as2js::CHAR32_EOF)
     193             :                 {
     194             :                     // read one line of JSON
     195       39674 :                     std::string str;
     196       39674 :                     std::string indent;
     197             :                     for(;;)
     198             :                     {
     199     1732566 :                         c = in->get();
     200     1732566 :                         if(c == as2js::CHAR32_EOF || c == '\n')
     201             :                         {
     202             :                             break;
     203             :                         }
     204     1692892 :                         if((c == ' ' || c == '\t') && str.empty())
     205             :                         {
     206             :                             // left trim
     207     1221167 :                             indent += c;
     208     1221167 :                             continue;
     209             :                         }
     210      471725 :                         if(str.empty() && c == '/')
     211             :                         {
     212        1649 :                             c = in->get();
     213        1649 :                             if(c == '/')
     214             :                             {
     215             :                                 // read comments
     216        1649 :                                 str += "/";
     217             :                                 do
     218             :                                 {
     219       36205 :                                     str += c;
     220       36205 :                                     c = in->get();
     221             :                                 }
     222       36205 :                                 while(c != as2js::CHAR32_EOF && c != '\n');
     223        1649 :                                 if(keep_comments)
     224             :                                 {
     225             :                                     // keep the comments, but not inside the JSON strings
     226           0 :                                     out->write_string(indent);
     227           0 :                                     out->write_string(str);
     228           0 :                                     if(str[str.length() - 1] == '\\')
     229             :                                     {
     230             :                                         // we add a $ when str ends with a '\'
     231           0 :                                         out->write_string("$");
     232             :                                     }
     233           0 :                                     out->write_string("\n");
     234             :                                 }
     235        1649 :                                 indent.clear();
     236        1649 :                                 str.clear();
     237        1649 :                                 continue;
     238             :                             }
     239             :                         }
     240      470076 :                         if(c == '"')
     241             :                         {
     242             :                             // add 1 '\' characters in front of the '"'
     243       62368 :                             str += "\\\"";
     244             :                         }
     245      407708 :                         else if(c == '\\')
     246             :                         {
     247             :                             // add 2 '\' character for each '\'
     248        2958 :                             str += "\\\\";
     249             :                         }
     250             :                         else
     251             :                         {
     252      404750 :                             str += c;
     253             :                         }
     254             :                     }
     255       39674 :                     if(!str.empty())
     256             :                     {
     257             :                         // if string ends with "\" then we need to add a "\n"
     258       39006 :                         if(newlines
     259       39006 :                         || str[str.length() - 1] == '\\')
     260             :                         {
     261       39006 :                             str += "\\n";
     262             :                         }
     263             : 
     264             :                         // output this one line as a C++ string
     265             :                         //
     266       39006 :                         out->write_string(indent);
     267       39006 :                         out->write_string("\"");
     268       39006 :                         out->write_string(str);
     269       39006 :                         out->write_string("\"\n");
     270             :                     }
     271       39674 :                 }
     272             :             }
     273             :             else
     274             :             {
     275           0 :                 as2js::message err_msg(as2js::message_level_t::MESSAGE_LEVEL_FATAL, as2js::err_code_t::AS_ERR_CANNOT_COMPILE, loaded_value->get_position());
     276           0 :                 err_msg << "could not re-open this JSON input file \"" << filename << "\".";
     277           0 :                 err = 1;
     278           0 :             }
     279          32 :         }
     280             :         else
     281             :         {
     282           0 :             err = 1;
     283             :         }
     284          32 :     }
     285             : 
     286          32 :     if(err == 1)
     287             :     {
     288             :         // on error make sure to delete because otherwise cmake thinks
     289             :         // that the target is all good.
     290             :         //
     291           0 :         unlink(output_filename.c_str());
     292             :     }
     293             : 
     294          32 :     return err;
     295          32 : }
     296             : 
     297             : // vim: ts=4 sw=4 et

Generated by: LCOV version 1.14