| [12] | 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 | 
|---|