Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: downloads/boost_1_34_1/boost/wave/util/macro_helpers.hpp @ 29

Last change on this file since 29 was 29, checked in by landauf, 17 years ago

updated boost from 1_33_1 to 1_34_1

File size: 9.4 KB
Line 
1/*=============================================================================
2    Boost.Wave: A Standard compliant C++ preprocessor library
3
4    http://www.boost.org/
5
6    Copyright (c) 2001-2007 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
11#if !defined(MACRO_HELPERS_HPP_931BBC99_EBFA_4692_8FBE_B555998C2C39_INCLUDED)
12#define MACRO_HELPERS_HPP_931BBC99_EBFA_4692_8FBE_B555998C2C39_INCLUDED
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
21// this must occur after all of the includes and before any code appears
22#ifdef BOOST_HAS_ABI_HEADERS
23#include BOOST_ABI_PREFIX
24#endif
25
26///////////////////////////////////////////////////////////////////////////////
27namespace boost {
28namespace wave {
29namespace util {
30
31namespace impl {
32
33    // escape a string literal (insert '\\' before every '\"', '?' and '\\')
34    template <typename StringT>
35    inline StringT
36    escape_lit(StringT const &value)
37    {
38        StringT result;
39        typename StringT::size_type pos = 0;
40        typename StringT::size_type pos1 = value.find_first_of ("\"\\?", 0);
41        if (StringT::npos != pos1) {
42            do {
43                result += value.substr(pos, pos1-pos) 
44                            + StringT("\\") 
45                            + StringT(1, value[pos1]);
46                pos1 = value.find_first_of ("\"\\?", pos = pos1+1);
47            } while (StringT::npos != pos1);
48            result += value.substr(pos);
49        }
50        else {
51            result = value;
52        }
53        return result;
54    }
55
56    // un-escape a string literal (remove '\\' just before '\\', '\"' or '?')
57    template <typename StringT>
58    inline StringT
59    unescape_lit(StringT const &value)
60    {
61        StringT result;
62        typename StringT::size_type pos = 0;
63        typename StringT::size_type pos1 = value.find_first_of ("\\", 0);
64        if (StringT::npos != pos1) {
65            do {
66                if ('\\' == value[pos1+1] || '\"' == value[pos1+1] || 
67                    '?' == value[pos1+1])
68                {
69                    result = result + value.substr(pos, pos1-pos);
70                    pos1 = value.find_first_of ("\\", (pos = pos1+1)+1);
71                }
72                else {
73                    result = result + value.substr(pos, pos1-pos+1);
74                    pos1 = value.find_first_of ("\\", pos = pos1+1);
75                }
76               
77            } while (pos1 != StringT::npos);
78            result = result + value.substr(pos);
79        }
80        else {
81        // the string doesn't contain any escaped character sequences
82            result = value;
83        }
84        return result;
85    }
86   
87    // return the string representation of a token sequence
88    template <typename ContainerT, typename PositionT>
89    inline typename ContainerT::value_type::string_type
90    as_stringlit (ContainerT const &token_sequence, PositionT const &pos)
91    {
92        using namespace boost::wave;
93        typedef typename ContainerT::value_type::string_type string_type;
94       
95        string_type result("\"");
96        bool was_whitespace = false;
97        typename ContainerT::const_iterator end = token_sequence.end();
98        for (typename ContainerT::const_iterator it = token_sequence.begin(); 
99             it != end; ++it) 
100        {
101            token_id id = token_id(*it);
102           
103            if (IS_CATEGORY(*it, WhiteSpaceTokenType) || T_NEWLINE == id) {
104                if (!was_whitespace) {
105                // C++ standard 16.3.2.2 [cpp.stringize]
106                // Each occurrence of white space between the argument’s
107                // preprocessing tokens becomes a single space character in the
108                // character string literal.
109                    result += " ";
110                    was_whitespace = true;
111                }
112            }
113            else if (T_STRINGLIT == id || T_CHARLIT == id) {
114            // string literals and character literals have to be escaped
115                result += impl::escape_lit((*it).get_value());
116                was_whitespace = false;
117            }
118            else 
119#if BOOST_WAVE_SUPPORT_VARIADICS_PLACEMARKERS != 0
120                if (T_PLACEMARKER != id) 
121#endif
122            {
123            // now append this token to the string
124                result += (*it).get_value();
125                was_whitespace = false;
126            }
127        }
128        result += "\"";
129
130    // validate the resulting literal to contain no invalid universal character
131    // value (throws if invalid chars found)
132        boost::wave::cpplexer::impl::validate_literal(result, pos.get_line(), 
133            pos.get_column(), pos.get_file()); 
134        return result;
135    }
136
137#if BOOST_WAVE_SUPPORT_VARIADICS_PLACEMARKERS != 0
138    // return the string representation of a token sequence
139    template <typename ContainerT, typename PositionT>
140    inline typename ContainerT::value_type::string_type
141    as_stringlit (std::vector<ContainerT> const &arguments, 
142        typename std::vector<ContainerT>::size_type i, PositionT const &pos)
143    {
144        using namespace boost::wave;
145        typedef typename ContainerT::value_type::string_type string_type;
146       
147        BOOST_ASSERT(i < arguments.size());
148       
149        string_type result("\"");
150        bool was_whitespace = false;
151       
152        for (/**/; i < arguments.size(); ++i) {
153        // stringize all remaining arguments
154            typename ContainerT::const_iterator end = arguments[i].end();
155            for (typename ContainerT::const_iterator it = arguments[i].begin(); 
156                 it != end; ++it) 
157            {
158                token_id id = token_id(*it);
159               
160                if (IS_CATEGORY(*it, WhiteSpaceTokenType) || T_NEWLINE == id) {
161                    if (!was_whitespace) {
162                    // C++ standard 16.3.2.2 [cpp.stringize]
163                    // Each occurrence of white space between the argument’s
164                    // preprocessing tokens becomes a single space character in the
165                    // character string literal.
166                        result += " ";
167                        was_whitespace = true;
168                    }
169                }
170                else if (T_STRINGLIT == id || T_CHARLIT == id) {
171                // string literals and character literals have to be escaped
172                    result += impl::escape_lit((*it).get_value());
173                    was_whitespace = false;
174                }
175                else if (T_PLACEMARKER != id) {
176                // now append this token to the string
177                    result += (*it).get_value();
178                    was_whitespace = false;
179                }
180            }
181           
182        // append comma, if not last argument
183            if (i < arguments.size()-1) {
184                result += ",";
185                was_whitespace = false;
186            }
187        }
188        result += "\"";
189
190    // validate the resulting literal to contain no invalid universal character
191    // value (throws if invalid chars found)
192        boost::wave::cpplexer::impl::validate_literal(result, pos.get_line(), 
193            pos.get_column(), pos.get_file()); 
194        return result;
195    }
196#endif // BOOST_WAVE_SUPPORT_VARIADICS_PLACEMARKERS != 0
197
198    // return the string representation of a token sequence
199    template <typename StringT, typename IteratorT>
200    inline StringT
201    as_string(IteratorT it, IteratorT const& end)
202    {
203        StringT result;
204        for (/**/; it != end; ++it) 
205        {
206            result += (*it).get_value();
207        }
208        return result;
209    }
210   
211    // return the string representation of a token sequence
212    template <typename ContainerT>
213    inline typename ContainerT::value_type::string_type
214    as_string (ContainerT const &token_sequence)
215    {
216        typedef typename ContainerT::value_type::string_type string_type;
217        return as_string<string_type>(token_sequence.begin(), 
218            token_sequence.end());
219    }
220   
221#if BOOST_WAVE_SUPPORT_VARIADICS_PLACEMARKERS != 0
222    ///////////////////////////////////////////////////////////////////////////
223    //
224    //  Copies all arguments beginning with the given index to the output
225    //  sequence. The arguments are separated by commas.
226    //
227    template <typename ContainerT, typename PositionT>
228    void replace_ellipsis (std::vector<ContainerT> const &arguments,
229        typename ContainerT::size_type index, 
230        ContainerT &expanded, PositionT const &pos)
231    {
232        using namespace cpplexer;
233        typedef typename ContainerT::value_type token_type;
234       
235        token_type comma(T_COMMA, ",", pos);
236        for (/**/; index < arguments.size(); ++index) {
237        ContainerT const &arg = arguments[index];
238       
239            std::copy(arg.begin(), arg.end(), 
240                std::inserter(expanded, expanded.end()));
241               
242            if (index < arguments.size()-1) 
243                expanded.push_back(comma);
244        }
245    }
246#endif
247
248}   // namespace impl
249
250///////////////////////////////////////////////////////////////////////////////
251}   // namespace util
252}   // namespace wave
253}   // namespace boost
254
255// the suffix header occurs after all of the code
256#ifdef BOOST_HAS_ABI_HEADERS
257#include BOOST_ABI_SUFFIX
258#endif
259
260#endif // !defined(MACRO_HELPERS_HPP_931BBC99_EBFA_4692_8FBE_B555998C2C39_INCLUDED)
Note: See TracBrowser for help on using the repository browser.