2012-07-03 3 views
1

ipv4 주소를 구문 분석하기 위해 boost :: spirit을 사용하고 싶습니다. 여기에 내가 할 노력했다 것입니다 :boost-spirit을 사용하여 ipv4 주소 구문 분석하기

#include <string> 
#include <string.h> 
#include <iostream> 
#include <boost/spirit/include/qi.hpp> 
#include <boost/spirit/include/phoenix_core.hpp> 
#include <boost/spirit/include/phoenix_operator.hpp> 

struct Ipv4 { union { uint32_t as_int; uint8_t as_char[4]; } raw; }; 

Ipv4 make_ipv4(uint8_t i1, uint8_t i2, uint8_t i3, uint8_t i4) { 
    Ipv4 ip; 
    ip.raw.as_char[0] = i1; ip.raw.as_char[1] = i2; 
    ip.raw.as_char[2] = i3; ip.raw.as_char[3] = i4; 
    return ip; 
} 

namespace qi = boost::spirit::qi; 
qi::uint_parser<uint8_t, 10, 1, 3> octet; 

struct Ipv4Address : qi::grammar<const char *, Ipv4()> { 
    Ipv4Address() : Ipv4Address::base_type(start) { 
     start = (octet >> qi::lit('.') >> octet >> qi::lit('.') >> 
        octet >> qi::lit('.') >> octet 
       ) [ 
        //qi::_val = make_ipv4(1, 2, 3, 4) // working 
        qi::_val = make_ipv4(qi::_1, qi::_2, qi::_3, qi::_4) // compile error 
       ] 
     ; 
    } 
    qi::rule<const char *, Ipv4()> start; 
} ipv4_address; 

int main() { 
    Ipv4 ip; 
    const char * s = "1.2.3.4"; 
    bool r = qi::parse(s, s+strlen(s), ipv4_address, ip); 
    std::cout << r << " " << (int)ip.raw.as_char[0] << "." << 
          (int)ip.raw.as_char[1] << "." << 
          (int)ip.raw.as_char[2] << "." << 
          (int)ip.raw.as_char[3] << std::endl; 
} 

나는 다음과 같은 컴파일 오류가 발생이 컴파일 :

/tmp/ip.cxx : 생성자 'Ipv4Address :: Ipv4Address()'에서 : /tmp/ip.cxx : 26 : 72 : 오류 : 'Ipv4 make_ipv4'에 'const _1_type {aka const boost :: phoenix :: actor>}'을 'uint8_t {aka unsigned char}'로 변환 할 수 없습니다. uint8_t, uint8_t, )

이렇게하는 것이 "올바른"방법입니까?

답변

3

당신은 게으르게 의미 작용의 기능을 결합하는 bind를 사용해야합니다 :

namespace qi = boost::spirit::qi; 
namespace phx = boost::phoenix; 
qi::uint_parser<uint8_t, 10, 1, 3> octet; 

struct Ipv4Address : qi::grammar<const char *, Ipv4()> { 
    Ipv4Address() : Ipv4Address::base_type(start) { 
     start = (octet >> qi::lit('.') >> octet >> qi::lit('.') >> 
        octet >> qi::lit('.') >> octet 
       ) [ 
        qi::_val = phx::bind(make_ipv4, qi::_1, qi::_2, qi::_3, qi::_4) 
       ] 
     ; 
    } 
    qi::rule<const char *, Ipv4()> start; 
} ipv4_address; 

전체 샘플 : 나는 선택 포트 번호로 우수한 예를 수정할 수있는 방법을

#include <string> 
#include <string.h> 
#include <iostream> 
#include <boost/spirit/include/qi.hpp> 
#include <boost/spirit/include/phoenix.hpp> 

struct Ipv4 { union { uint32_t as_int; uint8_t as_char[4]; } raw; }; 

Ipv4 make_ipv4(uint8_t i1, uint8_t i2, uint8_t i3, uint8_t i4) { 
    Ipv4 ip; 
    ip.raw.as_char[0] = i1; ip.raw.as_char[1] = i2; 
    ip.raw.as_char[2] = i3; ip.raw.as_char[3] = i4; 
    return ip; 
} 

namespace qi = boost::spirit::qi; 
namespace phx = boost::phoenix; 
qi::uint_parser<uint8_t, 10, 1, 3> octet; 

struct Ipv4Address : qi::grammar<const char *, Ipv4()> { 
    Ipv4Address() : Ipv4Address::base_type(start) { 
     start = (octet >> qi::lit('.') >> octet >> qi::lit('.') >> 
        octet >> qi::lit('.') >> octet 
       ) [ 
        qi::_val = phx::bind(make_ipv4, qi::_1, qi::_2, qi::_3, qi::_4) 
       ] 
     ; 
    } 
    qi::rule<const char *, Ipv4()> start; 
} ipv4_address; 

int main() { 
    Ipv4 ip; 
    const char * s = "1.2.3.4"; 
    bool r = qi::parse(s, s+strlen(s), ipv4_address, ip); 
    std::cout << r << " " << (int)ip.raw.as_char[0] << "." << 
          (int)ip.raw.as_char[1] << "." << 
          (int)ip.raw.as_char[2] << "." << 
          (int)ip.raw.as_char[3] << std::endl; 
} 
+0

. x.y.z.w : nnnnn 형식의 optinal 포트 지정자를 사용하여 IP 주소를 받아들이는 CSV 파서를 작성하려고합니다. 여기서 nnnnn은 1-65535 범위의 십진수입니다. – johnco3

+0

''qool :: uint_parser () | qi :: attr (0u)), ip, port)''bool r = qi :: parse (s, s + strlen (s), ipv4_address >>) 멋지게 @ johnco3 할거야. – sehe

관련 문제