LCOV - code coverage report
Current view: top level - root/contrail/src/contrail-analytics/contrail-collector - parser_util.cc (source / functions) Hit Total Coverage
Test: OpenSDN C/C++ coverage (all TARGET_SET jobs) Lines: 119 135 88.1 %
Date: 2026-08-03 02:19:58 Functions: 8 10 80.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :  * Copyright (c) 2014 Juniper Networks, Inc. All rights reserved.
       3             :  */
       4             : #define BOOST_SPIRIT_DEBUG
       5             : #include "boost/spirit/include/classic.hpp"
       6             : #include <boost/config/warning_disable.hpp>
       7             : #include <boost/spirit/include/qi.hpp>
       8             : #include <boost/spirit/include/phoenix_core.hpp>
       9             : #include <boost/spirit/include/phoenix_operator.hpp>
      10             : #include <boost/spirit/include/phoenix_stl.hpp>
      11             : #include <boost/spirit/include/qi_repeat.hpp>
      12             : 
      13             : #include <boost/assign/list_of.hpp>
      14             : 
      15             : #include <boost/algorithm/string/case_conv.hpp>
      16             : 
      17             : #include <iostream>
      18             : #include "base/regex.h"
      19             : #include "parser_util.h"
      20             : 
      21             : using contrail::regex;
      22             : using contrail::regex_match;
      23             : using contrail::regex_search;
      24             : 
      25             : namespace qi = boost::spirit::qi;
      26             : namespace ascii = boost::spirit::ascii;
      27             : namespace phx = boost::phoenix;
      28             : using namespace BOOST_SPIRIT_CLASSIC_NS;
      29             : 
      30             : bool
      31           7 : LineParser::GetAtrributes(const pugi::xml_node &node,
      32             :         LineParser::WordListType *words)
      33             : {
      34           7 :      bool r=true;
      35          13 :      for (pugi::xml_attribute attr = node.first_attribute(); attr;
      36           6 :              attr = attr.next_attribute()) {
      37          12 :          std::string s =  MakeSane(boost::algorithm::to_lower_copy(std::string(
      38           6 :                      attr.value())));
      39           6 :          if (!s.empty()) {
      40           6 :              r &= ParseDoc(s.begin(), s.end(), words);
      41             :          }
      42           6 :      }
      43           7 :      return r;
      44             : }
      45             : 
      46             : bool
      47           9 : LineParser::Traverse(const pugi::xml_node &node,
      48             :         LineParser::WordListType *words, bool check_attr)
      49             : {
      50           9 :     pugi::xml_node_type type = node.type();
      51           9 :     bool r = true;
      52             : 
      53           9 :     if (type == pugi::node_element) {
      54           5 :         if (check_attr)
      55           4 :             r &= GetAtrributes(node, words);
      56           4 :     } else if (type == pugi::node_pcdata || type == pugi::node_cdata) {
      57           8 :          std::string s =  MakeSane(boost::algorithm::to_lower_copy(std::string(
      58           4 :                      node.value())));
      59           4 :          if (!s.empty()) {
      60           4 :              r &= ParseDoc(s.begin(), s.end(), words);
      61             :          }
      62           4 :     }
      63          14 :     for (pugi::xml_node s = node.first_child(); s; s = s.next_sibling())
      64           5 :         r &= Traverse(s, words, check_attr);
      65           9 :     return r;
      66             : }
      67             : 
      68             : bool
      69           4 : LineParser::ParseXML(const pugi::xml_node &node,
      70             :         LineParser::WordListType *words, bool check_attr)
      71             : {
      72           4 :     bool r=true;
      73           4 :     if (check_attr)
      74           3 :         r &= GetAtrributes(node, words);
      75           8 :     for (pugi::xml_node s = node; s; s = s.next_sibling())
      76           4 :         r &= Traverse(s, words, check_attr);
      77           4 :     return r;
      78             : }
      79             : 
      80             : bool
      81          12 : LineParser::Parse(std::string s, LineParser::WordListType *words) {
      82          24 :     std::string ls = MakeSane(boost::algorithm::to_lower_copy(s));
      83          24 :     return ParseDoc(ls.begin(), ls.end(), words);
      84          12 : }
      85             : 
      86             : template<typename Iterator>
      87             : struct msg_skipper : public qi::grammar<Iterator> {
      88          22 :     msg_skipper() : msg_skipper::base_type(skip, "msgskpr") {
      89          44 :         skip = ascii::space | qi::char_(".,;:[](){}\t\r");
      90          22 :     }
      91             :     qi::rule<Iterator> skip;
      92             : };
      93             : 
      94             : template <typename Iterator>
      95             : bool
      96          22 : LineParser::ParseDoc(Iterator start, Iterator end,
      97             :         LineParser::WordListType *pv)
      98             : {
      99             :     using ascii::space;
     100             :     using qi::char_;
     101             :     using qi::lit;
     102             :     using qi::_1;
     103             :     using qi::lexeme;
     104             :     using qi::debug;
     105             :     using phx::insert;
     106             :     using phx::ref;
     107             :     using boost::spirit::repeat;
     108             : 
     109             :     typedef msg_skipper<Iterator> skipper_t;
     110          22 :     skipper_t skpr;
     111             : 
     112          66 :     qi::rule<Iterator, std::string(), skipper_t> num1 =
     113         132 :         lexeme[ *char_("0-9") >> '.' >> +char_("0-9") ];
     114          66 :     qi::rule<Iterator, std::string(), skipper_t> num2=
     115         110 :         lexeme[ +char_("0-9") >> -lit('.') ];
     116          66 :     qi::rule<Iterator, std::string(), skipper_t> hex1=
     117         110 :         lexeme[ lit('0') >> lit('x') >> +char_("0-9A-Fa-f") ];
     118          66 :     qi::rule<Iterator, std::string(), skipper_t> oct1=
     119          88 :         lexeme[ lit('0') >> +char_("0-7") ];
     120          66 :     qi::rule<Iterator, std::string(), skipper_t> word =
     121          88 :         lexeme[ +(char_ - char_(" .,;:[](){}\t\r")) ];
     122          44 :     qi::rule<Iterator, std::string(), skipper_t> word2 =
     123         132 :         '\'' >> lexeme[ +(char_ - '\'') ] >> '\'';
     124          44 :     qi::rule<Iterator, std::string(), skipper_t> word3 =
     125         132 :         '"' >> lexeme[ +(char_ - '"') ] >> '"';
     126          66 :     qi::rule<Iterator, std::string(), skipper_t> uuid =
     127          66 :         lexeme[ repeat(8)[char_("0-9a-fA-F")] >> char_('-') >>
     128         132 :          repeat(3)[ repeat(4)[char_("0-9a-fA-F")] >> char_('-') ] >>
     129          44 :          repeat(12)[char_("0-9a-fA-F")] ];
     130          66 :     qi::rule<Iterator, std::string(), skipper_t> ip =
     131          88 :     lexeme[ +char_(L'0', L'9') >> char_('.') >> +char_(L'0', L'9')
     132          88 :         >> +(char_('.') >> +char_(L'0', L'9'))
     133         132 :         >> -(char_('/') >> +char_(L'0', L'9'))];
     134          66 :     qi::rule<Iterator, std::string(), skipper_t> ipv6 =
     135          66 :     lexeme[ +char_("0-9a-fA-F") >> +(+ char_(':')
     136         110 :         >> +char_("0-9a-fA-F")) >> -(char_('/')
     137          88 :         >> +char_(L'0', L'9'))];
     138          66 :     qi::rule<Iterator, std::string(), skipper_t> stats =
     139         154 :     lexeme[ +char_(L'0', L'9') >> +(char_('/') >> +char_(L'0', L'9'))];
     140             : 
     141          44 :     qi::symbols<char, bool> stop_words;
     142             :     stop_words.add
     143          22 :         ("via", true)("or", true)("of", true)
     144          22 :         ("string", true)("sandesh", true)("client", true)
     145          22 :         ("the", true)("that", true)("and", true);
     146          44 :     qi::rule<Iterator, std::string(), skipper_t> aw =
     147          22 :         +( *( lit(":")
     148          44 :             | lit(",")
     149          44 :             | lit(".")
     150          44 :             | lit(";")
     151          44 :             | lit("&")
     152          22 :             ) >>
     153             :          ( stop_words
     154          66 :          | stats [insert(boost::phoenix::ref(*pv), _1)]
     155          66 :          | word2 [insert(boost::phoenix::ref(*pv), _1)]
     156          66 :          | word3 [insert(boost::phoenix::ref(*pv), _1)]
     157          66 :          | uuid  [insert(boost::phoenix::ref(*pv), _1)]
     158          66 :          | ip    [insert(boost::phoenix::ref(*pv), _1)]
     159          66 :          | ipv6  [insert(boost::phoenix::ref(*pv), _1)]
     160          22 :          | hex1
     161          22 :          | oct1
     162          22 :          | num1
     163          22 :          | num2
     164          88 :          | word  [insert(boost::phoenix::ref(*pv), _1)]
     165             :          )
     166             :         );
     167             : 
     168          44 :     bool r = qi::phrase_parse(start, end,
     169             :         // Begin grammer
     170          22 :         *aw
     171             :         // end grammer
     172             :         , skpr);
     173         198 :     BOOST_SPIRIT_DEBUG_NODES((word)(num1)(aw)(word2));
     174          66 :     BOOST_SPIRIT_DEBUG_RULE(word);
     175          66 :     BOOST_SPIRIT_DEBUG_RULE(word2);
     176          66 :     BOOST_SPIRIT_DEBUG_RULE(aw);
     177          44 :     return ((start == end) && r);
     178          22 : }
     179             : 
     180             : std::string
     181          22 : LineParser::MakeSane(const std::string &text) {
     182          22 :     std::ostringstream s;
     183        1725 :     for (std::string::const_iterator it = text.begin(); it != text.end();
     184        1703 :             ++it) {
     185        1703 :         if (0x80 & *it)
     186           0 :             s << "&#" << (int)((uint8_t)*it) << ";";
     187             :         else
     188        1703 :             s << *it;
     189             :     }
     190          44 :     return s.str();
     191          22 : }
     192             : 
     193             : std::string
     194           0 : LineParser::GetXmlString(const pugi::xml_node node) {
     195           0 :     std::ostringstream sstream;
     196           0 :     if (node.attribute("type").value() == std::string("string"))
     197           0 :         sstream <<  " " << LineParser::MakeSane(node.child_value());
     198           0 :     for (pugi::xml_node child = node.first_child(); child; child =
     199           0 :             child.next_sibling())
     200           0 :         sstream << LineParser::GetXmlString(child);
     201           0 :     return sstream.str();
     202           0 : }
     203             : 
     204             : unsigned int
     205           7 : LineParser::SearchPattern(const regex &exp, std::string text)
     206             : {
     207           7 :     unsigned int cnt = 0;
     208             : 
     209           7 :     boost::match_results<std::string::const_iterator> what;
     210           7 :     boost::match_flag_type flags = boost::match_default;
     211           7 :     std::string::const_iterator start = text.begin(), end = text.end();
     212          15 :     while(regex_search(start, end, what, exp, flags)) {
     213           8 :         cnt++;
     214             :         //start looking for next match after this one
     215           8 :         start = what[0].second;
     216             :         // update flags:
     217           8 :         flags |= boost::match_prev_avail;
     218           8 :         flags |= boost::match_not_bob;
     219             : //#define SYSLGDEBUG
     220             : #ifdef SYSLGDEBUG
     221             :         std::cout << "Text:        \"" << text << "\"\n";
     222             :         std::cout << "<String 5> \""
     223             :                   << std::string(what[5].first, what[5].second)
     224             :                   << "\" + <string 6> \"" << std::string(what[6].first, what[6].second)
     225             :                   << "\" = " << what[5].first - text.begin();
     226             :         std::cout << "\n what.size = " << what.size()
     227             :                   << "\n====================\n";
     228             :         for(unsigned int i = 0; i < what.size(); ++i)
     229             :         {
     230             :             std::cout << "      $" << i << " = {";
     231             :             std::cout << std::string(what[i].first,  what[i].second);
     232             :             std::cout << "}\n";
     233             :         }
     234             : #endif
     235             :     }
     236           7 :     return cnt;
     237           7 : }
     238             : 
     239             : 
     240             : // generate a method for the template(required for static template function
     241             : void
     242           0 : TemplateGen() {
     243           0 :     std::string s("hello");
     244           0 :     LineParser::WordListType words;
     245           0 :     LineParser::Parse(s, &words);
     246           0 :     std::cout << "result length: " << words.size() << std::endl;
     247           0 : }
     248             : 

Generated by: LCOV version 1.14