Compare commits

...

45 Commits

Author SHA1 Message Date
Marshall Clow 0fc0a8ef32 Release 1.54.0
[SVN r84923]
2013-07-01 16:53:14 +00:00
Antony Polukhin 3af0af9405 Merge from trunk:
* Fix for GCC-4.8 warning (fixes #8547)
* Disable tests, invalid for C11 (clang specific)

[SVN r84183]
2013-05-07 19:24:47 +00:00
Antony Polukhin b97f2542ec Mrege from trunk:
* Disable UTF16 and UTF32 tests for libc++ (fixes #8369)

[SVN r83764]
2013-04-04 15:47:02 +00:00
Antony Polukhin 32d70a0764 Merge from trunk:
* Fix stream related issues with libc++ and clang (fixes #7704, fixes #8267)
* Change runtime assert to compile time when converting to pointer (fixes #8267)

[SVN r83689]
2013-04-01 20:40:43 +00:00
Antony Polukhin a4bd056b8e Merge from trunk:
* Fixed incorrect usage of Boost.Math when it does not support long double (fixes #8162)
* Fixed ambiguity of boost::lexical_cast functions (fixes #7421)

[SVN r83542]
2013-03-24 14:37:56 +00:00
Antony Polukhin 335c868e9b Merge from trunk:
* Silence some buggy VS warnings (fixes #7949)
* Fix -Wconversion warnings (fixes #2558)
* Added support for int128 conversions (fixes #7909)

[SVN r83114]
2013-02-24 08:31:17 +00:00
Antony Polukhin 518203671c Merge from trunk: fixes #7814 (fixed some numeric to numeric conversions bugs, workaround warnings, -ftrapv now does not triggers coredump)
[SVN r82268]
2012-12-29 14:41:23 +00:00
Antony Polukhin 16890bf041 Merge from trunk
* Fixes #7799 (optimizations with std::array were not used)
* Fixes #7831 (documentation update)

[SVN r82224]
2012-12-27 18:54:28 +00:00
Antony Polukhin dbda7689e0 Merge lexical_cast from trunk:
* Deduce stream character type for user defined classes (fixes #6786)
* Deprecated macros replaced with new ones (thanks to Marshall Clow)
* Updated documentation (refs #6786, fixes #7582)
* More tests and minor bugfixes

[SVN r81668]
2012-12-02 09:33:42 +00:00
Antony Polukhin 0920c53e23 Merege fix for #7421 from trunk
[SVN r80787]
2012-09-30 16:07:32 +00:00
Antony Polukhin 8d373a0c99 Merge updated tests from trunk (now float types tests are less strict, workaround MSVC2012 bug)
[SVN r80672]
2012-09-23 17:19:05 +00:00
Antony Polukhin 733438e072 Merge from trunk:
1) #warning replaced with #error (refs #7228)
2) Pavel Korzh added to thanks list (refs #7157)
3) BOOST_NOEXCEPT modifiers added where possible
4) better support for c++11 Unicode characters
5) fixed compilation with MSVC+STLPort
6) more agressive usage of Traits template parameter
7) Added lexical_cast(const CharType* chars, std::size_t count) function overload (refs #6430 and refs #6663)
8) Fixed GCC warning in numeric_cast_test.cpp
9) Fix compilation of lexical cast with MSVC 2003 (refs #7255)

[SVN r80409]
2012-09-05 18:23:41 +00:00
Antony Polukhin f67347e308 Merge bugfix for volatile types (refs #7157)
[SVN r79871]
2012-08-05 09:46:43 +00:00
Antony Polukhin 46c6cc911b Merge fix of VC warning (fixes #7116)
[SVN r79605]
2012-07-19 18:42:34 +00:00
Antony Polukhin 80d480ca0b Fix typo in documentation (fixes #7129)
[SVN r79480]
2012-07-13 19:22:49 +00:00
Antony Polukhin 675d0bb451 Merge from trunk (now lexical_cast has optimized conversions to and from array<>, fixes #7065)
[SVN r79364]
2012-07-08 18:06:32 +00:00
Antony Polukhin 79d6468aeb Merge lexical_cast from trunk :
* force SunCC compiler to use fallback version of lexical_cast (with fallbak version SunCC can pass at least some tests)
* removed trailing whitespaces

[SVN r78565]
2012-05-24 04:22:04 +00:00
Antony Polukhin ca9c8d30bd Merge from trunk:
* Fixes ISO C++ does not support the ‘%lg’ gnu_printf format (refs #6852)
* explicit-failures-markup merge from trunk
* supress warnings in implicit_cast.cpp test

[SVN r78450]
2012-05-13 08:15:51 +00:00
Antony Polukhin b1b5305984 Merge from trunk:
* fixed #6812 (now converting "." to float type throws bad_lexical_cast)

[SVN r78211]
2012-04-26 17:59:17 +00:00
Antony Polukhin eb4ad73caf Merge lexical_cast library from trunk:
* multiple optimizations and bugfixes for boost::iterator_range (refs #6786, refs #6430, refs #6663)
* documentation update
* new Unicode characters support updated
* much more tests, removed incorrect tests

[SVN r78059]
2012-04-18 04:09:49 +00:00
Antony Polukhin 1e58331baf Merge lexical_cast from trunk:
* fixed #6717 (now lexical_cast won`t try to support non confirming swprintf)
* fixed #6670 (now using BOOST_NO_UNICODE_LITERALS macro to detect unicode literals support)
* rewritten Jamfile

[SVN r77804]
2012-04-07 07:52:23 +00:00
Antony Polukhin 93ee01ab69 Merge from trunk r77627 (merged lexical_cast optimizations for iterator_range<>, fixed performance regression, docs updated)
[SVN r77628]
2012-03-29 16:48:31 +00:00
Antony Polukhin a065884c59 Merge from trunk
* Much more tests
* Now numeric_cast (and lexical_cast) can be compiled with disabled exceptions
* Supress warning described in #6645 (implicit conversion shortens 64-bit value into a 32-bit value)
* Fixed compilation of lexical_cast with BOOST_NO_STD_LOCALE defined
* Documentation updates
* Case insensitive "NaN" and "Inf" parsing 
* Performance tests commit

[SVN r77288]
2012-03-10 07:31:36 +00:00
Antony Polukhin e51cf081b3 Merge from trunk (fixed #6251, fixed #6453, disabled some optimizations for sunCC #6462)
[SVN r76887]
2012-02-04 18:04:45 +00:00
Antony Polukhin 51a6aacb57 Merge from trunk r76357
(tiny documentation update)

[SVN r76358]
2012-01-08 09:25:04 +00:00
Antony Polukhin a2e4606e6c Merge from trunk r76354
(Fixes overflow detection, pointers casts)

[SVN r76355]
2012-01-08 09:05:35 +00:00
Antony Polukhin 82abf7b54f Merge from trunk r76232
[SVN r76233]
2011-12-30 15:18:00 +00:00
Antony Polukhin 7112ded1b9 Merge from trunk r75937
* fixed a lot of wchar_t errors
* Optimizations for boost::containers::basic_string
* More tests

[SVN r76062]
2011-12-19 15:19:43 +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
37 changed files with 7438 additions and 1547 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
;
+1018
View File
File diff suppressed because it is too large Load Diff
+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);
}
Executable → Regular
View File
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>
+231 -360
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-2012.
//
// 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,25 @@
#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 <algorithm> // std::transform
#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>
{
@@ -48,80 +58,74 @@ struct my_allocator : std::allocator<CharT>
{
};
// Test all 65536 values if true:
bool const lcast_test_small_integral_types_completely = false;
// lcast_integral_test_counter: use when testing all values of an integral
// types is not possible. Max. portable value is 32767.
int const lcast_integral_test_counter=1000;
using namespace boost;
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();
void test_conversion_from_wchar_t();
void test_conversion_to_wchar_t();
void test_conversion_from_wstring();
void test_conversion_to_wstring();
void test_bad_lexical_cast();
void test_no_whitespace_stripping();
void test_conversion_from_to_short();
void test_conversion_from_to_ushort();
void test_conversion_from_to_int();
void test_conversion_from_to_uint();
void test_conversion_from_to_long();
void test_conversion_from_to_ulong();
#ifdef LCAST_TEST_LONGLONG
void test_conversion_from_to_longlong();
void test_conversion_from_to_ulonglong();
#endif
void test_volatile_types_conversions();
#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
void test_traits();
void test_wtraits();
void test_allocator();
void test_wallocator();
#endif
void test_char_types_conversions();
void operators_overload_test();
#if !defined(BOOST_NO_CXX11_CHAR16_T) && !defined(BOOST_NO_CXX11_UNICODE_LITERALS)
void test_char16_conversions();
#endif
#if !defined(BOOST_NO_CXX11_CHAR32_T) && !defined(BOOST_NO_CXX11_UNICODE_LITERALS)
void test_char32_conversions();
#endif
void test_getting_pointer_to_function();
unit_test::test_suite *init_unit_test_suite(int, char *[])
{
unit_test_framework::test_suite *suite =
unit_test::test_suite *suite =
BOOST_TEST_SUITE("lexical_cast unit test");
suite->add(BOOST_TEST_CASE(test_conversion_to_char));
suite->add(BOOST_TEST_CASE(test_conversion_to_int));
suite->add(BOOST_TEST_CASE(test_conversion_to_double));
suite->add(BOOST_TEST_CASE(test_conversion_to_bool));
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_longlong));
suite->add(BOOST_TEST_CASE(&test_conversion_from_to_ulonglong));
#endif
#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
suite->add(BOOST_TEST_CASE(test_volatile_types_conversions));
#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));
#if !defined(BOOST_NO_CXX11_CHAR16_T) && !defined(BOOST_NO_CXX11_UNICODE_LITERALS)
suite->add(BOOST_TEST_CASE(&test_char16_conversions));
#endif
#if !defined(BOOST_NO_CXX11_CHAR32_T) && !defined(BOOST_NO_CXX11_UNICODE_LITERALS)
suite->add(BOOST_TEST_CASE(&test_char32_conversions));
#endif
suite->add(BOOST_TEST_CASE(&test_getting_pointer_to_function));
return suite;
}
@@ -184,19 +188,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(
@@ -212,9 +242,15 @@ void test_conversion_to_bool()
BOOST_CHECK_EQUAL(false, lexical_cast<bool>(0));
BOOST_CHECK_THROW(lexical_cast<bool>(123), bad_lexical_cast);
BOOST_CHECK_EQUAL(true, lexical_cast<bool>(1.0));
BOOST_CHECK_THROW(lexical_cast<bool>(-123), bad_lexical_cast);
BOOST_CHECK_EQUAL(false, lexical_cast<bool>(0.0));
BOOST_CHECK_THROW(lexical_cast<bool>(1234), bad_lexical_cast);
#if !defined(_CRAYC)
// Looks like a bug in CRAY compiler (throws bad_lexical_cast)
// TODO: localize the bug and report it to developers.
BOOST_CHECK_EQUAL(true, lexical_cast<bool>(true));
BOOST_CHECK_EQUAL(false, lexical_cast<bool>(false));
#endif
BOOST_CHECK_EQUAL(true, lexical_cast<bool>("1"));
BOOST_CHECK_EQUAL(false, lexical_cast<bool>("0"));
BOOST_CHECK_THROW(lexical_cast<bool>(""), bad_lexical_cast);
@@ -223,10 +259,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()
@@ -260,17 +310,9 @@ void test_conversion_from_to_wchar_t_alias()
BOOST_CHECK_EQUAL(std::string("123"), lexical_cast<std::string>(123ul));
}
void test_conversion_to_pointer()
{
BOOST_CHECK_THROW(lexical_cast<char *>("Test"), bad_lexical_cast);
#ifndef DISABLE_WIDE_CHAR_SUPPORT
BOOST_CHECK_THROW(lexical_cast<wchar_t *>("Test"), bad_lexical_cast);
#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 +345,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 +367,13 @@ 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
BOOST_CHECK(true);
}
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,18 +386,18 @@ 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
BOOST_CHECK(true);
}
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));
BOOST_CHECK(L"123" == lexical_cast<std::wstring>(123));
BOOST_CHECK(L"1.23" == lexical_cast<std::wstring>(1.23));
BOOST_CHECK(L"1.111111111" == lexical_cast<std::wstring>(1.111111111));
BOOST_CHECK(L"1" == lexical_cast<std::wstring>(true));
BOOST_CHECK(L"0" == lexical_cast<std::wstring>(false));
#if !defined(BOOST_NO_INTRINSIC_WCHAR_T)
@@ -368,7 +411,8 @@ 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
BOOST_CHECK(true);
}
void test_bad_lexical_cast()
@@ -392,306 +436,18 @@ void test_no_whitespace_stripping()
BOOST_CHECK_THROW(lexical_cast<int>("123 "), bad_lexical_cast);
}
// Replace "-,999" with "-999".
template<class CharT>
std::basic_string<CharT> to_str_gcc_workaround(std::basic_string<CharT> str)
void test_volatile_types_conversions()
{
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);
volatile int i1 = 100000;
BOOST_CHECK_EQUAL("100000", boost::lexical_cast<std::string>(i1));
if(np.grouping().empty())
return str;
volatile const int i2 = 100000;
BOOST_CHECK_EQUAL("100000", boost::lexical_cast<std::string>(i2));
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;
volatile const long int i3 = 1000000;
BOOST_CHECK_EQUAL("1000000", boost::lexical_cast<std::string>(i3));
}
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, class CharT>
void test_conversion_from_integral_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>
void test_conversion_from_integral_to_integral()
{
T t = 0;
BOOST_CHECK(lexical_cast<T>(t) == t);
// Next two variables are used to supress warnings.
int st = 32767; unsigned int ut = st;
t = st;
BOOST_CHECK(lexical_cast<short>(t) == st);
BOOST_CHECK(lexical_cast<unsigned short>(t) == ut);
BOOST_CHECK(lexical_cast<int>(t) == st);
BOOST_CHECK(lexical_cast<unsigned int>(t) == ut);
BOOST_CHECK(lexical_cast<long>(t) == st);
BOOST_CHECK(lexical_cast<unsigned long>(t) == ut);
t = (std::numeric_limits<T>::max)();
BOOST_CHECK(lexical_cast<T>(t) == t);
t = (std::numeric_limits<T>::min)();
BOOST_CHECK(lexical_cast<T>(t) == t);
}
template<class T, class CharT>
void test_conversion_from_integral_to_string(CharT)
{
typedef std::numeric_limits<T> limits;
typedef std::basic_string<CharT> string_type;
T t;
t = (limits::min)();
BOOST_CHECK(lexical_cast<string_type>(t) == to_str<CharT>(t));
t = (limits::max)();
BOOST_CHECK(lexical_cast<string_type>(t) == to_str<CharT>(t));
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)
BOOST_CHECK(lexical_cast<string_type>(t) == to_str<CharT>(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;
unsigned int i;
// Test values around min:
t = min_val;
for(i = 0; i < counter; ++i, ++t)
BOOST_CHECK(lexical_cast<string_type>(t) == to_str<CharT>(t));
// Test values around max:
t = max_val;
for(i = 0; i < counter; ++i, --t)
BOOST_CHECK(lexical_cast<string_type>(t) == to_str<CharT>(t));
// Test values around zero:
if(limits::is_signed)
for(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, ...
T ten_power = 100;
for(int e = 2; e <= limits::digits10; ++e, ten_power *= 10)
{
// ten_power + 100 probably never overflows
for(t = ten_power - 100; t != ten_power + 100; ++t)
BOOST_CHECK(lexical_cast<string_type>(t) == to_str<CharT>(t));
}
}
}
template<class T, class CharT>
void test_conversion_from_string_to_integral(CharT)
{
typedef std::numeric_limits<T> limits;
T t;
t = (limits::min)();
BOOST_CHECK(lexical_cast<T>(to_str<CharT>(t)) == t);
t = (limits::max)();
BOOST_CHECK(lexical_cast<T>(to_str<CharT>(t)) == t);
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)
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;
unsigned int i;
// Test values around min:
t = min_val;
for(i = 0; i < counter; ++i, ++t)
BOOST_CHECK(lexical_cast<T>(to_str<CharT>(t)) == t);
// Test values around max:
t = max_val;
for(i = 0; i < counter; ++i, --t)
BOOST_CHECK(lexical_cast<T>(to_str<CharT>(t)) == t);
// Test values around zero:
if(limits::is_signed)
for(t = -counter; t < static_cast<T>(counter); ++t)
BOOST_CHECK(lexical_cast<T>(to_str<CharT>(t)) == t);
// Test values around 100, 1000, 10000, ...
T ten_power = 100;
for(int e = 2; e <= limits::digits10; ++e, ten_power *= 10)
{
// ten_power + 100 probably never overflows
for(t = ten_power - 100; t != ten_power + 100; ++t)
BOOST_CHECK(lexical_cast<T>(to_str<CharT>(t)) == t);
}
}
}
template<class T>
void test_conversion_from_to_integral_for_locale()
{
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)
test_conversion_from_integral_to_string<T>(L'0');
test_conversion_from_string_to_integral<T>(L'0');
#endif
}
struct restore_oldloc
{
std::locale oldloc;
~restore_oldloc() { std::locale::global(oldloc); }
};
template<class T>
void test_conversion_from_to_integral()
{
char const zero = '0';
signed char const szero = '0';
unsigned char const uzero = '0';
test_conversion_from_integral_to_char<T>(zero);
test_conversion_from_integral_to_char<T>(szero);
test_conversion_from_integral_to_char<T>(uzero);
#if !defined(DISABLE_WIDE_CHAR_SUPPORT) && !defined(BOOST_NO_INTRINSIC_WCHAR_T)
wchar_t const wzero = L'0';
test_conversion_from_integral_to_char<T>(wzero);
#endif
// test_conversion_from_to_integral_for_locale
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_integral_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_integral_for_locale<T>();
if(grouping1.empty() && grouping2.empty())
BOOST_TEST_MESSAGE("Formatting with thousands_sep has not been tested");
}
void test_conversion_from_to_short()
{
test_conversion_from_to_integral<short>();
}
void test_conversion_from_to_ushort()
{
test_conversion_from_to_integral<unsigned short>();
}
void test_conversion_from_to_int()
{
test_conversion_from_to_integral<int>();
}
void test_conversion_from_to_uint()
{
test_conversion_from_to_integral<unsigned int>();
}
void test_conversion_from_to_ulong()
{
test_conversion_from_to_integral<unsigned long>();
}
void test_conversion_from_to_long()
{
test_conversion_from_to_integral<long>();
}
#if defined(BOOST_HAS_LONG_LONG)
void test_conversion_from_to_longlong()
{
test_conversion_from_to_integral<boost::long_long_type>();
}
void test_conversion_from_to_ulonglong()
{
test_conversion_from_to_integral<boost::ulong_long_type>();
}
#elif defined(LCAST_TEST_LONGLONG)
void test_conversion_from_to_longlong()
{
test_conversion_from_to_integral<__int64>();
}
void test_conversion_from_to_ulonglong()
{
test_conversion_from_to_integral<unsigned __int64>();
}
#endif
#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
void test_traits()
{
@@ -717,6 +473,11 @@ void test_wtraits()
void test_allocator()
{
// Following test cause compilation error on MSVC2012:
// (Reason: cannot convert from 'std::_Wrap_alloc<_Alloc>' to 'const my_allocator<CharT>')
//
// MSVC developer is notified about this issue
#if !defined(_MSC_VER) || (_MSC_VER < 1700)
typedef std::basic_string< char
, std::char_traits<char>
, my_allocator<char>
@@ -729,10 +490,16 @@ void test_allocator()
BOOST_CHECK(boost::lexical_cast<my_string>(1) == "1");
BOOST_CHECK(boost::lexical_cast<my_string>("s") == s);
BOOST_CHECK(boost::lexical_cast<my_string>(std::string("s")) == s);
#endif
}
void test_wallocator()
{
// Following test cause compilation error on MSVC2012:
// (Reason: cannot convert from 'std::_Wrap_alloc<_Alloc>' to 'const my_allocator<CharT>')
//
// MSVC developer is notified about this issue
#if !defined(_MSC_VER) || (_MSC_VER < 1700)
typedef std::basic_string< wchar_t
, std::char_traits<wchar_t>
, my_allocator<wchar_t>
@@ -745,7 +512,111 @@ void test_wallocator()
BOOST_CHECK(boost::lexical_cast<my_string>(1) == L"1");
BOOST_CHECK(boost::lexical_cast<my_string>(L"s") == s);
BOOST_CHECK(boost::lexical_cast<my_string>(std::wstring(L"s")) == s);
#endif
}
#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);
}
#if !defined(BOOST_NO_CXX11_CHAR16_T) && !defined(BOOST_NO_CXX11_UNICODE_LITERALS)
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
#if !defined(BOOST_NO_CXX11_CHAR16_T) && !defined(BOOST_NO_CXX11_UNICODE_LITERALS)
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
void test_getting_pointer_to_function()
{
// Just checking that &lexical_cast<To, From> is not ambiguous
typedef char char_arr[4];
typedef int(*f1)(const char_arr&);
f1 p1 = &boost::lexical_cast<int, char_arr>;
BOOST_CHECK(p1);
typedef int(*f2)(const std::string&);
f2 p2 = &boost::lexical_cast<int, std::string>;
BOOST_CHECK(p2);
typedef std::string(*f3)(const int&);
f3 p3 = &boost::lexical_cast<std::string, int>;
BOOST_CHECK(p3);
std::vector<int> values;
std::vector<std::string> ret;
std::transform(values.begin(), values.end(), ret.begin(), boost::lexical_cast<std::string, int>);
}
+2 -1
View File
@@ -28,7 +28,7 @@ using namespace boost;
using std::cout;
int test_main( int argc, char * argv[] )
int test_main( int , char * [] )
{
# ifdef NDEBUG
@@ -96,5 +96,6 @@ int test_main( int argc, char * argv[] )
{ cout<<"caught bad_numeric_cast #5\n"; caught_exception = true; }
BOOST_CHECK ( caught_exception );
(void)ul; // Supressing GCC warning about set but unused wariable
return 0 ;
}
+29
View File
@@ -0,0 +1,29 @@
#==============================================================================
# Copyright (c) 2012 Antony Polukhin
#
# 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)
#==============================================================================
# performance tests
import testing ;
import path ;
path-constant TEST_DIR : . ;
project performance/test
: source-location ./
: requirements
# <library>/boost/chrono//boost_chrono
# <library>/boost/system//boost_system
<link>static
<target-os>freebsd:<linkflags>"-lrt"
<target-os>linux:<linkflags>"-lrt"
<toolset>gcc:<cxxflags>-fvisibility=hidden
<toolset>intel-linux:<cxxflags>-fvisibility=hidden
<toolset>sun:<cxxflags>-xldscope=hidden
: default-build release
;
run performance_test.cpp : $(TEST_DIR) ;
+369
View File
@@ -0,0 +1,369 @@
// (C) Copyright Antony Polukhin 2012.
// 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)
// See http://www.boost.org/libs/config for most recent version.
//
// Testing lexical_cast<> performance
//
#define BOOST_ERROR_CODE_HEADER_ONLY
#define BOOST_CHRONO_HEADER_ONLY
#include <boost/lexical_cast.hpp>
#include <boost/chrono.hpp>
#include <fstream>
#include <cstring>
#include <boost/container/string.hpp>
// File to output data
std::fstream fout;
namespace boost {
inline std::istream& operator>> (std::istream& in, boost::array<char,50>& res) {
in >> res.begin();
return in;
}
}
template <class OutT, class InT>
static inline void test_lexical(const InT& in_val) {
OutT out_val = boost::lexical_cast<OutT>(in_val);
(void)out_val;
}
template <class OutT, class InT>
static inline void test_ss_constr(const InT& in_val) {
OutT out_val;
std::stringstream ss;
ss << in_val;
if (ss.fail()) throw std::logic_error("descr");
ss >> out_val;
if (ss.fail()) throw std::logic_error("descr");
}
template <class OutT, class CharT, std::size_t N>
static inline void test_ss_constr(const boost::array<CharT, N>& in_val) {
OutT out_val;
std::stringstream ss;
ss << in_val.begin();
if (ss.fail()) throw std::logic_error("descr");
ss >> out_val;
if (ss.fail()) throw std::logic_error("descr");
}
template <class OutT, class StringStreamT, class CharT, std::size_t N>
static inline void test_ss_noconstr(StringStreamT& ss, const boost::array<CharT, N>& in_val) {
OutT out_val;
ss << in_val.begin(); // ss is an instance of std::stringstream
if (ss.fail()) throw std::logic_error("descr");
ss >> out_val;
if (ss.fail()) throw std::logic_error("descr");
/* reseting std::stringstream to use it again */
ss.str(std::string());
ss.clear();
}
template <class OutT, class StringStreamT, class InT>
static inline void test_ss_noconstr(StringStreamT& ss, const InT& in_val) {
OutT out_val;
ss << in_val; // ss is an instance of std::stringstream
if (ss.fail()) throw std::logic_error("descr");
ss >> out_val;
if (ss.fail()) throw std::logic_error("descr");
/* reseting std::stringstream to use it again */
ss.str(std::string());
ss.clear();
}
struct structure_sprintf {
template <class OutT, class BufferT, class InT>
static inline void test(BufferT* buffer, const InT& in_val, const char* const conv) {
sprintf(buffer, conv, in_val);
OutT out_val(buffer);
}
template <class OutT, class BufferT>
static inline void test(BufferT* buffer, const std::string& in_val, const char* const conv) {
sprintf(buffer, conv, in_val.c_str());
OutT out_val(buffer);
}
};
struct structure_sscanf {
template <class OutT, class BufferT, class CharT, std::size_t N>
static inline void test(BufferT* /*buffer*/, const boost::array<CharT, N>& in_val, const char* const conv) {
OutT out_val;
sscanf(in_val.cbegin(), conv, &out_val);
}
template <class OutT, class BufferT, class InT>
static inline void test(BufferT* /*buffer*/, const InT& in_val, const char* const conv) {
OutT out_val;
sscanf(reinterpret_cast<const char*>(in_val), conv, &out_val);
}
template <class OutT, class BufferT>
static inline void test(BufferT* /*buffer*/, const std::string& in_val, const char* const conv) {
OutT out_val;
sscanf(in_val.c_str(), conv, &out_val);
}
template <class OutT, class BufferT>
static inline void test(BufferT* /*buffer*/, const boost::iterator_range<const char*>& in_val, const char* const conv) {
OutT out_val;
sscanf(in_val.begin(), conv, &out_val);
}
};
struct structure_fake {
template <class OutT, class BufferT, class InT>
static inline void test(BufferT* /*buffer*/, const InT& /*in_val*/, const char* const /*conv*/) {}
};
static const int fake_test_value = 9999;
template <class T>
static inline void min_fancy_output(T v1, T v2, T v3, T v4) {
const char beg_mark[] = "!!! *";
const char end_mark[] = "* !!!";
const char no_mark[] = "";
unsigned int res = 4;
if (v1 < v2 && v1 < v3 && v1 < v4) res = 1;
if (v2 < v1 && v2 < v3 && v2 < v4) res = 2;
if (v3 < v1 && v3 < v2 && v3 < v4) res = 3;
fout << "[ "
<< (res == 1 ? beg_mark : no_mark)
;
if (v1) fout << v1;
else fout << "<1";
fout << (res == 1 ? end_mark : no_mark)
<< " ][ "
<< (res == 2 ? beg_mark : no_mark)
;
if (v2) fout << v2;
else fout << "<1";
fout << (res == 2 ? end_mark : no_mark)
<< " ][ "
<< (res == 3 ? beg_mark : no_mark)
;
if (v3) fout << v3;
else fout << "<1";
fout << (res == 3 ? end_mark : no_mark)
<< " ][ "
<< (res == 4 ? beg_mark : no_mark)
;
if (!v4) fout << "<1";
else if (v4 == fake_test_value) fout << "---";
else fout << v4;
fout
<< (res == 4 ? end_mark : no_mark)
<< " ]";
}
template <unsigned int IetartionsCountV, class ToT, class SprintfT, class FromT>
static inline void perf_test_impl(const FromT& in_val, const char* const conv) {
typedef boost::chrono::steady_clock test_clock;
test_clock::time_point start;
typedef boost::chrono::milliseconds duration_t;
duration_t lexical_cast_time, ss_constr_time, ss_noconstr_time, printf_time;
start = test_clock::now();
for (unsigned int i = 0; i < IetartionsCountV; ++i) {
test_lexical<ToT>(in_val);
test_lexical<ToT>(in_val);
test_lexical<ToT>(in_val);
test_lexical<ToT>(in_val);
}
lexical_cast_time = boost::chrono::duration_cast<duration_t>(test_clock::now() - start);
start = test_clock::now();
for (unsigned int i = 0; i < IetartionsCountV; ++i) {
test_ss_constr<ToT>(in_val);
test_ss_constr<ToT>(in_val);
test_ss_constr<ToT>(in_val);
test_ss_constr<ToT>(in_val);
}
ss_constr_time = boost::chrono::duration_cast<duration_t>(test_clock::now() - start);
std::stringstream ss;
start = test_clock::now();
for (unsigned int i = 0; i < IetartionsCountV; ++i) {
test_ss_noconstr<ToT>(ss, in_val);
test_ss_noconstr<ToT>(ss, in_val);
test_ss_noconstr<ToT>(ss, in_val);
test_ss_noconstr<ToT>(ss, in_val);
}
ss_noconstr_time = boost::chrono::duration_cast<duration_t>(test_clock::now() - start);
char buffer[128];
start = test_clock::now();
for (unsigned int i = 0; i < IetartionsCountV; ++i) {
SprintfT::template test<ToT>(buffer, in_val, conv);
SprintfT::template test<ToT>(buffer, in_val, conv);
SprintfT::template test<ToT>(buffer, in_val, conv);
SprintfT::template test<ToT>(buffer, in_val, conv);
}
printf_time = boost::chrono::duration_cast<duration_t>(test_clock::now() - start);
min_fancy_output(
lexical_cast_time.count(),
ss_constr_time.count(),
ss_noconstr_time.count(),
boost::is_same<SprintfT, structure_fake>::value ? fake_test_value : printf_time.count()
);
}
template <class ToT, class SprintfT, class FromT>
static inline void perf_test(const std::string& test_name, const FromT& in_val, const char* const conv) {
const unsigned int ITERATIONSCOUNT = 100000;
fout << " [[ " << test_name << " ]";
perf_test_impl<ITERATIONSCOUNT/4, ToT, SprintfT>(in_val, conv);
fout << "]\n";
}
template <class ConverterT>
void string_like_test_set(const std::string& from) {
typedef structure_sscanf ssc_t;
ConverterT conv;
perf_test<char, ssc_t>(from + "->char", conv("c"), "%c");
perf_test<signed char, ssc_t>(from + "->signed char", conv("c"), "%hhd");
perf_test<unsigned char, ssc_t>(from + "->unsigned char", conv("c"), "%hhu");
perf_test<int, ssc_t>(from + "->int", conv("100"), "%d");
perf_test<short, ssc_t>(from + "->short", conv("100"), "%hd");
perf_test<long int, ssc_t>(from + "->long int", conv("100"), "%ld");
perf_test<boost::long_long_type, ssc_t>(from + "->long long", conv("100"), "%lld");
perf_test<unsigned int, ssc_t>(from + "->unsigned int", conv("100"), "%u");
perf_test<unsigned short, ssc_t>(from + "->unsigned short", conv("100"), "%hu");
perf_test<unsigned long int, ssc_t>(from + "->unsigned long int", conv("100"), "%lu");
perf_test<boost::ulong_long_type, ssc_t>(from + "->unsigned long long", conv("100"), "%llu");
// perf_test<bool, ssc_t>(from + "->bool", conv("1"), "%");
perf_test<float, ssc_t>(from + "->float", conv("1.123"), "%f");
perf_test<double, ssc_t>(from + "->double", conv("1.123"), "%lf");
perf_test<long double, ssc_t>(from + "->long double", conv("1.123"), "%Lf");
perf_test<boost::array<char, 50>, ssc_t>(from + "->array<char, 50>", conv("1.123"), "%s");
perf_test<std::string, structure_fake>(from + "->string", conv("string"), "%Lf");
perf_test<boost::container::string, structure_fake>(from + "->container::string"
, conv("string"), "%Lf");
}
struct to_string_conv {
std::string operator()(const char* const c) const {
return c;
}
};
struct to_char_conv {
const char* operator()(const char* const c) const {
return c;
}
};
struct to_uchar_conv {
const unsigned char* operator()(const char* const c) const {
return reinterpret_cast<const unsigned char*>(c);
}
};
struct to_schar_conv {
const signed char* operator()(const char* const c) const {
return reinterpret_cast<const signed char*>(c);
}
};
struct to_iterator_range {
boost::iterator_range<const char*> operator()(const char* const c) const {
return boost::make_iterator_range(c, c + std::strlen(c));
}
};
struct to_array_50 {
boost::array<char, 50> operator()(const char* const c) const {
boost::array<char, 50> ret;
std::strcpy(ret.begin(), c);
return ret;
}
};
int main(int argc, char** argv) {
BOOST_ASSERT(argc >= 2);
std::string output_path(argv[1]);
output_path += "/results.txt";
fout.open(output_path.c_str(), std::fstream::in | std::fstream::out | std::fstream::app);
BOOST_ASSERT(fout);
fout << "[section " << BOOST_COMPILER << "]\n"
<< "[table:id Performance Table ( "<< BOOST_COMPILER << ")\n"
<< "[[From->To] [lexical_cast] [std::stringstream with construction] "
<< "[std::stringstream without construction][scanf/printf]]\n";
// From std::string to ...
string_like_test_set<to_string_conv>("string");
// From ... to std::string
perf_test<std::string, structure_sprintf>("string->char", 'c', "%c");
perf_test<std::string, structure_sprintf>("string->signed char", static_cast<signed char>('c'), "%hhd");
perf_test<std::string, structure_sprintf>("string->unsigned char", static_cast<unsigned char>('c'), "%hhu");
perf_test<std::string, structure_sprintf>("int->string", 100, "%d");
perf_test<std::string, structure_sprintf>("short->string", static_cast<short>(100), "%hd");
perf_test<std::string, structure_sprintf>("long int->string", 100l, "%ld");
perf_test<std::string, structure_sprintf>("long long->string", 100ll, "%lld");
perf_test<std::string, structure_sprintf>("unsigned int->string", static_cast<unsigned short>(100u), "%u");
perf_test<std::string, structure_sprintf>("unsigned short->string", 100u, "%hu");
perf_test<std::string, structure_sprintf>("unsigned long int->string", 100ul, "%lu");
perf_test<std::string, structure_sprintf>("unsigned long long->string", static_cast<boost::ulong_long_type>(100), "%llu");
// perf_test<bool, structure_sscanf>("bool->string", std::string("1"), "%");
perf_test<std::string, structure_sprintf>("float->string", 1.123f, "%f");
perf_test<std::string, structure_sprintf>("double->string", 1.123, "%lf");
perf_test<std::string, structure_sprintf>("long double->string", 1.123L, "%Lf");
string_like_test_set<to_char_conv>("char*");
string_like_test_set<to_uchar_conv>("unsigned char*");
string_like_test_set<to_schar_conv>("signed char*");
string_like_test_set<to_iterator_range>("iterator_range<char*>");
string_like_test_set<to_array_50>("array<char, 50>");
perf_test<int, structure_fake>("int->int", 100, "");
perf_test<double, structure_fake>("float->double", 100.0f, "");
perf_test<signed char, structure_fake>("char->signed char", 'c', "");
fout << "]\n"
<< "[endsect]\n\n";
return 0;
}
-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
)
+51 -19
View File
@@ -1,29 +1,61 @@
# Signals library
# Copyright (C) 2001-2003 Douglas Gregor
# Copyright (C) 2011-2012 Antony Polukhin
#
# 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)
#
# Permission to copy, use, sell and distribute this software is granted
# provided this copyright notice appears in all copies. Permission to modify
# the code and to distribute modified code is granted provided this copyright
# notice appears in all copies, and a notice that the code was modified is
# included with the copyright notice. This software is provided "as is"
# without express or implied warranty, and with no claim as to its suitability
# for any purpose.
# For more information, see http://www.boost.org/
# bring in rules for testing
import testing ;
import feature ;
project
: requirements
<library>/boost/test//boost_unit_test_framework
<link>static
<toolset>gcc-4.7:<cxxflags>-ftrapv
<toolset>gcc-4.6:<cxxflags>-ftrapv
<toolset>clang:<cxxflags>-ftrapv
;
# Thanks to Steven Watanabe for helping with <nowchar> feature
feature.feature nowchar : on :
composite optional propagated link-incompatible ;
feature.compose <nowchar>on : <cxxflags>/Zc:wchar_t- ;
test-suite conversion
: [ run implicit_cast.cpp ]
[ compile-fail implicit_cast_fail.cpp ]
[ run ../cast_test.cpp ]
[ run ../numeric_cast_test.cpp ]
[ run ../lexical_cast_test.cpp ../../test/build//boost_unit_test_framework/<link>static ]
[ 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 ../numeric_cast_test.cpp ]
[ run ../lexical_cast_test.cpp ]
[ run lexical_cast_loopback_test.cpp ]
[ run lexical_cast_abstract_test.cpp ]
[ run lexical_cast_noncopyable_test.cpp ]
[ run lexical_cast_vc8_bug_test.cpp ]
[ run lexical_cast_wchars_test.cpp ]
[ run lexical_cast_float_types_test.cpp ]
[ run lexical_cast_inf_nan_test.cpp ]
[ run lexical_cast_containers_test.cpp ]
[ run lexical_cast_empty_input_test.cpp ]
[ run lexical_cast_pointers_test.cpp ]
[ compile lexical_cast_typedefed_wchar_test.cpp : <toolset>msvc:<nowchar>on ]
[ run lexical_cast_typedefed_wchar_test_runtime.cpp : : : <toolset>msvc:<nowchar>on <toolset>msvc,<stdlib>stlport:<build>no ]
[ run lexical_cast_no_locale_test.cpp : : : <define>BOOST_NO_STD_LOCALE <define>BOOST_LEXICAL_CAST_ASSUME_C_LOCALE ]
[ run lexical_cast_no_exceptions_test.cpp : : : <define>BOOST_NO_EXCEPTIONS
<toolset>gcc-4.3:<cxxflags>-fno-exceptions
<toolset>gcc-4.4:<cxxflags>-fno-exceptions
<toolset>gcc-4.5:<cxxflags>-fno-exceptions
<toolset>gcc-4.6:<cxxflags>-fno-exceptions
<toolset>gcc-4.7:<cxxflags>-fno-exceptions
<toolset>gcc-4.8:<cxxflags>-fno-exceptions
<toolset>clang:<cxxflags>-fno-exceptions
]
[ run lexical_cast_iterator_range_test.cpp ]
[ run lexical_cast_arrays_test.cpp ]
[ run lexical_cast_integral_types_test.cpp ]
[ run lexical_cast_stream_detection_test.cpp ]
[ run lexical_cast_stream_traits_test.cpp ]
[ compile-fail lexical_cast_to_pointer_test.cpp ]
[ run lexical_cast_filesystem_test.cpp ../../filesystem/build//boost_filesystem/<link>static ]
;
+6
View File
@@ -28,5 +28,11 @@ int main()
type<foo> f = check_return(boost::implicit_cast<foo>("hello"));
type<long> z = check_return(boost::implicit_cast<long>(foo("hello")));
// warning supression:
(void)x;
(void)f;
(void)z;
return boost::report_errors();
}
+2
View File
@@ -19,4 +19,6 @@ struct foo
int test_main(int, char*[])
{
foo x = implicit_cast<foo>("foobar");
(void)x; // warning suppression.
return 0;
}
+2 -2
View File
@@ -28,7 +28,7 @@ void test_abstract();
unit_test::test_suite *init_unit_test_suite(int, char *[])
{
unit_test_framework::test_suite *suite =
unit_test::test_suite *suite =
BOOST_TEST_SUITE("lexical_cast unit test");
suite->add(BOOST_TEST_CASE(&test_abstract));
@@ -51,7 +51,7 @@ std::ostream &operator<<(std::ostream &O, const A &a)
{
a.out(O);
return O;
};
}
void test_abstract()
{
+375
View File
@@ -0,0 +1,375 @@
// Testing boost::lexical_cast with boost::container::string.
//
// See http://www.boost.org for most recent version, including documentation.
//
// Copyright Antony Polukhin, 2012.
//
// 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/lexical_cast.hpp>
#include <boost/test/unit_test.hpp>
#include <boost/array.hpp>
void testing_boost_array_output_conversion();
void testing_std_array_output_conversion();
void testing_boost_array_input_conversion();
void testing_std_array_input_conversion();
using namespace boost;
#if !defined(BOOST_NO_CXX11_CHAR16_T) && !defined(BOOST_NO_CXX11_UNICODE_LITERALS) && !defined(_LIBCPP_VERSION)
#define BOOST_LC_RUNU16
#endif
#if !defined(BOOST_NO_CXX11_CHAR32_T) && !defined(BOOST_NO_CXX11_UNICODE_LITERALS) && !defined(_LIBCPP_VERSION)
#define BOOST_LC_RUNU32
#endif
boost::unit_test::test_suite *init_unit_test_suite(int, char *[])
{
unit_test::test_suite *suite =
BOOST_TEST_SUITE("Testing boost::lexical_cast with boost::array and std::array");
suite->add(BOOST_TEST_CASE(testing_boost_array_output_conversion));
suite->add(BOOST_TEST_CASE(testing_std_array_output_conversion));
suite->add(BOOST_TEST_CASE(testing_boost_array_input_conversion));
suite->add(BOOST_TEST_CASE(testing_std_array_input_conversion));
return suite;
}
template <template <class, std::size_t> class ArrayT, class T>
static void testing_template_array_output_on_spec_value(T val)
{
typedef ArrayT<char, 300> arr_type;
typedef ArrayT<char, 1> short_arr_type;
typedef ArrayT<unsigned char, 300> uarr_type;
typedef ArrayT<unsigned char, 1> ushort_arr_type;
typedef ArrayT<signed char, 4> sarr_type;
typedef ArrayT<signed char, 3> sshort_arr_type;
std::string ethalon("100");
using namespace std;
{
arr_type res1 = lexical_cast<arr_type>(val);
BOOST_CHECK_EQUAL(&res1[0], ethalon);
const arr_type res2 = lexical_cast<arr_type>(val);
BOOST_CHECK_EQUAL(&res2[0], ethalon);
BOOST_CHECK_THROW(lexical_cast<short_arr_type>(val), boost::bad_lexical_cast);
}
{
uarr_type res1 = lexical_cast<uarr_type>(val);
BOOST_CHECK_EQUAL(reinterpret_cast<char*>(&res1[0]), ethalon);
const uarr_type res2 = lexical_cast<uarr_type>(val);
BOOST_CHECK_EQUAL(reinterpret_cast<const char*>(&res2[0]), ethalon);
BOOST_CHECK_THROW(lexical_cast<ushort_arr_type>(val), boost::bad_lexical_cast);
}
{
sarr_type res1 = lexical_cast<sarr_type>(val);
BOOST_CHECK_EQUAL(reinterpret_cast<char*>(&res1[0]), ethalon);
const sarr_type res2 = lexical_cast<sarr_type>(val);
BOOST_CHECK_EQUAL(reinterpret_cast<const char*>(&res2[0]), ethalon);
BOOST_CHECK_THROW(lexical_cast<sshort_arr_type>(val), boost::bad_lexical_cast);
}
#if !defined(BOOST_NO_STRINGSTREAM) && !defined(BOOST_NO_STD_WSTRING)
typedef ArrayT<wchar_t, 300> warr_type;
typedef ArrayT<wchar_t, 3> wshort_arr_type;
std::wstring wethalon(L"100");
{
warr_type res = lexical_cast<warr_type>(val);
BOOST_CHECK(&res[0] == wethalon);
}
{
const warr_type res = lexical_cast<warr_type>(val);
BOOST_CHECK(&res[0] == wethalon);
}
BOOST_CHECK_THROW(lexical_cast<wshort_arr_type>(val), boost::bad_lexical_cast);
#endif
#ifdef BOOST_LC_RUNU16
typedef ArrayT<char16_t, 300> u16arr_type;
typedef ArrayT<char16_t, 3> u16short_arr_type;
std::u16string u16ethalon(u"100");
{
u16arr_type res = lexical_cast<u16arr_type>(val);
BOOST_CHECK(&res[0] == u16ethalon);
}
{
const u16arr_type res = lexical_cast<u16arr_type>(val);
BOOST_CHECK(&res[0] == u16ethalon);
}
BOOST_CHECK_THROW(lexical_cast<u16short_arr_type>(val), boost::bad_lexical_cast);
#endif
#ifdef BOOST_LC_RUNU32
typedef ArrayT<char32_t, 300> u32arr_type;
typedef ArrayT<char32_t, 3> u32short_arr_type;
std::u32string u32ethalon(U"100");
{
u32arr_type res = lexical_cast<u32arr_type>(val);
BOOST_CHECK(&res[0] == u32ethalon);
}
{
const u32arr_type res = lexical_cast<u32arr_type>(val);
BOOST_CHECK(&res[0] == u32ethalon);
}
BOOST_CHECK_THROW(lexical_cast<u32short_arr_type>(val), boost::bad_lexical_cast);
#endif
}
template <template <class, std::size_t> class ArrayT>
static void testing_template_array_output_on_char_value()
{
typedef ArrayT<char, 300> arr_type;
typedef ArrayT<char, 1> short_arr_type;
typedef ArrayT<unsigned char, 300> uarr_type;
typedef ArrayT<unsigned char, 1> ushort_arr_type;
typedef ArrayT<signed char, 4> sarr_type;
typedef ArrayT<signed char, 3> sshort_arr_type;
const char val[] = "100";
std::string ethalon("100");
using namespace std;
{
arr_type res1 = lexical_cast<arr_type>(val);
BOOST_CHECK_EQUAL(&res1[0], ethalon);
const arr_type res2 = lexical_cast<arr_type>(val);
BOOST_CHECK_EQUAL(&res2[0], ethalon);
BOOST_CHECK_THROW(lexical_cast<short_arr_type>(val), boost::bad_lexical_cast);
}
{
uarr_type res1 = lexical_cast<uarr_type>(val);
BOOST_CHECK_EQUAL(reinterpret_cast<char*>(&res1[0]), ethalon);
const uarr_type res2 = lexical_cast<uarr_type>(val);
BOOST_CHECK_EQUAL(reinterpret_cast<const char*>(&res2[0]), ethalon);
BOOST_CHECK_THROW(lexical_cast<ushort_arr_type>(val), boost::bad_lexical_cast);
}
{
sarr_type res1 = lexical_cast<sarr_type>(val);
BOOST_CHECK_EQUAL(reinterpret_cast<char*>(&res1[0]), ethalon);
const sarr_type res2 = lexical_cast<sarr_type>(val);
BOOST_CHECK_EQUAL(reinterpret_cast<const char*>(&res2[0]), ethalon);
BOOST_CHECK_THROW(lexical_cast<sshort_arr_type>(val), boost::bad_lexical_cast);
}
#if !defined(BOOST_NO_STRINGSTREAM) && !defined(BOOST_NO_STD_WSTRING)
typedef ArrayT<wchar_t, 4> warr_type;
typedef ArrayT<wchar_t, 3> wshort_arr_type;
std::wstring wethalon(L"100");
{
warr_type res = lexical_cast<warr_type>(val);
BOOST_CHECK(&res[0] == wethalon);
warr_type res3 = lexical_cast<warr_type>(wethalon);
BOOST_CHECK(&res3[0] == wethalon);
}
{
const warr_type res = lexical_cast<warr_type>(val);
BOOST_CHECK(&res[0] == wethalon);
const warr_type res3 = lexical_cast<warr_type>(wethalon);
BOOST_CHECK(&res3[0] == wethalon);
}
BOOST_CHECK_THROW(lexical_cast<wshort_arr_type>(val), boost::bad_lexical_cast);
#endif
#ifdef BOOST_LC_RUNU16
typedef ArrayT<char16_t, 300> u16arr_type;
typedef ArrayT<char16_t, 3> u16short_arr_type;
std::u16string u16ethalon(u"100");
{
#ifdef BOOST_STL_SUPPORTS_NEW_UNICODE_LOCALES
u16arr_type res = lexical_cast<u16arr_type>(val);
BOOST_CHECK(&res[0] == u16ethalon);
#endif
u16arr_type res3 = lexical_cast<u16arr_type>(u16ethalon);
BOOST_CHECK(&res3[0] == u16ethalon);
}
{
#ifdef BOOST_STL_SUPPORTS_NEW_UNICODE_LOCALES
const u16arr_type res = lexical_cast<u16arr_type>(val);
BOOST_CHECK(&res[0] == u16ethalon);
#endif
const u16arr_type res3 = lexical_cast<u16arr_type>(u16ethalon);
BOOST_CHECK(&res3[0] == u16ethalon);
}
BOOST_CHECK_THROW(lexical_cast<u16short_arr_type>(val), boost::bad_lexical_cast);
#endif
#ifdef BOOST_LC_RUNU32
typedef ArrayT<char32_t, 300> u32arr_type;
typedef ArrayT<char32_t, 3> u32short_arr_type;
std::u32string u32ethalon(U"100");
{
#ifdef BOOST_STL_SUPPORTS_NEW_UNICODE_LOCALES
u32arr_type res = lexical_cast<u32arr_type>(val);
BOOST_CHECK(&res[0] == u32ethalon);
#endif
u32arr_type res3 = lexical_cast<u32arr_type>(u32ethalon);
BOOST_CHECK(&res3[0] == u32ethalon);
}
{
#ifdef BOOST_STL_SUPPORTS_NEW_UNICODE_LOCALES
const u32arr_type res = lexical_cast<u32arr_type>(val);
BOOST_CHECK(&res[0] == u32ethalon);
#endif
const u32arr_type res3 = lexical_cast<u32arr_type>(u32ethalon);
BOOST_CHECK(&res3[0] == u32ethalon);
}
BOOST_CHECK_THROW(lexical_cast<u32short_arr_type>(val), boost::bad_lexical_cast);
#endif
}
void testing_boost_array_output_conversion()
{
testing_template_array_output_on_char_value<boost::array>();
testing_template_array_output_on_spec_value<boost::array>(100);
testing_template_array_output_on_spec_value<boost::array>(static_cast<short>(100));
testing_template_array_output_on_spec_value<boost::array>(static_cast<unsigned short>(100));
testing_template_array_output_on_spec_value<boost::array>(static_cast<unsigned int>(100));
}
void testing_std_array_output_conversion()
{
#ifndef BOOST_NO_CXX11_HDR_ARRAY
testing_template_array_output_on_char_value<std::array>();
testing_template_array_output_on_spec_value<std::array>(100);
testing_template_array_output_on_spec_value<std::array>(static_cast<short>(100));
testing_template_array_output_on_spec_value<std::array>(static_cast<unsigned short>(100));
testing_template_array_output_on_spec_value<std::array>(static_cast<unsigned int>(100));
#endif
BOOST_CHECK(true);
}
template <template <class, std::size_t> class ArrayT>
static void testing_generic_array_input_conversion()
{
{
ArrayT<char, 4> var_zero_terminated = {{ '1', '0', '0', '\0'}};
BOOST_CHECK_EQUAL(lexical_cast<std::string>(var_zero_terminated), "100");
BOOST_CHECK_EQUAL(lexical_cast<int>(var_zero_terminated), 100);
ArrayT<char, 3> var_none_terminated = {{ '1', '0', '0'}};
BOOST_CHECK_EQUAL(lexical_cast<std::string>(var_none_terminated), "100");
BOOST_CHECK_EQUAL(lexical_cast<short>(var_none_terminated), static_cast<short>(100));
ArrayT<const char, 4> var_zero_terminated_const_char = {{ '1', '0', '0', '\0'}};
BOOST_CHECK_EQUAL(lexical_cast<std::string>(var_zero_terminated_const_char), "100");
ArrayT<const char, 3> var_none_terminated_const_char = {{ '1', '0', '0'}};
BOOST_CHECK_EQUAL(lexical_cast<std::string>(var_none_terminated_const_char), "100");
const ArrayT<char, 4> var_zero_terminated_const_var = {{ '1', '0', '0', '\0'}};
BOOST_CHECK_EQUAL(lexical_cast<std::string>(var_zero_terminated_const_var), "100");
const ArrayT<char, 3> var_none_terminated_const_var = {{ '1', '0', '0'}};
BOOST_CHECK_EQUAL(lexical_cast<std::string>(var_none_terminated_const_var), "100");
const ArrayT<const char, 4> var_zero_terminated_const_var_const_char = {{ '1', '0', '0', '\0'}};
BOOST_CHECK_EQUAL(lexical_cast<std::string>(var_zero_terminated_const_var_const_char), "100");
const ArrayT<const char, 3> var_none_terminated_const_var_const_char = {{ '1', '0', '0'}};
BOOST_CHECK_EQUAL(lexical_cast<std::string>(var_none_terminated_const_var_const_char), "100");
BOOST_CHECK_EQUAL(lexical_cast<int>(var_none_terminated_const_var_const_char), 100);
}
{
const ArrayT<const unsigned char, 4> var_zero_terminated_const_var_const_char = {{ '1', '0', '0', '\0'}};
BOOST_CHECK_EQUAL(lexical_cast<std::string>(var_zero_terminated_const_var_const_char), "100");
const ArrayT<const unsigned char, 3> var_none_terminated_const_var_const_char = {{ '1', '0', '0'}};
BOOST_CHECK_EQUAL(lexical_cast<std::string>(var_none_terminated_const_var_const_char), "100");
}
{
const ArrayT<const signed char, 4> var_zero_terminated_const_var_const_char = {{ '1', '0', '0', '\0'}};
BOOST_CHECK_EQUAL(lexical_cast<std::string>(var_zero_terminated_const_var_const_char), "100");
const ArrayT<const signed char, 3> var_none_terminated_const_var_const_char = {{ '1', '0', '0'}};
BOOST_CHECK_EQUAL(lexical_cast<std::string>(var_none_terminated_const_var_const_char), "100");
BOOST_CHECK_EQUAL(lexical_cast<unsigned int>(var_none_terminated_const_var_const_char), 100u);
}
#if !defined(BOOST_NO_STRINGSTREAM) && !defined(BOOST_NO_STD_WSTRING)
{
const ArrayT<const wchar_t, 4> var_zero_terminated_const_var_const_char = {{ L'1', L'0', L'0', L'\0'}};
BOOST_CHECK(lexical_cast<std::wstring>(var_zero_terminated_const_var_const_char) == L"100");
const ArrayT<const wchar_t, 3> var_none_terminated_const_var_const_char = {{ L'1', L'0', L'0'}};
BOOST_CHECK(lexical_cast<std::wstring>(var_none_terminated_const_var_const_char) == L"100");
BOOST_CHECK_EQUAL(lexical_cast<int>(var_none_terminated_const_var_const_char), 100);
}
#endif
#ifdef BOOST_LC_RUNU16
{
const ArrayT<const char16_t, 4> var_zero_terminated_const_var_const_char = {{ u'1', u'0', u'0', u'\0'}};
BOOST_CHECK(lexical_cast<std::u16string>(var_zero_terminated_const_var_const_char) == u"100");
BOOST_CHECK_EQUAL(lexical_cast<unsigned short>(var_zero_terminated_const_var_const_char), static_cast<unsigned short>(100));
const ArrayT<const char16_t, 3> var_none_terminated_const_var_const_char = {{ u'1', u'0', u'0'}};
BOOST_CHECK(lexical_cast<std::u16string>(var_none_terminated_const_var_const_char) == u"100");
}
#endif
#ifdef BOOST_LC_RUNU32
{
const ArrayT<const char32_t, 4> var_zero_terminated_const_var_const_char = {{ U'1', U'0', U'0', U'\0'}};
BOOST_CHECK(lexical_cast<std::u32string>(var_zero_terminated_const_var_const_char) == U"100");
const ArrayT<const char32_t, 3> var_none_terminated_const_var_const_char = {{ U'1', U'0', U'0'}};
BOOST_CHECK(lexical_cast<std::u32string>(var_none_terminated_const_var_const_char) == U"100");
BOOST_CHECK_EQUAL(lexical_cast<int>(var_none_terminated_const_var_const_char), 100);
}
#endif
}
void testing_boost_array_input_conversion()
{
testing_generic_array_input_conversion<boost::array>();
}
void testing_std_array_input_conversion()
{
#ifndef BOOST_NO_CXX11_HDR_ARRAY
testing_generic_array_input_conversion<std::array>();
#endif
BOOST_CHECK(true);
}
+83
View File
@@ -0,0 +1,83 @@
// Testing boost::lexical_cast with boost::container::string.
//
// 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/lexical_cast.hpp>
#include <boost/test/unit_test.hpp>
#include <boost/container/string.hpp>
void testing_boost_containers_basic_string();
void testing_boost_containers_string_std_string();
void testing_boost_containers_string_widening();
using namespace boost;
boost::unit_test::test_suite *init_unit_test_suite(int, char *[])
{
unit_test::test_suite *suite =
BOOST_TEST_SUITE("Testing boost::lexical_cast with boost::container::string");
suite->add(BOOST_TEST_CASE(testing_boost_containers_basic_string));
suite->add(BOOST_TEST_CASE(testing_boost_containers_string_std_string));
suite->add(BOOST_TEST_CASE(testing_boost_containers_string_widening));
return suite;
}
void testing_boost_containers_basic_string()
{
BOOST_CHECK("100" == lexical_cast<boost::container::string>("100"));
BOOST_CHECK(L"100" == lexical_cast<boost::container::wstring>(L"100"));
BOOST_CHECK("100" == lexical_cast<boost::container::string>(100));
boost::container::string str("1000");
BOOST_CHECK(1000 == lexical_cast<int>(str));
}
#if defined(BOOST_NO_STRINGSTREAM) || defined(BOOST_NO_STD_WSTRING)
#define BOOST_LCAST_NO_WCHAR_T
#endif
void testing_boost_containers_string_std_string()
{
std::string std_str("std_str");
boost::container::string boost_str("boost_str");
BOOST_CHECK(boost::lexical_cast<std::string>(boost_str) == "boost_str");
BOOST_CHECK(boost::lexical_cast<boost::container::string>(std_str) == "std_str");
#ifndef BOOST_LCAST_NO_WCHAR_T
std::wstring std_wstr(L"std_wstr");
boost::container::wstring boost_wstr(L"boost_wstr");
BOOST_CHECK(boost::lexical_cast<std::wstring>(boost_wstr) == L"boost_wstr");
BOOST_CHECK(boost::lexical_cast<boost::container::wstring>(std_wstr) == L"std_wstr");
#endif
}
void testing_boost_containers_string_widening()
{
const char char_array[] = "Test string";
#ifndef BOOST_LCAST_NO_WCHAR_T
const wchar_t wchar_array[] = L"Test string";
BOOST_CHECK(boost::lexical_cast<boost::container::wstring>(char_array) == wchar_array);
#endif
#if !defined(BOOST_NO_CXX11_CHAR16_T) && !defined(BOOST_NO_CXX11_UNICODE_LITERALS) && defined(BOOST_STL_SUPPORTS_NEW_UNICODE_LOCALES)
const char16_t char16_array[] = u"Test string";
BOOST_CHECK(boost::lexical_cast<boost::container::basic_string<char16_t> >(char_array) == char16_array);
#endif
#if !defined(BOOST_NO_CXX11_CHAR32_T) && !defined(BOOST_NO_CXX11_UNICODE_LITERALS) && defined(BOOST_STL_SUPPORTS_NEW_UNICODE_LOCALES)
const char32_t char32_array[] = U"Test string";
BOOST_CHECK(boost::lexical_cast<boost::container::basic_string<char32_t> >(char_array) == char32_array);
#endif
}
+167
View File
@@ -0,0 +1,167 @@
// 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;
#if defined(BOOST_NO_STRINGSTREAM) || defined(BOOST_NO_STD_WSTRING)
#define BOOST_LCAST_NO_WCHAR_T
#endif
template <class T>
void do_test_on_empty_input(T& 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);
#ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS
BOOST_CHECK_THROW(lexical_cast<long double>(v), bad_lexical_cast);
#endif
BOOST_CHECK_THROW(lexical_cast<unsigned int>(v), bad_lexical_cast);
BOOST_CHECK_THROW(lexical_cast<unsigned short>(v), bad_lexical_cast);
#if defined(BOOST_HAS_LONG_LONG)
BOOST_CHECK_THROW(lexical_cast<boost::ulong_long_type>(v), bad_lexical_cast);
BOOST_CHECK_THROW(lexical_cast<boost::long_long_type>(v), bad_lexical_cast);
#elif defined(BOOST_HAS_MS_INT64)
BOOST_CHECK_THROW(lexical_cast<unsigned __int64>(v), bad_lexical_cast);
BOOST_CHECK_THROW(lexical_cast<__int64>(v), bad_lexical_cast);
#endif
}
void test_empty_iterator_range()
{
boost::iterator_range<char*> v;
do_test_on_empty_input(v);
BOOST_CHECK_EQUAL(lexical_cast<std::string>(v), std::string());
BOOST_CHECK_THROW(lexical_cast<char>(v), bad_lexical_cast);
BOOST_CHECK_THROW(lexical_cast<unsigned char>(v), bad_lexical_cast);
BOOST_CHECK_THROW(lexical_cast<signed char>(v), bad_lexical_cast);
boost::iterator_range<const char*> cv;
do_test_on_empty_input(cv);
BOOST_CHECK_EQUAL(lexical_cast<std::string>(cv), std::string());
BOOST_CHECK_THROW(lexical_cast<char>(cv), bad_lexical_cast);
BOOST_CHECK_THROW(lexical_cast<unsigned char>(cv), bad_lexical_cast);
BOOST_CHECK_THROW(lexical_cast<signed char>(cv), bad_lexical_cast);
const boost::iterator_range<const char*> ccv;
do_test_on_empty_input(ccv);
BOOST_CHECK_EQUAL(lexical_cast<std::string>(ccv), std::string());
BOOST_CHECK_THROW(lexical_cast<char>(ccv), bad_lexical_cast);
BOOST_CHECK_THROW(lexical_cast<unsigned char>(ccv), bad_lexical_cast);
BOOST_CHECK_THROW(lexical_cast<signed char>(ccv), bad_lexical_cast);
}
void test_empty_string()
{
std::string v;
do_test_on_empty_input(v);
BOOST_CHECK_THROW(lexical_cast<char>(v), bad_lexical_cast);
BOOST_CHECK_THROW(lexical_cast<unsigned char>(v), bad_lexical_cast);
BOOST_CHECK_THROW(lexical_cast<signed char>(v), bad_lexical_cast);
#ifndef BOOST_LCAST_NO_WCHAR_T
std::wstring vw;
do_test_on_empty_input(vw);
BOOST_CHECK_THROW(lexical_cast<wchar_t>(vw), bad_lexical_cast);
#endif
// Currently, no compiler and STL library fully support char16_t and char32_t
//#ifndef BOOST_NO_CXX11_CHAR16_T
// std::basic_string<char16_t> v16w;
// do_test_on_empty_input(v16w);
// BOOST_CHECK_THROW(lexical_cast<char16_t>(v16w), bad_lexical_cast);
//#endif
//#ifndef BOOST_NO_CXX11_CHAR32_T
// std::basic_string<char32_t> v32w;
// do_test_on_empty_input(v32w);
// BOOST_CHECK_THROW(lexical_cast<char32_t>(v32w), bad_lexical_cast);
//#endif
}
struct Escape
{
Escape(const std::string& s)
: str_(s)
{}
std::string str_;
};
inline std::ostream& operator<< (std::ostream& o, const Escape& rhs)
{
return o << rhs.str_;
}
void test_empty_user_class()
{
Escape v("");
do_test_on_empty_input(v);
BOOST_CHECK_THROW(lexical_cast<char>(v), bad_lexical_cast);
BOOST_CHECK_THROW(lexical_cast<unsigned char>(v), bad_lexical_cast);
BOOST_CHECK_THROW(lexical_cast<signed char>(v), bad_lexical_cast);
}
namespace std {
inline std::ostream & operator<<(std::ostream & out, const std::vector<long> & v)
{
std::ostream_iterator<long> it(out);
std::copy(v.begin(), v.end(), it);
assert(out);
return out;
}
}
void test_empty_vector()
{
std::vector<long> v;
do_test_on_empty_input(v);
BOOST_CHECK_THROW(lexical_cast<char>(v), bad_lexical_cast);
BOOST_CHECK_THROW(lexical_cast<unsigned char>(v), bad_lexical_cast);
BOOST_CHECK_THROW(lexical_cast<signed char>(v), bad_lexical_cast);
}
struct my_string {
friend std::ostream &operator<<(std::ostream& sout, my_string const&/* st*/) {
return sout << "";
}
};
void test_empty_zero_terminated_string()
{
my_string st;
BOOST_CHECK_EQUAL(boost::lexical_cast<std::string>(st), std::string());;
}
unit_test::test_suite *init_unit_test_suite(int, char *[])
{
unit_test::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));
suite->add(BOOST_TEST_CASE(&test_empty_user_class));
suite->add(BOOST_TEST_CASE(&test_empty_vector));
suite->add(BOOST_TEST_CASE(&test_empty_zero_terminated_string));
return suite;
}
+46
View File
@@ -0,0 +1,46 @@
// Unit test for boost::lexical_cast.
//
// See http://www.boost.org for most recent version, including documentation.
//
// Copyright Antony Polukhin, 2013.
//
// 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).
//
// Test lexical_cast usage with long filesystem::path. Bug 7704.
#include <boost/config.hpp>
#include <boost/test/unit_test.hpp>
#include <boost/lexical_cast.hpp>
#include <boost/filesystem/path.hpp>
using namespace boost;
void test_filesystem();
unit_test::test_suite *init_unit_test_suite(int, char *[])
{
unit_test::test_suite *suite =
BOOST_TEST_SUITE("lexical_cast unit test");
suite->add(BOOST_TEST_CASE(&test_filesystem));
return suite;
}
void test_filesystem()
{
boost::filesystem::path p;
std::string s1 = "aaaaaaaaaaaaaaaaaaaaaaa";
p = boost::lexical_cast<boost::filesystem::path>(s1);
BOOST_CHECK(!p.empty());
BOOST_CHECK_EQUAL(p, s1);
p.clear();
const char ab[] = "aaaaaaaaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb";
p = boost::lexical_cast<boost::filesystem::path>(ab);
BOOST_CHECK(!p.empty());
BOOST_CHECK_EQUAL(p, ab);
}
+523
View File
@@ -0,0 +1,523 @@
// 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::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 does not exceeds allowed 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>("."), bad_lexical_cast);
BOOST_CHECK_THROW(lexical_cast<test_t>("-B"), bad_lexical_cast);
// Following two tests are not valid for C++11 compilers
//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);
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() * 2));
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
// Epsilon is multiplied by 2 because of two lexical conversions
#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() * 2 \
);
/*
* 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()
{
// We do not run tests on compilers with bugs
#ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS
test_conversion_from_to_float<long double>();
#endif
BOOST_CHECK(true);
}
+205
View File
@@ -0,0 +1,205 @@
// 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_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_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") ) );
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_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()
{
// We do not run tests on compilers with bugs
#ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS
test_inf_nan_templated<long double >();
#endif
BOOST_CHECK(true);
}
unit_test::test_suite *init_unit_test_suite(int, char *[])
{
unit_test::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;
}
+612
View File
@@ -0,0 +1,612 @@
// Unit test for boost::lexical_cast.
//
// See http://www.boost.org for most recent version, including documentation.
//
// Copyright Terje Sletteb and Kevlin Henney, 2005.
// Copyright Alexander Nasonov, 2006.
// Copyright Antony Polukhin, 2011-2012.
//
// 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).
//
// 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)
#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>
#include <boost/type_traits/integral_promotion.hpp>
#include <boost/type_traits/make_unsigned.hpp>
#include <string>
#include <vector>
#include <memory>
#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
#if (defined(BOOST_LCAST_HAS_INT128) && !defined(__GNUC__)) || GCC_VERSION > 40700
#define BOOST_LCAST_HAS_INT128
#endif
// Test all 65536 values if true:
bool const lcast_test_small_integral_types_completely = false;
// lcast_integral_test_counter: use when testing all values of an integral
// types is not possible. Max. portable value is 32767.
int const lcast_integral_test_counter=500;
using namespace boost;
void test_conversion_from_to_short();
void test_conversion_from_to_ushort();
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();
#endif
#ifdef BOOST_LCAST_HAS_INT128
void test_conversion_from_to_int128();
void test_conversion_from_to_uint128();
#endif
void test_integral_conversions_on_min_max();
unit_test::test_suite *init_unit_test_suite(int, char *[])
{
unit_test::test_suite *suite =
BOOST_TEST_SUITE("lexical_cast unit test on integral types");
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_long));
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
#ifdef BOOST_LCAST_HAS_INT128
suite->add(BOOST_TEST_CASE(&test_conversion_from_to_int128));
suite->add(BOOST_TEST_CASE(&test_conversion_from_to_uint128));
#endif
suite->add(BOOST_TEST_CASE(&test_integral_conversions_on_min_max));
return suite;
}
template<class T, class CharT>
void test_conversion_from_integral_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_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()
{
T t = 0;
BOOST_CHECK(lexical_cast<T>(t) == t);
// Next two variables are used to supress warnings.
int st = 32767; unsigned int ut = st;
t = st;
BOOST_CHECK(lexical_cast<short>(t) == st);
BOOST_CHECK(lexical_cast<unsigned short>(t) == ut);
BOOST_CHECK(lexical_cast<int>(t) == st);
BOOST_CHECK(lexical_cast<unsigned int>(t) == ut);
BOOST_CHECK(lexical_cast<long>(t) == st);
BOOST_CHECK(lexical_cast<unsigned long>(t) == ut);
t = (std::numeric_limits<T>::max)();
BOOST_CHECK(lexical_cast<T>(t) == t);
t = (std::numeric_limits<T>::min)();
BOOST_CHECK(lexical_cast<T>(t) == t);
}
// 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, class CharT>
void test_conversion_from_integral_to_string(CharT)
{
typedef std::numeric_limits<T> limits;
typedef std::basic_string<CharT> string_type;
T t;
t = (limits::min)();
BOOST_CHECK(lexical_cast<string_type>(t) == to_str<CharT>(t));
t = (limits::max)();
BOOST_CHECK(lexical_cast<string_type>(t) == to_str<CharT>(t));
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)
BOOST_CHECK(lexical_cast<string_type>(t) == to_str<CharT>(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;
unsigned int i;
// Test values around min:
t = min_val;
for(i = 0; i < counter; ++i, ++t)
BOOST_CHECK(lexical_cast<string_type>(t) == to_str<CharT>(t));
// Test values around max:
t = max_val;
for(i = 0; i < counter; ++i, --t)
BOOST_CHECK(lexical_cast<string_type>(t) == to_str<CharT>(t));
// Test values around zero:
if(limits::is_signed)
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, ...
T ten_power = 100;
for(int e = 2; e < limits::digits10; ++e, ten_power *= 10)
{
// ten_power + 100 probably never overflows
for(t = ten_power - 100; t != ten_power + 100; ++t)
BOOST_CHECK(lexical_cast<string_type>(t) == to_str<CharT>(t));
}
}
}
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;
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)();
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);
}
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 t = 1 + min_val; t != max_val; ++t)
BOOST_CHECK(lexical_cast<T>(to_str<CharT>(t)) == t);
else
{
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:
t = min_val;
for(i = 0; i < counter; ++i, ++t)
BOOST_CHECK(lexical_cast<T>(to_str<CharT>(t)) == t);
// Test values around max:
t = max_val;
for(i = 0; i < counter; ++i, --t)
BOOST_CHECK(lexical_cast<T>(to_str<CharT>(t)) == t);
// Test values around zero:
if(limits::is_signed)
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, ...
T ten_power = 100;
for(int e = 2; e < limits::digits10; ++e, ten_power *= 10)
{
// ten_power + 100 probably never overflows
for(t = ten_power - 100; t != ten_power + 100; ++t)
BOOST_CHECK(lexical_cast<T>(to_str<CharT>(t)) == t);
}
}
}
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(BOOST_LCAST_NO_WCHAR_T)
test_conversion_from_integral_to_string<T>(L'0');
test_conversion_from_string_to_integral<T>(L'0');
#endif
}
struct restore_oldloc
{
std::locale oldloc;
~restore_oldloc() { std::locale::global(oldloc); }
};
template<class T>
void test_conversion_from_to_integral_minimal()
{
char const zero = '0';
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);
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
#if !defined(BOOST_NO_CXX11_CHAR16_T) && !defined(BOOST_NO_CXX11_UNICODE_LITERALS) && !defined(_LIBCPP_VERSION)
char16_t const u16zero = u'0';
test_conversion_from_integral_to_char<T>(u16zero);
test_conversion_from_char_to_integral<T>(u16zero);
#endif
#if !defined(BOOST_NO_CXX11_CHAR32_T) && !defined(BOOST_NO_CXX11_UNICODE_LITERALS) && !defined(_LIBCPP_VERSION)
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
// Overflow test case from David W. Birdsall
std::string must_owerflow_str = "160000000000000000000";
std::string must_owerflow_negative_str = "-160000000000000000000";
for (int i = 0; i < 15; ++i) {
BOOST_CHECK_THROW(lexical_cast<T>(must_owerflow_str), bad_lexical_cast);
BOOST_CHECK_THROW(lexical_cast<T>(must_owerflow_negative_str), bad_lexical_cast);
must_owerflow_str += '0';
must_owerflow_negative_str += '0';
}
}
template<class T>
void test_conversion_from_to_integral()
{
test_conversion_from_to_integral_minimal<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_integral_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_integral_for_locale<T>();
if(grouping1.empty() && grouping2.empty())
BOOST_TEST_MESSAGE("Formatting with thousands_sep has not been tested");
}
void test_conversion_from_to_short()
{
test_conversion_from_to_integral<short>();
}
void test_conversion_from_to_ushort()
{
test_conversion_from_to_integral<unsigned short>();
}
void test_conversion_from_to_int()
{
test_conversion_from_to_integral<int>();
}
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_intmax_t()
{
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)
void test_conversion_from_to_longlong()
{
test_conversion_from_to_integral<boost::long_long_type>();
}
void test_conversion_from_to_ulonglong()
{
test_conversion_from_to_integral<boost::ulong_long_type>();
}
#elif defined(BOOST_HAS_MS_INT64)
void test_conversion_from_to_longlong()
{
test_conversion_from_to_integral<__int64>();
}
void test_conversion_from_to_ulonglong()
{
test_conversion_from_to_integral<unsigned __int64>();
}
#endif
#ifdef BOOST_LCAST_HAS_INT128
void test_conversion_from_to_int128()
{
test_conversion_from_to_integral_minimal<boost::int128_type>();
}
void test_conversion_from_to_uint128()
{
test_conversion_from_to_integral_minimal<boost::uint128_type>();
}
#endif
template <typename SignedT>
void test_integral_conversions_on_min_max_impl()
{
typedef SignedT signed_t;
typedef BOOST_DEDUCED_TYPENAME boost::make_unsigned<signed_t>::type unsigned_t;
typedef std::numeric_limits<signed_t> s_limits;
typedef std::numeric_limits<unsigned_t> uns_limits;
BOOST_CHECK_EQUAL(lexical_cast<unsigned_t>((uns_limits::max)()), (uns_limits::max)());
BOOST_CHECK_EQUAL(lexical_cast<unsigned_t>((uns_limits::min)()), (uns_limits::min)());
BOOST_CHECK_EQUAL(lexical_cast<signed_t>((s_limits::max)()), (s_limits::max)());
BOOST_CHECK_EQUAL(lexical_cast<signed_t>((uns_limits::min)()), static_cast<signed_t>((uns_limits::min)()));
BOOST_CHECK_EQUAL(lexical_cast<unsigned_t>((s_limits::max)()), static_cast<unsigned_t>((s_limits::max)()));
BOOST_CHECK_EQUAL(lexical_cast<unsigned_t>((s_limits::min)()), static_cast<unsigned_t>((s_limits::min)()));
}
void test_integral_conversions_on_min_max()
{
test_integral_conversions_on_min_max_impl<int>();
test_integral_conversions_on_min_max_impl<short>();
#ifdef _MSC_VER
test_integral_conversions_on_min_max_impl<long int>();
#if defined(BOOST_HAS_LONG_LONG)
test_integral_conversions_on_min_max_impl<boost::long_long_type>();
#elif defined(BOOST_HAS_MS_INT64)
test_integral_conversions_on_min_max_impl<__int64>();
#endif
#ifdef BOOST_LCAST_HAS_INT128
test_integral_conversions_on_min_max_impl<boost::int128_type>();
#endif
#endif
}
+245
View File
@@ -0,0 +1,245 @@
// Unit test for boost::lexical_cast.
//
// See http://www.boost.org for most recent version, including documentation.
//
// Copyright Antony Polukhin, 2012.
//
// 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;
#if defined(BOOST_NO_STRINGSTREAM) || defined(BOOST_NO_STD_WSTRING)
#define BOOST_LCAST_NO_WCHAR_T
#endif
#if !defined(BOOST_NO_CXX11_CHAR16_T) && !defined(BOOST_NO_CXX11_UNICODE_LITERALS) && !defined(_LIBCPP_VERSION)
#define BOOST_LC_RUNU16
#endif
#if !defined(BOOST_NO_CXX11_CHAR32_T) && !defined(BOOST_NO_CXX11_UNICODE_LITERALS) && !defined(_LIBCPP_VERSION)
#define BOOST_LC_RUNU32
#endif
struct class_with_user_defined_sream_operators {
int i;
operator int() const {
return i;
}
};
template <class CharT>
inline std::basic_istream<CharT>& operator >> (std::basic_istream<CharT>& istr, class_with_user_defined_sream_operators& rhs)
{
return istr >> rhs.i;
}
template <class RngT>
void do_test_iterator_range_impl(const RngT& rng)
{
BOOST_CHECK_EQUAL(lexical_cast<int>(rng), 1);
BOOST_CHECK_EQUAL(lexical_cast<int>(rng.begin(), rng.size()), 1);
BOOST_CHECK_EQUAL(lexical_cast<unsigned int>(rng), 1u);
BOOST_CHECK_EQUAL(lexical_cast<unsigned int>(rng.begin(), rng.size()), 1u);
BOOST_CHECK_EQUAL(lexical_cast<short>(rng), 1);
BOOST_CHECK_EQUAL(lexical_cast<short>(rng.begin(), rng.size()), 1);
BOOST_CHECK_EQUAL(lexical_cast<unsigned short>(rng), 1u);
BOOST_CHECK_EQUAL(lexical_cast<unsigned short>(rng.begin(), rng.size()), 1u);
BOOST_CHECK_EQUAL(lexical_cast<long int>(rng), 1);
BOOST_CHECK_EQUAL(lexical_cast<long int>(rng.begin(), rng.size()), 1);
BOOST_CHECK_EQUAL(lexical_cast<unsigned long int>(rng), 1u);
BOOST_CHECK_EQUAL(lexical_cast<unsigned long int>(rng.begin(), rng.size()), 1u);
#ifdef BOOST_STL_SUPPORTS_NEW_UNICODE_LOCALES
BOOST_CHECK_EQUAL(lexical_cast<float>(rng), 1.0f);
BOOST_CHECK_EQUAL(lexical_cast<float>(rng.begin(), rng.size()), 1.0f);
BOOST_CHECK_EQUAL(lexical_cast<double>(rng), 1.0);
BOOST_CHECK_EQUAL(lexical_cast<double>(rng.begin(), rng.size()), 1.0);
#ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS
BOOST_CHECK_EQUAL(lexical_cast<long double>(rng), 1.0L);
BOOST_CHECK_EQUAL(lexical_cast<long double>(rng.begin(), rng.size()), 1.0L);
#endif
BOOST_CHECK_EQUAL(lexical_cast<class_with_user_defined_sream_operators>(rng), 1);
#endif
#if defined(BOOST_HAS_LONG_LONG)
BOOST_CHECK_EQUAL(lexical_cast<boost::ulong_long_type>(rng), 1u);
BOOST_CHECK_EQUAL(lexical_cast<boost::ulong_long_type>(rng.begin(), rng.size()), 1u);
BOOST_CHECK_EQUAL(lexical_cast<boost::long_long_type>(rng), 1);
BOOST_CHECK_EQUAL(lexical_cast<boost::long_long_type>(rng.begin(), rng.size()), 1);
#elif defined(BOOST_HAS_MS_INT64)
BOOST_CHECK_EQUAL(lexical_cast<unsigned __int64>(rng), 1u);
BOOST_CHECK_EQUAL(lexical_cast<unsigned __int64>(rng.begin(), rng.size()), 1u);
BOOST_CHECK_EQUAL(lexical_cast<__int64>(rng), 1);
BOOST_CHECK_EQUAL(lexical_cast<__int64>(rng.begin(), rng.size()), 1);
#endif
}
template <class CharT>
void test_it_range_using_any_chars(CharT* one, CharT* eleven)
{
typedef CharT test_char_type;
// Zero terminated
iterator_range<test_char_type*> rng1(one, one + 1);
do_test_iterator_range_impl(rng1);
iterator_range<const test_char_type*> crng1(one, one + 1);
do_test_iterator_range_impl(crng1);
// Non zero terminated
iterator_range<test_char_type*> rng2(eleven, eleven + 1);
do_test_iterator_range_impl(rng2);
iterator_range<const test_char_type*> crng2(eleven, eleven + 1);
do_test_iterator_range_impl(crng2);
}
template <class CharT>
void test_it_range_using_char(CharT* one, CharT* eleven)
{
typedef CharT test_char_type;
iterator_range<test_char_type*> rng1(one, one + 1);
BOOST_CHECK_EQUAL(lexical_cast<std::string>(rng1), "1");
iterator_range<const test_char_type*> crng1(one, one + 1);
BOOST_CHECK_EQUAL(lexical_cast<std::string>(crng1), "1");
iterator_range<test_char_type*> rng2(eleven, eleven + 1);
BOOST_CHECK_EQUAL(lexical_cast<std::string>(rng2), "1");
iterator_range<const test_char_type*> crng2(eleven, eleven + 1);
BOOST_CHECK_EQUAL(lexical_cast<std::string>(crng2), "1");
BOOST_CHECK_EQUAL(lexical_cast<float>(rng1), 1.0f);
BOOST_CHECK_EQUAL(lexical_cast<double>(rng1), 1.0);
#ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS
BOOST_CHECK_EQUAL(lexical_cast<long double>(rng1), 1.0L);
#endif
BOOST_CHECK_EQUAL(lexical_cast<class_with_user_defined_sream_operators>(rng1), 1);
BOOST_CHECK_EQUAL(lexical_cast<float>(crng2), 1.0f);
BOOST_CHECK_EQUAL(lexical_cast<double>(crng2), 1.0);
#ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS
BOOST_CHECK_EQUAL(lexical_cast<long double>(crng2), 1.0L);
#endif
BOOST_CHECK_EQUAL(lexical_cast<class_with_user_defined_sream_operators>(crng2), 1);
#ifndef BOOST_LCAST_NO_WCHAR_T
BOOST_CHECK(lexical_cast<std::wstring>(rng1) == L"1");
BOOST_CHECK(lexical_cast<std::wstring>(crng1) == L"1");
BOOST_CHECK(lexical_cast<std::wstring>(rng2) == L"1");
BOOST_CHECK(lexical_cast<std::wstring>(crng2) == L"1");
#endif
#if defined(BOOST_LC_RUNU16) && defined(BOOST_STL_SUPPORTS_NEW_UNICODE_LOCALES)
typedef std::basic_string<char16_t> my_char16_string;
BOOST_CHECK(lexical_cast<my_char16_string>(rng1) == u"1");
BOOST_CHECK(lexical_cast<my_char16_string>(crng1) == u"1");
BOOST_CHECK(lexical_cast<my_char16_string>(rng2) == u"1");
BOOST_CHECK(lexical_cast<my_char16_string>(crng2) == u"1");
#endif
#if defined(BOOST_LC_RUNU32) && defined(BOOST_STL_SUPPORTS_NEW_UNICODE_LOCALES)
typedef std::basic_string<char32_t> my_char32_string;
BOOST_CHECK(lexical_cast<my_char32_string>(rng1) == U"1");
BOOST_CHECK(lexical_cast<my_char32_string>(crng1) == U"1");
BOOST_CHECK(lexical_cast<my_char32_string>(rng2) == U"1");
BOOST_CHECK(lexical_cast<my_char32_string>(crng2) == U"1");
#endif
}
void test_char_iterator_ranges()
{
typedef char test_char_type;
test_char_type data1[] = "1";
test_char_type data2[] = "11";
test_it_range_using_any_chars(data1, data2);
test_it_range_using_char(data1, data2);
}
void test_unsigned_char_iterator_ranges()
{
typedef unsigned char test_char_type;
test_char_type data1[] = "1";
test_char_type data2[] = "11";
test_it_range_using_any_chars(data1, data2);
test_it_range_using_char(data1, data2);
}
void test_signed_char_iterator_ranges()
{
typedef signed char test_char_type;
test_char_type data1[] = "1";
test_char_type data2[] = "11";
test_it_range_using_any_chars(data1, data2);
test_it_range_using_char(data1, data2);
}
void test_wchar_iterator_ranges()
{
#ifndef BOOST_LCAST_NO_WCHAR_T
typedef wchar_t test_char_type;
test_char_type data1[] = L"1";
test_char_type data2[] = L"11";
test_it_range_using_any_chars(data1, data2);
#endif
BOOST_CHECK(true);
}
void test_char16_iterator_ranges()
{
#if defined(BOOST_LC_RUNU16)
typedef char16_t test_char_type;
test_char_type data1[] = u"1";
test_char_type data2[] = u"11";
test_it_range_using_any_chars(data1, data2);
#endif
BOOST_CHECK(true);
}
void test_char32_iterator_ranges()
{
#if defined(BOOST_LC_RUNU32)
typedef char32_t test_char_type;
test_char_type data1[] = U"1";
test_char_type data2[] = U"11";
test_it_range_using_any_chars(data1, data2);
#endif
BOOST_CHECK(true);
}
unit_test::test_suite *init_unit_test_suite(int, char *[])
{
unit_test::test_suite *suite = BOOST_TEST_SUITE("lexical_cast. Testing conversions using iterator_range<>");
suite->add(BOOST_TEST_CASE(&test_char_iterator_ranges));
suite->add(BOOST_TEST_CASE(&test_unsigned_char_iterator_ranges));
suite->add(BOOST_TEST_CASE(&test_signed_char_iterator_ranges));
suite->add(BOOST_TEST_CASE(&test_wchar_iterator_ranges));
suite->add(BOOST_TEST_CASE(&test_char16_iterator_ranges));
suite->add(BOOST_TEST_CASE(&test_char32_iterator_ranges));
return suite;
}
+4 -6
View File
@@ -30,7 +30,7 @@ void test_round_conversion_long_double();
unit_test::test_suite *init_unit_test_suite(int, char *[])
{
unit_test_framework::test_suite *suite =
unit_test::test_suite *suite =
BOOST_TEST_SUITE("lexical_cast unit test");
suite->add(BOOST_TEST_CASE(&test_round_conversion_float));
suite->add(BOOST_TEST_CASE(&test_round_conversion_double));
@@ -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,16 @@ 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()
{
// We do not run tests on compilers with bugs
#ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS
test_round_conversion<long double>();
#if defined(BOOST_MSVC)
test_msvc_magic_values<long double>();
#endif
BOOST_CHECK(true);
}
+95
View File
@@ -0,0 +1,95 @@
// Unit test for boost::lexical_cast.
//
// See http://www.boost.org for most recent version, including documentation.
//
// Copyright Antony Polukhin, 2012.
//
// 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>
#ifndef BOOST_NO_EXCEPTIONS
#error "This test must be compiled with -DBOOST_NO_EXCEPTIONS"
#endif
bool g_was_exception = false;
namespace boost {
void throw_exception(std::exception const & ) {
g_was_exception = true;
}
}
using namespace boost;
struct Escape
{
Escape(){}
Escape(const std::string& s)
: str_(s)
{}
std::string str_;
};
inline std::ostream& operator<< (std::ostream& o, const Escape& rhs)
{
return o << rhs.str_;
}
inline std::istream& operator>> (std::istream& i, Escape& rhs)
{
return i >> rhs.str_;
}
void test_exceptions_off()
{
Escape v("");
g_was_exception = false;
lexical_cast<char>(v);
BOOST_CHECK(g_was_exception);
g_was_exception = false;
lexical_cast<unsigned char>(v);
BOOST_CHECK(g_was_exception);
v = lexical_cast<Escape>(100);
BOOST_CHECK_EQUAL(lexical_cast<int>(v), 100);
BOOST_CHECK_EQUAL(lexical_cast<unsigned int>(v), 100u);
v = lexical_cast<Escape>(0.0);
BOOST_CHECK_EQUAL(lexical_cast<double>(v), 0.0);
BOOST_CHECK_EQUAL(lexical_cast<short>(100), 100);
BOOST_CHECK_EQUAL(lexical_cast<float>(0.0), 0.0);
g_was_exception = false;
lexical_cast<short>(700000);
BOOST_CHECK(g_was_exception);
}
unit_test::test_suite *init_unit_test_suite(int, char *[])
{
unit_test::test_suite *suite =
BOOST_TEST_SUITE("lexical_cast. Testing with BOOST_NO_EXCEPTIONS");
suite->add(BOOST_TEST_CASE(&test_exceptions_off));
return suite;
}
+168
View File
@@ -0,0 +1,168 @@
// Unit test for boost::lexical_cast.
//
// See http://www.boost.org for most recent version, including documentation.
//
// Copyright Antony Polukhin, 2012.
//
// 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;
// Testing compilation and some basic usage with BOOST_NO_STD_LOCALE
// Tests are mainly copyied from lexical_cast_empty_input_test.cpp (something
// new added to test_empty_3)
#ifndef BOOST_NO_STD_LOCALE
#error "This test must be compiled with -DBOOST_NO_STD_LOCALE"
#endif
template <class T>
void do_test_on_empty_input(T& 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);
#ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS
BOOST_CHECK_THROW(lexical_cast<long double>(v), bad_lexical_cast);
#endif
BOOST_CHECK_THROW(lexical_cast<unsigned int>(v), bad_lexical_cast);
BOOST_CHECK_THROW(lexical_cast<unsigned short>(v), bad_lexical_cast);
#if defined(BOOST_HAS_LONG_LONG)
BOOST_CHECK_THROW(lexical_cast<boost::ulong_long_type>(v), bad_lexical_cast);
BOOST_CHECK_THROW(lexical_cast<boost::long_long_type>(v), bad_lexical_cast);
#elif defined(BOOST_HAS_MS_INT64)
BOOST_CHECK_THROW(lexical_cast<unsigned __int64>(v), bad_lexical_cast);
BOOST_CHECK_THROW(lexical_cast<__int64>(v), bad_lexical_cast);
#endif
}
void test_empty_1()
{
boost::iterator_range<char*> v;
do_test_on_empty_input(v);
BOOST_CHECK_EQUAL(lexical_cast<std::string>(v), std::string());
BOOST_CHECK_THROW(lexical_cast<char>(v), bad_lexical_cast);
BOOST_CHECK_THROW(lexical_cast<unsigned char>(v), bad_lexical_cast);
BOOST_CHECK_THROW(lexical_cast<signed char>(v), bad_lexical_cast);
boost::iterator_range<const char*> cv;
do_test_on_empty_input(cv);
BOOST_CHECK_EQUAL(lexical_cast<std::string>(cv), std::string());
BOOST_CHECK_THROW(lexical_cast<char>(cv), bad_lexical_cast);
BOOST_CHECK_THROW(lexical_cast<unsigned char>(cv), bad_lexical_cast);
BOOST_CHECK_THROW(lexical_cast<signed char>(cv), bad_lexical_cast);
const boost::iterator_range<const char*> ccv;
do_test_on_empty_input(ccv);
BOOST_CHECK_EQUAL(lexical_cast<std::string>(ccv), std::string());
BOOST_CHECK_THROW(lexical_cast<char>(ccv), bad_lexical_cast);
BOOST_CHECK_THROW(lexical_cast<unsigned char>(ccv), bad_lexical_cast);
BOOST_CHECK_THROW(lexical_cast<signed char>(ccv), bad_lexical_cast);
}
void test_empty_2()
{
std::string v;
do_test_on_empty_input(v);
BOOST_CHECK_THROW(lexical_cast<char>(v), bad_lexical_cast);
BOOST_CHECK_THROW(lexical_cast<unsigned char>(v), bad_lexical_cast);
BOOST_CHECK_THROW(lexical_cast<signed char>(v), bad_lexical_cast);
}
struct Escape
{
Escape(){}
Escape(const std::string& s)
: str_(s)
{}
std::string str_;
};
inline std::ostream& operator<< (std::ostream& o, const Escape& rhs)
{
return o << rhs.str_;
}
inline std::istream& operator>> (std::istream& i, Escape& rhs)
{
return i >> rhs.str_;
}
void test_empty_3()
{
Escape v("");
do_test_on_empty_input(v);
BOOST_CHECK_THROW(lexical_cast<char>(v), bad_lexical_cast);
BOOST_CHECK_THROW(lexical_cast<unsigned char>(v), bad_lexical_cast);
BOOST_CHECK_THROW(lexical_cast<signed char>(v), bad_lexical_cast);
v = lexical_cast<Escape>(100);
BOOST_CHECK_EQUAL(lexical_cast<int>(v), 100);
BOOST_CHECK_EQUAL(lexical_cast<unsigned int>(v), 100u);
v = lexical_cast<Escape>(0.0);
BOOST_CHECK_EQUAL(lexical_cast<double>(v), 0.0);
}
namespace std {
inline std::ostream & operator<<(std::ostream & out, const std::vector<long> & v)
{
std::ostream_iterator<long> it(out);
std::copy(v.begin(), v.end(), it);
assert(out);
return out;
}
}
void test_empty_4()
{
std::vector<long> v;
do_test_on_empty_input(v);
BOOST_CHECK_THROW(lexical_cast<char>(v), bad_lexical_cast);
BOOST_CHECK_THROW(lexical_cast<unsigned char>(v), bad_lexical_cast);
BOOST_CHECK_THROW(lexical_cast<signed char>(v), bad_lexical_cast);
}
struct my_string {
friend std::ostream &operator<<(std::ostream& sout, my_string const&/* st*/) {
return sout << "";
}
};
void test_empty_5()
{
my_string st;
BOOST_CHECK_EQUAL(boost::lexical_cast<std::string>(st), std::string());;
}
unit_test::test_suite *init_unit_test_suite(int, char *[])
{
unit_test::test_suite *suite =
BOOST_TEST_SUITE("lexical_cast. Testing with BOOST_NO_STD_LOCALE");
suite->add(BOOST_TEST_CASE(&test_empty_1));
suite->add(BOOST_TEST_CASE(&test_empty_2));
suite->add(BOOST_TEST_CASE(&test_empty_3));
suite->add(BOOST_TEST_CASE(&test_empty_4));
suite->add(BOOST_TEST_CASE(&test_empty_5));
return suite;
}
+1 -1
View File
@@ -28,7 +28,7 @@ void test_noncopyable();
unit_test::test_suite *init_unit_test_suite(int, char *[])
{
unit_test_framework::test_suite *suite =
unit_test::test_suite *suite =
BOOST_TEST_SUITE("lexical_cast unit test");
suite->add(BOOST_TEST_CASE(&test_noncopyable));
+96
View File
@@ -0,0 +1,96 @@
// Unit test for boost::lexical_cast.
//
// See http://www.boost.org for most recent version, including documentation.
//
// Copyright Antony Polukhin, 2012.
//
// 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>
using namespace boost;
#if defined(BOOST_NO_STRINGSTREAM)
typedef std::strstream ss_t;
#else
typedef std::stringstream ss_t;
#endif
void test_void_pointers_conversions()
{
void *p_to_null = NULL;
const void *cp_to_data = "Some data";
char nonconst_data[5];
void *p_to_data = nonconst_data;
ss_t ss;
ss << p_to_null;
BOOST_CHECK_EQUAL(boost::lexical_cast<std::string>(p_to_null), ss.str());
ss.str(std::string());
ss << cp_to_data;
BOOST_CHECK_EQUAL(boost::lexical_cast<std::string>(cp_to_data), ss.str());
ss.str(std::string());
ss << p_to_data;
BOOST_CHECK_EQUAL(boost::lexical_cast<std::string>(p_to_data), ss.str());
ss.str(std::string());
}
struct incomplete_type;
void test_incomplete_type_pointers_conversions()
{
incomplete_type *p_to_null = NULL;
const incomplete_type *cp_to_data = NULL;
char nonconst_data[5];
incomplete_type *p_to_data = reinterpret_cast<incomplete_type*>(nonconst_data);
ss_t ss;
ss << p_to_null;
BOOST_CHECK_EQUAL(boost::lexical_cast<std::string>(p_to_null), ss.str());
ss.str(std::string());
ss << cp_to_data;
BOOST_CHECK_EQUAL(boost::lexical_cast<std::string>(cp_to_data), ss.str());
ss.str(std::string());
ss << p_to_data;
BOOST_CHECK_EQUAL(boost::lexical_cast<std::string>(p_to_data), ss.str());
ss.str(std::string());
}
struct ble;
typedef struct ble *meh;
std::ostream& operator <<(std::ostream &o, meh) {
o << "yay";
return o;
}
void test_inomplete_type_with_overloaded_ostream_op() {
meh heh = NULL;
ss_t ss;
ss << heh;
BOOST_CHECK_EQUAL(boost::lexical_cast<std::string>(heh), ss.str());
}
unit_test::test_suite *init_unit_test_suite(int, char *[])
{
unit_test::test_suite *suite =
BOOST_TEST_SUITE("lexical_cast pinters test");
suite->add(BOOST_TEST_CASE(&test_void_pointers_conversions));
suite->add(BOOST_TEST_CASE(&test_incomplete_type_pointers_conversions));
suite->add(BOOST_TEST_CASE(&test_inomplete_type_with_overloaded_ostream_op));
return suite;
}
+307
View File
@@ -0,0 +1,307 @@
// Unit test for boost::lexical_cast.
//
// See http://www.boost.org for most recent version, including documentation.
//
// Copyright Antony Polukhin, 2011-2012.
//
// 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>
#include <boost/test/unit_test.hpp>
#include <boost/lexical_cast.hpp>
#include <iostream>
///////////////////////// char streamable classes ///////////////////////////////////////////
struct streamable_easy { enum ENU {value = 0}; };
std::ostream& operator << (std::ostream& ostr, const streamable_easy&) {
return ostr << streamable_easy::value;
}
std::istream& operator >> (std::istream& istr, const streamable_easy&) {
int i; istr >> i; BOOST_CHECK_EQUAL(i, streamable_easy::value);
return istr;
}
struct streamable_medium { enum ENU {value = 1}; };
template <class CharT>
typename boost::enable_if<boost::is_same<CharT, char>, std::basic_ostream<CharT>&>::type
operator << (std::basic_ostream<CharT>& ostr, const streamable_medium&) {
return ostr << streamable_medium::value;
}
template <class CharT>
typename boost::enable_if<boost::is_same<CharT, char>, std::basic_istream<CharT>&>::type
operator >> (std::basic_istream<CharT>& istr, const streamable_medium&) {
int i; istr >> i; BOOST_CHECK_EQUAL(i, streamable_medium::value);
return istr;
}
struct streamable_hard { enum ENU {value = 2}; };
template <class CharT, class TraitsT>
typename boost::enable_if<boost::is_same<CharT, char>, std::basic_ostream<CharT, TraitsT>&>::type
operator << (std::basic_ostream<CharT, TraitsT>& ostr, const streamable_hard&) {
return ostr << streamable_hard::value;
}
template <class CharT, class TraitsT>
typename boost::enable_if<boost::is_same<CharT, char>, std::basic_istream<CharT, TraitsT>&>::type
operator >> (std::basic_istream<CharT, TraitsT>& istr, const streamable_hard&) {
int i; istr >> i; BOOST_CHECK_EQUAL(i, streamable_hard::value);
return istr;
}
struct streamable_hard2 { enum ENU {value = 3}; };
template <class TraitsT>
std::basic_ostream<char, TraitsT>& operator << (std::basic_ostream<char, TraitsT>& ostr, const streamable_hard2&) {
return ostr << streamable_hard2::value;
}
template <class TraitsT>
std::basic_istream<char, TraitsT>& operator >> (std::basic_istream<char, TraitsT>& istr, const streamable_hard2&) {
int i; istr >> i; BOOST_CHECK_EQUAL(i, streamable_hard2::value);
return istr;
}
///////////////////////// wchar_t streamable classes ///////////////////////////////////////////
struct wstreamable_easy { enum ENU {value = 4}; };
std::wostream& operator << (std::wostream& ostr, const wstreamable_easy&) {
return ostr << wstreamable_easy::value;
}
std::wistream& operator >> (std::wistream& istr, const wstreamable_easy&) {
int i; istr >> i; BOOST_CHECK_EQUAL(i, wstreamable_easy::value);
return istr;
}
struct wstreamable_medium { enum ENU {value = 5}; };
template <class CharT>
typename boost::enable_if<boost::is_same<CharT, wchar_t>, std::basic_ostream<CharT>& >::type
operator << (std::basic_ostream<CharT>& ostr, const wstreamable_medium&) {
return ostr << wstreamable_medium::value;
}
template <class CharT>
typename boost::enable_if<boost::is_same<CharT, wchar_t>, std::basic_istream<CharT>& >::type
operator >> (std::basic_istream<CharT>& istr, const wstreamable_medium&) {
int i; istr >> i; BOOST_CHECK_EQUAL(i, wstreamable_medium::value);
return istr;
}
struct wstreamable_hard { enum ENU {value = 6}; };
template <class CharT, class TraitsT>
typename boost::enable_if<boost::is_same<CharT, wchar_t>, std::basic_ostream<CharT, TraitsT>&>::type
operator << (std::basic_ostream<CharT, TraitsT>& ostr, const wstreamable_hard&) {
return ostr << wstreamable_hard::value;
}
template <class CharT, class TraitsT>
typename boost::enable_if<boost::is_same<CharT, wchar_t>, std::basic_istream<CharT, TraitsT>&>::type
operator >> (std::basic_istream<CharT, TraitsT>& istr, const wstreamable_hard&) {
int i; istr >> i; BOOST_CHECK_EQUAL(i, wstreamable_hard::value);
return istr;
}
struct wstreamable_hard2 { enum ENU {value = 7}; };
template <class TraitsT>
std::basic_ostream<wchar_t, TraitsT>& operator << (std::basic_ostream<wchar_t, TraitsT>& ostr, const wstreamable_hard2&) {
return ostr << wstreamable_hard2::value;
}
template <class TraitsT>
std::basic_istream<wchar_t, TraitsT>& operator >> (std::basic_istream<wchar_t, TraitsT>& istr, const wstreamable_hard2&) {
int i; istr >> i; BOOST_CHECK_EQUAL(i, wstreamable_hard2::value);
return istr;
}
///////////////////////// char and wchar_t streamable classes ///////////////////////////////////////////
struct bistreamable_easy { enum ENU {value = 8}; };
std::ostream& operator << (std::ostream& ostr, const bistreamable_easy&) {
return ostr << bistreamable_easy::value;
}
std::istream& operator >> (std::istream& istr, const bistreamable_easy&) {
int i; istr >> i; BOOST_CHECK_EQUAL(i, bistreamable_easy::value);
return istr;
}
std::wostream& operator << (std::wostream& ostr, const bistreamable_easy&) {
return ostr << bistreamable_easy::value + 100;
}
std::wistream& operator >> (std::wistream& istr, const bistreamable_easy&) {
int i; istr >> i; BOOST_CHECK_EQUAL(i, bistreamable_easy::value + 100);
return istr;
}
struct bistreamable_medium { enum ENU {value = 9}; };
template <class CharT>
std::basic_ostream<CharT>& operator << (std::basic_ostream<CharT>& ostr, const bistreamable_medium&) {
return ostr << bistreamable_medium::value + (sizeof(CharT) == 1 ? 0 : 100);
}
template <class CharT>
std::basic_istream<CharT>& operator >> (std::basic_istream<CharT>& istr, const bistreamable_medium&) {
int i; istr >> i; BOOST_CHECK_EQUAL(i, bistreamable_medium::value + (sizeof(CharT) == 1 ? 0 : 100));
return istr;
}
struct bistreamable_hard { enum ENU {value = 10}; };
template <class CharT, class TraitsT>
std::basic_ostream<CharT, TraitsT>& operator << (std::basic_ostream<CharT, TraitsT>& ostr, const bistreamable_hard&) {
return ostr << bistreamable_hard::value + (sizeof(CharT) == 1 ? 0 : 100);
}
template <class CharT, class TraitsT>
std::basic_istream<CharT, TraitsT>& operator >> (std::basic_istream<CharT, TraitsT>& istr, const bistreamable_hard&) {
int i; istr >> i; BOOST_CHECK_EQUAL(i, bistreamable_hard::value + (sizeof(CharT) == 1 ? 0 : 100));
return istr;
}
struct bistreamable_hard2 { enum ENU {value = 11}; };
template <class TraitsT>
std::basic_ostream<char, TraitsT>& operator << (std::basic_ostream<char, TraitsT>& ostr, const bistreamable_hard2&) {
return ostr << bistreamable_hard2::value;
}
template <class TraitsT>
std::basic_istream<char, TraitsT>& operator >> (std::basic_istream<char, TraitsT>& istr, const bistreamable_hard2&) {
int i; istr >> i; BOOST_CHECK_EQUAL(i, bistreamable_hard2::value);
return istr;
}
template <class TraitsT>
std::basic_ostream<wchar_t, TraitsT>& operator << (std::basic_ostream<wchar_t, TraitsT>& ostr, const bistreamable_hard2&) {
return ostr << bistreamable_hard2::value + 100;
}
template <class TraitsT>
std::basic_istream<wchar_t, TraitsT>& operator >> (std::basic_istream<wchar_t, TraitsT>& istr, const bistreamable_hard2&) {
int i; istr >> i; BOOST_CHECK_EQUAL(i, bistreamable_hard2::value + 100);
return istr;
}
void test_ostream_character_detection();
void test_istream_character_detection();
void test_mixed_stream_character_detection();
boost::unit_test::test_suite *init_unit_test_suite(int, char *[])
{
boost::unit_test::test_suite *suite =
BOOST_TEST_SUITE("lexical_cast stream character detection");
suite->add(BOOST_TEST_CASE(&test_ostream_character_detection));
suite->add(BOOST_TEST_CASE(&test_istream_character_detection));
suite->add(BOOST_TEST_CASE(&test_mixed_stream_character_detection));
return suite;
}
template <class T>
static void test_ostr_impl() {
T streamable;
BOOST_CHECK_EQUAL(T::value, boost::lexical_cast<int>(streamable));
BOOST_CHECK_EQUAL(boost::lexical_cast<std::string>(T::value), boost::lexical_cast<std::string>(streamable));
}
template <class T>
static void test_wostr_impl() {
T streamable;
BOOST_CHECK_EQUAL(T::value, boost::lexical_cast<int>(streamable));
// BOOST_CHECK_EQUAL(boost::lexical_cast<std::string>(T::value), boost::lexical_cast<std::string>(streamable)); // Shall not compile???
BOOST_CHECK(boost::lexical_cast<std::wstring>(T::value) == boost::lexical_cast<std::wstring>(streamable));
}
template <class T>
static void test_bistr_impl() {
T streamable;
BOOST_CHECK_EQUAL(T::value, boost::lexical_cast<int>(streamable));
BOOST_CHECK_EQUAL(boost::lexical_cast<std::string>(T::value), boost::lexical_cast<std::string>(streamable));
BOOST_CHECK(boost::lexical_cast<std::wstring>(T::value + 100) == boost::lexical_cast<std::wstring>(streamable));
}
void test_ostream_character_detection() {
test_ostr_impl<streamable_easy>();
test_ostr_impl<streamable_medium>();
test_ostr_impl<streamable_hard>();
test_ostr_impl<streamable_hard2>();
test_wostr_impl<wstreamable_easy>();
test_wostr_impl<wstreamable_medium>();
test_wostr_impl<wstreamable_hard>();
test_wostr_impl<wstreamable_hard2>();
test_bistr_impl<bistreamable_easy>();
test_bistr_impl<bistreamable_medium>();
test_bistr_impl<bistreamable_hard>();
test_bistr_impl<bistreamable_hard2>();
}
template <class T>
static void test_istr_impl() {
boost::lexical_cast<T>(T::value);
boost::lexical_cast<T>(boost::lexical_cast<std::string>(T::value));
}
template <class T>
static void test_wistr_impl() {
boost::lexical_cast<T>(T::value);
//boost::lexical_cast<T>(boost::lexical_cast<std::string>(T::value)); // Shall not compile???
boost::lexical_cast<T>(boost::lexical_cast<std::wstring>(T::value));
}
template <class T>
static void test_bistr_instr_impl() {
boost::lexical_cast<T>(T::value);
boost::lexical_cast<T>(boost::lexical_cast<std::string>(T::value));
boost::lexical_cast<T>(boost::lexical_cast<std::wstring>(T::value + 100));
}
void test_istream_character_detection() {
test_istr_impl<streamable_easy>();
test_istr_impl<streamable_medium>();
test_istr_impl<streamable_hard>();
test_istr_impl<streamable_hard2>();
test_wistr_impl<wstreamable_easy>();
test_wistr_impl<wstreamable_medium>();
test_wistr_impl<wstreamable_hard>();
test_wistr_impl<wstreamable_hard2>();
test_bistr_instr_impl<bistreamable_easy>();
test_bistr_instr_impl<bistreamable_medium>();
test_bistr_instr_impl<bistreamable_hard>();
test_bistr_instr_impl<bistreamable_hard2>();
}
struct wistreamble_ostreamable { enum ENU {value = 200}; };
std::ostream& operator << (std::ostream& ostr, const wistreamble_ostreamable&) {
return ostr << wistreamble_ostreamable::value;
}
std::wistream& operator >> (std::wistream& istr, const wistreamble_ostreamable&) {
int i; istr >> i; BOOST_CHECK_EQUAL(i, wistreamble_ostreamable::value);
return istr;
}
struct istreamble_wostreamable { enum ENU {value = 201}; };
std::wostream& operator << (std::wostream& ostr, const istreamble_wostreamable&) {
return ostr << istreamble_wostreamable::value;
}
std::istream& operator >> (std::istream& istr, const istreamble_wostreamable&) {
int i; istr >> i; BOOST_CHECK_EQUAL(i, istreamble_wostreamable::value);
return istr;
}
void test_mixed_stream_character_detection() {
//boost::lexical_cast<std::wstring>(std::string("qwe")); // TODO: ALLOW IT AS EXTENSION!
boost::lexical_cast<wistreamble_ostreamable>(wistreamble_ostreamable::value);
BOOST_CHECK_EQUAL(boost::lexical_cast<int>(wistreamble_ostreamable()), wistreamble_ostreamable::value);
boost::lexical_cast<istreamble_wostreamable>(istreamble_wostreamable::value);
BOOST_CHECK_EQUAL(boost::lexical_cast<int>(istreamble_wostreamable()), istreamble_wostreamable::value);
}
+158
View File
@@ -0,0 +1,158 @@
// Unit test for boost::lexical_cast.
//
// See http://www.boost.org for most recent version, including documentation.
//
// Copyright Antony Polukhin, 2012.
//
// 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>
#include <boost/lexical_cast.hpp>
#include <boost/test/unit_test.hpp>
template <class T>
static void test_optimized_types_to_string_const()
{
namespace de = boost::detail;
typedef de::lexical_cast_stream_traits<T, std::string> trait_1;
BOOST_CHECK(!trait_1::is_source_input_not_optimized_t::value);
BOOST_CHECK((boost::is_same<BOOST_DEDUCED_TYPENAME trait_1::src_char_t, char>::value));
BOOST_CHECK((boost::is_same<BOOST_DEDUCED_TYPENAME trait_1::target_char_t, char>::value));
BOOST_CHECK((boost::is_same<BOOST_DEDUCED_TYPENAME trait_1::char_type, char>::value));
BOOST_CHECK(!trait_1::is_string_widening_required_t::value);
BOOST_CHECK(!trait_1::is_source_input_not_optimized_t::value);
typedef de::lexical_cast_stream_traits<const T, std::string> trait_2;
BOOST_CHECK(!trait_2::is_source_input_not_optimized_t::value);
BOOST_CHECK((boost::is_same<BOOST_DEDUCED_TYPENAME trait_2::src_char_t, char>::value));
BOOST_CHECK((boost::is_same<BOOST_DEDUCED_TYPENAME trait_2::target_char_t, char>::value));
BOOST_CHECK((boost::is_same<BOOST_DEDUCED_TYPENAME trait_2::char_type, char>::value));
BOOST_CHECK(!trait_2::is_string_widening_required_t::value);
BOOST_CHECK(!trait_2::is_source_input_not_optimized_t::value);
typedef de::lexical_cast_stream_traits<T, std::wstring> trait_3;
BOOST_CHECK(!trait_3::is_source_input_not_optimized_t::value);
BOOST_CHECK((boost::is_same<BOOST_DEDUCED_TYPENAME trait_3::src_char_t, char>::value));
BOOST_CHECK((boost::is_same<BOOST_DEDUCED_TYPENAME trait_3::target_char_t, wchar_t>::value));
BOOST_CHECK((boost::is_same<BOOST_DEDUCED_TYPENAME trait_3::char_type, wchar_t>::value));
BOOST_CHECK((boost::detail::is_char_or_wchar<BOOST_DEDUCED_TYPENAME trait_3::no_cv_src>::value != trait_3::is_string_widening_required_t::value));
BOOST_CHECK(!trait_3::is_source_input_not_optimized_t::value);
}
template <class T>
static void test_optimized_types_to_string()
{
test_optimized_types_to_string_const<T>();
namespace de = boost::detail;
typedef de::lexical_cast_stream_traits<std::string, T> trait_4;
BOOST_CHECK(!trait_4::is_source_input_not_optimized_t::value);
BOOST_CHECK((boost::is_same<BOOST_DEDUCED_TYPENAME trait_4::src_char_t, char>::value));
BOOST_CHECK((boost::is_same<BOOST_DEDUCED_TYPENAME trait_4::target_char_t, char>::value));
BOOST_CHECK((boost::is_same<BOOST_DEDUCED_TYPENAME trait_4::char_type, char>::value));
BOOST_CHECK(!trait_4::is_string_widening_required_t::value);
BOOST_CHECK(!trait_4::is_source_input_not_optimized_t::value);
typedef de::lexical_cast_stream_traits<const std::string, T> trait_5;
BOOST_CHECK(!trait_5::is_source_input_not_optimized_t::value);
BOOST_CHECK((boost::is_same<BOOST_DEDUCED_TYPENAME trait_5::src_char_t, char>::value));
BOOST_CHECK((boost::is_same<BOOST_DEDUCED_TYPENAME trait_5::target_char_t, char>::value));
BOOST_CHECK((boost::is_same<BOOST_DEDUCED_TYPENAME trait_5::char_type, char>::value));
BOOST_CHECK(!trait_5::is_string_widening_required_t::value);
BOOST_CHECK(!trait_5::is_source_input_not_optimized_t::value);
typedef de::lexical_cast_stream_traits<const std::wstring, T> trait_6;
BOOST_CHECK(!trait_6::is_source_input_not_optimized_t::value);
BOOST_CHECK((boost::is_same<BOOST_DEDUCED_TYPENAME trait_6::src_char_t, wchar_t>::value));
BOOST_CHECK((boost::is_same<BOOST_DEDUCED_TYPENAME trait_6::target_char_t, char>::value));
BOOST_CHECK((boost::is_same<BOOST_DEDUCED_TYPENAME trait_6::char_type, wchar_t>::value));
BOOST_CHECK(!trait_6::is_string_widening_required_t::value);
}
void test_metafunctions()
{
test_optimized_types_to_string<bool>();
test_optimized_types_to_string<char>();
test_optimized_types_to_string<unsigned char>();
test_optimized_types_to_string<signed char>();
test_optimized_types_to_string<short>();
test_optimized_types_to_string<unsigned short>();
test_optimized_types_to_string<int>();
test_optimized_types_to_string<unsigned int>();
test_optimized_types_to_string<long>();
test_optimized_types_to_string<unsigned long>();
#if defined(BOOST_HAS_LONG_LONG)
test_optimized_types_to_string<boost::ulong_long_type>();
test_optimized_types_to_string<boost::long_long_type>();
#elif defined(BOOST_HAS_MS_INT64)
test_optimized_types_to_string<unsigned __int64>();
test_optimized_types_to_string<__int64>();
#endif
#if !defined(BOOST_NO_SWPRINTF) && !defined(__MINGW32__)
test_optimized_types_to_string<float>();
#endif
test_optimized_types_to_string<std::string>();
test_optimized_types_to_string<char*>();
//test_optimized_types_to_string<char[5]>();
//test_optimized_types_to_string<char[1]>();
test_optimized_types_to_string<unsigned char*>();
//test_optimized_types_to_string<unsigned char[5]>();
//test_optimized_types_to_string<unsigned char[1]>();
test_optimized_types_to_string<signed char*>();
//test_optimized_types_to_string<signed char[5]>();
//test_optimized_types_to_string<signed char[1]>();
test_optimized_types_to_string<boost::array<char, 1> >();
test_optimized_types_to_string<boost::array<char, 5> >();
test_optimized_types_to_string<boost::array<unsigned char, 1> >();
test_optimized_types_to_string<boost::array<unsigned char, 5> >();
test_optimized_types_to_string<boost::array<signed char, 1> >();
test_optimized_types_to_string<boost::array<signed char, 5> >();
test_optimized_types_to_string<boost::iterator_range<char*> >();
test_optimized_types_to_string<boost::iterator_range<unsigned char*> >();
test_optimized_types_to_string<boost::iterator_range<signed char*> >();
test_optimized_types_to_string_const<boost::array<const char, 1> >();
test_optimized_types_to_string_const<boost::array<const char, 5> >();
test_optimized_types_to_string_const<boost::array<const unsigned char, 1> >();
test_optimized_types_to_string_const<boost::array<const unsigned char, 5> >();
test_optimized_types_to_string_const<boost::array<const signed char, 1> >();
test_optimized_types_to_string_const<boost::array<const signed char, 5> >();
test_optimized_types_to_string_const<boost::iterator_range<const char*> >();
test_optimized_types_to_string_const<boost::iterator_range<const unsigned char*> >();
test_optimized_types_to_string_const<boost::iterator_range<const signed char*> >();
#ifndef BOOST_NO_CXX11_HDR_ARRAY
test_optimized_types_to_string<std::array<char, 1> >();
test_optimized_types_to_string<std::array<char, 5> >();
test_optimized_types_to_string<std::array<unsigned char, 1> >();
test_optimized_types_to_string<std::array<unsigned char, 5> >();
test_optimized_types_to_string<std::array<signed char, 1> >();
test_optimized_types_to_string<std::array<signed char, 5> >();
test_optimized_types_to_string_const<std::array<const char, 1> >();
test_optimized_types_to_string_const<std::array<const char, 5> >();
test_optimized_types_to_string_const<std::array<const unsigned char, 1> >();
test_optimized_types_to_string_const<std::array<const unsigned char, 5> >();
test_optimized_types_to_string_const<std::array<const signed char, 1> >();
test_optimized_types_to_string_const<std::array<const signed char, 5> >();
#endif
}
boost::unit_test::test_suite *init_unit_test_suite(int, char *[])
{
boost::unit_test::test_suite *suite =
BOOST_TEST_SUITE("lexical_cast traits tests");
suite->add(BOOST_TEST_CASE(&test_metafunctions));
return suite;
}
+21
View File
@@ -0,0 +1,21 @@
// // Unit test for boost::lexical_cast.
//
// See http://www.boost.org for most recent version, including documentation.
//
// Copyright Antony Polukhin, 2013.
//
// 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/lexical_cast.hpp>
#include <boost/type.hpp>
#define BOOST_INCLUDE_MAIN
#include <boost/test/test_tools.hpp>
int test_main(int, char*[])
{
boost::lexical_cast<char*>("Hello");
return 0;
}
+40
View File
@@ -0,0 +1,40 @@
// 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>
#include <boost/static_assert.hpp>
#include <boost/lexical_cast.hpp>
#include <boost/date_time/gregorian/gregorian.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
void parseDate()
{
std::locale locale;
boost::date_time::format_date_parser<boost::gregorian::date, wchar_t> parser(L"", locale);
boost::date_time::special_values_parser<boost::gregorian::date, wchar_t> svp;
boost::gregorian::date date = parser.parse_date(L"", L"", svp);
(void)date;
}
int main()
{
#ifdef BOOST_MSVC
BOOST_STATIC_ASSERT((boost::is_same<wchar_t, unsigned short>::value));
#endif
parseDate();
return ::boost::lexical_cast<int>(L"1000") == 1000;
}
+48
View File
@@ -0,0 +1,48 @@
// 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>
using namespace boost;
void test_typedefed_wchar_t_runtime()
{
#ifndef BOOST_LCAST_NO_WCHAR_T
#ifdef BOOST_MSVC
BOOST_STATIC_ASSERT((boost::is_same<wchar_t, unsigned short>::value));
BOOST_CHECK_EQUAL(boost::lexical_cast<int>(L'A'), 65);
BOOST_CHECK_EQUAL(boost::lexical_cast<int>(L'B'), 66);
BOOST_CHECK_EQUAL(boost::lexical_cast<wchar_t>(L"65"), 65);
BOOST_CHECK_EQUAL(boost::lexical_cast<wchar_t>(L"66"), 66);
#endif
#endif
BOOST_CHECK(1);
}
unit_test::test_suite *init_unit_test_suite(int, char *[])
{
unit_test::test_suite *suite =
BOOST_TEST_SUITE("lexical_cast typedefed wchar_t runtime test");
suite->add(BOOST_TEST_CASE(&test_typedefed_wchar_t_runtime));
return suite;
}
+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] += static_cast<CharT>(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] += static_cast<CharT>(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::test_suite *suite =
BOOST_TEST_SUITE("lexical_cast vc8 bug unit test");
suite->add(BOOST_TEST_CASE(test_vc8_bug));
return suite;
}
+86
View File
@@ -0,0 +1,86 @@
// Unit test for boost::lexical_cast.
//
// See http://www.boost.org for most recent version, including documentation.
//
// Copyright Antony Polukhin, 2011-2012.
//
// 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>
using namespace boost;
#if defined(BOOST_NO_STRINGSTREAM) || defined(BOOST_NO_STD_WSTRING)
#define BOOST_LCAST_NO_WCHAR_T
#endif
template <class CharT>
void test_impl(const CharT* wc_arr)
{
typedef CharT wide_char;
typedef std::basic_string<CharT> wide_string;
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";
// Following tests depend on realization of std::locale
// and pass for popular compilers and STL realizations
BOOST_CHECK(boost::lexical_cast<wide_char>(c_arr[0]) == wc_arr[0]);
BOOST_CHECK(boost::lexical_cast<wide_string>(c_arr) == wide_string(wc_arr));
BOOST_CHECK(boost::lexical_cast<wide_string>(sc_arr) == wide_string(wc_arr) );
BOOST_CHECK(boost::lexical_cast<wide_string>(uc_arr) == wide_string(wc_arr) );
BOOST_CHECK_EQUAL(boost::lexical_cast<wide_char>(uc_arr[0]), wc_arr[0]);
BOOST_CHECK_EQUAL(boost::lexical_cast<wide_char>(sc_arr[0]), wc_arr[0]);
}
void test_char_types_conversions_wchar_t()
{
#ifndef BOOST_LCAST_NO_WCHAR_T
test_impl(L"Test array of chars");
#endif
BOOST_CHECK(true);
}
void test_char_types_conversions_char16_t()
{
#if !defined(BOOST_NO_CXX11_CHAR16_T) && !defined(BOOST_NO_CXX11_UNICODE_LITERALS) && defined(BOOST_STL_SUPPORTS_NEW_UNICODE_LOCALES)
test_impl(u"Test array of chars");
#endif
BOOST_CHECK(true);
}
void test_char_types_conversions_char32_t()
{
#if !defined(BOOST_NO_CXX11_CHAR32_T) && !defined(BOOST_NO_CXX11_UNICODE_LITERALS) && defined(BOOST_STL_SUPPORTS_NEW_UNICODE_LOCALES)
test_impl(U"Test array of chars");
#endif
BOOST_CHECK(true);
}
unit_test::test_suite *init_unit_test_suite(int, char *[])
{
unit_test::test_suite *suite =
BOOST_TEST_SUITE("lexical_cast char => wide characters unit test (widening test)");
suite->add(BOOST_TEST_CASE(&test_char_types_conversions_wchar_t));
suite->add(BOOST_TEST_CASE(&test_char_types_conversions_char16_t));
suite->add(BOOST_TEST_CASE(&test_char_types_conversions_char32_t));
return suite;
}