Compare commits

..

18 Commits

Author SHA1 Message Date
Beman Dawes a018eeb617 Release 1.48.0
[SVN r75495]
2011-11-15 15:44:44 +00:00
Antony Polukhin 1eda87448e Fixes #6083
Merge from trunk

[SVN r75411]
2011-11-08 18:12:23 +00:00
Antony Polukhin 3a62368d0e Merge from trunk r74564
* char16_t and char32_t conversions now work on gcc for C locale
* Optimizations for C locale
* Performance section of documentation updated

[SVN r74565]
2011-09-25 16:44:39 +00:00
Antony Polukhin e1caac418c Mereged from r74355
Basic support for char16_t and char32_t

[SVN r74361]
2011-09-12 18:15:31 +00:00
Antony Polukhin 8480a6d083 Merge from trunk r73850
* Documentation commited

[SVN r73852]
2011-08-17 18:44:00 +00:00
Antony Polukhin 00f1246faf Merge from trunk r73850
* Compile time optimizations
* Float types optimizations
* Source code refactoring
* Parsing and writing inf and nan values according to the standart
* Fixed some bugs and warnings
* New tests
* New documentation

[SVN r73851]
2011-08-17 18:43:10 +00:00
Antony Polukhin 6c5f31e7a5 lexical-cast mereged from trunk r72347 (allow "C" locale grouping for other locales)
[SVN r72348]
2011-06-02 16:20:36 +00:00
Antony Polukhin 1f7147d24b mereged lexical_cast from trunk r72267 (more optimizations, updated documentation, added tests)
[SVN r72268]
2011-05-29 19:21:28 +00:00
Antony Polukhin a385c3ec99 Merge from trunk: r72184 (a lot of optimizations, new tests, fix inspection warnings).
[SVN r72185]
2011-05-26 16:27:53 +00:00
Antony Polukhin 701d5f0bf0 Merged from trunk revision 71922. Most part of this modifications of lexical_cast library were made and successfully tested during the year 2009.
Later commits affected only documentation bugs.

[SVN r71923]
2011-05-13 17:44:51 +00:00
Daniel James b5583b88fa Merge some detail changes.
- [53670] Avoid C style casts.
 - [55604] Fix #3346 boost/detail/scoped_enum_emulation.hpp enum_t conflict
   with Unix rpc/types.h
 - Don't foward declare containers when using gcc's parallel library and add a
   macro to disable forward declaration. Fixes #3866.


[SVN r59679]
2010-02-14 16:31:21 +00:00
Troy D. Straszheim 5b6e39b2b8 rm cmake from the release branch before it goes out broken. Policy dictates that you never commit to release, you commit to trunk and merge to release.
[SVN r56941]
2009-10-17 01:10:45 +00:00
Alexander Nasonov 04f73e5a89 Decrease indent of #if and #endif lines and test string<->integral conversons when BOOST_NO_INTRINSIC_WCHAR_T is defined.
[SVN r56231]
2009-09-15 23:55:47 +00:00
Alexander Nasonov 65328d9716 Add new test libs/conversion/test/lexical_cast_vc8_bug_test.cpp.
[SVN r56230]
2009-09-15 23:41:02 +00:00
Alexander Nasonov dc151d2b5a DISABLE_WIDE_CHAR_SUPPORT -> BOOST_LCAST_NO_WCHAR_T.
[SVN r56227]
2009-09-15 22:53:27 +00:00
Alexander Nasonov 23949682c1 [lexical_cast] Merge from trunk r56170 (#2295 Inconsistent behavior when using 64 bit integer types) and r56171 (Add a test for uintmax_t).
[SVN r56172]
2009-09-13 15:03:52 +00:00
Alexander Nasonov 5055e842cf Merge from trunk r56160 (Can't compile without <locale> header, boost::lexical_cast problem).
[SVN r56161]
2009-09-12 22:24:35 +00:00
Alexander Nasonov 9e764f3e49 [lexical_cast] Merge from trunk: r56158 (fix warning on MSVC warning level 4) and r53668 (avoid C style casts).
[SVN r56159]
2009-09-12 22:11:01 +00:00
17 changed files with 3452 additions and 1169 deletions
-28
View File
@@ -1,28 +0,0 @@
#
# Copyright Troy D. Straszheim
#
# Distributed under the Boost Software License, Version 1.0.
# See http://www.boost.org/LICENSE_1_0.txt
#
#----------------------------------------------------------------------------
# This file was automatically generated from the original CMakeLists.txt file
# Add a variable to hold the headers for the library
set (lib_headers
)
# Add a library target to the build system
boost_library_project(
conversion
# SRCDIRS
TESTDIRS test
# HEADERS ${lib_headers}
# DOCDIRS
DESCRIPTION "Polymorphic and lexical casts"
# MODULARIZED
AUTHORS "David Abrahams <dave -at- boost-consulting.com>"
"Kevlin Henney"
# MAINTAINERS
)
+16
View File
@@ -0,0 +1,16 @@
# Copyright Antony Polukhin 2011. Use, modification, and distribution are
# subject to the Boost Software License, Version 1.0. (See accompanying
# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
using quickbook ;
import boostbook : boostbook ;
xml lexical_cast : lexical_cast.qbk ;
boostbook standalone
:
lexical_cast
:
<xsl:param>boost.root=../../../..
<format>pdf:<xsl:param>boost.url.prefix=http://www.boost.org/doc/libs/release/doc/html
;
+607
View File
@@ -0,0 +1,607 @@
[library Boost.Lexical_Cast
[quickbook 1.5]
[version 1.0]
[copyright 2000-2005 Kevlin Henney]
[copyright 2006-2010 Alexander Nasonov]
[copyright 2011 Antony Polukhin]
[category String and text processing]
[category Miscellaneous]
[license
Distributed under the Boost Software License, Version 1.0.
(See accompanying file LICENSE_1_0.txt or copy at
[@http://www.boost.org/LICENSE_1_0.txt])
]
]
[def __numericcast__ [@boost:libs/numeric/conversion/doc/html/boost_numericconversion/improved_numeric_cast__.html `boost::numeric_cast`]]
[def __proposallong__ [@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2006/n1973.html Lexical Conversion Library Proposal for TR2, N1973 by Kevlin Henney and Beman Dawes]]
[def __proposalshort__ [@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2006/n1973.html Lexical Conversion Library Proposal for TR2, N1973]]
[section Motivation]
Sometimes a value must be converted to a literal text form, such as an [c++] `int` represented as a `std::string`, or vice-versa, when a `std::string` is interpreted as an `int`. Such examples are common when converting between data types internal to a program and representation external to a program, such as windows and configuration files.
The standard C and C++ libraries offer a number of facilities for performing such conversions. However, they vary with their ease of use, extensibility, and safety.
For instance, there are a number of limitations with the family of standard C functions typified by `atoi`:
* Conversion is supported in one direction only: from text to internal data type. Converting the other way using the C library requires either the inconvenience and compromised safety of the `sprintf` function, or the loss of portability associated with non-standard functions such as `itoa`.
* The range of types supported is only a subset of the built-in numeric types, namely `int`, `long`, and `double`.
* The range of types cannot be extended in a uniform manner. For instance, conversion from string representation to complex or rational.
The standard C functions typified by `strtol` have the same basic limitations, but offer finer control over the conversion process. However, for the common case such control is often either not required or not used. The `scanf` family of functions offer even greater control, but also lack safety and ease of use.
The standard C++ library offers `stringstream` for the kind of in-core formatting being discussed. It offers a great deal of control over the formatting and conversion of I/O to and from arbitrary types through text. However, for simple conversions direct use of `stringstream` can be either clumsy (with the introduction of extra local variables and the loss of infix-expression convenience) or obscure (where `stringstream` objects are created as temporary objects in an expression). Facets provide a comprehensive concept and facility for controlling textual representation, but their perceived complexity and high entry level requires an extreme degree of involvement for simple conversions, and excludes all but a few programmers.
The `lexical_cast` function template offers a convenient and consistent form for supporting common conversions to and from arbitrary types when they are represented as text. The simplification it offers is in expression-level convenience for such conversions. For more involved conversions, such as where precision or formatting need tighter control than is offered by the default behavior of `lexical_cast`, the conventional `std::stringstream` approach is recommended. Where the conversions are numeric to numeric, __numericcast__ may offer more reasonable behavior than `lexical_cast`.
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, [@http://www.gotw.ca/publications/mill19.htm The String Formatters of Manor Farm]. Also, take a look at the [link boost_lexical_cast.performance Performance] section.
[endsect]
[section Examples]
The following example treats command line arguments as a sequence of numeric data:
``
int main(int argc, char * argv[])
{
using boost::lexical_cast;
using boost::bad_lexical_cast;
std::vector<short> args;
while(*++argv)
{
try
{
args.push_back(lexical_cast<short>(*argv));
}
catch(bad_lexical_cast &)
{
args.push_back(0);
}
}
...
}
``
The following example uses numeric data in a string expression:
``
void log_message(const std::string &);
void log_errno(int yoko)
{
log_message("Error " + boost::lexical_cast<std::string>(yoko) + ": " + strerror(yoko));
}
``
[endsect]
[section Synopsis]
Library features defined in [@boost:boost/lexical_cast.hpp boost/lexical_cast.hpp]:
``
namespace boost
{
class bad_lexical_cast;
template<typename Target, typename Source>
Target lexical_cast(const Source& arg);
}
``
[section lexical_cast]
``
template<typename Target, typename Source>
Target lexical_cast(const Source& arg);
``
Returns the result of streaming arg into a standard library string-based stream and then out as a Target object. Where Target is either `std::string` or `std::wstring`, stream extraction takes the whole content of the string, including spaces, rather than relying on the default `operator>>` behavior. If the conversion is unsuccessful, a `bad_lexical_cast` exception is thrown.
The requirements on the argument and result types are:
* Source is OutputStreamable, meaning that an `operator<<` is defined that takes a `std::ostream` or `std::wostream` object on the left hand side and an instance of the argument type on the right.
* Target is InputStreamable, meaning that an `operator>>` is defined that takes a `std::istream` or `std::wistream` object on the left hand side and an instance of the result type on the right.
* Target is CopyConstructible [20.1.3].
* Target is DefaultConstructible, meaning that it is possible to default-initialize an object of that type [8.5, 20.1.4].
The character type of the underlying stream is assumed to be char unless either the Source or the Target requires wide-character streaming, in which case the underlying stream uses `wchar_t`. Source types that require wide-character streaming are `wchar_t`, `wchar_t *`, and `std::wstring`. Target types that require wide-character streaming are `wchar_t` and `std::wstring`.
Where a higher degree of control is required over conversions, `std::stringstream` and `std::wstringstream` offer a more appropriate path. Where non-stream-based conversions are required, `lexical_cast` is the wrong tool for the job and is not special-cased for such scenarios.
[endsect]
[section bad_lexical_cast]
``
class bad_lexical_cast : public std::bad_cast
{
public:
... // same member function interface as std::exception
};
``
Exception used to indicate runtime lexical_cast failure.
[endsect]
[endsect]
[section Frequently Asked Questions]
* [*Question:] Why does `lexical_cast<int8_t>("127")` throw `bad_lexical_cast`?
* [*Answer:] The type `int8_t` is a `typedef` to `char` or `signed char`. Lexical conversion to these types is simply reading a byte from source but since the source has more than one byte, the exception is thrown.
Please use other integer types such as `int` or `short int`. If bounds checking is important, you can also
call __numericcast__:
`numeric_cast<int8_t>(lexical_cast<int>("127"));`
[pre
]
* [*Question:] Why does `lexical_cast<unsigned char>("127")` throw `bad_lexical_cast`?
* [*Answer:] Lexical conversion to any char type is simply reading a byte from source. But since the source has more than one byte, the exception is thrown.
Please use other integer types such as `int` or `short int`. If bounds checking is important, you can also
call __numericcast__:
`numeric_cast<unsigned char>(lexical_cast<int>("127"));`
[pre
]
* [*Question:] What does `lexical_cast<std::string>` of an `int8_t` or `uint8_t` not do what I expect?
* [*Answer:] As above, note that int8_t and uint8_t are actually chars and are formatted as such. To avoid
this, cast to an integer type first: `lexical_cast<std::string>(static_cast<int>(n));`
[pre
]
* [*Question:] The implementation always resets the `ios_base::skipws` flag of an underlying stream object.
It breaks my `operator>>` that works only in presence of this flag. Can you remove code that resets the flag?
* [*Answer:] May be in a future version. There is no requirement in
__proposallong__ to reset the flag but
remember that __proposalshort__ is not yet accepted by the committee. By the way, it's a great opportunity to
make your `operator>>` conform to the standard.
Read a good C++ book, study `std::sentry` and [@boost:libs/io/doc/ios_state.html `ios_state_saver`].
[pre
]
* [*Question:] Why `std::cout << boost::lexical_cast<unsigned int>("-1");` does not throw, but outputs 4294967295?
* [*Answer:] `boost::lexical_cast` has the behavior of `std::stringstream`, which uses `num_get` functions of
`std::locale` to convert numbers. If we look at the Programming languages — C++, we'll see, that `num_get` uses
the rules of `scanf` for conversions. And in the C99 standard for unsigned input value minus sign is optional, so
if a negative number is read, no errors will arise and the result will be the two's complement.
[endsect]
[section Changes]
* [*boost 1.48.0 :]
* Added code to work with Inf and NaN on any platform.
* Better performance and less memory usage for conversions to float type (and to double type, if `sizeof(double) < sizeof(long double)`).
* [*boost 1.47.0 :]
* 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.
* Directly construct Target from Source on some conversions (like conversions from string to string, from char array to string, from char to char and others).
* [*boost 1.34.0 :]
* Better performance for many combinations of Source and Target types. For more details refer to Alexander Nasonovs article [@http://accu.org/index.php/journals/1375 Fine Tuning for lexical_cast, Overload #74, August 2006] [@http://www.accu.org/var/uploads/journals/overload74.pdf (PDF)].
* [*boost 1.33.0 :]
* Call-by-const reference for the parameters. This requires partial specialization of class templates, so it doesn't work for MSVC 6, and it uses the original pass by value there.
* The MSVC 6 support is deprecated, and will be removed in a future Boost version.
* [*Earlier :]
* The previous version of lexical_cast used the default stream precision for reading and writing floating-point numbers. For numerics that have a corresponding specialization of `std::numeric_limits`, the current version now chooses a precision to match.
* The previous version of lexical_cast did not support conversion to or from any wide-character-based types. For compilers with full language and library support for wide characters, `lexical_cast` now supports conversions from `wchar_t`, `wchar_t *`, and `std::wstring` and to `wchar_t` and `std::wstring`.
* The previous version of `lexical_cast` assumed that the conventional stream extractor operators were sufficient for reading values. However, string I/O is asymmetric, with the result that spaces play the role of I/O separators rather than string content. The current version fixes this error for `std::string` and, where supported, `std::wstring`: `lexical_cast<std::string>("Hello, World")` succeeds instead of failing with a `bad_lexical_cast` exception.
* The previous version of `lexical_cast` allowed unsafe and meaningless conversions to pointers. The current version now throws a `bad_lexical_cast` for conversions to pointers: `lexical_cast<char *>("Goodbye, World")` now throws an exception instead of causing undefined behavior.
[endsect]
[section Performance]
In most cases `boost::lexical_cast` is faster than `scanf`, `printf`, `std::stringstream`. For more detailed info you can look at the tables below.
[section Tests description]
All the tests measure execution speed in milliseconds for 10000 iterations of the following code blocks:
[table:legend Tests source code
[[Test name] [Code]]
[[lexical_cast]
[``
_out = boost::lexical_cast<OUTTYPE>(_in);
``]
]
[[std::stringstream with construction]
[``
std::stringstream ss;
ss << _in;
if (ss.fail()) throw std::logic_error(descr);
ss >> _out;
if (ss.fail()) throw std::logic_error(descr);
``]
]
[[std::stringstream without construction]
[``
ss << _in; // ss is an instance of std::stringstream
if (ss.fail()) throw std::logic_error(descr);
ss >> _out;
if (ss.fail()) throw std::logic_error(descr);
/* reseting std::stringstream to use it again */
ss.str(std::string());
ss.clear();
``]
]
[[scanf/printf]
[``
typename OUTTYPE::value_type buffer[500];
sprintf( (char*)buffer, conv, _in);
_out = buffer;
``]
]
]
Fastest results are highlitened with "!!! *x* !!!".
Do not use this results to compare compilers, because tests were taken on different hardware.
[endsect]
[/ BEGIN of section, generated by performance measuring program ]
[section clang-linux-2.8][table:id Performance Table (clang-linux-2.8)
[[From->To] [lexical_cast] [std::stringstream with construction] [std::stringstream without construction][scanf/printf]]
[[ string->char ][ !!! *<1* !!! ][ 148 ][ 14 ][ 12 ]]
[[ string->signed char ][ !!! *<1* !!! ][ 97 ][ 8 ][ 7 ]]
[[ string->unsigned char ][ !!! *<1* !!! ][ 90 ][ 8 ][ 13 ]]
[[ string->int ][ !!! *4* !!! ][ 102 ][ 19 ][ 15 ]]
[[ string->short ][ !!! *4* !!! ][ 105 ][ 20 ][ 15 ]]
[[ string->long int ][ !!! *4* !!! ][ 105 ][ 19 ][ 15 ]]
[[ string->long long ][ !!! *4* !!! ][ 115 ][ 19 ][ 14 ]]
[[ string->unsigned int ][ !!! *4* !!! ][ 102 ][ 18 ][ 14 ]]
[[ string->unsigned short ][ !!! *4* !!! ][ 101 ][ 19 ][ 15 ]]
[[ string->unsigned long int ][ !!! *3* !!! ][ 107 ][ 20 ][ 14 ]]
[[ string->unsigned long long ][ !!! *3* !!! ][ 103 ][ 20 ][ 14 ]]
[[ string->bool ][ !!! *<1* !!! ][ 97 ][ 16 ][ 8 ]]
[[ string->float ][ !!! *21* !!! ][ 170 ][ 61 ][ 32 ]]
[[ string->double ][ !!! *18* !!! ][ 206 ][ 93 ][ 58 ]]
[[ string->long double ][ 135 ][ 221 ][ 94 ][ !!! *57* !!! ]]
[[ char->string ][ !!! *7* !!! ][ 100 ][ 17 ][ 13 ]]
[[ unsigned char->string ][ !!! *7* !!! ][ 99 ][ 18 ][ 16 ]]
[[ signed char->string ][ !!! *7* !!! ][ 101 ][ 17 ][ 12 ]]
[[ int->string ][ !!! *13* !!! ][ 110 ][ 23 ][ 15 ]]
[[ short->string ][ !!! *13* !!! ][ 112 ][ 24 ][ 18 ]]
[[ long int->string ][ !!! *13* !!! ][ 119 ][ 23 ][ 17 ]]
[[ long long->string ][ !!! *13* !!! ][ 110 ][ 23 ][ 18 ]]
[[ unsigned int->string ][ !!! *14* !!! ][ 113 ][ 24 ][ 17 ]]
[[ unsigned short->string ][ !!! *13* !!! ][ 108 ][ 24 ][ 17 ]]
[[ unsigned long int->string ][ !!! *13* !!! ][ 109 ][ 24 ][ 16 ]]
[[ unsigned long long->string ][ !!! *13* !!! ][ 110 ][ 23 ][ 17 ]]
[[ bool->string ][ !!! *7* !!! ][ 105 ][ 24 ][ 12 ]]
[[ float->string ][ 70 ][ 192 ][ 94 ][ !!! *49* !!! ]]
[[ double->string ][ 106 ][ 217 ][ 122 ][ !!! *76* !!! ]]
[[ long double->string ][ 120 ][ 219 ][ 123 ][ !!! *80* !!! ]]
[[ char*->char ][ !!! *2* !!! ][ 90 ][ 9 ][ 8 ]]
[[ char*->signed char ][ !!! *2* !!! ][ 87 ][ 10 ][ 7 ]]
[[ char*->unsigned char ][ !!! *3* !!! ][ 90 ][ 10 ][ 13 ]]
[[ char*->int ][ !!! *6* !!! ][ 107 ][ 21 ][ 15 ]]
[[ char*->short ][ !!! *6* !!! ][ 110 ][ 19 ][ 14 ]]
[[ char*->long int ][ !!! *6* !!! ][ 103 ][ 19 ][ 14 ]]
[[ char*->long long ][ !!! *7* !!! ][ 104 ][ 20 ][ 15 ]]
[[ char*->unsigned int ][ !!! *6* !!! ][ 101 ][ 20 ][ 15 ]]
[[ char*->unsigned short ][ !!! *7* !!! ][ 100 ][ 20 ][ 14 ]]
[[ char*->unsigned long int ][ !!! *6* !!! ][ 105 ][ 22 ][ 15 ]]
[[ char*->unsigned long long ][ !!! *7* !!! ][ 106 ][ 21 ][ 14 ]]
[[ char*->bool ][ !!! *2* !!! ][ 99 ][ 18 ][ 7 ]]
[[ char*->float ][ !!! *22* !!! ][ 159 ][ 67 ][ 33 ]]
[[ char*->double ][ !!! *20* !!! ][ 205 ][ 94 ][ 58 ]]
[[ char*->long double ][ 140 ][ 214 ][ 95 ][ !!! *58* !!! ]]
[[ unsigned char*->char ][ !!! *2* !!! ][ 92 ][ 9 ][ 7 ]]
[[ unsigned char*->signed char ][ !!! *2* !!! ][ 89 ][ 10 ][ 7 ]]
[[ unsigned char*->unsigned char ][ !!! *2* !!! ][ 89 ][ 10 ][ 14 ]]
[[ unsigned char*->int ][ !!! *6* !!! ][ 104 ][ 20 ][ 14 ]]
[[ unsigned char*->short ][ !!! *6* !!! ][ 106 ][ 21 ][ 14 ]]
[[ unsigned char*->long int ][ !!! *6* !!! ][ 105 ][ 19 ][ 14 ]]
[[ unsigned char*->long long ][ !!! *6* !!! ][ 106 ][ 20 ][ 15 ]]
[[ unsigned char*->unsigned int ][ !!! *7* !!! ][ 105 ][ 19 ][ 14 ]]
[[ unsigned char*->unsigned short ][ !!! *6* !!! ][ 103 ][ 19 ][ 14 ]]
[[ unsigned char*->unsigned long int ][ !!! *6* !!! ][ 106 ][ 19 ][ 14 ]]
[[ unsigned char*->unsigned long long ][ !!! *6* !!! ][ 104 ][ 21 ][ 15 ]]
[[ unsigned char*->bool ][ !!! *2* !!! ][ 102 ][ 18 ][ 7 ]]
[[ unsigned char*->float ][ !!! *23* !!! ][ 160 ][ 66 ][ 32 ]]
[[ unsigned char*->double ][ !!! *20* !!! ][ 201 ][ 95 ][ 58 ]]
[[ unsigned char*->long double ][ 144 ][ 221 ][ 95 ][ !!! *60* !!! ]]
[[ unsigned char*->string ][ !!! *12* !!! ][ 104 ][ 23 ][ --- ]]
[[ signed char*->char ][ !!! *2* !!! ][ 90 ][ 9 ][ 7 ]]
[[ signed char*->signed char ][ !!! *2* !!! ][ 89 ][ 9 ][ 7 ]]
[[ signed char*->unsigned char ][ !!! *2* !!! ][ 89 ][ 10 ][ 13 ]]
[[ signed char*->int ][ !!! *6* !!! ][ 106 ][ 19 ][ 15 ]]
[[ signed char*->short ][ !!! *6* !!! ][ 107 ][ 20 ][ 15 ]]
[[ signed char*->long int ][ !!! *6* !!! ][ 103 ][ 19 ][ 14 ]]
[[ signed char*->long long ][ !!! *6* !!! ][ 103 ][ 19 ][ 14 ]]
[[ signed char*->unsigned int ][ !!! *6* !!! ][ 101 ][ 19 ][ 15 ]]
[[ signed char*->unsigned short ][ !!! *6* !!! ][ 101 ][ 19 ][ 16 ]]
[[ signed char*->unsigned long int ][ !!! *6* !!! ][ 105 ][ 22 ][ 15 ]]
[[ signed char*->unsigned long long ][ !!! *6* !!! ][ 104 ][ 21 ][ 15 ]]
[[ signed char*->bool ][ !!! *2* !!! ][ 100 ][ 18 ][ 7 ]]
[[ signed char*->float ][ !!! *23* !!! ][ 161 ][ 62 ][ 32 ]]
[[ signed char*->double ][ !!! *20* !!! ][ 207 ][ 102 ][ 57 ]]
[[ signed char*->long double ][ 144 ][ 216 ][ 96 ][ !!! *63* !!! ]]
[[ signed char*->string ][ !!! *12* !!! ][ 104 ][ 23 ][ --- ]]
[[ int->int ][ !!! *<1* !!! ][ 110 ][ 22 ][ --- ]]
[[ float->double ][ !!! *<1* !!! ][ 223 ][ 113 ][ --- ]]
[[ double->double ][ !!! *<1* !!! ][ 227 ][ 111 ][ --- ]]
[[ int->int ][ !!! *<1* !!! ][ 231 ][ 122 ][ --- ]]
[[ int->int ][ !!! *<1* !!! ][ 229 ][ 121 ][ --- ]]
[[ char->unsigned char ][ !!! *<1* !!! ][ 90 ][ 8 ][ --- ]]
[[ char->signed char ][ !!! *<1* !!! ][ 88 ][ 8 ][ --- ]]
[[ unsigned char->char ][ !!! *<1* !!! ][ 89 ][ 8 ][ --- ]]
[[ signed char->char ][ !!! *<1* !!! ][ 91 ][ 9 ][ --- ]]
]
[endsect]
[section gcc-4.4][table:id Performance Table (gcc-4.4)
[[From->To] [lexical_cast] [std::stringstream with construction] [std::stringstream without construction][scanf/printf]]
[[ string->char ][ !!! *<1* !!! ][ 90 ][ 7 ][ 7 ]]
[[ string->signed char ][ !!! *<1* !!! ][ 88 ][ 7 ][ 8 ]]
[[ string->unsigned char ][ !!! *<1* !!! ][ 88 ][ 8 ][ 14 ]]
[[ string->int ][ !!! *3* !!! ][ 103 ][ 18 ][ 15 ]]
[[ string->short ][ !!! *3* !!! ][ 105 ][ 20 ][ 15 ]]
[[ string->long int ][ !!! *3* !!! ][ 101 ][ 18 ][ 16 ]]
[[ string->long long ][ !!! *3* !!! ][ 101 ][ 18 ][ 15 ]]
[[ string->unsigned int ][ !!! *3* !!! ][ 98 ][ 23 ][ 14 ]]
[[ string->unsigned short ][ !!! *3* !!! ][ 100 ][ 17 ][ 14 ]]
[[ string->unsigned long int ][ !!! *3* !!! ][ 100 ][ 21 ][ 15 ]]
[[ string->unsigned long long ][ !!! *3* !!! ][ 99 ][ 19 ][ 15 ]]
[[ string->bool ][ !!! *<1* !!! ][ 95 ][ 16 ][ 8 ]]
[[ string->float ][ !!! *13* !!! ][ 160 ][ 61 ][ 33 ]]
[[ string->double ][ !!! *14* !!! ][ 206 ][ 93 ][ 59 ]]
[[ string->long double ][ 128 ][ 217 ][ 96 ][ !!! *61* !!! ]]
[[ char->string ][ !!! *7* !!! ][ 100 ][ 17 ][ 12 ]]
[[ unsigned char->string ][ !!! *7* !!! ][ 109 ][ 17 ][ 16 ]]
[[ signed char->string ][ !!! *7* !!! ][ 99 ][ 17 ][ 12 ]]
[[ int->string ][ !!! *13* !!! ][ 110 ][ 21 ][ 15 ]]
[[ short->string ][ !!! *14* !!! ][ 110 ][ 22 ][ 17 ]]
[[ long int->string ][ !!! *14* !!! ][ 109 ][ 21 ][ 16 ]]
[[ long long->string ][ !!! *13* !!! ][ 114 ][ 20 ][ 17 ]]
[[ unsigned int->string ][ !!! *13* !!! ][ 109 ][ 23 ][ 15 ]]
[[ unsigned short->string ][ !!! *14* !!! ][ 109 ][ 23 ][ 17 ]]
[[ unsigned long int->string ][ !!! *13* !!! ][ 112 ][ 23 ][ 16 ]]
[[ unsigned long long->string ][ !!! *14* !!! ][ 109 ][ 21 ][ 17 ]]
[[ bool->string ][ !!! *7* !!! ][ 108 ][ 23 ][ 11 ]]
[[ float->string ][ 63 ][ 185 ][ 92 ][ !!! *50* !!! ]]
[[ double->string ][ 106 ][ 216 ][ 116 ][ !!! *75* !!! ]]
[[ long double->string ][ 118 ][ 219 ][ 119 ][ !!! *80* !!! ]]
[[ char*->char ][ !!! *1* !!! ][ 93 ][ 9 ][ 9 ]]
[[ char*->signed char ][ !!! *1* !!! ][ 92 ][ 9 ][ 9 ]]
[[ char*->unsigned char ][ !!! *1* !!! ][ 92 ][ 9 ][ 14 ]]
[[ char*->int ][ !!! *4* !!! ][ 107 ][ 19 ][ 15 ]]
[[ char*->short ][ !!! *5* !!! ][ 109 ][ 19 ][ 15 ]]
[[ char*->long int ][ !!! *4* !!! ][ 113 ][ 19 ][ 15 ]]
[[ char*->long long ][ !!! *4* !!! ][ 108 ][ 20 ][ 15 ]]
[[ char*->unsigned int ][ !!! *4* !!! ][ 106 ][ 19 ][ 15 ]]
[[ char*->unsigned short ][ !!! *4* !!! ][ 106 ][ 18 ][ 15 ]]
[[ char*->unsigned long int ][ !!! *4* !!! ][ 103 ][ 22 ][ 15 ]]
[[ char*->unsigned long long ][ !!! *4* !!! ][ 105 ][ 20 ][ 15 ]]
[[ char*->bool ][ !!! *1* !!! ][ 104 ][ 18 ][ 8 ]]
[[ char*->float ][ !!! *15* !!! ][ 164 ][ 62 ][ 33 ]]
[[ char*->double ][ !!! *16* !!! ][ 203 ][ 97 ][ 58 ]]
[[ char*->long double ][ 132 ][ 223 ][ 98 ][ !!! *60* !!! ]]
[[ unsigned char*->char ][ !!! *2* !!! ][ 90 ][ 9 ][ 8 ]]
[[ unsigned char*->signed char ][ !!! *2* !!! ][ 92 ][ 10 ][ 8 ]]
[[ unsigned char*->unsigned char ][ !!! *2* !!! ][ 91 ][ 9 ][ 14 ]]
[[ unsigned char*->int ][ !!! *6* !!! ][ 106 ][ 20 ][ 15 ]]
[[ unsigned char*->short ][ !!! *6* !!! ][ 106 ][ 21 ][ 15 ]]
[[ unsigned char*->long int ][ !!! *6* !!! ][ 111 ][ 19 ][ 15 ]]
[[ unsigned char*->long long ][ !!! *6* !!! ][ 107 ][ 20 ][ 15 ]]
[[ unsigned char*->unsigned int ][ !!! *6* !!! ][ 105 ][ 19 ][ 15 ]]
[[ unsigned char*->unsigned short ][ !!! *6* !!! ][ 103 ][ 18 ][ 15 ]]
[[ unsigned char*->unsigned long int ][ !!! *6* !!! ][ 106 ][ 22 ][ 14 ]]
[[ unsigned char*->unsigned long long ][ !!! *6* !!! ][ 105 ][ 20 ][ 14 ]]
[[ unsigned char*->bool ][ !!! *2* !!! ][ 106 ][ 18 ][ 8 ]]
[[ unsigned char*->float ][ !!! *15* !!! ][ 167 ][ 68 ][ 33 ]]
[[ unsigned char*->double ][ !!! *17* !!! ][ 203 ][ 99 ][ 58 ]]
[[ unsigned char*->long double ][ 129 ][ 216 ][ 97 ][ !!! *61* !!! ]]
[[ unsigned char*->string ][ !!! *13* !!! ][ 111 ][ 23 ][ --- ]]
[[ signed char*->char ][ !!! *2* !!! ][ 92 ][ 9 ][ 8 ]]
[[ signed char*->signed char ][ !!! *2* !!! ][ 91 ][ 9 ][ 8 ]]
[[ signed char*->unsigned char ][ !!! *2* !!! ][ 91 ][ 9 ][ 14 ]]
[[ signed char*->int ][ !!! *6* !!! ][ 107 ][ 19 ][ 15 ]]
[[ signed char*->short ][ !!! *6* !!! ][ 109 ][ 24 ][ 14 ]]
[[ signed char*->long int ][ !!! *6* !!! ][ 112 ][ 19 ][ 15 ]]
[[ signed char*->long long ][ !!! *5* !!! ][ 107 ][ 20 ][ 15 ]]
[[ signed char*->unsigned int ][ !!! *6* !!! ][ 108 ][ 20 ][ 15 ]]
[[ signed char*->unsigned short ][ !!! *6* !!! ][ 104 ][ 18 ][ 15 ]]
[[ signed char*->unsigned long int ][ !!! *6* !!! ][ 102 ][ 22 ][ 15 ]]
[[ signed char*->unsigned long long ][ !!! *6* !!! ][ 104 ][ 20 ][ 15 ]]
[[ signed char*->bool ][ !!! *2* !!! ][ 104 ][ 18 ][ 8 ]]
[[ signed char*->float ][ !!! *16* !!! ][ 165 ][ 63 ][ 33 ]]
[[ signed char*->double ][ !!! *16* !!! ][ 203 ][ 98 ][ 59 ]]
[[ signed char*->long double ][ 129 ][ 215 ][ 98 ][ !!! *61* !!! ]]
[[ signed char*->string ][ !!! *13* !!! ][ 109 ][ 21 ][ --- ]]
[[ int->int ][ !!! *<1* !!! ][ 109 ][ 21 ][ --- ]]
[[ float->double ][ !!! *<1* !!! ][ 221 ][ 102 ][ --- ]]
[[ double->double ][ !!! *<1* !!! ][ 223 ][ 103 ][ --- ]]
[[ int->int ][ !!! *<1* !!! ][ 231 ][ 115 ][ --- ]]
[[ int->int ][ !!! *<1* !!! ][ 231 ][ 115 ][ --- ]]
[[ char->unsigned char ][ !!! *<1* !!! ][ 92 ][ 8 ][ --- ]]
[[ char->signed char ][ !!! *<1* !!! ][ 88 ][ 8 ][ --- ]]
[[ unsigned char->char ][ !!! *<1* !!! ][ 88 ][ 7 ][ --- ]]
[[ signed char->char ][ !!! *<1* !!! ][ 89 ][ 8 ][ --- ]]
]
[endsect]
[section gcc-4.5][table:id Performance Table (gcc-4.5)
[[From->To] [lexical_cast] [std::stringstream with construction] [std::stringstream without construction][scanf/printf]]
[[ string->char ][ !!! *<1* !!! ][ 91 ][ 8 ][ 7 ]]
[[ string->signed char ][ !!! *<1* !!! ][ 91 ][ 8 ][ 7 ]]
[[ string->unsigned char ][ !!! *<1* !!! ][ 90 ][ 8 ][ 13 ]]
[[ string->int ][ !!! *3* !!! ][ 100 ][ 20 ][ 14 ]]
[[ string->short ][ !!! *3* !!! ][ 106 ][ 20 ][ 14 ]]
[[ string->long int ][ !!! *3* !!! ][ 100 ][ 18 ][ 14 ]]
[[ string->long long ][ !!! *9* !!! ][ 100 ][ 18 ][ 15 ]]
[[ string->unsigned int ][ !!! *3* !!! ][ 97 ][ 20 ][ 14 ]]
[[ string->unsigned short ][ !!! *3* !!! ][ 102 ][ 17 ][ 14 ]]
[[ string->unsigned long int ][ !!! *3* !!! ][ 97 ][ 21 ][ 14 ]]
[[ string->unsigned long long ][ !!! *3* !!! ][ 97 ][ 19 ][ 14 ]]
[[ string->bool ][ !!! *<1* !!! ][ 95 ][ 16 ][ 7 ]]
[[ string->float ][ !!! *15* !!! ][ 157 ][ 63 ][ 32 ]]
[[ string->double ][ !!! *17* !!! ][ 203 ][ 95 ][ 59 ]]
[[ string->long double ][ 129 ][ 216 ][ 93 ][ !!! *58* !!! ]]
[[ char->string ][ !!! *8* !!! ][ 100 ][ 17 ][ 10 ]]
[[ unsigned char->string ][ !!! *8* !!! ][ 96 ][ 18 ][ 16 ]]
[[ signed char->string ][ !!! *8* !!! ][ 96 ][ 18 ][ 10 ]]
[[ int->string ][ !!! *14* !!! ][ 105 ][ 22 ][ 15 ]]
[[ short->string ][ !!! *14* !!! ][ 107 ][ 23 ][ 17 ]]
[[ long int->string ][ !!! *14* !!! ][ 109 ][ 22 ][ 17 ]]
[[ long long->string ][ !!! *14* !!! ][ 105 ][ 22 ][ 18 ]]
[[ unsigned int->string ][ !!! *14* !!! ][ 105 ][ 25 ][ 15 ]]
[[ unsigned short->string ][ !!! *15* !!! ][ 105 ][ 23 ][ 17 ]]
[[ unsigned long int->string ][ !!! *14* !!! ][ 109 ][ 24 ][ 17 ]]
[[ unsigned long long->string ][ !!! *14* !!! ][ 102 ][ 23 ][ 17 ]]
[[ bool->string ][ !!! *8* !!! ][ 104 ][ 23 ][ 12 ]]
[[ float->string ][ 66 ][ 181 ][ 92 ][ !!! *49* !!! ]]
[[ double->string ][ 107 ][ 215 ][ 120 ][ !!! *75* !!! ]]
[[ long double->string ][ 117 ][ 221 ][ 125 ][ !!! *79* !!! ]]
[[ char*->char ][ !!! *1* !!! ][ 89 ][ 9 ][ 7 ]]
[[ char*->signed char ][ !!! *1* !!! ][ 90 ][ 9 ][ 7 ]]
[[ char*->unsigned char ][ !!! *2* !!! ][ 90 ][ 9 ][ 13 ]]
[[ char*->int ][ !!! *7* !!! ][ 103 ][ 20 ][ 15 ]]
[[ char*->short ][ !!! *6* !!! ][ 102 ][ 29 ][ 14 ]]
[[ char*->long int ][ !!! *7* !!! ][ 101 ][ 20 ][ 15 ]]
[[ char*->long long ][ !!! *6* !!! ][ 102 ][ 20 ][ 14 ]]
[[ char*->unsigned int ][ !!! *6* !!! ][ 99 ][ 19 ][ 14 ]]
[[ char*->unsigned short ][ !!! *6* !!! ][ 101 ][ 18 ][ 14 ]]
[[ char*->unsigned long int ][ !!! *6* !!! ][ 102 ][ 22 ][ 14 ]]
[[ char*->unsigned long long ][ !!! *6* !!! ][ 101 ][ 21 ][ 14 ]]
[[ char*->bool ][ !!! *3* !!! ][ 98 ][ 18 ][ 7 ]]
[[ char*->float ][ !!! *18* !!! ][ 162 ][ 63 ][ 31 ]]
[[ char*->double ][ !!! *17* !!! ][ 203 ][ 96 ][ 58 ]]
[[ char*->long double ][ 135 ][ 214 ][ 98 ][ !!! *58* !!! ]]
[[ unsigned char*->char ][ !!! *2* !!! ][ 87 ][ 9 ][ 7 ]]
[[ unsigned char*->signed char ][ !!! *2* !!! ][ 87 ][ 9 ][ 7 ]]
[[ unsigned char*->unsigned char ][ !!! *3* !!! ][ 87 ][ 9 ][ 13 ]]
[[ unsigned char*->int ][ !!! *6* !!! ][ 105 ][ 20 ][ 14 ]]
[[ unsigned char*->short ][ !!! *6* !!! ][ 102 ][ 21 ][ 14 ]]
[[ unsigned char*->long int ][ !!! *6* !!! ][ 101 ][ 20 ][ 14 ]]
[[ unsigned char*->long long ][ !!! *6* !!! ][ 102 ][ 20 ][ 14 ]]
[[ unsigned char*->unsigned int ][ !!! *6* !!! ][ 99 ][ 19 ][ 14 ]]
[[ unsigned char*->unsigned short ][ !!! *6* !!! ][ 100 ][ 18 ][ 14 ]]
[[ unsigned char*->unsigned long int ][ !!! *6* !!! ][ 101 ][ 24 ][ 14 ]]
[[ unsigned char*->unsigned long long ][ !!! *6* !!! ][ 100 ][ 20 ][ 14 ]]
[[ unsigned char*->bool ][ !!! *3* !!! ][ 99 ][ 18 ][ 8 ]]
[[ unsigned char*->float ][ !!! *17* !!! ][ 164 ][ 64 ][ 32 ]]
[[ unsigned char*->double ][ !!! *18* !!! ][ 201 ][ 94 ][ 58 ]]
[[ unsigned char*->long double ][ 133 ][ 217 ][ 95 ][ !!! *60* !!! ]]
[[ unsigned char*->string ][ !!! *14* !!! ][ 103 ][ 23 ][ --- ]]
[[ signed char*->char ][ !!! *3* !!! ][ 88 ][ 10 ][ 8 ]]
[[ signed char*->signed char ][ !!! *2* !!! ][ 87 ][ 10 ][ 7 ]]
[[ signed char*->unsigned char ][ !!! *3* !!! ][ 87 ][ 9 ][ 13 ]]
[[ signed char*->int ][ !!! *6* !!! ][ 104 ][ 20 ][ 14 ]]
[[ signed char*->short ][ !!! *6* !!! ][ 105 ][ 21 ][ 14 ]]
[[ signed char*->long int ][ !!! *6* !!! ][ 104 ][ 20 ][ 15 ]]
[[ signed char*->long long ][ !!! *6* !!! ][ 106 ][ 20 ][ 14 ]]
[[ signed char*->unsigned int ][ !!! *6* !!! ][ 99 ][ 20 ][ 14 ]]
[[ signed char*->unsigned short ][ !!! *6* !!! ][ 100 ][ 18 ][ 14 ]]
[[ signed char*->unsigned long int ][ !!! *6* !!! ][ 102 ][ 23 ][ 14 ]]
[[ signed char*->unsigned long long ][ !!! *6* !!! ][ 103 ][ 20 ][ 14 ]]
[[ signed char*->bool ][ !!! *3* !!! ][ 99 ][ 18 ][ 7 ]]
[[ signed char*->float ][ !!! *18* !!! ][ 159 ][ 60 ][ 32 ]]
[[ signed char*->double ][ !!! *18* !!! ][ 203 ][ 95 ][ 57 ]]
[[ signed char*->long double ][ 129 ][ 213 ][ 97 ][ !!! *56* !!! ]]
[[ signed char*->string ][ !!! *14* !!! ][ 105 ][ 22 ][ --- ]]
[[ int->int ][ !!! *<1* !!! ][ 109 ][ 22 ][ --- ]]
[[ float->double ][ !!! *<1* !!! ][ 226 ][ 104 ][ --- ]]
[[ double->double ][ !!! *<1* !!! ][ 229 ][ 103 ][ --- ]]
[[ int->int ][ !!! *<1* !!! ][ 225 ][ 115 ][ --- ]]
[[ int->int ][ !!! *<1* !!! ][ 227 ][ 115 ][ --- ]]
[[ char->unsigned char ][ !!! *<1* !!! ][ 90 ][ 8 ][ --- ]]
[[ char->signed char ][ !!! *<1* !!! ][ 84 ][ 8 ][ --- ]]
[[ unsigned char->char ][ !!! *<1* !!! ][ 88 ][ 8 ][ --- ]]
[[ signed char->char ][ !!! *<1* !!! ][ 89 ][ 8 ][ --- ]]
]
[endsect]
[section gcc-4.6][table:id Performance Table (gcc-4.6)
[[From->To] [lexical_cast] [std::stringstream with construction] [std::stringstream without construction][scanf/printf]]
[[ string->char ][ !!! *<1* !!! ][ 94 ][ 8 ][ 7 ]]
[[ string->signed char ][ !!! *<1* !!! ][ 96 ][ 9 ][ 7 ]]
[[ string->unsigned char ][ !!! *<1* !!! ][ 96 ][ 8 ][ 13 ]]
[[ string->int ][ !!! *3* !!! ][ 110 ][ 18 ][ 16 ]]
[[ string->short ][ !!! *3* !!! ][ 111 ][ 18 ][ 16 ]]
[[ string->long int ][ !!! *3* !!! ][ 109 ][ 18 ][ 15 ]]
[[ string->long long ][ !!! *3* !!! ][ 111 ][ 18 ][ 15 ]]
[[ string->unsigned int ][ !!! *3* !!! ][ 110 ][ 20 ][ 15 ]]
[[ string->unsigned short ][ !!! *3* !!! ][ 111 ][ 18 ][ 15 ]]
[[ string->unsigned long int ][ !!! *3* !!! ][ 109 ][ 18 ][ 15 ]]
[[ string->unsigned long long ][ !!! *3* !!! ][ 114 ][ 19 ][ 15 ]]
[[ string->bool ][ !!! *<1* !!! ][ 106 ][ 17 ][ 8 ]]
[[ string->float ][ !!! *13* !!! ][ 175 ][ 70 ][ 33 ]]
[[ string->double ][ !!! *14* !!! ][ 182 ][ 81 ][ 58 ]]
[[ string->long double ][ 118 ][ 190 ][ 87 ][ !!! *58* !!! ]]
[[ char->string ][ !!! *8* !!! ][ 118 ][ 21 ][ 12 ]]
[[ unsigned char->string ][ !!! *8* !!! ][ 109 ][ 18 ][ 16 ]]
[[ signed char->string ][ !!! *8* !!! ][ 108 ][ 18 ][ 12 ]]
[[ int->string ][ 20 ][ 121 ][ 21 ][ !!! *16* !!! ]]
[[ short->string ][ !!! *15* !!! ][ 120 ][ 22 ][ 17 ]]
[[ long int->string ][ !!! *15* !!! ][ 120 ][ 22 ][ 16 ]]
[[ long long->string ][ !!! *15* !!! ][ 120 ][ 22 ][ 17 ]]
[[ unsigned int->string ][ !!! *15* !!! ][ 120 ][ 22 ][ 16 ]]
[[ unsigned short->string ][ !!! *15* !!! ][ 120 ][ 22 ][ 18 ]]
[[ unsigned long int->string ][ 16 ][ 118 ][ 22 ][ !!! *15* !!! ]]
[[ unsigned long long->string ][ !!! *15* !!! ][ 117 ][ 21 ][ 17 ]]
[[ bool->string ][ !!! *8* !!! ][ 117 ][ 23 ][ 10 ]]
[[ float->string ][ 77 ][ 218 ][ 105 ][ !!! *50* !!! ]]
[[ double->string ][ 108 ][ 247 ][ 129 ][ !!! *73* !!! ]]
[[ long double->string ][ 120 ][ 250 ][ 131 ][ !!! *79* !!! ]]
[[ char*->char ][ !!! *2* !!! ][ 99 ][ 9 ][ 7 ]]
[[ char*->signed char ][ !!! *2* !!! ][ 98 ][ 9 ][ 8 ]]
[[ char*->unsigned char ][ !!! *2* !!! ][ 98 ][ 9 ][ 13 ]]
[[ char*->int ][ !!! *6* !!! ][ 115 ][ 22 ][ 15 ]]
[[ char*->short ][ !!! *6* !!! ][ 114 ][ 22 ][ 15 ]]
[[ char*->long int ][ !!! *6* !!! ][ 114 ][ 22 ][ 16 ]]
[[ char*->long long ][ !!! *6* !!! ][ 119 ][ 22 ][ 15 ]]
[[ char*->unsigned int ][ !!! *6* !!! ][ 114 ][ 20 ][ 15 ]]
[[ char*->unsigned short ][ !!! *6* !!! ][ 116 ][ 20 ][ 15 ]]
[[ char*->unsigned long int ][ !!! *6* !!! ][ 117 ][ 22 ][ 15 ]]
[[ char*->unsigned long long ][ !!! *6* !!! ][ 118 ][ 22 ][ 15 ]]
[[ char*->bool ][ !!! *3* !!! ][ 113 ][ 18 ][ 8 ]]
[[ char*->float ][ !!! *15* !!! ][ 180 ][ 78 ][ 32 ]]
[[ char*->double ][ !!! *16* !!! ][ 185 ][ 89 ][ 58 ]]
[[ char*->long double ][ 119 ][ 193 ][ 91 ][ !!! *60* !!! ]]
[[ unsigned char*->char ][ !!! *2* !!! ][ 99 ][ 9 ][ 8 ]]
[[ unsigned char*->signed char ][ !!! *2* !!! ][ 99 ][ 10 ][ 8 ]]
[[ unsigned char*->unsigned char ][ !!! *2* !!! ][ 100 ][ 9 ][ 15 ]]
[[ unsigned char*->int ][ !!! *6* !!! ][ 118 ][ 22 ][ 15 ]]
[[ unsigned char*->short ][ !!! *6* !!! ][ 117 ][ 26 ][ 15 ]]
[[ unsigned char*->long int ][ !!! *6* !!! ][ 119 ][ 21 ][ 15 ]]
[[ unsigned char*->long long ][ !!! *6* !!! ][ 118 ][ 21 ][ 14 ]]
[[ unsigned char*->unsigned int ][ !!! *6* !!! ][ 115 ][ 22 ][ 14 ]]
[[ unsigned char*->unsigned short ][ !!! *6* !!! ][ 117 ][ 20 ][ 15 ]]
[[ unsigned char*->unsigned long int ][ !!! *6* !!! ][ 115 ][ 21 ][ 15 ]]
[[ unsigned char*->unsigned long long ][ !!! *6* !!! ][ 117 ][ 22 ][ 15 ]]
[[ unsigned char*->bool ][ !!! *3* !!! ][ 112 ][ 18 ][ 8 ]]
[[ unsigned char*->float ][ !!! *15* !!! ][ 181 ][ 78 ][ 33 ]]
[[ unsigned char*->double ][ !!! *16* !!! ][ 185 ][ 92 ][ 59 ]]
[[ unsigned char*->long double ][ 120 ][ 190 ][ 89 ][ !!! *58* !!! ]]
[[ unsigned char*->string ][ !!! *14* !!! ][ 121 ][ 22 ][ --- ]]
[[ signed char*->char ][ !!! *2* !!! ][ 99 ][ 9 ][ 9 ]]
[[ signed char*->signed char ][ !!! *2* !!! ][ 98 ][ 9 ][ 8 ]]
[[ signed char*->unsigned char ][ !!! *2* !!! ][ 98 ][ 9 ][ 14 ]]
[[ signed char*->int ][ !!! *6* !!! ][ 119 ][ 22 ][ 16 ]]
[[ signed char*->short ][ !!! *6* !!! ][ 115 ][ 22 ][ 15 ]]
[[ signed char*->long int ][ !!! *6* !!! ][ 119 ][ 22 ][ 15 ]]
[[ signed char*->long long ][ !!! *6* !!! ][ 117 ][ 22 ][ 15 ]]
[[ signed char*->unsigned int ][ !!! *6* !!! ][ 117 ][ 23 ][ 15 ]]
[[ signed char*->unsigned short ][ !!! *6* !!! ][ 117 ][ 21 ][ 14 ]]
[[ signed char*->unsigned long int ][ !!! *7* !!! ][ 119 ][ 24 ][ 15 ]]
[[ signed char*->unsigned long long ][ !!! *6* !!! ][ 116 ][ 22 ][ 15 ]]
[[ signed char*->bool ][ !!! *3* !!! ][ 111 ][ 18 ][ 8 ]]
[[ signed char*->float ][ !!! *16* !!! ][ 180 ][ 78 ][ 33 ]]
[[ signed char*->double ][ !!! *16* !!! ][ 185 ][ 89 ][ 59 ]]
[[ signed char*->long double ][ 120 ][ 191 ][ 91 ][ !!! *59* !!! ]]
[[ signed char*->string ][ !!! *14* !!! ][ 122 ][ 23 ][ --- ]]
[[ int->int ][ !!! *<1* !!! ][ 120 ][ 22 ][ --- ]]
[[ float->double ][ !!! *<1* !!! ][ 242 ][ 115 ][ --- ]]
[[ double->double ][ !!! *<1* !!! ][ 243 ][ 115 ][ --- ]]
[[ int->int ][ !!! *<1* !!! ][ 265 ][ 141 ][ --- ]]
[[ int->int ][ !!! *<1* !!! ][ 266 ][ 140 ][ --- ]]
[[ char->unsigned char ][ !!! *<1* !!! ][ 95 ][ 8 ][ --- ]]
[[ char->signed char ][ !!! *<1* !!! ][ 95 ][ 8 ][ --- ]]
[[ unsigned char->char ][ !!! *<1* !!! ][ 94 ][ 8 ][ --- ]]
[[ signed char->char ][ !!! *<1* !!! ][ 94 ][ 8 ][ --- ]]
]
[endsect]
[/ END of section, generated by performance measuring program ]
[endsect]
+2 -2
View File
@@ -173,8 +173,8 @@ inline void lcast_set_precision(std::ios_base& stream, T*)
template<class Source, class Target>
inline void lcast_set_precision(std::ios_base& stream, Source*, Target*)
{
std::streamsize const s = lcast_get_precision((Source*)0);
std::streamsize const t = lcast_get_precision((Target*)0);
std::streamsize const s = lcast_get_precision(static_cast<Source*>(0));
std::streamsize const t = lcast_get_precision(static_cast<Target*>(0));
stream.precision(s > t ? s : t);
}
File diff suppressed because it is too large Load Diff
+1 -1
View File
@@ -24,7 +24,7 @@ supplied by several headers:</p>
and <b>polymorphic_downcast&lt;&gt;</b> to perform safe casting between
polymorphic types.<br>
</li>
<li>The <a href="lexical_cast.htm">boost/lexical_cast</a> header provides <b>lexical_cast&lt;&gt;</b>
<li>The <a href="../../doc/html/boost_lexical_cast.html">boost/lexical_cast</a> header provides <b>lexical_cast&lt;&gt;</b>
general literal text conversions, such as an <code>int</code> represented as
a <code>string</code>, or vice-versa.</li>
</ul>
+14 -268
View File
@@ -1,270 +1,16 @@
<!-- saved from url=(0022)http://internet.e-mail -->
<!doctype html public "-//W3C//DTD HTML Transitional 4.0//EN">
<!--
Copyright 2005-2007 Daniel James.
Distributed under the Boost Software License, Version 1.0. (See accompanying
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
-->
<html>
<head>
<title>lexical_cast</title>
<meta name="author" content="Kevlin Henney, mailto:kevlin@curbralan.com">
<meta name="generator" content="Microsoft FrontPage 5.0">
</head>
<body bgcolor="#FFFFFF" text="#000000">
<h1><img src="../../boost.png" alt="boost.png (6897 bytes)" align="center" width="277" height="86">Header
<a href="../../boost/lexical_cast.hpp">boost/lexical_cast.hpp</a></h1>
<ul type="square">
<li>
<a href="#motivation">Motivation</a></li>
<li>
<a href="#examples">Examples</a></li>
<li>
<a href="#synopsis">Synopsis</a></li>
<li>
<a href="#lexical_cast"><code>lexical_cast</code></a></li>
<li>
<a href="#bad_lexical_cast"><code>bad_lexical_cast</code></a></li>
<li>
<a href="#faq">Frequently Asked Questions</a></li>
<li>
<a href="#references">References</a></li>
<li>
<a href="#changes">Changes</a></li>
</ul>
<hr>
<h2><a name="motivation">Motivation</a></h2>
Sometimes a value must be converted to a literal text form, such as an <code>int</code>
represented as a <code>string</code>, or vice-versa, when a <code>string</code>
is interpreted as an <code>int</code>. Such examples are common when converting
between data types internal to a program and representation external to a
program, such as windows and configuration files.
<p>
The standard C and C++ libraries offer a number of facilities for performing
such conversions. However, they vary with their ease of use, extensibility, and
safety.
<p>
For instance, there are a number of limitations with the family of standard C
functions typified by <code>atoi</code>:
<ul type="square">
<li>
Conversion is supported in one direction only: from text to internal data type.
Converting the other way using the C library requires either the inconvenience
and compromised safety of the <code>sprintf</code> function, or the loss of
portability associated with non-standard functions such as <code>itoa</code>.
</li>
<li>
The range of types supported is only a subset of the built-in numeric types,
namely <code>int</code>, <code>long</code>, and <code>double</code>.
</li>
<li>
The range of types cannot be extended in a uniform manner. For instance,
conversion from string representation to <code>complex</code> or <code>rational</code>.
</li>
</ul>
The standard C functions typified by <code>strtol</code> have the same basic
limitations, but offer finer control over the conversion process. However, for
the common case such control is often either not required or not used. The <code>scanf</code>
family of functions offer even greater control, but also lack safety and ease
of use.
<p>
The standard C++ library offers <code>stringstream</code> for the kind of
in-core formatting being discussed. It offers a great deal of control over the
formatting and conversion of I/O to and from arbitrary types through text.
However, for simple conversions direct use of <code>stringstream</code> can be
either clumsy (with the introduction of extra local variables and the loss of
infix-expression convenience) or obscure (where <code>stringstream</code>
objects are created as temporary objects in an expression). Facets provide a
comprehensive concept and facility for controlling textual representation, but
their perceived complexity and high entry level requires an extreme degree of
involvement for simple conversions, and excludes all but a few programmers.
<p>
The <code>lexical_cast</code> function template offers a convenient and
consistent form for supporting common conversions to and from arbitrary types
when they are represented as text. The simplification it offers is in
expression-level convenience for such conversions. For more involved
conversions, such as where precision or formatting need tighter control than is
offered by the default behavior of <code>lexical_cast</code>, the conventional <code>
stringstream</code> approach is recommended. Where the conversions are
numeric to numeric, <code><a href="../numeric/conversion/doc/html/boost_numericconversion/improved_numeric_cast__.html">numeric_cast</a></code>
may offer more reasonable behavior than <code>lexical_cast</code>.
<p>
For a good discussion of the options and issues involved in string-based
formatting, including comparison of <code>stringstream</code>, <code>lexical_cast</code>,
and others, see Herb Sutter's article, <a href="http://www.gotw.ca/publications/mill19.htm">
<i>The String Formatters of Manor Farm</i></a>.
<p>
<hr>
<h2><a name="examples">Examples</a></h2>
The following example treats command line arguments as a sequence of numeric
data: <blockquote>
<pre>int main(int argc, char * argv[])
{
using boost::lexical_cast;
using boost::bad_lexical_cast;
std::vector&lt;short&gt; args;
while(*++argv)
{
try
{
args.push_back(lexical_cast&lt;short&gt;(*argv));
}
catch(bad_lexical_cast &amp;)
{
args.push_back(0);
}
}
...
}
</pre>
</blockquote>The following example uses numeric data in a string expression: <blockquote>
<pre>void log_message(const std::string &amp;);
void log_errno(int yoko)
{
log_message(&quot;Error &quot; + boost::lexical_cast&lt;std::string&gt;(yoko) + &quot;: &quot; + strerror(yoko));
}
</pre>
</blockquote>
<hr>
<h2><a name="synopsis">Synopsis</a></h2>
Library features defined in <a href="../../boost/lexical_cast.hpp"><code>&quot;boost/lexical_cast.hpp&quot;</code></a>:
<blockquote>
<pre>namespace boost
{
class <a href="#bad_lexical_cast">bad_lexical_cast</a>;
template&lt;typename Target, typename Source&gt;
Target <a href="#lexical_cast">lexical_cast</a>(const Source&amp; arg);
}
</pre>
</blockquote>Unit test defined in <a href="lexical_cast_test.cpp"><code>&quot;lexical_cast_test.cpp&quot;</code></a>.
<p>
<hr>
<h2><a name="lexical_cast"><code>lexical_cast</code></a></h2>
<blockquote>
<pre>template&lt;typename Target, typename Source&gt;
Target lexical_cast(const Source&amp; arg);
</pre>
</blockquote>Returns the result of streaming <code>arg</code> into a
standard library string-based stream and then out as a <code>Target</code> object.
Where <code>Target</code> is either <code>std::string</code>
or <code>std::wstring</code>, stream extraction takes the whole content
of the string, including spaces, rather than relying on the default
<code>operator&gt;&gt;</code> behavior.
If the conversion is unsuccessful, a <a href="#bad_lexical_cast">
<code>bad_lexical_cast</code></a> exception is thrown.
<p>
The requirements on the argument and result types are:
<ul type="square">
<li>
<code>Source</code> is <i>OutputStreamable</i>, meaning that an <code>operator&lt;&lt;</code>
is defined that takes a <code>std::ostream</code> or <code>std::wostream</code> object on the
left hand side and an instance of the argument type on the right.
</li>
<li>
<code>Target</code> is <i>InputStreamable</i>, meaning that an <code>operator&gt;&gt;</code>
is defined that takes a <code>std::istream</code> or <code>std::wistream</code> object on the left hand side
and an instance of the result type on the right.
</li>
<li>
<code>Target</code> is <i>CopyConstructible</i> [20.1.3].
</li>
<li>
<code>Target</code> is <i>DefaultConstructible</i>, meaning that it is possible
to <i>default-initialize</i> an object of that type [8.5, 20.1.4].
</li>
</ul>
The character type of the underlying stream is assumed to be <code>char</code> unless
either the <code>Source</code> or the <code>Target</code> requires wide-character
streaming, in which case the underlying stream uses <code>wchar_t</code>.
<code>Source</code> types that require wide-character streaming are <code>wchar_t</code>,
<code>wchar_t *</code>, and <code>std::wstring</code>. <code>Target</code> types that
require wide-character streaming are <code>wchar_t</code> and <code>std::wstring</code>.
<p>
Where a higher degree of control is required over conversions, <code>std::stringstream</code>
and <code>std::wstringstream</code> offer a more appropriate path. Where non-stream-based conversions are
required, <code>lexical_cast</code>
is the wrong tool for the job and is not special-cased for such scenarios.
<p>
<hr>
<h2><a name="bad_lexical_cast"><code>bad_lexical_cast</code></a></h2>
<blockquote>
<pre>class bad_lexical_cast : public std::bad_cast
{
public:
... // <i>same member function interface as</i> std::exception
};
</pre>
</blockquote>Exception used to indicate runtime <a href="#lexical_cast"><code>lexical_cast</code></a>
failure.
<hr>
<h2><a name="faq">Frequently Asked Questions</h2>
<p> Q: Why does <code>lexical_cast&lt;int8_t&gt;("127")</code> throw <code>bad_lexical_cast</code>?
<br> A: The type <code>int8_t</code> is a typedef to <code>char</code> or <code>signed char</code>.
Lexical conversion to these types is simply reading a byte from source but since the source has
more than one byte, the exception is thrown.
<p>Please use other integer types such as <code>int</code> or <code>short int</code>. If bounds checking
is important, you can also call <a href="../../libs/numeric/conversion/doc/html/boost_numericconversion/improved_numeric_cast__.html">numeric_cast</a>:
<pre><a href="../../libs/numeric/conversion/doc/html/boost_numericconversion/improved_numeric_cast__.html">numeric_cast</a>&lt;int8_t&gt;(lexical_cast&lt;int&gt;("127"));</pre>
<p> Q: What does <code>lexical_cast&lt;std::string&gt;</code> of an <code>int8_t</code> or <code>uint8_t</code> not do what I expect?
<br> A: As above, note that <code>int8_t</code> and <code>uint8_t</code> are actually chars and are formatted as such. To avoid this, cast to an integer type first:
<pre>lexical_cast&lt;std::string&gt;(static_cast&lt;int&gt;(n));</pre>
<p> Q: The implementation always resets the <code>ios_base::skipws</code> flag of an underlying stream object. It breaks my <code>operator&gt;&gt;</code> that works only in presence of this flag. Can you remove code that resets the flag?
<br> A: May be in a future version. There is no requirement in <a href="#n1973">[N1973]</a> to reset the flag but remember that <a href="#n1973">[N1973]</a> is not yet accepted by the committee. By the way, it's a great opportunity to make your <code>operator&gt;&gt;</code> conform to the standard. Read a good C++ book, study <code>std::sentry</code> and <a href="../../libs/io/doc/ios_state.html">ios_state_saver</a>.
</ul>
<h2><a name="references">References</h2>
<ul type="square">
<a name="n1973"></a><li> [N1973] Kevlin Henney, Beman Dawes, Lexical Conversion Library Proposal for TR2,
<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2006/n1973.html">N1973</a>.
<a name="tuning"></a><li> [Tuning] Alexander Nasonov, Fine Tuning for lexical_cast,
<a href="http://www.accu.org/var/uploads/journals/overload74.pdf">Overload #74</a>,
August 2006.</li>
</ul>
<h2><a name="changes">Changes</a></h2>
<h3>August, October 2006:</h3>
<ul type="square">
<li>Better performance for many combinations of <code>Source</code> and <code>Target</code>
types. Refer to <a href="#tuning">[Tuning]</a> for more details.
</li>
</ul>
<h3>June 2005:</h3>
<ul type="square">
<li>Call-by-const reference for the parameters. This requires partial specialization
of class templates, so it doesn't work for MSVC 6, and it uses the original
pass by value there.<br>
</li>
<li>The MSVC 6 support is deprecated, and will be removed in a future Boost
version. </li>
</ul>
<h3>Earlier:</h3>
<ul type="square">
<li>The previous version of <code>lexical_cast</code> used the default stream
precision for reading and writing floating-point numbers. For numerics that
have a corresponding specialization of <code>std::numeric_limits</code>, the
current version now chooses a precision to match. <br>
<li>The previous version of <code>lexical_cast</code> did not support conversion
to or from any wide-character-based types. For compilers with full language
and library support for wide characters, <code>lexical_cast</code> now supports
conversions from <code>wchar_t</code>, <code>wchar_t *</code>, and <code>std::wstring</code>
and to <code>wchar_t</code> and <code>std::wstring</code>. <br>
<li>The previous version of <code>lexical_cast</code> assumed that the conventional
stream extractor operators were sufficient for reading values. However, string
I/O is asymmetric, with the result that spaces play the role of I/O separators
rather than string content. The current version fixes this error for <code>std::string</code>
and, where supported, <code>std::wstring</code>: <code>lexical_cast&lt;std::string&gt;("Hello,
World")</code> succeeds instead of failing with a <code>bad_lexical_cast</code>
exception. <br>
<li>The previous version of <code>lexical_cast</code> allowed unsafe and meaningless
conversions to pointers. The current version now throws a <code>bad_lexical_cast</code>
for conversions to pointers: <code>lexical_cast&lt;char *&gt;("Goodbye, World")</code>
now throws an exception instead of causing undefined behavior.
</ul>
<p>
<hr>
<div align="right"><small><i>&copy; Copyright Kevlin Henney, 2000&#150;2005</i></small></div>
</body>
<head>
<meta http-equiv="refresh" content="0; URL=../../doc/html/boost_lexical_cast.html">
</head>
<body>
Automatic redirection failed, please go to
<a href="../../doc/html/boost_lexical_cast.html">../../doc/html/boost_lexical_cast.html</a>
</body>
</html>
+327 -46
View File
@@ -2,8 +2,9 @@
//
// See http://www.boost.org for most recent version, including documentation.
//
// Copyright Terje Slettebø and Kevlin Henney, 2005.
// Copyright Terje Sletteb and Kevlin Henney, 2005.
// Copyright Alexander Nasonov, 2006.
// Copyright Antony Polukhin, 2011.
//
// Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
@@ -11,6 +12,13 @@
//
// Note: The unit test no longer compile on MSVC 6, but lexical_cast itself works for it.
//
// We need this #define before any #includes: otherwise msvc will emit warnings
// deep within std::string, resulting from our (perfectly legal) use of basic_string
// with a custom traits class:
//
#define _SCL_SECURE_NO_WARNINGS
#include <boost/config.hpp>
#if defined(__INTEL_COMPILER)
@@ -21,23 +29,24 @@
#include <boost/lexical_cast.hpp>
#include <boost/cstdint.hpp>
#include <boost/test/unit_test.hpp>
#include <boost/test/floating_point_comparison.hpp>
#include <boost/type_traits/integral_promotion.hpp>
#include <string>
#include <vector>
#include <memory>
#if defined(BOOST_NO_STRINGSTREAM) || \
defined(BOOST_NO_STD_WSTRING) || \
defined(BOOST_NO_STD_LOCALE)
#define DISABLE_WIDE_CHAR_SUPPORT
#endif
#if (defined(BOOST_HAS_LONG_LONG) || defined(BOOST_HAS_MS_INT64)) \
&& !(defined(BOOST_MSVC) && BOOST_MSVC < 1300)
#define LCAST_TEST_LONGLONG
#endif
#if defined(BOOST_NO_STRINGSTREAM) || defined(BOOST_NO_STD_WSTRING)
#define BOOST_LCAST_NO_WCHAR_T
#endif
template<class CharT>
struct my_traits : std::char_traits<CharT>
{
@@ -61,6 +70,7 @@ void test_conversion_to_char();
void test_conversion_to_int();
void test_conversion_to_double();
void test_conversion_to_bool();
void test_conversion_with_nonconst_char();
void test_conversion_to_string();
void test_conversion_from_to_wchar_t_alias();
void test_conversion_to_pointer();
@@ -76,6 +86,8 @@ void test_conversion_from_to_int();
void test_conversion_from_to_uint();
void test_conversion_from_to_long();
void test_conversion_from_to_ulong();
void test_conversion_from_to_intmax_t();
void test_conversion_from_to_uintmax_t();
#ifdef LCAST_TEST_LONGLONG
void test_conversion_from_to_longlong();
void test_conversion_from_to_ulonglong();
@@ -86,6 +98,15 @@ void test_wtraits();
void test_allocator();
void test_wallocator();
#endif
void test_char_types_conversions();
void operators_overload_test();
#ifndef BOOST_NO_CHAR16_T
void test_char16_conversions();
#endif
#ifndef BOOST_NO_CHAR32_T
void test_char32_conversions();
#endif
unit_test::test_suite *init_unit_test_suite(int, char *[])
{
@@ -98,30 +119,42 @@ unit_test::test_suite *init_unit_test_suite(int, char *[])
suite->add(BOOST_TEST_CASE(test_conversion_from_to_wchar_t_alias));
suite->add(BOOST_TEST_CASE(test_conversion_to_pointer));
suite->add(BOOST_TEST_CASE(test_conversion_to_string));
#ifndef DISABLE_WIDE_CHAR_SUPPORT
suite->add(BOOST_TEST_CASE(test_conversion_with_nonconst_char));
#ifndef BOOST_LCAST_NO_WCHAR_T
suite->add(BOOST_TEST_CASE(test_conversion_from_wchar_t));
suite->add(BOOST_TEST_CASE(test_conversion_to_wchar_t));
suite->add(BOOST_TEST_CASE(test_conversion_from_wstring));
suite->add(BOOST_TEST_CASE(test_conversion_to_wstring));
#endif
#endif
suite->add(BOOST_TEST_CASE(test_bad_lexical_cast));
suite->add(BOOST_TEST_CASE(test_no_whitespace_stripping));
suite->add(BOOST_TEST_CASE(&test_conversion_from_to_short));
suite->add(BOOST_TEST_CASE(&test_conversion_from_to_ushort));
suite->add(BOOST_TEST_CASE(&test_conversion_from_to_int));
suite->add(BOOST_TEST_CASE(&test_conversion_from_to_uint));
suite->add(BOOST_TEST_CASE(&test_conversion_from_to_ulong));
suite->add(BOOST_TEST_CASE(&test_conversion_from_to_long));
#ifdef LCAST_TEST_LONGLONG
suite->add(BOOST_TEST_CASE(&test_conversion_from_to_ulong));
suite->add(BOOST_TEST_CASE(&test_conversion_from_to_intmax_t));
suite->add(BOOST_TEST_CASE(&test_conversion_from_to_uintmax_t));
#ifdef LCAST_TEST_LONGLONG
suite->add(BOOST_TEST_CASE(&test_conversion_from_to_longlong));
suite->add(BOOST_TEST_CASE(&test_conversion_from_to_ulonglong));
#endif
#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
#endif
#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
suite->add(BOOST_TEST_CASE(&test_traits));
suite->add(BOOST_TEST_CASE(&test_wtraits));
suite->add(BOOST_TEST_CASE(&test_allocator));
suite->add(BOOST_TEST_CASE(&test_wallocator));
#endif
#endif
suite->add(BOOST_TEST_CASE(&test_char_types_conversions));
suite->add(BOOST_TEST_CASE(&operators_overload_test));
#ifndef BOOST_NO_CHAR16_T
suite->add(BOOST_TEST_CASE(&test_char16_conversions));
#endif
#ifndef BOOST_NO_CHAR32_T
suite->add(BOOST_TEST_CASE(&test_char32_conversions));
#endif
return suite;
}
@@ -184,19 +217,45 @@ void test_conversion_to_int()
lexical_cast<int>(std::string("Test")), bad_lexical_cast);
}
void test_conversion_with_nonconst_char()
{
std::vector<char> buffer;
buffer.push_back('1');
buffer.push_back('\0');
BOOST_CHECK_EQUAL(boost::lexical_cast<int>(&buffer[0]), 1);
std::vector<unsigned char> buffer2;
buffer2.push_back('1');
buffer2.push_back('\0');
BOOST_CHECK_EQUAL(boost::lexical_cast<int>(&buffer2[0]), 1);
std::vector<unsigned char> buffer3;
buffer3.push_back('1');
buffer3.push_back('\0');
BOOST_CHECK_EQUAL(boost::lexical_cast<int>(&buffer3[0]), 1);
#ifndef BOOST_LCAST_NO_WCHAR_T
std::vector<wchar_t> buffer4;
buffer4.push_back(L'1');
buffer4.push_back(L'\0');
BOOST_CHECK_EQUAL(boost::lexical_cast<int>(&buffer4[0]), 1);
#endif
}
void test_conversion_to_double()
{
BOOST_CHECK_CLOSE(1.0, lexical_cast<double>('1'), (std::numeric_limits<double>::epsilon()));
BOOST_CHECK_CLOSE_FRACTION(1.0, lexical_cast<double>('1'), (std::numeric_limits<double>::epsilon()));
BOOST_CHECK_THROW(lexical_cast<double>('A'), bad_lexical_cast);
BOOST_CHECK_CLOSE(1.0, lexical_cast<double>(1), (std::numeric_limits<double>::epsilon()));
BOOST_CHECK_CLOSE(1.23, lexical_cast<double>(1.23), (std::numeric_limits<double>::epsilon()));
BOOST_CHECK_CLOSE(1.234567890, 1.234567890, std::numeric_limits<double>::epsilon());
BOOST_CHECK_CLOSE(1.0, lexical_cast<double>(true), (std::numeric_limits<double>::epsilon()));
BOOST_CHECK_CLOSE(0.0, lexical_cast<double>(false), (std::numeric_limits<double>::epsilon()));
BOOST_CHECK_CLOSE(1.23, lexical_cast<double>("1.23"), (std::numeric_limits<double>::epsilon()));
BOOST_CHECK_CLOSE_FRACTION(1.0, lexical_cast<double>(1), (std::numeric_limits<double>::epsilon()));
BOOST_CHECK_CLOSE_FRACTION(1.23, lexical_cast<double>(1.23), (std::numeric_limits<double>::epsilon()));
BOOST_CHECK_CLOSE_FRACTION(1.234567890, lexical_cast<double>(1.234567890), std::numeric_limits<double>::epsilon());
BOOST_CHECK_CLOSE_FRACTION(1.234567890, lexical_cast<double>("1.234567890"), std::numeric_limits<double>::epsilon());
BOOST_CHECK_CLOSE_FRACTION(1.0, lexical_cast<double>(true), (std::numeric_limits<double>::epsilon()));
BOOST_CHECK_CLOSE_FRACTION(0.0, lexical_cast<double>(false), (std::numeric_limits<double>::epsilon()));
BOOST_CHECK_CLOSE_FRACTION(1.23, lexical_cast<double>("1.23"), (std::numeric_limits<double>::epsilon()));
BOOST_CHECK_THROW(lexical_cast<double>(""), bad_lexical_cast);
BOOST_CHECK_THROW(lexical_cast<double>("Test"), bad_lexical_cast);
BOOST_CHECK_CLOSE(1.23, lexical_cast<double>(std::string("1.23")), (std::numeric_limits<double>::epsilon()));
BOOST_CHECK_CLOSE_FRACTION(1.23, lexical_cast<double>(std::string("1.23")), (std::numeric_limits<double>::epsilon()));
BOOST_CHECK_THROW(
lexical_cast<double>(std::string("")), bad_lexical_cast);
BOOST_CHECK_THROW(
@@ -223,10 +282,24 @@ void test_conversion_to_bool()
BOOST_CHECK_EQUAL(false, lexical_cast<bool>("0"));
BOOST_CHECK_EQUAL(true, lexical_cast<bool>(std::string("1")));
BOOST_CHECK_EQUAL(false, lexical_cast<bool>(std::string("0")));
BOOST_CHECK_THROW(lexical_cast<bool>(1.0001L), bad_lexical_cast);
BOOST_CHECK_THROW(lexical_cast<bool>(2), bad_lexical_cast);
BOOST_CHECK_THROW(lexical_cast<bool>(2u), bad_lexical_cast);
BOOST_CHECK_THROW(lexical_cast<bool>(-1), bad_lexical_cast);
BOOST_CHECK_THROW(lexical_cast<bool>(-2), bad_lexical_cast);
BOOST_CHECK_THROW(
lexical_cast<bool>(std::string("")), bad_lexical_cast);
BOOST_CHECK_THROW(
lexical_cast<bool>(std::string("Test")), bad_lexical_cast);
BOOST_CHECK(lexical_cast<bool>("+1") == true );
BOOST_CHECK(lexical_cast<bool>("+0") == false );
BOOST_CHECK(lexical_cast<bool>("-0") == false );
BOOST_CHECK_THROW(lexical_cast<bool>("--0"), bad_lexical_cast);
BOOST_CHECK_THROW(lexical_cast<bool>("-+-0"), bad_lexical_cast);
}
void test_conversion_to_string()
@@ -263,14 +336,14 @@ void test_conversion_from_to_wchar_t_alias()
void test_conversion_to_pointer()
{
BOOST_CHECK_THROW(lexical_cast<char *>("Test"), bad_lexical_cast);
#ifndef DISABLE_WIDE_CHAR_SUPPORT
#ifndef BOOST_LCAST_NO_WCHAR_T
BOOST_CHECK_THROW(lexical_cast<wchar_t *>("Test"), bad_lexical_cast);
#endif
#endif
}
void test_conversion_from_wchar_t()
{
#ifndef DISABLE_WIDE_CHAR_SUPPORT
#ifndef BOOST_LCAST_NO_WCHAR_T
#if !defined(BOOST_NO_INTRINSIC_WCHAR_T)
BOOST_CHECK_EQUAL(1, lexical_cast<int>(L'1'));
BOOST_CHECK_THROW(lexical_cast<int>(L'A'), bad_lexical_cast);
@@ -303,7 +376,7 @@ void test_conversion_from_wchar_t()
void test_conversion_to_wchar_t()
{
#if !defined(DISABLE_WIDE_CHAR_SUPPORT) && !defined(BOOST_NO_INTRINSIC_WCHAR_T)
#if !defined(BOOST_LCAST_NO_WCHAR_T) && !defined(BOOST_NO_INTRINSIC_WCHAR_T)
BOOST_CHECK_EQUAL(L'1', lexical_cast<wchar_t>(1));
BOOST_CHECK_EQUAL(L'0', lexical_cast<wchar_t>(0));
BOOST_CHECK_EQUAL(L'1', lexical_cast<wchar_t>('1'));
@@ -325,12 +398,12 @@ void test_conversion_to_wchar_t()
lexical_cast<wchar_t>(std::wstring(L"")), bad_lexical_cast);
BOOST_CHECK_THROW(
lexical_cast<wchar_t>(std::wstring(L"Test")), bad_lexical_cast);
#endif
#endif
}
void test_conversion_from_wstring()
{
#ifndef DISABLE_WIDE_CHAR_SUPPORT
#ifndef BOOST_LCAST_NO_WCHAR_T
BOOST_CHECK_EQUAL(123, lexical_cast<int>(std::wstring(L"123")));
BOOST_CHECK_THROW(
lexical_cast<int>(std::wstring(L"")), bad_lexical_cast);
@@ -343,12 +416,12 @@ void test_conversion_from_wstring()
lexical_cast<bool>(std::wstring(L"")), bad_lexical_cast);
BOOST_CHECK_THROW(
lexical_cast<bool>(std::wstring(L"Test")), bad_lexical_cast);
#endif
#endif
}
void test_conversion_to_wstring()
{
#ifndef DISABLE_WIDE_CHAR_SUPPORT
#ifndef BOOST_LCAST_NO_WCHAR_T
wchar_t buf[] = L"hello";
wchar_t* str = buf;
BOOST_CHECK(str == lexical_cast<std::wstring>(str));
@@ -368,7 +441,7 @@ void test_conversion_to_wstring()
BOOST_CHECK(L"Test" == lexical_cast<std::wstring>(std::wstring(L"Test")));
BOOST_CHECK(L" " == lexical_cast<std::wstring>(std::wstring(L" ")));
BOOST_CHECK(L"" == lexical_cast<std::wstring>(std::wstring(L"")));
#endif
#endif
}
void test_bad_lexical_cast()
@@ -441,6 +514,24 @@ void test_conversion_from_integral_to_char(CharT zero)
BOOST_CHECK_THROW(lexical_cast<CharT>(t), bad_lexical_cast);
}
template<class T, class CharT>
void test_conversion_from_char_to_integral(CharT zero)
{
BOOST_CHECK(lexical_cast<T>( static_cast<CharT>(zero + 0)) == static_cast<T>(0) );
BOOST_CHECK(lexical_cast<T>( static_cast<CharT>(zero + 1)) == static_cast<T>(1) );
BOOST_CHECK(lexical_cast<T>( static_cast<CharT>(zero + 2)) == static_cast<T>(2) );
BOOST_CHECK(lexical_cast<T>( static_cast<CharT>(zero + 3)) == static_cast<T>(3) );
BOOST_CHECK(lexical_cast<T>( static_cast<CharT>(zero + 4)) == static_cast<T>(4) );
BOOST_CHECK(lexical_cast<T>( static_cast<CharT>(zero + 5)) == static_cast<T>(5) );
BOOST_CHECK(lexical_cast<T>( static_cast<CharT>(zero + 6)) == static_cast<T>(6) );
BOOST_CHECK(lexical_cast<T>( static_cast<CharT>(zero + 7)) == static_cast<T>(7) );
BOOST_CHECK(lexical_cast<T>( static_cast<CharT>(zero + 8)) == static_cast<T>(8) );
BOOST_CHECK(lexical_cast<T>( static_cast<CharT>(zero + 9)) == static_cast<T>(9) );
BOOST_CHECK_THROW(lexical_cast<T>( static_cast<CharT>(zero + 10)), bad_lexical_cast);
BOOST_CHECK_THROW(lexical_cast<T>( static_cast<CharT>(zero - 1)), bad_lexical_cast);
}
template<class T>
void test_conversion_from_integral_to_integral()
{
@@ -504,7 +595,7 @@ void test_conversion_from_integral_to_string(CharT)
// Test values around zero:
if(limits::is_signed)
for(t = -counter; t < static_cast<T>(counter); ++t)
for(t = static_cast<T>(-counter); t < static_cast<T>(counter); ++t)
BOOST_CHECK(lexical_cast<string_type>(t) == to_str<CharT>(t));
// Test values around 100, 1000, 10000, ...
@@ -522,27 +613,71 @@ template<class T, class CharT>
void test_conversion_from_string_to_integral(CharT)
{
typedef std::numeric_limits<T> limits;
typedef std::basic_string<CharT> string_type;
T t;
string_type s;
string_type const zero = to_str<CharT>(0);
string_type const nine = to_str<CharT>(9);
T const min_val = (limits::min)();
T const max_val = (limits::max)();
t = (limits::min)();
BOOST_CHECK(lexical_cast<T>(to_str<CharT>(t)) == t);
s = to_str<CharT>(min_val);
BOOST_CHECK_EQUAL(lexical_cast<T>(s), min_val);
if(limits::is_signed)
{
BOOST_CHECK_THROW(lexical_cast<T>(s + zero), bad_lexical_cast);
BOOST_CHECK_THROW(lexical_cast<T>(s + nine), bad_lexical_cast);
}
t = (limits::max)();
BOOST_CHECK(lexical_cast<T>(to_str<CharT>(t)) == t);
s = to_str<CharT>(max_val);
BOOST_CHECK_EQUAL(lexical_cast<T>(s), max_val);
{
BOOST_CHECK_THROW(lexical_cast<T>(s + zero), bad_lexical_cast);
BOOST_CHECK_THROW(lexical_cast<T>(s + nine), bad_lexical_cast);
s = to_str<CharT>(max_val);
for (int i =1; i <=10; ++i) {
s[s.size()-1] += 1;
BOOST_CHECK_THROW(lexical_cast<T>( s ), bad_lexical_cast);
}
s = to_str<CharT>(max_val);
std::locale loc;
typedef std::numpunct<char> numpunct;
if ( BOOST_USE_FACET(numpunct, loc).grouping().empty() ) {
// Following tests work well for locale C
BOOST_CHECK_EQUAL(lexical_cast<T>(to_str<CharT>(0)+s), max_val);
BOOST_CHECK_EQUAL(lexical_cast<T>(to_str<CharT>(0)+to_str<CharT>(0)+s), max_val);
BOOST_CHECK_EQUAL(lexical_cast<T>(to_str<CharT>(0)+to_str<CharT>(0)+to_str<CharT>(0)+s), max_val);
}
for (int i =1; i <=256; ++i) {
BOOST_CHECK_THROW(lexical_cast<T>( to_str<CharT>(i)+s ), bad_lexical_cast);
}
typedef BOOST_DEDUCED_TYPENAME boost::integral_promotion<T>::type promoted;
if ( !(boost::is_same<T, promoted>::value) )
{
promoted prom = max_val;
s = to_str<CharT>(max_val);
for (int i =1; i <=256; ++i) {
BOOST_CHECK_THROW(lexical_cast<T>( to_str<CharT>(prom+i) ), bad_lexical_cast);
BOOST_CHECK_THROW(lexical_cast<T>( to_str<CharT>(i)+s ), bad_lexical_cast);
}
}
}
if(limits::digits <= 16 && lcast_test_small_integral_types_completely)
// min and max have already been tested.
for(t = 1 + (limits::min)(); t != (limits::max)(); ++t)
for(T t = 1 + min_val; t != max_val; ++t)
BOOST_CHECK(lexical_cast<T>(to_str<CharT>(t)) == t);
else
{
T const min_val = (limits::min)();
T const max_val = (limits::max)();
T const half_max_val = max_val / 2;
T const cnt = lcast_integral_test_counter; // to supress warnings
unsigned int const counter = cnt < half_max_val ? cnt : half_max_val;
T t;
unsigned int i;
// Test values around min:
@@ -557,7 +692,7 @@ void test_conversion_from_string_to_integral(CharT)
// Test values around zero:
if(limits::is_signed)
for(t = -counter; t < static_cast<T>(counter); ++t)
for(t = static_cast<T>(-counter); t < static_cast<T>(counter); ++t)
BOOST_CHECK(lexical_cast<T>(to_str<CharT>(t)) == t);
// Test values around 100, 1000, 10000, ...
@@ -574,10 +709,25 @@ void test_conversion_from_string_to_integral(CharT)
template<class T>
void test_conversion_from_to_integral_for_locale()
{
std::locale current_locale;
typedef std::numpunct<char> numpunct;
numpunct const& np = BOOST_USE_FACET(numpunct, current_locale);
if ( !np.grouping().empty() )
{
BOOST_CHECK_THROW(
lexical_cast<T>( std::string("100") + np.thousands_sep() + np.thousands_sep() + "0" )
, bad_lexical_cast);
BOOST_CHECK_THROW(lexical_cast<T>( std::string("100") + np.thousands_sep() ), bad_lexical_cast);
BOOST_CHECK_THROW(lexical_cast<T>( np.thousands_sep() + std::string("100") ), bad_lexical_cast);
// Exception must not be thrown, when we are using no separators at all
BOOST_CHECK( lexical_cast<T>("30000") == static_cast<T>(30000) );
}
test_conversion_from_integral_to_integral<T>();
test_conversion_from_integral_to_string<T>('0');
test_conversion_from_string_to_integral<T>('0');
#if !defined(DISABLE_WIDE_CHAR_SUPPORT) && !defined(BOOST_NO_INTRINSIC_WCHAR_T)
#if !defined(BOOST_LCAST_NO_WCHAR_T)
test_conversion_from_integral_to_string<T>(L'0');
test_conversion_from_string_to_integral<T>(L'0');
#endif
@@ -596,13 +746,54 @@ void test_conversion_from_to_integral()
signed char const szero = '0';
unsigned char const uzero = '0';
test_conversion_from_integral_to_char<T>(zero);
test_conversion_from_char_to_integral<T>(zero);
test_conversion_from_integral_to_char<T>(szero);
test_conversion_from_char_to_integral<T>(szero);
test_conversion_from_integral_to_char<T>(uzero);
#if !defined(DISABLE_WIDE_CHAR_SUPPORT) && !defined(BOOST_NO_INTRINSIC_WCHAR_T)
test_conversion_from_char_to_integral<T>(uzero);
#if !defined(BOOST_LCAST_NO_WCHAR_T) && !defined(BOOST_NO_INTRINSIC_WCHAR_T)
wchar_t const wzero = L'0';
test_conversion_from_integral_to_char<T>(wzero);
test_conversion_from_char_to_integral<T>(wzero);
#endif
#ifndef BOOST_NO_CHAR16_T
char16_t const u16zero = u'0';
test_conversion_from_integral_to_char<T>(u16zero);
test_conversion_from_char_to_integral<T>(u16zero);
#endif
#ifndef BOOST_NO_CHAR32_T
char32_t const u32zero = u'0';
test_conversion_from_integral_to_char<T>(u32zero);
test_conversion_from_char_to_integral<T>(u32zero);
#endif
BOOST_CHECK(lexical_cast<T>("-1") == static_cast<T>(-1));
BOOST_CHECK(lexical_cast<T>("-9") == static_cast<T>(-9));
BOOST_CHECK(lexical_cast<T>(-1) == static_cast<T>(-1));
BOOST_CHECK(lexical_cast<T>(-9) == static_cast<T>(-9));
BOOST_CHECK_THROW(lexical_cast<T>("-1.0"), bad_lexical_cast);
BOOST_CHECK_THROW(lexical_cast<T>("-9.0"), bad_lexical_cast);
BOOST_CHECK(lexical_cast<T>(-1.0) == static_cast<T>(-1));
BOOST_CHECK(lexical_cast<T>(-9.0) == static_cast<T>(-9));
BOOST_CHECK(lexical_cast<T>(static_cast<T>(1)) == static_cast<T>(1));
BOOST_CHECK(lexical_cast<T>(static_cast<T>(9)) == static_cast<T>(9));
BOOST_CHECK_THROW(lexical_cast<T>(1.1f), bad_lexical_cast);
BOOST_CHECK_THROW(lexical_cast<T>(1.1), bad_lexical_cast);
BOOST_CHECK_THROW(lexical_cast<T>(1.1L), bad_lexical_cast);
BOOST_CHECK_THROW(lexical_cast<T>(1.0001f), bad_lexical_cast);
BOOST_CHECK_THROW(lexical_cast<T>(1.0001), bad_lexical_cast);
BOOST_CHECK_THROW(lexical_cast<T>(1.0001L), bad_lexical_cast);
BOOST_CHECK(lexical_cast<T>("+1") == static_cast<T>(1) );
BOOST_CHECK(lexical_cast<T>("+9") == static_cast<T>(9) );
BOOST_CHECK(lexical_cast<T>("+10") == static_cast<T>(10) );
BOOST_CHECK(lexical_cast<T>("+90") == static_cast<T>(90) );
BOOST_CHECK_THROW(lexical_cast<T>("++1"), bad_lexical_cast);
BOOST_CHECK_THROW(lexical_cast<T>("-+9"), bad_lexical_cast);
BOOST_CHECK_THROW(lexical_cast<T>("--1"), bad_lexical_cast);
BOOST_CHECK_THROW(lexical_cast<T>("+-9"), bad_lexical_cast);
// test_conversion_from_to_integral_for_locale
typedef std::numpunct<char> numpunct;
@@ -656,14 +847,24 @@ void test_conversion_from_to_uint()
test_conversion_from_to_integral<unsigned int>();
}
void test_conversion_from_to_long()
{
test_conversion_from_to_integral<long>();
}
void test_conversion_from_to_ulong()
{
test_conversion_from_to_integral<unsigned long>();
}
void test_conversion_from_to_long()
void test_conversion_from_to_intmax_t()
{
test_conversion_from_to_integral<long>();
test_conversion_from_to_integral<boost::intmax_t>();
}
void test_conversion_from_to_uintmax_t()
{
test_conversion_from_to_integral<boost::uintmax_t>();
}
#if defined(BOOST_HAS_LONG_LONG)
@@ -678,7 +879,7 @@ void test_conversion_from_to_ulonglong()
test_conversion_from_to_integral<boost::ulong_long_type>();
}
#elif defined(LCAST_TEST_LONGLONG)
#elif defined(BOOST_HAS_MS_INT64)
void test_conversion_from_to_longlong()
{
@@ -749,3 +950,83 @@ void test_wallocator()
#endif
void test_char_types_conversions()
{
const char c_arr[] = "Test array of chars";
const unsigned char uc_arr[] = "Test array of chars";
const signed char sc_arr[] = "Test array of chars";
BOOST_CHECK(boost::lexical_cast<std::string>(c_arr) == std::string(c_arr));
BOOST_CHECK(boost::lexical_cast<std::string>(uc_arr) == std::string(c_arr));
BOOST_CHECK(boost::lexical_cast<std::string>(sc_arr) == std::string(c_arr));
BOOST_CHECK(boost::lexical_cast<char>(c_arr[0]) == c_arr[0]);
BOOST_CHECK(boost::lexical_cast<char>(uc_arr[0]) == c_arr[0]);
BOOST_CHECK(boost::lexical_cast<char>(sc_arr[0]) == c_arr[0]);
BOOST_CHECK(boost::lexical_cast<unsigned char>(c_arr[0]) == uc_arr[0]);
BOOST_CHECK(boost::lexical_cast<unsigned char>(uc_arr[0]) == uc_arr[0]);
BOOST_CHECK(boost::lexical_cast<unsigned char>(sc_arr[0]) == uc_arr[0]);
BOOST_CHECK(boost::lexical_cast<signed char>(c_arr[0]) == sc_arr[0]);
BOOST_CHECK(boost::lexical_cast<signed char>(uc_arr[0]) == sc_arr[0]);
BOOST_CHECK(boost::lexical_cast<signed char>(sc_arr[0]) == sc_arr[0]);
#ifndef BOOST_LCAST_NO_WCHAR_T
const wchar_t wc_arr[]=L"Test array of chars";
BOOST_CHECK(boost::lexical_cast<std::wstring>(wc_arr) == std::wstring(wc_arr));
BOOST_CHECK(boost::lexical_cast<wchar_t>(wc_arr[0]) == wc_arr[0]);
#endif
}
struct foo_operators_test
{
foo_operators_test() : f(2) {}
int f;
};
template <typename OStream>
OStream& operator<<(OStream& ostr, const foo_operators_test& foo)
{
ostr << foo.f;
return ostr;
}
template <typename IStream>
IStream& operator>>(IStream& istr, foo_operators_test& foo)
{
istr >> foo.f;
return istr;
}
void operators_overload_test()
{
foo_operators_test foo;
BOOST_CHECK_EQUAL(boost::lexical_cast<std::string>(foo), "2");
BOOST_CHECK_EQUAL((boost::lexical_cast<foo_operators_test>("2")).f, 2);
// Must compile
(void)boost::lexical_cast<foo_operators_test>(foo);
}
#ifndef BOOST_NO_CHAR16_T
void test_char16_conversions()
{
BOOST_CHECK(u"100" == lexical_cast<std::u16string>(u"100"));
BOOST_CHECK(u"1" == lexical_cast<std::u16string>(u'1'));
}
#endif
#ifndef BOOST_NO_CHAR32_T
void test_char32_conversions()
{
BOOST_CHECK(U"100" == lexical_cast<std::u32string>(U"100"));
BOOST_CHECK(U"1" == lexical_cast<std::u32string>(U'1'));
}
#endif
-20
View File
@@ -1,20 +0,0 @@
#
# Copyright Troy D. Straszheim
#
# Distributed under the Boost Software License, Version 1.0.
# See http://www.boost.org/LICENSE_1_0.txt
#
boost_additional_test_dependencies(conversion BOOST_DEPENDS test detail numeric)
boost_test_run(implicit_cast)
boost_test_compile_fail(implicit_cast_fail)
boost_test_run(cast_test ../cast_test.cpp)
boost_test_run(numeric_cast_test ../numeric_cast_test.cpp)
boost_test_run(
lexical_cast_test
../lexical_cast_test.cpp
DEPENDS boost_unit_test_framework
)
+5
View File
@@ -24,6 +24,11 @@ test-suite conversion
[ run lexical_cast_loopback_test.cpp ../../test/build//boost_unit_test_framework/<link>static ]
[ run lexical_cast_abstract_test.cpp ../../test/build//boost_unit_test_framework/<link>static ]
[ run lexical_cast_noncopyable_test.cpp ../../test/build//boost_unit_test_framework/<link>static ]
[ run lexical_cast_vc8_bug_test.cpp ../../test/build//boost_unit_test_framework/<link>static ]
[ run lexical_cast_wchars_test.cpp ../../test/build//boost_unit_test_framework/<link>static ]
[ run lexical_cast_float_types_test.cpp ../../test/build//boost_unit_test_framework/<link>static ]
[ run lexical_cast_inf_nan_test.cpp ../../test/build//boost_unit_test_framework/<link>static ]
[ run lexical_cast_empty_input_test.cpp ../../test/build//boost_unit_test_framework/<link>static ]
;
+1 -1
View File
@@ -51,7 +51,7 @@ std::ostream &operator<<(std::ostream &O, const A &a)
{
a.out(O);
return O;
};
}
void test_abstract()
{
+58
View File
@@ -0,0 +1,58 @@
// Unit test for boost::lexical_cast.
//
// See http://www.boost.org for most recent version, including documentation.
//
// Copyright Antony Polukhin, 2011.
//
// Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt).
#include <boost/config.hpp>
#if defined(__INTEL_COMPILER)
#pragma warning(disable: 193 383 488 981 1418 1419)
#elif defined(BOOST_MSVC)
#pragma warning(disable: 4097 4100 4121 4127 4146 4244 4245 4511 4512 4701 4800)
#endif
#include <boost/lexical_cast.hpp>
#include <boost/test/unit_test.hpp>
#include <boost/range/iterator_range.hpp>
using namespace boost;
void test_empty_iterator_range()
{
boost::iterator_range<const char*> v;
BOOST_CHECK_THROW(lexical_cast<int>(v), bad_lexical_cast);
BOOST_CHECK_THROW(lexical_cast<float>(v), bad_lexical_cast);
BOOST_CHECK_THROW(lexical_cast<double>(v), bad_lexical_cast);
BOOST_CHECK_THROW(lexical_cast<long double>(v), bad_lexical_cast);
BOOST_CHECK_THROW(lexical_cast<unsigned int>(v), bad_lexical_cast);
BOOST_CHECK_THROW(lexical_cast<std::string>(v), bad_lexical_cast);
BOOST_CHECK_THROW(lexical_cast<unsigned short>(v), bad_lexical_cast);
BOOST_CHECK_THROW(lexical_cast<char>(v), bad_lexical_cast);
}
void test_empty_string()
{
BOOST_CHECK_THROW(lexical_cast<int>(std::string()), bad_lexical_cast);
BOOST_CHECK_THROW(lexical_cast<float>(std::string()), bad_lexical_cast);
BOOST_CHECK_THROW(lexical_cast<double>(std::string()), bad_lexical_cast);
BOOST_CHECK_THROW(lexical_cast<long double>(std::string()), bad_lexical_cast);
BOOST_CHECK_THROW(lexical_cast<unsigned int>(std::string()), bad_lexical_cast);
BOOST_CHECK_EQUAL(lexical_cast<std::string>(std::string()), std::string());
BOOST_CHECK_THROW(lexical_cast<unsigned short>(std::string()), bad_lexical_cast);
BOOST_CHECK_THROW(lexical_cast<char>(std::string()), bad_lexical_cast);
}
unit_test::test_suite *init_unit_test_suite(int, char *[])
{
unit_test_framework::test_suite *suite =
BOOST_TEST_SUITE("lexical_cast. Empty input unit test");
suite->add(BOOST_TEST_CASE(&test_empty_iterator_range));
suite->add(BOOST_TEST_CASE(&test_empty_string));
return suite;
}
+513
View File
@@ -0,0 +1,513 @@
// Unit test for boost::lexical_cast.
//
// See http://www.boost.org for most recent version, including documentation.
//
// Copyright Antony Polukhin, 2011.
//
// Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt).
#include <boost/config.hpp>
#if defined(__INTEL_COMPILER)
#pragma warning(disable: 193 383 488 981 1418 1419)
#elif defined(BOOST_MSVC)
#pragma warning(disable: 4097 4100 4121 4127 4146 4244 4245 4511 4512 4701 4800)
#endif
#include <boost/lexical_cast.hpp>
#include <boost/cstdint.hpp>
#include <boost/test/unit_test.hpp>
#include <boost/test/floating_point_comparison.hpp>
void test_conversion_from_to_float();
void test_conversion_from_to_double();
void test_conversion_from_to_long_double();
using namespace boost;
unit_test::test_suite *init_unit_test_suite(int, char *[])
{
unit_test_framework::test_suite *suite =
BOOST_TEST_SUITE("lexical_cast float types unit test");
suite->add(BOOST_TEST_CASE(&test_conversion_from_to_float));
suite->add(BOOST_TEST_CASE(&test_conversion_from_to_double));
suite->add(BOOST_TEST_CASE(&test_conversion_from_to_long_double));
return suite;
}
// Replace "-,999" with "-999".
template<class CharT>
std::basic_string<CharT> to_str_gcc_workaround(std::basic_string<CharT> str)
{
std::locale loc;
std::numpunct<CharT> const& np = BOOST_USE_FACET(std::numpunct<CharT>, loc);
std::ctype<CharT> const& ct = BOOST_USE_FACET(std::ctype<CharT>, loc);
if(np.grouping().empty())
return str;
CharT prefix[3] = { ct.widen('-'), np.thousands_sep(), CharT() };
if(str.find(prefix) != 0)
return str;
prefix[1] = CharT();
str.replace(0, 2, prefix);
return str;
}
template<class CharT, class T>
std::basic_string<CharT> to_str(T t)
{
std::basic_ostringstream<CharT> o;
o << t;
return to_str_gcc_workaround(o.str());
}
template<class T>
void test_conversion_from_to_float_for_locale()
{
std::locale current_locale;
typedef std::numpunct<char> numpunct;
numpunct const& np = BOOST_USE_FACET(numpunct, current_locale);
if ( !np.grouping().empty() )
{
BOOST_CHECK_THROW(
lexical_cast<T>( std::string("100") + np.thousands_sep() + np.thousands_sep() + "0" )
, bad_lexical_cast);
BOOST_CHECK_THROW(lexical_cast<T>( std::string("100") + np.thousands_sep() ), bad_lexical_cast);
BOOST_CHECK_THROW(lexical_cast<T>( np.thousands_sep() + std::string("100") ), bad_lexical_cast);
BOOST_CHECK_THROW(lexical_cast<T>( std::string("1") + np.thousands_sep() + np.decimal_point() + "e10" ), bad_lexical_cast);
BOOST_CHECK_THROW(lexical_cast<T>( std::string("1e10") + np.thousands_sep() ), bad_lexical_cast);
BOOST_CHECK_THROW(lexical_cast<T>( std::string("1") + np.thousands_sep() + "e10" ), bad_lexical_cast);
BOOST_CHECK_CLOSE_FRACTION(lexical_cast<T>( to_str< char >(100000) ), 100000, (std::numeric_limits<T>::epsilon()) );
BOOST_CHECK_CLOSE_FRACTION(lexical_cast<T>( to_str< char >(10000000u) ), 10000000u, (std::numeric_limits<T>::epsilon()) );
BOOST_CHECK_CLOSE_FRACTION(lexical_cast<T>( to_str< char >(100) ), 100, (std::numeric_limits<T>::epsilon()) );
#if !defined(BOOST_LCAST_NO_WCHAR_T) && !defined(BOOST_NO_INTRINSIC_WCHAR_T)
BOOST_CHECK_CLOSE_FRACTION(lexical_cast<T>( to_str< wchar_t >(100000) ), 100000, (std::numeric_limits<T>::epsilon()) );
BOOST_CHECK_CLOSE_FRACTION(lexical_cast<T>( to_str< wchar_t >(10000000u) ), 10000000u, (std::numeric_limits<T>::epsilon()) );
BOOST_CHECK_CLOSE_FRACTION(lexical_cast<T>( to_str< wchar_t >(100) ), 100, (std::numeric_limits<T>::epsilon()) );
#endif
// Exception must not be thrown, when we are using no separators at all
BOOST_CHECK_CLOSE_FRACTION( lexical_cast<T>("30000"), static_cast<T>(30000), (std::numeric_limits<T>::epsilon()) );
}
}
/*
* Converts char* [and wchar_t] to float number type and checks, that generated
* number is in interval [base_value-epsilon, base_value+epsilon].
*/
#ifndef BOOST_LCAST_NO_WCHAR_T
#define CHECK_CLOSE_ABS_DIFF(VAL,PREFIX) \
converted_val = lexical_cast<test_t>(#VAL); \
BOOST_CHECK_CLOSE_FRACTION( (VAL ## L? VAL ## L : std::numeric_limits<test_t>::epsilon()), \
(converted_val ? converted_val : std::numeric_limits<test_t>::epsilon()), \
std::numeric_limits<test_t>::epsilon() \
); \
BOOST_CHECK_EQUAL(converted_val, lexical_cast<test_t>(L## #VAL) );
#else
#define CHECK_CLOSE_ABS_DIFF(VAL,TYPE) \
converted_val = lexical_cast<test_t>(#VAL); \
BOOST_CHECK_CLOSE_FRACTION( (VAL ## L? VAL ## L : std::numeric_limits<test_t>::epsilon()), \
(converted_val ? converted_val : std::numeric_limits<test_t>::epsilon()), \
std::numeric_limits<test_t>::epsilon() \
);
#endif
template <class TestType>
void test_converion_to_float_types()
{
typedef TestType test_t;
test_t converted_val;
BOOST_CHECK_CLOSE_FRACTION(1.0, lexical_cast<test_t>('1'), (std::numeric_limits<test_t>::epsilon()));
BOOST_CHECK_EQUAL(0.0, lexical_cast<test_t>('0'));
unsigned char const uc_one = '1';
unsigned char const uc_zero ='0';
BOOST_CHECK_CLOSE_FRACTION(1.0, lexical_cast<test_t>(uc_one), (std::numeric_limits<test_t>::epsilon()));
BOOST_CHECK_EQUAL(0.0, lexical_cast<test_t>(uc_zero));
signed char const sc_one = '1';
signed char const sc_zero ='0';
BOOST_CHECK_CLOSE_FRACTION(1.0, lexical_cast<test_t>(sc_one), (std::numeric_limits<test_t>::epsilon()));
BOOST_CHECK_EQUAL(0.0, lexical_cast<test_t>(sc_zero));
BOOST_CHECK_CLOSE_FRACTION(1e34L, lexical_cast<test_t>( "10000000000000000000000000000000000"), (std::numeric_limits<test_t>::epsilon()) );
// VC failes the next test
// BOOST_CHECK_CLOSE_FRACTION(1e-35L, lexical_cast<test_t>("0.00000000000000000000000000000000001"), (std::numeric_limits<test_t>::epsilon()) );
BOOST_CHECK_CLOSE_FRACTION(
0.1111111111111111111111111111111111111111111111111111111111111111111111111L
, lexical_cast<test_t>("0.1111111111111111111111111111111111111111111111111111111111111111111111111")
, (std::numeric_limits<test_t>::epsilon()) );
CHECK_CLOSE_ABS_DIFF(1,test_t);
BOOST_CHECK_EQUAL(0,lexical_cast<test_t>("0"));
CHECK_CLOSE_ABS_DIFF(-1,test_t);
CHECK_CLOSE_ABS_DIFF(1.0, test_t);
CHECK_CLOSE_ABS_DIFF(0.0, test_t);
CHECK_CLOSE_ABS_DIFF(-1.0,test_t);
CHECK_CLOSE_ABS_DIFF(1e1, test_t);
CHECK_CLOSE_ABS_DIFF(0e1, test_t);
CHECK_CLOSE_ABS_DIFF(-1e1,test_t);
CHECK_CLOSE_ABS_DIFF(1.0e1, test_t);
CHECK_CLOSE_ABS_DIFF(0.0e1, test_t);
CHECK_CLOSE_ABS_DIFF(-1.0e1,test_t);
CHECK_CLOSE_ABS_DIFF(1e-1, test_t);
CHECK_CLOSE_ABS_DIFF(0e-1, test_t);
CHECK_CLOSE_ABS_DIFF(-1e-1,test_t);
CHECK_CLOSE_ABS_DIFF(1.0e-1, test_t);
CHECK_CLOSE_ABS_DIFF(0.0e-1, test_t);
CHECK_CLOSE_ABS_DIFF(-1.0e-1,test_t);
CHECK_CLOSE_ABS_DIFF(1E1, test_t);
CHECK_CLOSE_ABS_DIFF(0E1, test_t);
CHECK_CLOSE_ABS_DIFF(-1E1,test_t);
CHECK_CLOSE_ABS_DIFF(1.0E1, test_t);
CHECK_CLOSE_ABS_DIFF(0.0E1, test_t);
CHECK_CLOSE_ABS_DIFF(-1.0E1,test_t);
CHECK_CLOSE_ABS_DIFF(1E-1, test_t);
CHECK_CLOSE_ABS_DIFF(0E-1, test_t);
CHECK_CLOSE_ABS_DIFF(-1E-1,test_t);
CHECK_CLOSE_ABS_DIFF(1.0E-1, test_t);
CHECK_CLOSE_ABS_DIFF(0.0E-1, test_t);
CHECK_CLOSE_ABS_DIFF(-1.0E-1, test_t);
CHECK_CLOSE_ABS_DIFF(.0E-1, test_t);
CHECK_CLOSE_ABS_DIFF(.0E-1, test_t);
CHECK_CLOSE_ABS_DIFF(-.0E-1, test_t);
CHECK_CLOSE_ABS_DIFF(10.0, test_t);
CHECK_CLOSE_ABS_DIFF(00.0, test_t);
CHECK_CLOSE_ABS_DIFF(-10.0,test_t);
CHECK_CLOSE_ABS_DIFF(10e1, test_t);
CHECK_CLOSE_ABS_DIFF(00e1, test_t);
CHECK_CLOSE_ABS_DIFF(-10e1,test_t);
CHECK_CLOSE_ABS_DIFF(10.0e1, test_t);
CHECK_CLOSE_ABS_DIFF(00.0e1, test_t);
CHECK_CLOSE_ABS_DIFF(-10.0e1,test_t);
CHECK_CLOSE_ABS_DIFF(10e-1, test_t);
CHECK_CLOSE_ABS_DIFF(00e-1, test_t);
CHECK_CLOSE_ABS_DIFF(-10e-1,test_t);
CHECK_CLOSE_ABS_DIFF(10.0e-1, test_t);
CHECK_CLOSE_ABS_DIFF(00.0e-1, test_t);
CHECK_CLOSE_ABS_DIFF(-10.0e-1,test_t);
CHECK_CLOSE_ABS_DIFF(10E1, test_t);
CHECK_CLOSE_ABS_DIFF(00E1, test_t);
CHECK_CLOSE_ABS_DIFF(-10E1,test_t);
CHECK_CLOSE_ABS_DIFF(10.0E1, test_t);
CHECK_CLOSE_ABS_DIFF(00.0E1, test_t);
CHECK_CLOSE_ABS_DIFF(-10.0E1,test_t);
CHECK_CLOSE_ABS_DIFF(10E-1, test_t);
CHECK_CLOSE_ABS_DIFF(00E-1, test_t);
CHECK_CLOSE_ABS_DIFF(-10E-1,test_t);
CHECK_CLOSE_ABS_DIFF(10.0E-1, test_t);
CHECK_CLOSE_ABS_DIFF(00.0E-1, test_t);
CHECK_CLOSE_ABS_DIFF(-10.0E-1, test_t);
CHECK_CLOSE_ABS_DIFF(-10101.0E-011, test_t);
CHECK_CLOSE_ABS_DIFF(-10101093, test_t);
CHECK_CLOSE_ABS_DIFF(10101093, test_t);
CHECK_CLOSE_ABS_DIFF(-.34, test_t);
CHECK_CLOSE_ABS_DIFF(.34, test_t);
CHECK_CLOSE_ABS_DIFF(.34e10, test_t);
BOOST_CHECK_THROW(lexical_cast<test_t>("-1.e"), bad_lexical_cast);
BOOST_CHECK_THROW(lexical_cast<test_t>("-1.E"), bad_lexical_cast);
BOOST_CHECK_THROW(lexical_cast<test_t>("1.e"), bad_lexical_cast);
BOOST_CHECK_THROW(lexical_cast<test_t>("1.E"), bad_lexical_cast);
BOOST_CHECK_THROW(lexical_cast<test_t>("1.0e"), bad_lexical_cast);
BOOST_CHECK_THROW(lexical_cast<test_t>("1.0E"), bad_lexical_cast);
BOOST_CHECK_THROW(lexical_cast<test_t>("10E"), bad_lexical_cast);
BOOST_CHECK_THROW(lexical_cast<test_t>("10e"), bad_lexical_cast);
BOOST_CHECK_THROW(lexical_cast<test_t>("1.0e-"), bad_lexical_cast);
BOOST_CHECK_THROW(lexical_cast<test_t>("1.0E-"), bad_lexical_cast);
BOOST_CHECK_THROW(lexical_cast<test_t>("10E-"), bad_lexical_cast);
BOOST_CHECK_THROW(lexical_cast<test_t>("10e-"), bad_lexical_cast);
BOOST_CHECK_THROW(lexical_cast<test_t>("e1"), bad_lexical_cast);
BOOST_CHECK_THROW(lexical_cast<test_t>("e-1"), bad_lexical_cast);
BOOST_CHECK_THROW(lexical_cast<test_t>("e-"), bad_lexical_cast);
BOOST_CHECK_THROW(lexical_cast<test_t>(".e"), bad_lexical_cast);
BOOST_CHECK_THROW(lexical_cast<test_t>(".11111111111111111111111111111111111111111111111111111111111111111111ee"), bad_lexical_cast);
BOOST_CHECK_THROW(lexical_cast<test_t>(".11111111111111111111111111111111111111111111111111111111111111111111e-"), bad_lexical_cast);
BOOST_CHECK_THROW(lexical_cast<test_t>("-B"), bad_lexical_cast);
BOOST_CHECK_THROW(lexical_cast<test_t>("0xB"), bad_lexical_cast);
BOOST_CHECK_THROW(lexical_cast<test_t>("0x0"), bad_lexical_cast);
BOOST_CHECK_THROW(lexical_cast<test_t>("--1.0"), bad_lexical_cast);
BOOST_CHECK_THROW(lexical_cast<test_t>("1.0e--1"), bad_lexical_cast);
BOOST_CHECK_THROW(lexical_cast<test_t>("1.0.0"), bad_lexical_cast);
BOOST_CHECK_THROW(lexical_cast<test_t>("1e1e1"), bad_lexical_cast);
BOOST_CHECK_THROW(lexical_cast<test_t>("1.0e-1e-1"), bad_lexical_cast);
BOOST_CHECK_THROW(lexical_cast<test_t>(" 1.0"), bad_lexical_cast);
BOOST_CHECK_THROW(lexical_cast<test_t>("1.0 "), bad_lexical_cast);
BOOST_CHECK_THROW(lexical_cast<test_t>(""), bad_lexical_cast);
BOOST_CHECK_THROW(lexical_cast<test_t>("-"), bad_lexical_cast);
BOOST_CHECK_THROW(lexical_cast<test_t>('\0'), bad_lexical_cast);
BOOST_CHECK_THROW(lexical_cast<test_t>('-'), bad_lexical_cast);
}
template <class T>
void test_float_typess_for_overflows()
{
typedef T test_t;
test_t minvalue = (std::numeric_limits<test_t>::min)();
std::string s_min_value = lexical_cast<std::string>(minvalue);
BOOST_CHECK_CLOSE_FRACTION(minvalue, lexical_cast<test_t>(minvalue), (std::numeric_limits<test_t>::epsilon()));
BOOST_CHECK_CLOSE_FRACTION(minvalue, lexical_cast<test_t>(s_min_value), (std::numeric_limits<test_t>::epsilon()));
test_t maxvalue = (std::numeric_limits<test_t>::max)();
std::string s_max_value = lexical_cast<std::string>(maxvalue);
BOOST_CHECK_CLOSE_FRACTION(maxvalue, lexical_cast<test_t>(maxvalue), (std::numeric_limits<test_t>::epsilon()));
BOOST_CHECK_CLOSE_FRACTION(maxvalue, lexical_cast<test_t>(s_max_value), (std::numeric_limits<test_t>::epsilon()));
BOOST_CHECK_THROW(lexical_cast<test_t>(s_max_value+"1"), bad_lexical_cast);
BOOST_CHECK_THROW(lexical_cast<test_t>(s_max_value+"9"), bad_lexical_cast);
// VC9 can fail the fllowing tests on floats and doubles when using stingstream...
BOOST_CHECK_THROW(lexical_cast<test_t>("1"+s_max_value), bad_lexical_cast);
BOOST_CHECK_THROW(lexical_cast<test_t>("9"+s_max_value), bad_lexical_cast);
if ( is_same<test_t,float>::value )
{
BOOST_CHECK_THROW(lexical_cast<test_t>( (std::numeric_limits<double>::max)() ), bad_lexical_cast);
BOOST_CHECK(
(std::numeric_limits<double>::min)() - std::numeric_limits<test_t>::epsilon()
<= lexical_cast<test_t>( (std::numeric_limits<double>::min)() )
&& lexical_cast<test_t>( (std::numeric_limits<double>::min)() )
<= (std::numeric_limits<double>::min)() + std::numeric_limits<test_t>::epsilon()
);
}
if ( sizeof(test_t) < sizeof(long double) )
{
BOOST_CHECK_THROW(lexical_cast<test_t>( (std::numeric_limits<long double>::max)() ), bad_lexical_cast);
BOOST_CHECK(
(std::numeric_limits<long double>::min)() - std::numeric_limits<test_t>::epsilon()
<= lexical_cast<test_t>( (std::numeric_limits<long double>::min)() )
&& lexical_cast<test_t>( (std::numeric_limits<long double>::min)() )
<= (std::numeric_limits<long double>::min)() + std::numeric_limits<test_t>::epsilon()
);
}
}
#undef CHECK_CLOSE_ABS_DIFF
#define TEST_TO_FROM_CAST_AROUND_TYPED(VAL,STRING_TYPE) \
test_value = VAL + std::numeric_limits<test_t>::epsilon() * i ; \
converted_val = lexical_cast<test_t>( lexical_cast<STRING_TYPE>(test_value) ); \
BOOST_CHECK_CLOSE_FRACTION( \
test_value, \
converted_val, \
std::numeric_limits<test_t>::epsilon() \
);
/*
* For interval [ from_mult*epsilon+VAL, to_mult*epsilon+VAL ], converts float type
* numbers to string[wstring] and then back to float type, then compares initial
* values and generated.
* Step is epsilon
*/
#ifndef BOOST_LCAST_NO_WCHAR_T
# define TEST_TO_FROM_CAST_AROUND(VAL) \
for(i=from_mult; i<=to_mult; ++i) { \
TEST_TO_FROM_CAST_AROUND_TYPED(VAL, std::string) \
TEST_TO_FROM_CAST_AROUND_TYPED(VAL, std::wstring) \
}
#else
# define TEST_TO_FROM_CAST_AROUND(VAL) \
for(i=from_mult; i<=to_mult; ++i) { \
TEST_TO_FROM_CAST_AROUND_TYPED(VAL, std::string) \
}
#endif
template <class TestType>
void test_converion_from_to_float_types()
{
typedef TestType test_t;
test_t test_value;
test_t converted_val;
int i;
int from_mult = -50;
int to_mult = 50;
TEST_TO_FROM_CAST_AROUND( 0.0 );
long double val1;
for(val1 = 1.0e-10L; val1 < 1e11; val1*=10 )
TEST_TO_FROM_CAST_AROUND( val1 );
long double val2;
for(val2 = -1.0e-10L; val2 > -1e11; val2*=10 )
TEST_TO_FROM_CAST_AROUND( val2 );
from_mult = -100;
to_mult = 0;
TEST_TO_FROM_CAST_AROUND( (std::numeric_limits<test_t>::max)() );
from_mult = 0;
to_mult = 100;
TEST_TO_FROM_CAST_AROUND( (std::numeric_limits<test_t>::min)() );
}
#undef TEST_TO_FROM_CAST_AROUND
#undef TEST_TO_FROM_CAST_AROUND_TYPED
template<class T, class CharT>
void test_conversion_from_float_to_char(CharT zero)
{
BOOST_CHECK(lexical_cast<CharT>(static_cast<T>(0)) == zero + 0);
BOOST_CHECK(lexical_cast<CharT>(static_cast<T>(1)) == zero + 1);
BOOST_CHECK(lexical_cast<CharT>(static_cast<T>(2)) == zero + 2);
BOOST_CHECK(lexical_cast<CharT>(static_cast<T>(3)) == zero + 3);
BOOST_CHECK(lexical_cast<CharT>(static_cast<T>(4)) == zero + 4);
BOOST_CHECK(lexical_cast<CharT>(static_cast<T>(5)) == zero + 5);
BOOST_CHECK(lexical_cast<CharT>(static_cast<T>(6)) == zero + 6);
BOOST_CHECK(lexical_cast<CharT>(static_cast<T>(7)) == zero + 7);
BOOST_CHECK(lexical_cast<CharT>(static_cast<T>(8)) == zero + 8);
BOOST_CHECK(lexical_cast<CharT>(static_cast<T>(9)) == zero + 9);
BOOST_CHECK_THROW(lexical_cast<CharT>(static_cast<T>(10)), bad_lexical_cast);
T t = (std::numeric_limits<T>::max)();
BOOST_CHECK_THROW(lexical_cast<CharT>(t), bad_lexical_cast);
}
template<class T, class CharT>
void test_conversion_from_char_to_float(CharT zero)
{
BOOST_CHECK_CLOSE_FRACTION(lexical_cast<T>( static_cast<CharT>(zero + 0)), static_cast<T>(0), (std::numeric_limits<T>::epsilon()) );
BOOST_CHECK_CLOSE_FRACTION(lexical_cast<T>( static_cast<CharT>(zero + 1)), static_cast<T>(1), (std::numeric_limits<T>::epsilon()) );
BOOST_CHECK_CLOSE_FRACTION(lexical_cast<T>( static_cast<CharT>(zero + 2)), static_cast<T>(2), (std::numeric_limits<T>::epsilon()) );
BOOST_CHECK_CLOSE_FRACTION(lexical_cast<T>( static_cast<CharT>(zero + 3)), static_cast<T>(3), (std::numeric_limits<T>::epsilon()) );
BOOST_CHECK_CLOSE_FRACTION(lexical_cast<T>( static_cast<CharT>(zero + 4)), static_cast<T>(4), (std::numeric_limits<T>::epsilon()) );
BOOST_CHECK_CLOSE_FRACTION(lexical_cast<T>( static_cast<CharT>(zero + 5)), static_cast<T>(5), (std::numeric_limits<T>::epsilon()) );
BOOST_CHECK_CLOSE_FRACTION(lexical_cast<T>( static_cast<CharT>(zero + 6)), static_cast<T>(6), (std::numeric_limits<T>::epsilon()) );
BOOST_CHECK_CLOSE_FRACTION(lexical_cast<T>( static_cast<CharT>(zero + 7)), static_cast<T>(7), (std::numeric_limits<T>::epsilon()) );
BOOST_CHECK_CLOSE_FRACTION(lexical_cast<T>( static_cast<CharT>(zero + 8)), static_cast<T>(8), (std::numeric_limits<T>::epsilon()) );
BOOST_CHECK_CLOSE_FRACTION(lexical_cast<T>( static_cast<CharT>(zero + 9)), static_cast<T>(9), (std::numeric_limits<T>::epsilon()) );
BOOST_CHECK_THROW(lexical_cast<T>( static_cast<CharT>(zero + 10)), bad_lexical_cast);
BOOST_CHECK_THROW(lexical_cast<T>( static_cast<CharT>(zero - 1)), bad_lexical_cast);
}
struct restore_oldloc
{
std::locale oldloc;
~restore_oldloc() { std::locale::global(oldloc); }
};
template<class T>
void test_conversion_from_to_float()
{ char const zero = '0';
signed char const szero = '0';
unsigned char const uzero = '0';
test_conversion_from_float_to_char<T>(zero);
test_conversion_from_char_to_float<T>(zero);
test_conversion_from_float_to_char<T>(szero);
test_conversion_from_char_to_float<T>(szero);
test_conversion_from_float_to_char<T>(uzero);
test_conversion_from_char_to_float<T>(uzero);
#if !defined(BOOST_LCAST_NO_WCHAR_T) && !defined(BOOST_NO_INTRINSIC_WCHAR_T)
wchar_t const wzero = L'0';
test_conversion_from_float_to_char<T>(wzero);
test_conversion_from_char_to_float<T>(wzero);
#endif
BOOST_CHECK_CLOSE_FRACTION(lexical_cast<T>("+1"), 1, std::numeric_limits<T>::epsilon());
BOOST_CHECK_CLOSE_FRACTION(lexical_cast<T>("+9"), 9, std::numeric_limits<T>::epsilon());
BOOST_CHECK_THROW(lexical_cast<T>("++1"), bad_lexical_cast);
BOOST_CHECK_THROW(lexical_cast<T>("-+9"), bad_lexical_cast);
BOOST_CHECK_THROW(lexical_cast<T>("--1"), bad_lexical_cast);
BOOST_CHECK_THROW(lexical_cast<T>("+-9"), bad_lexical_cast);
test_converion_to_float_types<T>();
test_float_typess_for_overflows<T>();
test_converion_from_to_float_types<T>();
typedef std::numpunct<char> numpunct;
restore_oldloc guard;
std::locale const& oldloc = guard.oldloc;
std::string grouping1 = BOOST_USE_FACET(numpunct, oldloc).grouping();
std::string grouping2(grouping1);
test_conversion_from_to_float_for_locale<T>();
try
{
std::locale newloc("");
std::locale::global(newloc);
grouping2 = BOOST_USE_FACET(numpunct, newloc).grouping();
}
catch(std::exception const& ex)
{
std::string msg("Failed to set system locale: ");
msg += ex.what();
BOOST_TEST_MESSAGE(msg);
}
if(grouping1 != grouping2)
test_conversion_from_to_float_for_locale<T>();
if(grouping1.empty() && grouping2.empty())
BOOST_TEST_MESSAGE("Formatting with thousands_sep has not been tested");
}
void test_conversion_from_to_float()
{
test_conversion_from_to_float<float>();
}
void test_conversion_from_to_double()
{
test_conversion_from_to_float<double>();
}
void test_conversion_from_to_long_double()
{
test_conversion_from_to_float<long double>();
}
+180
View File
@@ -0,0 +1,180 @@
// Unit test for boost::lexical_cast.
//
// See http://www.boost.org for most recent version, including documentation.
//
// Copyright Antony Polukhin, 2011.
//
// Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt).
#include <boost/config.hpp>
#if defined(__INTEL_COMPILER)
#pragma warning(disable: 193 383 488 981 1418 1419)
#elif defined(BOOST_MSVC)
#pragma warning(disable: 4097 4100 4121 4127 4146 4244 4245 4511 4512 4701 4800)
#endif
#include <boost/lexical_cast.hpp>
#include <boost/math/special_functions/sign.hpp>
#include <boost/math/special_functions/fpclassify.hpp>
#include <boost/type_traits/is_same.hpp>
#include <boost/test/unit_test.hpp>
#include <boost/test/floating_point_comparison.hpp>
#if defined(BOOST_NO_STRINGSTREAM) || defined(BOOST_NO_STD_WSTRING)
#define BOOST_LCAST_NO_WCHAR_T
#endif
using namespace boost;
template <class T>
bool is_pos_inf(T value)
{
return (boost::math::isinf)(value) && !(boost::math::signbit)(value);
}
template <class T>
bool is_neg_inf(T value)
{
return (boost::math::isinf)(value) && (boost::math::signbit)(value);
}
template <class T>
bool is_pos_nan(T value)
{
return (boost::math::isnan)(value) && !(boost::math::signbit)(value);
}
template <class T>
bool is_neg_nan(T value)
{
/* There is some strange behaviour on Itanium platform with -nan nuber for long double.
* It is a IA64 feature, or it is a boost::math feature, not a lexical_cast bug */
#if defined(__ia64__) || defined(_M_IA64)
return (boost::math::isnan)(value)
&& ( boost::is_same<T, long double >::value || (boost::math::signbit)(value) );
#else
return (boost::math::isnan)(value) && (boost::math::signbit)(value);
#endif
}
template <class T>
void test_inf_nan_templated()
{
typedef T test_t;
BOOST_CHECK( is_pos_inf( lexical_cast<test_t>("inf") ) );
BOOST_CHECK( is_pos_inf( lexical_cast<test_t>("INF") ) );
BOOST_CHECK( is_neg_inf( lexical_cast<test_t>("-inf") ) );
BOOST_CHECK( is_neg_inf( lexical_cast<test_t>("-INF") ) );
BOOST_CHECK( is_pos_inf( lexical_cast<test_t>("+inf") ) );
BOOST_CHECK( is_pos_inf( lexical_cast<test_t>("+INF") ) );
BOOST_CHECK( is_pos_inf( lexical_cast<test_t>("infinity") ) );
BOOST_CHECK( is_pos_inf( lexical_cast<test_t>("INFINITY") ) );
BOOST_CHECK( is_neg_inf( lexical_cast<test_t>("-infinity") ) );
BOOST_CHECK( is_neg_inf( lexical_cast<test_t>("-INFINITY") ) );
BOOST_CHECK( is_pos_inf( lexical_cast<test_t>("+infinity") ) );
BOOST_CHECK( is_pos_inf( lexical_cast<test_t>("+INFINITY") ) );
BOOST_CHECK( is_pos_nan( lexical_cast<test_t>("nan") ) );
BOOST_CHECK( is_pos_nan( lexical_cast<test_t>("NAN") ) );
BOOST_CHECK( is_neg_nan( lexical_cast<test_t>("-nan") ) );
BOOST_CHECK( is_neg_nan( lexical_cast<test_t>("-NAN") ) );
BOOST_CHECK( is_pos_nan( lexical_cast<test_t>("+nan") ) );
BOOST_CHECK( is_pos_nan( lexical_cast<test_t>("+NAN") ) );
BOOST_CHECK( is_pos_nan( lexical_cast<test_t>("nan()") ) );
BOOST_CHECK( is_pos_nan( lexical_cast<test_t>("NAN(some string)") ) );
BOOST_CHECK_THROW( lexical_cast<test_t>("NAN(some string"), bad_lexical_cast );
BOOST_CHECK(lexical_cast<std::string>( (boost::math::changesign)(std::numeric_limits<test_t >::infinity()))
== "-inf" );
BOOST_CHECK(lexical_cast<std::string>( std::numeric_limits<test_t >::infinity()) == "inf" );
BOOST_CHECK(lexical_cast<std::string>( std::numeric_limits<test_t >::quiet_NaN()) == "nan" );
#if !defined(__ia64__) && !defined(_M_IA64)
BOOST_CHECK(lexical_cast<std::string>(
(boost::math::changesign)(std::numeric_limits<test_t >::quiet_NaN()))
== "-nan" );
#endif
#ifndef BOOST_LCAST_NO_WCHAR_T
BOOST_CHECK( is_pos_inf( lexical_cast<test_t>(L"inf") ) );
BOOST_CHECK( is_pos_inf( lexical_cast<test_t>(L"INF") ) );
BOOST_CHECK( is_neg_inf( lexical_cast<test_t>(L"-inf") ) );
BOOST_CHECK( is_neg_inf( lexical_cast<test_t>(L"-INF") ) );
BOOST_CHECK( is_pos_inf( lexical_cast<test_t>(L"+inf") ) );
BOOST_CHECK( is_pos_inf( lexical_cast<test_t>(L"+INF") ) );
BOOST_CHECK( is_pos_inf( lexical_cast<test_t>(L"infinity") ) );
BOOST_CHECK( is_pos_inf( lexical_cast<test_t>(L"INFINITY") ) );
BOOST_CHECK( is_neg_inf( lexical_cast<test_t>(L"-infinity") ) );
BOOST_CHECK( is_neg_inf( lexical_cast<test_t>(L"-INFINITY") ) );
BOOST_CHECK( is_pos_inf( lexical_cast<test_t>(L"+infinity") ) );
BOOST_CHECK( is_pos_inf( lexical_cast<test_t>(L"+INFINITY") ) );
BOOST_CHECK( is_pos_nan( lexical_cast<test_t>(L"nan") ) );
BOOST_CHECK( is_pos_nan( lexical_cast<test_t>(L"NAN") ) );
BOOST_CHECK( is_neg_nan( lexical_cast<test_t>(L"-nan") ) );
BOOST_CHECK( is_neg_nan( lexical_cast<test_t>(L"-NAN") ) );
BOOST_CHECK( is_pos_nan( lexical_cast<test_t>(L"+nan") ) );
BOOST_CHECK( is_pos_nan( lexical_cast<test_t>(L"+NAN") ) );
BOOST_CHECK( is_pos_nan( lexical_cast<test_t>(L"nan()") ) );
BOOST_CHECK( is_pos_nan( lexical_cast<test_t>(L"NAN(some string)") ) );
BOOST_CHECK_THROW( lexical_cast<test_t>(L"NAN(some string"), bad_lexical_cast );
BOOST_CHECK(lexical_cast<std::wstring>( (boost::math::changesign)(std::numeric_limits<test_t >::infinity()))
== L"-inf" );
BOOST_CHECK(lexical_cast<std::wstring>( std::numeric_limits<test_t >::infinity()) == L"inf" );
BOOST_CHECK(lexical_cast<std::wstring>( std::numeric_limits<test_t >::quiet_NaN()) == L"nan" );
#if !defined(__ia64__) && !defined(_M_IA64)
BOOST_CHECK(lexical_cast<std::wstring>(
(boost::math::changesign)(std::numeric_limits<test_t >::quiet_NaN()))
== L"-nan" );
#endif
#endif
}
void test_inf_nan_float()
{
test_inf_nan_templated<float >();
}
void test_inf_nan_double()
{
test_inf_nan_templated<double >();
}
void test_inf_nan_long_double()
{
test_inf_nan_templated<long double >();
}
unit_test::test_suite *init_unit_test_suite(int, char *[])
{
unit_test_framework::test_suite *suite =
BOOST_TEST_SUITE("lexical_cast inf anf nan parsing unit test");
suite->add(BOOST_TEST_CASE(&test_inf_nan_float));
suite->add(BOOST_TEST_CASE(&test_inf_nan_double));
suite->add(BOOST_TEST_CASE(&test_inf_nan_long_double));
return suite;
}
-6
View File
@@ -64,7 +64,6 @@ void test_round_conversion()
}
#if defined(BOOST_MSVC)
// See bug http://tinyurl.com/vhpvo
template<class T>
void test_msvc_magic_values()
@@ -73,7 +72,6 @@ void test_msvc_magic_values()
std::string magic_msvc_s = boost::lexical_cast<std::string>(magic_msvc);
BOOST_CHECK(magic_msvc == lexical_cast<T>(magic_msvc_s));
}
#endif
void test_round_conversion_float()
{
@@ -83,16 +81,12 @@ void test_round_conversion_float()
void test_round_conversion_double()
{
test_round_conversion<double>();
#if defined(BOOST_MSVC)
test_msvc_magic_values<double>();
#endif
}
void test_round_conversion_long_double()
{
test_round_conversion<long double>();
#if defined(BOOST_MSVC)
test_msvc_magic_values<long double>();
#endif
}
+67
View File
@@ -0,0 +1,67 @@
// Unit test for boost::lexical_cast.
//
// See http://www.boost.org for most recent version, including documentation.
//
// Copyright Alexander Nasonov, 2007.
//
// Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt).
//
// This tests now must pass on vc8, because lexical_cast
// implementation has changed and it does not use stringstream for casts
// to integral types
#include <boost/config.hpp>
#include <boost/lexical_cast.hpp>
#include <boost/cstdint.hpp>
#include <boost/test/unit_test.hpp>
#include <string>
using namespace boost;
// See also test_conversion_from_string_to_integral(CharT)
// in libs/conversion/lexical_cast_test.cpp
template<class T, class CharT>
void test_too_long_number(CharT zero)
{
typedef std::numeric_limits<T> limits;
std::basic_string<CharT> s;
std::basic_ostringstream<CharT> o;
o << (limits::max)() << zero;
s = o.str();
BOOST_CHECK_THROW(lexical_cast<T>(s), bad_lexical_cast);
s[s.size()-1] += 9; // '0' -> '9'
BOOST_CHECK_THROW(lexical_cast<T>(s), bad_lexical_cast);
if(limits::is_signed)
{
std::basic_ostringstream<CharT> o;
o << (limits::min)() << zero;
s = o.str();
BOOST_CHECK_THROW(lexical_cast<T>(s), bad_lexical_cast);
s[s.size()-1] += 9; // '0' -> '9'
BOOST_CHECK_THROW(lexical_cast<T>(s), bad_lexical_cast);
}
}
void test_vc8_bug()
{
test_too_long_number<boost::intmax_t>('0');
test_too_long_number<boost::uintmax_t>('0');
#if !defined(BOOST_LCAST_NO_WCHAR_T)
test_too_long_number<boost::intmax_t>(L'0');
test_too_long_number<boost::uintmax_t>(L'0');
#endif
}
unit_test::test_suite *init_unit_test_suite(int, char *[])
{
unit_test_framework::test_suite *suite =
BOOST_TEST_SUITE("lexical_cast vc8 bug unit test");
suite->add(BOOST_TEST_CASE(test_vc8_bug));
return suite;
}
+56
View File
@@ -0,0 +1,56 @@
// Unit test for boost::lexical_cast.
//
// See http://www.boost.org for most recent version, including documentation.
//
// Copyright Antony Polukhin, 2011.
//
// Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt).
#include <boost/config.hpp>
#if defined(__INTEL_COMPILER)
#pragma warning(disable: 193 383 488 981 1418 1419)
#elif defined(BOOST_MSVC)
#pragma warning(disable: 4097 4100 4121 4127 4146 4244 4245 4511 4512 4701 4800)
#endif
#include <boost/lexical_cast.hpp>
#include <boost/cstdint.hpp>
#include <boost/test/unit_test.hpp>
#include <boost/test/floating_point_comparison.hpp>
using namespace boost;
void test_char_types_conversions()
{
#ifndef BOOST_LCAST_NO_WCHAR_T
const char c_arr[] = "Test array of chars";
const unsigned char uc_arr[] = "Test array of chars";
const signed char sc_arr[] = "Test array of chars";
const wchar_t wc_arr[] =L"Test array of chars";
// Following tests depend on realization of std::locale
// and pass for popular compilers and STL realizations
BOOST_CHECK(boost::lexical_cast<wchar_t>(c_arr[0]) == wc_arr[0]);
BOOST_CHECK(boost::lexical_cast<std::wstring>(c_arr) == std::wstring(wc_arr));
BOOST_CHECK(boost::lexical_cast<std::wstring>(sc_arr) == std::wstring(wc_arr) );
BOOST_CHECK(boost::lexical_cast<std::wstring>(uc_arr) == std::wstring(wc_arr) );
BOOST_CHECK_EQUAL(boost::lexical_cast<wchar_t>(uc_arr[0]), wc_arr[0]);
BOOST_CHECK_EQUAL(boost::lexical_cast<wchar_t>(sc_arr[0]), wc_arr[0]);
#endif
BOOST_CHECK(1);
}
unit_test::test_suite *init_unit_test_suite(int, char *[])
{
unit_test_framework::test_suite *suite =
BOOST_TEST_SUITE("lexical_cast char<->wchar_t unit test");
suite->add(BOOST_TEST_CASE(&test_char_types_conversions));
return suite;
}