LCOV - code coverage report
Current view: top level - usr/include/boost/lexical_cast/detail - lcast_unsigned_converters.hpp (source / functions) Hit Total Coverage
Test: ROSE Lines: 15 79 19.0 %
Date: 2022-12-08 13:48:47 Functions: 3 7 42.9 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : // Copyright Kevlin Henney, 2000-2005.
       2             : // Copyright Alexander Nasonov, 2006-2010.
       3             : // Copyright Antony Polukhin, 2011-2019.
       4             : //
       5             : // Distributed under the Boost Software License, Version 1.0. (See
       6             : // accompanying file LICENSE_1_0.txt or copy at
       7             : // http://www.boost.org/LICENSE_1_0.txt)
       8             : //
       9             : // what:  lexical_cast custom keyword cast
      10             : // who:   contributed by Kevlin Henney,
      11             : //        enhanced with contributions from Terje Slettebo,
      12             : //        with additional fixes and suggestions from Gennaro Prota,
      13             : //        Beman Dawes, Dave Abrahams, Daryle Walker, Peter Dimov,
      14             : //        Alexander Nasonov, Antony Polukhin, Justin Viiret, Michael Hofmann,
      15             : //        Cheng Yang, Matthew Bradbury, David W. Birdsall, Pavel Korzh and other Boosters
      16             : // when:  November 2000, March 2003, June 2005, June 2006, March 2011 - 2014
      17             : 
      18             : #ifndef BOOST_LEXICAL_CAST_DETAIL_LCAST_UNSIGNED_CONVERTERS_HPP
      19             : #define BOOST_LEXICAL_CAST_DETAIL_LCAST_UNSIGNED_CONVERTERS_HPP
      20             : 
      21             : #include <boost/config.hpp>
      22             : #ifdef BOOST_HAS_PRAGMA_ONCE
      23             : #   pragma once
      24             : #endif
      25             : 
      26             : #include <climits>
      27             : #include <cstddef>
      28             : #include <string>
      29             : #include <cstring>
      30             : #include <cstdio>
      31             : #include <boost/limits.hpp>
      32             : #include <boost/type_traits/conditional.hpp>
      33             : #include <boost/static_assert.hpp>
      34             : #include <boost/detail/workaround.hpp>
      35             : 
      36             : 
      37             : #ifndef BOOST_NO_STD_LOCALE
      38             : #   include <locale>
      39             : #else
      40             : #   ifndef BOOST_LEXICAL_CAST_ASSUME_C_LOCALE
      41             :         // Getting error at this point means, that your STL library is old/lame/misconfigured.
      42             :         // If nothing can be done with STL library, define BOOST_LEXICAL_CAST_ASSUME_C_LOCALE,
      43             :         // but beware: lexical_cast will understand only 'C' locale delimeters and thousands
      44             :         // separators.
      45             : #       error "Unable to use <locale> header. Define BOOST_LEXICAL_CAST_ASSUME_C_LOCALE to force "
      46             : #       error "boost::lexical_cast to use only 'C' locale during conversions."
      47             : #   endif
      48             : #endif
      49             : 
      50             : #include <boost/lexical_cast/detail/lcast_char_constants.hpp>
      51             : #include <boost/type_traits/make_unsigned.hpp>
      52             : #include <boost/type_traits/is_signed.hpp>
      53             : #include <boost/noncopyable.hpp>
      54             : 
      55             : namespace boost 
      56             : {
      57             :     namespace detail // lcast_to_unsigned
      58             :     {
      59             :         template<class T>
      60             :         inline
      61      894123 :         BOOST_DEDUCED_TYPENAME boost::make_unsigned<T>::type lcast_to_unsigned(const T value) BOOST_NOEXCEPT {
      62             :             typedef BOOST_DEDUCED_TYPENAME boost::make_unsigned<T>::type result_type;
      63             :             return value < 0 
      64      894123 :                 ? static_cast<result_type>(0u - static_cast<result_type>(value)) 
      65             :                 : static_cast<result_type>(value);
      66             :         }
      67             :     }
      68             : 
      69             :     namespace detail // lcast_put_unsigned
      70             :     {
      71             :         template <class Traits, class T, class CharT>
      72             :         class lcast_put_unsigned: boost::noncopyable {
      73             :             typedef BOOST_DEDUCED_TYPENAME Traits::int_type int_type;
      74             :             BOOST_DEDUCED_TYPENAME boost::conditional<
      75             :                     (sizeof(unsigned) > sizeof(T))
      76             :                     , unsigned
      77             :                     , T
      78             :             >::type         m_value;
      79             :             CharT*          m_finish;
      80             :             CharT    const  m_czero;
      81             :             int_type const  m_zero;
      82             : 
      83             :         public:
      84      894484 :             lcast_put_unsigned(const T n_param, CharT* finish) BOOST_NOEXCEPT 
      85             :                 : m_value(n_param), m_finish(finish)
      86      894484 :                 , m_czero(lcast_char_constants<CharT>::zero), m_zero(Traits::to_int_type(m_czero))
      87             :             {
      88             : #ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS
      89             :                 BOOST_STATIC_ASSERT(!std::numeric_limits<T>::is_signed);
      90             : #endif
      91             :             }
      92             : 
      93      894484 :             CharT* convert() {
      94             : #ifndef BOOST_LEXICAL_CAST_ASSUME_C_LOCALE
      95      894484 :                 std::locale loc;
      96      894484 :                 if (loc == std::locale::classic()) {
      97      894484 :                     return main_convert_loop();
      98             :                 }
      99             : 
     100             :                 typedef std::numpunct<CharT> numpunct;
     101           0 :                 numpunct const& np = BOOST_USE_FACET(numpunct, loc);
     102      894484 :                 std::string const grouping = np.grouping();
     103           0 :                 std::string::size_type const grouping_size = grouping.size();
     104             : 
     105           0 :                 if (!grouping_size || grouping[0] <= 0) {
     106           0 :                     return main_convert_loop();
     107             :                 }
     108             : 
     109             : #ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS
     110             :                 // Check that ulimited group is unreachable:
     111             :                 BOOST_STATIC_ASSERT(std::numeric_limits<T>::digits10 < CHAR_MAX);
     112             : #endif
     113           0 :                 CharT const thousands_sep = np.thousands_sep();
     114           0 :                 std::string::size_type group = 0; // current group number
     115           0 :                 char last_grp_size = grouping[0];
     116           0 :                 char left = last_grp_size;
     117             : 
     118           0 :                 do {
     119           0 :                     if (left == 0) {
     120           0 :                         ++group;
     121           0 :                         if (group < grouping_size) {
     122           0 :                             char const grp_size = grouping[group];
     123           0 :                             last_grp_size = (grp_size <= 0 ? static_cast<char>(CHAR_MAX) : grp_size);
     124             :                         }
     125             : 
     126           0 :                         left = last_grp_size;
     127           0 :                         --m_finish;
     128           0 :                         Traits::assign(*m_finish, thousands_sep);
     129             :                     }
     130             : 
     131           0 :                     --left;
     132             :                 } while (main_convert_iteration());
     133             : 
     134           0 :                 return m_finish;
     135             : #else
     136             :                 return main_convert_loop();
     137             : #endif
     138             :             }
     139             : 
     140             :         private:
     141     1845559 :             inline bool main_convert_iteration() BOOST_NOEXCEPT {
     142     1845559 :                 --m_finish;
     143     1845559 :                 int_type const digit = static_cast<int_type>(m_value % 10U);
     144           0 :                 Traits::assign(*m_finish, Traits::to_char_type(m_zero + digit));
     145     1845559 :                 m_value /= 10;
     146             :                 return !!m_value; // suppressing warnings
     147             :             }
     148             : 
     149             :             inline CharT* main_convert_loop() BOOST_NOEXCEPT {
     150     1845559 :                 while (main_convert_iteration());
     151      894484 :                 return m_finish;
     152             :             }
     153             :         };
     154             :     }
     155             : 
     156             :     namespace detail // lcast_ret_unsigned
     157             :     {
     158             :         template <class Traits, class T, class CharT>
     159             :         class lcast_ret_unsigned: boost::noncopyable {
     160             :             bool m_multiplier_overflowed;
     161             :             T m_multiplier;
     162             :             T& m_value;
     163             :             const CharT* const m_begin;
     164             :             const CharT* m_end;
     165             :     
     166             :         public:
     167           0 :             lcast_ret_unsigned(T& value, const CharT* const begin, const CharT* end) BOOST_NOEXCEPT
     168           0 :                 : m_multiplier_overflowed(false), m_multiplier(1), m_value(value), m_begin(begin), m_end(end)
     169             :             {
     170             : #ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS
     171             :                 BOOST_STATIC_ASSERT(!std::numeric_limits<T>::is_signed);
     172             : 
     173             :                 // GCC when used with flag -std=c++0x may not have std::numeric_limits
     174             :                 // specializations for __int128 and unsigned __int128 types.
     175             :                 // Try compilation with -std=gnu++0x or -std=gnu++11.
     176             :                 //
     177             :                 // http://gcc.gnu.org/bugzilla/show_bug.cgi?id=40856
     178             :                 BOOST_STATIC_ASSERT_MSG(std::numeric_limits<T>::is_specialized,
     179             :                     "std::numeric_limits are not specialized for integral type passed to boost::lexical_cast"
     180             :                 );
     181             : #endif
     182             :             }
     183             : 
     184           0 :             inline bool convert() {
     185           0 :                 CharT const czero = lcast_char_constants<CharT>::zero;
     186           0 :                 --m_end;
     187           0 :                 m_value = static_cast<T>(0);
     188             : 
     189           0 :                 if (m_begin > m_end || *m_end < czero || *m_end >= czero + 10)
     190             :                     return false;
     191           0 :                 m_value = static_cast<T>(*m_end - czero);
     192           0 :                 --m_end;
     193             : 
     194             : #ifdef BOOST_LEXICAL_CAST_ASSUME_C_LOCALE
     195             :                 return main_convert_loop();
     196             : #else
     197           0 :                 std::locale loc;
     198           0 :                 if (loc == std::locale::classic()) {
     199           0 :                     return main_convert_loop();
     200             :                 }
     201             : 
     202             :                 typedef std::numpunct<CharT> numpunct;
     203           0 :                 numpunct const& np = BOOST_USE_FACET(numpunct, loc);
     204           0 :                 std::string const& grouping = np.grouping();
     205           0 :                 std::string::size_type const grouping_size = grouping.size();
     206             : 
     207             :                 /* According to Programming languages - C++
     208             :                  * we MUST check for correct grouping
     209             :                  */
     210           0 :                 if (!grouping_size || grouping[0] <= 0) {
     211           0 :                     return main_convert_loop();
     212             :                 }
     213             : 
     214           0 :                 unsigned char current_grouping = 0;
     215           0 :                 CharT const thousands_sep = np.thousands_sep();
     216           0 :                 char remained = static_cast<char>(grouping[current_grouping] - 1);
     217             : 
     218           0 :                 for (;m_end >= m_begin; --m_end)
     219             :                 {
     220           0 :                     if (remained) {
     221           0 :                         if (!main_convert_iteration()) {
     222             :                             return false;
     223             :                         }
     224           0 :                         --remained;
     225             :                     } else {
     226           0 :                         if ( !Traits::eq(*m_end, thousands_sep) ) //|| begin == end ) return false;
     227             :                         {
     228             :                             /*
     229             :                              * According to Programming languages - C++
     230             :                              * Digit grouping is checked. That is, the positions of discarded
     231             :                              * separators is examined for consistency with
     232             :                              * use_facet<numpunct<charT> >(loc ).grouping()
     233             :                              *
     234             :                              * BUT what if there is no separators at all and grouping()
     235             :                              * is not empty? Well, we have no extraced separators, so we
     236             :                              * won`t check them for consistency. This will allow us to
     237             :                              * work with "C" locale from other locales
     238             :                              */
     239           0 :                             return main_convert_loop();
     240             :                         } else {
     241           0 :                             if (m_begin == m_end) return false;
     242           0 :                             if (current_grouping < grouping_size - 1) ++current_grouping;
     243           0 :                             remained = grouping[current_grouping];
     244             :                         }
     245             :                     }
     246             :                 } /*for*/
     247             : 
     248             :                 return true;
     249             : #endif
     250             :             }
     251             : 
     252             :         private:
     253             :             // Iteration that does not care about grouping/separators and assumes that all 
     254             :             // input characters are digits
     255           0 :             inline bool main_convert_iteration() BOOST_NOEXCEPT {
     256           0 :                 CharT const czero = lcast_char_constants<CharT>::zero;
     257           0 :                 T const maxv = (std::numeric_limits<T>::max)();
     258             : 
     259           0 :                 m_multiplier_overflowed = m_multiplier_overflowed || (maxv/10 < m_multiplier);
     260           0 :                 m_multiplier = static_cast<T>(m_multiplier * 10);
     261             : 
     262           0 :                 T const dig_value = static_cast<T>(*m_end - czero);
     263           0 :                 T const new_sub_value = static_cast<T>(m_multiplier * dig_value);
     264             : 
     265             :                 // We must correctly handle situations like `000000000000000000000000000001`.
     266             :                 // So we take care of overflow only if `dig_value` is not '0'.
     267           0 :                 if (*m_end < czero || *m_end >= czero + 10  // checking for correct digit
     268           0 :                     || (dig_value && (                      // checking for overflow of ... 
     269             :                         m_multiplier_overflowed                             // ... multiplier
     270           0 :                         || static_cast<T>(maxv / dig_value) < m_multiplier  // ... subvalue
     271           0 :                         || static_cast<T>(maxv - new_sub_value) < m_value   // ... whole expression
     272             :                     ))
     273             :                 ) return false;
     274             : 
     275           0 :                 m_value = static_cast<T>(m_value + new_sub_value);
     276             :                 
     277           0 :                 return true;
     278             :             }
     279             : 
     280             :             bool main_convert_loop() BOOST_NOEXCEPT {
     281           0 :                 for ( ; m_end >= m_begin; --m_end) {
     282           0 :                     if (!main_convert_iteration()) {
     283             :                         return false;
     284             :                     }
     285             :                 }
     286             :             
     287             :                 return true;
     288             :             }
     289             :         };
     290             :     }
     291             : } // namespace boost
     292             : 
     293             : #endif // BOOST_LEXICAL_CAST_DETAIL_LCAST_UNSIGNED_CONVERTERS_HPP
     294             : 

Generated by: LCOV version 1.14