Telnet++  3.1.0.2
A C++ library for interacting with Telnet streams
request_parser_helper.hpp
1 #pragma once
2 
3 #include "telnetpp/options/new_environ/detail/stream.hpp"
4 #include "telnetpp/options/new_environ/protocol.hpp"
5 
6 #include <cassert>
7 
8 namespace telnetpp::options::new_environ::detail {
9 
10 enum class request_parser_state
11 {
12  state_send,
13  state_type,
14  state_name,
15  state_name_esc,
16 };
17 
18 struct request_parsing_state
19 {
20  request_parser_state state = request_parser_state::state_send;
21  request req;
22 };
23 
24 // ==========================================================================
25 // PARSE_REQUEST_SEND
26 // ==========================================================================
27 template <typename Continuation>
28 void parse_request_send(
29  request_parsing_state &state,
30  telnetpp::bytes::iterator /*current*/,
31  Continuation && /*cont*/)
32 {
33  state.state = request_parser_state::state_type;
34 }
35 
36 // ==========================================================================
37 // PARSE_REQUEST_TYPE
38 // ==========================================================================
39 template <typename Continuation>
40 void parse_request_type(
41  request_parsing_state &state,
42  telnetpp::bytes::iterator current,
43  Continuation && /*cont*/)
44 {
45  state.req.type = byte_to_type(*current);
46  state.state = request_parser_state::state_name;
47 }
48 
49 // ==========================================================================
50 // PARSE_REQUEST_NAME
51 // ==========================================================================
52 template <typename Continuation>
53 void parse_request_name(
54  request_parsing_state &state,
55  telnetpp::bytes::iterator current,
56  Continuation &&cont)
57 {
58  switch (*current)
59  {
60  case detail::esc:
61  state.state = request_parser_state::state_name_esc;
62  break;
63 
64  case detail::var: // Fall-through
65  case detail::uservar:
66  cont(state.req);
67  state.req = {};
68  state.req.type = byte_to_type(*current);
69  break;
70 
71  default:
72  state.req.name.push_back(*current);
73  break;
74  }
75 }
76 
77 // ==========================================================================
78 // PARSE_REQUEST_NAME_ESC
79 // ==========================================================================
80 template <typename Continuation>
81 void parse_request_name_esc(
82  request_parsing_state &state,
83  telnetpp::bytes::iterator current,
84  Continuation && /*cont*/)
85 {
86  state.req.name.push_back(*current);
87  state.state = request_parser_state::state_name;
88 }
89 
90 // ==========================================================================
91 // PARSE_REQUEST_BYTE
92 // ==========================================================================
93 template <typename Continuation>
94 void parse_request_byte(
95  request_parsing_state &state,
96  telnetpp::bytes::iterator current,
97  Continuation &&cont)
98 {
99  switch (state.state)
100  {
101  case request_parser_state::state_send:
102  parse_request_send(state, current, cont);
103  break;
104 
105  case request_parser_state::state_type:
106  parse_request_type(state, current, cont);
107  break;
108 
109  case request_parser_state::state_name:
110  parse_request_name(state, current, cont);
111  break;
112 
113  case request_parser_state::state_name_esc:
114  parse_request_name_esc(state, current, cont);
115  break;
116 
117  default:
118  assert(!"Invalid state in request parser");
119  break;
120  }
121 }
122 
123 // ==========================================================================
124 // PARSE_REQUEST_BYTE
125 // ==========================================================================
126 template <typename Continuation>
127 void parse_request_end(request_parsing_state &state, Continuation &&cont)
128 {
129  if (!state.req.name.empty())
130  {
131  cont(state.req);
132  }
133 }
134 
135 } // namespace telnetpp::options::new_environ::detail