Savarese Software Research Corporation
ToString.h
Go to the documentation of this file.
00001 /*
00002  * Copyright 2006-2009 Savarese Software Research Corporation
00003  *
00004  * Licensed under the Apache License, Version 2.0 (the "License");
00005  * you may not use this file except in compliance with the License.
00006  * You may obtain a copy of the License at
00007  *
00008  *     https://www.savarese.com/software/ApacheLicense-2.0
00009  *
00010  * Unless required by applicable law or agreed to in writing, software
00011  * distributed under the License is distributed on an "AS IS" BASIS,
00012  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00013  * See the License for the specific language governing permissions and
00014  * limitations under the License.
00015  */
00016 
00022 #ifndef __SSRC_WSPR_UTILITY_TO_STRING_H
00023 #define __SSRC_WSPR_UTILITY_TO_STRING_H
00024 
00025 #include <ssrc/wispers-packages.h>
00026 
00027 // Pull in std::bad_cast.
00028 #include <typeinfo>
00029 #include <sstream>
00030 
00031 // TODO: Determine if it's possible to use a static buffer in
00032 // configure.ac based on diagnostic test programs instead of
00033 // hardcoding a specific compiler and version check.
00034 #if defined(__GNUC__) && (__GNUC__ >= 4)
00035 #define __WSPR_LEXICAL_CAST_USE_STATIC_BUFFER
00036 #endif
00037 
00038 #ifdef __WSPR_LEXICAL_CAST_USE_STATIC_BUFFER
00039 #include <type_traits>
00040 #endif
00041 
00042 __BEGIN_NS_SSRC_WSPR_UTILITY
00043 
00044 using std::string;
00045 using std::ostringstream;
00046 
00058 class ToString {
00059   // This is big enough to hold the string representations of a
00060   // 128-bit integer.  If the representation is longer, the buffer
00061   // will not be overrun, but the output will be truncated.
00062 #ifdef __WSPR_LEXICAL_CAST_USE_STATIC_BUFFER
00063   char _buffer[64];
00064 #endif
00065   string _str;
00066   ostringstream _ostream;
00067 
00068 #ifdef __WSPR_LEXICAL_CAST_USE_STATIC_BUFFER
00069   void set_static_buffer() {
00070     _ostream.rdbuf()->pubsetbuf(_buffer, sizeof(_buffer));
00071   }
00072 
00073   template<typename T> const string & cast_to_string(const T & obj,
00074                                                      const std::true_type &)
00075     SSRC_DECL_THROW(std::bad_cast)
00076   {
00077     _ostream.seekp(0);
00078 
00079     if(!(_ostream << obj))
00080       throw std::bad_cast();
00081 
00082     _str.assign(_buffer,
00083                 std::min(static_cast<std::streampos>(sizeof(_buffer)),
00084                          _ostream.tellp()));
00085     return _str;
00086   }
00087 
00088   template<typename T> const char * cast_to_c_str(const T & obj,
00089                                                   const std::true_type &)
00090     SSRC_DECL_THROW(std::bad_cast)
00091   {
00092     _ostream.seekp(0);
00093 
00094     if(!(_ostream << obj))
00095       throw std::bad_cast();
00096 
00097     _buffer[std::min(static_cast<std::streampos>(sizeof(_buffer) - 1),
00098                      _ostream.tellp())] = 0;
00099     return _buffer;
00100   }
00101 #endif
00102 
00103   template<typename T> const string & cast_to_string(const T & obj
00104 #ifdef __WSPR_LEXICAL_CAST_USE_STATIC_BUFFER
00105                                                      , const std::false_type &
00106 #endif
00107                                                      )
00108     SSRC_DECL_THROW(std::bad_cast)
00109   {
00110     _ostream.str("");
00111 
00112     if(!(_ostream << obj))
00113       throw std::bad_cast();
00114 
00115     _str.assign(_ostream.str());
00116 
00117 #ifdef __WSPR_LEXICAL_CAST_USE_STATIC_BUFFER
00118     set_static_buffer();
00119 #endif
00120     return _str;
00121   }
00122 
00123   template<typename T> const char * cast_to_c_str(const T & obj
00124 #ifdef __WSPR_LEXICAL_CAST_USE_STATIC_BUFFER
00125                                                   , const std::false_type &
00126 #endif
00127                                                   )
00128     SSRC_DECL_THROW(std::bad_cast)
00129   {
00130     _ostream.str("");
00131 
00132     if(!(_ostream << obj))
00133       throw std::bad_cast();
00134 
00135     _str.assign(_ostream.str());
00136 
00137 #ifdef __WSPR_LEXICAL_CAST_USE_STATIC_BUFFER
00138     set_static_buffer();
00139 #endif
00140     return _str.c_str();
00141   }
00142 
00143 public:
00144   typedef ostringstream::fmtflags fmtflags;
00145   typedef ostringstream::iostate iostate;
00146 
00147   ToString(const ToString &) {
00148 #ifdef __WSPR_LEXICAL_CAST_USE_STATIC_BUFFER
00149     set_static_buffer();
00150 #endif
00151   }
00152 
00153   ToString() {
00154 #ifdef __WSPR_LEXICAL_CAST_USE_STATIC_BUFFER
00155     set_static_buffer();
00156 #endif
00157   }
00158 
00170 #ifdef __WSPR_LEXICAL_CAST_USE_STATIC_BUFFER
00171   template<typename T> const string & operator()(const T & obj)
00172     SSRC_DECL_THROW(std::bad_cast)
00173   {
00174     return cast_to_string(obj, std::is_fundamental<T>());
00175   }
00176 
00177   template<typename T> const char * c_str(const T & obj)
00178     SSRC_DECL_THROW(std::bad_cast)
00179   {
00180     return cast_to_c_str(obj, std::is_fundamental<T>());
00181   }
00182 #else
00183   template<typename T> const string & operator()(const T & obj)
00184     SSRC_DECL_THROW(std::bad_cast)
00185   {
00186     return cast_to_string(obj);
00187   }
00188 
00189   template<typename T> const char * c_str(const T & obj)
00190     SSRC_DECL_THROW(std::bad_cast)
00191   {
00192     return cast_to_c_str(obj);
00193   }
00194 #endif
00195 
00196   fmtflags flags() const {
00197     return _ostream.flags();
00198   }
00199 
00200   fmtflags flags(const fmtflags flags) {
00201     return _ostream.flags(flags);
00202   }
00203 
00204   fmtflags setf(const fmtflags flags) {
00205     return _ostream.setf(flags);
00206   }
00207 
00208   fmtflags setf(const fmtflags flags,
00209                                const fmtflags mask)
00210   {
00211     return _ostream.setf(flags, mask);
00212   }
00213 
00214   void unsetf(const fmtflags flags) {
00215     _ostream.unsetf(flags);
00216   }
00217 
00218   iostate rdstate() const {
00219     return _ostream.rdstate();
00220   }
00221 
00222   void clear(iostate state = ostringstream::goodbit) {
00223     _ostream.clear(state);
00224   }
00225 
00226   void setstate(iostate state) {
00227     _ostream.setstate(state);
00228   }
00229 
00230 };
00231 
00232 #ifdef __WSPR_LEXICAL_CAST_USE_STATIC_BUFFER
00233 #undef __WSPR_LEXICAL_CAST_USE_STATIC_BUFFER
00234 #endif
00235 
00236 // Only intended for primitive types, otherwise static buffer may
00237 // be too small.  Should really specialize behavior based on
00238 // primitive type.
00239 template<typename T>
00240 inline string to_string(const T & obj)
00241   SSRC_DECL_THROW(std::bad_cast)
00242 {
00243   ToString string_cast;
00244   return string_cast(obj);
00245 }
00246 
00247 template<>
00248 inline string to_string<string>(const string & obj)
00249   SSRC_DECL_THROW(std::bad_cast)
00250 {
00251   return obj;
00252 }
00253 
00254 template<>
00255 inline string to_string<char *>(char * const & obj)
00256   SSRC_DECL_THROW(std::bad_cast)
00257 {
00258   return obj;
00259 }
00260 
00261 __END_NS_SSRC_WSPR_UTILITY
00262 
00263 #endif

Savarese Software Research Corporation
Copyright © 2006-2011 Savarese Software Research Corporation. All rights reserved.