Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: downloads/boost_1_33_1/libs/spirit/example/intermediate/ipv4_opt.cpp @ 12

Last change on this file since 12 was 12, checked in by landauf, 17 years ago

added boost

File size: 5.9 KB
Line 
1/*=============================================================================
2    Copyright (c) 2002-2003 Joel de Guzman
3    http://spirit.sourceforge.net/
4
5    Use, modification and distribution is subject to the Boost Software
6    License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
7    http://www.boost.org/LICENSE_1_0.txt)
8=============================================================================*/
9#include <boost/spirit/core.hpp>
10#include <boost/spirit/actor/push_back_actor.hpp>
11#include <boost/spirit/dynamic/if.hpp>
12#include <boost/spirit/dynamic/for.hpp>
13#include <boost/spirit/phoenix.hpp>
14#include <iostream>
15#include <string>
16#include <vector>
17#include <algorithm>
18
19///////////////////////////////////////////////////////////////////////////////
20//
21//  Please check it out ipv4.cpp sample first!
22//  << See ipv4.cpp sample for details >>
23//
24//  This is a variation of the ipv4.cpp sample. The original ipv4.cpp code
25//  compiles to 36k on MSVC7.1. Not bad! Yet, we want to shave a little bit
26//  more. Is it possible? Yes! This time, we'll use subrules and just store
27//  the rules in a plain old struct. We are parsing at the char level anyway,
28//  so we know what type of rule we'll need: a plain rule<>. The result: we
29//  shaved off another 20k. Now the code compiles to 16k on MSVC7.1.
30//
31//  Could we have done better? Yes, but only if only we had typeof! << See
32//  the techniques section of the User's guide >> ... Someday... :-)
33//
34///////////////////////////////////////////////////////////////////////////////
35using namespace std;
36using namespace boost::spirit;
37using namespace phoenix;
38
39struct ipv4_prefix_data
40{
41    char prefix_len, n0, n1, n2, n3;
42
43    ipv4_prefix_data()
44        : prefix_len(0),n0(0),n1(0),n2(0),n3(0) {}
45};
46
47struct ipv4_data
48{
49    char packet_len, header_len;
50    std::string header;
51    std::vector<ipv4_prefix_data> prefixes;
52
53    ipv4_data()
54        : packet_len(0),header_len(0){}
55
56};
57
58struct ipv4
59{
60    ipv4(ipv4_data& data)
61        : data(data)
62    {
63        start =
64        (
65            packet =
66                '\xff'
67                >> anychar_p[var(data.packet_len) = arg1]
68                >> payload
69            ,
70
71            payload =
72                anychar_p[var(data.header_len) = arg1]
73                >>  for_p(var(i) = 0, var(i) < var(data.header_len), ++var(i))
74                    [
75                        anychar_p[var(data.header) += arg1]
76                    ]
77                >> *ipv4_prefix
78             ,
79
80            ipv4_prefix =
81                anychar_p
82                [
83                    var(temp.prefix_len) = arg1,
84                    var(temp.n0) = 0,
85                    var(temp.n1) = 0,
86                    var(temp.n2) = 0,
87                    var(temp.n3) = 0
88                ]
89
90                >>  if_p(var(temp.prefix_len) > 0x00)
91                    [
92                        anychar_p[var(temp.n0) = arg1]
93                        >>  if_p(var(temp.prefix_len) > 0x08)
94                            [
95                                anychar_p[var(temp.n1) = arg1]
96                                >>  if_p(var(temp.prefix_len) > 0x10)
97                                    [
98                                        anychar_p[var(temp.n2) = arg1]
99                                        >>  if_p(var(temp.prefix_len) > 0x18)
100                                            [
101                                                anychar_p[var(temp.n3) = arg1]
102                                            ]
103                                    ]
104                            ]
105                    ]
106                    [
107                        push_back_a(data.prefixes, temp)
108                    ]
109        );
110    }
111
112    int i;
113    ipv4_prefix_data temp;
114
115    rule<> start;
116    subrule<0> packet;
117    subrule<1> payload;
118    subrule<2> ipv4_prefix;
119    ipv4_data& data;
120};
121
122////////////////////////////////////////////////////////////////////////////
123//
124//  Main program
125//
126////////////////////////////////////////////////////////////////////////////
127int
128as_byte(char n)
129{
130    if (n < 0)
131        return n + 256;
132    return n;
133}
134
135void
136print_prefix(ipv4_prefix_data const& prefix)
137{
138    cout << "prefix length = " << as_byte(prefix.prefix_len) << endl;
139    cout << "n0 = " << as_byte(prefix.n0) << endl;
140    cout << "n1 = " << as_byte(prefix.n1) << endl;
141    cout << "n2 = " << as_byte(prefix.n2) << endl;
142    cout << "n3 = " << as_byte(prefix.n3) << endl;
143}
144
145void
146parse_ipv4(char const* str, unsigned len)
147{
148    ipv4_data data;
149    ipv4 g(data);
150    parse_info<> info = parse(str, str+len, g.start);
151
152    if (info.full)
153    {
154        cout << "-------------------------\n";
155        cout << "Parsing succeeded\n";
156
157        cout << "packet length = " << as_byte(data.packet_len) << endl;
158        cout << "header length = " << as_byte(data.header_len) << endl;
159        cout << "header = " << data.header << endl;
160
161        for_each(data.prefixes.begin(), data.prefixes.end(), print_prefix);
162        cout << "-------------------------\n";
163    }
164    else
165    {
166        cout << "Parsing failed\n";
167        cout << "stopped at:";
168        for (char const* s = info.stop; s != str+len; ++s)
169            cout << static_cast<int>(*s) << endl;
170    }
171}
172
173// Test inputs:
174
175// The string in the header is "empty", the prefix list is empty.
176char const i1[8] =
177{
178    0xff,0x08,0x05,
179    'e','m','p','t','y'
180};
181
182// The string in the header is "default route", the prefix list
183// has just one element, 0.0.0.0/0.
184char const i2[17] =
185{
186    0xff,0x11,0x0d,
187    'd','e','f','a','u','l','t',' ',
188    'r','o','u','t','e',
189    0x00
190};
191
192// The string in the header is "private address space", the prefix list
193// has the elements 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16.
194char const i3[32] =
195{
196    0xff,0x20,0x15,
197    'p','r','i','v','a','t','e',' ',
198    'a','d','d','r','e','s','s',' ',
199    's','p','a','c','e',
200    0x08,0x0a,
201    0x0c,0xac,0x10,
202    0x10,0xc0,0xa8
203};
204
205int
206main()
207{
208    parse_ipv4(i1, sizeof(i1));
209    parse_ipv4(i2, sizeof(i2));
210    parse_ipv4(i3, sizeof(i3));
211    return 0;
212}
213
Note: See TracBrowser for help on using the repository browser.