1    	/*=============================================================================
2    	    Copyright (c) 1998-2003 Joel de Guzman
3    	    Copyright (c) 2001-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_NUMERICS_IPP
11   	#define BOOST_SPIRIT_NUMERICS_IPP
12   	
13   	#include <boost/config/no_tr1/cmath.hpp>
14   	#include <limits>
15   	
16   	namespace boost { namespace spirit {
17   	
18   	BOOST_SPIRIT_CLASSIC_NAMESPACE_BEGIN
19   	
20   	    struct sign_parser; // forward declaration only
21   	
22   	    namespace impl
23   	    {
24   	        ///////////////////////////////////////////////////////////////////////
25   	        //
26   	        //  Extract the prefix sign (- or +)
27   	        //
28   	        ///////////////////////////////////////////////////////////////////////
29   	        template <typename ScannerT>
30   	        bool
31   	        extract_sign(ScannerT const& scan, std::size_t& count)
32   	        {
33   	            //  Extract the sign
34   	            count = 0;
35   	            bool neg = *scan == '-';
36   	            if (neg || (*scan == '+'))
37   	            {
38   	                ++scan;
39   	                ++count;
40   	                return neg;
41   	            }
42   	
43   	            return false;
44   	        }
45   	
46   	        ///////////////////////////////////////////////////////////////////////
47   	        //
48   	        //  Traits class for radix specific number conversion
49   	        //
50   	        //      Convert a digit from character representation, ch, to binary
51   	        //      representation, returned in val.
52   	        //      Returns whether the conversion was successful.
53   	        //
54   	        //        template<typename CharT> static bool digit(CharT ch, T& val);
55   	        //
56   	        ///////////////////////////////////////////////////////////////////////
57   	        template<const int Radix>
58   	        struct radix_traits;
59   	
60   	        ////////////////////////////////// Binary
61   	        template<>
62   	        struct radix_traits<2>
63   	        {
64   	            template<typename CharT, typename T>
65   	            static bool digit(CharT ch, T& val)
66   	            {
67   	                val = ch - '0';
68   	                return ('0' == ch || '1' == ch);
69   	            }
70   	        };
71   	
72   	        ////////////////////////////////// Octal
73   	        template<>
74   	        struct radix_traits<8>
75   	        {
76   	            template<typename CharT, typename T>
77   	            static bool digit(CharT ch, T& val)
78   	            {
79   	                val = ch - '0';
80   	                return ('0' <= ch && ch <= '7');
81   	            }
82   	        };
83   	
84   	        ////////////////////////////////// Decimal
85   	        template<>
86   	        struct radix_traits<10>
87   	        {
88   	            template<typename CharT, typename T>
89   	            static bool digit(CharT ch, T& val)
90   	            {
91   	                val = ch - '0';
92   	                return impl::isdigit_(ch);
93   	            }
94   	        };
95   	
96   	        ////////////////////////////////// Hexadecimal
97   	        template<>
98   	        struct radix_traits<16>
99   	        {
100  	            template<typename CharT, typename T>
101  	            static bool digit(CharT ch, T& val)
102  	            {
103  	                if (radix_traits<10>::digit(ch, val))
104  	                    return true;
105  	
106  	                CharT lc = impl::tolower_(ch);
107  	                if ('a' <= lc && lc <= 'f')
108  	                {
109  	                    val = lc - 'a' + 10;
110  	                    return true;
111  	                }
112  	                return false;
113  	            }
114  	        };
115  	
116  	        ///////////////////////////////////////////////////////////////////////
117  	        //
118  	        //      Helper templates for encapsulation of radix specific
119  	        //      conversion of an input string to an integral value.
120  	        //
121  	        //      main entry point:
122  	        //
123  	        //          extract_int<Radix, MinDigits, MaxDigits, Accumulate>
124  	        //              ::f(first, last, n, count);
125  	        //
126  	        //          The template parameter Radix represents the radix of the
127  	        //          number contained in the parsed string. The template
128  	        //          parameter MinDigits specifies the minimum digits to
129  	        //          accept. The template parameter MaxDigits specifies the
130  	        //          maximum digits to parse. A -1 value for MaxDigits will
131  	        //          make it parse an arbitrarilly large number as long as the
132  	        //          numeric type can hold it. Accumulate is either
133  	        //          positive_accumulate<Radix> (default) for parsing positive
134  	        //          numbers or negative_accumulate<Radix> otherwise.
135  	        //          Checking is only performed when std::numeric_limits<T>::
136  	        //          is_specialized is true. Otherwise, there's no way to
137  	        //          do the check.
138  	        //
139  	        //          scan.first and scan.last are iterators as usual (i.e.
140  	        //          first is mutable and is moved forward when a match is
141  	        //          found), n is a variable that holds the number (passed by
142  	        //          reference). The number of parsed characters is added to
143  	        //          count (also passed by reference)
144  	        //
145  	        //      NOTE:
146  	        //              Returns a non-match, if the number to parse
147  	        //              overflows (or underflows) the used type.
148  	        //
149  	        //      BEWARE:
150  	        //              the parameters 'n' and 'count' should be properly
151  	        //              initialized before calling this function.
152  	        //
153  	        ///////////////////////////////////////////////////////////////////////
154  	#if defined(BOOST_MSVC)
155  	#pragma warning(push) 
156  	#pragma warning(disable:4127) //conditional expression is constant
157  	#endif
158  	        
159  	        template <typename T, int Radix>
160  	        struct positive_accumulate
161  	        {
162  	            //  Use this accumulator if number is positive
163  	            static bool add(T& n, T digit)
164  	            {
165  	                if (std::numeric_limits<T>::is_specialized)
166  	                {
167  	                    static T const max = (std::numeric_limits<T>::max)();
168  	                    static T const max_div_radix = max/Radix;
169  	
170  	                    if (n > max_div_radix)
171  	                        return false;
172  	                    n *= Radix;
173  	
174  	                    if (n > max - digit)
175  	                        return false;
176  	                    n += digit;
177  	
178  	                    return true;
179  	                }
180  	                else
181  	                {
182  	                    n *= Radix;
183  	                    n += digit;
184  	                    return true;
185  	                }
186  	            }
187  	        };
188  	
189  	        template <typename T, int Radix>
190  	        struct negative_accumulate
191  	        {
192  	            //  Use this accumulator if number is negative
193  	            static bool add(T& n, T digit)
194  	            {
195  	                if (std::numeric_limits<T>::is_specialized)
196  	                {
197  	                    typedef std::numeric_limits<T> num_limits;
198  	                    static T const min =
199  	                        (!num_limits::is_integer && num_limits::is_signed && num_limits::has_denorm) ?
200  	                        -(num_limits::max)() : (num_limits::min)();
201  	                    static T const min_div_radix = min/Radix;
202  	
203  	                    if (n < min_div_radix)
204  	                        return false;
205  	                    n *= Radix;
206  	
207  	                    if (n < min + digit)
208  	                        return false;
209  	                    n -= digit;
210  	
211  	                    return true;
212  	                }
213  	                else
214  	                {
215  	                    n *= Radix;
216  	                    n -= digit;
217  	                    return true;
218  	                }
219  	            }
220  	        };
221  	
222  	        template <int MaxDigits>
223  	        inline bool allow_more_digits(std::size_t i)
224  	        {
225  	            return i < MaxDigits;
226  	        }
227  	
228  	        template <>
229  	        inline bool allow_more_digits<-1>(std::size_t)
230  	        {
231  	            return true;
232  	        }
233  	
234  	        //////////////////////////////////
235  	        template <
236  	            int Radix, unsigned MinDigits, int MaxDigits,
237  	            typename Accumulate
238  	        >
239  	        struct extract_int
240  	        {
241  	            template <typename ScannerT, typename T>
242  	            static bool
243  	            f(ScannerT& scan, T& n, std::size_t& count)
244  	            {
245  	                std::size_t i = 0;
246  	                T digit;
(3) Event example_checked: Example 2: "scan->at_end()" has its value checked in "scan->at_end()".
Also see events: [check_return][example_checked][example_checked][example_checked][example_checked]
247  	                while( allow_more_digits<MaxDigits>(i) && !scan.at_end() &&
248  	                    radix_traits<Radix>::digit(*scan, digit) )
249  	                {
250  	                    if (!Accumulate::add(n, digit))
251  	                        return false; // Overflow
252  	                    ++i, ++scan, ++count;
253  	                }
254  	                return i >= MinDigits;
255  	            }
256  	        };
257  	
258  	        ///////////////////////////////////////////////////////////////////////
259  	        //
260  	        //  uint_parser_impl class
261  	        //
262  	        ///////////////////////////////////////////////////////////////////////
263  	        template <
264  	            typename T = unsigned,
265  	            int Radix = 10,
266  	            unsigned MinDigits = 1,
267  	            int MaxDigits = -1
268  	        >
269  	        struct uint_parser_impl
270  	            : parser<uint_parser_impl<T, Radix, MinDigits, MaxDigits> >
271  	        {
272  	            typedef uint_parser_impl<T, Radix, MinDigits, MaxDigits> self_t;
273  	
274  	            template <typename ScannerT>
275  	            struct result
276  	            {
277  	                typedef typename match_result<ScannerT, T>::type type;
278  	            };
279  	
280  	            template <typename ScannerT>
281  	            typename parser_result<self_t, ScannerT>::type
282  	            parse(ScannerT const& scan) const
283  	            {
284  	                if (!scan.at_end())
285  	                {
286  	                    T n = 0;
287  	                    std::size_t count = 0;
288  	                    typename ScannerT::iterator_t save = scan.first;
289  	                    if (extract_int<Radix, MinDigits, MaxDigits,
290  	                        positive_accumulate<T, Radix> >::f(scan, n, count))
291  	                    {
292  	                        return scan.create_match(count, n, save, scan.first);
293  	                    }
294  	                    // return no-match if number overflows
295  	                }
296  	                return scan.no_match();
297  	            }
298  	        };
299  	
300  	        ///////////////////////////////////////////////////////////////////////
301  	        //
302  	        //  int_parser_impl class
303  	        //
304  	        ///////////////////////////////////////////////////////////////////////
305  	        template <
306  	            typename T = unsigned,
307  	            int Radix = 10,
308  	            unsigned MinDigits = 1,
309  	            int MaxDigits = -1
310  	        >
311  	        struct int_parser_impl
312  	            : parser<int_parser_impl<T, Radix, MinDigits, MaxDigits> >
313  	        {
314  	            typedef int_parser_impl<T, Radix, MinDigits, MaxDigits> self_t;
315  	
316  	            template <typename ScannerT>
317  	            struct result
318  	            {
319  	                typedef typename match_result<ScannerT, T>::type type;
320  	            };
321  	
322  	            template <typename ScannerT>
323  	            typename parser_result<self_t, ScannerT>::type
324  	            parse(ScannerT const& scan) const
325  	            {
326  	                typedef extract_int<Radix, MinDigits, MaxDigits,
327  	                    negative_accumulate<T, Radix> > extract_int_neg_t;
328  	                typedef extract_int<Radix, MinDigits, MaxDigits,
329  	                    positive_accumulate<T, Radix> > extract_int_pos_t;
330  	
(4) Event example_checked: Example 3: "scan->at_end()" has its value checked in "scan->at_end()".
Also see events: [check_return][example_checked][example_checked][example_checked][example_checked]
331  	                if (!scan.at_end())
332  	                {
333  	                    T n = 0;
334  	                    std::size_t count = 0;
335  	                    typename ScannerT::iterator_t save = scan.first;
336  	
337  	                    bool hit = impl::extract_sign(scan, count);
338  	
339  	                    if (hit)
340  	                        hit = extract_int_neg_t::f(scan, n, count);
341  	                    else
342  	                        hit = extract_int_pos_t::f(scan, n, count);
343  	
344  	                    if (hit)
345  	                        return scan.create_match(count, n, save, scan.first);
346  	                    else
347  	                        scan.first = save;
348  	                    // return no-match if number overflows or underflows
349  	                }
350  	                return scan.no_match();
351  	            }
352  	        };
353  	
354  	        ///////////////////////////////////////////////////////////////////////
355  	        //
356  	        //  real_parser_impl class
357  	        //
358  	        ///////////////////////////////////////////////////////////////////////
359  	        template <typename RT, typename T, typename RealPoliciesT>
360  	        struct real_parser_impl
361  	        {
362  	            typedef real_parser_impl<RT, T, RealPoliciesT> self_t;
363  	
364  	            template <typename ScannerT>
365  	            RT parse_main(ScannerT const& scan) const
366  	            {
(5) Event example_checked: Example 4: "scan->at_end()" has its value checked in "scan->at_end()".
Also see events: [check_return][example_checked][example_checked][example_checked][example_checked]
367  	                if (scan.at_end())
368  	                    return scan.no_match();
369  	                typename ScannerT::iterator_t save = scan.first;
370  	
371  	                typedef typename parser_result<sign_parser, ScannerT>::type
372  	                    sign_match_t;
373  	                typedef typename parser_result<chlit<>, ScannerT>::type
374  	                    exp_match_t;
375  	
376  	                sign_match_t    sign_match = RealPoliciesT::parse_sign(scan);
377  	                std::size_t     count = sign_match ? sign_match.length() : 0;
378  	                bool            neg = sign_match.has_valid_attribute() ?
379  	                                    sign_match.value() : false;
380  	
381  	                RT              n_match = RealPoliciesT::parse_n(scan);
382  	                T               n = n_match.has_valid_attribute() ?
383  	                                    n_match.value() : T(0);
384  	                bool            got_a_number = n_match;
385  	                exp_match_t     e_hit;
386  	
387  	                if (!got_a_number && !RealPoliciesT::allow_leading_dot)
388  	                     return scan.no_match();
389  	                else
390  	                    count += n_match.length();
391  	
392  	                if (neg)
393  	                    n = -n;
394  	
395  	                if (RealPoliciesT::parse_dot(scan))
396  	                {
397  	                    //  We got the decimal point. Now we will try to parse
398  	                    //  the fraction if it is there. If not, it defaults
399  	                    //  to zero (0) only if we already got a number.
400  	
401  	                    if (RT hit = RealPoliciesT::parse_frac_n(scan))
402  	                    {
403  	#if !defined(BOOST_NO_STDC_NAMESPACE)
404  	                        using namespace std;  // allow for ADL to find pow()
405  	#endif
406  	                        hit.value(hit.value()
407  	                            * pow(T(10), T(-hit.length())));
408  	                        if (neg)
409  	                            n -= hit.value();
410  	                        else
411  	                            n += hit.value();
412  	                        count += hit.length() + 1;
413  	
414  	                    }
415  	
416  	                    else if (!got_a_number ||
417  	                        !RealPoliciesT::allow_trailing_dot)
418  	                        return scan.no_match();
419  	
420  	                    e_hit = RealPoliciesT::parse_exp(scan);
421  	                }
422  	                else
423  	                {
424  	                    //  We have reached a point where we
425  	                    //  still haven't seen a number at all.
426  	                    //  We return early with a no-match.
427  	                    if (!got_a_number)
428  	                        return scan.no_match();
429  	
430  	                    //  If we must expect a dot and we didn't see
431  	                    //  an exponent, return early with a no-match.
432  	                    e_hit = RealPoliciesT::parse_exp(scan);
433  	                    if (RealPoliciesT::expect_dot && !e_hit)
434  	                        return scan.no_match();
435  	                }
436  	
437  	                if (e_hit)
438  	                {
439  	                    //  We got the exponent prefix. Now we will try to parse the
440  	                    //  actual exponent. It is an error if it is not there.
441  	                    if (RT e_n_hit = RealPoliciesT::parse_exp_n(scan))
442  	                    {
443  	#if !defined(BOOST_NO_STDC_NAMESPACE)
444  	                        using namespace std;    // allow for ADL to find pow()
445  	#endif
446  	                        n *= pow(T(10), T(e_n_hit.value()));
447  	                        count += e_n_hit.length() + e_hit.length();
448  	                    }
449  	                    else
450  	                    {
451  	                        //  Oops, no exponent, return a no-match
452  	                        return scan.no_match();
453  	                    }
454  	                }
455  	
456  	                return scan.create_match(count, n, save, scan.first);
457  	            }
458  	
459  	            template <typename ScannerT>
460  	            static RT parse(ScannerT const& scan)
461  	            {
462  	                static self_t this_;
463  	                return impl::implicit_lexeme_parse<RT>(this_, scan, scan);
464  	            }
465  	        };
466  	
467  	#if defined(BOOST_MSVC)
468  	#pragma warning(pop)
469  	#endif
470  	
471  	    }   //  namespace impl
472  	
473  	///////////////////////////////////////////////////////////////////////////////
474  	BOOST_SPIRIT_CLASSIC_NAMESPACE_END
475  	
476  	}} // namespace boost::spirit
477  	
478  	#endif
479