]> git.proxmox.com Git - ceph.git/blame - ceph/src/boost/boost/wave/util/macro_helpers.hpp
import quincy beta 17.1.0
[ceph.git] / ceph / src / boost / boost / wave / util / macro_helpers.hpp
CommitLineData
7c673cae
FG
1/*=============================================================================
2 Boost.Wave: A Standard compliant C++ preprocessor library
3
4 http://www.boost.org/
5
6 Copyright (c) 2001-2012 Hartmut Kaiser. Distributed under the Boost
7 Software License, Version 1.0. (See accompanying file
8 LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
9=============================================================================*/
10
20effc67
TL
11#if !defined(BOOST_MACRO_HELPERS_HPP_931BBC99_EBFA_4692_8FBE_B555998C2C39_INCLUDED)
12#define BOOST_MACRO_HELPERS_HPP_931BBC99_EBFA_4692_8FBE_B555998C2C39_INCLUDED
7c673cae
FG
13
14#include <vector>
15
16#include <boost/assert.hpp>
17#include <boost/wave/wave_config.hpp>
18#include <boost/wave/token_ids.hpp>
19#include <boost/wave/cpplexer/validate_universal_char.hpp>
20#include <boost/wave/util/unput_queue_iterator.hpp>
21
22// this must occur after all of the includes and before any code appears
23#ifdef BOOST_HAS_ABI_HEADERS
24#include BOOST_ABI_PREFIX
25#endif
26
27///////////////////////////////////////////////////////////////////////////////
28namespace boost {
29namespace wave {
30namespace util {
31
32namespace impl {
33
34 // escape a string literal (insert '\\' before every '\"', '?' and '\\')
35 template <typename StringT>
36 inline StringT
37 escape_lit(StringT const &value)
38 {
39 StringT result;
40 typename StringT::size_type pos = 0;
41 typename StringT::size_type pos1 = value.find_first_of ("\"\\?", 0);
42 if (StringT::npos != pos1) {
43 do {
b32b8144
FG
44 result += value.substr(pos, pos1-pos)
45 + StringT("\\")
7c673cae
FG
46 + StringT(1, value[pos1]);
47 pos1 = value.find_first_of ("\"\\?", pos = pos1+1);
48 } while (StringT::npos != pos1);
49 result += value.substr(pos);
50 }
51 else {
52 result = value;
53 }
54 return result;
55 }
56
57 // un-escape a string literal (remove '\\' just before '\\', '\"' or '?')
58 template <typename StringT>
59 inline StringT
60 unescape_lit(StringT const &value)
61 {
62 StringT result;
63 typename StringT::size_type pos = 0;
64 typename StringT::size_type pos1 = value.find_first_of ("\\", 0);
65 if (StringT::npos != pos1) {
66 do {
67 switch (value[pos1+1]) {
68 case '\\':
69 case '\"':
70 case '?':
71 result = result + value.substr(pos, pos1-pos);
72 pos1 = value.find_first_of ("\\", (pos = pos1+1)+1);
73 break;
74
75 case 'n':
76 result = result + value.substr(pos, pos1-pos) + "\n";
77 pos1 = value.find_first_of ("\\", pos = pos1+1);
78 ++pos;
79 break;
80
81 default:
82 result = result + value.substr(pos, pos1-pos+1);
83 pos1 = value.find_first_of ("\\", pos = pos1+1);
84 }
85
86 } while (pos1 != StringT::npos);
87 result = result + value.substr(pos);
88 }
89 else {
90 // the string doesn't contain any escaped character sequences
91 result = value;
92 }
93 return result;
94 }
95
96 // return the string representation of a token sequence
97 template <typename ContainerT, typename PositionT>
98 inline typename ContainerT::value_type::string_type
99 as_stringlit (ContainerT const &token_sequence, PositionT const &pos)
100 {
101 using namespace boost::wave;
102 typedef typename ContainerT::value_type::string_type string_type;
103
104 string_type result("\"");
105 bool was_whitespace = false;
106 typename ContainerT::const_iterator end = token_sequence.end();
b32b8144
FG
107 for (typename ContainerT::const_iterator it = token_sequence.begin();
108 it != end; ++it)
7c673cae
FG
109 {
110 token_id id = token_id(*it);
111
112 if (IS_CATEGORY(*it, WhiteSpaceTokenType) || T_NEWLINE == id) {
113 if (!was_whitespace) {
114 // C++ standard 16.3.2.2 [cpp.stringize]
b32b8144
FG
115 // Each occurrence of white space between the argument's
116 // preprocessing tokens becomes a single space character in the
7c673cae
FG
117 // character string literal.
118 result += " ";
119 was_whitespace = true;
120 }
121 }
122 else if (T_STRINGLIT == id || T_CHARLIT == id) {
123 // string literals and character literals have to be escaped
124 result += impl::escape_lit((*it).get_value());
125 was_whitespace = false;
126 }
b32b8144 127 else
7c673cae 128#if BOOST_WAVE_SUPPORT_VARIADICS_PLACEMARKERS != 0
b32b8144
FG
129 if (T_PLACEMARKER != id)
130#endif
7c673cae
FG
131 {
132 // now append this token to the string
133 result += (*it).get_value();
134 was_whitespace = false;
135 }
136 }
137 result += "\"";
138
139 // validate the resulting literal to contain no invalid universal character
140 // value (throws if invalid chars found)
b32b8144
FG
141 boost::wave::cpplexer::impl::validate_literal(result, pos.get_line(),
142 pos.get_column(), pos.get_file());
7c673cae
FG
143 return result;
144 }
145
146#if BOOST_WAVE_SUPPORT_VARIADICS_PLACEMARKERS != 0
147 // return the string representation of a token sequence
148 template <typename ContainerT, typename PositionT>
149 inline typename ContainerT::value_type::string_type
b32b8144 150 as_stringlit (std::vector<ContainerT> const &arguments,
7c673cae
FG
151 typename std::vector<ContainerT>::size_type i, PositionT const &pos)
152 {
153 using namespace boost::wave;
154 typedef typename ContainerT::value_type::string_type string_type;
155
156 BOOST_ASSERT(i < arguments.size());
157
158 string_type result("\"");
159 bool was_whitespace = false;
160
161 for (/**/; i < arguments.size(); ++i) {
162 // stringize all remaining arguments
163 typename ContainerT::const_iterator end = arguments[i].end();
b32b8144
FG
164 for (typename ContainerT::const_iterator it = arguments[i].begin();
165 it != end; ++it)
7c673cae
FG
166 {
167 token_id id = token_id(*it);
b32b8144 168
7c673cae
FG
169 if (IS_CATEGORY(*it, WhiteSpaceTokenType) || T_NEWLINE == id) {
170 if (!was_whitespace) {
171 // C++ standard 16.3.2.2 [cpp.stringize]
b32b8144
FG
172 // Each occurrence of white space between the argument's
173 // preprocessing tokens becomes a single space character in the
7c673cae
FG
174 // character string literal.
175 result += " ";
176 was_whitespace = true;
177 }
178 }
179 else if (T_STRINGLIT == id || T_CHARLIT == id) {
180 // string literals and character literals have to be escaped
181 result += impl::escape_lit((*it).get_value());
182 was_whitespace = false;
183 }
184 else if (T_PLACEMARKER != id) {
185 // now append this token to the string
186 result += (*it).get_value();
187 was_whitespace = false;
188 }
189 }
190
191 // append comma, if not last argument
192 if (i < arguments.size()-1) {
193 result += ",";
194 was_whitespace = false;
195 }
196 }
197 result += "\"";
198
199 // validate the resulting literal to contain no invalid universal character
200 // value (throws if invalid chars found)
b32b8144
FG
201 boost::wave::cpplexer::impl::validate_literal(result, pos.get_line(),
202 pos.get_column(), pos.get_file());
7c673cae
FG
203 return result;
204 }
205#endif // BOOST_WAVE_SUPPORT_VARIADICS_PLACEMARKERS != 0
206
207 // return the string representation of a token sequence
208 template <typename StringT, typename IteratorT>
209 inline StringT
210 as_string(IteratorT it, IteratorT const& end)
211 {
212 StringT result;
b32b8144 213 for (/**/; it != end; ++it)
7c673cae
FG
214 {
215 result += (*it).get_value();
216 }
217 return result;
218 }
219
220 // return the string representation of a token sequence
221 template <typename ContainerT>
222 inline typename ContainerT::value_type::string_type
223 as_string (ContainerT const &token_sequence)
224 {
225 typedef typename ContainerT::value_type::string_type string_type;
b32b8144 226 return as_string<string_type>(token_sequence.begin(),
7c673cae
FG
227 token_sequence.end());
228 }
229
230#if BOOST_WAVE_SUPPORT_VARIADICS_PLACEMARKERS != 0
231 ///////////////////////////////////////////////////////////////////////////
232 //
b32b8144 233 // Copies all arguments beginning with the given index to the output
7c673cae
FG
234 // sequence. The arguments are separated by commas.
235 //
236 template <typename ContainerT, typename PositionT>
237 void replace_ellipsis (std::vector<ContainerT> const &arguments,
b32b8144 238 typename ContainerT::size_type index,
7c673cae
FG
239 ContainerT &expanded, PositionT const &pos)
240 {
241 using namespace cpplexer;
242 typedef typename ContainerT::value_type token_type;
b32b8144 243
7c673cae
FG
244 token_type comma(T_COMMA, ",", pos);
245 for (/**/; index < arguments.size(); ++index) {
246 ContainerT const &arg = arguments[index];
247
b32b8144 248 std::copy(arg.begin(), arg.end(),
7c673cae 249 std::inserter(expanded, expanded.end()));
b32b8144
FG
250
251 if (index < arguments.size()-1)
7c673cae
FG
252 expanded.push_back(comma);
253 }
254 }
20effc67
TL
255
256#if BOOST_WAVE_SUPPORT_VA_OPT != 0
257 ///////////////////////////////////////////////////////////////////////////
258 //
259 // Finds the token range inside __VA_OPT__.
260 // Updates mdit to the position of the final rparen.
261 // If the parenthesis do not match up, or there are none, returns false
262 // and leaves mdit unchanged.
263 //
264 template <typename MDefIterT>
265 bool find_va_opt_args (
266 MDefIterT & mdit, // VA_OPT
267 MDefIterT mdend)
268 {
269 if ((std::distance(mdit, mdend) < 3) ||
270 (T_LEFTPAREN != next_token<MDefIterT>::peek(mdit, mdend))) {
271 return false;
272 }
273
274 MDefIterT mdstart_it = mdit;
275 ++mdit; // skip to lparen
276 std::size_t scope = 0;
277 // search for final rparen, leaving iterator there
278 for (; (mdit != mdend) && !((scope == 1) && (T_RIGHTPAREN == token_id(*mdit)));
279 ++mdit) {
280 // count balanced parens
281 if (T_RIGHTPAREN == token_id(*mdit)) {
282 scope--;
283 } else if (T_LEFTPAREN == token_id(*mdit)) {
284 scope++;
285 }
286 }
287 if ((mdit == mdend) && ((scope != 1) || (T_RIGHTPAREN != token_id(*mdit)))) {
288 // arrived at end without matching rparen
289 mdit = mdstart_it;
290 return false;
291 }
292
293 return true;
294 }
295
296#endif
7c673cae
FG
297#endif
298
299 // Skip all whitespace characters and queue the skipped characters into the
300 // given container
301 template <typename IteratorT>
b32b8144 302 inline boost::wave::token_id
7c673cae
FG
303 skip_whitespace(IteratorT &first, IteratorT const &last)
304 {
305 token_id id = util::impl::next_token<IteratorT>::peek(first, last, false);
306 if (IS_CATEGORY(id, WhiteSpaceTokenType)) {
307 do {
308 ++first;
309 id = util::impl::next_token<IteratorT>::peek(first, last, false);
310 } while (IS_CATEGORY(id, WhiteSpaceTokenType));
311 }
312 ++first;
313 return id;
314 }
315
316 template <typename IteratorT, typename ContainerT>
b32b8144 317 inline boost::wave::token_id
7c673cae
FG
318 skip_whitespace(IteratorT &first, IteratorT const &last, ContainerT &queue)
319 {
320 queue.push_back (*first); // queue up the current token
321
322 token_id id = util::impl::next_token<IteratorT>::peek(first, last, false);
323 if (IS_CATEGORY(id, WhiteSpaceTokenType)) {
324 do {
b32b8144 325 queue.push_back(*++first); // queue up the next whitespace
7c673cae
FG
326 id = util::impl::next_token<IteratorT>::peek(first, last, false);
327 } while (IS_CATEGORY(id, WhiteSpaceTokenType));
328 }
329 ++first;
330 return id;
331 }
332
20effc67
TL
333 // trim all whitespace from the beginning and the end of the given string
334 template <typename StringT>
335 inline StringT
336 trim_whitespace(StringT const &s)
337 {
338 typedef typename StringT::size_type size_type;
339
340 size_type first = s.find_first_not_of(" \t\v\f");
341 if (StringT::npos == first)
342 return StringT();
343 size_type last = s.find_last_not_of(" \t\v\f");
344 return s.substr(first, last-first+1);
345 }
346
7c673cae
FG
347} // namespace impl
348
349///////////////////////////////////////////////////////////////////////////////
350} // namespace util
351} // namespace wave
352} // namespace boost
353
354// the suffix header occurs after all of the code
355#ifdef BOOST_HAS_ABI_HEADERS
356#include BOOST_ABI_SUFFIX
357#endif
358
20effc67 359#endif // !defined(BOOST_MACRO_HELPERS_HPP_931BBC99_EBFA_4692_8FBE_B555998C2C39_INCLUDED)