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

Generated by: LCOV version 1.14