lexical_cast.hpp

Go to the documentation of this file.
00001 /* $Id: lexical_cast.hpp 52533 2012-01-07 02:35:17Z shadowmaster $ */
00002 /*
00003    Copyright (C) 2009 - 2012 by Mark de Wever <koraq@xs4all.nl>
00004    Part of the Battle for Wesnoth Project http://www.wesnoth.org/
00005 
00006    This program is free software; you can redistribute it and/or modify
00007    it under the terms of the GNU General Public License as published by
00008    the Free Software Foundation; either version 2 of the License, or
00009    (at your option) any later version.
00010    This program is distributed in the hope that it will be useful,
00011    but WITHOUT ANY WARRANTY.
00012 
00013    See the COPYING file for more details.
00014 */
00015 
00016 /**
00017  * @file
00018  * New lexcical_cast header.
00019  *
00020  * For debugging you can include this header _in_ a namespace (to honour ODR)
00021  * and have a set of functions that throws exceptions instead of doing the
00022  * real job. This is done for the unit tests but should normally not be done.
00023  */
00024 
00025 #ifdef LEXICAL_CAST_DEBUG
00026 #undef LEXICAL_CAST_HPP_INCLUDED
00027 #endif
00028 
00029 #ifndef LEXICAL_CAST_HPP_INCLUDED
00030 #define LEXICAL_CAST_HPP_INCLUDED
00031 
00032 #ifdef LEXICAL_CAST_DEBUG
00033 
00034 #undef DEBUG_THROW
00035 /**
00036  * Throws an exception for debugging.
00037  *
00038  * @param id                      The unique name to identify the function.
00039  *                                @note this name is a user defined string and
00040  *                                should not be modified once used!
00041  */
00042 #define DEBUG_THROW(id) throw id;
00043 #else
00044 
00045 #ifdef __FreeBSD__
00046 #define __LONG_LONG_SUPPORTED
00047 #endif
00048 
00049 #ifdef _MSC_VER
00050 #define strtoll _strtoi64
00051 #define strtoull _strtoui64
00052 #endif
00053 
00054 #include "global.hpp"
00055 
00056 #include <string>
00057 #include <sstream>
00058 #include <boost/mpl/set.hpp>
00059 #include <boost/type_traits.hpp>
00060 #include <boost/utility/enable_if.hpp>
00061 
00062 #define DEBUG_THROW(id)
00063 #endif
00064 
00065 /**
00066  * @namespace implementation
00067  * Contains the implementation details for lexical_cast and shouldn't be used
00068  * directly.
00069  */
00070 namespace implementation {
00071 
00072     template<
00073           typename To
00074         , typename From
00075         , typename ToEnable = void
00076         , typename FromEnable = void
00077     >
00078     struct tlexical_cast;
00079 
00080 } // namespace implementation
00081 
00082 /**
00083  * Lexical cast converts one type to another.
00084  *
00085  * @tparam To                     The type to convert to.
00086  * @tparam From                   The type to convert from.
00087  *
00088  * @param value                   The value to convert.
00089  *
00090  * @returns                       The converted value.
00091  */
00092 template<typename To, typename From>
00093 inline To lexical_cast(From value)
00094 {
00095     return implementation::tlexical_cast<To, From>().operator()(value);
00096 }
00097 
00098 /** Thrown when a lexical_cast fails. */
00099 struct bad_lexical_cast {};
00100 
00101 namespace implementation {
00102 
00103 /**
00104  * Base class for the conversion.
00105  *
00106  * Since functions can't be partially specialized we use a class, which can be
00107  * partially specialized for the conversion.
00108  *
00109  * @tparam To                     The type to convert to.
00110  * @tparam From                   The type to convert from.
00111  * @tparam ToEnable               Filter to enable the To type.
00112  * @tparam FromEnable             Filter to enable the From type.
00113  */
00114 template<
00115       typename To
00116     , typename From
00117     , typename ToEnable
00118     , typename FromEnable
00119 >
00120 struct tlexical_cast
00121 {
00122     To operator()(From value)
00123     {
00124         DEBUG_THROW("generic");
00125 
00126         To result;
00127         std::stringstream sstr;
00128 
00129         if(!(sstr << value && sstr >> result)) {
00130             throw bad_lexical_cast();
00131         } else {
00132             return result;
00133         }
00134     }
00135 };
00136 
00137 /**
00138  * Specialized conversion class.
00139  *
00140  * Specialized for returning strings from an integral type or a pointer to an
00141  * intergral type.
00142  */
00143 template <typename From>
00144 struct tlexical_cast<
00145       std::string
00146     , From
00147     , void
00148     , typename boost::enable_if<boost::is_integral<
00149             typename boost::remove_pointer<From>::type> >::type
00150 >
00151 {
00152     std::string operator()(From value)
00153     {
00154         DEBUG_THROW("specialized - To std::string - From integral (pointer)");
00155 
00156         std::stringstream sstr;
00157         sstr << value;
00158         return sstr.str();
00159     }
00160 };
00161 
00162 /**
00163  * Specialized conversion class.
00164  *
00165  * Specialized for returning a long long from a (const) char*.
00166  * @note is separate from the other signed types since a long long has a
00167  * performance penalty at 32 bit systems.
00168  */
00169 template <class From>
00170 struct tlexical_cast<
00171       long long
00172     , From
00173     , void
00174     , typename boost::enable_if<boost::mpl::has_key<boost::mpl::set<
00175             char*, const char*> , From> >::type
00176     >
00177 {
00178     long long operator()(From value)
00179     {
00180         DEBUG_THROW("specialized - To long long - From (const) char*");
00181 
00182         char* endptr;
00183         int res = strtoll(value, &endptr, 10);
00184 
00185         if (*value == '\0' || *endptr != '\0') {
00186             throw bad_lexical_cast();
00187         } else {
00188             return res;
00189         }
00190     }
00191 };
00192 
00193 /**
00194  * Specialized conversion class.
00195  *
00196  * Specialized for returning a long long from a std::string.
00197  * @note is separate from the other signed types since a long long has a
00198  * performance penalty at 32 bit systems.
00199  */
00200 template <>
00201 struct tlexical_cast<
00202       long long
00203     , std::string
00204     >
00205 {
00206     long long operator()(const std::string& value)
00207     {
00208         DEBUG_THROW("specialized - To long long - From std::string");
00209 
00210         return lexical_cast<long long>(value.c_str());
00211     }
00212 };
00213 
00214 /**
00215  * Specialized conversion class.
00216  *
00217  * Specialized for returning a signed type from a (const) char*.
00218  */
00219 template <class To, class From>
00220 struct tlexical_cast<
00221       To
00222     , From
00223     , typename boost::enable_if<boost::is_signed<To> >::type
00224     , typename boost::enable_if<boost::mpl::has_key<boost::mpl::set<
00225             char*, const char*> , From> >::type
00226     >
00227 {
00228     To operator()(From value)
00229     {
00230         DEBUG_THROW("specialized - To signed - From (const) char*");
00231 
00232         char* endptr;
00233         int res = strtol(value, &endptr, 10);
00234 
00235         if (*value == '\0' || *endptr != '\0') {
00236             throw bad_lexical_cast();
00237         } else {
00238             return res;
00239         }
00240     }
00241 };
00242 
00243 /**
00244  * Specialized conversion class.
00245  *
00246  * Specialized for returning a signed type from a std::string.
00247  */
00248 template <class To>
00249 struct tlexical_cast<
00250       To
00251     , std::string
00252     , typename boost::enable_if<boost::is_signed<To> >::type
00253     >
00254 {
00255     To operator()(const std::string& value)
00256     {
00257         DEBUG_THROW("specialized - To signed - From std::string");
00258 
00259         return lexical_cast<To>(value.c_str());
00260     }
00261 };
00262 
00263 /**
00264  * Specialized conversion class.
00265  *
00266  * Specialized for returning a unsigned long long from a (const) char*.
00267  * @note is separate from the other unsigned types since a unsigned long long
00268  * has a performance penalty at 32 bit systems.
00269  */
00270 template <class From>
00271 struct tlexical_cast<
00272       unsigned long long
00273     , From
00274     , void
00275     , typename boost::enable_if<boost::mpl::has_key<boost::mpl::set<
00276             char*, const char*> , From> >::type
00277     >
00278 {
00279     long long operator()(From value)
00280     {
00281         DEBUG_THROW(
00282                 "specialized - To unsigned long long - From (const) char*");
00283 
00284         char* endptr;
00285         int res = strtoull(value, &endptr, 10);
00286 
00287         if (*value == '\0' || *endptr != '\0') {
00288             throw bad_lexical_cast();
00289         } else {
00290             return res;
00291         }
00292     }
00293 };
00294 
00295 /**
00296  * Specialized conversion class.
00297  *
00298  * Specialized for returning a unsigned long long from a std::string.
00299  * @note is separate from the other unsigned types since a unsigned long long
00300  * has a performance penalty at 32 bit systems.
00301  */
00302 template <>
00303 struct tlexical_cast<
00304       unsigned long long
00305     , std::string
00306     >
00307 {
00308     long long operator()(const std::string& value)
00309     {
00310         DEBUG_THROW("specialized - To unsigned long long - From std::string");
00311 
00312         return lexical_cast<unsigned long long>(value.c_str());
00313     }
00314 };
00315 
00316 /**
00317  * Specialized conversion class.
00318  *
00319  * Specialized for returning a unsigned type from a (const) char*.
00320  */
00321 template <class To, class From>
00322 struct tlexical_cast<
00323       To
00324     , From
00325     , typename boost::enable_if<boost::is_unsigned<To> >::type
00326     , typename boost::enable_if<boost::mpl::has_key<boost::mpl::set<
00327             char*, const char*> , From> >::type
00328     >
00329 {
00330     To operator()(From value)
00331     {
00332         DEBUG_THROW("specialized - To unsigned - From (const) char*");
00333 
00334         char* endptr;
00335         int res = strtoul(value, &endptr, 10);
00336 
00337         if (*value == '\0' || *endptr != '\0') {
00338             throw bad_lexical_cast();
00339         } else {
00340             return res;
00341         }
00342     }
00343 };
00344 
00345 /**
00346  * Specialized conversion class.
00347  *
00348  * Specialized for returning a unsigned type from a std::string.
00349  */
00350 template <class To>
00351 struct tlexical_cast<
00352       To
00353     , std::string
00354     , typename boost::enable_if<boost::is_unsigned<To> >::type
00355     >
00356 {
00357     To operator()(const std::string& value)
00358     {
00359         DEBUG_THROW("specialized - To unsigned - From std::string");
00360 
00361         return lexical_cast<To>(value.c_str());
00362     }
00363 };
00364 
00365 } // namespace implementation
00366 
00367 #endif
00368 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines

Generated by doxygen 1.7.1 on Fri May 25 2012 01:03:03 for The Battle for Wesnoth
Gna! | Forum | Wiki | CIA | devdocs