/////////////////////////////////////////////////////////////////////////////// // // Copyright (C) 2008-2012 Artyom Beilis (Tonkikh) // // See accompanying file COPYING.TXT file for licensing details. // /////////////////////////////////////////////////////////////////////////////// #ifndef CPPCMS_HTTP_PARSER_H #define CPPCMS_HTTP_PARSER_H #include "http_protocol.h" #include #include #include #ifdef getc #undef getc #endif namespace cppcms { namespace http { namespace impl { class parser { enum { idle, input_observed, last_lf_exptected, lf_exptected, space_or_other_exptected, quote_expected, pass_quote_exptected, closing_bracket_expected, pass_closing_bracket_expected } state_; unsigned bracket_counter_; std::vector *body_; unsigned *body_ptr_; char const **pbase_,**pptr_,**epptr_; std::stack ungot_; // Non copyable parser(parser const &); parser const &operator=(parser const &); protected: inline int getc() { if(!ungot_.empty()) { unsigned char r=ungot_.top(); ungot_.pop(); return r; } if(body_) { if(*body_ptr_ < body_->size()) { return (unsigned char)(*body_)[(*body_ptr_)++]; } else { body_->clear(); *body_ptr_=0; return -1; } } else { if(*pptr_ != *epptr_) { unsigned char c = *(*pptr_)++; return c; } else { return -1; } } } inline void ungetc(int c) { if(body_) { if(*body_ptr_ > 0) (*body_ptr_)--; else ungot_.push(c); } else { if(*pbase_!=*pptr_) (*pptr_)--; else ungot_.push(c); } } public: std::string header_; parser(std::vector &body,unsigned &body_ptr) : state_(idle), bracket_counter_(0), body_(&body), body_ptr_(&body_ptr), pbase_(0), pptr_(0), epptr_(0) { header_.reserve(32); } parser(char const *&pbase,char const *&pptr,char const *&epptr) : state_(idle), bracket_counter_(0), body_(0), body_ptr_(0), pbase_(&pbase), pptr_(&pptr), epptr_(&epptr) { header_.reserve(32); } void reset() { state_ = idle; bracket_counter_ = 0; header_.clear(); } enum { more_data, got_header, end_of_headers , error_observerd }; int step() { #ifdef DEBUG_HTTP_PARSER static char const *states[]= { "idle", "input_observed", "last_lf_exptected", "lf_exptected", "space_or_other_exptected", "quote_expected", "pass_quote_exptected", "closing_bracket_expected", "pass_closing_bracket_expected" }; #endif for(;;) { int c=getc(); #if defined DEBUG_HTTP_PARSER std::cerr<<"Step("<=32) std::cerr<<"["<=127) return error_observerd; state_=quote_expected; break; case closing_bracket_expected: switch(c) { case ')': bracket_counter_--; if(bracket_counter_==0) state_=input_observed; break; case '\\': state_=pass_closing_bracket_expected; break; } break; case pass_closing_bracket_expected: if(c < 0 || c >=127) return error_observerd; state_=closing_bracket_expected; break; } header_+=char(c); /* switch(state_) { case idle: case input_observed: case last_lf_exptected: case lf_exptected: case space_or_other_exptected: if(separator(c)) { parsed_.push_back(element_type(c,std::string())); } else if(0x20 <= c && c<=0x7E) { if(parsed_.empty() || parsed_.back().first != token_element) { parsed.push_back(element_type(token_element,std::string())); } parsed.back().second+=c; } break; default: ; // Nothing }*/ } } }; // class parser }}} // cppcms::http::impl #endif