Branch data Line data Source code
1 : : // ***************************************************************************** 2 : : /*! 3 : : \file src/Control/StringParser.cpp 4 : : \copyright 2012-2015 J. Bakosi, 5 : : 2016-2018 Los Alamos National Security, LLC., 6 : : 2019-2021 Triad National Security, LLC. 7 : : All rights reserved. See the LICENSE file for details. 8 : : \brief String parser base class definition 9 : : \details String parser base class definition. String parser base serves as 10 : : a base class for various string parsers, e.g., command-line parsers. It does 11 : : generic after-parser diagnostics. 12 : : */ 13 : : // ***************************************************************************** 14 : : 15 : : #include <vector> 16 : : #include <iostream> 17 : : #include <cstddef> 18 : : #include <string> 19 : : 20 : : #include "StringParser.hpp" 21 : : #include "Exception.hpp" 22 : : 23 : : using tk::StringParser; 24 : : 25 : 331 : StringParser::StringParser( int argc, char** argv ) : m_string() 26 : : // ***************************************************************************** 27 : : // Constructor 28 : : //! \param[in] argc Number of C-style character arrays in argv 29 : : //! \param[in] argv C-style character array of character arrays 30 : : //! \details Convert C-style character array of character arrays to a single 31 : : //! std::string substrings separated by spaces. Exception safety: basic 32 : : //! guarantee: if an exception is thrown, the stream is in a valid state. 33 : : // ***************************************************************************** 34 : : { 35 [ + + ]: 2382 : for (int i=1; i<argc; ++i) 36 [ + - ][ + - ]: 2051 : m_string += std::string(argv[i]) + ' '; [ + - ] 37 : 331 : } 38 : : 39 : : void 40 : 330 : StringParser::diagnostics( const tk::Print& print, 41 : : const std::vector< std::string >& messages ) 42 : : // ***************************************************************************** 43 : : // Echo errors and warnings accumulated during parsing 44 : : //! \param[in] print Pretty printer 45 : : //! \param[in] messages Vector of strings of errors and warnings 46 : : // ***************************************************************************** 47 : : { 48 : 330 : bool err = false; // signaling whether there were any errors 49 : : 50 : : // Underline errors and warnings 51 [ + - ]: 660 : std::string underline( m_string.size(), ' ' ); 52 [ - + ]: 330 : for (const auto& e : messages) { 53 : : 54 : : // decide if error or warning 55 : 0 : char underchar = ' '; 56 [ - - ]: 0 : if (e.find( "Error" ) != std::string::npos) { err = true; underchar = '^'; } 57 [ - - ]: 0 : else if (e.find( "Warning" ) != std::string::npos) underchar = '~'; 58 : : 59 : : // underline error and warning 60 [ - - ][ - - ]: 0 : if (underchar == '^' || underchar == '~') { 61 : 0 : auto sloc = e.find( "at 1," ); 62 [ - - ]: 0 : if (sloc != std::string::npos) { // if we have location info 63 : : // skip "at 1," 64 : 0 : sloc += 5; 65 : : // find a dot starting from after "at 1," 66 : 0 : const auto eloc = e.find_first_of( '.', sloc ); 67 : : // compute location of error by extracting it from error message 68 [ - - ][ - - ]: 0 : const std::size_t errloc = std::stoul( e.substr( sloc, eloc-sloc ) ) - 1; 69 : : // find beginning of erroneous argument 70 : 0 : sloc = m_string.rfind( ' ', errloc-1 ); 71 : : // special-handle the first argument with no space in front of it 72 [ - - ]: 0 : if (sloc == std::string::npos) sloc = 0; else ++sloc; 73 : : // underline error and warning differently 74 [ - - ][ - - ]: 0 : for (std::size_t i=sloc; i<errloc; ++i) underline[i] = underchar; 75 : : } 76 : : } 77 : : } 78 : : 79 : : // Output errors and warnings underlined (if any) to quiet stream, list errors 80 : : // and warnings, and exit 81 [ - + ]: 330 : if (!messages.empty()) { 82 [ - - ]: 0 : print % '\n'; 83 [ - - ][ - - ]: 0 : print % ">>> Command line parsed: '" % m_string % "'\n"; [ - - ] 84 [ - - ][ - - ]: 0 : print % ">>> " % underline % "\n"; [ - - ] 85 [ - - ][ - - ]: 0 : for (const auto& e : messages) print % ">>> " % e % std::endl; // messages [ - - ][ - - ] 86 : : // Exit if there were any errors 87 [ - - ][ - - ]: 0 : if (err) Throw( "Error(s) occurred while parsing the command line\n" ); [ - - ][ - - ] 88 : : } 89 : 330 : }