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& 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
{
DecOctet() : DecOctet::base_type(start)
{
start %= qi::uint_parser();
}
qi::rule start;
} dec_octet;
struct Ipv4Address : qi::grammar
{
Ipv4Address() : Ipv4Address::base_type(start)
{
start %= dec_octet >> qi::lit('.') >>
dec_octet >> qi::lit('.') >>
dec_octet >> qi::lit('.') >>
dec_octet
;
}
qi::rule 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