1010#include < boost/range/iterator_range.hpp>
1111#include < boost/logic/tribool.hpp>
1212#include < boost/fusion/tuple.hpp>
13+ #include < boost/algorithm/string/classification.hpp>
1314
1415namespace boost {namespace network {namespace http {
1516
@@ -26,9 +27,11 @@ namespace boost { namespace network { namespace http {
2627 , version_t1
2728 , version_t2
2829 , version_p
30+ , version_slash
2931 , version_d1
3032 , version_dot
3133 , version_d2
34+ , version_cr
3235 , version_done
3336 , header_name
3437 , header_colon
@@ -50,7 +53,7 @@ namespace boost { namespace network { namespace http {
5053template <class Range >
5154 fusion::tuple<logic::tribool, iterator_range<typename Range::const_iterator> >
5255parse_until (state_t stop_state, Range & range) {
53- logic::tribool parsed_ok;
56+ logic::tribool parsed_ok = logic::indeterminate ;
5457typedef typename range_iterator<Range>::type iterator;
5558 iterator start =boost::begin (range)
5659 , end =boost::end (range)
@@ -60,12 +63,72 @@ namespace boost { namespace network { namespace http {
6063while (
6164 !boost::empty (local_range)
6265 && stop_state != internal_state
63- &&parsed_ok == logic:: indeterminate
66+ &&indeterminate (parsed_ok)
6467 ) {
68+ current_iterator =boost::begin (local_range);
6569switch (internal_state) {
70+ case method_start:
71+ if (algorithm::is_upper ()(*current_iterator)) internal_state = method_char;
72+ else parsed_ok =false ;
73+ break ;
74+ case method_char:
75+ if (algorithm::is_upper ()(*current_iterator))break ;
76+ else if (algorithm::is_space ()(*current_iterator)) internal_state = method_done;
77+ else parsed_ok =false ;
78+ break ;
79+ case method_done:
80+ if (algorithm::is_cntrl ()(*current_iterator)) parsed_ok =false ;
81+ else if (algorithm::is_space ()(*current_iterator)) parsed_ok =false ;
82+ else internal_state = uri_char;
83+ break ;
84+ case uri_char:
85+ if (algorithm::is_cntrl ()(*current_iterator)) parsed_ok =false ;
86+ else if (algorithm::is_space ()(*current_iterator)) internal_state = uri_done;
87+ break ;
88+ case uri_done:
89+ if (*current_iterator ==' H' ) internal_state = version_h;
90+ else parsed_ok =false ;
91+ break ;
92+ case version_h:
93+ if (*current_iterator ==' T' ) internal_state = version_t1;
94+ else parsed_ok =false ;
95+ break ;
96+ case version_t1:
97+ if (*current_iterator ==' T' ) internal_state = version_t2;
98+ else parsed_ok =false ;
99+ break ;
100+ case version_t2:
101+ if (*current_iterator ==' P' ) internal_state = version_p;
102+ else parsed_ok =false ;
103+ break ;
104+ case version_p:
105+ if (*current_iterator ==' /' ) internal_state = version_slash;
106+ else parsed_ok =false ;
107+ break ;
108+ case version_slash:
109+ if (algorithm::is_digit ()(*current_iterator)) internal_state = version_d1;
110+ else parsed_ok =false ;
111+ break ;
112+ case version_d1:
113+ if (*current_iterator ==' .' ) internal_state = version_dot;
114+ else parsed_ok =false ;
115+ break ;
116+ case version_dot:
117+ if (algorithm::is_digit ()(*current_iterator)) internal_state = version_d2;
118+ else parsed_ok =false ;
119+ break ;
120+ case version_d2:
121+ if (*current_iterator ==' \r ' ) internal_state = version_cr;
122+ else parsed_ok =false ;
123+ break ;
124+ case version_cr:
125+ if (*current_iterator ==' \n ' ) internal_state = version_done;
126+ else parsed_ok =false ;
127+ break ;
66128default :
67129 parsed_ok =false ;
68130 };
131+ if (internal_state == stop_state) parsed_ok =true ;
69132 local_range =boost::make_iterator_range (
70133 ++current_iterator, end);
71134 }