diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 18:45:59 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 18:45:59 +0000 |
commit | 19fcec84d8d7d21e796c7624e521b60d28ee21ed (patch) | |
tree | 42d26aa27d1e3f7c0b8bd3fd14e7d7082f5008dc /src/boost/libs/convert | |
parent | Initial commit. (diff) | |
download | ceph-upstream.tar.xz ceph-upstream.zip |
Adding upstream version 16.2.11+ds.upstream/16.2.11+dsupstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/boost/libs/convert')
31 files changed, 3486 insertions, 0 deletions
diff --git a/src/boost/libs/convert/README.md b/src/boost/libs/convert/README.md new file mode 100644 index 000000000..1d45aa7b4 --- /dev/null +++ b/src/boost/libs/convert/README.md @@ -0,0 +1,7 @@ +The library builds on the `boost::lexical_cast` experience and takes those type conversion/transformation-related ideas further + +* to be useful and applicable in a wider range of deployment scenarios, +* to provide a flexible, extendible and configurable type-conversion framework. + +**HTML documentation is available [here](http://boostorg.github.io/convert).** + diff --git a/src/boost/libs/convert/example/algorithms.cpp b/src/boost/libs/convert/example/algorithms.cpp new file mode 100644 index 000000000..6235fbfb3 --- /dev/null +++ b/src/boost/libs/convert/example/algorithms.cpp @@ -0,0 +1,186 @@ +// Copyright (c) 2009-2016 Vladimir Batov. +// Use, modification and distribution are subject to the Boost Software License, +// Version 1.0. See http://www.boost.org/LICENSE_1_0.txt. + +#include <boost/convert.hpp> +#include <boost/convert/stream.hpp> +#include <boost/convert/lexical_cast.hpp> +#include <boost/detail/lightweight_test.hpp> +#include <boost/array.hpp> +#include <boost/bind.hpp> +#include <vector> + +using std::string; + +static +void +introduction() +{ +//[algorithm_introduction + + /*`The following code demonstrates conversion of an array of integers from their textual ['hexadecimal] + representation. It assigns -1 to those which fail to convert: + */ + + boost::array<char const*, 3> strs = {{ " 5", "0XF", "not an int" }}; + std::vector<int> ints; + boost::cnv::cstream cnv; + + // Configure converter to read hexadecimal, skip (leading) white spaces. + cnv(std::hex)(std::skipws); + + std::transform(strs.begin(), strs.end(), std::back_inserter(ints), + boost::cnv::apply<int>(boost::cref(cnv)).value_or(-1)); + + BOOST_TEST(ints.size() == 3); // Number of values processed. + BOOST_TEST(ints[0] == 5); // " 5" + BOOST_TEST(ints[1] == 15); // "0XF" + BOOST_TEST(ints[2] == -1); // "not an int" +//] +} + +static +void +example1() +{ +//[algorithm_example1 + /*`The following code demonstrates a failed attempt (and one of the reasons ['Boost.Convert] + has been developed) to convert a few `string`s to `int`s with `boost::lexical_cast`: + */ + + boost::array<char const*, 3> strs = {{ " 5", "0XF", "not an int" }}; + std::vector<int> ints; + + try + { + std::transform(strs.begin(), strs.end(), std::back_inserter(ints), + boost::bind(boost::lexical_cast<int, string>, _1)); + + BOOST_TEST(0 && "Never reached!"); + } + catch (std::exception&) + { + BOOST_TEST(ints.size() == 0); // No strings converted. + } +//] +} + +static +void +example2() +{ +//[algorithm_example2 + /*`If the exception-throwing behavior is the desired behavior, then ['Boost.Convert] supports that. + In addition, it also supports a non-throwing process-flow: + */ + boost::array<char const*, 3> strs = {{ " 5", "0XF", "not an int" }}; + std::vector<int> ints; + + std::transform(strs.begin(), strs.end(), std::back_inserter(ints), + boost::cnv::apply<int>(boost::cnv::lexical_cast()).value_or(-1)); + + BOOST_TEST(ints.size() == 3); + BOOST_TEST(ints[0] == -1); // Failed conversion does not throw. + BOOST_TEST(ints[1] == -1); // Failed conversion does not throw. + BOOST_TEST(ints[2] == -1); // Failed conversion does not throw. +//] +} + +static +void +example3() +{ +//[algorithm_example3 + /*`Deploying `boost::cnv::cstream` with better formatting capabilities yields + better results with exception-throwing and non-throwing process-flows still supported: + */ + + boost::array<char const*, 3> strs = {{ " 5", "0XF", "not an int" }}; + std::vector<int> ints; + boost::cnv::cstream cnv; + + try + { + std::transform(strs.begin(), strs.end(), std::back_inserter(ints), + boost::cnv::apply<int>(boost::cref(cnv(std::hex)(std::skipws)))); + + BOOST_TEST(0 && "Never reached!"); + } + catch (boost::bad_optional_access const&) + { + BOOST_TEST(ints.size() == 2); // Only the first two strings converted. + BOOST_TEST(ints[0] == 5); // " 5" + BOOST_TEST(ints[1] == 15); // "0XF" + + // "not an int" causes the exception thrown. + } +//] +} + +static +void +example4() +{ + boost::array<char const*, 3> strs = {{ " 5", "0XF", "not an int" }}; + std::vector<int> ints; + boost::cnv::cstream cnv; + +//[algorithm_example4 + + std::transform(strs.begin(), strs.end(), std::back_inserter(ints), + boost::cnv::apply<int>(boost::cref(cnv(std::hex)(std::skipws))).value_or(-1)); + + BOOST_TEST(ints.size() == 3); + BOOST_TEST(ints[0] == 5); + BOOST_TEST(ints[1] == 15); + BOOST_TEST(ints[2] == -1); // Failed conversion + + /*`[important One notable difference in the deployment of `boost::cnv::cstream` with algorithms is + the use of `boost::cref` (or `std::cref` in C++11). + + It needs to be remembered that with standard algorithms the deployed converter needs to be + [@http://en.cppreference.com/w/cpp/named_req/TriviallyCopyable copyable] or + [@http://en.cppreference.com/w/cpp/named_req/MoveAssignable movable (C++11)] + and is, in fact, copied or moved by the respective algorithm before being used. + Given that `std::cstringstream` is not copyable, `boost::cnv::cstream` is not copyable either. + That limitation is routinely worked-around using `boost::ref` or `boost::cref`.] + */ +//] +} + +static +void +example5() +{ +//[algorithm_example5 + /*`And now an example of algorithm-based integer-to-string formatted conversion with + `std::hex`, `std::uppercase` and `std::showbase` formatting applied: + */ + boost::array<int, 3> ints = {{ 15, 16, 17 }}; + std::vector<std::string> strs; + boost::cnv::cstream cnv; + + cnv(std::hex)(std::uppercase)(std::showbase); + + std::transform(ints.begin(), ints.end(), std::back_inserter(strs), + boost::cnv::apply<string>(boost::cref(cnv))); + + BOOST_TEST(strs.size() == 3); + BOOST_TEST(strs[0] == "0XF"); // 15 + BOOST_TEST(strs[1] == "0X10"); // 16 + BOOST_TEST(strs[2] == "0X11"); // 17 +//] +} + +int +main(int, char const* []) +{ + introduction(); + example1(); + example2(); + example3(); + example4(); + example5(); + + return boost::report_errors(); +} diff --git a/src/boost/libs/convert/example/default_converter.cpp b/src/boost/libs/convert/example/default_converter.cpp new file mode 100644 index 000000000..fdcee8463 --- /dev/null +++ b/src/boost/libs/convert/example/default_converter.cpp @@ -0,0 +1,39 @@ +// Boost.Convert test and usage example +// Copyright (c) 2009-2016 Vladimir Batov. +// Use, modification and distribution are subject to the Boost Software License, +// Version 1.0. See http://www.boost.org/LICENSE_1_0.txt. + +#include <boost/convert.hpp> +#include <boost/convert/stream.hpp> +#include <boost/detail/lightweight_test.hpp> + +#ifdef ONLY_FOR_DEMONSTRATION_PURPOSES +//[default_converter_declaration_simple +struct boost::cnv::by_default : boost::cnv::cstream {}; +//] +#endif +//[default_converter_declaration_formatted +struct boost::cnv::by_default : boost::cnv::cstream +{ + by_default() { (*this)(std::uppercase)(std::hex); } +}; +//] + +int +main(int, char const* []) +{ + //[default_converter_example1 + // No explicit converter provided. boost::cnv::by_default is used. + int i = boost::convert<int>("F").value_or(-1); + std::string s = boost::convert<std::string>(255).value_or("bad"); + + // 'i' and 's' are converted using boost::cnv::cstream + // with std::uppercase and std::hex formatting applied. + + BOOST_TEST(i == 15); // 15(10) = F(16) + BOOST_TEST(s == "FF"); // 255(10) = FF(16) + //] + + return boost::report_errors(); +} + diff --git a/src/boost/libs/convert/example/default_converter_fail.cpp b/src/boost/libs/convert/example/default_converter_fail.cpp new file mode 100644 index 000000000..966399644 --- /dev/null +++ b/src/boost/libs/convert/example/default_converter_fail.cpp @@ -0,0 +1,20 @@ +// Boost.Convert test and usage example +// Copyright (c) 2009-2016 Vladimir Batov. +// Use, modification and distribution are subject to the Boost Software License, +// Version 1.0. See http://www.boost.org/LICENSE_1_0.txt. + +#include <boost/convert.hpp> + +using std::string; +using boost::convert; + +// This is expected to fail to compile: +//'boost::cnv::by_default' : class has no constructors. + +int +main(int, char const* []) +{ + int i = convert<int>("123").value(); + string s = convert<string>(123).value(); +} + diff --git a/src/boost/libs/convert/example/getting_serious.cpp b/src/boost/libs/convert/example/getting_serious.cpp new file mode 100644 index 000000000..1e0b7597d --- /dev/null +++ b/src/boost/libs/convert/example/getting_serious.cpp @@ -0,0 +1,155 @@ +// Copyright (c) 2009-2016 Vladimir Batov. +// Use, modification and distribution are subject to the Boost Software License, +// Version 1.0. See http://www.boost.org/LICENSE_1_0.txt. + +#ifdef BOOST_MSVC +# pragma warning(disable : 4127) // conditional expression is constant. +# pragma warning(disable : 4189) // local variable is initialized but not referenced. +#endif + +#include <boost/convert.hpp> +#include <boost/convert/stream.hpp> +#include <boost/convert/lexical_cast.hpp> + +using std::string; +using boost::convert; +using boost::lexical_cast; +using boost::optional; + +static void process_failure() {} +static void log(...) {} +static int fallback_function() { return -1; } + +//[getting_serious_default_converter +struct boost::cnv::by_default : boost::cnv::cstream {}; +//] +static +void +example1() +{ + boost::cnv::cstream cnv; + std::string const str = "123"; + std::string const str1 = "123"; + std::string const str2 = "123"; + std::string const str3 = "123"; + int const fallback_value = -1; + + { + //[getting_serious_example1 + int i2 = convert<int>("not an int", cnv).value_or(-1); // after the call i2==-1 + + if (i2 == -1) process_failure(); + //] + } + { + //[getting_serious_example2 + try + { + int i1 = lexical_cast<int>(str); // Throws if the conversion fails. + int i2 = convert<int>(str, cnv).value(); // Throws if the conversion fails. + } + catch (...) + { + process_failure(); + } + //] + } + { + //[getting_serious_example3 + optional<int> r1 = convert<int>(str1, cnv); // Does not throw on conversion failure. + optional<int> r2 = convert<int>(str2, cnv); // Does not throw on conversion failure. + // ... + try // Delayed processing of potential exceptions. + { + int i1 = r1.value(); // Will throw if conversion failed. + int i2 = r2.value(); // Will throw if conversion failed. + } + catch (boost::bad_optional_access const&) + { + // Handle failed conversion. + } + + // Exceptions are avoided altogether. + int i1 = r1 ? r1.value() : fallback_value; + int i2 = r2.value_or(fallback_value); + int i3 = convert<int>(str3, cnv).value_or(fallback_value); + int i4 = convert<int>(str3, cnv).value_or_eval(fallback_function); + //] + } +} + +//[getting_serious_example5 +struct fallback_func +{ + int operator()() const { log("Failed to convert"); return 42; } +}; +//] + +static +void +example4() +{ + boost::cnv::cstream cnv; + std::string const str = "123"; + int const fallback_value = -1; + //[getting_serious_example4 + boost::optional<int> res = boost::convert<int>(str, cnv); + + if (!res) log("str conversion failed!"); + + int i1 = res.value_or(fallback_value); + + // ...proceed + //] + //[getting_serious_example6 + // Fallback function is called when failed + int i2 = convert<int>(str, cnv).value_or_eval(fallback_func()); + int i3 = convert<int>(str, cnv, fallback_func()); // Same as above. Alternative API. + //] +} + +static +void +example7() +{ + boost::cnv::cstream cnv; + std::string const str = "123"; + int const fallback_value = -1; + //[getting_serious_example7 + // Error-processing behavior are specified unambiguously and uniformly. + // a) i1: Returns the provided fallback value; + // b) i2: Calls the provided failure-processing function; + // c) i3: Throws an exception. + + int i1 = convert<int>(str, cnv, fallback_value); + int i2 = convert<int>(str, cnv, fallback_func()); + + try + { + // Throwing behavior specified explicitly rather than implied. + int i3 = convert<int>(str, cnv, boost::throw_on_failure); + } + catch (boost::bad_optional_access const&) + { + // Handle failed conversion. + } + //] + //[getting_serious_example8 + int m1 = convert<int>(str, cnv).value_or(fallback_value); + int m2 = convert<int>(str, cnv).value_or_eval(fallback_func()); + int m3 = convert<int>(str, cnv).value(); + //] + //[getting_serious_example9 + int n1 = convert<int>(str).value_or(fallback_value); + int n2 = convert<int>(str).value_or_eval(fallback_func()); + int n3 = convert<int>(str).value(); + //] +} + +int +main(int, char const* []) +{ + example1(); + example4(); + example7(); +} diff --git a/src/boost/libs/convert/example/getting_started.cpp b/src/boost/libs/convert/example/getting_started.cpp new file mode 100644 index 000000000..5fa9c5314 --- /dev/null +++ b/src/boost/libs/convert/example/getting_started.cpp @@ -0,0 +1,268 @@ +// Copyright (c) 2009-2016 Vladimir Batov. +// Use, modification and distribution are subject to the Boost Software License, +// Version 1.0. See http://www.boost.org/LICENSE_1_0.txt. + +#ifdef _MSC_VER +# pragma warning(disable : 4127) // conditional expression is constant. +# pragma warning(disable : 4189) // local variable is initialized but not referenced. +# pragma warning(disable : 4100) // unreferenced formal parameter. +# pragma warning(disable : 4714) // marked as __forceinline not inlined. +#endif + +namespace { namespace local +{ +#if defined(_MSC_VER) + static bool const is_msc = true; +#else + static bool const is_msc = false; +#endif +}} + +#include <boost/bind.hpp> +#include <boost/detail/lightweight_test.hpp> + +static +void +log(char const*) +{ + // Dummy function to demonstrate how problems might be logged. +} + +//[getting_started_headers1 +#include <boost/convert.hpp> +#include <boost/convert/lexical_cast.hpp> +//] + +//[getting_started_using +using std::string; +using boost::lexical_cast; +using boost::convert; +//] +//[getting_started_default_converter +// Definition of the default converter (optional) +struct boost::cnv::by_default : boost::cnv::lexical_cast {}; +//] + +static +void +getting_started_example1() +{ + //[getting_started_example1 + try + { + boost::cnv::lexical_cast cnv; // boost::lexical_cast-based converter + + int i1 = lexical_cast<int>("123"); // boost::lexical_cast standard deployment + int i2 = convert<int>("123").value(); // boost::convert with the default converter + int i3 = convert<int>("123", cnv).value(); // boost::convert with an explicit converter + string s1 = lexical_cast<string>(123); // boost::lexical_cast standard deployment + string s2 = convert<string>(123).value(); // boost::convert with the default converter + string s3 = convert<string>(123, cnv).value(); // boost::convert with an explicit converter + + BOOST_TEST(i1 == 123); + BOOST_TEST(i2 == 123); + BOOST_TEST(i3 == 123); + BOOST_TEST(s1 == "123"); + BOOST_TEST(s2 == "123"); + BOOST_TEST(s3 == "123"); + } + catch (std::exception const& ex) + { + // Please be aware that the conversion requests above can fail. + // Use try'n'catch blocks to handle any exceptions thrown. + // Ignore this at your peril! + std::cerr << "Exception " << ex.what() << std::endl; + } + //] [/getting_started_example1] +} + +static +void +getting_started_example2() +{ + //[getting_started_example2 + // Does not throw. Returns fallback value (-1) when failed. + int i = convert<int>("uhm", boost::cnv::lexical_cast()).value_or(-1); + + BOOST_TEST(i == -1); // Conversion failed. 'i' assigned the fallback value. + //] +} + +//[getting_started_headers3 +#include <boost/convert/strtol.hpp> +#include <boost/convert/spirit.hpp> +//] + +static +void +getting_started_example3() +{ + //[getting_started_example3 + boost::cnv::lexical_cast cnv1; + boost::cnv::strtol cnv2; + boost::cnv::spirit cnv3; + + int i1 = convert<int>("123", cnv1).value(); + int i2 = convert<int>("123", cnv2).value(); // Two times faster than lexical_cast. + int i3 = convert<int>("123", cnv3).value(); // Four times faster than lexical_cast. + //] +} + +//[getting_started_headers4 +#include <boost/convert/stream.hpp> +//] + +static +void +getting_started_example4() +{ + //[getting_started_example4 + boost::cnv::cstream cnv; + + try + { + int i1 = lexical_cast<int>(" 123"); // Does not work. + BOOST_TEST(!"Never reached"); + } + catch (...) {} + + int i2 = convert<int>(" 123", cnv(std::skipws)).value(); // Success + string s1 = lexical_cast<string>(12.34567); + string s2 = convert<string>(12.34567, cnv(std::fixed)(std::setprecision(3))).value(); + string s3 = convert<string>(12.34567, cnv(std::scientific)(std::setprecision(3))).value(); + string expected = local::is_msc ? "1.235e+001" : "1.235e+01"; + + BOOST_TEST(i2 == 123); // boost::cnv::cstream. Successful conversion of " 123". + BOOST_TEST(s1 == "12.34567"); // boost::lexical_cast. Precision is not configurable. + BOOST_TEST(s2 == "12.346"); // boost::cnv::cstream. Precision was set to 3. Fixed. + BOOST_TEST(s3 == expected); // boost::cnv::cstream. Precision was set to 3. Scientific. + //] +} + +static +void +getting_started_example5() +{ + //[getting_started_example5 + boost::cnv::cstream cnv; + + int i1 = lexical_cast<int>("123"); // Throws when conversion fails. + int i2 = convert<int>("123", cnv).value(); // Throws when conversion fails. + int i3 = convert<int>("uhm", cnv).value_or(-1); // Returns -1 when conversion fails. + + BOOST_TEST(i1 == 123); + BOOST_TEST(i2 == 123); + BOOST_TEST(i3 == -1); + //] +} + +static +void +getting_started_example6() +{ + std::string const s1 = "123"; + std::string const s2 = "456"; + int const default_i1 = 11; + int const default_i2 = 12; + boost::cnv::cstream cnv; + + //[getting_started_example6 + + int i1 = convert<int>(s1, cnv(std::hex)).value_or(-1); // Read as hex + int i2 = convert<int>(s2, cnv(std::dec)).value_or(-1); // Read as decimal + + if (i1 == -1) log("bad i1"), i1 = default_i1; // Log failure. Proceed with the default + if (i2 == -1) log("bad i2"), i2 = default_i2; // Log failure. Proceed with the default + + // ... proceed + //] + BOOST_TEST(i1 == 291); + BOOST_TEST(i2 == 456); +} + +static +void +getting_started_example7() +{ + std::string const s1 = "123"; + std::string const s2 = "456"; + int const default_i1 = 11; + int const default_i2 = 12; + boost::cnv::cstream cnv; + + //[getting_started_example7 + + int i1 = convert<int>(s1, cnv(std::hex)).value_or(default_i1); // If failed, proceed with the default + int i2 = convert<int>(s2, cnv(std::dec)).value_or(default_i2); // If failed, proceed with the default + // ... proceed + //] + BOOST_TEST(i1 == 291); + BOOST_TEST(i2 == 456); +} + +static +//[getting_started_example9_func +int +fallback_fun(char const* msg, int fallback_value) +{ + // The principal advantage of a fallback_func over a fallback_value + // is that the former is only called when the conversion request fails. + // Consequently, the returned fallback_value is only calculated (which + // potentially might be expensive) when it is absolutely necessary. + log(msg); return fallback_value; +} +//] +static +void +getting_started_example9() +{ + std::string const s1 = "123"; + std::string const s2 = "456"; + int const default_i1 = 11; + int const default_i2 = 12; + + //[getting_started_example9 + int i1 = convert<int>(s1).value_or_eval(boost::bind(fallback_fun, "bad i1", default_i1)); + int i2 = convert<int>(s2).value_or_eval(boost::bind(fallback_fun, "bad i2", default_i2)); + // ... proceed + //] + BOOST_TEST(i1 == 123); + BOOST_TEST(i2 == 456); +} + +static +void +getting_started_example8() +{ + std::string const str = "123"; + int const default_i1 = 12; + //[getting_started_example8 + int i1 = default_i1; + + try + { + i1 = lexical_cast<int>(str); + } + catch (...) + { + log("bad i1"); + } + //] + BOOST_TEST(i1 == 123); +} + +int +main(int, char const* []) +{ + getting_started_example1(); + getting_started_example2(); + getting_started_example3(); + getting_started_example4(); + getting_started_example5(); + getting_started_example6(); + getting_started_example7(); + getting_started_example8(); + getting_started_example9(); + + return boost::report_errors(); +} diff --git a/src/boost/libs/convert/example/jamfile.v2 b/src/boost/libs/convert/example/jamfile.v2 new file mode 100644 index 000000000..485cb4914 --- /dev/null +++ b/src/boost/libs/convert/example/jamfile.v2 @@ -0,0 +1,34 @@ +# Convert Jamfile +# Copyright (c) Vladimir Batov 2009-2014 +# Distributed under the Boost Software License, Version 1.0. +# See copy at http://www.boost.org/LICENSE_1_0.txt. + +# bring in the rules for testing +import testing ; + +project convert_examples + : requirements + <warnings>on + <toolset>gcc:<warnings>all + <toolset>msvc:<warnings>all + <toolset>gcc:<cxxflags>"-Wno-unused-local-typedefs -Wno-unused-variable -Wno-long-long" + <toolset>msvc:<cxxflags>"/wd4996 /wd4512 /wd4610 /wd4510 /wd4127 /wd4701 /wd4127 /wd4305 /wd4100 /wd4512 /wd4714" + <toolset>msvc:<asynch-exceptions>on + <toolset>msvc:<define>_CRT_SECURE_NO_DEPRECATE + <toolset>msvc:<define>_SCL_SECURE_NO_DEPRECATE + <toolset>msvc:<define>_SCL_SECURE_NO_WARNINGS + <toolset>msvc:<define>_CRT_SECURE_NO_WARNINGS + <include>../include + ; + +run algorithms.cpp : : : : convert_example_algorithms ; +run default_converter.cpp : : : : convert_example_default_converter ; +run getting_serious.cpp : : : : convert_example_getting_started ; +run getting_started.cpp : : : : convert_example_getting_serious ; +run lexical_cast.cpp : : : : convert_example_lexical_cast_converter ; +run stream.cpp : : : : convert_example_stream_converter ; + +compile-fail default_converter_fail.cpp : <warnings>off <cxxflags>"-w" ; + + + diff --git a/src/boost/libs/convert/example/lexical_cast.cpp b/src/boost/libs/convert/example/lexical_cast.cpp new file mode 100644 index 000000000..5527cf142 --- /dev/null +++ b/src/boost/libs/convert/example/lexical_cast.cpp @@ -0,0 +1,35 @@ +// Copyright (c) 2009-2016 Vladimir Batov. +// Use, modification and distribution are subject to the Boost Software License, +// Version 1.0. See http://www.boost.org/LICENSE_1_0.txt. + +//[lexical_cast_headers1 +#include <boost/convert.hpp> +#include <boost/convert/lexical_cast.hpp> +#include <boost/detail/lightweight_test.hpp> + +using std::string; +using boost::convert; +using boost::lexical_cast; + +struct boost::cnv::by_default : boost::cnv::lexical_cast {}; +//] + +int +main(int, char const* []) +{ + //[lexical_cast_example1 + int i1 = lexical_cast<int>("123"); // Throws if the conversion fails. + int i2 = convert<int>("123").value(); // Throws if the conversion fails. + int i3 = convert<int>("uhm").value_or(-1); // Returns -1 if the conversion fails. + string s1 = lexical_cast<string>(123); + string s2 = convert<string>(123).value(); + + BOOST_TEST(i1 == 123); + BOOST_TEST(i2 == 123); + BOOST_TEST(i3 == -1); + BOOST_TEST(s1 == "123"); + BOOST_TEST(s2 == "123"); + //] + + return boost::report_errors(); +} diff --git a/src/boost/libs/convert/example/stream.cpp b/src/boost/libs/convert/example/stream.cpp new file mode 100644 index 000000000..0a22c2346 --- /dev/null +++ b/src/boost/libs/convert/example/stream.cpp @@ -0,0 +1,101 @@ +// Copyright (c) 2009-2016 Vladimir Batov. +// Use, modification and distribution are subject to the Boost Software License, +// Version 1.0. See http://www.boost.org/LICENSE_1_0.txt. + +#include <boost/convert.hpp> +#include <boost/convert/lexical_cast.hpp> + +//[stream_headers1 +#include <boost/convert.hpp> +#include <boost/convert/stream.hpp> +#include <boost/detail/lightweight_test.hpp> + +using std::string; +using boost::convert; + +struct boost::cnv::by_default : boost::cnv::cstream {}; +//] +//[stream_headers2 +namespace cnv = boost::cnv; +namespace arg = boost::cnv::parameter; +//] + +#include "../test/test.hpp" + +static +void +example1() +{ + //[stream_example1 + int i2 = convert<int>("123").value(); // Throws when fails. + int i3 = convert<int>("uhm").value_or(-1); // Returns -1 when fails. + string s2 = convert<string>(123).value(); + + BOOST_TEST(i2 == 123); + BOOST_TEST(i3 == -1); + BOOST_TEST(s2 == "123"); + //] +} + +static +void +example2() +{ + //[stream_example2 + boost::cnv::cstream ccnv; + boost::cnv::wstream wcnv; + + int v01 = convert<int>(" FF", ccnv(std::hex)(std::skipws)).value_or(0); + int v02 = convert<int>(L" F", wcnv(std::hex)(std::skipws)).value_or(0); + int v03 = convert<int>(" FF", ccnv(std::dec)(std::skipws)).value_or(-5); + int v04 = convert<int>(L" F", wcnv(std::dec)(std::skipws)).value_or(-5); + + BOOST_TEST(v01 == 255); // "FF" + BOOST_TEST(v02 == 15); // L"F" + BOOST_TEST(v03 == -5); // Failed to convert "FF" as decimal. + BOOST_TEST(v04 == -5); // Failed to convert L"F" as decimal. + //] + //[stream_example3 + ccnv(std::showbase)(std::uppercase)(std::hex); + + BOOST_TEST(convert<string>(255, ccnv, "bad") == "0XFF"); + BOOST_TEST(convert<string>( 15, ccnv, "bad") == "0XF"); + //] + //[stream_example4 + ccnv(arg::base = cnv::base::dec) + (arg::uppercase = true) + (arg::notation = cnv::notation::scientific); + //] + //[stream_example5 + ccnv(std::dec)(std::uppercase)(std::scientific); + //] +} + +static +void +example6() +{ + //[stream_example6 + boost::cnv::cstream cnv1; + boost::cnv::lexical_cast cnv2; + + change chg = change::up; + string s1 = convert<string>(chg, cnv1, "bad"); // Input type (change) deduced + string s2 = convert<string, change>(change::dn, cnv1, "bad"); // Input type (change) enforced + + BOOST_TEST(convert<change>("up", cnv1, change::no) == change::up); + BOOST_TEST(convert<change>("up", cnv2, change::no) == change::up); + BOOST_TEST(s1 == "up"); + BOOST_TEST(s2 == "dn"); + //] +} + +int +main(int, char const* []) +{ + example1(); + example2(); + example6(); + + return boost::report_errors(); +} diff --git a/src/boost/libs/convert/index.html b/src/boost/libs/convert/index.html new file mode 100644 index 000000000..6cc92f7fa --- /dev/null +++ b/src/boost/libs/convert/index.html @@ -0,0 +1,29 @@ +<!DOCTYPE html> +<html> +<head> +<title>Boost.Convert</title> +<meta charset="utf-8"> +<meta http-equiv="refresh" content="0; url=doc/html/index.html"> +<style> + body { + background: #fff; + color: #000; + } + a { + color: #00f; + text-decoration: none; + } +</style> +</head> +<body> + <p> + Automatic redirection failed, please go to <a href="doc/html/index.html">doc/html/index.html</a> + </p> + <p>Copyright Vladimir Batov 2009-2016</p> + <p>Distributed under the Boost Software License, Version 1.0. (See accompanying file + <a href="../../LICENSE_1_0.txt">LICENSE_1_0.txt</a> or copy at + <a href="http://www.boost.org/LICENSE_1_0.txt">www.boost.org/LICENSE_1_0.txt</a>). + </p> +</body> +</html> + diff --git a/src/boost/libs/convert/makefile b/src/boost/libs/convert/makefile new file mode 100644 index 000000000..98d69831f --- /dev/null +++ b/src/boost/libs/convert/makefile @@ -0,0 +1,29 @@ +BOOST_ROOT = $(PRJROOT)/boost + +cflags = -O3 -I./include -I$(BOOST_ROOT) -Wno-unused-variable -Wno-uninitialized -Wno-deprecated-declarations +lflags = -L$(BOOST_ROOT)/stage/lib -lboost_timer -lboost_chrono -lboost_system + +target_1 = convert-test-callable test/callable.cpp +target_2 = convert-test-is-converter test/is_converter.cpp +target_3 = convert-test-fallbacks test/fallbacks.cpp +target_4 = convert-test-spirit-converter test/spirit_converter.cpp +target_5 = convert-test-stream-converter test/stream_converter.cpp +target_6 = convert-test-lcast-converter test/lcast_converter.cpp +target_7 = convert-test-printf-converter test/printf_converter.cpp +target_8 = convert-test-strtol-converter test/strtol_converter.cpp +target_9 = convert-test-encryption test/encryption.cpp +target_10 = convert-test-user-type test/user_type.cpp +target_11 = convert-test-str-to-int test/str_to_int.cpp +target_12 = convert-test-sfinae test/sfinae.cpp +target_13 = convert-test-has-member test/has_member.cpp +target_14 = convert-test-performance test/performance.cpp +target_15 = convert-test-performance-spirit test/performance_spirit.cpp + +target_21 = convert-example-algorithms example/algorithms.cpp +target_22 = convert-example-default_converter example/default_converter.cpp +target_23 = convert-example-getting_serious example/getting_serious.cpp +target_24 = convert-example-getting_started example/getting_started.cpp +target_25 = convert-example-lexical_cast example/lexical_cast.cpp +target_26 = convert-example-stream example/stream.cpp + +include $(PRJROOT)/make/makefile diff --git a/src/boost/libs/convert/meta/libraries.json b/src/boost/libs/convert/meta/libraries.json new file mode 100644 index 000000000..23e9511f1 --- /dev/null +++ b/src/boost/libs/convert/meta/libraries.json @@ -0,0 +1,11 @@ +{ + "key": "convert", + "name": "Convert", + "authors": [ "Vladimir Batov" ], + "maintainers": [ "Vladimir Batov <vbmail247 -at- gmail.com>" ], + "description": "An extendible and configurable type-conversion framework.", + "category": [ + "Miscellaneous", + "String" + ] +} diff --git a/src/boost/libs/convert/test/callable.cpp b/src/boost/libs/convert/test/callable.cpp new file mode 100644 index 000000000..b8f36146b --- /dev/null +++ b/src/boost/libs/convert/test/callable.cpp @@ -0,0 +1,114 @@ +// Boost.Convert test and usage example +// Copyright (c) 2009-2016 Vladimir Batov. +// Use, modification and distribution are subject to the Boost Software License, +// Version 1.0. See http://www.boost.org/LICENSE_1_0.txt. + +#include "./test.hpp" + +#if defined(BOOST_CONVERT_IS_NOT_SUPPORTED) +int main(int, char const* []) { return 0; } +#else + +#include <boost/convert.hpp> +#include <boost/convert/lexical_cast.hpp> +#include <boost/detail/lightweight_test.hpp> +#include <boost/function.hpp> +#include <boost/bind.hpp> + +using std::string; +using boost::convert; +using boost::lexical_cast; + +//[callable_example1 +void plain_old_func(string const& value_in, boost::optional<int>& value_out) +//] +{ + try + { + value_out = lexical_cast<int>(value_in); + } + catch (...) + { + } +} + +template<typename TypeIn, typename TypeOut> +void +convert_all(TypeIn const&, boost::optional<TypeOut>&) +{ +} + +template<typename Type> +void +assign(boost::optional<Type>& value_out, Type const& value_in) +{ + value_out = value_in; +} + +struct converter1 +{ + template<typename TypeIn, typename TypeOut> + void + operator()(TypeIn const&, boost::optional<TypeOut>&) const + { + } +}; + +//[callable_example4 +struct take_double { void operator()(double, boost::optional<string>&) const {}}; +struct take_int { void operator()(int, boost::optional<string>&) const {}}; +//] + +//[callable_example6 +struct double_only +{ + // Declared for all types. + template<typename TypeIn> void operator()(TypeIn, boost::optional<string>&) const; +}; + +// Defined only for certain types. +template<> void double_only::operator()<double>(double, boost::optional<string>&) const {} +//] + +int +main(int, char const* []) +{ + typedef boost::function<void (string const& value_in, boost::optional<int>&)> boost_func; + + char const* const str = "-12"; + + // Testing old-function-based converter. + //[callable_example2 + int v01 = convert<int>(str, plain_old_func).value_or(-1); + //] + // Testing boost::function-based converter. + int v02 = convert<int>(str, boost_func(plain_old_func)).value_or(-1); + // Testing crazy boost::bind-based converter. + //[callable_example3 + int v03 = convert<int>(str, + boost::bind(assign<int>, _2, + boost::bind(lexical_cast<int, string>, _1))).value_or(-1); + //] + BOOST_TEST(v01 == -12); + BOOST_TEST(v02 == -12); + BOOST_TEST(v03 == -12); + + convert<int>(str, convert_all<string, int>); + convert<string>(11, convert_all<int, string>); + convert< int>(str, converter1()); + convert<string>(11, converter1()); + convert<string>(11.23, take_double()); + convert<string>(11, take_int()); + //[callable_example5 + convert<string>(11, take_double()); // Compiler applies int-to-double promotion to call the converter. + convert<string>(11.23, take_int()); // Compiler applies double-to-int implicit truncation. + //] + //[callable_example7 + convert<string>(11.23, double_only()); // Fine. +// convert<string>(11, double_only()); // Fails: undefined reference to double_only::operator()<int> + //] + + return boost::report_errors(); +} + +#endif diff --git a/src/boost/libs/convert/test/encryption.cpp b/src/boost/libs/convert/test/encryption.cpp new file mode 100644 index 000000000..684c6d506 --- /dev/null +++ b/src/boost/libs/convert/test/encryption.cpp @@ -0,0 +1,44 @@ +// Copyright (c) 2009-2016 Vladimir Batov. +// Use, modification and distribution are subject to the Boost Software License, +// Version 1.0. See http://www.boost.org/LICENSE_1_0.txt. + +#include "./test.hpp" + +#if defined(BOOST_CONVERT_IS_NOT_SUPPORTED) +int main(int, char const* []) { return 0; } +#else + +#include <boost/convert.hpp> +#include <boost/detail/lightweight_test.hpp> + +static +bool +my_cypher(std::string const& value_in, boost::optional<std::string>& value_out) +{ + size_t const cypher = 'A' - '1'; + + value_out = value_in; + + for (std::string::iterator it = value_out->begin(); it != value_out->end(); ++it) + (*it < 'A') ? (*it += cypher) : (*it -= cypher); + + return true; +} + +int +main(int, char const* []) +{ + //////////////////////////////////////////////////////////////////////////// + // Testing custom converter. + //////////////////////////////////////////////////////////////////////////// + + std::string encrypted = boost::convert<std::string>("ABC", my_cypher).value(); + std::string decrypted = boost::convert<std::string>(encrypted, my_cypher).value(); + + BOOST_TEST(encrypted == "123"); + BOOST_TEST(decrypted == "ABC"); + + return boost::report_errors(); +} + +#endif diff --git a/src/boost/libs/convert/test/fallbacks.cpp b/src/boost/libs/convert/test/fallbacks.cpp new file mode 100644 index 000000000..b0192e9b1 --- /dev/null +++ b/src/boost/libs/convert/test/fallbacks.cpp @@ -0,0 +1,81 @@ +// Boost.Convert test and usage example +// Copyright (c) 2009-2016 Vladimir Batov. +// Use, modification and distribution are subject to the Boost Software License, +// Version 1.0. See http://www.boost.org/LICENSE_1_0.txt. + +#include "./test.hpp" + +#if defined(BOOST_CONVERT_IS_NOT_SUPPORTED) +int main(int, char const* []) { return 0; } +#else + +#include <boost/convert.hpp> +#include <boost/convert/stream.hpp> +#include <boost/detail/lightweight_test.hpp> +#include <boost/function.hpp> +#include <boost/bind.hpp> + +namespace { namespace local +{ + bool called_functor_int; + bool called_functor_double; + bool called_functor_foo; + bool called_function_int; + bool called_function_long; +}} + +struct functor_int { int operator() () const { local:: called_functor_int = true; return INT_MAX; }}; +struct functor_double { double operator() () const { local::called_functor_double = true; return INT_MAX; }}; +struct functor_foo { int func (int) const { local:: called_functor_foo = true; return INT_MAX; }}; + +int function_int () { local:: called_function_int = true; return INT_MAX; } +long function_long () { local::called_function_long = true; return INT_MAX; } + +int +main(int, char const* []) +{ + boost::cnv::cstream cnv; + functor_foo foo; + + int i01 = boost::convert<int>("uhm", cnv).value_or_eval(functor_int()); + int i02 = boost::convert<int>("uhm", cnv).value_or_eval(functor_double()); + int i03 = boost::convert<int>("uhm", cnv).value_or_eval(boost::bind(&functor_foo::func, foo, 0)); + int i04 = boost::convert<int>("uhm", cnv).value_or_eval(function_int); + int i05 = boost::convert<int>("uhm", cnv).value_or_eval(function_long); + + BOOST_TEST(local:: called_functor_int && i01 == INT_MAX); + BOOST_TEST(local::called_functor_double && i02 == INT_MAX); + BOOST_TEST(local:: called_functor_foo && i03 == INT_MAX); + BOOST_TEST(local:: called_function_int && i04 == INT_MAX); + BOOST_TEST(local:: called_function_long && i05 == INT_MAX); + + local:: called_functor_int = false; + local::called_functor_double = false; + local:: called_functor_foo = false; + local:: called_function_int = false; + local:: called_function_long = false; + + boost::convert<int>("uhm", cnv, functor_int()); + boost::convert<int>("uhm", cnv, functor_double()); + boost::convert<int>("uhm", cnv, boost::bind(&functor_foo::func, foo, 0)); + boost::convert<int>("uhm", cnv, function_int); + boost::convert<int>("uhm", cnv, function_long); + + BOOST_TEST(local:: called_functor_int && i01 == INT_MAX); + BOOST_TEST(local::called_functor_double && i02 == INT_MAX); + BOOST_TEST(local:: called_functor_foo && i03 == INT_MAX); + BOOST_TEST(local:: called_function_int && i04 == INT_MAX); + BOOST_TEST(local:: called_function_long && i05 == INT_MAX); + + try + { + boost::convert<int>("uhm", cnv, boost::throw_on_failure); + BOOST_TEST(0); + } + catch (boost::bad_optional_access const&) + { + } + return boost::report_errors(); +} + +#endif diff --git a/src/boost/libs/convert/test/has_member.cpp b/src/boost/libs/convert/test/has_member.cpp new file mode 100644 index 000000000..088d047ae --- /dev/null +++ b/src/boost/libs/convert/test/has_member.cpp @@ -0,0 +1,104 @@ +// Boost.Convert test and usage example +// Copyright (c) 2009-2016 Vladimir Batov. +// Use, modification and distribution are subject to the Boost Software License, +// Version 1.0. See http://www.boost.org/LICENSE_1_0.txt. + +#include "./test.hpp" + +#if defined(BOOST_CONVERT_IS_NOT_SUPPORTED) +int main(int, char const* []) { return 0; } +#else + +#include <boost/convert.hpp> +#include <boost/detail/lightweight_test.hpp> +#include <vector> +#include <iostream> + +//[has_member_declaration +namespace { namespace local +{ + BOOST_DECLARE_HAS_MEMBER(has_begin, begin); + BOOST_DECLARE_HAS_MEMBER(has_funop, operator()); +}} +//] +//[has_member_classes_tested +namespace { namespace local +{ + struct test01 { int begin; }; + struct test02 { char* begin() { return 0; } }; + struct test22 { void operator()() {} }; +}} +//] + +namespace { namespace local +{ + struct test03 + { + void begin(int) {} + int begin(int, int) { return 0; } + }; + struct test04 + { + virtual ~test04() {} + + private: virtual char* begin() { return 0; } + }; + struct test05 + { + virtual char* begin() { return 0; } + virtual ~test05() {} + }; + struct test06 : public test04 {}; + struct test07 : private test04 {}; + struct test08 : public test05 {}; + struct test09 : private test05 {}; + + struct test11 { int no_begin; }; + struct test12 { char* no_begin() { return 0; } }; +}} + +namespace { namespace local +{ + struct test21 { void zoo () {} }; + struct test23 { void operator() () const {} }; + struct test24 { int operator() (int) { return 0; } }; + struct test25 { int operator() (int) const { return 0; } }; + struct test26 { int operator() (int) const { return 0; } void operator() () const {} }; +}} + +int +main(int, char const* []) +{ + BOOST_TEST(local::has_begin<local::test01>::value == true); + BOOST_TEST(local::has_begin<local::test02>::value == true); + BOOST_TEST(local::has_begin<local::test03>::value == true); + BOOST_TEST(local::has_begin<local::test04>::value == true); + BOOST_TEST(local::has_begin<local::test05>::value == true); + BOOST_TEST(local::has_begin<local::test06>::value == true); + BOOST_TEST(local::has_begin<local::test07>::value == true); + BOOST_TEST(local::has_begin<local::test08>::value == true); + BOOST_TEST(local::has_begin<local::test09>::value == true); + BOOST_TEST(local::has_begin<std::string>::value == true); + BOOST_TEST(local::has_begin<std::vector<int> >::value == true); + + BOOST_TEST(local::has_begin<local::test11>::value == false); + BOOST_TEST(local::has_begin<local::test12>::value == false); + BOOST_TEST(local::has_begin<std::iostream>::value == false); + + //[has_member_usage + BOOST_TEST(local::has_begin<local::test01>::value == true); + BOOST_TEST(local::has_begin<local::test02>::value == true); + BOOST_TEST(local::has_funop<local::test22>::value == true); + //] + + BOOST_TEST(local::has_funop<local::test21>::value == false); + BOOST_TEST(local::has_funop<local::test22>::value == true); + BOOST_TEST(local::has_funop<local::test23>::value == true); + BOOST_TEST(local::has_funop<local::test24>::value == true); + BOOST_TEST(local::has_funop<local::test25>::value == true); + BOOST_TEST(local::has_funop<local::test26>::value == true); + + return boost::report_errors(); +} + +#endif diff --git a/src/boost/libs/convert/test/is_converter.cpp b/src/boost/libs/convert/test/is_converter.cpp new file mode 100644 index 000000000..f528a33c5 --- /dev/null +++ b/src/boost/libs/convert/test/is_converter.cpp @@ -0,0 +1,86 @@ +// Boost.Convert test and usage example +// Copyright (c) 2009-2016 Vladimir Batov. +// Use, modification and distribution are subject to the Boost Software License, +// Version 1.0. See http://www.boost.org/LICENSE_1_0.txt. + +#include "./test.hpp" + +#if defined(BOOST_CONVERT_IS_NOT_SUPPORTED) +int main(int, char const* []) { return 0; } +#else + +#include <boost/convert.hpp> +#include <boost/convert/detail/is_converter.hpp> +#include <boost/detail/lightweight_test.hpp> + +using std::string; +using std::wstring; + +namespace { namespace local +{ + typedef void not_converter01 (string const&); + typedef void not_converter02 (int const&, string const&); + typedef void not_converter03 (); + typedef void converter01 (int const&, boost::optional<string>&); + typedef void converter02 (double const&, boost::optional<string>&); + + struct converter11 + { + void operator()(int const&, boost::optional<string>&) {} + void operator()(double const&, boost::optional<string>&) {} + void operator()(string const&, boost::optional<int>&) {} + }; + struct converter12 + { + template<typename TypeIn, typename TypeOut> void operator()(TypeIn const&, boost::optional<TypeOut>&) {} + }; + struct converter13 + { + void operator()(int const&, boost::optional<string>&) {} + }; + struct converter14 + { + void operator()(int const&, boost::optional<string>&) const {} + }; + struct not_converter11 + { + }; + struct not_converter12 + { + void operator()() {} + }; + struct not_converter13 + { + void operator()(int const&, string const&) {} + }; +}} + +int +main(int, char const* []) +{ + BOOST_TEST( (boost::cnv::is_cnv<local::converter01, int, string>::value)); + BOOST_TEST( (boost::cnv::is_cnv<local::converter01, double, string>::value)); + BOOST_TEST( (boost::cnv::is_cnv<local::converter01, short int, string>::value)); + BOOST_TEST( (boost::cnv::is_cnv<local::converter11, int, string>::value)); + BOOST_TEST( (boost::cnv::is_cnv<local::converter11, double, string>::value)); + BOOST_TEST( (boost::cnv::is_cnv<local::converter11, string, int>::value)); + BOOST_TEST( (boost::cnv::is_cnv<local::converter12, int, string>::value)); + BOOST_TEST( (boost::cnv::is_cnv<local::converter12, double, string>::value)); + BOOST_TEST( (boost::cnv::is_cnv<local::converter12, string, int>::value)); + BOOST_TEST( (boost::cnv::is_cnv<local::converter13, int, string>::value)); + BOOST_TEST( (boost::cnv::is_cnv<local::converter13, double, string>::value)); + BOOST_TEST( (boost::cnv::is_cnv<local::converter13, int, string>::value)); + BOOST_TEST( (boost::cnv::is_cnv<local::converter14, int, string>::value)); + BOOST_TEST(!(boost::cnv::is_cnv<local::converter13, string, int>::value)); + BOOST_TEST(!(boost::cnv::is_cnv<local::converter14, string, int>::value)); + + BOOST_TEST(!(boost::cnv::is_cnv<local::not_converter01, int, string>::value)); + BOOST_TEST(!(boost::cnv::is_cnv<local::not_converter02, int, string>::value)); + BOOST_TEST(!(boost::cnv::is_cnv<local::not_converter11, int, string>::value)); + BOOST_TEST(!(boost::cnv::is_cnv<local::not_converter12, int, string>::value)); + BOOST_TEST(!(boost::cnv::is_cnv<local::not_converter13, int, string>::value)); + + return boost::report_errors(); +} + +#endif diff --git a/src/boost/libs/convert/test/jamfile.v2 b/src/boost/libs/convert/test/jamfile.v2 new file mode 100644 index 000000000..9a60a3f5d --- /dev/null +++ b/src/boost/libs/convert/test/jamfile.v2 @@ -0,0 +1,41 @@ +# Convert Jamfile +# Copyright (c) Vladimir Batov 2009-2014 +# Distributed under the Boost Software License, Version 1.0. +# See copy at http://www.boost.org/LICENSE_1_0.txt. + +# bring in the rules for testing +import testing ; + +project convert_test + : requirements + <warnings>on + <toolset>icpc:<cxxflags>"-std=c++11" + <toolset>clang:<cxxflags>"-std=c++11" + <toolset>gcc:<warnings>all + <toolset>gcc:<cxxflags>"-O3 -std=c++0x -Wno-unused-variable -Wno-unused-local-typedefs -Wno-long-long" + <toolset>msvc:<warnings>all + <toolset>msvc:<cxxflags>"/wd4996 /wd4512 /wd4610 /wd4510 /wd4127 /wd4701 /wd4127 /wd4305 /wd4244 /wd4714 /wd4189" + <toolset>msvc:<asynch-exceptions>on + <toolset>msvc:<define>_CRT_SECURE_NO_DEPRECATE + <toolset>msvc:<define>_SCL_SECURE_NO_DEPRECATE + <toolset>msvc:<define>_SCL_SECURE_NO_WARNINGS + <toolset>msvc:<define>_CRT_SECURE_NO_WARNINGS + <include>../include + ; + +exe convert_test_performance : performance.cpp /boost/timer//boost_timer ; +exe convert_test_performance_spirit : performance_spirit.cpp ; + +run callable.cpp : : : : convert_test_callable ; +run fallbacks.cpp : : : : convert_test_fallbacks ; +run spirit_converter.cpp : : : : convert_test_spirit_converter ; +run stream_converter.cpp : : : : convert_test_stream_converter ; +run printf_converter.cpp : : : : convert_test_printf_converter ; +run strtol_converter.cpp : : : : convert_test_strtol_converter ; +run lcast_converter.cpp : : : : convert_test_lcast_converter ; +run encryption.cpp : : : : convert_test_encryption ; +run user_type.cpp : : : : convert_test_user_type ; +run str_to_int.cpp : : : : convert_test_str_to_int ; +run sfinae.cpp : : : : convert_test_sfinae ; +run has_member.cpp : : : : convert_test_has_member ; + diff --git a/src/boost/libs/convert/test/lcast_converter.cpp b/src/boost/libs/convert/test/lcast_converter.cpp new file mode 100644 index 000000000..8cd14c448 --- /dev/null +++ b/src/boost/libs/convert/test/lcast_converter.cpp @@ -0,0 +1,77 @@ +// Boost.Convert test and usage example +// Copyright (c) 2009-2016 Vladimir Batov. +// Use, modification and distribution are subject to the Boost Software License, +// Version 1.0. See http://www.boost.org/LICENSE_1_0.txt. + +#include "./test.hpp" + +#if defined(BOOST_CONVERT_IS_NOT_SUPPORTED) +int main(int, char const* []) { return 0; } +#else + +#include <boost/convert.hpp> +#include <boost/convert/lexical_cast.hpp> +#include <boost/detail/lightweight_test.hpp> + +using std::string; +using boost::convert; + +struct boost::cnv::by_default : boost::cnv::lexical_cast {}; + +static +void +test_invalid() +{ + char const* str[] = { "not", "1 2", " 33", "44 ", "0x11", "7 + 5" }; + int const size = sizeof(str) / sizeof(str[0]); + + for (int k = 0; k < size; ++k) + { + boost::optional<int> const res = convert<int>(str[k]); + bool const failed = !res; + + if (!failed) + { + printf("test::cnv::invalid() failed for: <%s><%d>\n", str[k], res.value()); + } + BOOST_TEST(failed); + } +} + +static +void +test_dbl_to_str() +{ +// printf("100.00 %s\n", convert<string>( 99.999).value().c_str()); +// printf( "99.95 %s\n", convert<string>( 99.949).value().c_str()); +// printf("-99.95 %s\n", convert<string>(-99.949).value().c_str()); +// printf( "99.9 %s\n", convert<string>( 99.949).value().c_str()); +// printf( "1.00 %s\n", convert<string>( 0.999).value().c_str()); +// printf( "-1.00 %s\n", convert<string>( -0.999).value().c_str()); +// printf( "0.95 %s\n", convert<string>( 0.949).value().c_str()); +// printf( "-0.95 %s\n", convert<string>( -0.949).value().c_str()); +// printf( "1.9 %s\n", convert<string>( 1.949).value().c_str()); +// printf( "-1.9 %s\n", convert<string>( -1.949).value().c_str()); +} + +int +main(int, char const* []) +{ + string const not_int_str = "not an int"; + string const std_str = "-11"; + char const* const c_str = "-12"; + int const v00 = convert<int>(not_int_str).value_or(-1); + int const v01 = convert<int>( std_str).value_or(-1); + int const v02 = convert<int>( c_str).value_or(-1); + + BOOST_TEST(v00 == -1); // Failed conversion. No throw + BOOST_TEST(v01 == -11); + BOOST_TEST(v02 == -12); + + test_invalid(); + test_dbl_to_str(); + + return boost::report_errors(); +} + +#endif diff --git a/src/boost/libs/convert/test/performance.cpp b/src/boost/libs/convert/test/performance.cpp new file mode 100644 index 000000000..ac2080970 --- /dev/null +++ b/src/boost/libs/convert/test/performance.cpp @@ -0,0 +1,317 @@ +// Boost.Convert test and usage example +// Copyright (c) 2009-2016 Vladimir Batov. +// Use, modification and distribution are subject to the Boost Software License, +// Version 1.0. See http://www.boost.org/LICENSE_1_0.txt. + +#include "./test.hpp" + +#if defined(BOOST_CONVERT_IS_NOT_SUPPORTED) +int main(int, char const* []) { return 0; } +#else + +#include "./prepare.hpp" +#include <boost/convert.hpp> +#include <boost/convert/stream.hpp> +#include <boost/convert/printf.hpp> +#include <boost/convert/strtol.hpp> +#include <boost/convert/spirit.hpp> +#include <boost/convert/lexical_cast.hpp> +#include <boost/detail/lightweight_test.hpp> +#include <boost/timer/timer.hpp> +#include <boost/array.hpp> +#include <boost/random/mersenne_twister.hpp> +#include <boost/random/uniform_int_distribution.hpp> +#include <cstdlib> +#include <cstdio> + +using std::string; +using boost::convert; + +namespace cnv = boost::cnv; +namespace arg = boost::cnv::parameter; + +namespace { namespace local +{ + template<typename Type> + struct array + { + typedef boost::array<Type, 20> type; + }; + template<typename T> static typename array<T>::type const& get(); + + static int const num_cycles = 1000000; + int sum = 0; + + struct timer : public boost::timer::cpu_timer + { + typedef timer this_type; + typedef boost::timer::cpu_timer base_type; + + double value() const + { + boost::timer::cpu_times times = base_type::elapsed(); + int const use_sum = (sum % 2) ? 0 : (sum % 2); BOOST_TEST(use_sum == 0); + + return double(times.user + times.system) / 1000000000 + use_sum; + } + }; + template< typename Type, typename Cnv> static double str_to (Cnv const&); + template<typename S, typename Type, typename Cnv> static double to_str (Cnv const&); + + template<> + local::array<int>::type const& + get<int>() + { + static array<int>::type ints; + static bool filled; + + if (!filled) + { + boost::random::mt19937 gen (::time(0)); + boost::random::uniform_int_distribution<> dist (INT_MIN, INT_MAX); // INT_MAX(32) = 2,147,483,647 + + for (size_t k = 0; k < ints.size(); ++k) + ints[k] = dist(gen); + + filled = true; + } + return ints; + } + template<> + array<long int>::type const& + get<long int>() + { + static array<long int>::type ints; + static bool filled; + + if (!filled) + { + boost::random::mt19937 gen (::time(0)); + boost::random::uniform_int_distribution<> dist (INT_MIN, INT_MAX); // INT_MAX(32) = 2147483647 + + for (size_t k = 0; k < ints.size(); ++k) + ints[k] = dist(gen); + + filled = true; + } + return ints; + } + template<> + array<double>::type const& + get<double>() + { + static array<double>::type dbls; + static bool filled; + + if (!filled) + { + boost::random::mt19937 gen (::time(0)); + boost::random::uniform_int_distribution<> dist (INT_MIN, INT_MAX); // INT_MAX(32) = 2147483647 + + for (size_t k = 0; k < dbls.size(); ++k) + dbls[k] = double(dist(gen)) + 0.7654321; + + filled = true; + } + return dbls; + } +}} + +struct raw_str_to_int_spirit +{ + int operator()(char const* str) const + { + char const* beg = str; + char const* end = beg + strlen(str); + int result; + + if (boost::spirit::qi::parse(beg, end, boost::spirit::int_, result)) + if (beg == end) // ensure the whole string was parsed + return result; + + return (BOOST_ASSERT(0), result); + } +}; + +struct raw_str_to_int_lxcast +{ + int operator()(char const* str) const + { + return boost::lexical_cast<int>(str); + } +}; + +template<typename Type, typename Converter> +double +raw_str_to(Converter const& cnv) +{ + local::strings strings = local::get_strs(); // Create strings on the stack + int const size = strings.size(); + local::timer timer; + + for (int t = 0; t < local::num_cycles; ++t) + for (int k = 0; k < size; ++k) + local::sum += cnv(strings[k].c_str()); + + return timer.value(); +} + +template<typename Type, typename Converter> +double +local::str_to(Converter const& try_converter) +{ + local::strings strings = local::get_strs(); // Create strings on the stack + int const size = strings.size(); + local::timer timer; + + for (int t = 0; t < local::num_cycles; ++t) + for (int k = 0; k < size; ++k) + local::sum += boost::convert<Type>(strings[k].c_str(), try_converter).value(); + + return timer.value(); +} + +template<typename string_type, typename Type, typename Converter> +double +local::to_str(Converter const& try_converter) +{ + typedef typename local::array<Type>::type collection; + + collection values = local::get<Type>(); + int const size = values.size(); + local::timer timer; + + for (int t = 0; t < local::num_cycles; ++t) + for (int k = 0; k < size; ++k) + local::sum += *boost::convert<string_type>(Type(values[k]), try_converter).value().begin(); + + return timer.value(); +} + +template<typename Converter> +double +performance_str_to_type(Converter const& try_converter) +{ + char const* input[] = { "no", "up", "dn" }; + local::timer timer; + + for (int k = 0; k < local::num_cycles; ++k) + { + change chg = boost::convert<change>(input[k % 3], try_converter).value(); + int res = chg.value(); + + BOOST_TEST(res == k % 3); + + local::sum += res; // Make sure chg is not optimized out + } + return timer.value(); +} + +template<typename Converter> +double +performance_type_to_str(Converter const& try_converter) +{ + boost::array<change, 3> input = {{ change::no, change::up, change::dn }}; + boost::array<string, 3> results = {{ "no", "up", "dn" }}; + local::timer timer; + + for (int k = 0; k < local::num_cycles; ++k) + { + string res = boost::convert<string>(input[k % 3], try_converter).value(); + + BOOST_TEST(res == results[k % 3]); + + local::sum += res[0]; // Make sure res is not optimized out + } + return timer.value(); +} + +template<typename Raw, typename Cnv> +void +performance_comparative(Raw const& raw, Cnv const& cnv, char const* txt) +{ + int const num_tries = 5; + double cnv_time = 0; + double raw_time = 0; + + for (int k = 0; k < num_tries; ++k) cnv_time += local::str_to<int>(cnv); + for (int k = 0; k < num_tries; ++k) raw_time += raw_str_to<int>(raw); + + cnv_time /= num_tries; + raw_time /= num_tries; + + double change = 100 * (1 - cnv_time / raw_time); + + printf("str-to-int: %s raw/cnv=%.2f/%.2f seconds (%.2f%%).\n", txt, raw_time, cnv_time, change); +} + +int +main(int, char const* []) +{ + printf("Started performance tests...\n"); + + printf("str-to-int: spirit/strtol/lcast/scanf/stream=%7.2f/%7.2f/%7.2f/%7.2f/%7.2f seconds.\n", + local::str_to<int>(boost::cnv::spirit()), + local::str_to<int>(boost::cnv::strtol()), + local::str_to<int>(boost::cnv::lexical_cast()), + local::str_to<int>(boost::cnv::printf()), + local::str_to<int>(boost::cnv::cstream())); + printf("str-to-lng: spirit/strtol/lcast/scanf/stream=%7.2f/%7.2f/%7.2f/%7.2f/%7.2f seconds.\n", + local::str_to<long int>(boost::cnv::spirit()), + local::str_to<long int>(boost::cnv::strtol()), + local::str_to<long int>(boost::cnv::lexical_cast()), + local::str_to<long int>(boost::cnv::printf()), + local::str_to<long int>(boost::cnv::cstream())); + printf("str-to-dbl: spirit/strtol/lcast/scanf/stream=%7.2f/%7.2f/%7.2f/%7.2f/%7.2f seconds.\n", + local::str_to<double>(boost::cnv::spirit()), + local::str_to<double>(boost::cnv::strtol()), + local::str_to<double>(boost::cnv::lexical_cast()), + local::str_to<double>(boost::cnv::printf()), + local::str_to<double>(boost::cnv::cstream())); + + printf("int-to-str: spirit/strtol/lcast/prntf/stream=%7.2f/%7.2f/%7.2f/%7.2f/%7.2f seconds.\n", + local::to_str<std::string, int>(boost::cnv::spirit()), + local::to_str<std::string, int>(boost::cnv::strtol()), + local::to_str<std::string, int>(boost::cnv::lexical_cast()), + local::to_str<std::string, int>(boost::cnv::printf()), + local::to_str<std::string, int>(boost::cnv::cstream())); + printf("lng-to-str: spirit/strtol/lcast/prntf/stream=%7.2f/%7.2f/%7.2f/%7.2f/%7.2f seconds.\n", + local::to_str<std::string, long int>(boost::cnv::spirit()), + local::to_str<std::string, long int>(boost::cnv::strtol()), + local::to_str<std::string, long int>(boost::cnv::lexical_cast()), + local::to_str<std::string, long int>(boost::cnv::printf()), + local::to_str<std::string, long int>(boost::cnv::cstream())); + printf("dbl-to-str: spirit/strtol/lcast/prntf/stream=%7.2f/%7.2f/%7.2f/%7.2f/%7.2f seconds.\n", + local::to_str<std::string, double>(boost::cnv::spirit()), + local::to_str<std::string, double>(boost::cnv::strtol()(arg::precision = 6)), + local::to_str<std::string, double>(boost::cnv::lexical_cast()), + local::to_str<std::string, double>(boost::cnv::printf()(arg::precision = 6)), + local::to_str<std::string, double>(boost::cnv::cstream()(arg::precision = 6))); + + printf("str-to-user-type: lcast/stream/strtol=%.2f/%.2f/%.2f seconds.\n", + performance_str_to_type(boost::cnv::lexical_cast()), + performance_str_to_type(boost::cnv::cstream()), + performance_str_to_type(boost::cnv::strtol())); + printf("user-type-to-str: lcast/stream/strtol=%.2f/%.2f/%.2f seconds.\n", + performance_type_to_str(boost::cnv::lexical_cast()), + performance_type_to_str(boost::cnv::cstream()), + performance_type_to_str(boost::cnv::strtol())); + + //[small_string_results + printf("strtol int-to std::string/small-string: %.2f/%.2f seconds.\n", + local::to_str<std::string, int>(boost::cnv::strtol()), + local::to_str< my_string, int>(boost::cnv::strtol())); + printf("spirit int-to std::string/small-string: %.2f/%.2f seconds.\n", + local::to_str<std::string, int>(boost::cnv::spirit()), + local::to_str< my_string, int>(boost::cnv::spirit())); + printf("stream int-to std::string/small-string: %.2f/%.2f seconds.\n", + local::to_str<std::string, int>(boost::cnv::cstream()), + local::to_str< my_string, int>(boost::cnv::cstream())); + //] + performance_comparative(raw_str_to_int_spirit(), boost::cnv::spirit(), "spirit"); + performance_comparative(raw_str_to_int_lxcast(), boost::cnv::lexical_cast(), "lxcast"); + + return boost::report_errors(); +} + +#endif diff --git a/src/boost/libs/convert/test/performance_spirit.cpp b/src/boost/libs/convert/test/performance_spirit.cpp new file mode 100644 index 000000000..4878b07d2 --- /dev/null +++ b/src/boost/libs/convert/test/performance_spirit.cpp @@ -0,0 +1,112 @@ +// Boost.Convert test and usage example +// Copyright (c) 2009-2016 Vladimir Batov. +// Use, modification and distribution are subject to the Boost Software License, +// Version 1.0. See http://www.boost.org/LICENSE_1_0.txt. + +// This code has been adapted from libs/spirit/optimization/qi/int_parser.cpp. +// This code uses the performance testing framework from libs/spirit/optimization/measure.cpp. +// See these mentioned files for the copyright notice. + +#include "./test.hpp" + +#if defined(BOOST_CONVERT_IS_NOT_SUPPORTED) +int main(int, char const* []) { return 0; } +#else + +#include <boost/convert.hpp> +#include <boost/convert/spirit.hpp> +#include <boost/convert/strtol.hpp> +#include <boost/convert/lexical_cast.hpp> +#include "./prepare.hpp" + +//#define main() old_str_to_int_test_spirit() +//#include <libs/spirit/optimization/qi/int_parser.cpp> +#include <libs/spirit/workbench/measure.hpp> +#include <string> +#include <vector> +#include <cstdlib> +#include <boost/spirit/include/qi.hpp> + +namespace +{ + namespace local + { + struct base : test::base + { + base() : strings_(local::get_strs()) {} + + // Test strings are created as part of the object, i.e. on the stack to make sure + // they are easily accessed. + local::strings strings_; + }; + } + struct raw_lxcast_str_to_int_test : local::base + { + void benchmark() + { + for (size_t i = 0; i < strings_.size(); ++i) + this->val += boost::lexical_cast<int>(strings_[i].c_str()); + } + }; + struct cnv_lxcast_str_to_int_test : local::base + { + void benchmark() + { + for (size_t i = 0; i < strings_.size(); ++i) + this->val += boost::convert<int>(strings_[i].c_str(), cnv).value(); + } + boost::cnv::lexical_cast cnv; + }; + struct raw_spirit_str_to_int_test : local::base + { + static int parse(char const* str) + { + char const* beg = str; + char const* end = beg + strlen(str); + int n; + + if (boost::spirit::qi::parse(beg, end, boost::spirit::qi::int_, n)) + if (beg == end) + return n; + + return (BOOST_ASSERT(0), 0); + } + void benchmark() + { + for (size_t i = 0; i < strings_.size(); ++i) + this->val += parse(strings_[i].c_str()); + } + }; + struct cnv_spirit_str_to_int_test : local::base + { + void benchmark() + { + for (size_t i = 0; i < strings_.size(); ++i) + this->val += boost::convert<int>(strings_[i].c_str(), cnv).value(); + } + boost::cnv::spirit cnv; + }; +} + +int +main(int, char const* []) +{ + // This code has been adapted from libs/spirit/optimization/qi/int_parser.cpp. + // This code uses the performance testing framework from libs/spirit/optimization/measure.cpp. + // See these mentioned files for the copyright notice. + + BOOST_SPIRIT_TEST_BENCHMARK( + 10000000, // This is the maximum repetitions to execute + (raw_lxcast_str_to_int_test) + (cnv_lxcast_str_to_int_test) + (raw_spirit_str_to_int_test) + (cnv_spirit_str_to_int_test) + ) + + // This is ultimately responsible for preventing all the test code + // from being optimized away. Change this to return 0 and you + // unplug the whole test's life support system. + return test::live_code != 0; +} + +#endif diff --git a/src/boost/libs/convert/test/prepare.hpp b/src/boost/libs/convert/test/prepare.hpp new file mode 100644 index 000000000..15c4d0153 --- /dev/null +++ b/src/boost/libs/convert/test/prepare.hpp @@ -0,0 +1,59 @@ +// Boost.Convert test and usage example +// Copyright (c) 2009-2016 Vladimir Batov. +// Use, modification and distribution are subject to the Boost Software License, +// Version 1.0. See http://www.boost.org/LICENSE_1_0.txt. + +#ifndef BOOST_CONVERT_TEST_PREPARE_HPP +#define BOOST_CONVERT_TEST_PREPARE_HPP + +#include <boost/array.hpp> +#include <ctime> +#include <cstdlib> + +// boostinspect:nounnamed +namespace { namespace local +{ + // C1. 18 = 9 positive + 9 negative numbers with the number of digits from 1 to 9. + // Even though INT_MAX(32) = 2147483647, i.e. 10 digits (not to mention long int) + // we only test up to 9 digits as Spirit does not handle more than 9. + + typedef boost::array<my_string, 18> strings; //C1 + /////////////////////////////////////////////////////////////////////////// + // Generate a random number string with N digits + std::string + gen_int(int digits, bool negative) + { + std::string result; + + if (negative) // Prepend a '-' + result += '-'; + + result += '1' + (std::rand()%9); // The first digit cannot be '0' + + for (int i = 1; i < digits; ++i) // Generate the remaining digits + result += '0' + (std::rand()%10); + return result; + } + + local::strings const& + get_strs() + { + static local::strings strings; + static bool filled; + static bool negative = true; + + if (!filled) + { + // Seed the random generator + std::srand(std::time(0)); + + for (size_t k = 0; k < strings.size(); ++k) + strings[k] = local::gen_int(k/2 + 1, negative = !negative).c_str(); + + filled = true; + } + return strings; + } +}} + +#endif // BOOST_CONVERT_TEST_PREPARE_HPP diff --git a/src/boost/libs/convert/test/printf_converter.cpp b/src/boost/libs/convert/test/printf_converter.cpp new file mode 100644 index 000000000..a56c95b55 --- /dev/null +++ b/src/boost/libs/convert/test/printf_converter.cpp @@ -0,0 +1,47 @@ +// Boost.Convert test and usage example +// Copyright (c) 2009-2016 Vladimir Batov. +// Use, modification and distribution are subject to the Boost Software License, +// Version 1.0. See http://www.boost.org/LICENSE_1_0.txt. + +#include "./test.hpp" + +#if defined(BOOST_CONVERT_IS_NOT_SUPPORTED) +int main(int, char const* []) { return 0; } +#else + +#include <boost/convert.hpp> +#include <boost/convert/printf.hpp> +#include <boost/detail/lightweight_test.hpp> + +using std::string; +using boost::convert; + +namespace arg = boost::cnv::parameter; + +int +main(int, char const* []) +{ + boost::cnv::printf cnv; + + string const not_int_str = "not an int"; + string const std_str = "-11"; + char const* const c_str = "-12"; + + BOOST_TEST( -1 == convert<int>(not_int_str, cnv).value_or(-1)); + BOOST_TEST(-11 == convert<int>(std_str, cnv).value_or(-1)); + BOOST_TEST(-12 == convert<int>(c_str, cnv).value_or(-1)); + + BOOST_TEST("255" == convert<std::string>(255, cnv(arg::base = boost::cnv::base::dec)).value()); + BOOST_TEST( "ff" == convert<std::string>(255, cnv(arg::base = boost::cnv::base::hex)).value()); + BOOST_TEST("377" == convert<std::string>(255, cnv(arg::base = boost::cnv::base::oct)).value()); + + string s01 = convert<string>(12.3456, cnv(arg::precision = 6)).value(); + string s02 = convert<string>(12.3456, cnv(arg::precision = 3)).value(); + + BOOST_TEST(s01 == "12.345600"); + BOOST_TEST(s02 == "12.346"); + + return boost::report_errors(); +} + +#endif diff --git a/src/boost/libs/convert/test/sfinae.cpp b/src/boost/libs/convert/test/sfinae.cpp new file mode 100644 index 000000000..5236a4d6c --- /dev/null +++ b/src/boost/libs/convert/test/sfinae.cpp @@ -0,0 +1,159 @@ +// Boost.Convert test and usage example +// Copyright (c) 2009-2016 Vladimir Batov. +// Use, modification and distribution are subject to the Boost Software License, +// Version 1.0. See http://www.boost.org/LICENSE_1_0.txt. + +#include "./test.hpp" + +#if defined(BOOST_CONVERT_IS_NOT_SUPPORTED) +int main(int, char const* []) { return 0; } +#else + +#include <boost/convert.hpp> +#include <boost/convert/detail/is_string.hpp> +#include <boost/convert/detail/is_callable.hpp> +#include <boost/detail/lightweight_test.hpp> + +//[is_callable_declaration +namespace { namespace local +{ + BOOST_DECLARE_IS_CALLABLE(can_call_funop, operator()); + BOOST_DECLARE_IS_CALLABLE(can_call_func, func); +}} +//] + +//[is_callable_classes_tested +namespace { namespace callable +{ + struct test1 { int operator()(double, std::string) { return 0; }}; + struct test2 { void operator()(double, std::string) {}}; + struct test3 { void operator()(int) {}}; + struct test4 { std::string operator()(int) const { return std::string(); }}; + struct test5 { std::string operator()(int, std::string const& =std::string()) const { return std::string(); }}; + struct test6 { template<typename T> std::string operator()(T) const { return std::string(); }}; + struct test7 { template<typename T> T operator()(T) const { return T(); }}; + + struct test11 { int func(double, std::string) { return 0; }}; + struct test12 { void func(double, std::string) {}}; + struct test13 { void func(int) {}}; + struct test14 { std::string func(int) const { return std::string(); }}; + struct test15 { std::string func(int, std::string const& =std::string()) const { return std::string(); }}; + struct test16 { template<typename T> std::string func(T) const { return std::string(); }}; + struct test17 { template<typename T> T func(T) const { return T(); }}; +}} +//] + +static +void +test_is_callable() +{ + // C1. Unfortunately, passing 'double' where 'int' is expected returns 'true'. + // The same as the following (which successfully compiles): + // void fun(int) {} + // fun(double(1)); + + //[is_callable_usage1 + BOOST_TEST((local::can_call_funop<callable::test1, int (double, std::string)>::value == true)); + BOOST_TEST((local::can_call_funop<callable::test1, double (int, std::string)>::value == true)); + BOOST_TEST((local::can_call_funop<callable::test1, void (double, std::string)>::value == true)); + BOOST_TEST((local::can_call_funop<callable::test1, void (int, std::string)>::value == true)); + BOOST_TEST((local::can_call_funop<callable::test1, void (int, char const*)>::value == true)); + BOOST_TEST((local::can_call_funop<callable::test1, int (double, int)>::value == false)); + BOOST_TEST((local::can_call_funop<callable::test1, int (double)>::value == false)); + + BOOST_TEST((local::can_call_funop<callable::test2, int (double, std::string)>::value == false)); + BOOST_TEST((local::can_call_funop<callable::test2, void (double, std::string)>::value == true)); + BOOST_TEST((local::can_call_funop<callable::test2, void ( int, std::string)>::value == true)); + BOOST_TEST((local::can_call_funop<callable::test2, void ( int, char const*)>::value == true)); + //] + BOOST_TEST((local::can_call_funop<callable::test3, void (double)>::value == true)); //C1 + BOOST_TEST((local::can_call_funop<callable::test3, void (int)>::value == true)); + BOOST_TEST((local::can_call_funop<callable::test3 const, void (int)>::value == false)); + + BOOST_TEST((local::can_call_funop<callable::test4 const, std::string (int)>::value == true)); + BOOST_TEST((local::can_call_funop<callable::test4, std::string (int)>::value == true)); + BOOST_TEST((local::can_call_funop<callable::test4 const, void (int)>::value == true)); + BOOST_TEST((local::can_call_funop<callable::test4, void (int)>::value == true)); + + BOOST_TEST((local::can_call_funop<callable::test5, std::string (int, std::string)>::value == true)); + BOOST_TEST((local::can_call_funop<callable::test5, std::string (int, std::string const&)>::value == true)); + BOOST_TEST((local::can_call_funop<callable::test5, void (int, char const*)>::value == true)); + BOOST_TEST((local::can_call_funop<callable::test5, std::string (int)>::value == true)); + BOOST_TEST((local::can_call_funop<callable::test5 const, std::string (int)>::value == true)); + BOOST_TEST((local::can_call_funop<callable::test5, void (int)>::value == true)); + BOOST_TEST((local::can_call_funop<callable::test5 const, void (int)>::value == true)); + BOOST_TEST((local::can_call_funop<callable::test5, void (char const*)>::value == false)); + BOOST_TEST((local::can_call_funop<callable::test5 const, void (char const*)>::value == false)); + + BOOST_TEST((local::can_call_funop<callable::test6, std::string (int)>::value == true)); + BOOST_TEST((local::can_call_funop<callable::test6, std::string (std::string)>::value == true)); + BOOST_TEST((local::can_call_funop<callable::test6, void (int)>::value == true)); + BOOST_TEST((local::can_call_funop<callable::test6, void (std::string)>::value == true)); + + BOOST_TEST((local::can_call_funop<callable::test7, std::string (int)>::value == false)); + BOOST_TEST((local::can_call_funop<callable::test7, std::string (std::string)>::value == true)); + BOOST_TEST((local::can_call_funop<callable::test7, void (int)>::value == true)); + BOOST_TEST((local::can_call_funop<callable::test7, void (std::string)>::value == true)); + + //[is_callable_usage2 + BOOST_TEST((local::can_call_func<callable::test11, int (double, std::string)>::value == true)); + BOOST_TEST((local::can_call_func<callable::test11, double (int, std::string)>::value == true)); + BOOST_TEST((local::can_call_func<callable::test11, void (double, std::string)>::value == true)); + BOOST_TEST((local::can_call_func<callable::test11, void (int, std::string)>::value == true)); + BOOST_TEST((local::can_call_func<callable::test11, void (int, char const*)>::value == true)); + BOOST_TEST((local::can_call_func<callable::test11, int (double, int)>::value == false)); + BOOST_TEST((local::can_call_func<callable::test11, int (double)>::value == false)); + + BOOST_TEST((local::can_call_func<callable::test12, int (double, std::string)>::value == false)); + BOOST_TEST((local::can_call_func<callable::test12, void (double, std::string)>::value == true)); + BOOST_TEST((local::can_call_func<callable::test12, void ( int, std::string)>::value == true)); + BOOST_TEST((local::can_call_func<callable::test12, void ( int, char const*)>::value == true)); + //] + BOOST_TEST((local::can_call_func<callable::test13, void (double)>::value == true)); //C1 + BOOST_TEST((local::can_call_func<callable::test13, void (int)>::value == true)); + BOOST_TEST((local::can_call_func<callable::test13 const, void (int)>::value == false)); + + BOOST_TEST((local::can_call_func<callable::test14 const, std::string (int)>::value == true)); + BOOST_TEST((local::can_call_func<callable::test14, std::string (int)>::value == true)); + BOOST_TEST((local::can_call_func<callable::test14 const, void (int)>::value == true)); + BOOST_TEST((local::can_call_func<callable::test14, void (int)>::value == true)); + + BOOST_TEST((local::can_call_func<callable::test15, std::string (int, std::string)>::value == true)); + BOOST_TEST((local::can_call_func<callable::test15, std::string (int, std::string const&)>::value == true)); + BOOST_TEST((local::can_call_func<callable::test15, void (int, char const*)>::value == true)); + BOOST_TEST((local::can_call_func<callable::test15, std::string (int)>::value == true)); + BOOST_TEST((local::can_call_func<callable::test15 const, std::string (int)>::value == true)); + BOOST_TEST((local::can_call_func<callable::test15, void (int)>::value == true)); + BOOST_TEST((local::can_call_func<callable::test15 const, void (int)>::value == true)); + BOOST_TEST((local::can_call_func<callable::test15, void (char const*)>::value == false)); + BOOST_TEST((local::can_call_func<callable::test15 const, void (char const*)>::value == false)); + + BOOST_TEST((local::can_call_func<callable::test16, std::string (int)>::value == true)); + BOOST_TEST((local::can_call_func<callable::test16, std::string (std::string)>::value == true)); + BOOST_TEST((local::can_call_func<callable::test16, void (int)>::value == true)); + BOOST_TEST((local::can_call_func<callable::test16, void (std::string)>::value == true)); + + BOOST_TEST((local::can_call_func<callable::test17, std::string (int)>::value == false)); + BOOST_TEST((local::can_call_func<callable::test17, std::string (std::string)>::value == true)); + BOOST_TEST((local::can_call_func<callable::test17, void (int)>::value == true)); + BOOST_TEST((local::can_call_func<callable::test17, void (std::string)>::value == true)); +} + +int +main(int, char const* []) +{ + //[is_callable_usage + //] + + test_is_callable(); + + BOOST_TEST(boost::cnv::is_string<direction>::value == false); + BOOST_TEST(boost::cnv::is_string<std::string>::value == true); + BOOST_TEST(boost::cnv::is_string<std::wstring>::value == true); + BOOST_TEST(boost::cnv::is_string<my_string>::value == true); + BOOST_TEST(boost::cnv::is_string<int>::value == false); + + return boost::report_errors(); +} + +#endif diff --git a/src/boost/libs/convert/test/spirit_converter.cpp b/src/boost/libs/convert/test/spirit_converter.cpp new file mode 100644 index 000000000..bbbc5b976 --- /dev/null +++ b/src/boost/libs/convert/test/spirit_converter.cpp @@ -0,0 +1,87 @@ +// Boost.Convert test and usage example +// Copyright (c) 2009-2016 Vladimir Batov. +// Use, modification and distribution are subject to the Boost Software License, +// Version 1.0. See http://www.boost.org/LICENSE_1_0.txt. + +#include "./test.hpp" + +#if defined(BOOST_CONVERT_IS_NOT_SUPPORTED) +int main(int, char const* []) { return 0; } +#else + +#include <boost/convert.hpp> +#include <boost/convert/spirit.hpp> +#include <boost/detail/lightweight_test.hpp> +#include <cstdio> + +using std::string; +using std::wstring; +using boost::convert; + +namespace cnv = boost::cnv; +namespace arg = boost::cnv::parameter; + +struct boost::cnv::by_default : boost::cnv::spirit {}; + +int +main(int, char const* []) +{ + char const* const c_stri ("12345"); + char const* const c_strd ("123.45"); + wchar_t const* const c_wstri (L"12345"); + wchar_t const* const c_wstrd (L"123.45"); + std::string const std_stri (c_stri); + std::string const std_strd (c_strd); + std::wstring const std_wstri (c_wstri); + std::wstring const std_wstrd (c_wstrd); + my_string const my_stri (c_stri, c_stri + strlen(c_stri)); + my_string const my_strd (c_strd, c_strd + strlen(c_strd)); + + boost::cnv::spirit cnv; + + BOOST_TEST( 12345 == convert< int>( c_stri).value()); + BOOST_TEST( 12345 == convert< int>( c_wstri).value()); + BOOST_TEST( 12345 == convert< int>( std_stri).value()); + BOOST_TEST( 12345 == convert< int>(std_wstri).value()); + BOOST_TEST( 12345 == convert< int>( my_stri).value()); + BOOST_TEST( 12345 == convert<unsigned int>(c_stri).value()); + BOOST_TEST( 12345 == convert<long int>( c_stri).value()); + BOOST_TEST( 12345 == convert<long int>( c_wstri).value()); + BOOST_TEST( 12345 == convert<long int>( std_stri).value()); + BOOST_TEST( 12345 == convert<long int>(std_wstri).value()); + BOOST_TEST( 12345 == convert<long int>( my_stri).value()); + BOOST_TEST( 12345 == convert<unsigned long int>(c_stri).value()); + BOOST_TEST( 12345 == convert<long long int>(c_stri).value()); + BOOST_TEST( 12345 == convert<unsigned long long int>(c_stri).value()); + BOOST_TEST(123.45 == convert< double>( c_strd).value()); + BOOST_TEST(123.45 == convert< double>( c_wstrd).value()); +// BOOST_TEST(123.45 == convert< double>( std_strd).value()); +// BOOST_TEST(123.45 == convert< double>(std_wstrd).value()); + BOOST_TEST(123.45 == convert< double>( my_strd).value()); + + BOOST_TEST(!convert< int>("uhm")); + BOOST_TEST(!convert< int>(L"uhm")); + BOOST_TEST(!convert<double>("12.uhm")); + BOOST_TEST(!convert<double>("L12.uhm")); + + BOOST_TEST( "1234" == convert<string>(1234).value()); + BOOST_TEST( "1234" == convert<string>(1234u).value()); + BOOST_TEST( "1234" == convert<string>(1234ll).value()); + BOOST_TEST( "1234" == convert<string>(1234ull).value()); + BOOST_TEST( L"1234" == convert<wstring>(1234).value()); + BOOST_TEST( "12xxx" == convert<string>(12, cnv(arg::width = 5) + (arg::fill = 'x') + (arg::adjust = cnv::adjust::left)).value()); + BOOST_TEST(L"12xxx" == convert<wstring>(12, cnv(arg::width = 5) + (arg::fill = 'x') + (arg::adjust = cnv::adjust::left)).value()); + BOOST_TEST( "x12xx" == convert<string>(12, cnv(arg::adjust = cnv::adjust::center)).value()); + BOOST_TEST(L"x12xx" == convert<wstring>(12, cnv(arg::adjust = cnv::adjust::center)).value()); + +// BOOST_TEST("12.34" == convert<std::string>(12.34).value()); +// printf("%s\n", convert<std::string>(12.34).value().c_str()); + + return boost::report_errors(); +} + +#endif diff --git a/src/boost/libs/convert/test/str_to_int.cpp b/src/boost/libs/convert/test/str_to_int.cpp new file mode 100644 index 000000000..42951c0d1 --- /dev/null +++ b/src/boost/libs/convert/test/str_to_int.cpp @@ -0,0 +1,156 @@ +// Boost.Convert test and usage example +// Copyright (c) 2009-2016 Vladimir Batov. +// Use, modification and distribution are subject to the Boost Software License, +// Version 1.0. See http://www.boost.org/LICENSE_1_0.txt. + +#include "./test.hpp" + +#if defined(BOOST_CONVERT_IS_NOT_SUPPORTED) +int main(int, char const* []) { return 0; } +#else + +#include <boost/convert.hpp> +#include <boost/convert/stream.hpp> +#include <boost/convert/printf.hpp> +#include <boost/convert/strtol.hpp> +#include <boost/convert/lexical_cast.hpp> +#include <boost/convert/spirit.hpp> +#include <boost/detail/lightweight_test.hpp> + +using std::string; + +template<typename Converter> +void +int_to_str(Converter const& cnv) +{ + string const not_int_str = "not an int"; + string const std_str = "-11"; + char const* const c_str = "-12"; + char const array_str[] = "-15"; + + //////////////////////////////////////////////////////////////////////////// + // Testing int-to-string conversion with various string + // containers as the fallback values. + //////////////////////////////////////////////////////////////////////////// + + string s01 = boost::convert< string>(-1, cnv).value_or(std_str); + string s02 = boost::convert< string>(-2, cnv).value_or(c_str); + string s05 = boost::convert< string>(-5, cnv).value_or(array_str); + boost::optional< string> rs01 = boost::convert< string>(-1, cnv); + boost::optional< string> rs02 = boost::convert< string>(-2, cnv); + boost::optional< string> rs05 = boost::convert< string>(-5, cnv); + + BOOST_TEST(s01 == "-1"); BOOST_TEST(rs01 && rs01.value() == "-1"); + BOOST_TEST(s02 == "-2"); BOOST_TEST(rs02 && rs02.value() == "-2"); + BOOST_TEST(s05 == "-5"); BOOST_TEST(rs05 && rs05.value() == "-5"); + + string s11 = boost::convert< string>(-1, cnv).value(); + boost::optional< string> rs11 = boost::convert< string>(-1, cnv); + + BOOST_TEST( s11 == "-1"); + BOOST_TEST(rs11 && rs11.value() == "-1"); +} + +template<typename Converter> +void +str_to_int(Converter const& cnv) +{ + string const not_int_str = "not an int"; + string const std_str = "-11"; + char const* const c_str = "-123"; + char const array_str[] = "3456"; + + //////////////////////////////////////////////////////////////////////////// + // Testing various kinds of string containers. + // Testing implicit conversion directly to TypeOut (int). + // Testing with the fallback value value provided. + // On failure returns the provided fallback value and DOES NOT THROW. + //////////////////////////////////////////////////////////////////////////// + + int const a00 = boost::convert<int>(not_int_str, cnv).value_or(-1); + int const a01 = boost::convert<int>(std_str, cnv).value_or(-1); + int const a02 = boost::convert<int>(c_str, cnv).value_or(-1); + int const a05 = boost::convert<int>(array_str, cnv).value_or(-1); + + BOOST_TEST(a00 == -1); // Failed conversion + BOOST_TEST(a01 == -11); + BOOST_TEST(a02 == -123); + BOOST_TEST(a05 == 3456); + + //////////////////////////////////////////////////////////////////////////// + // Testing "optional" + //////////////////////////////////////////////////////////////////////////// + + boost::optional<int> const r00 = boost::convert<int>(not_int_str, cnv); + boost::optional<int> const r01 = boost::convert<int>(std_str, cnv); + boost::optional<int> const r02 = boost::convert<int>(c_str, cnv); + boost::optional<int> const r05 = boost::convert<int>(array_str, cnv); + + BOOST_TEST(!r00); // Failed conversion + BOOST_TEST( r01 && r01.value() == -11); + BOOST_TEST( r02 && r02.value() == -123); + BOOST_TEST( r05 && r05.value() == 3456); + + //////////////////////////////////////////////////////////////////////////// + // Testing value() on invalid result. + //////////////////////////////////////////////////////////////////////////// + + try + { + boost::convert<int>(not_int_str, cnv).value(); + BOOST_TEST(!"failed to throw"); + } + catch (std::exception&) + { + // Expected behavior: received 'boost::convert failed' exception. All well. + } + //////////////////////////////////////////////////////////////////////////// + // Testing value() on valid result. + //////////////////////////////////////////////////////////////////////////// + + int a21 = boost::convert<int>(std_str, cnv).value(); + int a22 = boost::convert<int>(c_str, cnv).value(); + int a25 = boost::convert<int>(array_str, cnv).value(); + + BOOST_TEST(a21 == -11); + BOOST_TEST(a22 == -123); + BOOST_TEST(a25 == 3456); + + //////////////////////////////////////////////////////////////////////////// + // Testing empty string. + //////////////////////////////////////////////////////////////////////////// + + int a31 = boost::convert<int>(std::string(), cnv).value_or(-1); + int a32 = boost::convert<int>(std::string(""), cnv).value_or(-1); + int a33 = boost::convert<int>("", cnv).value_or(-1); + + BOOST_ASSERT(a31 == -1); + BOOST_ASSERT(a32 == -1); + BOOST_ASSERT(a33 == -1); +} + +int +main(int, char const* []) +{ + boost::cnv::lexical_cast lxcast_cnv; + boost::cnv::cstream stream_cnv; + boost::cnv::strtol strtol_cnv; + boost::cnv::printf printf_cnv; + boost::cnv::spirit spirit_cnv; + + str_to_int(lxcast_cnv); + str_to_int(stream_cnv); + str_to_int(strtol_cnv); + str_to_int(printf_cnv); + str_to_int(spirit_cnv); + + int_to_str(lxcast_cnv); + int_to_str(stream_cnv); + int_to_str(strtol_cnv); + int_to_str(printf_cnv); + int_to_str(spirit_cnv); + + return boost::report_errors(); +} + +#endif diff --git a/src/boost/libs/convert/test/stream_converter.cpp b/src/boost/libs/convert/test/stream_converter.cpp new file mode 100644 index 000000000..fcab03da3 --- /dev/null +++ b/src/boost/libs/convert/test/stream_converter.cpp @@ -0,0 +1,381 @@ +// Boost.Convert test and usage example +// Copyright (c) 2009-2016 Vladimir Batov. +// Use, modification and distribution are subject to the Boost Software License, +// Version 1.0. See http://www.boost.org/LICENSE_1_0.txt. + +#include "./test.hpp" + +#if defined(BOOST_CONVERT_IS_NOT_SUPPORTED) +int main(int, char const* []) { return 0; } +#else + +#include <boost/convert.hpp> +#include <boost/convert/stream.hpp> +#include <boost/detail/lightweight_test.hpp> +#include <cstdio> +#include <cstdlib> +#include <stdlib.h> + +//[stream_using +using std::string; +using std::wstring; +using boost::convert; +//] +//[stream_cnv_namespace_shortcut +namespace cnv = boost::cnv; +namespace arg = boost::cnv::parameter; +//] + +static +void +test_dbl_to_str() +{ + boost::cnv::cstream cnv; + + cnv(std::fixed); + + BOOST_TEST(convert<string>( 99.999, cnv(arg::precision = 2)).value_or("bad") == "100.00"); + BOOST_TEST(convert<string>( 99.949, cnv(arg::precision = 2)).value_or("bad") == "99.95"); + BOOST_TEST(convert<string>(-99.949, cnv(arg::precision = 2)).value_or("bad") == "-99.95"); + BOOST_TEST(convert<string>( 99.949, cnv(arg::precision = 1)).value_or("bad") == "99.9"); + BOOST_TEST(convert<string>( 0.999, cnv(arg::precision = 2)).value_or("bad") == "1.00"); + BOOST_TEST(convert<string>( -0.999, cnv(arg::precision = 2)).value_or("bad") == "-1.00"); + BOOST_TEST(convert<string>( 0.949, cnv(arg::precision = 2)).value_or("bad") == "0.95"); + BOOST_TEST(convert<string>( -0.949, cnv(arg::precision = 2)).value_or("bad") == "-0.95"); + BOOST_TEST(convert<string>( 1.949, cnv(arg::precision = 1)).value_or("bad") == "1.9"); + BOOST_TEST(convert<string>( -1.949, cnv(arg::precision = 1)).value_or("bad") == "-1.9"); +} + +static +void +test_numbase() +{ + //[stream_numbase_example1 + /*`The following example demonstrates the deployment of `std::dec`, `std::oct` `std::hex` + manipulators: + */ + boost::cnv::cstream ccnv; + + BOOST_TEST(convert<int>( "11", ccnv(std::hex)).value_or(0) == 17); // 11(16) = 17(10) + BOOST_TEST(convert<int>( "11", ccnv(std::oct)).value_or(0) == 9); // 11(8) = 9(10) + BOOST_TEST(convert<int>( "11", ccnv(std::dec)).value_or(0) == 11); + + BOOST_TEST(convert<string>( 18, ccnv(std::hex)).value_or("bad") == "12"); // 18(10) = 12(16) + BOOST_TEST(convert<string>( 10, ccnv(std::oct)).value_or("bad") == "12"); // 10(10) = 12(8) + BOOST_TEST(convert<string>( 12, ccnv(std::dec)).value_or("bad") == "12"); + BOOST_TEST(convert<string>(255, ccnv(arg::base = boost::cnv::base::oct)).value_or("bad") == "377"); + BOOST_TEST(convert<string>(255, ccnv(arg::base = boost::cnv::base::hex)).value_or("bad") == "ff"); + BOOST_TEST(convert<string>(255, ccnv(arg::base = boost::cnv::base::dec)).value_or("bad") == "255"); + + ccnv(std::showbase); + + BOOST_TEST(convert<string>(18, ccnv(std::hex)).value_or("bad") == "0x12"); + BOOST_TEST(convert<string>(10, ccnv(std::oct)).value_or("bad") == "012"); + + ccnv(std::uppercase); + + BOOST_TEST(convert<string>(18, ccnv(std::hex)).value_or("bad") == "0X12"); + //] + //[stream_numbase_example2 + BOOST_TEST(convert<int>("11", ccnv(arg::base = cnv::base::hex)).value_or(0) == 17); + BOOST_TEST(convert<int>("11", ccnv(arg::base = cnv::base::oct)).value_or(0) == 9); + BOOST_TEST(convert<int>("11", ccnv(arg::base = cnv::base::dec)).value_or(0) == 11); + //] + //[wide_stream_numeric_base + boost::cnv::wstream wcnv; + + BOOST_TEST(convert<int>(L"11", wcnv(std::hex)).value_or(0) == 17); // 11(16) = 17(10) + BOOST_TEST(convert<int>(L"11", wcnv(std::oct)).value_or(0) == 9); // 11(8) = 9(10) + BOOST_TEST(convert<int>(L"11", wcnv(std::dec)).value_or(0) == 11); + + BOOST_TEST(convert<wstring>(254, wcnv(arg::base = cnv::base::dec)).value_or(L"bad") == L"254"); + BOOST_TEST(convert<wstring>(254, wcnv(arg::base = cnv::base::hex)).value_or(L"bad") == L"fe"); + BOOST_TEST(convert<wstring>(254, wcnv(arg::base = cnv::base::oct)).value_or(L"bad") == L"376"); + //] +} + +static +void +test_boolalpha() +{ + boost::cnv::cstream cnv; + //[stream_boolalpha_example + BOOST_TEST(convert<string>( true, cnv(std::boolalpha)).value_or("bad") == "true"); + BOOST_TEST(convert<string>(false, cnv(std::boolalpha)).value_or("bad") == "false"); + + BOOST_TEST(convert<bool>( "true", cnv(std::boolalpha)).value_or(false) == true); + BOOST_TEST(convert<bool>("false", cnv(std::boolalpha)).value_or( true) == false); + + BOOST_TEST(convert<string>( true, cnv(std::noboolalpha)).value_or("bad") == "1"); + BOOST_TEST(convert<string>(false, cnv(std::noboolalpha)).value_or("bad") == "0"); + + BOOST_TEST(convert<bool>("1", cnv(std::noboolalpha)).value_or(false) == true); + BOOST_TEST(convert<bool>("0", cnv(std::noboolalpha)).value_or( true) == false); + //] +} + +static +void +test_skipws_char() +{ + //[stream_skipws_example + boost::cnv::cstream ccnv; + char const* const cstr_good = " 123"; + char const* const cstr_bad = " 123 "; // std::skipws only affects leading spaces. + + ccnv(std::skipws); // Ignore leading whitespaces +// ccnv(arg::skipws = true); // Ignore leading whitespaces. Alternative interface + + BOOST_TEST(convert<int>(cstr_good, ccnv).value_or(0) == 123); + BOOST_TEST(convert<string>(" 123", ccnv).value_or("bad") == "123"); + + BOOST_TEST(!convert<int>(cstr_bad, ccnv)); + + ccnv(std::noskipws); // Do not ignore leading whitespaces +// ccnv(arg::skipws = false); // Do not ignore leading whitespaces. Alternative interface + + // All conversions fail. + BOOST_TEST(!convert<int>(cstr_good, ccnv)); + BOOST_TEST(!convert<int>( cstr_bad, ccnv)); + //] +} + +static +void +test_skipws_wchar() +{ + //[wide_stream_skipws + boost::cnv::wstream wcnv; + + wcnv(std::noskipws); // Do not ignore leading whitespaces + + BOOST_TEST( convert<int>( L"123", wcnv).value_or(0) == 123); + BOOST_TEST(!convert<int>( L" 123", wcnv)); + BOOST_TEST(!convert<int>(L" 123 ", wcnv)); + + wcnv(std::skipws); // Ignore leading whitespaces +// wcnv(arg::skipws = true); // Ignore leading whitespaces. Alternative interface + + BOOST_TEST( convert<int>( L" 123", wcnv).value_or(0) == 123); + BOOST_TEST(!convert<int>(L" 123 ", wcnv)); + //] +} + +static +void +test_width() +{ + //[stream_width_example + boost::cnv::cstream cnv; + + boost::optional<string> s01 = convert<string>(12, cnv(std::setw(4))); + boost::optional<string> s02 = convert<string>(12, cnv(std::setw(5))(std::setfill('*'))); + boost::optional<string> s03 = convert<string>(12, cnv(std::setw(5))(std::setfill('*'))(std::left)); + + BOOST_TEST(s01 && s01.value() == " 12"); // Field width = 4. + BOOST_TEST(s02 && s02.value() == "***12"); // Field width = 5, filler = '*'. + BOOST_TEST(s03 && s03.value() == "12***"); // Field width = 5, filler = '*', left adjustment + + /*`It needs to be remembered that `boost::cnv::stream` converter uses `std::stream` as its underlying + conversion engine. Consequently, formatting-related behavior are driven by the `std::stream`. Namely, + after every operation is performed, the ['default field width is restored]. The values of + the fill character and the adjustment remain unchanged until they are modified explicitly. + */ + + // The fill and adjustment remain '*' and 'left'. + boost::optional<string> s11 = convert<string>(12, cnv(arg::width = 4)); + boost::optional<string> s12 = convert<string>(12, cnv(arg::width = 5) + (arg::fill = ' ') + (arg::adjust = cnv::adjust::right)); + + BOOST_TEST(s11 && s11.value() == "12**"); // Field width was set to 4. + BOOST_TEST(s12 && s12.value() == " 12"); // Field width was set to 5 with the ' ' filler. + //] +} + +static +void +test_manipulators() +{ + boost::cnv::cstream ccnv; + boost::cnv::wstream wcnv; + + int const hex_v01 = boost::convert<int>("FF", ccnv(std::hex)).value_or(0); + int const hex_v02 = boost::convert<int>(L"F", wcnv(std::hex)).value_or(0); + int const hex_v03 = boost::convert<int>("FF", ccnv(std::dec)).value_or(-5); + int const hex_v04 = boost::convert<int>(L"F", wcnv(std::dec)).value_or(-6); + + BOOST_TEST(hex_v01 == 255); // "FF" + BOOST_TEST(hex_v02 == 15); // L"F" + BOOST_TEST(hex_v03 == -5); // Failed conversion + BOOST_TEST(hex_v04 == -6); // Failed conversion + + ccnv(std::noshowbase)(std::nouppercase)(std::oct); + + BOOST_TEST(boost::convert<string>(255, ccnv).value_or("bad") == "377"); + BOOST_TEST(boost::convert<string>( 15, ccnv).value_or("bad") == "17"); + + ccnv(std::showbase); + + BOOST_TEST(boost::convert<string>(255, ccnv).value_or("bad") == "0377"); + BOOST_TEST(boost::convert<string>( 15, ccnv).value_or("bad") == "017"); + + ccnv(std::uppercase)(std::hex); + + BOOST_TEST(boost::convert<string>(255, ccnv).value_or("bad") == "0XFF"); + BOOST_TEST(boost::convert<string>( 15, ccnv).value_or("bad") == "0XF"); + + ccnv(std::noshowbase)(std::nouppercase)(std::oct); + + BOOST_TEST(boost::convert<string>(255, ccnv).value_or("bad") == "377"); + BOOST_TEST(boost::convert<string>( 15, ccnv).value_or("bad") == "17"); + + ccnv(std::showbase)(arg::uppercase = true)(arg::base = cnv::base::hex); + + BOOST_TEST(boost::convert<string>(255, ccnv).value_or("bad") == "0XFF"); + BOOST_TEST(boost::convert<string>( 15, ccnv).value_or("bad") == "0XF"); +} + +void +test_locale_example() +{ + //[stream_locale_example1 + boost::cnv::cstream cnv; + std::locale rus_locale; + std::locale eng_locale; + + char const* eng_locale_name = test::cnv::is_msc ? "English_United States.1251" : "en_US.UTF-8"; + char const* rus_locale_name = test::cnv::is_msc ? "Russian_Russia.1251" : "ru_RU.UTF-8"; + char const* rus_expected = test::cnv::is_msc ? "1,235e-002" : "1,235e-02"; + char const* eng_expected = test::cnv::is_msc ? "1.235e-002" : "1.235e-02"; + char const* dbl_expected = test::cnv::is_msc ? "1.2345E-002" : "1.2345E-02"; + +// cnv(std::setprecision(4))(std::uppercase)(std::scientific); + cnv(arg::precision = 4) + (arg::uppercase = true) + (arg::notation = cnv::notation::scientific); + + double double_v01 = convert<double>(dbl_expected, cnv).value_or(0); + string double_s02 = convert<string>(double_v01, cnv).value_or("bad"); + + BOOST_TEST(dbl_expected == double_s02); + + try { rus_locale = std::locale(rus_locale_name); } + catch (...) { printf("Bad locale %s.\n", rus_locale_name); exit(1); } + + try { eng_locale = std::locale(eng_locale_name); } + catch (...) { printf("Bad locale %s.\n", eng_locale_name); exit(1); } + +// cnv(std::setprecision(3))(std::nouppercase); + cnv(arg::precision = 3)(arg::uppercase = false); + + string double_rus = convert<string>(double_v01, cnv(rus_locale)).value_or("bad double_rus"); + string double_eng = convert<string>(double_v01, cnv(eng_locale)).value_or("bad double_eng"); + + BOOST_TEST(double_rus == rus_expected); + BOOST_TEST(double_eng == eng_expected); + //] +} + +void +test_locale(double v, boost::cnv::cstream const& cnv, char const* expected) +{ + boost::optional<string> res = convert<string>(v, cnv); + std::string str = res ? *res : "conversion failed"; + + BOOST_TEST(res); + BOOST_TEST(str == expected); + + if (str != expected) + printf("%s [%d]: result=<%s>, expected=<%s>\n", __FILE__, __LINE__, str.c_str(), expected); +} + +static +void +test_locale() +{ + boost::cnv::cstream cnv; + std::locale rus_locale; + std::locale eng_locale; + bool eng_ignore = false; + bool rus_ignore = false; + char const* eng_locale_name = test::cnv::is_msc ? "English_United States.1251" : "en_US.UTF-8"; + char const* rus_locale_name = test::cnv::is_msc ? "Russian_Russia.1251" : "ru_RU.UTF-8"; + char const* eng_expected = test::cnv::is_old_msc ? "1.235e-002" : "1.235e-02"; + char const* rus_expected = test::cnv::is_old_msc ? "1,235e-002" : "1,235e-02"; + char const* dbl_expected = test::cnv::is_old_msc ? "1.2345E-002" : "1.2345E-02"; + + cnv(arg::precision = 4) + (arg::uppercase = true) + (arg::notation = cnv::notation::scientific); + + double const double_v01 = convert<double>(dbl_expected, cnv).value_or(0); + string const double_s02 = convert<string>(double_v01, cnv).value_or("bad"); + + BOOST_TEST(double_v01 != 0); + BOOST_TEST(dbl_expected == double_s02); + + if (dbl_expected != double_s02) + printf("%s [%d]: <%s> != <%s>\n", __FILE__, __LINE__, dbl_expected, double_s02.c_str()); + + try { eng_locale = std::locale(eng_locale_name); } + catch (...) { printf("Bad locale %s. Ignored.\n", eng_locale_name); eng_ignore = true; } + + try { rus_locale = std::locale(rus_locale_name); } + catch (...) { printf("Bad locale %s. Ignored.\n", rus_locale_name); rus_ignore = true; } + +// cnv(std::setprecision(3))(std::nouppercase); + cnv(arg::precision = 3)(arg::uppercase = false); + + if (!eng_ignore) test_locale(double_v01, cnv(eng_locale), eng_expected); + if (!rus_ignore) test_locale(double_v01, cnv(rus_locale), rus_expected); +} + +static +void +test_user_str() +{ + //[stream_my_string + boost::cnv::cstream cnv; + my_string my_str("123"); + + cnv(std::setprecision(2))(std::fixed); + + BOOST_TEST(convert<int>(my_str, cnv).value_or(0) == 123); + + BOOST_TEST(convert<my_string>( 99.999, cnv).value_or("bad") == "100.00"); + BOOST_TEST(convert<my_string>( 99.949, cnv).value_or("bad") == "99.95"); + BOOST_TEST(convert<my_string>(-99.949, cnv).value_or("bad") == "-99.95"); + //] +} + +int +main(int, char const* []) +{ + try + { + // QNX fails to handle std::skipws for wchat_t. + // Excluding from tests so that I do not have to stare on the yellow box (regression failure) + /*********************/ test_skipws_char(); + if (!test::cnv::is_qnx) test_skipws_wchar(); + + test_numbase(); + test_boolalpha(); + test_width(); + test_manipulators(); + test_locale(); + test_dbl_to_str(); + test_user_str(); + } + catch(boost::bad_optional_access const&) + { + BOOST_TEST(!"Caught boost::bad_optional_access exception"); + } + catch(...) + { + BOOST_TEST(!"Caught an unknown exception"); + } + return boost::report_errors(); +} + +#endif diff --git a/src/boost/libs/convert/test/strtol_converter.cpp b/src/boost/libs/convert/test/strtol_converter.cpp new file mode 100644 index 000000000..69e33e345 --- /dev/null +++ b/src/boost/libs/convert/test/strtol_converter.cpp @@ -0,0 +1,407 @@ +// Boost.Convert test and usage example +// Copyright (c) 2009-2016 Vladimir Batov. +// Use, modification and distribution are subject to the Boost Software License, +// Version 1.0. See http://www.boost.org/LICENSE_1_0.txt. + +#include "./test.hpp" + +#if defined(BOOST_CONVERT_IS_NOT_SUPPORTED) +int main(int, char const* []) { return 0; } +#else + +#include <boost/convert.hpp> +#include <boost/convert/printf.hpp> +#include <boost/convert/stream.hpp> +#include <boost/detail/lightweight_test.hpp> +#include <boost/random/mersenne_twister.hpp> +#include <boost/random/uniform_int_distribution.hpp> +#include <boost/random/uniform_01.hpp> +#include <boost/lexical_cast.hpp> +#include <boost/utility/string_view.hpp> + +//[strtol_basic_deployment_header +#include <boost/convert.hpp> +#include <boost/convert/strtol.hpp> + +using std::string; +using std::wstring; +using boost::convert; + +struct boost::cnv::by_default : boost::cnv::strtol {}; +//] + +static +void +test_str_to_uint() +{ + string const bad_str = "not an int"; + string const neg_str = "-11"; + string const std_str = "11"; + char const* const c_str = "12"; + boost::string_view v_str = boost::string_view(c_str, 1); + unsigned int const imax = (std::numeric_limits<unsigned int>::max)(); + unsigned long int const lmax = (std::numeric_limits<unsigned long int>::max)(); + std::string const imax_str = boost::lexical_cast<std::string>(imax); + std::string const lmax_str = boost::lexical_cast<std::string>(lmax); + + BOOST_TEST( 0 == convert<unsigned int>(bad_str).value_or(0)); + BOOST_TEST( 0 == convert<unsigned int>(neg_str).value_or(0)); + BOOST_TEST( 0 == convert<unsigned long int>(neg_str).value_or(0)); + BOOST_TEST( 0 == convert<unsigned long int>(neg_str).value_or(0)); + BOOST_TEST(11 == convert<unsigned int>(std_str).value()); + BOOST_TEST(12 == convert<unsigned int>( c_str).value()); + BOOST_TEST( 1 == convert<unsigned int>( v_str).value_or(0)); + BOOST_TEST(11 == convert<unsigned long int>(std_str).value()); + BOOST_TEST(12 == convert<unsigned long int>( c_str).value()); + BOOST_TEST(imax == convert< unsigned int>(imax_str).value()); + BOOST_TEST(lmax == convert<unsigned long int>(lmax_str).value()); +} + +static +void +test_str_to_int() +{ + //[strtol_basic_deployment + string const bad_str = "not an int"; + string const std_str = "-11"; + char const* const c_str = "-12"; + boost::string_view v_str = boost::string_view(c_str, 2); + + BOOST_TEST( -1 == convert<int>(bad_str).value_or(-1)); + BOOST_TEST(-11 == convert<int>(std_str).value()); + BOOST_TEST(-12 == convert<int>( c_str).value()); + BOOST_TEST( -1 == convert<int>( v_str).value_or(0)); + //] + wstring const bad_wstr = L"not an int"; + wstring const wstd_str = L"-11"; + wchar_t const* const wc_str = L"-12"; + + BOOST_TEST( -1 == convert<int>(bad_wstr).value_or(-1)); + BOOST_TEST(-11 == convert<int>(wstd_str).value()); + BOOST_TEST(-12 == convert<int>( wc_str).value()); +} + +static +void +test_int_to_str() +{ + short const s_int = -123; + int const i_int = -123; + long const l_int = -123; + long long const ll_int = -123; + + BOOST_TEST( "-123" == convert< std::string> ( s_int).value()); + BOOST_TEST( "-123" == convert< std::string> ( i_int).value()); + BOOST_TEST( "-123" == convert< std::string> ( l_int).value()); + BOOST_TEST( "-123" == convert< std::string> (ll_int).value()); + + BOOST_TEST(L"-123" == convert<std::wstring> ( s_int).value()); + BOOST_TEST(L"-123" == convert<std::wstring> ( i_int).value()); + BOOST_TEST(L"-123" == convert<std::wstring> ( l_int).value()); + BOOST_TEST(L"-123" == convert<std::wstring> (ll_int).value()); + + int const imin = (std::numeric_limits<int>::min)(); + int const imax = (std::numeric_limits<int>::max)(); + long int const lmin = (std::numeric_limits<long int>::min)(); + long int const lmax = (std::numeric_limits<long int>::max)(); + long long int const llmin = (std::numeric_limits<long long int>::min)(); + long long int const llmax = (std::numeric_limits<long long int>::max)(); + + std::string const imin_str = boost::lexical_cast<std::string>(imin); + std::string const imax_str = boost::lexical_cast<std::string>(imax); + std::string const lmin_str = boost::lexical_cast<std::string>(lmin); + std::string const lmax_str = boost::lexical_cast<std::string>(lmax); + std::string const llmin_str = boost::lexical_cast<std::string>(llmin); + std::string const llmax_str = boost::lexical_cast<std::string>(llmax); + + BOOST_TEST( imin_str == convert<std::string>( imin).value()); + BOOST_TEST( imax_str == convert<std::string>( imax).value()); + BOOST_TEST( lmin_str == convert<std::string>( lmin).value()); + BOOST_TEST( lmax_str == convert<std::string>( lmax).value()); + BOOST_TEST(llmin_str == convert<std::string>(llmin).value()); + BOOST_TEST(llmax_str == convert<std::string>(llmax).value()); +} + +static +void +test_uint_to_str() +{ + unsigned short const us_int = 123; + unsigned int const ui_int = 123; + unsigned long const ul_int = 123; + unsigned long long const ull_int = 123; + + BOOST_TEST( "123" == convert< std::string> ( us_int).value()); + BOOST_TEST( "123" == convert< std::string> ( ui_int).value()); + BOOST_TEST( "123" == convert< std::string> ( ul_int).value()); + BOOST_TEST( "123" == convert< std::string> (ull_int).value()); + + BOOST_TEST(L"123" == convert<std::wstring> ( us_int).value()); + BOOST_TEST(L"123" == convert<std::wstring> ( ui_int).value()); + BOOST_TEST(L"123" == convert<std::wstring> ( ul_int).value()); + BOOST_TEST(L"123" == convert<std::wstring> (ull_int).value()); + + unsigned int const uimax = (std::numeric_limits<unsigned int>::max)(); + unsigned long int const ulmax = (std::numeric_limits<unsigned long int>::max)(); + unsigned long long int const ullmax = (std::numeric_limits<unsigned long long int>::max)(); + + std::string const uimax_str = boost::lexical_cast<std::string>( uimax); + std::string const ulmax_str = boost::lexical_cast<std::string>( ulmax); + std::string const ullmax_str = boost::lexical_cast<std::string>(ullmax); + + BOOST_TEST( uimax_str == convert<std::string>( uimax).value()); + BOOST_TEST( ulmax_str == convert<std::string>( ulmax).value()); + BOOST_TEST(ullmax_str == convert<std::string>(ullmax).value()); +} + +//[strtol_numeric_base_header +#include <boost/convert.hpp> +#include <boost/convert/strtol.hpp> + +using std::string; +using std::wstring; +using boost::convert; + +namespace cnv = boost::cnv; +namespace arg = boost::cnv::parameter; +//] +static +void +test_width() +{ + //[strtol_width + boost::cnv::strtol cnv; + + string s01 = convert<string>( 12, cnv(arg::width = 4)).value(); + string s02 = convert<string>( 12, cnv(arg::width = 5) + (arg::fill = '*')).value(); + string s03 = convert<string>( 12, cnv(arg::width = 5) + (arg::fill = 'x') + (arg::adjust = cnv::adjust::left)).value(); + string s04 = convert<string>(-98, cnv(arg::width = 6) + (arg::fill = 'Z') + (arg::adjust = cnv::adjust::right)).value(); + + string s05 = convert<string>(-12.3451, cnv(arg::precision = 2) + (arg::width = 10) + (arg::fill = '*') + (arg::adjust = cnv::adjust::left)).value(); + string s06 = convert<string>(-12.3450, cnv(arg::adjust = cnv::adjust::right)).value(); + string s07 = convert<string>(-12.3450, cnv(arg::adjust = cnv::adjust::center)).value(); + + BOOST_TEST(s01 == " 12"); + BOOST_TEST(s02 == "***12"); + BOOST_TEST(s03 == "12xxx"); + BOOST_TEST(s04 == "ZZZ-98"); + BOOST_TEST(s05 == "-12.35****"); + BOOST_TEST(s06 == "****-12.35"); + BOOST_TEST(s07 == "**-12.35**"); + //] +} + +static +void +test_base() +{ + //[strtol_numeric_base + boost::cnv::strtol cnv; + + BOOST_TEST( "11111110" == convert< string>(254, cnv(arg::base = cnv::base::bin)).value()); + BOOST_TEST( "254" == convert< string>(254, cnv(arg::base = cnv::base::dec)).value()); + BOOST_TEST( "FE" == convert< string>(254, cnv(arg::base = cnv::base::hex)).value()); + BOOST_TEST( "376" == convert< string>(254, cnv(arg::base = cnv::base::oct)).value()); + //] + //[wide_strtol_numeric_base + BOOST_TEST(L"11111110" == convert<wstring>(254, cnv(arg::base = cnv::base::bin)).value()); + BOOST_TEST( L"254" == convert<wstring>(254, cnv(arg::base = cnv::base::dec)).value()); + BOOST_TEST( L"FE" == convert<wstring>(254, cnv(arg::base = cnv::base::hex)).value()); + BOOST_TEST( L"376" == convert<wstring>(254, cnv(arg::base = cnv::base::oct)).value()); + //] +} + +static +void +test_upper() +{ +// boost::cnv::strtol cnv; +// char const* c_lcase = "abcde"; +// char const* c_ucase = "ABCDE"; +// wchar_t const* w_lcase = L"abcde"; +// wchar_t const* w_ucase = L"ABCDE"; +// +// BOOST_TEST(c_lcase == convert< string>(c_lcase, cnv(arg::uppercase = false)).value_or("")); +// BOOST_TEST(c_ucase == convert< string>(c_lcase, cnv(arg::uppercase = true)).value_or("")); +// BOOST_TEST(w_ucase == convert<wstring>(w_lcase, cnv(arg::uppercase = false)).value_or("")); +// BOOST_TEST(w_ucase == convert<wstring>(w_lcase, cnv(arg::uppercase = true)).value_or("")); +} + +static +void +test_skipws() +{ + //[strtol_skipws + boost::cnv::strtol cnv; + + BOOST_TEST(-1 == convert<int>( " 12", cnv(arg::skipws = false)).value_or(-1)); + BOOST_TEST(12 == convert<int>( " 12", cnv(arg::skipws = true)).value_or(-1)); + //] + //[wide_strtol_skipws + BOOST_TEST(-1 == convert<int>(L" 12", cnv(arg::skipws = false)).value_or(-1)); + BOOST_TEST(12 == convert<int>(L" 12", cnv(arg::skipws = true)).value_or(-1)); + //] +} + +static +void +dbl_to_str_example() +{ + //[strtol_precision + boost::cnv::strtol cnv; + + BOOST_TEST( "12.3" == convert<string>(12.3456, cnv(arg::precision = 1)).value()); + BOOST_TEST( "12.35" == convert<string>(12.3456, cnv(arg::precision = 2)).value()); + BOOST_TEST("12.346" == convert<string>(12.3456, cnv(arg::precision = 3)).value()); + + BOOST_TEST( "-12.3" == convert<string>(-12.3456, cnv(arg::precision = 1)).value()); + BOOST_TEST( "-12.35" == convert<string>(-12.3456, cnv(arg::precision = 2)).value()); + BOOST_TEST("-12.346" == convert<string>(-12.3456, cnv(arg::precision = 3)).value()); + //] +} + +static +std::pair<double, int> +get_random() +{ + namespace rdm = boost::random; + + static rdm::mt19937 gen (::time(0)); + static rdm::uniform_int_distribution<> precision (0, 6); + static rdm::uniform_int_distribution<> int_part (0, SHRT_MAX); + static rdm::uniform_01<double> fraction; // uniform double in [0,1) + static bool sign; + + double dbl = (int_part(gen) + fraction(gen)) * ((sign = !sign) ? 1 : -1); + +// printf("%.12f\n", dbl); + + return std::make_pair(dbl, precision(gen)); +} + +static +void +compare(std::pair<double, int const> pair) +{ + boost::cnv::strtol cnv1; + boost::cnv::printf cnv2; + + string s1 = convert<string>(pair.first, cnv1(arg::precision = pair.second)).value(); + string s2 = convert<string>(pair.first, cnv2(arg::precision = pair.second)).value(); + + if (s1 != s2) + printf("dbl=%.12f(%d).strtol/printf=%s/%s.\n", pair.first, pair.second, s1.c_str(), s2.c_str()); +} + +static +void +test_str_to_dbl() +{ + char const* const c_str = "1.23456"; + + BOOST_TEST(1.2 == convert<double>(boost::string_view(c_str, 3)).value_or(0)); + BOOST_TEST(1.23 == convert<double>(boost::string_view(c_str, 4)).value_or(0)); +} + +static +void +test_dbl_to_str() +{ +// double round_up_abs01 = ::rint(-0.5); +// double round_up_abs02 = ::round(-0.5); +// double round_up_abs11 = ::rint(0.5); +// double round_up_abs12 = ::round(0.5); + +// double huge_v = 987654321098765432109.123; +// +// printf("%f\n", huge_v); +// string huge = convert<string>(huge_v, cnv1(arg::precision = 2)).value(); +// printf("%s\n", huge.c_str()); + + int const num_tries = 1000000; + double const dbls[] = { 0.90, 1.0, 1.1, 0.94, 0.96, 1.04, 1.05, 1.06, 9.654, 999.888 }; + int const num_dbls = sizeof(dbls) / sizeof(dbls[0]); + + printf("cnv::strtol::%s: started with %d random numbers...\n", __FUNCTION__, num_tries); + + BOOST_TEST( "0" == convert<string>( 0.0, cnv::strtol()(arg::precision = 0)).value()); + BOOST_TEST( "0.0" == convert<string>( 0.0, cnv::strtol()(arg::precision = 1)).value()); + BOOST_TEST("0.00" == convert<string>( 0.0, cnv::strtol()(arg::precision = 2)).value()); + BOOST_TEST( "1" == convert<string>(0.95, cnv::strtol()(arg::precision = 0)).value()); + BOOST_TEST( "1.0" == convert<string>(0.95, cnv::strtol()(arg::precision = 1)).value()); + BOOST_TEST("0.95" == convert<string>(0.95, cnv::strtol()(arg::precision = 2)).value()); + + for (int k = 0; k < num_tries; ++k) + compare(get_random()); + + for (int k = 0; k < num_dbls; ++k) + for (int precision = 0; precision < 3; ++precision) + { + compare(std::make_pair( dbls[k], precision)); + compare(std::make_pair(-dbls[k], precision)); + } + + printf("cnv::strtol::%s: finished.\n", __FUNCTION__); +} + +static +void +test_user_string() +{ + //[strtol_user_string + boost::cnv::strtol cnv; + + BOOST_TEST( "12" == convert<my_string>(12, cnv).value()); + BOOST_TEST("0.95" == convert<my_string>(0.95, cnv(arg::precision = 2)).value()); + //] +} + +static +void +test_user_type() +{ + //[strtol_user_type + boost::cnv::strtol cnv; + change up_chg = change::up; + change dn_chg = change::dn; + + BOOST_TEST(convert<std::string>(up_chg, cnv, "bad") == "up"); + BOOST_TEST(convert<std::string>(dn_chg, cnv, "bad") == "dn"); + BOOST_TEST(convert<std::string>( 12, cnv, "bad") == "12"); + + BOOST_TEST(convert<change>("up", cnv, change::no) == change::up); + BOOST_TEST(convert<change>("dn", cnv, change::no) == change::dn); + BOOST_TEST(convert< int>("12", cnv, -1) == 12); + //] +} + +int +main(int, char const* []) +{ + dbl_to_str_example(); + + test_str_to_int(); + test_str_to_uint(); + test_int_to_str(); + test_uint_to_str(); + test_base(); + test_upper(); + test_skipws(); + test_str_to_dbl(); + test_dbl_to_str(); + test_width(); + test_user_string(); + test_user_type(); + + return boost::report_errors(); +} + +#endif diff --git a/src/boost/libs/convert/test/test.hpp b/src/boost/libs/convert/test/test.hpp new file mode 100644 index 000000000..e2fbbc6e6 --- /dev/null +++ b/src/boost/libs/convert/test/test.hpp @@ -0,0 +1,187 @@ +// Copyright (c) 2009-2016 Vladimir Batov. +// Use, modification and distribution are subject to the Boost Software License, +// Version 1.0. See http://www.boost.org/LICENSE_1_0.txt. + +#ifndef BOOST_CONVERT_TEST_HPP +#define BOOST_CONVERT_TEST_HPP + +#include <boost/convert/detail/config.hpp> +#include <boost/make_default.hpp> +#include <boost/static_assert.hpp> +#include <string> +#include <istream> +#include <string.h> // For strlen, strcmp, memcpy +#include <memory.h> // Is needed for 'memset' +#include <stdio.h> +#include <time.h> + +#if defined(_MSC_VER) +# pragma warning(disable: 4189) // local variable is initialized but not referenced. +# pragma warning(disable: 4127) // conditional expression is constant. +# pragma warning(disable: 4100) // unreferenced formal parameter. +# pragma warning(disable: 4714) // marked as __forceinline not #endif +# pragma warning(disable: 4706) +# pragma warning(disable: 4005) +# pragma warning(disable: 4459) // declaration hides global declaration +# pragma warning(disable: 4456) // declaration hides previous local declaration +#endif + +//[change_declaration +struct change +{ + enum value_type { no, up, dn }; + + change(value_type v =no) : value_(v) {} + bool operator==(change v) const { return value_ == v.value_; } + value_type value() const { return value_; } + + private: value_type value_; +}; +//] +//[change_stream_operators +std::istream& operator>>(std::istream& stream, change& chg) +{ + std::string str; stream >> str; + + /**/ if (str == "up") chg = change::up; + else if (str == "dn") chg = change::dn; + else if (str == "no") chg = change::no; + else stream.setstate(std::ios_base::failbit); + + return stream; +} + +std::ostream& operator<<(std::ostream& stream, change const& chg) +{ + return stream << (chg == change::up ? "up" : chg == change::dn ? "dn" : "no"); +} +//] +//[change_convert_operators +inline void operator>>(change chg, boost::optional<std::string>& str) +{ + str = chg == change::up ? "up" : chg == change::dn ? "dn" : "no"; +} + +inline void operator>>(std::string const& str, boost::optional<change>& chg) +{ + /**/ if (str == "up") chg = change::up; + else if (str == "dn") chg = change::dn; + else if (str == "no") chg = change::no; +} +//] +//[direction_declaration +struct direction +{ + // Note: the class does NOT have the default constructor. + + enum value_type { up, dn }; + + direction(value_type value) : value_(value) {} + bool operator==(direction that) const { return value_ == that.value_; } + value_type value() const { return value_; } + + private: value_type value_; +}; +//] +//[direction_stream_operators +std::istream& operator>>(std::istream& stream, direction& dir) +{ + std::string str; stream >> str; + + /**/ if (str == "up") dir = direction::up; + else if (str == "dn") dir = direction::dn; + else stream.setstate(std::ios_base::failbit); + + return stream; +} +std::ostream& operator<<(std::ostream& stream, direction const& dir) +{ + return stream << (dir.value() == direction::up ? "up" : "dn"); +} +//] +//[direction_declaration_make_default +namespace boost +{ + template<> inline direction make_default<direction>() + { + return direction(direction::up); + } +} +//] +// Quick and dirty small-string implementation for performance tests. +//[my_string_declaration +struct my_string +{ + typedef my_string this_type; + typedef char value_type; + typedef value_type* iterator; + typedef value_type const* const_iterator; + + my_string (); + my_string (const_iterator, const_iterator =0); + + char const* c_str () const { return storage_; } + const_iterator begin () const { return storage_; } + const_iterator end () const { return storage_ + strlen(storage_); } + this_type& operator= (char const*); + + private: + + static size_t const size_ = 12; + char storage_[size_]; +}; +//] +inline +my_string::my_string() +{ + storage_[0] = 0; +} + +inline +my_string::my_string(const_iterator beg, const_iterator end) +{ + std::size_t const sz = end ? (end - beg) : strlen(beg); + + BOOST_ASSERT(sz < size_); + memcpy(storage_, beg, sz); storage_[sz] = 0; +} + +inline +my_string& +my_string::operator=(char const* str) +{ + BOOST_ASSERT(strlen(str) < size_); + strcpy(storage_, str); + return *this; +} + +inline bool operator==(char const* s1, my_string const& s2) { return strcmp(s1, s2.c_str()) == 0; } +inline bool operator==(my_string const& s1, char const* s2) { return strcmp(s2, s1.c_str()) == 0; } + +namespace test +{ + struct cnv + { +#if defined(__QNXNTO__) + static bool const is_qnx = true; +#else + static bool const is_qnx = false; +#endif + +#if defined(_MSC_VER) && _MSC_VER < 1900 + static bool const is_msc = true; + static bool const is_old_msc = true; +#elif defined(_MSC_VER) + static bool const is_msc = true; + static bool const is_old_msc = false; +#elif defined(__MINGW32__) + static bool const is_msc = true; + static bool const is_old_msc = true; +#else + static bool const is_msc = false; + static bool const is_old_msc = false; +#endif + }; +} + +#endif // BOOST_CONVERT_TEST_HPP diff --git a/src/boost/libs/convert/test/user_type.cpp b/src/boost/libs/convert/test/user_type.cpp new file mode 100644 index 000000000..bd2bb545f --- /dev/null +++ b/src/boost/libs/convert/test/user_type.cpp @@ -0,0 +1,101 @@ +// Boost.Convert test and usage example +// Copyright (c) 2009-2016 Vladimir Batov. +// Use, modification and distribution are subject to the Boost Software License, +// Version 1.0. See http://www.boost.org/LICENSE_1_0.txt. + +#include "./test.hpp" + +#if defined(BOOST_CONVERT_IS_NOT_SUPPORTED) +int main(int, char const* []) { return 0; } +#else + +#include <boost/convert.hpp> +#include <boost/convert/stream.hpp> +#include <boost/detail/lightweight_test.hpp> +#include <boost/array.hpp> +#include <vector> + +using std::string; +using std::wstring; + +static +void +test_user_type() +{ + boost::cnv::cstream cnv; // stringstream-based char converter + + direction const up_dir1 = direction::up; + direction const dn_dir1 = direction::dn; +// string const up_dir0_str = boost::convert<string, direction>(direction::up, cnv).value(); +// string const dn_dir0_str = boost::convert<string, direction>(direction::dn, cnv).value(); + string const up_dir1_str = boost::convert<string>(up_dir1, cnv).value(); + string const dn_dir1_str = boost::convert<string>(dn_dir1, cnv).value(); + direction const up_dir2 = boost::convert<direction>(up_dir1_str, cnv).value(); + direction const dn_dir2 = boost::convert<direction>(dn_dir1_str, cnv).value(); + direction const up_dir3 = boost::convert<direction>(up_dir1_str, cnv).value(); + direction const dn_dir3 = boost::convert<direction>(dn_dir1_str, cnv).value(); + direction const dn_dir4 = boost::convert<direction>("junk", cnv).value_or(direction::dn); + boost::optional<direction> up_dir4 = boost::convert<direction>("junk", cnv); + +// BOOST_TEST(up_dir0_str == "up"); +// BOOST_TEST(dn_dir0_str == "dn"); + BOOST_TEST(up_dir1_str == "up"); + BOOST_TEST(dn_dir1_str == "dn"); + BOOST_TEST(up_dir2 == up_dir1); + BOOST_TEST(dn_dir2 == dn_dir1); + BOOST_TEST(up_dir3 == direction::up); + BOOST_TEST(dn_dir3 == direction::dn); + BOOST_TEST(dn_dir4 == direction::dn); + BOOST_TEST(!up_dir4); // Failed conversion +} + +static +void +test_algorithms() +{ +//[algorithm_example6 + boost::array<change, 3> chgs1 = {{ change::no, change::up, change::dn }}; + boost::array<change::value_type, 3> chgs2 = {{ change::no, change::up, change::dn }}; + std::vector<std::string> strs1; + std::vector<std::string> strs2; + std::vector<std::string> strs3; + boost::cnv::cstream cnv; + + std::transform(chgs1.begin(), chgs1.end(), std::back_inserter(strs1), + boost::cnv::apply<string>(boost::cref(cnv))); // Deduced TypeIn is 'change' + + std::transform(chgs2.begin(), chgs2.end(), std::back_inserter(strs2), + boost::cnv::apply<string>(boost::cref(cnv))); // Deduced TypeIn is 'change::value_type' + + BOOST_TEST(strs1.size() == 3); + BOOST_TEST(strs1[0] == "no"); + BOOST_TEST(strs1[1] == "up"); + BOOST_TEST(strs1[2] == "dn"); + + BOOST_TEST(strs2.size() == 3); + BOOST_TEST(strs2[0] == "0"); + BOOST_TEST(strs2[1] == "1"); + BOOST_TEST(strs2[2] == "2"); +//] +//[algorithm_example7 + + std::transform(chgs2.begin(), chgs2.end(), std::back_inserter(strs3), + boost::cnv::apply<string, change>(boost::cref(cnv))); + + BOOST_TEST(strs3.size() == 3); + BOOST_TEST(strs3[0] == "no"); + BOOST_TEST(strs3[1] == "up"); + BOOST_TEST(strs3[2] == "dn"); +//] +} + +int +main(int, char const* []) +{ + test_user_type(); + test_algorithms(); + + return boost::report_errors(); +} + +#endif diff --git a/src/boost/libs/convert/todo.txt b/src/boost/libs/convert/todo.txt new file mode 100644 index 000000000..7bf36d540 --- /dev/null +++ b/src/boost/libs/convert/todo.txt @@ -0,0 +1,12 @@ +boost-no-inspect + +* Adding Doxygen comments to describe briefly the files, functions etc (so users can find which include files may be needed?) +* I don't understand the timing figures given in Performance section. Some items refer to MSVC express 10, other detailed tables in Boost 1.55 to 11? No Clang results? + +* You are not using links to take from the text to the appropriate functions etc +in the reference section. Users will find this helpful too. + +* The reference section could be much improved by adding brief Doxygen comments to +the files, functions etc. + + |