log4cplus  2.0.0
stringhelper.h
Go to the documentation of this file.
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_