log4cplus
2.0.0
|
00001 // -*- C++ -*- 00002 // Module: Log4CPLUS 00003 // File: stringhelper.h 00004 // Created: 3/2003 00005 // Author: Tad E. Smith 00006 // 00007 // 00008 // Copyright 2003-2015 Tad E. Smith 00009 // 00010 // Licensed under the Apache License, Version 2.0 (the "License"); 00011 // you may not use this file except in compliance with the License. 00012 // You may obtain a copy of the License at 00013 // 00014 // http://www.apache.org/licenses/LICENSE-2.0 00015 // 00016 // Unless required by applicable law or agreed to in writing, software 00017 // distributed under the License is distributed on an "AS IS" BASIS, 00018 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00019 // See the License for the specific language governing permissions and 00020 // limitations under the License. 00021 00024 #ifndef LOG4CPLUS_HELPERS_STRINGHELPER_HEADER_ 00025 #define LOG4CPLUS_HELPERS_STRINGHELPER_HEADER_ 00026 00027 #include <log4cplus/config.hxx> 00028 00029 #if defined (LOG4CPLUS_HAVE_PRAGMA_ONCE) 00030 #pragma once 00031 #endif 00032 00033 #include <log4cplus/tstring.h> 00034 00035 #include <algorithm> 00036 #include <limits> 00037 00038 00039 namespace log4cplus { 00040 namespace helpers { 00041 00045 LOG4CPLUS_EXPORT log4cplus::tstring toUpper(const log4cplus::tstring& s); 00046 LOG4CPLUS_EXPORT tchar toUpper(tchar); 00047 00048 00052 LOG4CPLUS_EXPORT log4cplus::tstring toLower(const log4cplus::tstring& s); 00053 LOG4CPLUS_EXPORT tchar toLower(tchar); 00054 00055 00069 template <class StringType, class OutputIter> 00070 inline 00071 void 00072 tokenize(const StringType& s, typename StringType::value_type c, 00073 OutputIter result, bool collapseTokens = true) 00074 { 00075 typedef typename StringType::size_type size_type; 00076 size_type const slen = s.length(); 00077 size_type first = 0; 00078 size_type i = 0; 00079 for (i=0; i < slen; ++i) 00080 { 00081 if (s[i] == c) 00082 { 00083 *result = StringType (s, first, i - first); 00084 ++result; 00085 if (collapseTokens) 00086 while (i+1 < slen && s[i+1] == c) 00087 ++i; 00088 first = i + 1; 00089 } 00090 } 00091 if (first != i) 00092 *result = StringType (s, first, i - first); 00093 else if (! collapseTokens && first == i) 00094 *result = StringType (); 00095 } 00096 00097 00098 template <typename intType, typename stringType, bool isSigned> 00099 struct ConvertIntegerToStringHelper; 00100 00101 00102 template <typename intType, typename charType> 00103 struct ConvertIntegerToStringHelper<intType, charType, true> 00104 { 00105 static inline 00106 void 00107 step1 (charType * & it, intType & value) 00108 { 00109 // The sign of the result of the modulo operator is 00110 // implementation defined. That's why we work with 00111 // positive counterpart instead. Also, in twos 00112 // complement arithmetic the smallest negative number 00113 // does not have positive counterpart; the range is 00114 // asymetric. That's why we handle the case of value 00115 // == min() specially here. 00116 if (LOG4CPLUS_UNLIKELY ( 00117 value == (std::numeric_limits<intType>::min) ())) 00118 { 00119 intType const r = value / 10; 00120 intType const a = (-r) * 10; 00121 intType const mod = -(a + value); 00122 value = -r; 00123 00124 *(it - 1) 00125 = static_cast<charType>(LOG4CPLUS_TEXT('0') + mod); 00126 --it; 00127 } 00128 else 00129 value = -value; 00130 } 00131 00132 static 00133 bool 00134 is_negative (intType val) 00135 { 00136 return val < 0; 00137 } 00138 }; 00139 00140 00141 template <typename intType, typename charType> 00142 struct ConvertIntegerToStringHelper<intType, charType, false> 00143 { 00144 static inline 00145 void 00146 step1 (charType * &, intType &) 00147 { 00148 // This will never be called for unsigned types. 00149 } 00150 00151 static 00152 bool 00153 is_negative (intType) 00154 { 00155 return false; 00156 } 00157 }; 00158 00159 00160 template <class stringType, class intType> 00161 inline 00162 void 00163 convertIntegerToString (stringType & str, intType value) 00164 { 00165 typedef std::numeric_limits<intType> intTypeLimits; 00166 typedef typename stringType::value_type charType; 00167 typedef ConvertIntegerToStringHelper<intType, charType, 00168 intTypeLimits::is_signed> HelperType; 00169 00170 charType buffer[intTypeLimits::digits10 + 2]; 00171 const std::size_t buffer_size 00172 = sizeof (buffer) / sizeof (charType); 00173 00174 charType * it = &buffer[buffer_size]; 00175 charType const * const buf_end = &buffer[buffer_size]; 00176 00177 if (LOG4CPLUS_UNLIKELY (value == 0)) 00178 { 00179 --it; 00180 *it = LOG4CPLUS_TEXT('0'); 00181 } 00182 else 00183 { 00184 bool const negative = HelperType::is_negative (value); 00185 if (negative) 00186 HelperType::step1 (it, value); 00187 00188 for (; value != 0; --it) 00189 { 00190 intType mod = value % 10; 00191 value = value / 10; 00192 *(it - 1) = static_cast<charType>(LOG4CPLUS_TEXT('0') 00193 + mod); 00194 } 00195 00196 if (negative) 00197 { 00198 --it; 00199 *it = LOG4CPLUS_TEXT('-'); 00200 } 00201 } 00202 00203 str.assign (static_cast<charType const *>(it), buf_end); 00204 } 00205 00206 00207 template<class intType> 00208 inline 00209 tstring 00210 convertIntegerToString (intType value) 00211 { 00212 tstring result; 00213 convertIntegerToString (result, value); 00214 return result; 00215 } 00216 00217 00218 template<class intType> 00219 inline 00220 std::string 00221 convertIntegerToNarrowString (intType value) 00222 { 00223 std::string result; 00224 convertIntegerToString (result, value); 00225 return result; 00226 } 00227 00228 00230 template <typename Iterator, typename Separator> 00231 inline 00232 void 00233 join_worker (tstring & result, Iterator & start, Iterator & last, 00234 Separator const & sep) 00235 { 00236 if (start != last) 00237 result = *start++; 00238 00239 for (; start != last; ++start) 00240 { 00241 result += sep; 00242 result += *start; 00243 } 00244 } 00245 00247 template <typename Iterator> 00248 inline 00249 void 00250 join (tstring & result, Iterator start, Iterator last, 00251 tstring const & sep) 00252 { 00253 join_worker (result, start, last, sep); 00254 } 00255 00257 template <typename Iterator> 00258 inline 00259 void 00260 join (tstring & result, Iterator start, Iterator last, 00261 tstring::value_type sep) 00262 { 00263 join_worker (result, start, last, sep); 00264 } 00265 00266 00267 } // namespace helpers 00268 00269 } // namespace log4cplus 00270 00271 #endif // LOG4CPLUS_HELPERS_STRINGHELPER_HEADER_