]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/spirit/include/boost/spirit/home/classic/utility/impl/escape_char.ipp
bump version to 12.2.2-pve1
[ceph.git] / ceph / src / boost / libs / spirit / include / boost / spirit / home / classic / utility / impl / escape_char.ipp
1 /*=============================================================================
2 Copyright (c) 2001-2003 Daniel Nuffer
3 Copyright (c) 2002-2003 Hartmut Kaiser
4 http://spirit.sourceforge.net/
5
6 Use, modification and distribution is subject to the Boost Software
7 License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
8 http://www.boost.org/LICENSE_1_0.txt)
9 =============================================================================*/
10 #ifndef BOOST_SPIRIT_ESCAPE_CHAR_IPP
11 #define BOOST_SPIRIT_ESCAPE_CHAR_IPP
12
13 #include <boost/spirit/home/classic/core/parser.hpp>
14 #include <boost/spirit/home/classic/core/primitives/numerics.hpp>
15 #include <boost/spirit/home/classic/core/composite/difference.hpp>
16 #include <boost/spirit/home/classic/core/composite/sequence.hpp>
17
18 ///////////////////////////////////////////////////////////////////////////////
19 namespace boost { namespace spirit {
20
21 BOOST_SPIRIT_CLASSIC_NAMESPACE_BEGIN
22
23 ///////////////////////////////////////////////////////////////////////////////
24 //
25 // escape_char_parser class
26 //
27 ///////////////////////////////////////////////////////////////////////////////
28
29 const unsigned long c_escapes = 1;
30 const unsigned long lex_escapes = c_escapes << 1;
31
32 //////////////////////////////////
33 namespace impl {
34
35 //////////////////////////////////
36 #if (defined(BOOST_MSVC) && (BOOST_MSVC <= 1310))
37 #pragma warning(push)
38 #pragma warning(disable:4127)
39 #endif
40 template <unsigned long Flags, typename CharT>
41 struct escape_char_action_parse {
42
43 template <typename ParserT, typename ScannerT>
44 static typename parser_result<ParserT, ScannerT>::type
45 parse(ScannerT const& scan, ParserT const &p)
46 {
47 // Actually decode the escape char.
48 typedef CharT char_t;
49 typedef typename ScannerT::iterator_t iterator_t;
50 typedef typename parser_result<ParserT, ScannerT>::type result_t;
51
52 if (scan.first != scan.last) {
53
54 iterator_t save = scan.first;
55 if (result_t hit = p.subject().parse(scan)) {
56
57 char_t unescaped;
58
59 scan.first = save;
60 if (*scan.first == '\\') {
61
62 ++scan.first;
63 switch (*scan.first) {
64 case 'b': unescaped = '\b'; ++scan.first; break;
65 case 't': unescaped = '\t'; ++scan.first; break;
66 case 'n': unescaped = '\n'; ++scan.first; break;
67 case 'f': unescaped = '\f'; ++scan.first; break;
68 case 'r': unescaped = '\r'; ++scan.first; break;
69 case '"': unescaped = '"'; ++scan.first; break;
70 case '\'': unescaped = '\''; ++scan.first; break;
71 case '\\': unescaped = '\\'; ++scan.first; break;
72
73 case 'x': case 'X':
74 {
75 char_t hex = 0;
76 char_t const lim =
77 (std::numeric_limits<char_t>::max)() >> 4;
78
79 ++scan.first;
80 while (scan.first != scan.last)
81 {
82 char_t c = *scan.first;
83 if (hex > lim && impl::isxdigit_(c))
84 {
85 // overflow detected
86 scan.first = save;
87 return scan.no_match();
88 }
89 if (impl::isdigit_(c))
90 {
91 hex <<= 4;
92 hex |= c - '0';
93 ++scan.first;
94 }
95 else if (impl::isxdigit_(c))
96 {
97 hex <<= 4;
98 c = impl::toupper_(c);
99 hex |= c - 'A' + 0xA;
100 ++scan.first;
101 }
102 else
103 {
104 break; // reached the end of the number
105 }
106 }
107 unescaped = hex;
108 }
109 break;
110
111 case '0': case '1': case '2': case '3':
112 case '4': case '5': case '6': case '7':
113 {
114 char_t oct = 0;
115 char_t const lim =
116 (std::numeric_limits<char_t>::max)() >> 3;
117 while (scan.first != scan.last)
118 {
119 char_t c = *scan.first;
120 if (oct > lim && (c >= '0' && c <= '7'))
121 {
122 // overflow detected
123 scan.first = save;
124 return scan.no_match();
125 }
126
127 if (c >= '0' && c <= '7')
128 {
129 oct <<= 3;
130 oct |= c - '0';
131 ++scan.first;
132 }
133 else
134 {
135 break; // reached end of digits
136 }
137 }
138 unescaped = oct;
139 }
140 break;
141
142 default:
143 if (Flags & c_escapes)
144 {
145 // illegal C escape sequence
146 scan.first = save;
147 return scan.no_match();
148 }
149 else
150 {
151 unescaped = *scan.first;
152 ++scan.first;
153 }
154 break;
155 }
156 }
157 else {
158 unescaped = *scan.first;
159 ++scan.first;
160 }
161
162 scan.do_action(p.predicate(), unescaped, save, scan.first);
163 return hit;
164 }
165 }
166 return scan.no_match(); // overflow detected
167 }
168 };
169 #if (defined(BOOST_MSVC) && (BOOST_MSVC <= 1310))
170 #pragma warning(pop)
171 #endif
172
173 //////////////////////////////////
174 template <typename CharT>
175 struct escape_char_parse {
176
177 template <typename ScannerT, typename ParserT>
178 static typename parser_result<ParserT, ScannerT>::type
179 parse(ScannerT const &scan, ParserT const &/*p*/)
180 {
181 typedef
182 uint_parser<CharT, 8, 1,
183 std::numeric_limits<CharT>::digits / 3 + 1
184 >
185 oct_parser_t;
186 typedef
187 uint_parser<CharT, 16, 1,
188 std::numeric_limits<CharT>::digits / 4 + 1
189 >
190 hex_parser_t;
191
192 typedef alternative<difference<anychar_parser, chlit<CharT> >,
193 sequence<chlit<CharT>, alternative<alternative<oct_parser_t,
194 sequence<inhibit_case<chlit<CharT> >, hex_parser_t > >,
195 difference<difference<anychar_parser,
196 inhibit_case<chlit<CharT> > >, oct_parser_t > > > >
197 parser_t;
198
199 static parser_t p =
200 ( (anychar_p - chlit<CharT>(CharT('\\')))
201 | (chlit<CharT>(CharT('\\')) >>
202 ( oct_parser_t()
203 | as_lower_d[chlit<CharT>(CharT('x'))] >> hex_parser_t()
204 | (anychar_p - as_lower_d[chlit<CharT>(CharT('x'))] - oct_parser_t())
205 )
206 ));
207
208 BOOST_SPIRIT_DEBUG_TRACE_NODE(p,
209 (BOOST_SPIRIT_DEBUG_FLAGS & BOOST_SPIRIT_DEBUG_FLAGS_ESCAPE_CHAR) != 0);
210
211 return p.parse(scan);
212 }
213 };
214
215 ///////////////////////////////////////////////////////////////////////////////
216 } // namespace impl
217
218 ///////////////////////////////////////////////////////////////////////////////
219 BOOST_SPIRIT_CLASSIC_NAMESPACE_END
220
221 }} // namespace boost::spirit
222
223 #endif
224