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
Copyright © 2006-2011 Savarese Software Research Corporation. All rights reserved.