|
Boost Users : |
Subject: [Boost-users] boost-spirit: need help with simple parser
From: Allan Nielsen (a_at_[hidden])
Date: 2012-07-03 06:04:31
Hi
I would like to use boost::spirit for parsing ipv4 addresses. Here is
what I have tried to do:
struct Ipv4 {
Ipv4() { raw.as_int = 0; }
Ipv4( const Ipv4& i ) { raw.as_int = i.raw.as_int; }
Ipv4& operator=(const Ipv4& i ) { raw.as_int = i.raw.as_int; return *this; }
Ipv4(const boost::tuple<uint8_t, uint8_t, uint8_t, uint8_t>& v) {
raw.as_char[3] = v.get<0>();
raw.as_char[2] = v.get<1>();
raw.as_char[1] = v.get<2>();
raw.as_char[0] = v.get<3>();
}
union {
uint32_t as_int;
uint16_t as_short[2];
uint8_t as_char[4];
} raw;
};
struct DecOctet : qi::grammar<const char *, uint8_t()>
{
DecOctet() : DecOctet::base_type(start)
{
start %= qi::uint_parser<uint8_t, 10, 1, 3>();
}
qi::rule<const char *, uint8_t()> start;
} dec_octet;
struct Ipv4Address : qi::grammar<const char *, Ipv4()>
{
Ipv4Address() : Ipv4Address::base_type(start)
{
start %= dec_octet >> qi::lit('.') >>
dec_octet >> qi::lit('.') >>
dec_octet >> qi::lit('.') >>
dec_octet
;
}
qi::rule<const char *, Ipv4()> start;
} ipv4_address;
bool parse(const const_string& s, Ipv4& i)
{
Ipv4 _i;
const char * iter = s.begin();
bool r = qi::parse(iter, s.end(), ipv4_address, _i);
if( !r || iter != s.end() )
return false;
i = _i;
return true;
}
But unfortunately if I parse an address such as "1.2.3.4", I end up
with the address "1.0.0.0" in my Ipv4 struct. The IPv4 struct is
legacy code, and the union member can therefor not be changed. I can
add other constructors, but I prefer non-intrusive changes.
So here are my questions:
- What have I done wrong?
- How should this has been done if I did not have a constructor
accepting the tuple?
- How would you have done?
Best regards
Allan W. Nielsen
Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net