AirInv Logo  0.1.2
C++ Simulated Airline Inventory Management System library
RequestParser.cpp
Go to the documentation of this file.
00001 // //////////////////////////////////////////////////////////////////////
00002 // Import section
00003 // //////////////////////////////////////////////////////////////////////
00004 // STL
00005 #include <cassert>
00006 // AirInv
00007 #include <airinv/server/RequestParser.hpp>
00008 #include <airinv/server/Request.hpp>
00009 
00010 namespace AIRINV {
00011 
00012   // //////////////////////////////////////////////////////////////////////
00013   RequestParser::RequestParser()
00014     : state_(method_start) {
00015   }
00016 
00017   // //////////////////////////////////////////////////////////////////////
00018   void RequestParser::reset() {
00019     state_ = method_start;
00020   }
00021 
00022   // //////////////////////////////////////////////////////////////////////
00023   boost::tribool RequestParser::consume (Request& req, char input) {
00024 
00025     switch (state_) {
00026 
00027     case method_start:
00028       if (!is_char(input) || is_ctl(input) || is_tspecial(input)) {
00029         return false;
00030       
00031       } else {
00032         state_ = method;
00033         req.method.push_back(input);
00034         return boost::indeterminate;
00035       }
00036     
00037     case method:
00038       if (input == ' ') {
00039         state_ = uri;
00040         return boost::indeterminate;
00041       
00042       } else if (!is_char(input) || is_ctl(input) || is_tspecial(input)) {
00043         return false;
00044       
00045       } else {
00046         req.method.push_back(input);
00047         return boost::indeterminate;
00048       }
00049     
00050     case uri_start:
00051       if (is_ctl(input)) {
00052         return false;
00053       
00054       } else {
00055         state_ = uri;
00056         req.uri.push_back(input);
00057         return boost::indeterminate;
00058       }
00059     
00060     case uri:
00061       if (input == ' ') {
00062         state_ = http_version_h;
00063         return boost::indeterminate;
00064       
00065       } else if (is_ctl(input)) {
00066         return false;
00067       
00068       } else {
00069         req.uri.push_back(input);
00070         return boost::indeterminate;
00071       }
00072     
00073     case http_version_h:
00074       if (input == 'H') {
00075         state_ = http_version_t_1;
00076         return boost::indeterminate;
00077       
00078       } else {
00079         return false;
00080       }
00081     
00082     case http_version_t_1:
00083       if (input == 'T') {
00084         state_ = http_version_t_2;
00085         return boost::indeterminate;
00086       
00087       } else {
00088         return false;
00089       }
00090     
00091     case http_version_t_2:
00092       if (input == 'T') {
00093         state_ = http_version_p;
00094         return boost::indeterminate;
00095       
00096       } else {
00097         return false;
00098       }
00099     
00100     case http_version_p:
00101       if (input == 'P') {
00102         state_ = http_version_slash;
00103         return boost::indeterminate;
00104       
00105       } else {
00106         return false;
00107       }
00108     
00109     case http_version_slash:
00110       if (input == '/') {
00111         req.http_version_major = 0;
00112         req.http_version_minor = 0;
00113         state_ = http_version_major_start;
00114         return boost::indeterminate;
00115       
00116       } else {
00117         return false;
00118       }
00119     
00120     case http_version_major_start:
00121       if (is_digit(input)) {
00122         req.http_version_major = req.http_version_major * 10 + input - '0';
00123         state_ = http_version_major;
00124         return boost::indeterminate;
00125       
00126       } else {
00127         return false;
00128       }
00129     
00130     case http_version_major:
00131       if (input == '.') {
00132         state_ = http_version_minor_start;
00133         return boost::indeterminate;
00134       
00135       } else if (is_digit(input)) {
00136         req.http_version_major = req.http_version_major * 10 + input - '0';
00137         return boost::indeterminate;
00138       
00139       } else {
00140         return false;
00141       }
00142     
00143     case http_version_minor_start:
00144       if (is_digit(input)) {
00145         req.http_version_minor = req.http_version_minor * 10 + input - '0';
00146         state_ = http_version_minor;
00147         return boost::indeterminate;
00148       
00149       } else {
00150         return false;
00151       }
00152     
00153     case http_version_minor:
00154       if (input == '\r') {
00155         state_ = expecting_newline_1;
00156         return boost::indeterminate;
00157       
00158       } else if (is_digit(input)) {
00159         req.http_version_minor = req.http_version_minor * 10 + input - '0';
00160         return boost::indeterminate;
00161       
00162       } else {
00163         return false;
00164       }
00165     
00166     case expecting_newline_1:
00167       if (input == '\n') {
00168         state_ = header_line_start;
00169         return boost::indeterminate;
00170       
00171       } else {
00172         return false;
00173       }
00174     
00175     case header_line_start:
00176       if (input == '\r') {
00177         state_ = expecting_newline_3;
00178         return boost::indeterminate;
00179       
00180       } else if (!is_char(input) || is_ctl(input) || is_tspecial(input)) {
00181         return false;
00182       
00183       } else {
00184         state_ = header_name;
00185         return boost::indeterminate;
00186       }
00187     
00188     case header_lws:
00189       if (input == '\r') {
00190         state_ = expecting_newline_2;
00191         return boost::indeterminate;
00192       
00193       } else if (input == ' ' || input == '\t') {
00194         return boost::indeterminate;
00195       
00196       } else if (is_ctl(input)) {
00197         return false;
00198       
00199       } else {
00200         state_ = header_value;
00201         return boost::indeterminate;
00202       }
00203     
00204     case header_name:
00205       if (input == ':') {
00206         state_ = space_before_header_value;
00207         return boost::indeterminate;
00208       
00209       } else if (!is_char(input) || is_ctl(input) || is_tspecial(input)) {
00210         return false;
00211       
00212       } else {
00213         return boost::indeterminate;
00214       }
00215     
00216     case space_before_header_value:
00217       if (input == ' ') {
00218         state_ = header_value;
00219         return boost::indeterminate;
00220       
00221       } else {
00222         return false;
00223       }
00224     
00225     case header_value:
00226       if (input == '\r') {
00227         state_ = expecting_newline_2;
00228         return boost::indeterminate;
00229       
00230       } else if (is_ctl(input)) {
00231         return false;
00232       
00233       } else {
00234         return boost::indeterminate;
00235       }
00236     
00237     case expecting_newline_2:
00238       if (input == '\n') {
00239         state_ = header_line_start;
00240         return boost::indeterminate;
00241       
00242       } else {
00243         return false;
00244       }
00245     
00246     case expecting_newline_3:
00247       return (input == '\n');
00248     
00249     default:
00250       return false;
00251     }
00252   }
00253 
00254   // //////////////////////////////////////////////////////////////////////
00255   bool RequestParser::is_char(int c) {
00256     return c >= 0 && c <= 127;
00257   }
00258 
00259   // //////////////////////////////////////////////////////////////////////
00260   bool RequestParser::is_ctl(int c) {
00261     return (c >= 0 && c <= 31) || (c == 127);
00262   }
00263 
00264   // //////////////////////////////////////////////////////////////////////
00265   bool RequestParser::is_tspecial(int c) {
00266     switch (c) {
00267     case '(': case ')': case '<': case '>': case '@':
00268     case ',': case ';': case ':': case '\\': case '"':
00269     case '/': case '[': case ']': case '?': case '=':
00270     case '{': case '}': case ' ': case '\t':
00271       return true;
00272     default:
00273       return false;
00274     }
00275   }
00276 
00277   // //////////////////////////////////////////////////////////////////////
00278   bool RequestParser::is_digit(int c) {
00279     return c >= '0' && c <= '9';
00280   }
00281 
00282 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines