1 // Copyright Kevlin Henney, 2000-2005.
2 // Copyright Alexander Nasonov, 2006-2010.
3 // Copyright Antony Polukhin, 2011-2014.
4 //
5 // Distributed under the Boost Software License, Version 1.0. (See
6 // accompanying file LICENSE_1_0.txt or copy at
7 // http://www.boost.org/LICENSE_1_0.txt)
8 //
9 // what:  lexical_cast custom keyword cast
10 // who:   contributed by Kevlin Henney,
11 //        enhanced with contributions from Terje Slettebo,
12 //        with additional fixes and suggestions from Gennaro Prota,
13 //        Beman Dawes, Dave Abrahams, Daryle Walker, Peter Dimov,
14 //        Alexander Nasonov, Antony Polukhin, Justin Viiret, Michael Hofmann,
15 //        Cheng Yang, Matthew Bradbury, David W. Birdsall, Pavel Korzh and other Boosters
16 // when:  November 2000, March 2003, June 2005, June 2006, March 2011 - 2014
17 
18 #ifndef BOOST_LEXICAL_CAST_TRY_LEXICAL_CONVERT_HPP
19 #define BOOST_LEXICAL_CAST_TRY_LEXICAL_CONVERT_HPP
20 
21 #include <boost/config.hpp>
22 #ifdef BOOST_HAS_PRAGMA_ONCE
23 #   pragma once
24 #endif
25 
26 #if defined(__clang__) || (defined(__GNUC__) && \
27     !(defined(__INTEL_COMPILER) || defined(__ICL) || defined(__ICC) || defined(__ECC)) && \
28     (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)))
29 #pragma GCC diagnostic push
30 #pragma GCC diagnostic ignored "-Wuninitialized"
31 #endif
32 
33 #include <string>
34 #include <boost/mpl/bool.hpp>
35 #include <boost/mpl/identity.hpp>
36 #include <boost/mpl/if.hpp>
37 #include <boost/type_traits/is_same.hpp>
38 #include <boost/type_traits/is_arithmetic.hpp>
39 
40 #include <boost/lexical_cast/detail/is_character.hpp>
41 #include <boost/lexical_cast/detail/converter_numeric.hpp>
42 #include <boost/lexical_cast/detail/converter_lexical.hpp>
43 
44 #include <boost/range/iterator_range_core.hpp>
45 #include <boost/container/container_fwd.hpp>
46 
47 namespace pdalboost {
48     namespace detail
49     {
50         template<typename T>
51         struct is_stdstring
52             : pdalboost::false_type
53         {};
54 
55         template<typename CharT, typename Traits, typename Alloc>
56         struct is_stdstring< std::basic_string<CharT, Traits, Alloc> >
57             : pdalboost::true_type
58         {};
59 
60         template<typename CharT, typename Traits, typename Alloc>
61         struct is_stdstring< pdalboost::container::basic_string<CharT, Traits, Alloc> >
62             : pdalboost::true_type
63         {};
64 
65         template<typename Target, typename Source>
66         struct is_arithmetic_and_not_xchars
67         {
68             typedef pdalboost::mpl::bool_<
69                     !(pdalboost::detail::is_character<Target>::value) &&
70                     !(pdalboost::detail::is_character<Source>::value) &&
71                     pdalboost::is_arithmetic<Source>::value &&
72                     pdalboost::is_arithmetic<Target>::value
73                 > type;
74 
75             BOOST_STATIC_CONSTANT(bool, value = (
76                 type::value
77             ));
78         };
79 
80         /*
81          * is_xchar_to_xchar<Target, Source>::value is true,
82          * Target and Souce are char types of the same size 1 (char, signed char, unsigned char).
83          */
84         template<typename Target, typename Source>
85         struct is_xchar_to_xchar
86         {
87             typedef pdalboost::mpl::bool_<
88                      sizeof(Source) == sizeof(Target) &&
89                      sizeof(Source) == sizeof(char) &&
90                      pdalboost::detail::is_character<Target>::value &&
91                      pdalboost::detail::is_character<Source>::value
92                 > type;
93 
94             BOOST_STATIC_CONSTANT(bool, value = (
95                 type::value
96             ));
97         };
98 
99         template<typename Target, typename Source>
100         struct is_char_array_to_stdstring
101             : pdalboost::false_type
102         {};
103 
104         template<typename CharT, typename Traits, typename Alloc>
105         struct is_char_array_to_stdstring< std::basic_string<CharT, Traits, Alloc>, CharT* >
106             : pdalboost::true_type
107         {};
108 
109         template<typename CharT, typename Traits, typename Alloc>
110         struct is_char_array_to_stdstring< std::basic_string<CharT, Traits, Alloc>, const CharT* >
111             : pdalboost::true_type
112         {};
113 
114         template<typename CharT, typename Traits, typename Alloc>
115         struct is_char_array_to_stdstring< pdalboost::container::basic_string<CharT, Traits, Alloc>, CharT* >
116             : pdalboost::true_type
117         {};
118 
119         template<typename CharT, typename Traits, typename Alloc>
120         struct is_char_array_to_stdstring< pdalboost::container::basic_string<CharT, Traits, Alloc>, const CharT* >
121             : pdalboost::true_type
122         {};
123 
124         template <typename Target, typename Source>
125         struct copy_converter_impl
126         {
127 // MSVC fail to forward an array (DevDiv#555157 "SILENT BAD CODEGEN triggered by perfect forwarding",
128 // fixed in 2013 RTM).
129 #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && (!defined(BOOST_MSVC) || BOOST_MSVC >= 1800)
130             template <class T>
try_convertpdalboost::detail::copy_converter_impl131             static inline bool try_convert(T&& arg, Target& result) {
132                 result = static_cast<T&&>(arg); // eqaul to `result = std::forward<T>(arg);`
133                 return true;
134             }
135 #else
136             static inline bool try_convert(const Source& arg, Target& result) {
137                 result = arg;
138                 return true;
139             }
140 #endif
141         };
142     }
143 
144     namespace conversion { namespace detail {
145 
146         template <typename Target, typename Source>
try_lexical_convert(const Source & arg,Target & result)147         inline bool try_lexical_convert(const Source& arg, Target& result)
148         {
149             typedef BOOST_DEDUCED_TYPENAME pdalboost::detail::array_to_pointer_decay<Source>::type src;
150 
151             typedef pdalboost::mpl::bool_<
152                 pdalboost::detail::is_xchar_to_xchar<Target, src >::value ||
153                 pdalboost::detail::is_char_array_to_stdstring<Target, src >::value ||
154                 (
155                      pdalboost::is_same<Target, src >::value &&
156                      pdalboost::detail::is_stdstring<Target >::value
157                 ) ||
158                 (
159                      pdalboost::is_same<Target, src >::value &&
160                      pdalboost::detail::is_character<Target >::value
161                 )
162             > shall_we_copy_t;
163 
164             typedef pdalboost::detail::is_arithmetic_and_not_xchars<Target, src >
165                 shall_we_copy_with_dynamic_check_t;
166 
167             // We do evaluate second `if_` lazily to avoid unnecessary instantiations
168             // of `shall_we_copy_with_dynamic_check_t` and improve compilation times.
169             typedef BOOST_DEDUCED_TYPENAME pdalboost::mpl::if_c<
170                 shall_we_copy_t::value,
171                 pdalboost::mpl::identity<pdalboost::detail::copy_converter_impl<Target, src > >,
172                 pdalboost::mpl::if_<
173                      shall_we_copy_with_dynamic_check_t,
174                      pdalboost::detail::dynamic_num_converter_impl<Target, src >,
175                      pdalboost::detail::lexical_converter_impl<Target, src >
176                 >
177             >::type caster_type_lazy;
178 
179             typedef BOOST_DEDUCED_TYPENAME caster_type_lazy::type caster_type;
180 
181             return caster_type::try_convert(arg, result);
182         }
183 
184         template <typename Target, typename CharacterT>
try_lexical_convert(const CharacterT * chars,std::size_t count,Target & result)185         inline bool try_lexical_convert(const CharacterT* chars, std::size_t count, Target& result)
186         {
187             BOOST_STATIC_ASSERT_MSG(
188                 pdalboost::detail::is_character<CharacterT>::value,
189                 "This overload of try_lexical_convert is meant to be used only with arrays of characters."
190             );
191             return ::pdalboost::conversion::detail::try_lexical_convert(
192                 ::pdalboost::iterator_range<const CharacterT*>(chars, chars + count), result
193             );
194         }
195 
196     }} // namespace conversion::detail
197 
198     namespace conversion {
199         // ADL barrier
200         using ::pdalboost::conversion::detail::try_lexical_convert;
201     }
202 
203 } // namespace pdalboost
204 
205 #if defined(__clang__) || (defined(__GNUC__) && \
206     !(defined(__INTEL_COMPILER) || defined(__ICL) || defined(__ICC) || defined(__ECC)) && \
207     (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)))
208 #pragma GCC diagnostic pop
209 #endif
210 
211 #endif // BOOST_LEXICAL_CAST_TRY_LEXICAL_CONVERT_HPP
212 
213