AirInv Logo  1.00.7
C++ Simulated Airline Inventory Management System Library
Loading...
Searching...
No Matches
RequestParser.cpp
Go to the documentation of this file.
1// //////////////////////////////////////////////////////////////////////
2// Import section
3// //////////////////////////////////////////////////////////////////////
4// STL
5#include <cassert>
6// AirInv
9
10namespace AIRINV {
11
12 // //////////////////////////////////////////////////////////////////////
14 : state_(method_start) {
15 }
16
17 // //////////////////////////////////////////////////////////////////////
19 state_ = method_start;
20 }
21
22 // //////////////////////////////////////////////////////////////////////
23 boost::tribool RequestParser::consume (Request& req, char input) {
24
25 switch (state_) {
26
27 case method_start:
28 if (!is_char(input) || is_ctl(input) || is_tspecial(input)) {
29 return false;
30
31 } else {
32 state_ = method;
33 req.method.push_back(input);
34 return boost::indeterminate;
35 }
36
37 case method:
38 if (input == ' ') {
39 state_ = uri;
40 return boost::indeterminate;
41
42 } else if (!is_char(input) || is_ctl(input) || is_tspecial(input)) {
43 return false;
44
45 } else {
46 req.method.push_back(input);
47 return boost::indeterminate;
48 }
49
50 case uri_start:
51 if (is_ctl(input)) {
52 return false;
53
54 } else {
55 state_ = uri;
56 req.uri.push_back(input);
57 return boost::indeterminate;
58 }
59
60 case uri:
61 if (input == ' ') {
62 state_ = http_version_h;
63 return boost::indeterminate;
64
65 } else if (is_ctl(input)) {
66 return false;
67
68 } else {
69 req.uri.push_back(input);
70 return boost::indeterminate;
71 }
72
73 case http_version_h:
74 if (input == 'H') {
75 state_ = http_version_t_1;
76 return boost::indeterminate;
77
78 } else {
79 return false;
80 }
81
82 case http_version_t_1:
83 if (input == 'T') {
84 state_ = http_version_t_2;
85 return boost::indeterminate;
86
87 } else {
88 return false;
89 }
90
91 case http_version_t_2:
92 if (input == 'T') {
93 state_ = http_version_p;
94 return boost::indeterminate;
95
96 } else {
97 return false;
98 }
99
100 case http_version_p:
101 if (input == 'P') {
102 state_ = http_version_slash;
103 return boost::indeterminate;
104
105 } else {
106 return false;
107 }
108
109 case http_version_slash:
110 if (input == '/') {
111 req.http_version_major = 0;
112 req.http_version_minor = 0;
113 state_ = http_version_major_start;
114 return boost::indeterminate;
115
116 } else {
117 return false;
118 }
119
120 case http_version_major_start:
121 if (is_digit(input)) {
122 req.http_version_major = req.http_version_major * 10 + input - '0';
123 state_ = http_version_major;
124 return boost::indeterminate;
125
126 } else {
127 return false;
128 }
129
130 case http_version_major:
131 if (input == '.') {
132 state_ = http_version_minor_start;
133 return boost::indeterminate;
134
135 } else if (is_digit(input)) {
136 req.http_version_major = req.http_version_major * 10 + input - '0';
137 return boost::indeterminate;
138
139 } else {
140 return false;
141 }
142
143 case http_version_minor_start:
144 if (is_digit(input)) {
145 req.http_version_minor = req.http_version_minor * 10 + input - '0';
146 state_ = http_version_minor;
147 return boost::indeterminate;
148
149 } else {
150 return false;
151 }
152
153 case http_version_minor:
154 if (input == '\r') {
155 state_ = expecting_newline_1;
156 return boost::indeterminate;
157
158 } else if (is_digit(input)) {
159 req.http_version_minor = req.http_version_minor * 10 + input - '0';
160 return boost::indeterminate;
161
162 } else {
163 return false;
164 }
165
166 case expecting_newline_1:
167 if (input == '\n') {
168 state_ = header_line_start;
169 return boost::indeterminate;
170
171 } else {
172 return false;
173 }
174
175 case header_line_start:
176 if (input == '\r') {
177 state_ = expecting_newline_3;
178 return boost::indeterminate;
179
180 } else if (!is_char(input) || is_ctl(input) || is_tspecial(input)) {
181 return false;
182
183 } else {
184 state_ = header_name;
185 return boost::indeterminate;
186 }
187
188 case header_lws:
189 if (input == '\r') {
190 state_ = expecting_newline_2;
191 return boost::indeterminate;
192
193 } else if (input == ' ' || input == '\t') {
194 return boost::indeterminate;
195
196 } else if (is_ctl(input)) {
197 return false;
198
199 } else {
200 state_ = header_value;
201 return boost::indeterminate;
202 }
203
204 case header_name:
205 if (input == ':') {
206 state_ = space_before_header_value;
207 return boost::indeterminate;
208
209 } else if (!is_char(input) || is_ctl(input) || is_tspecial(input)) {
210 return false;
211
212 } else {
213 return boost::indeterminate;
214 }
215
216 case space_before_header_value:
217 if (input == ' ') {
218 state_ = header_value;
219 return boost::indeterminate;
220
221 } else {
222 return false;
223 }
224
225 case header_value:
226 if (input == '\r') {
227 state_ = expecting_newline_2;
228 return boost::indeterminate;
229
230 } else if (is_ctl(input)) {
231 return false;
232
233 } else {
234 return boost::indeterminate;
235 }
236
237 case expecting_newline_2:
238 if (input == '\n') {
239 state_ = header_line_start;
240 return boost::indeterminate;
241
242 } else {
243 return false;
244 }
245
246 case expecting_newline_3:
247 return (input == '\n');
248
249 default:
250 return false;
251 }
252 }
253
254 // //////////////////////////////////////////////////////////////////////
255 bool RequestParser::is_char(int c) {
256 return c >= 0 && c <= 127;
257 }
258
259 // //////////////////////////////////////////////////////////////////////
260 bool RequestParser::is_ctl(int c) {
261 return (c >= 0 && c <= 31) || (c == 127);
262 }
263
264 // //////////////////////////////////////////////////////////////////////
265 bool RequestParser::is_tspecial(int c) {
266 switch (c) {
267 case '(': case ')': case '<': case '>': case '@':
268 case ',': case ';': case ':': case '\\': case '"':
269 case '/': case '[': case ']': case '?': case '=':
270 case '{': case '}': case ' ': case '\t':
271 return true;
272 default:
273 return false;
274 }
275 }
276
277 // //////////////////////////////////////////////////////////////////////
278 bool RequestParser::is_digit(int c) {
279 return c >= '0' && c <= '9';
280 }
281
282}
RequestParser()
Construct ready to parse the request method.
void reset()
Reset to initial parser state.