AirInv Logo  1.00.0
C++ Simulated Airline Inventory Management System library
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
RequestParser.cpp
Go to the documentation of this file.
1 // //////////////////////////////////////////////////////////////////////
2 // Import section
3 // //////////////////////////////////////////////////////////////////////
4 // STL
5 #include <cassert>
6 // AirInv
9 
10 namespace 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 }