[29] | 1 | #ifndef BOOST_LEXICAL_CAST_INCLUDED |
---|
| 2 | #define BOOST_LEXICAL_CAST_INCLUDED |
---|
| 3 | |
---|
| 4 | // Boost lexical_cast.hpp header -------------------------------------------// |
---|
| 5 | // |
---|
| 6 | // See http://www.boost.org for most recent version including documentation. |
---|
| 7 | // See end of this header for rights and permissions. |
---|
| 8 | // |
---|
| 9 | // what: lexical_cast custom keyword cast |
---|
| 10 | // who: contributed by Kevlin Henney, |
---|
| 11 | // enhanced with contributions from Terje Slettebø, |
---|
| 12 | // with additional fixes and suggestions from Gennaro Prota, |
---|
| 13 | // Beman Dawes, Dave Abrahams, Daryle Walker, Peter Dimov, |
---|
| 14 | // and other Boosters |
---|
| 15 | // when: November 2000, March 2003, June 2005 |
---|
| 16 | |
---|
| 17 | #include <cstddef> |
---|
| 18 | #include <string> |
---|
| 19 | #include <typeinfo> |
---|
| 20 | #include <boost/config.hpp> |
---|
| 21 | #include <boost/limits.hpp> |
---|
| 22 | #include <boost/throw_exception.hpp> |
---|
| 23 | #include <boost/type_traits/is_pointer.hpp> |
---|
| 24 | |
---|
| 25 | #ifdef BOOST_NO_STRINGSTREAM |
---|
| 26 | #include <strstream> |
---|
| 27 | #else |
---|
| 28 | #include <sstream> |
---|
| 29 | #endif |
---|
| 30 | |
---|
| 31 | #if defined(BOOST_NO_STRINGSTREAM) || \ |
---|
| 32 | defined(BOOST_NO_STD_WSTRING) || \ |
---|
| 33 | defined(BOOST_NO_STD_LOCALE) |
---|
| 34 | #define DISABLE_WIDE_CHAR_SUPPORT |
---|
| 35 | #endif |
---|
| 36 | |
---|
| 37 | namespace boost |
---|
| 38 | { |
---|
| 39 | // exception used to indicate runtime lexical_cast failure |
---|
| 40 | class bad_lexical_cast : public std::bad_cast |
---|
| 41 | { |
---|
| 42 | public: |
---|
| 43 | bad_lexical_cast() : |
---|
| 44 | source(&typeid(void)), target(&typeid(void)) |
---|
| 45 | { |
---|
| 46 | } |
---|
| 47 | bad_lexical_cast( |
---|
| 48 | const std::type_info &source_type, |
---|
| 49 | const std::type_info &target_type) : |
---|
| 50 | source(&source_type), target(&target_type) |
---|
| 51 | { |
---|
| 52 | } |
---|
| 53 | const std::type_info &source_type() const |
---|
| 54 | { |
---|
| 55 | return *source; |
---|
| 56 | } |
---|
| 57 | const std::type_info &target_type() const |
---|
| 58 | { |
---|
| 59 | return *target; |
---|
| 60 | } |
---|
| 61 | virtual const char *what() const throw() |
---|
| 62 | { |
---|
| 63 | return "bad lexical cast: " |
---|
| 64 | "source type value could not be interpreted as target"; |
---|
| 65 | } |
---|
| 66 | virtual ~bad_lexical_cast() throw() |
---|
| 67 | { |
---|
| 68 | } |
---|
| 69 | private: |
---|
| 70 | const std::type_info *source; |
---|
| 71 | const std::type_info *target; |
---|
| 72 | }; |
---|
| 73 | |
---|
| 74 | namespace detail // selectors for choosing stream character type |
---|
| 75 | { |
---|
| 76 | template<typename Type> |
---|
| 77 | struct stream_char |
---|
| 78 | { |
---|
| 79 | typedef char type; |
---|
| 80 | }; |
---|
| 81 | |
---|
| 82 | #ifndef DISABLE_WIDE_CHAR_SUPPORT |
---|
| 83 | #if !defined(BOOST_NO_INTRINSIC_WCHAR_T) |
---|
| 84 | template<> |
---|
| 85 | struct stream_char<wchar_t> |
---|
| 86 | { |
---|
| 87 | typedef wchar_t type; |
---|
| 88 | }; |
---|
| 89 | #endif |
---|
| 90 | |
---|
| 91 | template<> |
---|
| 92 | struct stream_char<wchar_t *> |
---|
| 93 | { |
---|
| 94 | typedef wchar_t type; |
---|
| 95 | }; |
---|
| 96 | |
---|
| 97 | template<> |
---|
| 98 | struct stream_char<const wchar_t *> |
---|
| 99 | { |
---|
| 100 | typedef wchar_t type; |
---|
| 101 | }; |
---|
| 102 | |
---|
| 103 | template<> |
---|
| 104 | struct stream_char<std::wstring> |
---|
| 105 | { |
---|
| 106 | typedef wchar_t type; |
---|
| 107 | }; |
---|
| 108 | #endif |
---|
| 109 | |
---|
| 110 | template<typename TargetChar, typename SourceChar> |
---|
| 111 | struct widest_char |
---|
| 112 | { |
---|
| 113 | typedef TargetChar type; |
---|
| 114 | }; |
---|
| 115 | |
---|
| 116 | template<> |
---|
| 117 | struct widest_char<char, wchar_t> |
---|
| 118 | { |
---|
| 119 | typedef wchar_t type; |
---|
| 120 | }; |
---|
| 121 | } |
---|
| 122 | |
---|
| 123 | namespace detail // stream wrapper for handling lexical conversions |
---|
| 124 | { |
---|
| 125 | template<typename Target, typename Source> |
---|
| 126 | class lexical_stream |
---|
| 127 | { |
---|
| 128 | private: |
---|
| 129 | typedef typename widest_char< |
---|
| 130 | typename stream_char<Target>::type, |
---|
| 131 | typename stream_char<Source>::type>::type char_type; |
---|
| 132 | |
---|
| 133 | public: |
---|
| 134 | lexical_stream() |
---|
| 135 | { |
---|
| 136 | stream.unsetf(std::ios::skipws); |
---|
| 137 | |
---|
| 138 | if(std::numeric_limits<Target>::is_specialized) |
---|
| 139 | stream.precision(std::numeric_limits<Target>::digits10 + 1); |
---|
| 140 | else if(std::numeric_limits<Source>::is_specialized) |
---|
| 141 | stream.precision(std::numeric_limits<Source>::digits10 + 1); |
---|
| 142 | } |
---|
| 143 | ~lexical_stream() |
---|
| 144 | { |
---|
| 145 | #if defined(BOOST_NO_STRINGSTREAM) |
---|
| 146 | stream.freeze(false); |
---|
| 147 | #endif |
---|
| 148 | } |
---|
| 149 | bool operator<<(const Source &input) |
---|
| 150 | { |
---|
| 151 | return !(stream << input).fail(); |
---|
| 152 | } |
---|
| 153 | template<typename InputStreamable> |
---|
| 154 | bool operator>>(InputStreamable &output) |
---|
| 155 | { |
---|
| 156 | return !is_pointer<InputStreamable>::value && |
---|
| 157 | stream >> output && |
---|
| 158 | stream.get() == |
---|
| 159 | #if defined(__GNUC__) && (__GNUC__<3) && defined(BOOST_NO_STD_WSTRING) |
---|
| 160 | // GCC 2.9x lacks std::char_traits<>::eof(). |
---|
| 161 | // We use BOOST_NO_STD_WSTRING to filter out STLport and libstdc++-v3 |
---|
| 162 | // configurations, which do provide std::char_traits<>::eof(). |
---|
| 163 | |
---|
| 164 | EOF; |
---|
| 165 | #else |
---|
| 166 | std::char_traits<char_type>::eof(); |
---|
| 167 | #endif |
---|
| 168 | } |
---|
| 169 | bool operator>>(std::string &output) |
---|
| 170 | { |
---|
| 171 | #if defined(BOOST_NO_STRINGSTREAM) |
---|
| 172 | stream << '\0'; |
---|
| 173 | #endif |
---|
| 174 | output = stream.str(); |
---|
| 175 | return true; |
---|
| 176 | } |
---|
| 177 | #ifndef DISABLE_WIDE_CHAR_SUPPORT |
---|
| 178 | bool operator>>(std::wstring &output) |
---|
| 179 | { |
---|
| 180 | output = stream.str(); |
---|
| 181 | return true; |
---|
| 182 | } |
---|
| 183 | #endif |
---|
| 184 | private: |
---|
| 185 | #if defined(BOOST_NO_STRINGSTREAM) |
---|
| 186 | std::strstream stream; |
---|
| 187 | #elif defined(BOOST_NO_STD_LOCALE) |
---|
| 188 | std::stringstream stream; |
---|
| 189 | #else |
---|
| 190 | std::basic_stringstream<char_type> stream; |
---|
| 191 | #endif |
---|
| 192 | }; |
---|
| 193 | } |
---|
| 194 | |
---|
| 195 | #ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION |
---|
| 196 | |
---|
| 197 | // call-by-const reference version |
---|
| 198 | |
---|
| 199 | namespace detail |
---|
| 200 | { |
---|
| 201 | template<class T> |
---|
| 202 | struct array_to_pointer_decay |
---|
| 203 | { |
---|
| 204 | typedef T type; |
---|
| 205 | }; |
---|
| 206 | |
---|
| 207 | template<class T, std::size_t N> |
---|
| 208 | struct array_to_pointer_decay<T[N]> |
---|
| 209 | { |
---|
| 210 | typedef const T * type; |
---|
| 211 | }; |
---|
| 212 | } |
---|
| 213 | |
---|
| 214 | template<typename Target, typename Source> |
---|
| 215 | Target lexical_cast(const Source &arg) |
---|
| 216 | { |
---|
| 217 | typedef typename detail::array_to_pointer_decay<Source>::type NewSource; |
---|
| 218 | |
---|
| 219 | detail::lexical_stream<Target, NewSource> interpreter; |
---|
| 220 | Target result; |
---|
| 221 | |
---|
| 222 | if(!(interpreter << arg && interpreter >> result)) |
---|
| 223 | throw_exception(bad_lexical_cast(typeid(NewSource), typeid(Target))); |
---|
| 224 | return result; |
---|
| 225 | } |
---|
| 226 | |
---|
| 227 | #else |
---|
| 228 | |
---|
| 229 | // call-by-value fallback version (deprecated) |
---|
| 230 | |
---|
| 231 | template<typename Target, typename Source> |
---|
| 232 | Target lexical_cast(Source arg) |
---|
| 233 | { |
---|
| 234 | detail::lexical_stream<Target, Source> interpreter; |
---|
| 235 | Target result; |
---|
| 236 | |
---|
| 237 | if(!(interpreter << arg && interpreter >> result)) |
---|
| 238 | throw_exception(bad_lexical_cast(typeid(Source), typeid(Target))); |
---|
| 239 | return result; |
---|
| 240 | } |
---|
| 241 | |
---|
| 242 | #endif |
---|
| 243 | } |
---|
| 244 | |
---|
| 245 | // Copyright Kevlin Henney, 2000-2005. All rights reserved. |
---|
| 246 | // |
---|
| 247 | // Distributed under the Boost Software License, Version 1.0. (See |
---|
| 248 | // accompanying file LICENSE_1_0.txt or copy at |
---|
| 249 | // http://www.boost.org/LICENSE_1_0.txt) |
---|
| 250 | |
---|
| 251 | #undef DISABLE_WIDE_CHAR_SUPPORT |
---|
| 252 | #endif |
---|