util/lexical_cast.h

Go to the documentation of this file.
00001 //  boost lexical_cast.hpp header  -------------------------------------------//
00002 
00003 //  See http://www.boost.org for most recent version including documentation.
00004 
00005 #ifndef BOOST_LEXICAL_CAST_INCLUDED
00006 #define BOOST_LEXICAL_CAST_INCLUDED
00007 
00008 // what:  lexical_cast custom keyword cast
00009 // who:   contributed by Kevlin Henney, with alternative naming, behaviors
00010 //        and fixes contributed by Dave Abrahams, Daryle Walker and other
00011 //        Boosters on the list
00012 // when:  November 2000
00013 // where: tested with MSVC 6.0, BCC 5.5, and g++ 2.91
00014 
00015 #include <sstream>
00016 #include <typeinfo>
00017 #include <util/XmlBCfg.h>
00018 #include <stdio.h> 
00019 #if __GNUC__ == 2
00020   // g++ 2.95.3 does only know limits.h
00021 #else
00022 #  include <limits>
00023 #endif
00024 
00025 #if defined(_WINDOWS)
00026 #  if _MSC_VER >= 1400  /* _WINDOWS: 1200->VC++6.0, 1310->VC++7.1 (2003), 1400->VC++8.0 (2005) */
00027 //#    define XMLBLASTER_CPP_SNPRINTF snprintf0
00028 #    define XMLBLASTER_CPP_SNPRINTF sprintf_s
00029 #  else
00030 #    define XMLBLASTER_CPP_SNPRINTF _snprintf
00031 #  endif
00032 #else
00033 #  define XMLBLASTER_CPP_SNPRINTF snprintf
00034 #endif
00035 
00036 namespace org { namespace xmlBlaster { namespace util {
00037 
00038 #if __sun__
00039 # define DISABLE_WIDE_CHAR_SUPPORT
00040 #endif
00041 
00042 #if __GNUC__ == 2
00043    // Marcel 2004-04-01:
00044    // Is buggy for lexical_cast<string>(string("")): empty strings throw a bad_lexical_cast
00045    // Newest version from boost handles it but did not compile on g++ 2.9x
00046     class Dll_Export bad_lexical_cast : public std::bad_cast
00047     {
00048     public:
00049         // constructors, destructors, and assignment operator defaulted
00050 
00051         // function inlined for brevity and consistency with rest of library
00052         virtual const char * what() const throw()
00053         {
00054             return "bad lexical cast: "
00055                    "source type value could not be interpreted as target";
00056         }
00057     };
00058 
00066     template<typename Target, typename Source>
00067     Target lexical_cast(Source arg)
00068     {
00069 // # ifdef BOOST_LEXICAL_CAST_USE_STRSTREAM
00070 //        std::strstream interpreter; // for out-of-the-box g++ 2.95.2
00071 // # else
00072         std::stringstream interpreter;
00073 // # endif
00074         Target result;
00075 
00076         // Precision fix for "double" and "long double"
00077         // Marcel Ruff 2004-01-17
00078         //int origPrecision = interpreter.precision(); // 6 digits
00079         if (typeid(arg) == typeid(double(1.7L)))
00080             interpreter.precision(15);
00081         if (typeid(arg) == typeid((long double)(1.7L)))
00082             interpreter.precision(18);
00083 
00084         if(!(interpreter << arg) || !(interpreter >> result) ||
00085            !(interpreter >> std::ws).eof())
00086             throw bad_lexical_cast();
00087 
00088         //interpreter.precision(origPrecision);
00089 
00090         return result;
00091     }
00092 #else
00093    // Marcel 2004-04-01:
00094    // Copy from current boost.org cvs, slightly modified
00095    // to be not depending on other boost headers,
00096    // and added more expressive exception.what() text
00097 
00098     // exception used to indicate runtime lexical_cast failure
00099     class bad_lexical_cast : public std::bad_cast
00100     {
00101     public:
00102         bad_lexical_cast() :
00103         source(&typeid(void)), target(&typeid(void))
00104         {
00105         }
00106         bad_lexical_cast(
00107             const std::type_info &s,
00108             const std::type_info &t) :
00109             source(&s), target(&t)
00110         {
00111         }
00112         const std::type_info &source_type() const
00113         {
00114             return *source;
00115         }
00116         const std::type_info &target_type() const
00117         {
00118             return *target;
00119         }
00120         virtual const char *what() const throw()
00121         {
00122             XMLBLASTER_CPP_SNPRINTF((char*)str_, 255, "bad lexical cast: source type value '%.50s' could not be interpreted as target '%.50s'", 
00123                      source->name(), target->name());
00124             return str_;
00125         }
00126         virtual ~bad_lexical_cast() throw()
00127         {
00128         }
00129     private:
00130         const std::type_info *source;
00131         const std::type_info *target;
00132         char str_[256];
00133     };
00134 
00135     namespace detail // selectors for choosing stream character type
00136     {
00137         template<typename Type>
00138         struct stream_char
00139         {
00140             typedef char type;
00141         };
00142 
00143         #ifndef DISABLE_WIDE_CHAR_SUPPORT
00144         template<>
00145         struct stream_char<wchar_t>
00146         {
00147             typedef wchar_t type;
00148         };
00149 
00150         template<>
00151         struct stream_char<wchar_t *>
00152         {
00153             typedef wchar_t type;
00154         };
00155 
00156         template<>
00157         struct stream_char<const wchar_t *>
00158         {
00159             typedef wchar_t type;
00160         };
00161 
00162         template<>
00163         struct stream_char<std::wstring>
00164         {
00165             typedef wchar_t type;
00166         };
00167         #endif
00168 
00169         template<typename TargetChar, typename SourceChar>
00170         struct widest_char
00171         {
00172             typedef TargetChar type;
00173         };
00174 
00175         template<>
00176         struct widest_char<char, wchar_t>
00177         {
00178             typedef wchar_t type;
00179         };
00180     }
00181     
00182     namespace detail // stream wrapper for handling lexical conversions
00183     {
00184         template<typename Target, typename Source>
00185         class lexical_stream
00186         {
00187         public:
00188             lexical_stream()
00189             {
00190                 stream.unsetf(std::ios::skipws);
00191 
00192                 if(std::numeric_limits<Target>::is_specialized)
00193                     stream.precision(std::numeric_limits<Target>::digits10 + 1);
00194                 else if(std::numeric_limits<Source>::is_specialized)
00195                     stream.precision(std::numeric_limits<Source>::digits10 + 1);
00196             }
00197             ~lexical_stream()
00198             {
00199                 #if defined(BOOST_NO_STRINGSTREAM)
00200                 stream.freeze(false);
00201                 #endif
00202             }
00203             bool operator<<(const Source &input)
00204             {
00205                 return !(stream << input).fail();
00206             }
00207             template<typename InputStreamable>
00208             bool operator>>(InputStreamable &output)
00209             {
00210                 return 
00211                        stream >> output &&
00212                        (stream >> std::ws).eof();
00213             }
00214             bool operator>>(std::string &output)
00215             {
00216                 #if defined(BOOST_NO_STRINGSTREAM)
00217                 stream << '\0';
00218                 #endif
00219                 output = stream.str();
00220                 return true;
00221             }
00222             #ifndef DISABLE_WIDE_CHAR_SUPPORT
00223             bool operator>>(std::wstring &output)
00224             {
00225                 output = stream.str();
00226                 return true;
00227             }
00228             #endif
00229         private:
00230             typedef typename widest_char<
00231                 typename stream_char<Target>::type,
00232                 typename stream_char<Source>::type>::type char_type;
00233 
00234             #if defined(BOOST_NO_STRINGSTREAM)
00235             std::strstream stream;
00236             #elif defined(BOOST_NO_STD_LOCALE)
00237             std::stringstream stream;
00238             #else
00239             std::basic_stringstream<char_type> stream;
00240             #endif
00241         };
00242     }
00243 
00244     template<typename Target, typename Source>
00245     Target lexical_cast(Source arg)
00246     {
00247         detail::lexical_stream<Target, Source> interpreter;
00248         Target result;
00249 
00250         if(!(interpreter << arg && interpreter >> result))
00251             throw bad_lexical_cast(typeid(Target), typeid(Source));
00252         return result;
00253     }
00254 #endif
00255 
00256 //#if __GNUC__ == 2 || defined(__sun)
00257 #if __GNUC__ == 2 || defined(__SUNPRO_CC)
00258 //#if __GNUC__ == 2
00259   // Problems with g++ 2.95.3 and template<>
00260 #else
00261 
00265    template<> Dll_Export std::string lexical_cast(bool arg); // See Global.cpp
00266 
00270    template<> Dll_Export const char * lexical_cast(bool arg);
00271 
00278    template<> Dll_Export std::string lexical_cast(std::string arg); // See Global.cpp
00279 
00284    template<> Dll_Export bool lexical_cast(std::string arg); // See Global.cpp
00285    template<> Dll_Export bool lexical_cast(const char* arg); // See Global.cpp
00286 
00287 #endif
00288 }}}
00289 
00290 
00291 // Copyright Kevlin Henney, 2000, 2001, 2002. All rights reserved.
00292 //
00293 // Permission to use, copy, modify, and distribute this software for any
00294 // purpose is hereby granted without fee, provided that this copyright and
00295 // permissions notice appear in all copies and derivatives.
00296 //
00297 // This software is provided "as is" without express or implied warranty.
00298 
00299 #endif