pg_async
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
protocol_parsers.hpp
Go to the documentation of this file.
1 /*
2  * protocol_parsers.hpp
3  *
4  * Created on: Jul 19, 2015
5  * Author: zmij
6  */
7 
8 #ifndef LIB_PG_ASYNC_SRC_TIP_DB_PG_DETAIL_PROTOCOL_PARSERS_HPP_
9 #define LIB_PG_ASYNC_SRC_TIP_DB_PG_DETAIL_PROTOCOL_PARSERS_HPP_
10 
11 #include <boost/logic/tribool.hpp>
12 #include <algorithm>
13 #include <cctype>
14 
15 namespace tip {
16 namespace db {
17 namespace pg {
18 namespace io {
19 namespace detail {
20 
21 class bytea_parser {
22 
23  enum state {
24  expecting_backslash,
25  expecting_x,
26  nibble_one,
27  nibble_two
28  } state_;
29  char most_sighificant_nibble_;
30 public:
31  bytea_parser() : state_(expecting_backslash), most_sighificant_nibble_(0) {}
32 
33  template < typename InputIterator, typename OutputIterator >
34  std::pair< boost::tribool, InputIterator >
35  parse(InputIterator begin, InputIterator end, OutputIterator data)
36  {
37  boost::tribool result = boost::indeterminate;
38  while (begin != end) {
39  result = consume(data, *begin++);
40  }
41  return std::make_pair(result, begin);
42  }
43 
44  void
46  {
47  state_ = expecting_backslash;
48  most_sighificant_nibble_ = 0;
49  }
50 private:
51  template < typename OutputIterator >
52  boost::tribool
53  consume( OutputIterator data, char input )
54  {
55  switch (state_) {
56  case expecting_backslash:
57  if (input == '\\') {
58  state_ = expecting_x;
59  return boost::indeterminate;
60  } else {
61  return false;
62  }
63  case expecting_x:
64  if (input == 'x') {
65  state_ = nibble_one;
66  return true;
67  } else {
68  return false;
69  }
70  case nibble_one:
71  if (std::isxdigit(input)) {
72  most_sighificant_nibble_ = hex_to_byte(input);
73  state_ = nibble_two;
74  return boost::indeterminate;
75  } else {
76  return false;
77  }
78  case nibble_two:
79  if (std::isxdigit(input)) {
80  *data++ = (hex_to_byte(input) << 4) | most_sighificant_nibble_;
81  state_ = nibble_one;
82  return true;
83  } else {
84  return false;
85  }
86  default:
87  break;
88  }
89  }
90 
91  static char
92  hex_to_byte(char);
93 };
94 
95 } // namespace detail
96 } // namespace io
97 } // namespace pg
98 } // namespace db
99 } // namespace tip
100 
101 
102 #endif /* LIB_PG_ASYNC_SRC_TIP_DB_PG_DETAIL_PROTOCOL_PARSERS_HPP_ */
std::pair< boost::tribool, InputIterator > parse(InputIterator begin, InputIterator end, OutputIterator data)