Telnet++  3.1.0.2
A C++ library for interacting with Telnet streams
response_parser_helper.hpp
1 #pragma once
2 
3 #include "telnetpp/options/new_environ/detail/protocol.hpp"
4 #include "telnetpp/options/new_environ/detail/stream.hpp"
5 
6 #include <cassert>
7 
8 namespace telnetpp::options::new_environ::detail {
9 
10 constexpr telnetpp::byte type_to_byte(variable_type type)
11 {
12  return type == variable_type::var
13  ? telnetpp::options::new_environ::detail::var
14  : telnetpp::options::new_environ::detail::uservar;
15 }
16 
17 enum class parser_state
18 {
19  state_is_or_info,
20  state_type,
21  state_name,
22  state_name_esc,
23  state_value,
24  state_value_esc,
25 };
26 
27 struct parsing_state
28 {
29  parser_state state = parser_state::state_is_or_info;
30  response rsp;
31 };
32 
33 template <typename Continuation>
34 void parse_is_or_info(
35  telnetpp::bytes::iterator /*current*/,
36  parsing_state &state,
37  Continuation && /*cont*/)
38 {
39  state.state = parser_state::state_type;
40 }
41 
42 template <typename Continuation>
43 void parse_type(
44  telnetpp::bytes::iterator current,
45  parsing_state &state,
46  Continuation && /*cont*/)
47 {
48  state.rsp.type = byte_to_type(*current);
49  state.state = parser_state::state_name;
50 }
51 
52 template <typename Continuation>
53 void parse_name(
54  telnetpp::bytes::iterator current,
55  parsing_state &state,
56  Continuation &&cont)
57 {
58  using namespace telnetpp::literals; // NOLINT
59 
60  switch (*current)
61  {
62  case detail::var: // Fall-through
63  case detail::uservar:
64  cont(state.rsp);
65  state.rsp = {};
66  state.rsp.type = byte_to_type(*current);
67  state.state = parser_state::state_name;
68  break;
69 
70  case detail::esc:
71  state.state = parser_state::state_name_esc;
72  break;
73 
74  case detail::value:
75  state.rsp.value = ""_tb;
76  state.state = parser_state::state_value;
77  break;
78 
79  default:
80  state.rsp.name.push_back(*current);
81  break;
82  }
83 }
84 
85 template <typename Continuation>
86 void parse_name_esc(
87  telnetpp::bytes::iterator current,
88  parsing_state &state,
89  Continuation && /*cont*/)
90 {
91  state.rsp.name.push_back(*current);
92  state.state = parser_state::state_name;
93 }
94 
95 template <typename Continuation>
96 void parse_value(
97  telnetpp::bytes::iterator current,
98  parsing_state &state,
99  Continuation &&cont)
100 {
101  switch (*current)
102  {
103  case detail::var: // Fall-through
104  case detail::uservar:
105  cont(state.rsp);
106  state.rsp = {};
107  state.rsp.type = byte_to_type(*current);
108  state.state = parser_state::state_name;
109  break;
110 
111  case detail::esc:
112  state.state = parser_state::state_value_esc;
113  break;
114 
115  default:
116  state.rsp.value->push_back(*current);
117  break;
118  }
119 }
120 
121 template <typename Continuation>
122 void parse_value_esc(
123  telnetpp::bytes::iterator current,
124  parsing_state &state,
125  Continuation && /*cont*/)
126 {
127  state.rsp.value->push_back(*current);
128  state.state = parser_state::state_value;
129 }
130 
131 template <typename Continuation>
132 void parse_byte(
133  telnetpp::bytes::iterator current,
134  parsing_state &state,
135  Continuation &&cont)
136 {
137  switch (state.state)
138  {
139  case parser_state::state_is_or_info:
140  parse_is_or_info(current, state, cont);
141  break;
142 
143  case parser_state::state_type:
144  parse_type(current, state, cont);
145  break;
146 
147  case parser_state::state_name:
148  parse_name(current, state, cont);
149  break;
150 
151  case parser_state::state_name_esc:
152  parse_name_esc(current, state, cont);
153  break;
154 
155  case parser_state::state_value:
156  parse_value(current, state, cont);
157  break;
158 
159  case parser_state::state_value_esc:
160  parse_value_esc(current, state, cont);
161  break;
162 
163  default:
164  assert(!"Invalid state in NEW_ENVIRON response parser");
165  break;
166  }
167 }
168 
169 template <typename Continuation>
170 void parse_end(parsing_state &state, Continuation &&cont)
171 {
172  if (!state.rsp.name.empty())
173  {
174  cont(state.rsp);
175  }
176 }
177 
178 } // namespace telnetpp::options::new_environ::detail
variable_type
An enumeration of the type of variables that NEW_ENVIRON handles.
Definition: protocol.hpp:13