1 /*=============================================================================
2     Copyright (c) 2001-2011 Joel de Guzman
3     Copyright (c) 2011 Jan Frederick Eick
4 
5     Distributed under the Boost Software License, Version 1.0. (See accompanying
6     file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
7 ==============================================================================*/
8 #if !defined(BOOST_SPIRIT_NUMERIC_UTILS_APRIL_17_2006_0830AM)
9 #define BOOST_SPIRIT_NUMERIC_UTILS_APRIL_17_2006_0830AM
10 
11 #if defined(_MSC_VER)
12 #pragma once
13 #endif
14 
15 #include <boost/spirit/home/support/assert_msg.hpp>
16 #include <boost/spirit/home/qi/detail/assign_to.hpp>
17 #include <boost/spirit/home/qi/numeric/detail/numeric_utils.hpp>
18 #include <boost/assert.hpp>
19 #include <boost/mpl/assert.hpp>
20 
21 namespace boost { namespace spirit { namespace qi
22 {
23     ///////////////////////////////////////////////////////////////////////////
24     //  Extract the prefix sign (- or +), return true if a '-' was found
25     ///////////////////////////////////////////////////////////////////////////
26     template <typename Iterator>
27     inline bool
extract_sign(Iterator & first,Iterator const & last)28     extract_sign(Iterator& first, Iterator const& last)
29     {
30         (void)last;                  // silence unused warnings
31         BOOST_ASSERT(first != last); // precondition
32 
33         // Extract the sign
34         bool neg = *first == '-';
35         if (neg || (*first == '+'))
36         {
37             ++first;
38             return neg;
39         }
40         return false;
41     }
42 
43     ///////////////////////////////////////////////////////////////////////////
44     // Low level unsigned integer parser
45     ///////////////////////////////////////////////////////////////////////////
46     template <typename T, unsigned Radix, unsigned MinDigits, int MaxDigits
47       , bool Accumulate = false, bool IgnoreOverflowDigits = false>
48     struct extract_uint
49     {
50         // check template parameter 'Radix' for validity
51         BOOST_SPIRIT_ASSERT_MSG(
52             Radix >= 2 && Radix <= 36,
53             not_supported_radix, ());
54 
55         template <typename Iterator>
callboost::spirit::qi::extract_uint56         inline static bool call(Iterator& first, Iterator const& last, T& attr_)
57         {
58             if (first == last)
59                 return false;
60 
61             typedef detail::extract_int<
62                 T
63               , Radix
64               , MinDigits
65               , MaxDigits
66               , detail::positive_accumulator<Radix>
67               , Accumulate
68               , IgnoreOverflowDigits>
69             extract_type;
70 
71             Iterator save = first;
72             if (!extract_type::parse(first, last,
73                 detail::cast_unsigned<T>::call(attr_)))
74             {
75                 first = save;
76                 return false;
77             }
78             return true;
79         }
80 
81         template <typename Iterator, typename Attribute>
callboost::spirit::qi::extract_uint82         inline static bool call(Iterator& first, Iterator const& last, Attribute& attr_)
83         {
84             // this case is called when Attribute is not T
85             T attr_local;
86             if (call(first, last, attr_local))
87             {
88                 traits::assign_to(attr_local, attr_);
89                 return true;
90             }
91             return false;
92         }
93     };
94 
95     ///////////////////////////////////////////////////////////////////////////
96     // Low level signed integer parser
97     ///////////////////////////////////////////////////////////////////////////
98     template <typename T, unsigned Radix, unsigned MinDigits, int MaxDigits>
99     struct extract_int
100     {
101         // check template parameter 'Radix' for validity
102         BOOST_SPIRIT_ASSERT_MSG(
103             Radix == 2 || Radix == 8 || Radix == 10 || Radix == 16,
104             not_supported_radix, ());
105 
106         template <typename Iterator>
callboost::spirit::qi::extract_int107         inline static bool call(Iterator& first, Iterator const& last, T& attr_)
108         {
109             if (first == last)
110                 return false;
111 
112             typedef detail::extract_int<
113                 T, Radix, MinDigits, MaxDigits>
114             extract_pos_type;
115 
116             typedef detail::extract_int<
117                 T, Radix, MinDigits, MaxDigits, detail::negative_accumulator<Radix> >
118             extract_neg_type;
119 
120             Iterator save = first;
121             bool hit = extract_sign(first, last);
122             if (hit)
123                 hit = extract_neg_type::parse(first, last, attr_);
124             else
125                 hit = extract_pos_type::parse(first, last, attr_);
126 
127             if (!hit)
128             {
129                 first = save;
130                 return false;
131             }
132             return true;
133         }
134 
135         template <typename Iterator, typename Attribute>
callboost::spirit::qi::extract_int136         inline static bool call(Iterator& first, Iterator const& last, Attribute& attr_)
137         {
138             // this case is called when Attribute is not T
139             T attr_local;
140             if (call(first, last, attr_local))
141             {
142                 traits::assign_to(attr_local, attr_);
143                 return true;
144             }
145             return false;
146         }
147     };
148 }}}
149 
150 #endif
151