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