Coverage Report

Created: 2026-03-31 07:26

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/log4cplus/include/log4cplus/helpers/stringhelper.h
Line
Count
Source
1
// -*- C++ -*-
2
// Module:  Log4CPLUS
3
// File:    stringhelper.h
4
// Created: 3/2003
5
// Author:  Tad E. Smith
6
//
7
//
8
// Copyright 2003-2017 Tad E. Smith
9
//
10
// Licensed under the Apache License, Version 2.0 (the "License");
11
// you may not use this file except in compliance with the License.
12
// You may obtain a copy of the License at
13
//
14
//     http://www.apache.org/licenses/LICENSE-2.0
15
//
16
// Unless required by applicable law or agreed to in writing, software
17
// distributed under the License is distributed on an "AS IS" BASIS,
18
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
19
// See the License for the specific language governing permissions and
20
// limitations under the License.
21
22
/** @file */
23
24
#ifndef LOG4CPLUS_HELPERS_STRINGHELPER_HEADER_
25
#define LOG4CPLUS_HELPERS_STRINGHELPER_HEADER_
26
27
#include <log4cplus/config.hxx>
28
29
#if defined (LOG4CPLUS_HAVE_PRAGMA_ONCE)
30
#pragma once
31
#endif
32
33
#include <log4cplus/tstring.h>
34
35
#include <algorithm>
36
#include <limits>
37
38
39
namespace log4cplus {
40
    namespace helpers {
41
42
        /**
43
         * Returns <code>s</code> in upper case.
44
         */
45
        LOG4CPLUS_EXPORT log4cplus::tstring toUpper(const log4cplus::tstring& s);
46
        LOG4CPLUS_EXPORT tchar toUpper(tchar);
47
48
49
        /**
50
         * Returns <code>s</code> in lower case.
51
         */
52
        LOG4CPLUS_EXPORT log4cplus::tstring toLower(const log4cplus::tstring& s);
53
        LOG4CPLUS_EXPORT tchar toLower(tchar);
54
55
56
        /**
57
         * Tokenize <code>s</code> using <code>c</code> as the delimiter and
58
         * put the resulting tokens in <code>_result</code>.  If
59
         * <code>collapseTokens</code> is false, multiple adjacent delimiters
60
         * will result in zero length tokens.
61
         *
62
         * <b>Example:</b>
63
         * <pre>
64
         *   string s = // Set string with '.' as delimiters
65
         *   list<log4cplus::tstring> tokens;
66
         *   tokenize(s, '.', back_insert_iterator<list<string> >(tokens));
67
         * </pre>
68
         */
69
        template <class StringType, class OutputIter>
70
        inline
71
        void
72
        tokenize(const StringType& s, typename StringType::value_type c,
73
            OutputIter result, bool collapseTokens = true)
74
120k
        {
75
120k
            typedef typename StringType::size_type size_type;
76
120k
            size_type const slen = s.length();
77
120k
            size_type first = 0;
78
120k
            size_type i = 0;
79
1.56M
            for (i=0; i < slen; ++i)
80
1.44M
            {
81
1.44M
                if (s[i] == c)
82
120k
                {
83
120k
                    *result = StringType (s, first, i - first);
84
120k
                    ++result;
85
120k
                    if (collapseTokens)
86
120k
                        while (i+1 < slen && s[i+1] == c)
87
0
                            ++i;
88
120k
                    first = i + 1;
89
120k
                }
90
1.44M
            }
91
120k
            if (first != i)
92
120k
                *result = StringType (s, first, i - first);
93
0
            else if (! collapseTokens && first == i)
94
0
                *result = StringType ();
95
120k
        }
96
97
98
        template <typename intType, typename stringType, bool isSigned>
99
        struct ConvertIntegerToStringHelper;
100
101
102
        template <typename intType, typename charType>
103
        struct ConvertIntegerToStringHelper<intType, charType, true>
104
        {
105
            static inline
106
            void
107
            step1 (charType * & it, intType & value)
108
0
            {
109
                // The sign of the result of the modulo operator is
110
                // implementation defined. That's why we work with
111
                // positive counterpart instead.  Also, in twos
112
                // complement arithmetic the smallest negative number
113
                // does not have positive counterpart; the range is
114
                // asymetric.  That's why we handle the case of value
115
                // == min() specially here.
116
0
                if (LOG4CPLUS_UNLIKELY (
117
0
                    value == (std::numeric_limits<intType>::min) ()))
118
0
                {
119
0
                    intType const r = value / 10;
120
0
                    intType const a = (-r) * 10;
121
0
                    intType const mod = -(a + value);
122
0
                    value = -r;
123
124
0
                    *(it - 1)
125
0
                        = static_cast<charType>(LOG4CPLUS_TEXT('0') + mod);
126
0
                    --it;
127
0
                }
128
0
                else
129
0
                    value = -value;
130
0
            }
Unexecuted instantiation: log4cplus::helpers::ConvertIntegerToStringHelper<int, char, true>::step1(char*&, int&)
Unexecuted instantiation: log4cplus::helpers::ConvertIntegerToStringHelper<long, char, true>::step1(char*&, long&)
131
132
            static
133
            bool
134
            is_negative (intType val)
135
1.12M
            {
136
1.12M
                return val < 0;
137
1.12M
            }
log4cplus::helpers::ConvertIntegerToStringHelper<int, char, true>::is_negative(int)
Line
Count
Source
135
561k
            {
136
561k
                return val < 0;
137
561k
            }
log4cplus::helpers::ConvertIntegerToStringHelper<long, char, true>::is_negative(long)
Line
Count
Source
135
560k
            {
136
560k
                return val < 0;
137
560k
            }
138
        };
139
140
141
        template <typename intType, typename charType>
142
        struct ConvertIntegerToStringHelper<intType, charType, false>
143
        {
144
            static inline
145
            void
146
            step1 (charType * &, intType &)
147
0
            {
148
                // This will never be called for unsigned types.
149
0
            }
Unexecuted instantiation: log4cplus::helpers::ConvertIntegerToStringHelper<unsigned int, char, false>::step1(char*&, unsigned int&)
Unexecuted instantiation: log4cplus::helpers::ConvertIntegerToStringHelper<unsigned short, char, false>::step1(char*&, unsigned short&)
Unexecuted instantiation: log4cplus::helpers::ConvertIntegerToStringHelper<unsigned long, char, false>::step1(char*&, unsigned long&)
150
151
            static
152
            bool
153
            is_negative (intType)
154
120k
            {
155
120k
                return false;
156
120k
            }
log4cplus::helpers::ConvertIntegerToStringHelper<unsigned int, char, false>::is_negative(unsigned int)
Line
Count
Source
154
120k
            {
155
120k
                return false;
156
120k
            }
Unexecuted instantiation: log4cplus::helpers::ConvertIntegerToStringHelper<unsigned short, char, false>::is_negative(unsigned short)
Unexecuted instantiation: log4cplus::helpers::ConvertIntegerToStringHelper<unsigned long, char, false>::is_negative(unsigned long)
157
        };
158
159
160
        template <class stringType, class intType>
161
        inline
162
        void
163
        convertIntegerToString (stringType & str, intType value)
164
1.24M
        {
165
1.24M
            typedef std::numeric_limits<intType> intTypeLimits;
166
1.24M
            typedef typename stringType::value_type charType;
167
1.24M
            typedef ConvertIntegerToStringHelper<intType, charType,
168
1.24M
                intTypeLimits::is_signed> HelperType;
169
170
1.24M
            charType buffer[intTypeLimits::digits10 + 2];
171
1.24M
            const std::size_t buffer_size
172
1.24M
                = sizeof (buffer) / sizeof (charType);
173
174
1.24M
            charType * it = &buffer[buffer_size];
175
1.24M
            charType const * const buf_end = &buffer[buffer_size];
176
177
1.24M
            if (LOG4CPLUS_UNLIKELY (value == 0))
178
521
            {
179
521
                --it;
180
521
                *it = LOG4CPLUS_TEXT('0');
181
521
            }
182
1.24M
            else
183
1.24M
            {
184
1.24M
                bool const negative = HelperType::is_negative (value);
185
1.24M
                if (negative)
186
0
                    HelperType::step1 (it, value);
187
188
5.96M
                for (; value != 0; --it)
189
4.72M
                {
190
4.72M
                    intType mod = value % 10;
191
4.72M
                    value = value / 10;
192
4.72M
                    *(it - 1) = static_cast<charType>(LOG4CPLUS_TEXT('0')
193
4.72M
                        + mod);
194
4.72M
                }
195
196
1.24M
                if (negative)
197
0
                {
198
0
                    --it;
199
0
                    *it = LOG4CPLUS_TEXT('-');
200
0
                }
201
1.24M
            }
202
203
1.24M
            str.assign (static_cast<charType const *>(it), buf_end);
204
1.24M
        }
void log4cplus::helpers::convertIntegerToString<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, unsigned int>(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >&, unsigned int)
Line
Count
Source
164
120k
        {
165
120k
            typedef std::numeric_limits<intType> intTypeLimits;
166
120k
            typedef typename stringType::value_type charType;
167
120k
            typedef ConvertIntegerToStringHelper<intType, charType,
168
120k
                intTypeLimits::is_signed> HelperType;
169
170
120k
            charType buffer[intTypeLimits::digits10 + 2];
171
120k
            const std::size_t buffer_size
172
120k
                = sizeof (buffer) / sizeof (charType);
173
174
120k
            charType * it = &buffer[buffer_size];
175
120k
            charType const * const buf_end = &buffer[buffer_size];
176
177
120k
            if (LOG4CPLUS_UNLIKELY (value == 0))
178
0
            {
179
0
                --it;
180
0
                *it = LOG4CPLUS_TEXT('0');
181
0
            }
182
120k
            else
183
120k
            {
184
120k
                bool const negative = HelperType::is_negative (value);
185
120k
                if (negative)
186
0
                    HelperType::step1 (it, value);
187
188
241k
                for (; value != 0; --it)
189
120k
                {
190
120k
                    intType mod = value % 10;
191
120k
                    value = value / 10;
192
120k
                    *(it - 1) = static_cast<charType>(LOG4CPLUS_TEXT('0')
193
120k
                        + mod);
194
120k
                }
195
196
120k
                if (negative)
197
0
                {
198
0
                    --it;
199
0
                    *it = LOG4CPLUS_TEXT('-');
200
0
                }
201
120k
            }
202
203
120k
            str.assign (static_cast<charType const *>(it), buf_end);
204
120k
        }
void log4cplus::helpers::convertIntegerToString<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, int>(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >&, int)
Line
Count
Source
164
561k
        {
165
561k
            typedef std::numeric_limits<intType> intTypeLimits;
166
561k
            typedef typename stringType::value_type charType;
167
561k
            typedef ConvertIntegerToStringHelper<intType, charType,
168
561k
                intTypeLimits::is_signed> HelperType;
169
170
561k
            charType buffer[intTypeLimits::digits10 + 2];
171
561k
            const std::size_t buffer_size
172
561k
                = sizeof (buffer) / sizeof (charType);
173
174
561k
            charType * it = &buffer[buffer_size];
175
561k
            charType const * const buf_end = &buffer[buffer_size];
176
177
561k
            if (LOG4CPLUS_UNLIKELY (value == 0))
178
0
            {
179
0
                --it;
180
0
                *it = LOG4CPLUS_TEXT('0');
181
0
            }
182
561k
            else
183
561k
            {
184
561k
                bool const negative = HelperType::is_negative (value);
185
561k
                if (negative)
186
0
                    HelperType::step1 (it, value);
187
188
3.53M
                for (; value != 0; --it)
189
2.97M
                {
190
2.97M
                    intType mod = value % 10;
191
2.97M
                    value = value / 10;
192
2.97M
                    *(it - 1) = static_cast<charType>(LOG4CPLUS_TEXT('0')
193
2.97M
                        + mod);
194
2.97M
                }
195
196
561k
                if (negative)
197
0
                {
198
0
                    --it;
199
0
                    *it = LOG4CPLUS_TEXT('-');
200
0
                }
201
561k
            }
202
203
561k
            str.assign (static_cast<charType const *>(it), buf_end);
204
561k
        }
Unexecuted instantiation: void log4cplus::helpers::convertIntegerToString<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, unsigned short>(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >&, unsigned short)
Unexecuted instantiation: void log4cplus::helpers::convertIntegerToString<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, unsigned long>(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >&, unsigned long)
void log4cplus::helpers::convertIntegerToString<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, long>(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >&, long)
Line
Count
Source
164
561k
        {
165
561k
            typedef std::numeric_limits<intType> intTypeLimits;
166
561k
            typedef typename stringType::value_type charType;
167
561k
            typedef ConvertIntegerToStringHelper<intType, charType,
168
561k
                intTypeLimits::is_signed> HelperType;
169
170
561k
            charType buffer[intTypeLimits::digits10 + 2];
171
561k
            const std::size_t buffer_size
172
561k
                = sizeof (buffer) / sizeof (charType);
173
174
561k
            charType * it = &buffer[buffer_size];
175
561k
            charType const * const buf_end = &buffer[buffer_size];
176
177
561k
            if (LOG4CPLUS_UNLIKELY (value == 0))
178
521
            {
179
521
                --it;
180
521
                *it = LOG4CPLUS_TEXT('0');
181
521
            }
182
560k
            else
183
560k
            {
184
560k
                bool const negative = HelperType::is_negative (value);
185
560k
                if (negative)
186
0
                    HelperType::step1 (it, value);
187
188
2.18M
                for (; value != 0; --it)
189
1.62M
                {
190
1.62M
                    intType mod = value % 10;
191
1.62M
                    value = value / 10;
192
1.62M
                    *(it - 1) = static_cast<charType>(LOG4CPLUS_TEXT('0')
193
1.62M
                        + mod);
194
1.62M
                }
195
196
560k
                if (negative)
197
0
                {
198
0
                    --it;
199
0
                    *it = LOG4CPLUS_TEXT('-');
200
0
                }
201
560k
            }
202
203
561k
            str.assign (static_cast<charType const *>(it), buf_end);
204
561k
        }
205
206
207
        template<class intType>
208
        inline
209
        tstring
210
        convertIntegerToString (intType value)
211
120k
        {
212
120k
            tstring result;
213
120k
            convertIntegerToString (result, value);
214
120k
            return result;
215
120k
        }
std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > log4cplus::helpers::convertIntegerToString<unsigned int>(unsigned int)
Line
Count
Source
211
120k
        {
212
120k
            tstring result;
213
120k
            convertIntegerToString (result, value);
214
120k
            return result;
215
120k
        }
Unexecuted instantiation: std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > log4cplus::helpers::convertIntegerToString<int>(int)
216
217
218
        template<class intType>
219
        inline
220
        std::string
221
        convertIntegerToNarrowString (intType value)
222
0
        {
223
0
            std::string result;
224
0
            convertIntegerToString (result, value);
225
0
            return result;
226
0
        }
Unexecuted instantiation: std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > log4cplus::helpers::convertIntegerToNarrowString<unsigned short>(unsigned short)
Unexecuted instantiation: std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > log4cplus::helpers::convertIntegerToNarrowString<unsigned long>(unsigned long)
227
228
229
        //! Join a list of items into a string.
230
        template <typename Iterator, typename Separator>
231
        inline
232
        void
233
        join_worker (tstring & result, Iterator & start, Iterator & last,
234
            Separator const & sep)
235
0
        {
236
0
            if (start != last)
237
0
                result = *start++;
238
239
0
            for (; start != last; ++start)
240
0
            {
241
0
                result += sep;
242
0
                result += *start;
243
0
            }
244
0
        }
245
246
        //! Join a list of items into a string.
247
        template <typename Iterator>
248
        inline
249
        void
250
        join (tstring & result, Iterator start, Iterator last,
251
            tstring const & sep)
252
0
        {
253
0
            join_worker (result, start, last, sep);
254
0
        }
255
256
        //! Join a list of items into a string.
257
        template <typename Iterator>
258
        inline
259
        void
260
        join (tstring & result, Iterator start, Iterator last,
261
            tstring::value_type sep)
262
        {
263
            join_worker (result, start, last, sep);
264
        }
265
266
267
    } // namespace helpers
268
269
} // namespace log4cplus
270
271
#endif // LOG4CPLUS_HELPERS_STRINGHELPER_HEADER_