00001 #ifndef CPPTL_STRINGTOOLS_H_INCLUDED
00002 # define CPPTL_STRINGTOOLS_H_INCLUDED
00003
00004 # include <cpptl/conststring.h>
00005 # include <float.h>
00006 # include <stdio.h>
00007
00008 namespace CppTL {
00009
00010 inline bool isDigit( char c )
00011 {
00012 return unsigned(c) >= '0' && unsigned(c) <= '9';
00013 }
00014
00015 inline char digit( unsigned number )
00016 {
00017 static const char *digits = "0123456789";
00018 return digits[number];
00019 }
00020
00021 inline char hexaDigit( unsigned number )
00022 {
00023 static const char *digit = "0123456789abcdef";
00024 return digit[number];
00025 }
00026
00027 template<class IntType>
00028 struct SignedPolicy
00029 {
00030 void makePositive( IntType &value )
00031 {
00032 isNegative_ = value < 0;
00033 if ( isNegative_ )
00034 value *= -1;
00035 }
00036
00037 bool needMinusSign() const
00038 {
00039 return isNegative_;
00040 }
00041
00042 bool isNegative_;
00043 };
00044
00045 template<class IntType>
00046 struct UnsignedPolicy
00047 {
00048 void makePositive( IntType & )
00049 {
00050 }
00051
00052 bool needMinusSign() const
00053 {
00054 return false;
00055 }
00056 };
00057
00058 template<class IntType, class SignPolicy>
00059 CppTL::ConstString integerToString( IntType v, SignPolicy sign )
00060 {
00061 char buffer[32];
00062 char *current = &buffer[32];
00063 *--current = 0;
00064 if ( v == 0 )
00065 *--current = '0';
00066 else
00067 {
00068 sign.makePositive( v );
00069 while ( v != 0 )
00070 {
00071 *--current = digit( unsigned(v % 10) );
00072 v /= 10;
00073 }
00074 if ( sign.needMinusSign() )
00075 *--current = '-';
00076 }
00077 return current;
00078 }
00079
00080
00081 template<class UnsignedIntegerType>
00082 CppTL::ConstString
00083 integerToHexaString( UnsignedIntegerType value )
00084 {
00085 const int bufferLength = sizeof(UnsignedIntegerType) * 2 + 1;
00086 char buffer[ bufferLength ];
00087 char *current = &buffer[ bufferLength ];
00088 char *end = current;
00089 *--current = 0;
00090 do
00091 {
00092 *--current += hexaDigit( size_type(value & 15) );
00093 value /= 16;
00094 }
00095 while ( value != 0 );
00096
00097 return CppTL::ConstString( current, end );
00098 }
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127 inline CppTL::ConstString toString( char c )
00128 {
00129 return CppTL::ConstString( &c, 1 );
00130 }
00131
00132 inline CppTL::ConstString toString( int v )
00133 {
00134 return integerToString( v, SignedPolicy<int>() );
00135 }
00136
00137 inline CppTL::ConstString toString( unsigned int v )
00138 {
00139 return integerToString( v, UnsignedPolicy<unsigned int>() );
00140 }
00141
00142 inline CppTL::ConstString toString( long v )
00143 {
00144 return integerToString( v, SignedPolicy<long>() );
00145 }
00146
00147 inline CppTL::ConstString toString( unsigned long v )
00148 {
00149 return integerToString( v, UnsignedPolicy<unsigned long>() );
00150 }
00151
00152 inline CppTL::ConstString toString( short v )
00153 {
00154 return integerToString( v, SignedPolicy<short>() );
00155 }
00156
00157 inline CppTL::ConstString toString( unsigned short v )
00158 {
00159 return integerToString( v, UnsignedPolicy<unsigned short>() );
00160 }
00161
00162 #ifndef CPPTL_NO_INT64
00163
00164 inline CppTL::ConstString toString( int64_t v )
00165 {
00166 return integerToString( v, SignedPolicy<int64_t>() );
00167 }
00168
00169 inline CppTL::ConstString toString( uint64_t v )
00170 {
00171 return integerToString( v, UnsignedPolicy<uint64_t>() );
00172 }
00173 #endif
00174
00175 inline CppTL::ConstString toString( float v )
00176 {
00177 #ifdef FLT_DIG
00178 const int precision = FLT_DIG;
00179 #else
00180 const int precision = 6;
00181 #endif // #ifdef FLT_DIG
00182 char buffer[128];
00183 #ifdef __STDC_SECURE_LIB__ // Use secure version with visual studio 2005 to avoid warning.
00184 sprintf_s(buffer, sizeof(buffer), "%.*g", precision, v);
00185 #else
00186 sprintf(buffer, "%.*g", precision, v);
00187 #endif
00188 return buffer;
00189 }
00190
00191 inline CppTL::ConstString toString( double v )
00192 {
00193 #ifdef DBL_DIG
00194 const int precision = DBL_DIG;
00195 #else
00196 const int precision = 15;
00197 #endif // #ifdef DBL_DIG
00198 char buffer[128];
00199 #ifdef __STDC_SECURE_LIB__ // Use secure version with visual studio 2005 to avoid warning.
00200 sprintf_s(buffer, sizeof(buffer), "%.*g", precision, v);
00201 #else
00202 sprintf(buffer, "%.*g", precision, v);
00203 #endif
00204 return buffer;
00205 }
00206
00207 inline CppTL::ConstString toString( long double v )
00208 {
00209 #ifdef DBL_DIG
00210 const int precision = DBL_DIG;
00211 #else
00212 const int precision = 15;
00213 #endif // #ifdef DBL_DIG
00214 char buffer[128];
00215 #ifdef __STDC_SECURE_LIB__ // Use secure version with visual studio 2005 to avoid warning.
00216 sprintf_s(buffer, sizeof(buffer), "%.*g", precision, v);
00217 #else
00218 sprintf(buffer, "%.*g", precision, v);
00219 #endif
00220 return buffer;
00221 }
00222
00223 inline CppTL::ConstString toString( bool v )
00224 {
00225 return v ? "true" : "false";
00226 }
00227
00228
00229 inline CppTL::ConstString toHexaString( unsigned int v )
00230 {
00231 return integerToHexaString( v );
00232 }
00233
00234
00235 #ifndef CPPTL_NO_INT64
00236 inline CppTL::ConstString toHexaString( uint64_t v )
00237 {
00238 return integerToHexaString( v );
00239 }
00240 #endif
00241
00242
00243 inline void
00244 escapeControl( char c, CppTL::StringBuffer &escaped, const char *newLineEscape = "\\n" )
00245 {
00246 switch ( c )
00247 {
00248 case '\n':
00249 escaped += newLineEscape;
00250 break;
00251 case '\t':
00252 escaped += CppTL::ConstCharView( "\\t", 2 );
00253 break;
00254 case '\r':
00255 escaped += CppTL::ConstCharView( "\\r", 2 );
00256 break;
00257 case '\v':
00258 escaped += CppTL::ConstCharView( "\\v", 2 );
00259 break;
00260 default:
00261 {
00262 char hexa[2];
00263 hexa[0] = hexaDigit( (c >> 4) & 15 );
00264 hexa[1] = hexaDigit( c & 15 );
00265 escaped += CppTL::ConstCharView( "\\x", 2 )
00266 + ConstCharView( hexa, hexa + sizeof(hexa) );
00267 }
00268 break;
00269 }
00270 }
00271
00272
00273 inline void
00274 escape( char c, CppTL::StringBuffer &escaped, const char *newLineEscape = "\\n" )
00275 {
00276 if ( c >=0 && c < 32 )
00277 escapeControl( c, escaped, newLineEscape );
00278 else if ( c == '\\' )
00279 escaped += CppTL::ConstCharView( "\\\\", 2 );
00280 escaped += CppTL::ConstCharView( &c, 1 );
00281 }
00282
00283
00284
00285 inline void
00286 escapeRange( const char *first,
00287 const char *last,
00288 CppTL::StringBuffer &escaped,
00289 const char *newLineEscape = "\\n" )
00290 {
00291 while ( first != last )
00292 escape( *first++, escaped, newLineEscape );
00293 }
00294
00295 inline void
00296 escape( const CppTL::ConstString &text,
00297 CppTL::StringBuffer &escaped,
00298 const char *newLineEscape = "\\n" )
00299 {
00300 escapeRange( text.c_str(), text.c_str() + text.length(), escaped );
00301 }
00302
00303
00304 inline CppTL::ConstString
00305 quoteStringRange( const char *first,
00306 const char *last,
00307 const char *newLineEscape = "\\n" )
00308 {
00309 CppTL::StringBuffer escaped( size_type((last-first) * 1.2) + 64 );
00310 escaped += CppTL::ConstCharView( "\"", 1 );
00311 escapeRange(first, last, escaped, newLineEscape );
00312 escaped += CppTL::ConstCharView( "\"", 1 );
00313 return escaped;
00314 }
00315
00316
00317 inline CppTL::ConstString
00318 quoteString( const CppTL::ConstString &text,
00319 const char *newLineEscape = "\\n" )
00320 {
00321 return quoteStringRange( text.c_str(), text.c_str() + text.length() );
00322 }
00323
00324
00325 inline CppTL::ConstString
00326 quoteMultiLineStringRange( const char *first,
00327 const char *last )
00328 {
00329 return quoteStringRange( first, last, "\\n\n" );
00330 }
00331
00332
00333 inline CppTL::ConstString
00334 quoteMultiLineString( const CppTL::ConstString &str )
00335 {
00336 return quoteString( str, "\\n\n" );
00337 }
00338
00339
00340 }
00341
00342 #endif // CPPTL_STRINGTOOLS_H_INCLUDED
00343