PageRenderTime 9ms CodeModel.GetById 1ms app.highlight 3ms RepoModel.GetById 1ms app.codeStats 1ms

/Src/Dependencies/Boost/boost/spirit/home/classic/utility/impl/escape_char.ipp

http://hadesmem.googlecode.com/
C++ Header | 224 lines | 170 code | 30 blank | 24 comment | 25 complexity | f462679d33b3a120cb13518ea8b4d43a MD5 | raw file
  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///////////////////////////////////////////////////////////////////////////////
 19namespace boost { namespace spirit {
 20
 21BOOST_SPIRIT_CLASSIC_NAMESPACE_BEGIN
 22
 23///////////////////////////////////////////////////////////////////////////////
 24//
 25//  escape_char_parser class
 26//
 27///////////////////////////////////////////////////////////////////////////////
 28
 29const unsigned long c_escapes = 1;
 30const unsigned long lex_escapes = c_escapes << 1;
 31
 32//////////////////////////////////
 33namespace 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///////////////////////////////////////////////////////////////////////////////
219BOOST_SPIRIT_CLASSIC_NAMESPACE_END
220
221}} // namespace boost::spirit
222
223#endif
224