diff --git a/include/boost/lexical_cast.hpp b/include/boost/lexical_cast.hpp index d185852..c1b083b 100644 --- a/include/boost/lexical_cast.hpp +++ b/include/boost/lexical_cast.hpp @@ -555,6 +555,10 @@ namespace boost BOOST_STATIC_ASSERT(!std::numeric_limits::is_signed); #endif + typedef typename Traits::int_type int_type; + CharT const czero = lcast_char_constants::zero; + int_type const zero = Traits::to_int_type(czero); + #ifndef BOOST_LEXICAL_CAST_ASSUME_C_LOCALE // TODO: use BOOST_NO_STD_LOCALE std::locale loc; @@ -562,47 +566,54 @@ namespace boost numpunct const& np = BOOST_USE_FACET(numpunct, loc); std::string const& grouping = np.grouping(); std::string::size_type const grouping_size = grouping.size(); - CharT thousands_sep = grouping_size ? np.thousands_sep() : 0; - std::string::size_type group = 0; // current group number - char last_grp_size = - grouping_size == 0 || grouping[0] <= 0 ? CHAR_MAX : grouping[0]; + + if ( grouping_size && grouping[0] > 0 ) + { + #ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS // Check that ulimited group is unreachable: BOOST_STATIC_ASSERT(std::numeric_limits::digits10 < CHAR_MAX); #endif + CharT thousands_sep = np.thousands_sep(); + std::string::size_type group = 0; // current group number + char last_grp_size = grouping[0]; + char left = last_grp_size; - char left = last_grp_size; -#endif - - typedef typename Traits::int_type int_type; - CharT const czero = lcast_char_constants::zero; - int_type const zero = Traits::to_int_type(czero); - - do - { -#ifndef BOOST_LEXICAL_CAST_ASSUME_C_LOCALE - if(left == 0) + do { - ++group; - if(group < grouping_size) + if(left == 0) { - char const grp_size = grouping[group]; - last_grp_size = grp_size <= 0 ? CHAR_MAX : grp_size; + ++group; + if(group < grouping_size) + { + char const grp_size = grouping[group]; + last_grp_size = grp_size <= 0 ? CHAR_MAX : grp_size; + } + + left = last_grp_size; + --finish; + Traits::assign(*finish, thousands_sep); } - left = last_grp_size; + --left; + --finish; - Traits::assign(*finish, thousands_sep); - } + int_type const digit = static_cast(n % 10U); + Traits::assign(*finish, Traits::to_char_type(zero + digit)); + n /= 10; + } while(n); - --left; + } else #endif - - --finish; - int_type const digit = static_cast(n % 10U); - Traits::assign(*finish, Traits::to_char_type(zero + digit)); - n /= 10; - } while(n); + { + do + { + --finish; + int_type const digit = static_cast(n % 10U); + Traits::assign(*finish, Traits::to_char_type(zero + digit)); + n /= 10; + } while(n); + } return finish; } @@ -638,10 +649,10 @@ namespace boost /* According to [22.2.2.1.2] of Programming languages - C++ * we MUST check for correct grouping */ - if (grouping_size) + if (grouping_size && grouping[0] > 0) { unsigned char current_grouping = 0; - CharT const thousands_sep = grouping_size ? np.thousands_sep() : 0; + CharT const thousands_sep = np.thousands_sep(); char remained = grouping[current_grouping] - 1; for(;end>=begin; --end) diff --git a/lexical_cast.htm b/lexical_cast.htm index 03625b4..2292d2a 100644 --- a/lexical_cast.htm +++ b/lexical_cast.htm @@ -26,6 +26,8 @@ References
  • Changes
  • +
  • + Performance

  • Motivation

    @@ -87,7 +89,7 @@ For a good discussion of the options and issues involved in string-based formatting, including comparison of stringstream, lexical_cast, and others, see Herb Sutter's article, - The String Formatters of Manor Farm. + The String Formatters of Manor Farm. Also, take a look at the Performance section.


    Examples

    @@ -267,6 +269,7 @@ Eliminate an overhead of std::locale if your program runs in the "C

    Changes

    May 2011:

      +
    • Optimizations for "C" and other locales without number grouping.
    • Better performance and less memory usage for unsigned char and signed char conversions.
    • Better performance and less memory usage for conversions to arithmetic types.
    • Better performance and less memory usage for conversions from arithmetic type to arithmetic type.
    • @@ -313,7 +316,34 @@ Eliminate an overhead of std::locale if your program runs in the "C


    - + +

    Performance

    +This table shows the execution speed for 100000 iterations in milliseconds of the following code blocks: + + + + + + + + + + + + + + + + + + + + +
    From->To target = lexical_cast<Target>(source); std::stringstream ss;
    ss << source;
    ss >> target;
    ss << source;
    ss >> target;
    ss.str(std::string());
    ss.clear();
    sscanf( (const char*)source, <...>, &target);
    OR
    sprintf( (char*)buffer, <...>, source);
    + target = buffer;
    string->char<191710
    string->int71152318
    string->unsigned int71172217
    string->bool<11041910
    string->float851726033
    char->string71051612
    int->string151312117
    unsigned int->string141252117
    bool->string71222412
    float->string12422311548
    char*->string912320---
    int->int<112026---
    float->float<1262142---
    + +Fastest results are highlitened with green. +
    Copyright © Kevlin Henney, 2000-2005
    Copyright © Alexander Nasonov, 2006-2010
    Copyright © Antony Polukhin, 2011
    diff --git a/lexical_cast_test.cpp b/lexical_cast_test.cpp index 75d12ff..f88017f 100644 --- a/lexical_cast_test.cpp +++ b/lexical_cast_test.cpp @@ -937,7 +937,6 @@ void test_wallocator() #endif -#include void test_char_types_conversions() { const char c_arr[] = "Test array of chars";