source: NonGTP/Boost/boost/wave/util/macro_helpers.hpp @ 857

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