Coverage Report

Created: 2025-11-16 09:57

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libreoffice/sal/rtl/strtmpl.hxx
Line
Count
Source
1
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2
/*
3
 * This file is part of the LibreOffice project.
4
 *
5
 * This Source Code Form is subject to the terms of the Mozilla Public
6
 * License, v. 2.0. If a copy of the MPL was not distributed with this
7
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8
 *
9
 * This file incorporates work covered by the following license notice:
10
 *
11
 *   Licensed to the Apache Software Foundation (ASF) under one or more
12
 *   contributor license agreements. See the NOTICE file distributed
13
 *   with this work for additional information regarding copyright
14
 *   ownership. The ASF licenses this file to you under the Apache
15
 *   License, Version 2.0 (the "License"); you may not use this file
16
 *   except in compliance with the License. You may obtain a copy of
17
 *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
18
 */
19
20
#pragma once
21
22
#include <algorithm>
23
#include <cassert>
24
#include <cmath>
25
#include <cstddef>
26
#include <cstdlib>
27
#include <cstring>
28
#include <cwchar>
29
#include <limits>
30
#include <new>
31
#include <string_view>
32
#include <type_traits>
33
#include <utility>
34
35
#include "strimp.hxx"
36
37
#include <o3tl/safeint.hxx>
38
#include <o3tl/string_view.hxx>
39
#include <osl/diagnose.h>
40
#include <sal/log.hxx>
41
#include <rtl/character.hxx>
42
#include <rtl/math.h>
43
#include <rtl/string.h>
44
#include <rtl/ustring.h>
45
46
#include <dragonbox/dragonbox.h>
47
48
void internRelease(rtl_uString*);
49
50
namespace rtl::str
51
{
52
13.3G
template <typename C> auto UChar(C c) { return std::make_unsigned_t<C>(c); }
auto rtl::str::UChar<char>(char)
Line
Count
Source
52
1.60G
template <typename C> auto UChar(C c) { return std::make_unsigned_t<C>(c); }
auto rtl::str::UChar<char16_t>(char16_t)
Line
Count
Source
52
11.7G
template <typename C> auto UChar(C c) { return std::make_unsigned_t<C>(c); }
53
54
// Wrappers around null-terminated/known-length strings, that allow to generalize algorithms
55
// without overhead (e.g., without need to get length of null-terminated strings).
56
57
template <typename C> struct null_terminated
58
{
59
    C* p;
60
    null_terminated(C* pStr)
61
374M
        : p(pStr)
62
374M
    {
63
374M
        assert(pStr);
64
374M
    }
rtl::str::null_terminated<char const>::null_terminated(char const*)
Line
Count
Source
61
355M
        : p(pStr)
62
355M
    {
63
        assert(pStr);
64
355M
    }
Unexecuted instantiation: rtl::str::null_terminated<char>::null_terminated(char*)
rtl::str::null_terminated<char16_t const>::null_terminated(char16_t const*)
Line
Count
Source
61
19.2M
        : p(pStr)
62
19.2M
    {
63
        assert(pStr);
64
19.2M
    }
Unexecuted instantiation: rtl::str::null_terminated<char16_t>::null_terminated(char16_t*)
65
374M
    auto begin() const { return p; }
rtl::str::null_terminated<char const>::begin() const
Line
Count
Source
65
355M
    auto begin() const { return p; }
Unexecuted instantiation: rtl::str::null_terminated<char>::begin() const
rtl::str::null_terminated<char16_t const>::begin() const
Line
Count
Source
65
19.2M
    auto begin() const { return p; }
Unexecuted instantiation: rtl::str::null_terminated<char16_t>::begin() const
66
    struct EndDetector
67
    {
68
        friend bool operator==(EndDetector, C* iter) { return *iter == 0; }
69
1.02G
        friend bool operator==(C* iter, EndDetector) { return *iter == 0; }
rtl::str::operator==(char const*, rtl::str::null_terminated<char const>::EndDetector)
Line
Count
Source
69
826M
        friend bool operator==(C* iter, EndDetector) { return *iter == 0; }
Unexecuted instantiation: rtl::str::operator==(char*, rtl::str::null_terminated<char>::EndDetector)
rtl::str::operator==(char16_t const*, rtl::str::null_terminated<char16_t const>::EndDetector)
Line
Count
Source
69
199M
        friend bool operator==(C* iter, EndDetector) { return *iter == 0; }
Unexecuted instantiation: rtl::str::operator==(char16_t*, rtl::str::null_terminated<char16_t>::EndDetector)
70
    };
71
374M
    static auto end() { return EndDetector{}; }
rtl::str::null_terminated<char const>::end()
Line
Count
Source
71
355M
    static auto end() { return EndDetector{}; }
Unexecuted instantiation: rtl::str::null_terminated<char>::end()
rtl::str::null_terminated<char16_t const>::end()
Line
Count
Source
71
19.2M
    static auto end() { return EndDetector{}; }
Unexecuted instantiation: rtl::str::null_terminated<char16_t>::end()
72
};
73
74
template <typename C> struct with_length
75
{
76
    C* p;
77
    sal_Int32 len;
78
    with_length(C* pStr, sal_Int32 nLength)
79
9.11G
        : p(pStr)
80
9.11G
        , len(nLength)
81
9.11G
    {
82
9.11G
        assert(len >= 0);
83
9.11G
    }
rtl::str::with_length<char const>::with_length(char const*, int)
Line
Count
Source
79
320M
        : p(pStr)
80
320M
        , len(nLength)
81
320M
    {
82
        assert(len >= 0);
83
320M
    }
Unexecuted instantiation: rtl::str::with_length<char>::with_length(char*, int)
rtl::str::with_length<char16_t const>::with_length(char16_t const*, int)
Line
Count
Source
79
8.79G
        : p(pStr)
80
8.79G
        , len(nLength)
81
8.79G
    {
82
        assert(len >= 0);
83
8.79G
    }
rtl::str::with_length<char16_t>::with_length(char16_t*, int)
Line
Count
Source
79
376k
        : p(pStr)
80
376k
        , len(nLength)
81
376k
    {
82
        assert(len >= 0);
83
376k
    }
84
575M
    auto begin() const { return p; }
rtl::str::with_length<char const>::begin() const
Line
Count
Source
84
18.1M
    auto begin() const { return p; }
Unexecuted instantiation: rtl::str::with_length<char>::begin() const
rtl::str::with_length<char16_t const>::begin() const
Line
Count
Source
84
557M
    auto begin() const { return p; }
rtl::str::with_length<char16_t>::begin() const
Line
Count
Source
84
376k
    auto begin() const { return p; }
85
575M
    auto end() const { return p + len; }
rtl::str::with_length<char const>::end() const
Line
Count
Source
85
18.1M
    auto end() const { return p + len; }
Unexecuted instantiation: rtl::str::with_length<char>::end() const
rtl::str::with_length<char16_t const>::end() const
Line
Count
Source
85
557M
    auto end() const { return p + len; }
rtl::str::with_length<char16_t>::end() const
Line
Count
Source
85
376k
    auto end() const { return p + len; }
86
};
87
88
template <bool (&fApplicable)(sal_uInt32), sal_uInt32 (&fReplace)(sal_uInt32)> struct CaseReplace
89
{
90
54.6M
    static auto Applicable() { return [](auto c) { return fApplicable(UChar(c)); }; }
rtl::str::CaseReplace<rtl::isAsciiUpperCase(unsigned int), rtl::toAsciiLowerCase(unsigned int)>::Applicable()
Line
Count
Source
90
9.19M
    static auto Applicable() { return [](auto c) { return fApplicable(UChar(c)); }; }
rtl::str::CaseReplace<rtl::isAsciiLowerCase(unsigned int), rtl::toAsciiUpperCase(unsigned int)>::Applicable()
Line
Count
Source
90
6.48M
    static auto Applicable() { return [](auto c) { return fApplicable(UChar(c)); }; }
auto rtl::str::CaseReplace<rtl::isAsciiUpperCase(unsigned int), rtl::toAsciiLowerCase(unsigned int)>::Applicable()::{lambda(auto:1)#1}::operator()<char>(char) const
Line
Count
Source
90
34.8k
    static auto Applicable() { return [](auto c) { return fApplicable(UChar(c)); }; }
auto rtl::str::CaseReplace<rtl::isAsciiLowerCase(unsigned int), rtl::toAsciiUpperCase(unsigned int)>::Applicable()::{lambda(auto:1)#1}::operator()<char>(char) const
Line
Count
Source
90
80
    static auto Applicable() { return [](auto c) { return fApplicable(UChar(c)); }; }
auto rtl::str::CaseReplace<rtl::isAsciiUpperCase(unsigned int), rtl::toAsciiLowerCase(unsigned int)>::Applicable()::{lambda(auto:1)#1}::operator()<char16_t>(char16_t) const
Line
Count
Source
90
28.9M
    static auto Applicable() { return [](auto c) { return fApplicable(UChar(c)); }; }
auto rtl::str::CaseReplace<rtl::isAsciiLowerCase(unsigned int), rtl::toAsciiUpperCase(unsigned int)>::Applicable()::{lambda(auto:1)#1}::operator()<char16_t>(char16_t) const
Line
Count
Source
90
25.6M
    static auto Applicable() { return [](auto c) { return fApplicable(UChar(c)); }; }
91
82.7M
    template <typename C> static C Replace(C c) { return fReplace(UChar(c)); }
char rtl::str::CaseReplace<rtl::isAsciiUpperCase(unsigned int), rtl::toAsciiLowerCase(unsigned int)>::Replace<char>(char)
Line
Count
Source
91
68.5k
    template <typename C> static C Replace(C c) { return fReplace(UChar(c)); }
char rtl::str::CaseReplace<rtl::isAsciiLowerCase(unsigned int), rtl::toAsciiUpperCase(unsigned int)>::Replace<char>(char)
Line
Count
Source
91
80
    template <typename C> static C Replace(C c) { return fReplace(UChar(c)); }
char16_t rtl::str::CaseReplace<rtl::isAsciiUpperCase(unsigned int), rtl::toAsciiLowerCase(unsigned int)>::Replace<char16_t>(char16_t)
Line
Count
Source
91
53.3M
    template <typename C> static C Replace(C c) { return fReplace(UChar(c)); }
char16_t rtl::str::CaseReplace<rtl::isAsciiLowerCase(unsigned int), rtl::toAsciiUpperCase(unsigned int)>::Replace<char16_t>(char16_t)
Line
Count
Source
91
29.3M
    template <typename C> static C Replace(C c) { return fReplace(UChar(c)); }
92
};
93
constexpr CaseReplace<rtl::isAsciiUpperCase, rtl::toAsciiLowerCase> toAsciiLower;
94
constexpr CaseReplace<rtl::isAsciiLowerCase, rtl::toAsciiUpperCase> toAsciiUpper;
95
96
template <typename C> struct FromTo
97
{
98
    C from;
99
    C to;
100
530k
    FromTo(C cFrom, C cTo) : from(cFrom), to(cTo) {}
Unexecuted instantiation: rtl::str::FromTo<char>::FromTo(char, char)
rtl::str::FromTo<char16_t>::FromTo(char16_t, char16_t)
Line
Count
Source
100
530k
    FromTo(C cFrom, C cTo) : from(cFrom), to(cTo) {}
101
13.5M
    auto Applicable() const { return [this](C c) { return c == from; }; }
Unexecuted instantiation: rtl::str::FromTo<char>::Applicable() const
rtl::str::FromTo<char16_t>::Applicable() const
Line
Count
Source
101
530k
    auto Applicable() const { return [this](C c) { return c == from; }; }
Unexecuted instantiation: rtl::str::FromTo<char>::Applicable() const::{lambda(char)#1}::operator()(char) const
rtl::str::FromTo<char16_t>::Applicable() const::{lambda(char16_t)#1}::operator()(char16_t) const
Line
Count
Source
101
13.5M
    auto Applicable() const { return [this](C c) { return c == from; }; }
102
10.8M
    C Replace(C c) const { return c == from ? to : c; }
Unexecuted instantiation: rtl::str::FromTo<char>::Replace(char) const
rtl::str::FromTo<char16_t>::Replace(char16_t) const
Line
Count
Source
102
10.8M
    C Replace(C c) const { return c == from ? to : c; }
103
};
104
105
template <typename C> void Copy(C* _pDest, const C* _pSrc, sal_Int32 _nCount)
106
2.16G
{
107
    // take advantage of builtin optimisations
108
2.16G
    std::copy(_pSrc, _pSrc + _nCount, _pDest);
109
2.16G
}
void rtl::str::Copy<char>(char*, char const*, int)
Line
Count
Source
106
122M
{
107
    // take advantage of builtin optimisations
108
122M
    std::copy(_pSrc, _pSrc + _nCount, _pDest);
109
122M
}
void rtl::str::Copy<char16_t>(char16_t*, char16_t const*, int)
Line
Count
Source
106
2.04G
{
107
    // take advantage of builtin optimisations
108
2.04G
    std::copy(_pSrc, _pSrc + _nCount, _pDest);
109
2.04G
}
110
111
template <typename C> void CopyBackward(C* _pDest, const C* _pSrc, sal_Int32 _nCount)
112
12.8M
{
113
    // take advantage of builtin optimisations
114
12.8M
    std::copy_backward(_pSrc, _pSrc + _nCount, _pDest + _nCount);
115
12.8M
}
Unexecuted instantiation: void rtl::str::CopyBackward<char>(char*, char const*, int)
void rtl::str::CopyBackward<char16_t>(char16_t*, char16_t const*, int)
Line
Count
Source
112
12.8M
{
113
    // take advantage of builtin optimisations
114
12.8M
    std::copy_backward(_pSrc, _pSrc + _nCount, _pDest + _nCount);
115
12.8M
}
116
117
inline void Copy(sal_Unicode* _pDest, const char* _pSrc, sal_Int32 _nCount)
118
75.0M
{
119
75.0M
    std::transform(_pSrc, _pSrc + _nCount, _pDest,
120
75.0M
                   [](char c)
121
1.68G
                   {
122
1.68G
                       assert(rtl::isAscii(static_cast<unsigned char>(c)));
123
1.68G
                       SAL_WARN_IF(c == '\0', "rtl.string", "Found embedded \\0 ASCII character");
124
1.68G
                       return static_cast<unsigned char>(c);
125
1.68G
                   });
126
75.0M
}
127
128
inline sal_Int16 implGetDigit(sal_Unicode ch, sal_Int16 nRadix)
129
251M
{
130
251M
    sal_Int16 n = -1;
131
251M
    if ((ch >= '0') && (ch <= '9'))
132
246M
        n = ch - '0';
133
4.97M
    else if ((ch >= 'a') && (ch <= 'z'))
134
487k
        n = ch - 'a' + 10;
135
4.48M
    else if ((ch >= 'A') && (ch <= 'Z'))
136
763k
        n = ch - 'A' + 10;
137
251M
    return (n < nRadix) ? n : -1;
138
251M
}
139
140
/* ======================================================================= */
141
/* C-String functions which could be used without the String-Class         */
142
/* ======================================================================= */
143
144
template <typename T> sal_Int32 getLength( const T* pStr )
145
196M
{
146
196M
    assert(pStr);
147
    if constexpr (std::is_class_v<T>)
148
176k
    {
149
176k
        return pStr->length;
150
    }
151
    else
152
195M
    {
153
        // take advantage of builtin optimisations
154
195M
        return std::char_traits<T>::length(pStr);
155
195M
    }
156
196M
}
int rtl::str::getLength<char>(char const*)
Line
Count
Source
145
181M
{
146
181M
    assert(pStr);
147
    if constexpr (std::is_class_v<T>)
148
    {
149
        return pStr->length;
150
    }
151
    else
152
181M
    {
153
        // take advantage of builtin optimisations
154
181M
        return std::char_traits<T>::length(pStr);
155
181M
    }
156
181M
}
Unexecuted instantiation: int rtl::str::getLength<_rtl_String>(_rtl_String const*)
int rtl::str::getLength<char16_t>(char16_t const*)
Line
Count
Source
145
14.8M
{
146
14.8M
    assert(pStr);
147
    if constexpr (std::is_class_v<T>)
148
    {
149
        return pStr->length;
150
    }
151
    else
152
14.8M
    {
153
        // take advantage of builtin optimisations
154
14.8M
        return std::char_traits<T>::length(pStr);
155
14.8M
    }
156
14.8M
}
int rtl::str::getLength<_rtl_uString>(_rtl_uString const*)
Line
Count
Source
145
176k
{
146
176k
    assert(pStr);
147
    if constexpr (std::is_class_v<T>)
148
176k
    {
149
176k
        return pStr->length;
150
    }
151
    else
152
    {
153
        // take advantage of builtin optimisations
154
        return std::char_traits<T>::length(pStr);
155
    }
156
176k
}
157
158
/* ----------------------------------------------------------------------- */
159
160
template <typename C> void warnIfCharAndNotAscii(C c)
161
1.67G
{
162
    if constexpr (sizeof(c) == sizeof(char))
163
839M
        SAL_WARN_IF(!rtl::isAscii(static_cast<unsigned char>(c)), "rtl.string",
164
1.67G
                    "Found non-ASCII char");
165
1.67G
}
void rtl::str::warnIfCharAndNotAscii<char16_t>(char16_t)
Line
Count
Source
161
839M
{
162
    if constexpr (sizeof(c) == sizeof(char))
163
        SAL_WARN_IF(!rtl::isAscii(static_cast<unsigned char>(c)), "rtl.string",
164
839M
                    "Found non-ASCII char");
165
839M
}
void rtl::str::warnIfCharAndNotAscii<char>(char)
Line
Count
Source
161
839M
{
162
    if constexpr (sizeof(c) == sizeof(char))
163
839M
        SAL_WARN_IF(!rtl::isAscii(static_cast<unsigned char>(c)), "rtl.string",
164
839M
                    "Found non-ASCII char");
165
839M
}
166
167
template <typename C1, typename C2> void warnIfOneIsCharAndNotAscii(C1 c1, C2 c2)
168
4.48G
{
169
    if constexpr (sizeof(c1) != sizeof(c2))
170
839M
    {
171
839M
        warnIfCharAndNotAscii(c1);
172
839M
        warnIfCharAndNotAscii(c2);
173
839M
    }
174
4.48G
}
void rtl::str::warnIfOneIsCharAndNotAscii<char, char>(char, char)
Line
Count
Source
168
365M
{
169
    if constexpr (sizeof(c1) != sizeof(c2))
170
    {
171
        warnIfCharAndNotAscii(c1);
172
        warnIfCharAndNotAscii(c2);
173
    }
174
365M
}
void rtl::str::warnIfOneIsCharAndNotAscii<char16_t, char>(char16_t, char)
Line
Count
Source
168
839M
{
169
    if constexpr (sizeof(c1) != sizeof(c2))
170
839M
    {
171
839M
        warnIfCharAndNotAscii(c1);
172
839M
        warnIfCharAndNotAscii(c2);
173
839M
    }
174
839M
}
void rtl::str::warnIfOneIsCharAndNotAscii<char16_t, char16_t>(char16_t, char16_t)
Line
Count
Source
168
3.28G
{
169
    if constexpr (sizeof(c1) != sizeof(c2))
170
    {
171
        warnIfCharAndNotAscii(c1);
172
        warnIfCharAndNotAscii(c2);
173
    }
174
3.28G
}
175
176
struct CompareNormal
177
{
178
    template <typename C1, typename C2> static sal_Int32 compare(C1 c1, C2 c2)
179
4.20G
    {
180
4.20G
        warnIfOneIsCharAndNotAscii(c1, c2);
181
4.20G
        return static_cast<sal_Int32>(UChar(c1))
182
4.20G
               - static_cast<sal_Int32>(UChar(c2));
183
4.20G
    }
int rtl::str::CompareNormal::compare<char, char>(char, char)
Line
Count
Source
179
365M
    {
180
365M
        warnIfOneIsCharAndNotAscii(c1, c2);
181
365M
        return static_cast<sal_Int32>(UChar(c1))
182
365M
               - static_cast<sal_Int32>(UChar(c2));
183
365M
    }
int rtl::str::CompareNormal::compare<char16_t, char>(char16_t, char)
Line
Count
Source
179
806M
    {
180
806M
        warnIfOneIsCharAndNotAscii(c1, c2);
181
806M
        return static_cast<sal_Int32>(UChar(c1))
182
806M
               - static_cast<sal_Int32>(UChar(c2));
183
806M
    }
int rtl::str::CompareNormal::compare<char16_t, char16_t>(char16_t, char16_t)
Line
Count
Source
179
3.03G
    {
180
3.03G
        warnIfOneIsCharAndNotAscii(c1, c2);
181
3.03G
        return static_cast<sal_Int32>(UChar(c1))
182
3.03G
               - static_cast<sal_Int32>(UChar(c2));
183
3.03G
    }
184
};
185
186
struct CompareIgnoreAsciiCase
187
{
188
    template <typename C1, typename C2> static sal_Int32 compare(C1 c1, C2 c2)
189
281M
    {
190
281M
        warnIfOneIsCharAndNotAscii(c1, c2);
191
281M
        return rtl::compareIgnoreAsciiCase(UChar(c1), UChar(c2));
192
281M
    }
int rtl::str::CompareIgnoreAsciiCase::compare<char, char>(char, char)
Line
Count
Source
189
614k
    {
190
614k
        warnIfOneIsCharAndNotAscii(c1, c2);
191
614k
        return rtl::compareIgnoreAsciiCase(UChar(c1), UChar(c2));
192
614k
    }
int rtl::str::CompareIgnoreAsciiCase::compare<char16_t, char>(char16_t, char)
Line
Count
Source
189
33.5M
    {
190
33.5M
        warnIfOneIsCharAndNotAscii(c1, c2);
191
33.5M
        return rtl::compareIgnoreAsciiCase(UChar(c1), UChar(c2));
192
33.5M
    }
int rtl::str::CompareIgnoreAsciiCase::compare<char16_t, char16_t>(char16_t, char16_t)
Line
Count
Source
189
247M
    {
190
247M
        warnIfOneIsCharAndNotAscii(c1, c2);
191
247M
        return rtl::compareIgnoreAsciiCase(UChar(c1), UChar(c2));
192
247M
    }
193
};
194
195
/* ----------------------------------------------------------------------- */
196
197
struct NoShortening
198
{
199
0
    constexpr bool operator>=(int) { return true; } // for assert
200
0
    constexpr bool operator==(int) { return false; } // for loop break check
201
765M
    constexpr void operator--() {} // for decrement in loop
202
} constexpr noShortening;
203
204
template <class S1, class S2, class Compare, typename Shorten_t>
205
sal_Int32 compare(S1 s1, S2 s2, Compare, Shorten_t shortenedLength)
206
427M
{
207
427M
    static_assert(std::is_same_v<Shorten_t, NoShortening> || std::is_same_v<Shorten_t, sal_Int32>);
208
427M
    assert(shortenedLength >= 0);
209
427M
    auto pStr1 = s1.begin();
210
427M
    const auto end1 = s1.end();
211
427M
    auto pStr2 = s2.begin();
212
427M
    const auto end2 = s2.end();
213
427M
    for (;;)
214
1.21G
    {
215
1.21G
        if (shortenedLength == 0)
216
629k
            return 0;
217
1.21G
        if (pStr2 == end2)
218
40.9M
            return pStr1 == end1 ? 0 : 1;
219
1.17G
        if (pStr1 == end1)
220
4.32M
            return -1;
221
1.16G
        if (const sal_Int32 nRet = Compare::compare(*pStr1, *pStr2))
222
381M
            return nRet;
223
786M
        --shortenedLength;
224
786M
        ++pStr1;
225
786M
        ++pStr2;
226
786M
    }
227
427M
}
int rtl::str::compare<rtl::str::null_terminated<char const>, rtl::str::null_terminated<char const>, rtl::str::CompareIgnoreAsciiCase, rtl::str::NoShortening>(rtl::str::null_terminated<char const>, rtl::str::null_terminated<char const>, rtl::str::CompareIgnoreAsciiCase, rtl::str::NoShortening)
Line
Count
Source
206
142k
{
207
142k
    static_assert(std::is_same_v<Shorten_t, NoShortening> || std::is_same_v<Shorten_t, sal_Int32>);
208
142k
    assert(shortenedLength >= 0);
209
142k
    auto pStr1 = s1.begin();
210
142k
    const auto end1 = s1.end();
211
142k
    auto pStr2 = s2.begin();
212
142k
    const auto end2 = s2.end();
213
142k
    for (;;)
214
448k
    {
215
448k
        if (shortenedLength == 0)
216
0
            return 0;
217
448k
        if (pStr2 == end2)
218
20.3k
            return pStr1 == end1 ? 0 : 1;
219
428k
        if (pStr1 == end1)
220
0
            return -1;
221
428k
        if (const sal_Int32 nRet = Compare::compare(*pStr1, *pStr2))
222
122k
            return nRet;
223
305k
        --shortenedLength;
224
305k
        ++pStr1;
225
305k
        ++pStr2;
226
305k
    }
227
142k
}
int rtl::str::compare<rtl::str::with_length<char const>, rtl::str::with_length<char const>, rtl::str::CompareIgnoreAsciiCase, rtl::str::NoShortening>(rtl::str::with_length<char const>, rtl::str::with_length<char const>, rtl::str::CompareIgnoreAsciiCase, rtl::str::NoShortening)
Line
Count
Source
206
160k
{
207
160k
    static_assert(std::is_same_v<Shorten_t, NoShortening> || std::is_same_v<Shorten_t, sal_Int32>);
208
160k
    assert(shortenedLength >= 0);
209
160k
    auto pStr1 = s1.begin();
210
160k
    const auto end1 = s1.end();
211
160k
    auto pStr2 = s2.begin();
212
160k
    const auto end2 = s2.end();
213
160k
    for (;;)
214
188k
    {
215
188k
        if (shortenedLength == 0)
216
0
            return 0;
217
188k
        if (pStr2 == end2)
218
2.13k
            return pStr1 == end1 ? 0 : 1;
219
186k
        if (pStr1 == end1)
220
0
            return -1;
221
186k
        if (const sal_Int32 nRet = Compare::compare(*pStr1, *pStr2))
222
158k
            return nRet;
223
28.5k
        --shortenedLength;
224
28.5k
        ++pStr1;
225
28.5k
        ++pStr2;
226
28.5k
    }
227
160k
}
int rtl::str::compare<rtl::str::null_terminated<char16_t const>, rtl::str::null_terminated<char const>, rtl::str::CompareNormal, rtl::str::NoShortening>(rtl::str::null_terminated<char16_t const>, rtl::str::null_terminated<char const>, rtl::str::CompareNormal, rtl::str::NoShortening)
Line
Count
Source
206
314k
{
207
314k
    static_assert(std::is_same_v<Shorten_t, NoShortening> || std::is_same_v<Shorten_t, sal_Int32>);
208
314k
    assert(shortenedLength >= 0);
209
314k
    auto pStr1 = s1.begin();
210
314k
    const auto end1 = s1.end();
211
314k
    auto pStr2 = s2.begin();
212
314k
    const auto end2 = s2.end();
213
314k
    for (;;)
214
1.50M
    {
215
1.50M
        if (shortenedLength == 0)
216
0
            return 0;
217
1.50M
        if (pStr2 == end2)
218
227k
            return pStr1 == end1 ? 0 : 1;
219
1.27M
        if (pStr1 == end1)
220
0
            return -1;
221
1.27M
        if (const sal_Int32 nRet = Compare::compare(*pStr1, *pStr2))
222
86.8k
            return nRet;
223
1.18M
        --shortenedLength;
224
1.18M
        ++pStr1;
225
1.18M
        ++pStr2;
226
1.18M
    }
227
314k
}
int rtl::str::compare<rtl::str::with_length<char16_t const>, rtl::str::null_terminated<char const>, rtl::str::CompareNormal, rtl::str::NoShortening>(rtl::str::with_length<char16_t const>, rtl::str::null_terminated<char const>, rtl::str::CompareNormal, rtl::str::NoShortening)
Line
Count
Source
206
343M
{
207
343M
    static_assert(std::is_same_v<Shorten_t, NoShortening> || std::is_same_v<Shorten_t, sal_Int32>);
208
343M
    assert(shortenedLength >= 0);
209
343M
    auto pStr1 = s1.begin();
210
343M
    const auto end1 = s1.end();
211
343M
    auto pStr2 = s2.begin();
212
343M
    const auto end2 = s2.end();
213
343M
    for (;;)
214
789M
    {
215
789M
        if (shortenedLength == 0)
216
0
            return 0;
217
789M
        if (pStr2 == end2)
218
10.2M
            return pStr1 == end1 ? 0 : 1;
219
779M
        if (pStr1 == end1)
220
1.86M
            return -1;
221
777M
        if (const sal_Int32 nRet = Compare::compare(*pStr1, *pStr2))
222
331M
            return nRet;
223
445M
        --shortenedLength;
224
445M
        ++pStr1;
225
445M
        ++pStr2;
226
445M
    }
227
343M
}
int rtl::str::compare<rtl::str::with_length<char16_t const>, rtl::str::null_terminated<char const>, rtl::str::CompareNormal, int>(rtl::str::with_length<char16_t const>, rtl::str::null_terminated<char const>, rtl::str::CompareNormal, int)
Line
Count
Source
206
7.85M
{
207
7.85M
    static_assert(std::is_same_v<Shorten_t, NoShortening> || std::is_same_v<Shorten_t, sal_Int32>);
208
7.85M
    assert(shortenedLength >= 0);
209
7.85M
    auto pStr1 = s1.begin();
210
7.85M
    const auto end1 = s1.end();
211
7.85M
    auto pStr2 = s2.begin();
212
7.85M
    const auto end2 = s2.end();
213
7.85M
    for (;;)
214
28.0M
    {
215
28.0M
        if (shortenedLength == 0)
216
542k
            return 0;
217
27.4M
        if (pStr2 == end2)
218
0
            return pStr1 == end1 ? 0 : 1;
219
27.4M
        if (pStr1 == end1)
220
51
            return -1;
221
27.4M
        if (const sal_Int32 nRet = Compare::compare(*pStr1, *pStr2))
222
7.31M
            return nRet;
223
20.1M
        --shortenedLength;
224
20.1M
        ++pStr1;
225
20.1M
        ++pStr2;
226
20.1M
    }
227
7.85M
}
Unexecuted instantiation: int rtl::str::compare<rtl::str::null_terminated<char16_t const>, rtl::str::null_terminated<char const>, rtl::str::CompareIgnoreAsciiCase, rtl::str::NoShortening>(rtl::str::null_terminated<char16_t const>, rtl::str::null_terminated<char const>, rtl::str::CompareIgnoreAsciiCase, rtl::str::NoShortening)
int rtl::str::compare<rtl::str::with_length<char16_t const>, rtl::str::null_terminated<char const>, rtl::str::CompareIgnoreAsciiCase, rtl::str::NoShortening>(rtl::str::with_length<char16_t const>, rtl::str::null_terminated<char const>, rtl::str::CompareIgnoreAsciiCase, rtl::str::NoShortening)
Line
Count
Source
206
2.69M
{
207
2.69M
    static_assert(std::is_same_v<Shorten_t, NoShortening> || std::is_same_v<Shorten_t, sal_Int32>);
208
2.69M
    assert(shortenedLength >= 0);
209
2.69M
    auto pStr1 = s1.begin();
210
2.69M
    const auto end1 = s1.end();
211
2.69M
    auto pStr2 = s2.begin();
212
2.69M
    const auto end2 = s2.end();
213
2.69M
    for (;;)
214
5.68M
    {
215
5.68M
        if (shortenedLength == 0)
216
0
            return 0;
217
5.68M
        if (pStr2 == end2)
218
370k
            return pStr1 == end1 ? 0 : 1;
219
5.31M
        if (pStr1 == end1)
220
6.44k
            return -1;
221
5.31M
        if (const sal_Int32 nRet = Compare::compare(*pStr1, *pStr2))
222
2.31M
            return nRet;
223
2.99M
        --shortenedLength;
224
2.99M
        ++pStr1;
225
2.99M
        ++pStr2;
226
2.99M
    }
227
2.69M
}
int rtl::str::compare<rtl::str::with_length<char16_t const>, rtl::str::with_length<char const>, rtl::str::CompareIgnoreAsciiCase, rtl::str::NoShortening>(rtl::str::with_length<char16_t const>, rtl::str::with_length<char const>, rtl::str::CompareIgnoreAsciiCase, rtl::str::NoShortening)
Line
Count
Source
206
8.32M
{
207
8.32M
    static_assert(std::is_same_v<Shorten_t, NoShortening> || std::is_same_v<Shorten_t, sal_Int32>);
208
8.32M
    assert(shortenedLength >= 0);
209
8.32M
    auto pStr1 = s1.begin();
210
8.32M
    const auto end1 = s1.end();
211
8.32M
    auto pStr2 = s2.begin();
212
8.32M
    const auto end2 = s2.end();
213
8.32M
    for (;;)
214
31.6M
    {
215
31.6M
        if (shortenedLength == 0)
216
0
            return 0;
217
31.6M
        if (pStr2 == end2)
218
4.50M
            return pStr1 == end1 ? 0 : 1;
219
27.1M
        if (pStr1 == end1)
220
53.7k
            return -1;
221
27.0M
        if (const sal_Int32 nRet = Compare::compare(*pStr1, *pStr2))
222
3.76M
            return nRet;
223
23.3M
        --shortenedLength;
224
23.3M
        ++pStr1;
225
23.3M
        ++pStr2;
226
23.3M
    }
227
8.32M
}
int rtl::str::compare<rtl::str::with_length<char16_t const>, rtl::str::null_terminated<char const>, rtl::str::CompareIgnoreAsciiCase, int>(rtl::str::with_length<char16_t const>, rtl::str::null_terminated<char const>, rtl::str::CompareIgnoreAsciiCase, int)
Line
Count
Source
206
575k
{
207
575k
    static_assert(std::is_same_v<Shorten_t, NoShortening> || std::is_same_v<Shorten_t, sal_Int32>);
208
575k
    assert(shortenedLength >= 0);
209
575k
    auto pStr1 = s1.begin();
210
575k
    const auto end1 = s1.end();
211
575k
    auto pStr2 = s2.begin();
212
575k
    const auto end2 = s2.end();
213
575k
    for (;;)
214
1.22M
    {
215
1.22M
        if (shortenedLength == 0)
216
87.0k
            return 0;
217
1.14M
        if (pStr2 == end2)
218
0
            return pStr1 == end1 ? 0 : 1;
219
1.14M
        if (pStr1 == end1)
220
20.3k
            return -1;
221
1.12M
        if (const sal_Int32 nRet = Compare::compare(*pStr1, *pStr2))
222
468k
            return nRet;
223
652k
        --shortenedLength;
224
652k
        ++pStr1;
225
652k
        ++pStr2;
226
652k
    }
227
575k
}
int rtl::str::compare<rtl::str::null_terminated<char16_t const>, rtl::str::null_terminated<char16_t const>, rtl::str::CompareNormal, rtl::str::NoShortening>(rtl::str::null_terminated<char16_t const>, rtl::str::null_terminated<char16_t const>, rtl::str::CompareNormal, rtl::str::NoShortening)
Line
Count
Source
206
5.70M
{
207
5.70M
    static_assert(std::is_same_v<Shorten_t, NoShortening> || std::is_same_v<Shorten_t, sal_Int32>);
208
5.70M
    assert(shortenedLength >= 0);
209
5.70M
    auto pStr1 = s1.begin();
210
5.70M
    const auto end1 = s1.end();
211
5.70M
    auto pStr2 = s2.begin();
212
5.70M
    const auto end2 = s2.end();
213
5.70M
    for (;;)
214
80.9M
    {
215
80.9M
        if (shortenedLength == 0)
216
0
            return 0;
217
80.9M
        if (pStr2 == end2)
218
252k
            return pStr1 == end1 ? 0 : 1;
219
80.6M
        if (pStr1 == end1)
220
21.1k
            return -1;
221
80.6M
        if (const sal_Int32 nRet = Compare::compare(*pStr1, *pStr2))
222
5.43M
            return nRet;
223
75.2M
        --shortenedLength;
224
75.2M
        ++pStr1;
225
75.2M
        ++pStr2;
226
75.2M
    }
227
5.70M
}
Unexecuted instantiation: int rtl::str::compare<rtl::str::null_terminated<char16_t const>, rtl::str::null_terminated<char16_t const>, rtl::str::CompareIgnoreAsciiCase, rtl::str::NoShortening>(rtl::str::null_terminated<char16_t const>, rtl::str::null_terminated<char16_t const>, rtl::str::CompareIgnoreAsciiCase, rtl::str::NoShortening)
int rtl::str::compare<rtl::str::with_length<char16_t const>, rtl::str::with_length<char16_t const>, rtl::str::CompareIgnoreAsciiCase, rtl::str::NoShortening>(rtl::str::with_length<char16_t const>, rtl::str::with_length<char16_t const>, rtl::str::CompareIgnoreAsciiCase, rtl::str::NoShortening)
Line
Count
Source
206
57.9M
{
207
57.9M
    static_assert(std::is_same_v<Shorten_t, NoShortening> || std::is_same_v<Shorten_t, sal_Int32>);
208
57.9M
    assert(shortenedLength >= 0);
209
57.9M
    auto pStr1 = s1.begin();
210
57.9M
    const auto end1 = s1.end();
211
57.9M
    auto pStr2 = s2.begin();
212
57.9M
    const auto end2 = s2.end();
213
57.9M
    for (;;)
214
274M
    {
215
274M
        if (shortenedLength == 0)
216
0
            return 0;
217
274M
        if (pStr2 == end2)
218
25.3M
            return pStr1 == end1 ? 0 : 1;
219
249M
        if (pStr1 == end1)
220
2.36M
            return -1;
221
247M
        if (const sal_Int32 nRet = Compare::compare(*pStr1, *pStr2))
222
30.2M
            return nRet;
223
217M
        --shortenedLength;
224
217M
        ++pStr1;
225
217M
        ++pStr2;
226
217M
    }
227
57.9M
}
228
229
// take advantage of builtin optimisations
230
template <typename C> requires (sizeof(C) == sizeof(wchar_t))
231
sal_Int32 compare(null_terminated<C> s1, null_terminated<C> s2, CompareNormal, NoShortening)
232
{
233
    return wcscmp(reinterpret_cast<wchar_t const*>(s1.p), reinterpret_cast<wchar_t const*>(s2.p));
234
}
235
template <typename C> requires (sizeof(C) == sizeof(char))
236
sal_Int32 compare(null_terminated<C> s1, null_terminated<C> s2, CompareNormal, NoShortening)
237
5.50k
{
238
5.50k
    return strcmp(reinterpret_cast<char const*>(s1.p), reinterpret_cast<char const*>(s2.p));
239
5.50k
}
240
template <typename C>
241
sal_Int32 compare(with_length<C> s1, with_length<C> s2, CompareNormal, NoShortening)
242
4.27G
{
243
4.27G
    std::basic_string_view sv1(s1.p, s1.len);
244
4.27G
    return sv1.compare(std::basic_string_view(s2.p, s2.len));
245
4.27G
}
int rtl::str::compare<char const>(rtl::str::with_length<char const>, rtl::str::with_length<char const>, rtl::str::CompareNormal, rtl::str::NoShortening)
Line
Count
Source
242
151M
{
243
151M
    std::basic_string_view sv1(s1.p, s1.len);
244
151M
    return sv1.compare(std::basic_string_view(s2.p, s2.len));
245
151M
}
int rtl::str::compare<char16_t const>(rtl::str::with_length<char16_t const>, rtl::str::with_length<char16_t const>, rtl::str::CompareNormal, rtl::str::NoShortening)
Line
Count
Source
242
4.11G
{
243
4.11G
    std::basic_string_view sv1(s1.p, s1.len);
244
4.11G
    return sv1.compare(std::basic_string_view(s2.p, s2.len));
245
4.11G
}
246
template <typename C1, typename C2, class Compare>
247
sal_Int32 compare(with_length<C1> s1, with_length<C2> s2, Compare cf, sal_Int32 nShortenedLength)
248
1.81G
{
249
1.81G
    assert(nShortenedLength >= 0);
250
1.81G
    s1.len = std::min(s1.len, nShortenedLength);
251
1.81G
    s2.len = std::min(s2.len, nShortenedLength);
252
1.81G
    return compare(s1, s2, cf, noShortening);
253
1.81G
}
int rtl::str::compare<char const, char const, rtl::str::CompareNormal>(rtl::str::with_length<char const>, rtl::str::with_length<char const>, rtl::str::CompareNormal, int)
Line
Count
Source
248
3.19M
{
249
    assert(nShortenedLength >= 0);
250
3.19M
    s1.len = std::min(s1.len, nShortenedLength);
251
3.19M
    s2.len = std::min(s2.len, nShortenedLength);
252
3.19M
    return compare(s1, s2, cf, noShortening);
253
3.19M
}
Unexecuted instantiation: int rtl::str::compare<char const, char const, rtl::str::CompareIgnoreAsciiCase>(rtl::str::with_length<char const>, rtl::str::with_length<char const>, rtl::str::CompareIgnoreAsciiCase, int)
int rtl::str::compare<char16_t const, char16_t const, rtl::str::CompareNormal>(rtl::str::with_length<char16_t const>, rtl::str::with_length<char16_t const>, rtl::str::CompareNormal, int)
Line
Count
Source
248
1.80G
{
249
    assert(nShortenedLength >= 0);
250
1.80G
    s1.len = std::min(s1.len, nShortenedLength);
251
1.80G
    s2.len = std::min(s2.len, nShortenedLength);
252
1.80G
    return compare(s1, s2, cf, noShortening);
253
1.80G
}
int rtl::str::compare<char16_t const, char16_t const, rtl::str::CompareIgnoreAsciiCase>(rtl::str::with_length<char16_t const>, rtl::str::with_length<char16_t const>, rtl::str::CompareIgnoreAsciiCase, int)
Line
Count
Source
248
8.32M
{
249
    assert(nShortenedLength >= 0);
250
8.32M
    s1.len = std::min(s1.len, nShortenedLength);
251
8.32M
    s2.len = std::min(s2.len, nShortenedLength);
252
8.32M
    return compare(s1, s2, cf, noShortening);
253
8.32M
}
254
255
/* ----------------------------------------------------------------------- */
256
257
template <typename C1, typename C2, class Compare>
258
sal_Int32 reverseCompare_WithLengths(const C1* pStr1, sal_Int32 nStr1Len,
259
                                     const C2* pStr2, sal_Int32 nStr2Len, Compare)
260
398M
{
261
398M
    assert(pStr1 || nStr1Len == 0);
262
398M
    assert(nStr1Len >= 0);
263
398M
    assert(pStr2 || nStr2Len == 0);
264
398M
    assert(nStr2Len >= 0);
265
398M
    const C1* pStr1Run = pStr1+nStr1Len;
266
398M
    const C2* pStr2Run = pStr2+nStr2Len;
267
3.49G
    while ((pStr1 < pStr1Run) && (pStr2 < pStr2Run))
268
3.31G
    {
269
3.31G
        pStr1Run--;
270
3.31G
        pStr2Run--;
271
3.31G
        if (const sal_Int32 nRet = Compare::compare(*pStr1Run, *pStr2Run))
272
218M
            return nRet;
273
3.31G
    }
274
275
180M
    return nStr1Len - nStr2Len;
276
398M
}
int rtl::str::reverseCompare_WithLengths<char, char, rtl::str::CompareNormal>(char const*, int, char const*, int, rtl::str::CompareNormal)
Line
Count
Source
260
29.0M
{
261
29.0M
    assert(pStr1 || nStr1Len == 0);
262
29.0M
    assert(nStr1Len >= 0);
263
29.0M
    assert(pStr2 || nStr2Len == 0);
264
29.0M
    assert(nStr2Len >= 0);
265
29.0M
    const C1* pStr1Run = pStr1+nStr1Len;
266
29.0M
    const C2* pStr2Run = pStr2+nStr2Len;
267
394M
    while ((pStr1 < pStr1Run) && (pStr2 < pStr2Run))
268
365M
    {
269
365M
        pStr1Run--;
270
365M
        pStr2Run--;
271
365M
        if (const sal_Int32 nRet = Compare::compare(*pStr1Run, *pStr2Run))
272
64.9k
            return nRet;
273
365M
    }
274
275
28.9M
    return nStr1Len - nStr2Len;
276
29.0M
}
int rtl::str::reverseCompare_WithLengths<char16_t, char, rtl::str::CompareNormal>(char16_t const*, int, char const*, int, rtl::str::CompareNormal)
Line
Count
Source
260
3.48k
{
261
3.48k
    assert(pStr1 || nStr1Len == 0);
262
3.48k
    assert(nStr1Len >= 0);
263
3.48k
    assert(pStr2 || nStr2Len == 0);
264
3.48k
    assert(nStr2Len >= 0);
265
3.48k
    const C1* pStr1Run = pStr1+nStr1Len;
266
3.48k
    const C2* pStr2Run = pStr2+nStr2Len;
267
4.72k
    while ((pStr1 < pStr1Run) && (pStr2 < pStr2Run))
268
4.64k
    {
269
4.64k
        pStr1Run--;
270
4.64k
        pStr2Run--;
271
4.64k
        if (const sal_Int32 nRet = Compare::compare(*pStr1Run, *pStr2Run))
272
3.41k
            return nRet;
273
4.64k
    }
274
275
75
    return nStr1Len - nStr2Len;
276
3.48k
}
int rtl::str::reverseCompare_WithLengths<char16_t, char16_t, rtl::str::CompareNormal>(char16_t const*, int, char16_t const*, int, rtl::str::CompareNormal)
Line
Count
Source
260
369M
{
261
369M
    assert(pStr1 || nStr1Len == 0);
262
369M
    assert(nStr1Len >= 0);
263
369M
    assert(pStr2 || nStr2Len == 0);
264
369M
    assert(nStr2Len >= 0);
265
369M
    const C1* pStr1Run = pStr1+nStr1Len;
266
369M
    const C2* pStr2Run = pStr2+nStr2Len;
267
3.10G
    while ((pStr1 < pStr1Run) && (pStr2 < pStr2Run))
268
2.95G
    {
269
2.95G
        pStr1Run--;
270
2.95G
        pStr2Run--;
271
2.95G
        if (const sal_Int32 nRet = Compare::compare(*pStr1Run, *pStr2Run))
272
218M
            return nRet;
273
2.95G
    }
274
275
151M
    return nStr1Len - nStr2Len;
276
369M
}
277
278
/* ----------------------------------------------------------------------- */
279
280
template <typename C> sal_Int32 hashCode_WithLength(const C* pStr, sal_Int32 nLen)
281
115M
{
282
115M
    assert(nLen >= 0);
283
115M
    sal_uInt32 h = static_cast<sal_uInt32>(nLen);
284
3.99G
    while ( nLen > 0 )
285
3.88G
    {
286
3.88G
        h = (h*37U) + UChar( *pStr );
287
3.88G
        pStr++;
288
3.88G
        nLen--;
289
3.88G
    }
290
115M
    return static_cast<sal_Int32>(h);
291
115M
}
int rtl::str::hashCode_WithLength<char>(char const*, int)
Line
Count
Source
281
644
{
282
644
    assert(nLen >= 0);
283
644
    sal_uInt32 h = static_cast<sal_uInt32>(nLen);
284
54.1k
    while ( nLen > 0 )
285
53.4k
    {
286
53.4k
        h = (h*37U) + UChar( *pStr );
287
53.4k
        pStr++;
288
53.4k
        nLen--;
289
53.4k
    }
290
644
    return static_cast<sal_Int32>(h);
291
644
}
int rtl::str::hashCode_WithLength<char16_t>(char16_t const*, int)
Line
Count
Source
281
115M
{
282
115M
    assert(nLen >= 0);
283
115M
    sal_uInt32 h = static_cast<sal_uInt32>(nLen);
284
3.99G
    while ( nLen > 0 )
285
3.88G
    {
286
3.88G
        h = (h*37U) + UChar( *pStr );
287
3.88G
        pStr++;
288
3.88G
        nLen--;
289
3.88G
    }
290
115M
    return static_cast<sal_Int32>(h);
291
115M
}
292
293
/* ----------------------------------------------------------------------- */
294
295
template <typename C> sal_Int32 hashCode(const C* pStr)
296
244k
{
297
244k
    return hashCode_WithLength( pStr, getLength( pStr ) );
298
244k
}
int rtl::str::hashCode<char>(char const*)
Line
Count
Source
296
644
{
297
644
    return hashCode_WithLength( pStr, getLength( pStr ) );
298
644
}
int rtl::str::hashCode<char16_t>(char16_t const*)
Line
Count
Source
296
243k
{
297
243k
    return hashCode_WithLength( pStr, getLength( pStr ) );
298
243k
}
299
300
/* ----------------------------------------------------------------------- */
301
302
template <typename C> sal_Int32 indexOfChar(const C* pStr, C c)
303
108
{
304
108
    assert(pStr);
305
108
    if (!c)
306
0
        return -1; // Unifies behavior of strchr/wcschr and unoptimized algorithm wrt '\0'
307
308
    if constexpr (sizeof(C) == sizeof(char))
309
0
    {
310
        // take advantage of builtin optimisations
311
0
        const C* p = strchr(pStr, c);
312
0
        return p ? p - pStr : -1;
313
    }
314
    else if constexpr (sizeof(C) == sizeof(wchar_t))
315
    {
316
        // take advantage of builtin optimisations
317
        wchar_t const * p = wcschr(reinterpret_cast<wchar_t const *>(pStr), static_cast<wchar_t>(c));
318
        return p ? p - reinterpret_cast<wchar_t const *>(pStr) : -1;
319
    }
320
    else
321
108
    {
322
108
        const C* pTempStr = pStr;
323
108
        while ( *pTempStr )
324
108
        {
325
108
            if ( *pTempStr == c )
326
108
                return pTempStr-pStr;
327
328
0
            pTempStr++;
329
0
        }
330
331
0
        return -1;
332
108
    }
333
108
}
Unexecuted instantiation: int rtl::str::indexOfChar<char>(char const*, char)
int rtl::str::indexOfChar<char16_t>(char16_t const*, char16_t)
Line
Count
Source
303
108
{
304
108
    assert(pStr);
305
108
    if (!c)
306
0
        return -1; // Unifies behavior of strchr/wcschr and unoptimized algorithm wrt '\0'
307
308
    if constexpr (sizeof(C) == sizeof(char))
309
    {
310
        // take advantage of builtin optimisations
311
        const C* p = strchr(pStr, c);
312
        return p ? p - pStr : -1;
313
    }
314
    else if constexpr (sizeof(C) == sizeof(wchar_t))
315
    {
316
        // take advantage of builtin optimisations
317
        wchar_t const * p = wcschr(reinterpret_cast<wchar_t const *>(pStr), static_cast<wchar_t>(c));
318
        return p ? p - reinterpret_cast<wchar_t const *>(pStr) : -1;
319
    }
320
    else
321
108
    {
322
108
        const C* pTempStr = pStr;
323
108
        while ( *pTempStr )
324
108
        {
325
108
            if ( *pTempStr == c )
326
108
                return pTempStr-pStr;
327
328
0
            pTempStr++;
329
0
        }
330
331
0
        return -1;
332
108
    }
333
108
}
334
335
/* ----------------------------------------------------------------------- */
336
337
template <typename C> sal_Int32 indexOfChar_WithLength(const C* pStr, sal_Int32 nLen, C c)
338
105M
{
339
//    assert(nLen >= 0);
340
105M
    if (nLen <= 0)
341
21.3M
        return -1;
342
    // take advantage of builtin optimisations
343
84.1M
    std::basic_string_view v(pStr, nLen);
344
84.1M
    auto idx = v.find(c);
345
84.1M
    return idx == v.npos ? -1 : idx;
346
105M
}
int rtl::str::indexOfChar_WithLength<char>(char const*, int, char)
Line
Count
Source
338
3.77M
{
339
//    assert(nLen >= 0);
340
3.77M
    if (nLen <= 0)
341
145
        return -1;
342
    // take advantage of builtin optimisations
343
3.77M
    std::basic_string_view v(pStr, nLen);
344
3.77M
    auto idx = v.find(c);
345
3.77M
    return idx == v.npos ? -1 : idx;
346
3.77M
}
int rtl::str::indexOfChar_WithLength<char16_t>(char16_t const*, int, char16_t)
Line
Count
Source
338
101M
{
339
//    assert(nLen >= 0);
340
101M
    if (nLen <= 0)
341
21.3M
        return -1;
342
    // take advantage of builtin optimisations
343
80.3M
    std::basic_string_view v(pStr, nLen);
344
80.3M
    auto idx = v.find(c);
345
80.3M
    return idx == v.npos ? -1 : idx;
346
101M
}
347
348
/* ----------------------------------------------------------------------- */
349
350
template <typename C> sal_Int32 lastIndexOfChar_WithLength(const C* pStr, sal_Int32 nLen, C c)
351
3.31M
{
352
3.31M
    assert(nLen >= 0);
353
    // take advantage of builtin optimisations
354
3.31M
    std::basic_string_view v(pStr, nLen);
355
3.31M
    auto idx = v.rfind(c);
356
3.31M
    return idx == v.npos ? -1 : idx;
357
3.31M
}
int rtl::str::lastIndexOfChar_WithLength<char>(char const*, int, char)
Line
Count
Source
351
328k
{
352
328k
    assert(nLen >= 0);
353
    // take advantage of builtin optimisations
354
328k
    std::basic_string_view v(pStr, nLen);
355
328k
    auto idx = v.rfind(c);
356
328k
    return idx == v.npos ? -1 : idx;
357
328k
}
int rtl::str::lastIndexOfChar_WithLength<char16_t>(char16_t const*, int, char16_t)
Line
Count
Source
351
2.99M
{
352
2.99M
    assert(nLen >= 0);
353
    // take advantage of builtin optimisations
354
2.99M
    std::basic_string_view v(pStr, nLen);
355
2.99M
    auto idx = v.rfind(c);
356
2.99M
    return idx == v.npos ? -1 : idx;
357
2.99M
}
358
359
/* ----------------------------------------------------------------------- */
360
361
template <typename C> sal_Int32 lastIndexOfChar(const C* pStr, C c)
362
0
{
363
0
    assert(pStr);
364
0
    if (!c)
365
0
        return -1; // Unifies behavior of strrchr/wcsrchr and lastIndexOfChar_WithLength wrt '\0'
366
367
    if constexpr (sizeof(C) == sizeof(char))
368
0
    {
369
        // take advantage of builtin optimisations
370
0
        const C* p = strrchr(pStr, c);
371
0
        return p ? p - pStr : -1;
372
    }
373
    else if constexpr (sizeof(C) == sizeof(wchar_t))
374
    {
375
        // take advantage of builtin optimisations
376
        wchar_t const * p = wcsrchr(reinterpret_cast<wchar_t const *>(pStr), static_cast<wchar_t>(c));
377
        return p ? p - reinterpret_cast<wchar_t const *>(pStr) : -1;
378
    }
379
    else
380
0
    {
381
0
        return lastIndexOfChar_WithLength( pStr, getLength( pStr ), c );
382
0
    }
383
0
}
Unexecuted instantiation: int rtl::str::lastIndexOfChar<char>(char const*, char)
Unexecuted instantiation: int rtl::str::lastIndexOfChar<char16_t>(char16_t const*, char16_t)
384
385
/* ----------------------------------------------------------------------- */
386
387
template <typename C>
388
sal_Int32 indexOfStr_WithLength(const C* pStr, sal_Int32 nStrLen,
389
                                const C* pSubStr, sal_Int32 nSubLen)
390
80.9M
{
391
80.9M
    assert(nStrLen >= 0);
392
80.9M
    assert(nSubLen >= 0);
393
    /* an empty SubString is always not findable */
394
80.9M
    if ( nSubLen == 0 )
395
4.94M
        return -1;
396
    // take advantage of builtin optimisations
397
76.0M
    std::basic_string_view v(pStr, nStrLen);
398
76.0M
    auto idx = nSubLen == 1 ? v.find(*pSubStr) : v.find(pSubStr, 0, nSubLen);
399
76.0M
    return idx == v.npos ? -1 : idx;
400
80.9M
}
int rtl::str::indexOfStr_WithLength<char>(char const*, int, char const*, int)
Line
Count
Source
390
2.92M
{
391
2.92M
    assert(nStrLen >= 0);
392
2.92M
    assert(nSubLen >= 0);
393
    /* an empty SubString is always not findable */
394
2.92M
    if ( nSubLen == 0 )
395
0
        return -1;
396
    // take advantage of builtin optimisations
397
2.92M
    std::basic_string_view v(pStr, nStrLen);
398
2.92M
    auto idx = nSubLen == 1 ? v.find(*pSubStr) : v.find(pSubStr, 0, nSubLen);
399
2.92M
    return idx == v.npos ? -1 : idx;
400
2.92M
}
int rtl::str::indexOfStr_WithLength<char16_t>(char16_t const*, int, char16_t const*, int)
Line
Count
Source
390
78.0M
{
391
78.0M
    assert(nStrLen >= 0);
392
78.0M
    assert(nSubLen >= 0);
393
    /* an empty SubString is always not findable */
394
78.0M
    if ( nSubLen == 0 )
395
4.94M
        return -1;
396
    // take advantage of builtin optimisations
397
73.1M
    std::basic_string_view v(pStr, nStrLen);
398
73.1M
    auto idx = nSubLen == 1 ? v.find(*pSubStr) : v.find(pSubStr, 0, nSubLen);
399
73.1M
    return idx == v.npos ? -1 : idx;
400
78.0M
}
401
402
inline sal_Int32 indexOfStr_WithLength(const sal_Unicode* pStr, sal_Int32 nStrLen,
403
                                       const char* pSubStr, sal_Int32 nSubLen)
404
28.6M
{
405
28.6M
    assert(nStrLen >= 0);
406
28.6M
    assert(nSubLen >= 0);
407
28.6M
    if (nSubLen > 0 && nSubLen <= nStrLen)
408
23.2M
    {
409
23.2M
        sal_Unicode const* end = pStr + nStrLen;
410
23.2M
        sal_Unicode const* cursor = pStr;
411
412
28.6M
        while (cursor < end)
413
28.6M
        {
414
28.6M
            cursor = std::char_traits<sal_Unicode>::find(cursor, end - cursor, *pSubStr);
415
28.6M
            if (!cursor || (end - cursor < nSubLen))
416
16.1M
            {
417
                /* no enough left to actually have a match */
418
16.1M
                break;
419
16.1M
            }
420
            /* now it is worth trying a full match */
421
12.5M
            if (nSubLen == 1 || rtl_ustr_asciil_reverseEquals_WithLength(cursor, pSubStr, nSubLen))
422
7.08M
            {
423
7.08M
                return cursor - pStr;
424
7.08M
            }
425
5.48M
            cursor += 1;
426
5.48M
        }
427
23.2M
    }
428
21.5M
    return -1;
429
28.6M
}
430
431
/* ----------------------------------------------------------------------- */
432
433
template <typename C> sal_Int32 indexOfStr(const C* pStr, const C* pSubStr)
434
0
{
435
0
    assert(pStr);
436
0
    assert(pSubStr);
437
    /* an empty SubString is always not findable */
438
0
    if (*pSubStr == 0)
439
0
        return -1;
440
    if constexpr (sizeof(C) == sizeof(char))
441
0
    {
442
        // take advantage of builtin optimisations
443
0
        const C* p = strstr(pStr, pSubStr);
444
0
        return p ? p - pStr : -1;
445
    }
446
    else if constexpr (sizeof(C) == sizeof(wchar_t))
447
    {
448
        // take advantage of builtin optimisations
449
        wchar_t const * p = wcsstr(reinterpret_cast<wchar_t const *>(pStr), reinterpret_cast<wchar_t const *>(pSubStr));
450
        return p ? p - reinterpret_cast<wchar_t const *>(pStr) : -1;
451
    }
452
    else
453
0
    {
454
0
        return indexOfStr_WithLength( pStr, getLength( pStr ),
455
0
                                                         pSubStr, getLength( pSubStr ) );
456
0
    }
457
0
}
Unexecuted instantiation: int rtl::str::indexOfStr<char>(char const*, char const*)
Unexecuted instantiation: int rtl::str::indexOfStr<char16_t>(char16_t const*, char16_t const*)
458
459
/* ----------------------------------------------------------------------- */
460
461
template <typename C>
462
sal_Int32 lastIndexOfStr_WithLength(const C* pStr, sal_Int32 nStrLen,
463
                                    const C* pSubStr, sal_Int32 nSubLen)
464
0
{
465
0
    assert(nStrLen >= 0);
466
0
    assert(nSubLen >= 0);
467
    /* an empty SubString is always not findable */
468
0
    if ( nSubLen == 0 )
469
0
        return -1;
470
    // take advantage of builtin optimisations
471
0
    std::basic_string_view v(pStr, nStrLen);
472
0
    std::basic_string_view needle(pSubStr, nSubLen);
473
0
    auto idx = v.rfind(needle);
474
0
    return idx == v.npos ? -1 : idx;
475
0
}
Unexecuted instantiation: int rtl::str::lastIndexOfStr_WithLength<char>(char const*, int, char const*, int)
Unexecuted instantiation: int rtl::str::lastIndexOfStr_WithLength<char16_t>(char16_t const*, int, char16_t const*, int)
476
477
/* ----------------------------------------------------------------------- */
478
479
template <typename C> sal_Int32 lastIndexOfStr(const C* pStr, const C* pSubStr)
480
0
{
481
0
    return lastIndexOfStr_WithLength(pStr, getLength(pStr), pSubStr, getLength(pSubStr));
482
0
}
Unexecuted instantiation: int rtl::str::lastIndexOfStr<char>(char const*, char const*)
Unexecuted instantiation: int rtl::str::lastIndexOfStr<char16_t>(char16_t const*, char16_t const*)
483
484
/* ----------------------------------------------------------------------- */
485
486
template <class S, class Replacer> void replaceChars(S str, Replacer replacer)
487
376k
{
488
376k
    for (auto& rChar : str)
489
1.11M
        rChar = replacer.Replace(rChar);
490
376k
}
Unexecuted instantiation: void rtl::str::replaceChars<rtl::str::null_terminated<char>, rtl::str::FromTo<char> >(rtl::str::null_terminated<char>, rtl::str::FromTo<char>)
Unexecuted instantiation: void rtl::str::replaceChars<rtl::str::with_length<char>, rtl::str::FromTo<char> >(rtl::str::with_length<char>, rtl::str::FromTo<char>)
Unexecuted instantiation: void rtl::str::replaceChars<rtl::str::null_terminated<char>, rtl::str::CaseReplace<rtl::isAsciiUpperCase(unsigned int), rtl::toAsciiLowerCase(unsigned int)> >(rtl::str::null_terminated<char>, rtl::str::CaseReplace<rtl::isAsciiUpperCase(unsigned int), rtl::toAsciiLowerCase(unsigned int)>)
Unexecuted instantiation: void rtl::str::replaceChars<rtl::str::with_length<char>, rtl::str::CaseReplace<rtl::isAsciiUpperCase(unsigned int), rtl::toAsciiLowerCase(unsigned int)> >(rtl::str::with_length<char>, rtl::str::CaseReplace<rtl::isAsciiUpperCase(unsigned int), rtl::toAsciiLowerCase(unsigned int)>)
Unexecuted instantiation: void rtl::str::replaceChars<rtl::str::null_terminated<char>, rtl::str::CaseReplace<rtl::isAsciiLowerCase(unsigned int), rtl::toAsciiUpperCase(unsigned int)> >(rtl::str::null_terminated<char>, rtl::str::CaseReplace<rtl::isAsciiLowerCase(unsigned int), rtl::toAsciiUpperCase(unsigned int)>)
Unexecuted instantiation: void rtl::str::replaceChars<rtl::str::with_length<char>, rtl::str::CaseReplace<rtl::isAsciiLowerCase(unsigned int), rtl::toAsciiUpperCase(unsigned int)> >(rtl::str::with_length<char>, rtl::str::CaseReplace<rtl::isAsciiLowerCase(unsigned int), rtl::toAsciiUpperCase(unsigned int)>)
Unexecuted instantiation: void rtl::str::replaceChars<rtl::str::null_terminated<char16_t>, rtl::str::FromTo<char16_t> >(rtl::str::null_terminated<char16_t>, rtl::str::FromTo<char16_t>)
Unexecuted instantiation: void rtl::str::replaceChars<rtl::str::with_length<char16_t>, rtl::str::FromTo<char16_t> >(rtl::str::with_length<char16_t>, rtl::str::FromTo<char16_t>)
Unexecuted instantiation: void rtl::str::replaceChars<rtl::str::null_terminated<char16_t>, rtl::str::CaseReplace<rtl::isAsciiUpperCase(unsigned int), rtl::toAsciiLowerCase(unsigned int)> >(rtl::str::null_terminated<char16_t>, rtl::str::CaseReplace<rtl::isAsciiUpperCase(unsigned int), rtl::toAsciiLowerCase(unsigned int)>)
Unexecuted instantiation: void rtl::str::replaceChars<rtl::str::with_length<char16_t>, rtl::str::CaseReplace<rtl::isAsciiUpperCase(unsigned int), rtl::toAsciiLowerCase(unsigned int)> >(rtl::str::with_length<char16_t>, rtl::str::CaseReplace<rtl::isAsciiUpperCase(unsigned int), rtl::toAsciiLowerCase(unsigned int)>)
Unexecuted instantiation: void rtl::str::replaceChars<rtl::str::null_terminated<char16_t>, rtl::str::CaseReplace<rtl::isAsciiLowerCase(unsigned int), rtl::toAsciiUpperCase(unsigned int)> >(rtl::str::null_terminated<char16_t>, rtl::str::CaseReplace<rtl::isAsciiLowerCase(unsigned int), rtl::toAsciiUpperCase(unsigned int)>)
void rtl::str::replaceChars<rtl::str::with_length<char16_t>, rtl::str::CaseReplace<rtl::isAsciiLowerCase(unsigned int), rtl::toAsciiUpperCase(unsigned int)> >(rtl::str::with_length<char16_t>, rtl::str::CaseReplace<rtl::isAsciiLowerCase(unsigned int), rtl::toAsciiUpperCase(unsigned int)>)
Line
Count
Source
487
376k
{
488
376k
    for (auto& rChar : str)
489
1.11M
        rChar = replacer.Replace(rChar);
490
376k
}
491
492
/* ----------------------------------------------------------------------- */
493
494
template <typename C> sal_Int32 trim_WithLength(C* pStr, sal_Int32 nLen)
495
0
{
496
0
    const auto view = o3tl::trim(std::basic_string_view(pStr, nLen));
497
498
0
    if (static_cast<sal_Int32>(view.size()) != nLen)
499
0
    {
500
0
        nLen = static_cast<sal_Int32>(view.size());
501
0
        if (view.data() != pStr)
502
0
            Copy(pStr, view.data(), nLen);
503
0
        *(pStr+nLen) = 0;
504
0
    }
505
506
0
    return nLen;
507
0
}
Unexecuted instantiation: int rtl::str::trim_WithLength<char>(char*, int)
Unexecuted instantiation: int rtl::str::trim_WithLength<char16_t>(char16_t*, int)
508
509
/* ----------------------------------------------------------------------- */
510
511
0
template <typename C> sal_Int32 trim(C* pStr) { return trim_WithLength(pStr, getLength(pStr)); }
Unexecuted instantiation: int rtl::str::trim<char>(char*)
Unexecuted instantiation: int rtl::str::trim<char16_t>(char16_t*)
512
513
/* ----------------------------------------------------------------------- */
514
515
template <typename C> sal_Int32 valueOfBoolean(C* pStr, sal_Bool b)
516
0
{
517
0
    assert(pStr);
518
0
    if ( b )
519
0
    {
520
0
        *pStr = 't';
521
0
        pStr++;
522
0
        *pStr = 'r';
523
0
        pStr++;
524
0
        *pStr = 'u';
525
0
        pStr++;
526
0
        *pStr = 'e';
527
0
        pStr++;
528
0
        *pStr = 0;
529
0
        return 4;
530
0
    }
531
0
    else
532
0
    {
533
0
        *pStr = 'f';
534
0
        pStr++;
535
0
        *pStr = 'a';
536
0
        pStr++;
537
0
        *pStr = 'l';
538
0
        pStr++;
539
0
        *pStr = 's';
540
0
        pStr++;
541
0
        *pStr = 'e';
542
0
        pStr++;
543
0
        *pStr = 0;
544
0
        return 5;
545
0
    }
546
0
}
Unexecuted instantiation: int rtl::str::valueOfBoolean<char>(char*, unsigned char)
Unexecuted instantiation: int rtl::str::valueOfBoolean<char16_t>(char16_t*, unsigned char)
547
548
/* ----------------------------------------------------------------------- */
549
550
template <typename C> sal_Int32 valueOfChar(C* pStr, C c)
551
0
{
552
0
    assert(pStr);
553
0
    *pStr++ = c;
554
0
    *pStr = 0;
555
0
    return 1;
556
0
}
Unexecuted instantiation: int rtl::str::valueOfChar<char>(char*, char)
Unexecuted instantiation: int rtl::str::valueOfChar<char16_t>(char16_t*, char16_t)
557
558
/* ----------------------------------------------------------------------- */
559
560
template <sal_Int32 maxLen, typename C, typename T>
561
sal_Int32 valueOfInt(C* pStr, T n, sal_Int16 nRadix)
562
74.2M
{
563
74.2M
    assert(pStr);
564
74.2M
    assert( nRadix >= RTL_STR_MIN_RADIX && nRadix <= RTL_STR_MAX_RADIX );
565
74.2M
    const auto* const pStart = pStr;
566
74.2M
    char    aBuf[maxLen];
567
74.2M
    char*   pBuf = aBuf;
568
74.2M
    using uT = std::make_unsigned_t<T>;
569
74.2M
    uT nValue;
570
571
    /* Radix must be valid */
572
74.2M
    if ( (nRadix < RTL_STR_MIN_RADIX) || (nRadix > RTL_STR_MAX_RADIX) )
573
0
        nRadix = 10;
574
575
    if constexpr (std::is_signed_v<T>)
576
71.6M
    {
577
        /* is value negative */
578
71.6M
        if ( n < 0 )
579
3.49M
        {
580
3.49M
            *pStr = '-';
581
3.49M
            pStr++;
582
3.49M
            nValue = n == std::numeric_limits<T>::min() ? static_cast<uT>(n) : -n;
583
3.49M
        }
584
68.1M
        else
585
68.1M
            nValue = n;
586
    }
587
    else
588
2.61M
        nValue = n;
589
590
    /* create a recursive buffer with all values, except the last one */
591
74.2M
    do
592
179M
    {
593
179M
        char nDigit = static_cast<char>(nValue % nRadix);
594
179M
        nValue /= nRadix;
595
179M
        if ( nDigit > 9 )
596
4.04M
            *pBuf = (nDigit-10) + 'a';
597
175M
        else
598
175M
            *pBuf = (nDigit + '0' );
599
179M
        pBuf++;
600
179M
    }
601
179M
    while ( nValue > 0 );
602
603
    /* copy the values in the right direction into the destination buffer */
604
74.2M
    pStr = std::reverse_copy(aBuf, pBuf, pStr);
605
74.2M
    *pStr = 0;
606
607
74.2M
    return pStr - pStart;
608
74.2M
}
int rtl::str::valueOfInt<33, char, int>(char*, int, short)
Line
Count
Source
562
8.06M
{
563
8.06M
    assert(pStr);
564
8.06M
    assert( nRadix >= RTL_STR_MIN_RADIX && nRadix <= RTL_STR_MAX_RADIX );
565
8.06M
    const auto* const pStart = pStr;
566
8.06M
    char    aBuf[maxLen];
567
8.06M
    char*   pBuf = aBuf;
568
8.06M
    using uT = std::make_unsigned_t<T>;
569
8.06M
    uT nValue;
570
571
    /* Radix must be valid */
572
8.06M
    if ( (nRadix < RTL_STR_MIN_RADIX) || (nRadix > RTL_STR_MAX_RADIX) )
573
0
        nRadix = 10;
574
575
    if constexpr (std::is_signed_v<T>)
576
8.06M
    {
577
        /* is value negative */
578
8.06M
        if ( n < 0 )
579
2.15M
        {
580
2.15M
            *pStr = '-';
581
2.15M
            pStr++;
582
2.15M
            nValue = n == std::numeric_limits<T>::min() ? static_cast<uT>(n) : -n;
583
2.15M
        }
584
5.90M
        else
585
5.90M
            nValue = n;
586
    }
587
    else
588
        nValue = n;
589
590
    /* create a recursive buffer with all values, except the last one */
591
8.06M
    do
592
11.0M
    {
593
11.0M
        char nDigit = static_cast<char>(nValue % nRadix);
594
11.0M
        nValue /= nRadix;
595
11.0M
        if ( nDigit > 9 )
596
0
            *pBuf = (nDigit-10) + 'a';
597
11.0M
        else
598
11.0M
            *pBuf = (nDigit + '0' );
599
11.0M
        pBuf++;
600
11.0M
    }
601
11.0M
    while ( nValue > 0 );
602
603
    /* copy the values in the right direction into the destination buffer */
604
8.06M
    pStr = std::reverse_copy(aBuf, pBuf, pStr);
605
8.06M
    *pStr = 0;
606
607
8.06M
    return pStr - pStart;
608
8.06M
}
int rtl::str::valueOfInt<65, char, long>(char*, long, short)
Line
Count
Source
562
78.8k
{
563
78.8k
    assert(pStr);
564
78.8k
    assert( nRadix >= RTL_STR_MIN_RADIX && nRadix <= RTL_STR_MAX_RADIX );
565
78.8k
    const auto* const pStart = pStr;
566
78.8k
    char    aBuf[maxLen];
567
78.8k
    char*   pBuf = aBuf;
568
78.8k
    using uT = std::make_unsigned_t<T>;
569
78.8k
    uT nValue;
570
571
    /* Radix must be valid */
572
78.8k
    if ( (nRadix < RTL_STR_MIN_RADIX) || (nRadix > RTL_STR_MAX_RADIX) )
573
0
        nRadix = 10;
574
575
    if constexpr (std::is_signed_v<T>)
576
78.8k
    {
577
        /* is value negative */
578
78.8k
        if ( n < 0 )
579
7.31k
        {
580
7.31k
            *pStr = '-';
581
7.31k
            pStr++;
582
7.31k
            nValue = n == std::numeric_limits<T>::min() ? static_cast<uT>(n) : -n;
583
7.31k
        }
584
71.5k
        else
585
71.5k
            nValue = n;
586
    }
587
    else
588
        nValue = n;
589
590
    /* create a recursive buffer with all values, except the last one */
591
78.8k
    do
592
238k
    {
593
238k
        char nDigit = static_cast<char>(nValue % nRadix);
594
238k
        nValue /= nRadix;
595
238k
        if ( nDigit > 9 )
596
0
            *pBuf = (nDigit-10) + 'a';
597
238k
        else
598
238k
            *pBuf = (nDigit + '0' );
599
238k
        pBuf++;
600
238k
    }
601
238k
    while ( nValue > 0 );
602
603
    /* copy the values in the right direction into the destination buffer */
604
78.8k
    pStr = std::reverse_copy(aBuf, pBuf, pStr);
605
78.8k
    *pStr = 0;
606
607
78.8k
    return pStr - pStart;
608
78.8k
}
int rtl::str::valueOfInt<65, char, unsigned long>(char*, unsigned long, short)
Line
Count
Source
562
237k
{
563
237k
    assert(pStr);
564
237k
    assert( nRadix >= RTL_STR_MIN_RADIX && nRadix <= RTL_STR_MAX_RADIX );
565
237k
    const auto* const pStart = pStr;
566
237k
    char    aBuf[maxLen];
567
237k
    char*   pBuf = aBuf;
568
237k
    using uT = std::make_unsigned_t<T>;
569
237k
    uT nValue;
570
571
    /* Radix must be valid */
572
237k
    if ( (nRadix < RTL_STR_MIN_RADIX) || (nRadix > RTL_STR_MAX_RADIX) )
573
0
        nRadix = 10;
574
575
    if constexpr (std::is_signed_v<T>)
576
    {
577
        /* is value negative */
578
        if ( n < 0 )
579
        {
580
            *pStr = '-';
581
            pStr++;
582
            nValue = n == std::numeric_limits<T>::min() ? static_cast<uT>(n) : -n;
583
        }
584
        else
585
            nValue = n;
586
    }
587
    else
588
237k
        nValue = n;
589
590
    /* create a recursive buffer with all values, except the last one */
591
237k
    do
592
1.06M
    {
593
1.06M
        char nDigit = static_cast<char>(nValue % nRadix);
594
1.06M
        nValue /= nRadix;
595
1.06M
        if ( nDigit > 9 )
596
0
            *pBuf = (nDigit-10) + 'a';
597
1.06M
        else
598
1.06M
            *pBuf = (nDigit + '0' );
599
1.06M
        pBuf++;
600
1.06M
    }
601
1.06M
    while ( nValue > 0 );
602
603
    /* copy the values in the right direction into the destination buffer */
604
237k
    pStr = std::reverse_copy(aBuf, pBuf, pStr);
605
237k
    *pStr = 0;
606
607
237k
    return pStr - pStart;
608
237k
}
int rtl::str::valueOfInt<33, char16_t, int>(char16_t*, int, short)
Line
Count
Source
562
61.6M
{
563
61.6M
    assert(pStr);
564
61.6M
    assert( nRadix >= RTL_STR_MIN_RADIX && nRadix <= RTL_STR_MAX_RADIX );
565
61.6M
    const auto* const pStart = pStr;
566
61.6M
    char    aBuf[maxLen];
567
61.6M
    char*   pBuf = aBuf;
568
61.6M
    using uT = std::make_unsigned_t<T>;
569
61.6M
    uT nValue;
570
571
    /* Radix must be valid */
572
61.6M
    if ( (nRadix < RTL_STR_MIN_RADIX) || (nRadix > RTL_STR_MAX_RADIX) )
573
0
        nRadix = 10;
574
575
    if constexpr (std::is_signed_v<T>)
576
61.6M
    {
577
        /* is value negative */
578
61.6M
        if ( n < 0 )
579
1.32M
        {
580
1.32M
            *pStr = '-';
581
1.32M
            pStr++;
582
1.32M
            nValue = n == std::numeric_limits<T>::min() ? static_cast<uT>(n) : -n;
583
1.32M
        }
584
60.2M
        else
585
60.2M
            nValue = n;
586
    }
587
    else
588
        nValue = n;
589
590
    /* create a recursive buffer with all values, except the last one */
591
61.6M
    do
592
138M
    {
593
138M
        char nDigit = static_cast<char>(nValue % nRadix);
594
138M
        nValue /= nRadix;
595
138M
        if ( nDigit > 9 )
596
481k
            *pBuf = (nDigit-10) + 'a';
597
137M
        else
598
137M
            *pBuf = (nDigit + '0' );
599
138M
        pBuf++;
600
138M
    }
601
138M
    while ( nValue > 0 );
602
603
    /* copy the values in the right direction into the destination buffer */
604
61.6M
    pStr = std::reverse_copy(aBuf, pBuf, pStr);
605
61.6M
    *pStr = 0;
606
607
61.6M
    return pStr - pStart;
608
61.6M
}
int rtl::str::valueOfInt<65, char16_t, long>(char16_t*, long, short)
Line
Count
Source
562
1.89M
{
563
1.89M
    assert(pStr);
564
1.89M
    assert( nRadix >= RTL_STR_MIN_RADIX && nRadix <= RTL_STR_MAX_RADIX );
565
1.89M
    const auto* const pStart = pStr;
566
1.89M
    char    aBuf[maxLen];
567
1.89M
    char*   pBuf = aBuf;
568
1.89M
    using uT = std::make_unsigned_t<T>;
569
1.89M
    uT nValue;
570
571
    /* Radix must be valid */
572
1.89M
    if ( (nRadix < RTL_STR_MIN_RADIX) || (nRadix > RTL_STR_MAX_RADIX) )
573
0
        nRadix = 10;
574
575
    if constexpr (std::is_signed_v<T>)
576
1.89M
    {
577
        /* is value negative */
578
1.89M
        if ( n < 0 )
579
63
        {
580
63
            *pStr = '-';
581
63
            pStr++;
582
63
            nValue = n == std::numeric_limits<T>::min() ? static_cast<uT>(n) : -n;
583
63
        }
584
1.89M
        else
585
1.89M
            nValue = n;
586
    }
587
    else
588
        nValue = n;
589
590
    /* create a recursive buffer with all values, except the last one */
591
1.89M
    do
592
16.5M
    {
593
16.5M
        char nDigit = static_cast<char>(nValue % nRadix);
594
16.5M
        nValue /= nRadix;
595
16.5M
        if ( nDigit > 9 )
596
2.19M
            *pBuf = (nDigit-10) + 'a';
597
14.3M
        else
598
14.3M
            *pBuf = (nDigit + '0' );
599
16.5M
        pBuf++;
600
16.5M
    }
601
16.5M
    while ( nValue > 0 );
602
603
    /* copy the values in the right direction into the destination buffer */
604
1.89M
    pStr = std::reverse_copy(aBuf, pBuf, pStr);
605
1.89M
    *pStr = 0;
606
607
1.89M
    return pStr - pStart;
608
1.89M
}
int rtl::str::valueOfInt<65, char16_t, unsigned long>(char16_t*, unsigned long, short)
Line
Count
Source
562
2.37M
{
563
2.37M
    assert(pStr);
564
2.37M
    assert( nRadix >= RTL_STR_MIN_RADIX && nRadix <= RTL_STR_MAX_RADIX );
565
2.37M
    const auto* const pStart = pStr;
566
2.37M
    char    aBuf[maxLen];
567
2.37M
    char*   pBuf = aBuf;
568
2.37M
    using uT = std::make_unsigned_t<T>;
569
2.37M
    uT nValue;
570
571
    /* Radix must be valid */
572
2.37M
    if ( (nRadix < RTL_STR_MIN_RADIX) || (nRadix > RTL_STR_MAX_RADIX) )
573
0
        nRadix = 10;
574
575
    if constexpr (std::is_signed_v<T>)
576
    {
577
        /* is value negative */
578
        if ( n < 0 )
579
        {
580
            *pStr = '-';
581
            pStr++;
582
            nValue = n == std::numeric_limits<T>::min() ? static_cast<uT>(n) : -n;
583
        }
584
        else
585
            nValue = n;
586
    }
587
    else
588
2.37M
        nValue = n;
589
590
    /* create a recursive buffer with all values, except the last one */
591
2.37M
    do
592
12.2M
    {
593
12.2M
        char nDigit = static_cast<char>(nValue % nRadix);
594
12.2M
        nValue /= nRadix;
595
12.2M
        if ( nDigit > 9 )
596
1.37M
            *pBuf = (nDigit-10) + 'a';
597
10.9M
        else
598
10.9M
            *pBuf = (nDigit + '0' );
599
12.2M
        pBuf++;
600
12.2M
    }
601
12.2M
    while ( nValue > 0 );
602
603
    /* copy the values in the right direction into the destination buffer */
604
2.37M
    pStr = std::reverse_copy(aBuf, pBuf, pStr);
605
2.37M
    *pStr = 0;
606
607
2.37M
    return pStr - pStart;
608
2.37M
}
609
610
/* ----------------------------------------------------------------------- */
611
612
template <typename C> sal_Bool toBoolean(const C* pStr)
613
14.1k
{
614
14.1k
    assert(pStr);
615
14.1k
    if ( *pStr == '1' )
616
228
        return true;
617
618
13.9k
    if ( (*pStr == 'T') || (*pStr == 't') )
619
6
    {
620
6
        pStr++;
621
6
        if ( (*pStr == 'R') || (*pStr == 'r') )
622
6
        {
623
6
            pStr++;
624
6
            if ( (*pStr == 'U') || (*pStr == 'u') )
625
6
            {
626
6
                pStr++;
627
6
                if ( (*pStr == 'E') || (*pStr == 'e') )
628
6
                    return true;
629
6
            }
630
6
        }
631
6
    }
632
633
13.8k
    return false;
634
13.9k
}
Unexecuted instantiation: unsigned char rtl::str::toBoolean<char>(char const*)
unsigned char rtl::str::toBoolean<char16_t>(char16_t const*)
Line
Count
Source
613
14.1k
{
614
14.1k
    assert(pStr);
615
14.1k
    if ( *pStr == '1' )
616
228
        return true;
617
618
13.9k
    if ( (*pStr == 'T') || (*pStr == 't') )
619
6
    {
620
6
        pStr++;
621
6
        if ( (*pStr == 'R') || (*pStr == 'r') )
622
6
        {
623
6
            pStr++;
624
6
            if ( (*pStr == 'U') || (*pStr == 'u') )
625
6
            {
626
6
                pStr++;
627
6
                if ( (*pStr == 'E') || (*pStr == 'e') )
628
6
                    return true;
629
6
            }
630
6
        }
631
6
    }
632
633
13.8k
    return false;
634
13.9k
}
635
636
/* ----------------------------------------------------------------------- */
637
638
template <typename T, class Iter> inline bool HandleSignChar(Iter& iter)
639
94.9M
{
640
    if constexpr (std::numeric_limits<T>::is_signed)
641
94.9M
    {
642
94.9M
        if (*iter == '-')
643
185k
        {
644
185k
            ++iter;
645
185k
            return true;
646
185k
        }
647
94.9M
    }
648
94.9M
    if (*iter == '+')
649
4.01k
        ++iter;
650
94.9M
    return false;
651
94.9M
}
bool rtl::str::HandleSignChar<int, char const*>(char const*&)
Line
Count
Source
639
511
{
640
    if constexpr (std::numeric_limits<T>::is_signed)
641
511
    {
642
511
        if (*iter == '-')
643
0
        {
644
0
            ++iter;
645
0
            return true;
646
0
        }
647
511
    }
648
511
    if (*iter == '+')
649
0
        ++iter;
650
511
    return false;
651
511
}
bool rtl::str::HandleSignChar<long, char const*>(char const*&)
Line
Count
Source
639
9.46M
{
640
    if constexpr (std::numeric_limits<T>::is_signed)
641
9.46M
    {
642
9.46M
        if (*iter == '-')
643
50.4k
        {
644
50.4k
            ++iter;
645
50.4k
            return true;
646
50.4k
        }
647
9.46M
    }
648
9.46M
    if (*iter == '+')
649
20
        ++iter;
650
9.46M
    return false;
651
9.46M
}
Unexecuted instantiation: bool rtl::str::HandleSignChar<unsigned int, char const*>(char const*&)
Unexecuted instantiation: bool rtl::str::HandleSignChar<unsigned long, char const*>(char const*&)
bool rtl::str::HandleSignChar<int, char16_t const*>(char16_t const*&)
Line
Count
Source
639
7.34M
{
640
    if constexpr (std::numeric_limits<T>::is_signed)
641
7.34M
    {
642
7.34M
        if (*iter == '-')
643
4.69k
        {
644
4.69k
            ++iter;
645
4.69k
            return true;
646
4.69k
        }
647
7.34M
    }
648
7.34M
    if (*iter == '+')
649
1.03k
        ++iter;
650
7.34M
    return false;
651
7.34M
}
bool rtl::str::HandleSignChar<long, char16_t const*>(char16_t const*&)
Line
Count
Source
639
78.1M
{
640
    if constexpr (std::numeric_limits<T>::is_signed)
641
78.1M
    {
642
78.1M
        if (*iter == '-')
643
130k
        {
644
130k
            ++iter;
645
130k
            return true;
646
130k
        }
647
78.1M
    }
648
78.1M
    if (*iter == '+')
649
2.95k
        ++iter;
650
78.1M
    return false;
651
78.1M
}
bool rtl::str::HandleSignChar<unsigned int, char16_t const*>(char16_t const*&)
Line
Count
Source
639
28.0k
{
640
    if constexpr (std::numeric_limits<T>::is_signed)
641
    {
642
        if (*iter == '-')
643
        {
644
            ++iter;
645
            return true;
646
        }
647
    }
648
28.0k
    if (*iter == '+')
649
0
        ++iter;
650
28.0k
    return false;
651
28.0k
}
Unexecuted instantiation: bool rtl::str::HandleSignChar<unsigned long, char16_t const*>(char16_t const*&)
652
653
template <typename T> std::pair<T, sal_Int16> DivMod(sal_Int16 nRadix, [[maybe_unused]] bool bNeg)
654
94.9M
{
655
    if constexpr (std::numeric_limits<T>::is_signed)
656
94.9M
        if (bNeg)
657
185k
            return { -(std::numeric_limits<T>::min() / nRadix),
658
185k
                     -(std::numeric_limits<T>::min() % nRadix) };
659
94.7M
    return { std::numeric_limits<T>::max() / nRadix, std::numeric_limits<T>::max() % nRadix };
660
94.9M
}
std::__1::pair<int, short> rtl::str::DivMod<int>(short, bool)
Line
Count
Source
654
7.34M
{
655
    if constexpr (std::numeric_limits<T>::is_signed)
656
7.34M
        if (bNeg)
657
4.69k
            return { -(std::numeric_limits<T>::min() / nRadix),
658
4.69k
                     -(std::numeric_limits<T>::min() % nRadix) };
659
7.33M
    return { std::numeric_limits<T>::max() / nRadix, std::numeric_limits<T>::max() % nRadix };
660
7.34M
}
std::__1::pair<long, short> rtl::str::DivMod<long>(short, bool)
Line
Count
Source
654
87.5M
{
655
    if constexpr (std::numeric_limits<T>::is_signed)
656
87.5M
        if (bNeg)
657
180k
            return { -(std::numeric_limits<T>::min() / nRadix),
658
180k
                     -(std::numeric_limits<T>::min() % nRadix) };
659
87.3M
    return { std::numeric_limits<T>::max() / nRadix, std::numeric_limits<T>::max() % nRadix };
660
87.5M
}
std::__1::pair<unsigned int, short> rtl::str::DivMod<unsigned int>(short, bool)
Line
Count
Source
654
28.0k
{
655
    if constexpr (std::numeric_limits<T>::is_signed)
656
        if (bNeg)
657
            return { -(std::numeric_limits<T>::min() / nRadix),
658
                     -(std::numeric_limits<T>::min() % nRadix) };
659
28.0k
    return { std::numeric_limits<T>::max() / nRadix, std::numeric_limits<T>::max() % nRadix };
660
28.0k
}
Unexecuted instantiation: std::__1::pair<unsigned long, short> rtl::str::DivMod<unsigned long>(short, bool)
661
662
template <typename T, class S> T toInt(S str, sal_Int16 nRadix)
663
95.1M
{
664
95.1M
    assert( nRadix >= RTL_STR_MIN_RADIX && nRadix <= RTL_STR_MAX_RADIX );
665
666
95.1M
    if ( (nRadix < RTL_STR_MIN_RADIX) || (nRadix > RTL_STR_MAX_RADIX) )
667
0
        nRadix = 10;
668
669
95.1M
    auto pStr = str.begin();
670
95.1M
    const auto end = str.end();
671
672
    /* Skip whitespaces */
673
95.2M
    while (pStr != end && o3tl::internal::implIsWhitespace(UChar(*pStr)))
674
123k
        pStr++;
675
95.1M
    if (pStr == end)
676
221k
        return 0;
677
678
94.9M
    const bool bNeg = HandleSignChar<T>(pStr);
679
94.9M
    const auto& [nDiv, nMod] = DivMod<T>(nRadix, bNeg);
680
94.9M
    assert(nDiv > 0);
681
682
94.9M
    std::make_unsigned_t<T> n = 0;
683
342M
    while (pStr != end)
684
251M
    {
685
251M
        sal_Int16 nDigit = implGetDigit(UChar(*pStr), nRadix);
686
251M
        if ( nDigit < 0 )
687
4.10M
            break;
688
247M
        if (static_cast<std::make_unsigned_t<T>>(nMod < nDigit ? nDiv - 1 : nDiv) < n)
689
189k
            return 0;
690
691
247M
        n *= nRadix;
692
247M
        n += nDigit;
693
694
247M
        pStr++;
695
247M
    }
696
697
    if constexpr (std::numeric_limits<T>::is_signed)
698
94.7M
        if (bNeg)
699
184k
            return n == static_cast<std::make_unsigned_t<T>>(std::numeric_limits<T>::min())
700
184k
                       ? std::numeric_limits<T>::min()
701
184k
                       : -static_cast<T>(n);
702
94.5M
    return static_cast<T>(n);
703
94.9M
}
int rtl::str::toInt<int, rtl::str::null_terminated<char const> >(rtl::str::null_terminated<char const>, short)
Line
Count
Source
663
511
{
664
511
    assert( nRadix >= RTL_STR_MIN_RADIX && nRadix <= RTL_STR_MAX_RADIX );
665
666
511
    if ( (nRadix < RTL_STR_MIN_RADIX) || (nRadix > RTL_STR_MAX_RADIX) )
667
0
        nRadix = 10;
668
669
511
    auto pStr = str.begin();
670
511
    const auto end = str.end();
671
672
    /* Skip whitespaces */
673
511
    while (pStr != end && o3tl::internal::implIsWhitespace(UChar(*pStr)))
674
0
        pStr++;
675
511
    if (pStr == end)
676
0
        return 0;
677
678
511
    const bool bNeg = HandleSignChar<T>(pStr);
679
511
    const auto& [nDiv, nMod] = DivMod<T>(nRadix, bNeg);
680
511
    assert(nDiv > 0);
681
682
511
    std::make_unsigned_t<T> n = 0;
683
1.65k
    while (pStr != end)
684
1.14k
    {
685
1.14k
        sal_Int16 nDigit = implGetDigit(UChar(*pStr), nRadix);
686
1.14k
        if ( nDigit < 0 )
687
0
            break;
688
1.14k
        if (static_cast<std::make_unsigned_t<T>>(nMod < nDigit ? nDiv - 1 : nDiv) < n)
689
0
            return 0;
690
691
1.14k
        n *= nRadix;
692
1.14k
        n += nDigit;
693
694
1.14k
        pStr++;
695
1.14k
    }
696
697
    if constexpr (std::numeric_limits<T>::is_signed)
698
511
        if (bNeg)
699
0
            return n == static_cast<std::make_unsigned_t<T>>(std::numeric_limits<T>::min())
700
0
                       ? std::numeric_limits<T>::min()
701
0
                       : -static_cast<T>(n);
702
511
    return static_cast<T>(n);
703
511
}
Unexecuted instantiation: long rtl::str::toInt<long, rtl::str::null_terminated<char const> >(rtl::str::null_terminated<char const>, short)
long rtl::str::toInt<long, rtl::str::with_length<char const> >(rtl::str::with_length<char const>, short)
Line
Count
Source
663
9.46M
{
664
9.46M
    assert( nRadix >= RTL_STR_MIN_RADIX && nRadix <= RTL_STR_MAX_RADIX );
665
666
9.46M
    if ( (nRadix < RTL_STR_MIN_RADIX) || (nRadix > RTL_STR_MAX_RADIX) )
667
0
        nRadix = 10;
668
669
9.46M
    auto pStr = str.begin();
670
9.46M
    const auto end = str.end();
671
672
    /* Skip whitespaces */
673
9.46M
    while (pStr != end && o3tl::internal::implIsWhitespace(UChar(*pStr)))
674
498
        pStr++;
675
9.46M
    if (pStr == end)
676
800
        return 0;
677
678
9.46M
    const bool bNeg = HandleSignChar<T>(pStr);
679
9.46M
    const auto& [nDiv, nMod] = DivMod<T>(nRadix, bNeg);
680
9.46M
    assert(nDiv > 0);
681
682
9.46M
    std::make_unsigned_t<T> n = 0;
683
30.9M
    while (pStr != end)
684
21.4M
    {
685
21.4M
        sal_Int16 nDigit = implGetDigit(UChar(*pStr), nRadix);
686
21.4M
        if ( nDigit < 0 )
687
6.39k
            break;
688
21.4M
        if (static_cast<std::make_unsigned_t<T>>(nMod < nDigit ? nDiv - 1 : nDiv) < n)
689
3.73k
            return 0;
690
691
21.4M
        n *= nRadix;
692
21.4M
        n += nDigit;
693
694
21.4M
        pStr++;
695
21.4M
    }
696
697
    if constexpr (std::numeric_limits<T>::is_signed)
698
9.45M
        if (bNeg)
699
50.3k
            return n == static_cast<std::make_unsigned_t<T>>(std::numeric_limits<T>::min())
700
50.3k
                       ? std::numeric_limits<T>::min()
701
50.3k
                       : -static_cast<T>(n);
702
9.40M
    return static_cast<T>(n);
703
9.46M
}
Unexecuted instantiation: unsigned int rtl::str::toInt<unsigned int, rtl::str::null_terminated<char const> >(rtl::str::null_terminated<char const>, short)
Unexecuted instantiation: unsigned long rtl::str::toInt<unsigned long, rtl::str::null_terminated<char const> >(rtl::str::null_terminated<char const>, short)
int rtl::str::toInt<int, rtl::str::null_terminated<char16_t const> >(rtl::str::null_terminated<char16_t const>, short)
Line
Count
Source
663
7.47M
{
664
7.47M
    assert( nRadix >= RTL_STR_MIN_RADIX && nRadix <= RTL_STR_MAX_RADIX );
665
666
7.47M
    if ( (nRadix < RTL_STR_MIN_RADIX) || (nRadix > RTL_STR_MAX_RADIX) )
667
0
        nRadix = 10;
668
669
7.47M
    auto pStr = str.begin();
670
7.47M
    const auto end = str.end();
671
672
    /* Skip whitespaces */
673
7.49M
    while (pStr != end && o3tl::internal::implIsWhitespace(UChar(*pStr)))
674
13.2k
        pStr++;
675
7.47M
    if (pStr == end)
676
135k
        return 0;
677
678
7.34M
    const bool bNeg = HandleSignChar<T>(pStr);
679
7.34M
    const auto& [nDiv, nMod] = DivMod<T>(nRadix, bNeg);
680
7.34M
    assert(nDiv > 0);
681
682
7.34M
    std::make_unsigned_t<T> n = 0;
683
20.7M
    while (pStr != end)
684
14.2M
    {
685
14.2M
        sal_Int16 nDigit = implGetDigit(UChar(*pStr), nRadix);
686
14.2M
        if ( nDigit < 0 )
687
754k
            break;
688
13.5M
        if (static_cast<std::make_unsigned_t<T>>(nMod < nDigit ? nDiv - 1 : nDiv) < n)
689
161k
            return 0;
690
691
13.3M
        n *= nRadix;
692
13.3M
        n += nDigit;
693
694
13.3M
        pStr++;
695
13.3M
    }
696
697
    if constexpr (std::numeric_limits<T>::is_signed)
698
7.18M
        if (bNeg)
699
4.59k
            return n == static_cast<std::make_unsigned_t<T>>(std::numeric_limits<T>::min())
700
4.59k
                       ? std::numeric_limits<T>::min()
701
4.59k
                       : -static_cast<T>(n);
702
7.17M
    return static_cast<T>(n);
703
7.34M
}
long rtl::str::toInt<long, rtl::str::null_terminated<char16_t const> >(rtl::str::null_terminated<char16_t const>, short)
Line
Count
Source
663
11.7k
{
664
11.7k
    assert( nRadix >= RTL_STR_MIN_RADIX && nRadix <= RTL_STR_MAX_RADIX );
665
666
11.7k
    if ( (nRadix < RTL_STR_MIN_RADIX) || (nRadix > RTL_STR_MAX_RADIX) )
667
0
        nRadix = 10;
668
669
11.7k
    auto pStr = str.begin();
670
11.7k
    const auto end = str.end();
671
672
    /* Skip whitespaces */
673
11.7k
    while (pStr != end && o3tl::internal::implIsWhitespace(UChar(*pStr)))
674
0
        pStr++;
675
11.7k
    if (pStr == end)
676
0
        return 0;
677
678
11.7k
    const bool bNeg = HandleSignChar<T>(pStr);
679
11.7k
    const auto& [nDiv, nMod] = DivMod<T>(nRadix, bNeg);
680
11.7k
    assert(nDiv > 0);
681
682
11.7k
    std::make_unsigned_t<T> n = 0;
683
57.6k
    while (pStr != end)
684
45.9k
    {
685
45.9k
        sal_Int16 nDigit = implGetDigit(UChar(*pStr), nRadix);
686
45.9k
        if ( nDigit < 0 )
687
57
            break;
688
45.9k
        if (static_cast<std::make_unsigned_t<T>>(nMod < nDigit ? nDiv - 1 : nDiv) < n)
689
18
            return 0;
690
691
45.9k
        n *= nRadix;
692
45.9k
        n += nDigit;
693
694
45.9k
        pStr++;
695
45.9k
    }
696
697
    if constexpr (std::numeric_limits<T>::is_signed)
698
11.7k
        if (bNeg)
699
11
            return n == static_cast<std::make_unsigned_t<T>>(std::numeric_limits<T>::min())
700
11
                       ? std::numeric_limits<T>::min()
701
11
                       : -static_cast<T>(n);
702
11.7k
    return static_cast<T>(n);
703
11.7k
}
long rtl::str::toInt<long, rtl::str::with_length<char16_t const> >(rtl::str::with_length<char16_t const>, short)
Line
Count
Source
663
78.1M
{
664
78.1M
    assert( nRadix >= RTL_STR_MIN_RADIX && nRadix <= RTL_STR_MAX_RADIX );
665
666
78.1M
    if ( (nRadix < RTL_STR_MIN_RADIX) || (nRadix > RTL_STR_MAX_RADIX) )
667
0
        nRadix = 10;
668
669
78.1M
    auto pStr = str.begin();
670
78.1M
    const auto end = str.end();
671
672
    /* Skip whitespaces */
673
78.2M
    while (pStr != end && o3tl::internal::implIsWhitespace(UChar(*pStr)))
674
110k
        pStr++;
675
78.1M
    if (pStr == end)
676
84.6k
        return 0;
677
678
78.0M
    const bool bNeg = HandleSignChar<T>(pStr);
679
78.0M
    const auto& [nDiv, nMod] = DivMod<T>(nRadix, bNeg);
680
78.0M
    assert(nDiv > 0);
681
682
78.0M
    std::make_unsigned_t<T> n = 0;
683
290M
    while (pStr != end)
684
215M
    {
685
215M
        sal_Int16 nDigit = implGetDigit(UChar(*pStr), nRadix);
686
215M
        if ( nDigit < 0 )
687
3.34M
            break;
688
212M
        if (static_cast<std::make_unsigned_t<T>>(nMod < nDigit ? nDiv - 1 : nDiv) < n)
689
23.7k
            return 0;
690
691
212M
        n *= nRadix;
692
212M
        n += nDigit;
693
694
212M
        pStr++;
695
212M
    }
696
697
    if constexpr (std::numeric_limits<T>::is_signed)
698
78.0M
        if (bNeg)
699
129k
            return n == static_cast<std::make_unsigned_t<T>>(std::numeric_limits<T>::min())
700
129k
                       ? std::numeric_limits<T>::min()
701
129k
                       : -static_cast<T>(n);
702
77.9M
    return static_cast<T>(n);
703
78.0M
}
unsigned int rtl::str::toInt<unsigned int, rtl::str::null_terminated<char16_t const> >(rtl::str::null_terminated<char16_t const>, short)
Line
Count
Source
663
28.2k
{
664
28.2k
    assert( nRadix >= RTL_STR_MIN_RADIX && nRadix <= RTL_STR_MAX_RADIX );
665
666
28.2k
    if ( (nRadix < RTL_STR_MIN_RADIX) || (nRadix > RTL_STR_MAX_RADIX) )
667
0
        nRadix = 10;
668
669
28.2k
    auto pStr = str.begin();
670
28.2k
    const auto end = str.end();
671
672
    /* Skip whitespaces */
673
28.2k
    while (pStr != end && o3tl::internal::implIsWhitespace(UChar(*pStr)))
674
0
        pStr++;
675
28.2k
    if (pStr == end)
676
130
        return 0;
677
678
28.0k
    const bool bNeg = HandleSignChar<T>(pStr);
679
28.0k
    const auto& [nDiv, nMod] = DivMod<T>(nRadix, bNeg);
680
28.0k
    assert(nDiv > 0);
681
682
28.0k
    std::make_unsigned_t<T> n = 0;
683
85.2k
    while (pStr != end)
684
57.2k
    {
685
57.2k
        sal_Int16 nDigit = implGetDigit(UChar(*pStr), nRadix);
686
57.2k
        if ( nDigit < 0 )
687
0
            break;
688
57.2k
        if (static_cast<std::make_unsigned_t<T>>(nMod < nDigit ? nDiv - 1 : nDiv) < n)
689
60
            return 0;
690
691
57.1k
        n *= nRadix;
692
57.1k
        n += nDigit;
693
694
57.1k
        pStr++;
695
57.1k
    }
696
697
    if constexpr (std::numeric_limits<T>::is_signed)
698
        if (bNeg)
699
            return n == static_cast<std::make_unsigned_t<T>>(std::numeric_limits<T>::min())
700
                       ? std::numeric_limits<T>::min()
701
                       : -static_cast<T>(n);
702
28.0k
    return static_cast<T>(n);
703
28.0k
}
Unexecuted instantiation: unsigned long rtl::str::toInt<unsigned long, rtl::str::null_terminated<char16_t const> >(rtl::str::null_terminated<char16_t const>, short)
704
705
/* ======================================================================= */
706
/* Internal String-Class help functions                                    */
707
/* ======================================================================= */
708
709
template <class rtl_tString> using Char_T = std::remove_extent_t<decltype(rtl_tString::buffer)>;
710
711
template <typename rtl_tString> rtl_tString* Alloc(sal_Int32 nLen)
712
1.44G
{
713
1.44G
    constexpr auto fix = offsetof(rtl_tString, buffer) + sizeof rtl_tString::buffer;
714
1.44G
    rtl_tString * pData
715
1.44G
        = (o3tl::make_unsigned(nLen)
716
1.44G
           <= ((std::numeric_limits<std::size_t>::max() - fix)
717
1.44G
               / sizeof (Char_T<rtl_tString>)))
718
1.44G
        ? static_cast<rtl_tString *>(rtl_allocateString(
719
1.44G
            fix + nLen * sizeof (Char_T<rtl_tString>)))
720
1.44G
        : nullptr;
721
1.44G
    if (pData != nullptr) {
722
1.44G
        pData->refCount = 1;
723
1.44G
        pData->length = nLen;
724
1.44G
        pData->buffer[nLen] = 0;
725
1.44G
    }
726
1.44G
    return pData;
727
1.44G
}
_rtl_String* rtl::str::Alloc<_rtl_String>(int)
Line
Count
Source
712
121M
{
713
121M
    constexpr auto fix = offsetof(rtl_tString, buffer) + sizeof rtl_tString::buffer;
714
121M
    rtl_tString * pData
715
121M
        = (o3tl::make_unsigned(nLen)
716
121M
           <= ((std::numeric_limits<std::size_t>::max() - fix)
717
121M
               / sizeof (Char_T<rtl_tString>)))
718
121M
        ? static_cast<rtl_tString *>(rtl_allocateString(
719
121M
            fix + nLen * sizeof (Char_T<rtl_tString>)))
720
121M
        : nullptr;
721
121M
    if (pData != nullptr) {
722
121M
        pData->refCount = 1;
723
121M
        pData->length = nLen;
724
121M
        pData->buffer[nLen] = 0;
725
121M
    }
726
121M
    return pData;
727
121M
}
_rtl_uString* rtl::str::Alloc<_rtl_uString>(int)
Line
Count
Source
712
1.32G
{
713
1.32G
    constexpr auto fix = offsetof(rtl_tString, buffer) + sizeof rtl_tString::buffer;
714
1.32G
    rtl_tString * pData
715
1.32G
        = (o3tl::make_unsigned(nLen)
716
1.32G
           <= ((std::numeric_limits<std::size_t>::max() - fix)
717
1.32G
               / sizeof (Char_T<rtl_tString>)))
718
1.32G
        ? static_cast<rtl_tString *>(rtl_allocateString(
719
1.32G
            fix + nLen * sizeof (Char_T<rtl_tString>)))
720
1.32G
        : nullptr;
721
1.32G
    if (pData != nullptr) {
722
1.32G
        pData->refCount = 1;
723
1.32G
        pData->length = nLen;
724
1.32G
        pData->buffer[nLen] = 0;
725
1.32G
    }
726
1.32G
    return pData;
727
1.32G
}
728
729
/* ======================================================================= */
730
/* String-Class functions                                                  */
731
/* ======================================================================= */
732
733
template <typename rtl_tString> void acquire(rtl_tString* pThis)
734
7.10G
{
735
7.10G
    if (!SAL_STRING_IS_STATIC (pThis))
736
3.03G
        osl_atomic_increment( &((pThis)->refCount) );
737
7.10G
}
void rtl::str::acquire<_rtl_String>(_rtl_String*)
Line
Count
Source
734
24.2M
{
735
24.2M
    if (!SAL_STRING_IS_STATIC (pThis))
736
23.0M
        osl_atomic_increment( &((pThis)->refCount) );
737
24.2M
}
void rtl::str::acquire<_rtl_uString>(_rtl_uString*)
Line
Count
Source
734
7.07G
{
735
7.07G
    if (!SAL_STRING_IS_STATIC (pThis))
736
3.01G
        osl_atomic_increment( &((pThis)->refCount) );
737
7.07G
}
738
739
/* ----------------------------------------------------------------------- */
740
741
template <typename rtl_tString> void release(rtl_tString* pThis)
742
15.4G
{
743
15.4G
    if (SAL_UNLIKELY(SAL_STRING_IS_STATIC (pThis)))
744
10.9G
        return;
745
746
    /* OString doesn't have an 'intern' */
747
    if constexpr (sizeof(Char_T<rtl_tString>) == sizeof(sal_Unicode))
748
4.33G
    {
749
4.33G
        if (SAL_STRING_IS_INTERN (pThis))
750
0
        {
751
0
            internRelease (pThis);
752
0
            return;
753
0
        }
754
4.33G
    }
755
756
4.47G
    if ( !osl_atomic_decrement( &(pThis->refCount) ) )
757
1.44G
    {
758
1.44G
        RTL_LOG_STRING_DELETE( pThis );
759
1.44G
        rtl_freeString( pThis );
760
1.44G
    }
761
4.47G
}
void rtl::str::release<_rtl_String>(_rtl_String*)
Line
Count
Source
742
270M
{
743
270M
    if (SAL_UNLIKELY(SAL_STRING_IS_STATIC (pThis)))
744
126M
        return;
745
746
    /* OString doesn't have an 'intern' */
747
    if constexpr (sizeof(Char_T<rtl_tString>) == sizeof(sal_Unicode))
748
    {
749
        if (SAL_STRING_IS_INTERN (pThis))
750
        {
751
            internRelease (pThis);
752
            return;
753
        }
754
    }
755
756
144M
    if ( !osl_atomic_decrement( &(pThis->refCount) ) )
757
121M
    {
758
121M
        RTL_LOG_STRING_DELETE( pThis );
759
121M
        rtl_freeString( pThis );
760
121M
    }
761
144M
}
void rtl::str::release<_rtl_uString>(_rtl_uString*)
Line
Count
Source
742
15.1G
{
743
15.1G
    if (SAL_UNLIKELY(SAL_STRING_IS_STATIC (pThis)))
744
10.8G
        return;
745
746
    /* OString doesn't have an 'intern' */
747
    if constexpr (sizeof(Char_T<rtl_tString>) == sizeof(sal_Unicode))
748
4.33G
    {
749
4.33G
        if (SAL_STRING_IS_INTERN (pThis))
750
0
        {
751
0
            internRelease (pThis);
752
0
            return;
753
0
        }
754
4.33G
    }
755
756
4.33G
    if ( !osl_atomic_decrement( &(pThis->refCount) ) )
757
1.32G
    {
758
1.32G
        RTL_LOG_STRING_DELETE( pThis );
759
1.32G
        rtl_freeString( pThis );
760
1.32G
    }
761
4.33G
}
762
763
/* ----------------------------------------------------------------------- */
764
765
/* static data to be referenced by all empty strings
766
 * the refCount is predefined to 1 and must never become 0 !
767
 */
768
template <typename rtl_tString> struct EmptyStringImpl
769
{
770
    static rtl_tString data;
771
};
772
773
template <>
774
inline rtl_uString EmptyStringImpl<rtl_uString>::data = {
775
    sal_Int32(SAL_STRING_INTERN_FLAG | SAL_STRING_STATIC_FLAG | 1), /* sal_Int32   refCount;  */
776
    0,                                                              /* sal_Int32   length;    */
777
    { 0 }                                                           /* sal_Unicode buffer[1]; */
778
};
779
780
template <>
781
inline rtl_String EmptyStringImpl<rtl_String>::data = {
782
    SAL_STRING_STATIC_FLAG | 1, /* sal_Int32 refCount;  */
783
    0,                          /* sal_Int32 length;    */
784
    { 0 }                       /* char      buffer[1]; */
785
};
786
787
template <typename rtl_tString> void new_(rtl_tString** ppThis)
788
2.43G
{
789
2.43G
    assert(ppThis);
790
2.43G
    if ( *ppThis)
791
176M
        release( *ppThis );
792
793
2.43G
    *ppThis = &EmptyStringImpl<rtl_tString>::data;
794
2.43G
}
void rtl::str::new_<_rtl_String>(_rtl_String**)
Line
Count
Source
788
38.8M
{
789
38.8M
    assert(ppThis);
790
38.8M
    if ( *ppThis)
791
16.2M
        release( *ppThis );
792
793
38.8M
    *ppThis = &EmptyStringImpl<rtl_tString>::data;
794
38.8M
}
void rtl::str::new_<_rtl_uString>(_rtl_uString**)
Line
Count
Source
788
2.39G
{
789
2.39G
    assert(ppThis);
790
2.39G
    if ( *ppThis)
791
160M
        release( *ppThis );
792
793
2.39G
    *ppThis = &EmptyStringImpl<rtl_tString>::data;
794
2.39G
}
795
796
/* ----------------------------------------------------------------------- */
797
798
template <typename rtl_tString> void new_WithLength(rtl_tString** ppThis, sal_Int32 nLen)
799
367M
{
800
367M
    assert(ppThis);
801
367M
    assert(nLen >= 0);
802
367M
    if ( nLen <= 0 )
803
12.5M
        new_( ppThis );
804
354M
    else
805
354M
    {
806
354M
        if ( *ppThis)
807
2.09M
            release( *ppThis );
808
809
354M
        *ppThis = Alloc<rtl_tString>( nLen );
810
354M
        assert(*ppThis != nullptr);
811
354M
        (*ppThis)->length   = 0;
812
354M
        (*ppThis)->buffer[0] = 0;
813
354M
    }
814
367M
}
void rtl::str::new_WithLength<_rtl_String>(_rtl_String**, int)
Line
Count
Source
799
18.7M
{
800
18.7M
    assert(ppThis);
801
18.7M
    assert(nLen >= 0);
802
18.7M
    if ( nLen <= 0 )
803
0
        new_( ppThis );
804
18.7M
    else
805
18.7M
    {
806
18.7M
        if ( *ppThis)
807
0
            release( *ppThis );
808
809
18.7M
        *ppThis = Alloc<rtl_tString>( nLen );
810
        assert(*ppThis != nullptr);
811
18.7M
        (*ppThis)->length   = 0;
812
18.7M
        (*ppThis)->buffer[0] = 0;
813
18.7M
    }
814
18.7M
}
void rtl::str::new_WithLength<_rtl_uString>(_rtl_uString**, int)
Line
Count
Source
799
348M
{
800
348M
    assert(ppThis);
801
348M
    assert(nLen >= 0);
802
348M
    if ( nLen <= 0 )
803
12.5M
        new_( ppThis );
804
335M
    else
805
335M
    {
806
335M
        if ( *ppThis)
807
2.09M
            release( *ppThis );
808
809
335M
        *ppThis = Alloc<rtl_tString>( nLen );
810
        assert(*ppThis != nullptr);
811
335M
        (*ppThis)->length   = 0;
812
335M
        (*ppThis)->buffer[0] = 0;
813
335M
    }
814
348M
}
815
816
/* ----------------------------------------------------------------------- */
817
818
template <typename rtl_tString, typename C>
819
void newFromStr_WithLength(rtl_tString** ppThis, const C* pCharStr, sal_Int32 nLen,
820
                           sal_Int32 allocExtra = 0)
821
425M
{
822
425M
    assert(ppThis);
823
425M
    assert(nLen >= 0);
824
425M
    assert(pCharStr || nLen == 0);
825
425M
    assert(allocExtra >= 0);
826
827
425M
    if (nLen + allocExtra == 0)
828
6.94M
        return new_(ppThis);
829
830
418M
    rtl_tString* pOrg = *ppThis;
831
418M
    *ppThis = Alloc<rtl_tString>(nLen + allocExtra);
832
418M
    assert(*ppThis != nullptr);
833
418M
    if (nLen > 0)
834
414M
        Copy((*ppThis)->buffer, pCharStr, nLen);
835
418M
    if (allocExtra > 0)
836
36.6M
    {
837
36.6M
        (*ppThis)->length = nLen;
838
36.6M
        (*ppThis)->buffer[nLen] = 0;
839
36.6M
    }
840
841
418M
    RTL_LOG_STRING_NEW(*ppThis);
842
843
    /* must be done last, if pCharStr belongs to *ppThis */
844
418M
    if (pOrg)
845
75.7M
        release(pOrg);
846
418M
}
void rtl::str::newFromStr_WithLength<_rtl_String, char>(_rtl_String**, char const*, int, int)
Line
Count
Source
821
14.3M
{
822
14.3M
    assert(ppThis);
823
14.3M
    assert(nLen >= 0);
824
14.3M
    assert(pCharStr || nLen == 0);
825
14.3M
    assert(allocExtra >= 0);
826
827
14.3M
    if (nLen + allocExtra == 0)
828
162k
        return new_(ppThis);
829
830
14.2M
    rtl_tString* pOrg = *ppThis;
831
14.2M
    *ppThis = Alloc<rtl_tString>(nLen + allocExtra);
832
14.2M
    assert(*ppThis != nullptr);
833
14.2M
    if (nLen > 0)
834
14.1M
        Copy((*ppThis)->buffer, pCharStr, nLen);
835
14.2M
    if (allocExtra > 0)
836
606k
    {
837
606k
        (*ppThis)->length = nLen;
838
606k
        (*ppThis)->buffer[nLen] = 0;
839
606k
    }
840
841
14.2M
    RTL_LOG_STRING_NEW(*ppThis);
842
843
    /* must be done last, if pCharStr belongs to *ppThis */
844
14.2M
    if (pOrg)
845
606k
        release(pOrg);
846
14.2M
}
void rtl::str::newFromStr_WithLength<_rtl_uString, char>(_rtl_uString**, char const*, int, int)
Line
Count
Source
821
58.8M
{
822
58.8M
    assert(ppThis);
823
58.8M
    assert(nLen >= 0);
824
58.8M
    assert(pCharStr || nLen == 0);
825
58.8M
    assert(allocExtra >= 0);
826
827
58.8M
    if (nLen + allocExtra == 0)
828
100
        return new_(ppThis);
829
830
58.8M
    rtl_tString* pOrg = *ppThis;
831
58.8M
    *ppThis = Alloc<rtl_tString>(nLen + allocExtra);
832
58.8M
    assert(*ppThis != nullptr);
833
58.8M
    if (nLen > 0)
834
58.8M
        Copy((*ppThis)->buffer, pCharStr, nLen);
835
58.8M
    if (allocExtra > 0)
836
427k
    {
837
427k
        (*ppThis)->length = nLen;
838
427k
        (*ppThis)->buffer[nLen] = 0;
839
427k
    }
840
841
58.8M
    RTL_LOG_STRING_NEW(*ppThis);
842
843
    /* must be done last, if pCharStr belongs to *ppThis */
844
58.8M
    if (pOrg)
845
32.9M
        release(pOrg);
846
58.8M
}
void rtl::str::newFromStr_WithLength<_rtl_uString, char16_t>(_rtl_uString**, char16_t const*, int, int)
Line
Count
Source
821
351M
{
822
351M
    assert(ppThis);
823
351M
    assert(nLen >= 0);
824
351M
    assert(pCharStr || nLen == 0);
825
351M
    assert(allocExtra >= 0);
826
827
351M
    if (nLen + allocExtra == 0)
828
6.77M
        return new_(ppThis);
829
830
345M
    rtl_tString* pOrg = *ppThis;
831
345M
    *ppThis = Alloc<rtl_tString>(nLen + allocExtra);
832
345M
    assert(*ppThis != nullptr);
833
345M
    if (nLen > 0)
834
341M
        Copy((*ppThis)->buffer, pCharStr, nLen);
835
345M
    if (allocExtra > 0)
836
35.6M
    {
837
35.6M
        (*ppThis)->length = nLen;
838
35.6M
        (*ppThis)->buffer[nLen] = 0;
839
35.6M
    }
840
841
345M
    RTL_LOG_STRING_NEW(*ppThis);
842
843
    /* must be done last, if pCharStr belongs to *ppThis */
844
345M
    if (pOrg)
845
42.1M
        release(pOrg);
846
345M
}
847
848
template <typename rtl_tString> void newFromString(rtl_tString** ppThis, const rtl_tString* pStr)
849
294
{
850
294
    assert(pStr);
851
852
294
    newFromStr_WithLength(ppThis, pStr->buffer, pStr->length);
853
294
}
Unexecuted instantiation: void rtl::str::newFromString<_rtl_String>(_rtl_String**, _rtl_String const*)
void rtl::str::newFromString<_rtl_uString>(_rtl_uString**, _rtl_uString const*)
Line
Count
Source
849
294
{
850
294
    assert(pStr);
851
852
294
    newFromStr_WithLength(ppThis, pStr->buffer, pStr->length);
853
294
}
854
855
/* ----------------------------------------------------------------------- */
856
857
template <typename rtl_tString>
858
void newFromStr(rtl_tString** ppThis, const Char_T<rtl_tString>* pCharStr)
859
22.2M
{
860
22.2M
    newFromStr_WithLength(ppThis, pCharStr, getLength(pCharStr));
861
22.2M
}
_ZN3rtl3str10newFromStrI11_rtl_StringEEvPPT_PKu15__remove_extentIDtsrS3_6bufferEE
Line
Count
Source
859
9.34M
{
860
9.34M
    newFromStr_WithLength(ppThis, pCharStr, getLength(pCharStr));
861
9.34M
}
_ZN3rtl3str10newFromStrI12_rtl_uStringEEvPPT_PKu15__remove_extentIDtsrS3_6bufferEE
Line
Count
Source
859
12.9M
{
860
12.9M
    newFromStr_WithLength(ppThis, pCharStr, getLength(pCharStr));
861
12.9M
}
862
863
/* ----------------------------------------------------------------------- */
864
865
template <typename rtl_tString> void assign(rtl_tString** ppThis, rtl_tString* pStr)
866
2.24G
{
867
2.24G
    assert(ppThis);
868
    /* must be done at first, if pStr == *ppThis */
869
2.24G
    acquire( pStr );
870
871
2.24G
    if ( *ppThis )
872
2.01G
        release( *ppThis );
873
874
2.24G
    *ppThis = pStr;
875
2.24G
}
void rtl::str::assign<_rtl_String>(_rtl_String**, _rtl_String*)
Line
Count
Source
866
2.45M
{
867
2.45M
    assert(ppThis);
868
    /* must be done at first, if pStr == *ppThis */
869
2.45M
    acquire( pStr );
870
871
2.45M
    if ( *ppThis )
872
1.46M
        release( *ppThis );
873
874
2.45M
    *ppThis = pStr;
875
2.45M
}
void rtl::str::assign<_rtl_uString>(_rtl_uString**, _rtl_uString*)
Line
Count
Source
866
2.23G
{
867
2.23G
    assert(ppThis);
868
    /* must be done at first, if pStr == *ppThis */
869
2.23G
    acquire( pStr );
870
871
2.23G
    if ( *ppThis )
872
2.01G
        release( *ppThis );
873
874
2.23G
    *ppThis = pStr;
875
2.23G
}
876
877
/* ----------------------------------------------------------------------- */
878
879
template <typename rtl_tString>
880
void newFromSubString(rtl_tString** ppThis, const rtl_tString* pFrom, sal_Int32 beginIndex,
881
                      sal_Int32 count)
882
56.9M
{
883
56.9M
    assert(ppThis);
884
56.9M
    if ( beginIndex == 0 && count == pFrom->length )
885
31.4M
        return assign(ppThis, const_cast<rtl_tString*>(pFrom));
886
25.4M
    if ( count < 0 || beginIndex < 0 || beginIndex + count > pFrom->length )
887
13
    {
888
13
        assert(false); // fail fast at least in debug builds
889
13
        return newFromStr_WithLength(ppThis, "!!br0ken!!", 10);
890
13
    }
891
892
25.4M
    newFromStr_WithLength( ppThis, pFrom->buffer + beginIndex, count );
893
25.4M
}
void rtl::str::newFromSubString<_rtl_String>(_rtl_String**, _rtl_String const*, int, int)
Line
Count
Source
882
1.72M
{
883
1.72M
    assert(ppThis);
884
1.72M
    if ( beginIndex == 0 && count == pFrom->length )
885
988k
        return assign(ppThis, const_cast<rtl_tString*>(pFrom));
886
733k
    if ( count < 0 || beginIndex < 0 || beginIndex + count > pFrom->length )
887
0
    {
888
0
        assert(false); // fail fast at least in debug builds
889
0
        return newFromStr_WithLength(ppThis, "!!br0ken!!", 10);
890
0
    }
891
892
733k
    newFromStr_WithLength( ppThis, pFrom->buffer + beginIndex, count );
893
733k
}
void rtl::str::newFromSubString<_rtl_uString>(_rtl_uString**, _rtl_uString const*, int, int)
Line
Count
Source
882
55.1M
{
883
55.1M
    assert(ppThis);
884
55.1M
    if ( beginIndex == 0 && count == pFrom->length )
885
30.4M
        return assign(ppThis, const_cast<rtl_tString*>(pFrom));
886
24.7M
    if ( count < 0 || beginIndex < 0 || beginIndex + count > pFrom->length )
887
13
    {
888
13
        assert(false); // fail fast at least in debug builds
889
13
        return newFromStr_WithLength(ppThis, "!!br0ken!!", 10);
890
13
    }
891
892
24.7M
    newFromStr_WithLength( ppThis, pFrom->buffer + beginIndex, count );
893
24.7M
}
894
895
/* ----------------------------------------------------------------------- */
896
897
template <typename rtl_tString> auto* getStr(rtl_tString* pThis)
898
121k
{
899
121k
    assert(pThis);
900
121k
    return pThis->buffer;
901
121k
}
auto* rtl::str::getStr<_rtl_String>(_rtl_String*)
Line
Count
Source
898
60.6k
{
899
    assert(pThis);
900
60.6k
    return pThis->buffer;
901
60.6k
}
auto* rtl::str::getStr<_rtl_uString>(_rtl_uString*)
Line
Count
Source
898
60.7k
{
899
    assert(pThis);
900
60.7k
    return pThis->buffer;
901
60.7k
}
902
903
/* ----------------------------------------------------------------------- */
904
905
enum ThrowPolicy { NoThrow, Throw };
906
907
template <ThrowPolicy throwPolicy, typename rtl_tString, typename C1, typename C2>
908
void newConcat(rtl_tString** ppThis, const C1* pLeft, sal_Int32 nLeftLength,
909
               const C2* pRight, sal_Int32 nRightLength)
910
255M
{
911
255M
    assert(ppThis);
912
255M
    assert(nLeftLength >= 0);
913
255M
    assert(pLeft || nLeftLength == 0);
914
255M
    assert(nRightLength >= 0);
915
255M
    assert(pRight || nRightLength == 0);
916
255M
    rtl_tString* pOrg = *ppThis;
917
918
255M
    if (nLeftLength > std::numeric_limits<sal_Int32>::max() - nRightLength)
919
0
    {
920
        if constexpr (throwPolicy == NoThrow)
921
0
            *ppThis = nullptr;
922
        else
923
0
        {
924
0
#if !defined(__COVERITY__) || __COVERITY_MAJOR__ > 2024
925
0
            throw std::length_error("newConcat");
926
#else
927
            //coverity doesn't report std::bad_alloc as an unhandled exception when
928
            //potentially thrown from destructors but does report std::length_error
929
            throw std::bad_alloc();
930
#endif
931
0
        }
932
0
    }
933
255M
    else
934
255M
    {
935
255M
        auto* pTempStr = Alloc<rtl_tString>(nLeftLength + nRightLength);
936
255M
        OSL_ASSERT(pTempStr != nullptr);
937
255M
        *ppThis = pTempStr;
938
255M
        if (*ppThis != nullptr) {
939
255M
            if (nLeftLength)
940
252M
                Copy( pTempStr->buffer, pLeft, nLeftLength );
941
255M
            if (nRightLength)
942
255M
                Copy( pTempStr->buffer+nLeftLength, pRight, nRightLength );
943
944
255M
            RTL_LOG_STRING_NEW( *ppThis );
945
255M
        }
946
255M
    }
947
948
    /* must be done last, if left or right == *ppThis */
949
255M
    if ( pOrg )
950
22.8M
        release( pOrg );
951
255M
}
Unexecuted instantiation: void rtl::str::newConcat<(rtl::str::ThrowPolicy)1, _rtl_String, char, char>(_rtl_String**, char const*, int, char const*, int)
void rtl::str::newConcat<(rtl::str::ThrowPolicy)0, _rtl_String, char, char>(_rtl_String**, char const*, int, char const*, int)
Line
Count
Source
910
100k
{
911
100k
    assert(ppThis);
912
100k
    assert(nLeftLength >= 0);
913
100k
    assert(pLeft || nLeftLength == 0);
914
100k
    assert(nRightLength >= 0);
915
100k
    assert(pRight || nRightLength == 0);
916
100k
    rtl_tString* pOrg = *ppThis;
917
918
100k
    if (nLeftLength > std::numeric_limits<sal_Int32>::max() - nRightLength)
919
0
    {
920
        if constexpr (throwPolicy == NoThrow)
921
0
            *ppThis = nullptr;
922
        else
923
        {
924
#if !defined(__COVERITY__) || __COVERITY_MAJOR__ > 2024
925
            throw std::length_error("newConcat");
926
#else
927
            //coverity doesn't report std::bad_alloc as an unhandled exception when
928
            //potentially thrown from destructors but does report std::length_error
929
            throw std::bad_alloc();
930
#endif
931
        }
932
0
    }
933
100k
    else
934
100k
    {
935
100k
        auto* pTempStr = Alloc<rtl_tString>(nLeftLength + nRightLength);
936
100k
        OSL_ASSERT(pTempStr != nullptr);
937
100k
        *ppThis = pTempStr;
938
100k
        if (*ppThis != nullptr) {
939
100k
            if (nLeftLength)
940
100k
                Copy( pTempStr->buffer, pLeft, nLeftLength );
941
100k
            if (nRightLength)
942
100k
                Copy( pTempStr->buffer+nLeftLength, pRight, nRightLength );
943
944
100k
            RTL_LOG_STRING_NEW( *ppThis );
945
100k
        }
946
100k
    }
947
948
    /* must be done last, if left or right == *ppThis */
949
100k
    if ( pOrg )
950
100k
        release( pOrg );
951
100k
}
void rtl::str::newConcat<(rtl::str::ThrowPolicy)1, _rtl_uString, char16_t, char>(_rtl_uString**, char16_t const*, int, char const*, int)
Line
Count
Source
910
3.41M
{
911
3.41M
    assert(ppThis);
912
3.41M
    assert(nLeftLength >= 0);
913
3.41M
    assert(pLeft || nLeftLength == 0);
914
3.41M
    assert(nRightLength >= 0);
915
3.41M
    assert(pRight || nRightLength == 0);
916
3.41M
    rtl_tString* pOrg = *ppThis;
917
918
3.41M
    if (nLeftLength > std::numeric_limits<sal_Int32>::max() - nRightLength)
919
0
    {
920
        if constexpr (throwPolicy == NoThrow)
921
            *ppThis = nullptr;
922
        else
923
0
        {
924
0
#if !defined(__COVERITY__) || __COVERITY_MAJOR__ > 2024
925
0
            throw std::length_error("newConcat");
926
#else
927
            //coverity doesn't report std::bad_alloc as an unhandled exception when
928
            //potentially thrown from destructors but does report std::length_error
929
            throw std::bad_alloc();
930
#endif
931
0
        }
932
0
    }
933
3.41M
    else
934
3.41M
    {
935
3.41M
        auto* pTempStr = Alloc<rtl_tString>(nLeftLength + nRightLength);
936
3.41M
        OSL_ASSERT(pTempStr != nullptr);
937
3.41M
        *ppThis = pTempStr;
938
3.41M
        if (*ppThis != nullptr) {
939
3.41M
            if (nLeftLength)
940
2.32M
                Copy( pTempStr->buffer, pLeft, nLeftLength );
941
3.41M
            if (nRightLength)
942
3.41M
                Copy( pTempStr->buffer+nLeftLength, pRight, nRightLength );
943
944
3.41M
            RTL_LOG_STRING_NEW( *ppThis );
945
3.41M
        }
946
3.41M
    }
947
948
    /* must be done last, if left or right == *ppThis */
949
3.41M
    if ( pOrg )
950
3.41M
        release( pOrg );
951
3.41M
}
void rtl::str::newConcat<(rtl::str::ThrowPolicy)1, _rtl_uString, char16_t, char16_t>(_rtl_uString**, char16_t const*, int, char16_t const*, int)
Line
Count
Source
910
18.2M
{
911
18.2M
    assert(ppThis);
912
18.2M
    assert(nLeftLength >= 0);
913
18.2M
    assert(pLeft || nLeftLength == 0);
914
18.2M
    assert(nRightLength >= 0);
915
18.2M
    assert(pRight || nRightLength == 0);
916
18.2M
    rtl_tString* pOrg = *ppThis;
917
918
18.2M
    if (nLeftLength > std::numeric_limits<sal_Int32>::max() - nRightLength)
919
0
    {
920
        if constexpr (throwPolicy == NoThrow)
921
            *ppThis = nullptr;
922
        else
923
0
        {
924
0
#if !defined(__COVERITY__) || __COVERITY_MAJOR__ > 2024
925
0
            throw std::length_error("newConcat");
926
#else
927
            //coverity doesn't report std::bad_alloc as an unhandled exception when
928
            //potentially thrown from destructors but does report std::length_error
929
            throw std::bad_alloc();
930
#endif
931
0
        }
932
0
    }
933
18.2M
    else
934
18.2M
    {
935
18.2M
        auto* pTempStr = Alloc<rtl_tString>(nLeftLength + nRightLength);
936
18.2M
        OSL_ASSERT(pTempStr != nullptr);
937
18.2M
        *ppThis = pTempStr;
938
18.2M
        if (*ppThis != nullptr) {
939
18.2M
            if (nLeftLength)
940
15.6M
                Copy( pTempStr->buffer, pLeft, nLeftLength );
941
18.2M
            if (nRightLength)
942
18.2M
                Copy( pTempStr->buffer+nLeftLength, pRight, nRightLength );
943
944
18.2M
            RTL_LOG_STRING_NEW( *ppThis );
945
18.2M
        }
946
18.2M
    }
947
948
    /* must be done last, if left or right == *ppThis */
949
18.2M
    if ( pOrg )
950
18.2M
        release( pOrg );
951
18.2M
}
void rtl::str::newConcat<(rtl::str::ThrowPolicy)0, _rtl_uString, char16_t, char16_t>(_rtl_uString**, char16_t const*, int, char16_t const*, int)
Line
Count
Source
910
234M
{
911
234M
    assert(ppThis);
912
234M
    assert(nLeftLength >= 0);
913
234M
    assert(pLeft || nLeftLength == 0);
914
234M
    assert(nRightLength >= 0);
915
234M
    assert(pRight || nRightLength == 0);
916
234M
    rtl_tString* pOrg = *ppThis;
917
918
234M
    if (nLeftLength > std::numeric_limits<sal_Int32>::max() - nRightLength)
919
0
    {
920
        if constexpr (throwPolicy == NoThrow)
921
0
            *ppThis = nullptr;
922
        else
923
        {
924
#if !defined(__COVERITY__) || __COVERITY_MAJOR__ > 2024
925
            throw std::length_error("newConcat");
926
#else
927
            //coverity doesn't report std::bad_alloc as an unhandled exception when
928
            //potentially thrown from destructors but does report std::length_error
929
            throw std::bad_alloc();
930
#endif
931
        }
932
0
    }
933
234M
    else
934
234M
    {
935
234M
        auto* pTempStr = Alloc<rtl_tString>(nLeftLength + nRightLength);
936
234M
        OSL_ASSERT(pTempStr != nullptr);
937
234M
        *ppThis = pTempStr;
938
234M
        if (*ppThis != nullptr) {
939
234M
            if (nLeftLength)
940
234M
                Copy( pTempStr->buffer, pLeft, nLeftLength );
941
234M
            if (nRightLength)
942
234M
                Copy( pTempStr->buffer+nLeftLength, pRight, nRightLength );
943
944
234M
            RTL_LOG_STRING_NEW( *ppThis );
945
234M
        }
946
234M
    }
947
948
    /* must be done last, if left or right == *ppThis */
949
234M
    if ( pOrg )
950
996k
        release( pOrg );
951
234M
}
952
953
template <typename rtl_tString, typename C>
954
void newConcat(rtl_tString** ppThis, rtl_tString* pLeft, const C* pRight, sal_Int32 nRightLength)
955
22.3M
{
956
22.3M
    assert(pLeft != nullptr);
957
22.3M
    if (nRightLength == 0)
958
631k
        assign(ppThis, pLeft);
959
21.7M
    else
960
21.7M
        newConcat<Throw>(ppThis, pLeft->buffer, pLeft->length, pRight, nRightLength);
961
22.3M
}
Unexecuted instantiation: void rtl::str::newConcat<_rtl_String, char>(_rtl_String**, _rtl_String*, char const*, int)
void rtl::str::newConcat<_rtl_uString, char>(_rtl_uString**, _rtl_uString*, char const*, int)
Line
Count
Source
955
3.41M
{
956
3.41M
    assert(pLeft != nullptr);
957
3.41M
    if (nRightLength == 0)
958
0
        assign(ppThis, pLeft);
959
3.41M
    else
960
3.41M
        newConcat<Throw>(ppThis, pLeft->buffer, pLeft->length, pRight, nRightLength);
961
3.41M
}
void rtl::str::newConcat<_rtl_uString, char16_t>(_rtl_uString**, _rtl_uString*, char16_t const*, int)
Line
Count
Source
955
18.9M
{
956
18.9M
    assert(pLeft != nullptr);
957
18.9M
    if (nRightLength == 0)
958
631k
        assign(ppThis, pLeft);
959
18.2M
    else
960
18.2M
        newConcat<Throw>(ppThis, pLeft->buffer, pLeft->length, pRight, nRightLength);
961
18.9M
}
962
963
template <typename rtl_tString>
964
void newConcat(rtl_tString** ppThis, rtl_tString* pLeft, rtl_tString* pRight)
965
375M
{
966
    /* Test for 0-Pointer - if not, change newReplaceStrAt! */
967
375M
    if ( !pRight || !pRight->length )
968
72.4M
    {
969
72.4M
        assert(pLeft != nullptr);
970
72.4M
        assign(ppThis, pLeft);
971
72.4M
    }
972
303M
    else if ( !pLeft || !pLeft->length )
973
69.1M
        assign(ppThis, pRight);
974
234M
    else
975
234M
        newConcat<NoThrow>(ppThis, pLeft->buffer, pLeft->length, pRight->buffer, pRight->length);
976
375M
}
void rtl::str::newConcat<_rtl_String>(_rtl_String**, _rtl_String*, _rtl_String*)
Line
Count
Source
965
169k
{
966
    /* Test for 0-Pointer - if not, change newReplaceStrAt! */
967
169k
    if ( !pRight || !pRight->length )
968
18.6k
    {
969
18.6k
        assert(pLeft != nullptr);
970
18.6k
        assign(ppThis, pLeft);
971
18.6k
    }
972
151k
    else if ( !pLeft || !pLeft->length )
973
51.1k
        assign(ppThis, pRight);
974
100k
    else
975
100k
        newConcat<NoThrow>(ppThis, pLeft->buffer, pLeft->length, pRight->buffer, pRight->length);
976
169k
}
void rtl::str::newConcat<_rtl_uString>(_rtl_uString**, _rtl_uString*, _rtl_uString*)
Line
Count
Source
965
375M
{
966
    /* Test for 0-Pointer - if not, change newReplaceStrAt! */
967
375M
    if ( !pRight || !pRight->length )
968
72.4M
    {
969
72.4M
        assert(pLeft != nullptr);
970
72.4M
        assign(ppThis, pLeft);
971
72.4M
    }
972
303M
    else if ( !pLeft || !pLeft->length )
973
69.1M
        assign(ppThis, pRight);
974
234M
    else
975
234M
        newConcat<NoThrow>(ppThis, pLeft->buffer, pLeft->length, pRight->buffer, pRight->length);
976
375M
}
977
978
/* ----------------------------------------------------------------------- */
979
980
template <typename rtl_tString> void ensureCapacity(rtl_tString** ppThis, sal_Int32 size)
981
10.9M
{
982
10.9M
    assert(ppThis);
983
10.9M
    rtl_tString* const pOrg = *ppThis;
984
10.9M
    if ( pOrg->refCount == 1 && pOrg->length >= size )
985
0
        return;
986
10.9M
    assert( pOrg->length <= size ); // do not truncate
987
10.9M
    auto* pTempStr = Alloc<rtl_tString>( size );
988
10.9M
    Copy( pTempStr->buffer, pOrg->buffer, pOrg->length );
989
    // right now the length is still the same as of the original
990
10.9M
    pTempStr->length = pOrg->length;
991
10.9M
    pTempStr->buffer[ pOrg->length ] = '\0';
992
10.9M
    *ppThis = pTempStr;
993
10.9M
    RTL_LOG_STRING_NEW( *ppThis );
994
995
10.9M
    release( pOrg );
996
10.9M
}
void rtl::str::ensureCapacity<_rtl_String>(_rtl_String**, int)
Line
Count
Source
981
3.22M
{
982
3.22M
    assert(ppThis);
983
3.22M
    rtl_tString* const pOrg = *ppThis;
984
3.22M
    if ( pOrg->refCount == 1 && pOrg->length >= size )
985
0
        return;
986
3.22M
    assert( pOrg->length <= size ); // do not truncate
987
3.22M
    auto* pTempStr = Alloc<rtl_tString>( size );
988
3.22M
    Copy( pTempStr->buffer, pOrg->buffer, pOrg->length );
989
    // right now the length is still the same as of the original
990
3.22M
    pTempStr->length = pOrg->length;
991
3.22M
    pTempStr->buffer[ pOrg->length ] = '\0';
992
3.22M
    *ppThis = pTempStr;
993
3.22M
    RTL_LOG_STRING_NEW( *ppThis );
994
995
3.22M
    release( pOrg );
996
3.22M
}
void rtl::str::ensureCapacity<_rtl_uString>(_rtl_uString**, int)
Line
Count
Source
981
7.72M
{
982
7.72M
    assert(ppThis);
983
7.72M
    rtl_tString* const pOrg = *ppThis;
984
7.72M
    if ( pOrg->refCount == 1 && pOrg->length >= size )
985
0
        return;
986
7.72M
    assert( pOrg->length <= size ); // do not truncate
987
7.72M
    auto* pTempStr = Alloc<rtl_tString>( size );
988
7.72M
    Copy( pTempStr->buffer, pOrg->buffer, pOrg->length );
989
    // right now the length is still the same as of the original
990
7.72M
    pTempStr->length = pOrg->length;
991
7.72M
    pTempStr->buffer[ pOrg->length ] = '\0';
992
7.72M
    *ppThis = pTempStr;
993
7.72M
    RTL_LOG_STRING_NEW( *ppThis );
994
995
7.72M
    release( pOrg );
996
7.72M
}
997
998
/* ----------------------------------------------------------------------- */
999
1000
template <typename rtl_tString, typename C>
1001
void newReplaceStrAt(rtl_tString** ppThis, rtl_tString* pStr, sal_Int32 nIndex, sal_Int32 nCount,
1002
                     const C* pNewSubStr, sal_Int32 nNewSubStrLen)
1003
8.67M
{
1004
8.67M
    assert(ppThis);
1005
8.67M
    assert(nIndex >= 0 && nIndex <= pStr->length);
1006
8.67M
    assert(nCount >= 0);
1007
8.67M
    assert(nCount <= pStr->length - nIndex);
1008
8.67M
    assert(pNewSubStr != nullptr || nNewSubStrLen == 0);
1009
8.67M
    assert(nNewSubStrLen >= 0);
1010
    /* Append? */
1011
8.67M
    if ( nIndex >= pStr->length )
1012
44.5k
        return newConcat(ppThis, pStr, pNewSubStr, nNewSubStrLen);
1013
1014
    /* not more than the String length could be deleted */
1015
8.63M
    if ( nCount >= pStr->length-nIndex )
1016
4.52M
    {
1017
        /* Assign of NewSubStr? */
1018
4.52M
        if (nIndex == 0)
1019
1.56M
            return newFromStr_WithLength( ppThis, pNewSubStr, nNewSubStrLen );
1020
1021
2.95M
        nCount = pStr->length - nIndex;
1022
2.95M
    }
1023
1024
    /* Assign of Str? */
1025
7.06M
    if ( !nCount && !nNewSubStrLen )
1026
3.23k
        return assign(ppThis, pStr);
1027
1028
7.06M
    rtl_tString*    pOrg = *ppThis;
1029
1030
    /* Alloc New Buffer */
1031
7.06M
    *ppThis = Alloc<rtl_tString>(pStr->length - nCount + nNewSubStrLen);
1032
7.06M
    assert(*ppThis != nullptr);
1033
7.06M
    auto* pBuffer = (*ppThis)->buffer;
1034
7.06M
    if ( nIndex )
1035
6.17M
    {
1036
6.17M
        Copy( pBuffer, pStr->buffer, nIndex );
1037
6.17M
        pBuffer += nIndex;
1038
6.17M
    }
1039
7.06M
    if ( nNewSubStrLen )
1040
6.51M
    {
1041
6.51M
        Copy( pBuffer, pNewSubStr, nNewSubStrLen );
1042
6.51M
        pBuffer += nNewSubStrLen;
1043
6.51M
    }
1044
7.06M
    Copy( pBuffer, pStr->buffer+nIndex+nCount, pStr->length-nIndex-nCount );
1045
1046
7.06M
    RTL_LOG_STRING_NEW( *ppThis );
1047
    /* must be done last, if pStr or pNewSubStr == *ppThis */
1048
7.06M
    if ( pOrg )
1049
0
        release( pOrg );
1050
7.06M
}
void rtl::str::newReplaceStrAt<_rtl_String, char>(_rtl_String**, _rtl_String*, int, int, char const*, int)
Line
Count
Source
1003
5.45k
{
1004
5.45k
    assert(ppThis);
1005
5.45k
    assert(nIndex >= 0 && nIndex <= pStr->length);
1006
5.45k
    assert(nCount >= 0);
1007
5.45k
    assert(nCount <= pStr->length - nIndex);
1008
5.45k
    assert(pNewSubStr != nullptr || nNewSubStrLen == 0);
1009
5.45k
    assert(nNewSubStrLen >= 0);
1010
    /* Append? */
1011
5.45k
    if ( nIndex >= pStr->length )
1012
0
        return newConcat(ppThis, pStr, pNewSubStr, nNewSubStrLen);
1013
1014
    /* not more than the String length could be deleted */
1015
5.45k
    if ( nCount >= pStr->length-nIndex )
1016
0
    {
1017
        /* Assign of NewSubStr? */
1018
0
        if (nIndex == 0)
1019
0
            return newFromStr_WithLength( ppThis, pNewSubStr, nNewSubStrLen );
1020
1021
0
        nCount = pStr->length - nIndex;
1022
0
    }
1023
1024
    /* Assign of Str? */
1025
5.45k
    if ( !nCount && !nNewSubStrLen )
1026
0
        return assign(ppThis, pStr);
1027
1028
5.45k
    rtl_tString*    pOrg = *ppThis;
1029
1030
    /* Alloc New Buffer */
1031
5.45k
    *ppThis = Alloc<rtl_tString>(pStr->length - nCount + nNewSubStrLen);
1032
5.45k
    assert(*ppThis != nullptr);
1033
5.45k
    auto* pBuffer = (*ppThis)->buffer;
1034
5.45k
    if ( nIndex )
1035
5.45k
    {
1036
5.45k
        Copy( pBuffer, pStr->buffer, nIndex );
1037
5.45k
        pBuffer += nIndex;
1038
5.45k
    }
1039
5.45k
    if ( nNewSubStrLen )
1040
5.45k
    {
1041
5.45k
        Copy( pBuffer, pNewSubStr, nNewSubStrLen );
1042
5.45k
        pBuffer += nNewSubStrLen;
1043
5.45k
    }
1044
5.45k
    Copy( pBuffer, pStr->buffer+nIndex+nCount, pStr->length-nIndex-nCount );
1045
1046
5.45k
    RTL_LOG_STRING_NEW( *ppThis );
1047
    /* must be done last, if pStr or pNewSubStr == *ppThis */
1048
5.45k
    if ( pOrg )
1049
0
        release( pOrg );
1050
5.45k
}
void rtl::str::newReplaceStrAt<_rtl_uString, char>(_rtl_uString**, _rtl_uString*, int, int, char const*, int)
Line
Count
Source
1003
1.37k
{
1004
1.37k
    assert(ppThis);
1005
1.37k
    assert(nIndex >= 0 && nIndex <= pStr->length);
1006
1.37k
    assert(nCount >= 0);
1007
1.37k
    assert(nCount <= pStr->length - nIndex);
1008
1.37k
    assert(pNewSubStr != nullptr || nNewSubStrLen == 0);
1009
1.37k
    assert(nNewSubStrLen >= 0);
1010
    /* Append? */
1011
1.37k
    if ( nIndex >= pStr->length )
1012
0
        return newConcat(ppThis, pStr, pNewSubStr, nNewSubStrLen);
1013
1014
    /* not more than the String length could be deleted */
1015
1.37k
    if ( nCount >= pStr->length-nIndex )
1016
479
    {
1017
        /* Assign of NewSubStr? */
1018
479
        if (nIndex == 0)
1019
0
            return newFromStr_WithLength( ppThis, pNewSubStr, nNewSubStrLen );
1020
1021
479
        nCount = pStr->length - nIndex;
1022
479
    }
1023
1024
    /* Assign of Str? */
1025
1.37k
    if ( !nCount && !nNewSubStrLen )
1026
0
        return assign(ppThis, pStr);
1027
1028
1.37k
    rtl_tString*    pOrg = *ppThis;
1029
1030
    /* Alloc New Buffer */
1031
1.37k
    *ppThis = Alloc<rtl_tString>(pStr->length - nCount + nNewSubStrLen);
1032
1.37k
    assert(*ppThis != nullptr);
1033
1.37k
    auto* pBuffer = (*ppThis)->buffer;
1034
1.37k
    if ( nIndex )
1035
1.37k
    {
1036
1.37k
        Copy( pBuffer, pStr->buffer, nIndex );
1037
1.37k
        pBuffer += nIndex;
1038
1.37k
    }
1039
1.37k
    if ( nNewSubStrLen )
1040
1.37k
    {
1041
1.37k
        Copy( pBuffer, pNewSubStr, nNewSubStrLen );
1042
1.37k
        pBuffer += nNewSubStrLen;
1043
1.37k
    }
1044
1.37k
    Copy( pBuffer, pStr->buffer+nIndex+nCount, pStr->length-nIndex-nCount );
1045
1046
1.37k
    RTL_LOG_STRING_NEW( *ppThis );
1047
    /* must be done last, if pStr or pNewSubStr == *ppThis */
1048
1.37k
    if ( pOrg )
1049
0
        release( pOrg );
1050
1.37k
}
void rtl::str::newReplaceStrAt<_rtl_uString, char16_t>(_rtl_uString**, _rtl_uString*, int, int, char16_t const*, int)
Line
Count
Source
1003
8.66M
{
1004
8.66M
    assert(ppThis);
1005
8.66M
    assert(nIndex >= 0 && nIndex <= pStr->length);
1006
8.66M
    assert(nCount >= 0);
1007
8.66M
    assert(nCount <= pStr->length - nIndex);
1008
8.66M
    assert(pNewSubStr != nullptr || nNewSubStrLen == 0);
1009
8.66M
    assert(nNewSubStrLen >= 0);
1010
    /* Append? */
1011
8.66M
    if ( nIndex >= pStr->length )
1012
44.5k
        return newConcat(ppThis, pStr, pNewSubStr, nNewSubStrLen);
1013
1014
    /* not more than the String length could be deleted */
1015
8.62M
    if ( nCount >= pStr->length-nIndex )
1016
4.52M
    {
1017
        /* Assign of NewSubStr? */
1018
4.52M
        if (nIndex == 0)
1019
1.56M
            return newFromStr_WithLength( ppThis, pNewSubStr, nNewSubStrLen );
1020
1021
2.95M
        nCount = pStr->length - nIndex;
1022
2.95M
    }
1023
1024
    /* Assign of Str? */
1025
7.05M
    if ( !nCount && !nNewSubStrLen )
1026
3.23k
        return assign(ppThis, pStr);
1027
1028
7.05M
    rtl_tString*    pOrg = *ppThis;
1029
1030
    /* Alloc New Buffer */
1031
7.05M
    *ppThis = Alloc<rtl_tString>(pStr->length - nCount + nNewSubStrLen);
1032
7.05M
    assert(*ppThis != nullptr);
1033
7.05M
    auto* pBuffer = (*ppThis)->buffer;
1034
7.05M
    if ( nIndex )
1035
6.16M
    {
1036
6.16M
        Copy( pBuffer, pStr->buffer, nIndex );
1037
6.16M
        pBuffer += nIndex;
1038
6.16M
    }
1039
7.05M
    if ( nNewSubStrLen )
1040
6.50M
    {
1041
6.50M
        Copy( pBuffer, pNewSubStr, nNewSubStrLen );
1042
6.50M
        pBuffer += nNewSubStrLen;
1043
6.50M
    }
1044
7.05M
    Copy( pBuffer, pStr->buffer+nIndex+nCount, pStr->length-nIndex-nCount );
1045
1046
7.05M
    RTL_LOG_STRING_NEW( *ppThis );
1047
    /* must be done last, if pStr or pNewSubStr == *ppThis */
1048
7.05M
    if ( pOrg )
1049
0
        release( pOrg );
1050
7.05M
}
1051
1052
/* ----------------------------------------------------------------------- */
1053
1054
template <typename rtl_tString>
1055
void newReplaceStrAt(rtl_tString** ppThis, rtl_tString* pStr, sal_Int32 nIndex, sal_Int32 nCount,
1056
                     rtl_tString* pNewSubStr)
1057
46.9M
{
1058
46.9M
    assert(ppThis);
1059
46.9M
    assert(nIndex >= 0 && nIndex <= pStr->length);
1060
46.9M
    assert(nCount >= 0);
1061
46.9M
    assert(nCount <= pStr->length - nIndex);
1062
    /* Append? */
1063
46.9M
    if (nIndex >= pStr->length)
1064
41.0M
    {
1065
        /* newConcat test, if pNewSubStr is 0 */
1066
41.0M
        newConcat(ppThis, pStr, pNewSubStr);
1067
41.0M
        return;
1068
41.0M
    }
1069
1070
    /* not more than the String length could be deleted */
1071
5.90M
    if (nCount >= pStr->length-nIndex)
1072
5.13M
    {
1073
        /* Assign of NewSubStr? */
1074
5.13M
        if (nIndex == 0)
1075
2.56M
        {
1076
2.56M
            if (!pNewSubStr)
1077
0
                return new_(ppThis);
1078
2.56M
            else
1079
2.56M
                return assign(ppThis, pNewSubStr);
1080
2.56M
        }
1081
2.57M
        nCount = pStr->length - nIndex;
1082
2.57M
    }
1083
1084
3.34M
    const auto* pNewSubStrBuf = pNewSubStr ? pNewSubStr->buffer : nullptr;
1085
3.34M
    const sal_Int32 nNewSubStrLength = pNewSubStr ? pNewSubStr->length : 0;
1086
3.34M
    newReplaceStrAt(ppThis, pStr, nIndex, nCount, pNewSubStrBuf, nNewSubStrLength);
1087
3.34M
}
Unexecuted instantiation: void rtl::str::newReplaceStrAt<_rtl_String>(_rtl_String**, _rtl_String*, int, int, _rtl_String*)
void rtl::str::newReplaceStrAt<_rtl_uString>(_rtl_uString**, _rtl_uString*, int, int, _rtl_uString*)
Line
Count
Source
1057
46.9M
{
1058
46.9M
    assert(ppThis);
1059
46.9M
    assert(nIndex >= 0 && nIndex <= pStr->length);
1060
46.9M
    assert(nCount >= 0);
1061
46.9M
    assert(nCount <= pStr->length - nIndex);
1062
    /* Append? */
1063
46.9M
    if (nIndex >= pStr->length)
1064
41.0M
    {
1065
        /* newConcat test, if pNewSubStr is 0 */
1066
41.0M
        newConcat(ppThis, pStr, pNewSubStr);
1067
41.0M
        return;
1068
41.0M
    }
1069
1070
    /* not more than the String length could be deleted */
1071
5.90M
    if (nCount >= pStr->length-nIndex)
1072
5.13M
    {
1073
        /* Assign of NewSubStr? */
1074
5.13M
        if (nIndex == 0)
1075
2.56M
        {
1076
2.56M
            if (!pNewSubStr)
1077
0
                return new_(ppThis);
1078
2.56M
            else
1079
2.56M
                return assign(ppThis, pNewSubStr);
1080
2.56M
        }
1081
2.57M
        nCount = pStr->length - nIndex;
1082
2.57M
    }
1083
1084
3.34M
    const auto* pNewSubStrBuf = pNewSubStr ? pNewSubStr->buffer : nullptr;
1085
3.34M
    const sal_Int32 nNewSubStrLength = pNewSubStr ? pNewSubStr->length : 0;
1086
3.34M
    newReplaceStrAt(ppThis, pStr, nIndex, nCount, pNewSubStrBuf, nNewSubStrLength);
1087
3.34M
}
1088
1089
/* ----------------------------------------------------------------------- */
1090
1091
template <typename rtl_tString, class Replacer>
1092
void newReplaceChars(rtl_tString** ppThis, rtl_tString* pStr, Replacer replacer)
1093
16.2M
{
1094
16.2M
    assert(ppThis);
1095
16.2M
    assert(pStr);
1096
1097
16.2M
    const auto pEnd = pStr->buffer + pStr->length;
1098
16.2M
    auto pCharStr = std::find_if(pStr->buffer, pEnd, replacer.Applicable());
1099
16.2M
    if (pCharStr != pEnd)
1100
6.59M
    {
1101
6.59M
        rtl_tString* pOrg = *ppThis;
1102
6.59M
        *ppThis = Alloc<rtl_tString>(pStr->length);
1103
6.59M
        assert(*ppThis != nullptr);
1104
6.59M
        auto* pNewCharStr = (*ppThis)->buffer;
1105
        /* Copy String */
1106
6.59M
        const sal_Int32 nCount = pCharStr - pStr->buffer;
1107
6.59M
        Copy(pNewCharStr, pStr->buffer, nCount);
1108
6.59M
        pNewCharStr += nCount;
1109
        /* replace/copy rest of the string */
1110
6.59M
        do
1111
92.5M
        {
1112
92.5M
            *pNewCharStr = replacer.Replace(*pCharStr);
1113
92.5M
            pNewCharStr++;
1114
92.5M
            pCharStr++;
1115
92.5M
        } while (pCharStr != pEnd);
1116
1117
6.59M
        RTL_LOG_STRING_NEW(*ppThis);
1118
        /* must be done last, if pStr == *ppThis */
1119
6.59M
        if (pOrg)
1120
0
            release(pOrg);
1121
6.59M
    }
1122
9.61M
    else
1123
9.61M
        assign(ppThis, pStr);
1124
16.2M
}
Unexecuted instantiation: void rtl::str::newReplaceChars<_rtl_String, rtl::str::FromTo<char> >(_rtl_String**, _rtl_String*, rtl::str::FromTo<char>)
void rtl::str::newReplaceChars<_rtl_String, rtl::str::CaseReplace<rtl::isAsciiUpperCase(unsigned int), rtl::toAsciiLowerCase(unsigned int)> >(_rtl_String**, _rtl_String*, rtl::str::CaseReplace<rtl::isAsciiUpperCase(unsigned int), rtl::toAsciiLowerCase(unsigned int)>)
Line
Count
Source
1093
14.2k
{
1094
14.2k
    assert(ppThis);
1095
14.2k
    assert(pStr);
1096
1097
14.2k
    const auto pEnd = pStr->buffer + pStr->length;
1098
14.2k
    auto pCharStr = std::find_if(pStr->buffer, pEnd, replacer.Applicable());
1099
14.2k
    if (pCharStr != pEnd)
1100
14.2k
    {
1101
14.2k
        rtl_tString* pOrg = *ppThis;
1102
14.2k
        *ppThis = Alloc<rtl_tString>(pStr->length);
1103
14.2k
        assert(*ppThis != nullptr);
1104
14.2k
        auto* pNewCharStr = (*ppThis)->buffer;
1105
        /* Copy String */
1106
14.2k
        const sal_Int32 nCount = pCharStr - pStr->buffer;
1107
14.2k
        Copy(pNewCharStr, pStr->buffer, nCount);
1108
14.2k
        pNewCharStr += nCount;
1109
        /* replace/copy rest of the string */
1110
14.2k
        do
1111
68.5k
        {
1112
68.5k
            *pNewCharStr = replacer.Replace(*pCharStr);
1113
68.5k
            pNewCharStr++;
1114
68.5k
            pCharStr++;
1115
68.5k
        } while (pCharStr != pEnd);
1116
1117
14.2k
        RTL_LOG_STRING_NEW(*ppThis);
1118
        /* must be done last, if pStr == *ppThis */
1119
14.2k
        if (pOrg)
1120
0
            release(pOrg);
1121
14.2k
    }
1122
32
    else
1123
32
        assign(ppThis, pStr);
1124
14.2k
}
void rtl::str::newReplaceChars<_rtl_String, rtl::str::CaseReplace<rtl::isAsciiLowerCase(unsigned int), rtl::toAsciiUpperCase(unsigned int)> >(_rtl_String**, _rtl_String*, rtl::str::CaseReplace<rtl::isAsciiLowerCase(unsigned int), rtl::toAsciiUpperCase(unsigned int)>)
Line
Count
Source
1093
80
{
1094
80
    assert(ppThis);
1095
80
    assert(pStr);
1096
1097
80
    const auto pEnd = pStr->buffer + pStr->length;
1098
80
    auto pCharStr = std::find_if(pStr->buffer, pEnd, replacer.Applicable());
1099
80
    if (pCharStr != pEnd)
1100
80
    {
1101
80
        rtl_tString* pOrg = *ppThis;
1102
80
        *ppThis = Alloc<rtl_tString>(pStr->length);
1103
80
        assert(*ppThis != nullptr);
1104
80
        auto* pNewCharStr = (*ppThis)->buffer;
1105
        /* Copy String */
1106
80
        const sal_Int32 nCount = pCharStr - pStr->buffer;
1107
80
        Copy(pNewCharStr, pStr->buffer, nCount);
1108
80
        pNewCharStr += nCount;
1109
        /* replace/copy rest of the string */
1110
80
        do
1111
80
        {
1112
80
            *pNewCharStr = replacer.Replace(*pCharStr);
1113
80
            pNewCharStr++;
1114
80
            pCharStr++;
1115
80
        } while (pCharStr != pEnd);
1116
1117
80
        RTL_LOG_STRING_NEW(*ppThis);
1118
        /* must be done last, if pStr == *ppThis */
1119
80
        if (pOrg)
1120
0
            release(pOrg);
1121
80
    }
1122
0
    else
1123
0
        assign(ppThis, pStr);
1124
80
}
void rtl::str::newReplaceChars<_rtl_uString, rtl::str::FromTo<char16_t> >(_rtl_uString**, _rtl_uString*, rtl::str::FromTo<char16_t>)
Line
Count
Source
1093
530k
{
1094
530k
    assert(ppThis);
1095
530k
    assert(pStr);
1096
1097
530k
    const auto pEnd = pStr->buffer + pStr->length;
1098
530k
    auto pCharStr = std::find_if(pStr->buffer, pEnd, replacer.Applicable());
1099
530k
    if (pCharStr != pEnd)
1100
330k
    {
1101
330k
        rtl_tString* pOrg = *ppThis;
1102
330k
        *ppThis = Alloc<rtl_tString>(pStr->length);
1103
330k
        assert(*ppThis != nullptr);
1104
330k
        auto* pNewCharStr = (*ppThis)->buffer;
1105
        /* Copy String */
1106
330k
        const sal_Int32 nCount = pCharStr - pStr->buffer;
1107
330k
        Copy(pNewCharStr, pStr->buffer, nCount);
1108
330k
        pNewCharStr += nCount;
1109
        /* replace/copy rest of the string */
1110
330k
        do
1111
10.8M
        {
1112
10.8M
            *pNewCharStr = replacer.Replace(*pCharStr);
1113
10.8M
            pNewCharStr++;
1114
10.8M
            pCharStr++;
1115
10.8M
        } while (pCharStr != pEnd);
1116
1117
330k
        RTL_LOG_STRING_NEW(*ppThis);
1118
        /* must be done last, if pStr == *ppThis */
1119
330k
        if (pOrg)
1120
0
            release(pOrg);
1121
330k
    }
1122
199k
    else
1123
199k
        assign(ppThis, pStr);
1124
530k
}
void rtl::str::newReplaceChars<_rtl_uString, rtl::str::CaseReplace<rtl::isAsciiUpperCase(unsigned int), rtl::toAsciiLowerCase(unsigned int)> >(_rtl_uString**, _rtl_uString*, rtl::str::CaseReplace<rtl::isAsciiUpperCase(unsigned int), rtl::toAsciiLowerCase(unsigned int)>)
Line
Count
Source
1093
9.18M
{
1094
9.18M
    assert(ppThis);
1095
9.18M
    assert(pStr);
1096
1097
9.18M
    const auto pEnd = pStr->buffer + pStr->length;
1098
9.18M
    auto pCharStr = std::find_if(pStr->buffer, pEnd, replacer.Applicable());
1099
9.18M
    if (pCharStr != pEnd)
1100
4.39M
    {
1101
4.39M
        rtl_tString* pOrg = *ppThis;
1102
4.39M
        *ppThis = Alloc<rtl_tString>(pStr->length);
1103
4.39M
        assert(*ppThis != nullptr);
1104
4.39M
        auto* pNewCharStr = (*ppThis)->buffer;
1105
        /* Copy String */
1106
4.39M
        const sal_Int32 nCount = pCharStr - pStr->buffer;
1107
4.39M
        Copy(pNewCharStr, pStr->buffer, nCount);
1108
4.39M
        pNewCharStr += nCount;
1109
        /* replace/copy rest of the string */
1110
4.39M
        do
1111
53.3M
        {
1112
53.3M
            *pNewCharStr = replacer.Replace(*pCharStr);
1113
53.3M
            pNewCharStr++;
1114
53.3M
            pCharStr++;
1115
53.3M
        } while (pCharStr != pEnd);
1116
1117
4.39M
        RTL_LOG_STRING_NEW(*ppThis);
1118
        /* must be done last, if pStr == *ppThis */
1119
4.39M
        if (pOrg)
1120
0
            release(pOrg);
1121
4.39M
    }
1122
4.78M
    else
1123
4.78M
        assign(ppThis, pStr);
1124
9.18M
}
void rtl::str::newReplaceChars<_rtl_uString, rtl::str::CaseReplace<rtl::isAsciiLowerCase(unsigned int), rtl::toAsciiUpperCase(unsigned int)> >(_rtl_uString**, _rtl_uString*, rtl::str::CaseReplace<rtl::isAsciiLowerCase(unsigned int), rtl::toAsciiUpperCase(unsigned int)>)
Line
Count
Source
1093
6.48M
{
1094
6.48M
    assert(ppThis);
1095
6.48M
    assert(pStr);
1096
1097
6.48M
    const auto pEnd = pStr->buffer + pStr->length;
1098
6.48M
    auto pCharStr = std::find_if(pStr->buffer, pEnd, replacer.Applicable());
1099
6.48M
    if (pCharStr != pEnd)
1100
1.85M
    {
1101
1.85M
        rtl_tString* pOrg = *ppThis;
1102
1.85M
        *ppThis = Alloc<rtl_tString>(pStr->length);
1103
1.85M
        assert(*ppThis != nullptr);
1104
1.85M
        auto* pNewCharStr = (*ppThis)->buffer;
1105
        /* Copy String */
1106
1.85M
        const sal_Int32 nCount = pCharStr - pStr->buffer;
1107
1.85M
        Copy(pNewCharStr, pStr->buffer, nCount);
1108
1.85M
        pNewCharStr += nCount;
1109
        /* replace/copy rest of the string */
1110
1.85M
        do
1111
28.2M
        {
1112
28.2M
            *pNewCharStr = replacer.Replace(*pCharStr);
1113
28.2M
            pNewCharStr++;
1114
28.2M
            pCharStr++;
1115
28.2M
        } while (pCharStr != pEnd);
1116
1117
1.85M
        RTL_LOG_STRING_NEW(*ppThis);
1118
        /* must be done last, if pStr == *ppThis */
1119
1.85M
        if (pOrg)
1120
0
            release(pOrg);
1121
1.85M
    }
1122
4.63M
    else
1123
4.63M
        assign(ppThis, pStr);
1124
6.48M
}
1125
1126
/* ----------------------------------------------------------------------- */
1127
1128
template <typename rtl_tString> void newTrim(rtl_tString** ppThis, rtl_tString* pStr)
1129
1.17M
{
1130
1.17M
    assert(pStr);
1131
1.17M
    const auto view = o3tl::trim(std::basic_string_view(pStr->buffer, pStr->length));
1132
1133
1.17M
    if (static_cast<sal_Int32>(view.size()) == pStr->length)
1134
363k
        assign(ppThis, pStr);
1135
810k
    else
1136
810k
        newFromStr_WithLength(ppThis, view.data(), view.size());
1137
1.17M
}
Unexecuted instantiation: void rtl::str::newTrim<_rtl_String>(_rtl_String**, _rtl_String*)
void rtl::str::newTrim<_rtl_uString>(_rtl_uString**, _rtl_uString*)
Line
Count
Source
1129
1.17M
{
1130
1.17M
    assert(pStr);
1131
1.17M
    const auto view = o3tl::trim(std::basic_string_view(pStr->buffer, pStr->length));
1132
1133
1.17M
    if (static_cast<sal_Int32>(view.size()) == pStr->length)
1134
363k
        assign(ppThis, pStr);
1135
810k
    else
1136
810k
        newFromStr_WithLength(ppThis, view.data(), view.size());
1137
1.17M
}
1138
1139
/* ----------------------------------------------------------------------- */
1140
1141
template <typename rtl_tString>
1142
sal_Int32 getToken(rtl_tString** ppThis, rtl_tString* pStr, sal_Int32 nToken,
1143
                   Char_T<rtl_tString> cTok, sal_Int32 nIndex)
1144
8.33M
{
1145
8.33M
    assert(ppThis);
1146
8.33M
    assert(pStr);
1147
8.33M
    assert(nIndex <= pStr->length);
1148
1149
    // Set ppThis to an empty string and return -1 if either nToken or nIndex is
1150
    // negative:
1151
8.33M
    if (nIndex >= 0 && nToken >= 0)
1152
8.33M
    {
1153
8.33M
        const auto* pOrgCharStr = pStr->buffer;
1154
8.33M
        const auto* pCharStr = pOrgCharStr + nIndex;
1155
8.33M
        sal_Int32 nLen = pStr->length - nIndex;
1156
8.33M
        sal_Int32 nTokCount = 0;
1157
8.33M
        const auto* pCharStrStart = pCharStr;
1158
107M
        while (nLen > 0)
1159
101M
        {
1160
101M
            if (*pCharStr == cTok)
1161
3.25M
            {
1162
3.25M
                nTokCount++;
1163
1164
3.25M
                if (nTokCount > nToken)
1165
3.25M
                    break;
1166
10
                if (nTokCount == nToken)
1167
10
                    pCharStrStart = pCharStr + 1;
1168
10
            }
1169
1170
98.6M
            pCharStr++;
1171
98.6M
            nLen--;
1172
98.6M
        }
1173
8.33M
        if (nTokCount >= nToken)
1174
8.33M
        {
1175
8.33M
            newFromStr_WithLength(ppThis, pCharStrStart, pCharStr - pCharStrStart);
1176
8.33M
            if (nLen > 0)
1177
3.25M
                return pCharStr - pOrgCharStr + 1;
1178
5.07M
            else
1179
5.07M
                return -1;
1180
8.33M
        }
1181
8.33M
    }
1182
1183
1.71k
    new_(ppThis);
1184
1.71k
    return -1;
1185
8.33M
}
_ZN3rtl3str8getTokenI11_rtl_StringEEiPPT_S4_iu15__remove_extentIDtsrS3_6bufferEEi
Line
Count
Source
1144
324
{
1145
324
    assert(ppThis);
1146
324
    assert(pStr);
1147
324
    assert(nIndex <= pStr->length);
1148
1149
    // Set ppThis to an empty string and return -1 if either nToken or nIndex is
1150
    // negative:
1151
324
    if (nIndex >= 0 && nToken >= 0)
1152
324
    {
1153
324
        const auto* pOrgCharStr = pStr->buffer;
1154
324
        const auto* pCharStr = pOrgCharStr + nIndex;
1155
324
        sal_Int32 nLen = pStr->length - nIndex;
1156
324
        sal_Int32 nTokCount = 0;
1157
324
        const auto* pCharStrStart = pCharStr;
1158
13.8k
        while (nLen > 0)
1159
13.7k
        {
1160
13.7k
            if (*pCharStr == cTok)
1161
216
            {
1162
216
                nTokCount++;
1163
1164
216
                if (nTokCount > nToken)
1165
216
                    break;
1166
0
                if (nTokCount == nToken)
1167
0
                    pCharStrStart = pCharStr + 1;
1168
0
            }
1169
1170
13.5k
            pCharStr++;
1171
13.5k
            nLen--;
1172
13.5k
        }
1173
324
        if (nTokCount >= nToken)
1174
324
        {
1175
324
            newFromStr_WithLength(ppThis, pCharStrStart, pCharStr - pCharStrStart);
1176
324
            if (nLen > 0)
1177
216
                return pCharStr - pOrgCharStr + 1;
1178
108
            else
1179
108
                return -1;
1180
324
        }
1181
324
    }
1182
1183
0
    new_(ppThis);
1184
0
    return -1;
1185
324
}
_ZN3rtl3str8getTokenI12_rtl_uStringEEiPPT_S4_iu15__remove_extentIDtsrS3_6bufferEEi
Line
Count
Source
1144
8.33M
{
1145
8.33M
    assert(ppThis);
1146
8.33M
    assert(pStr);
1147
8.33M
    assert(nIndex <= pStr->length);
1148
1149
    // Set ppThis to an empty string and return -1 if either nToken or nIndex is
1150
    // negative:
1151
8.33M
    if (nIndex >= 0 && nToken >= 0)
1152
8.33M
    {
1153
8.33M
        const auto* pOrgCharStr = pStr->buffer;
1154
8.33M
        const auto* pCharStr = pOrgCharStr + nIndex;
1155
8.33M
        sal_Int32 nLen = pStr->length - nIndex;
1156
8.33M
        sal_Int32 nTokCount = 0;
1157
8.33M
        const auto* pCharStrStart = pCharStr;
1158
106M
        while (nLen > 0)
1159
101M
        {
1160
101M
            if (*pCharStr == cTok)
1161
3.25M
            {
1162
3.25M
                nTokCount++;
1163
1164
3.25M
                if (nTokCount > nToken)
1165
3.25M
                    break;
1166
10
                if (nTokCount == nToken)
1167
10
                    pCharStrStart = pCharStr + 1;
1168
10
            }
1169
1170
98.6M
            pCharStr++;
1171
98.6M
            nLen--;
1172
98.6M
        }
1173
8.33M
        if (nTokCount >= nToken)
1174
8.33M
        {
1175
8.33M
            newFromStr_WithLength(ppThis, pCharStrStart, pCharStr - pCharStrStart);
1176
8.33M
            if (nLen > 0)
1177
3.25M
                return pCharStr - pOrgCharStr + 1;
1178
5.07M
            else
1179
5.07M
                return -1;
1180
8.33M
        }
1181
8.33M
    }
1182
1183
1.71k
    new_(ppThis);
1184
1.71k
    return -1;
1185
8.33M
}
1186
1187
/* ======================================================================= */
1188
/* String buffer help functions                                            */
1189
/* ======================================================================= */
1190
1191
template <class rtl_tString>
1192
void stringbuffer_newFromStr_WithLength(rtl_tString** ppThis,
1193
                                        const Char_T<rtl_tString>* pStr, sal_Int32 count)
1194
28.6M
{
1195
28.6M
    assert(ppThis);
1196
28.6M
    assert(count >= 0);
1197
28.6M
    if (!pStr)
1198
0
        count = 0; // Because old code didn't care about count when !pStr
1199
1200
28.6M
    newFromStr_WithLength(ppThis, pStr, count, 16);
1201
28.6M
}
Unexecuted instantiation: _ZN3rtl3str34stringbuffer_newFromStr_WithLengthI11_rtl_StringEEvPPT_PKu15__remove_extentIDtsrS3_6bufferEEi
_ZN3rtl3str34stringbuffer_newFromStr_WithLengthI12_rtl_uStringEEvPPT_PKu15__remove_extentIDtsrS3_6bufferEEi
Line
Count
Source
1194
28.6M
{
1195
28.6M
    assert(ppThis);
1196
28.6M
    assert(count >= 0);
1197
28.6M
    if (!pStr)
1198
0
        count = 0; // Because old code didn't care about count when !pStr
1199
1200
28.6M
    newFromStr_WithLength(ppThis, pStr, count, 16);
1201
28.6M
}
1202
1203
template <class rtl_tString>
1204
sal_Int32 stringbuffer_newFromStringBuffer(rtl_tString** ppThis, sal_Int32 capacity,
1205
                                           rtl_tString* pStr)
1206
712k
{
1207
712k
    assert(capacity >= 0);
1208
712k
    assert(pStr);
1209
1210
712k
    if (capacity < pStr->length)
1211
0
        capacity = pStr->length;
1212
1213
712k
    newFromStr_WithLength(ppThis, pStr->buffer, pStr->length, capacity - pStr->length);
1214
712k
    return capacity;
1215
712k
}
Unexecuted instantiation: int rtl::str::stringbuffer_newFromStringBuffer<_rtl_String>(_rtl_String**, int, _rtl_String*)
int rtl::str::stringbuffer_newFromStringBuffer<_rtl_uString>(_rtl_uString**, int, _rtl_uString*)
Line
Count
Source
1206
712k
{
1207
712k
    assert(capacity >= 0);
1208
712k
    assert(pStr);
1209
1210
712k
    if (capacity < pStr->length)
1211
0
        capacity = pStr->length;
1212
1213
712k
    newFromStr_WithLength(ppThis, pStr->buffer, pStr->length, capacity - pStr->length);
1214
712k
    return capacity;
1215
712k
}
1216
1217
template <class rtl_tString>
1218
void stringbuffer_ensureCapacity(rtl_tString** ppThis, sal_Int32* capacity,
1219
                                 sal_Int32 minimumCapacity)
1220
1.43G
{
1221
1.43G
    assert(ppThis);
1222
1.43G
    assert(capacity && *capacity >= 0);
1223
    // assert(minimumCapacity >= 0); // It was commented out in rtl_stringbuffer_ensureCapacity
1224
1.43G
    if (minimumCapacity <= *capacity)
1225
1.42G
        return;
1226
1227
7.42M
    const auto nLength = (*ppThis)->length;
1228
7.42M
    *capacity = (nLength + 1) * 2;
1229
7.42M
    if (minimumCapacity > *capacity)
1230
3.36M
        *capacity = minimumCapacity;
1231
1232
7.42M
    newFromStr_WithLength(ppThis, (*ppThis)->buffer, nLength, *capacity - nLength);
1233
7.42M
}
void rtl::str::stringbuffer_ensureCapacity<_rtl_String>(_rtl_String**, int*, int)
Line
Count
Source
1220
254M
{
1221
254M
    assert(ppThis);
1222
254M
    assert(capacity && *capacity >= 0);
1223
    // assert(minimumCapacity >= 0); // It was commented out in rtl_stringbuffer_ensureCapacity
1224
254M
    if (minimumCapacity <= *capacity)
1225
254M
        return;
1226
1227
606k
    const auto nLength = (*ppThis)->length;
1228
606k
    *capacity = (nLength + 1) * 2;
1229
606k
    if (minimumCapacity > *capacity)
1230
196k
        *capacity = minimumCapacity;
1231
1232
606k
    newFromStr_WithLength(ppThis, (*ppThis)->buffer, nLength, *capacity - nLength);
1233
606k
}
void rtl::str::stringbuffer_ensureCapacity<_rtl_uString>(_rtl_uString**, int*, int)
Line
Count
Source
1220
1.18G
{
1221
1.18G
    assert(ppThis);
1222
1.18G
    assert(capacity && *capacity >= 0);
1223
    // assert(minimumCapacity >= 0); // It was commented out in rtl_stringbuffer_ensureCapacity
1224
1.18G
    if (minimumCapacity <= *capacity)
1225
1.17G
        return;
1226
1227
6.81M
    const auto nLength = (*ppThis)->length;
1228
6.81M
    *capacity = (nLength + 1) * 2;
1229
6.81M
    if (minimumCapacity > *capacity)
1230
3.17M
        *capacity = minimumCapacity;
1231
1232
6.81M
    newFromStr_WithLength(ppThis, (*ppThis)->buffer, nLength, *capacity - nLength);
1233
6.81M
}
1234
1235
template <class rtl_tString, typename C>
1236
void stringbuffer_insert(rtl_tString** ppThis, sal_Int32* capacity, sal_Int32 offset,
1237
                         const C* pStr, sal_Int32 len)
1238
1.45G
{
1239
1.45G
    assert(ppThis);
1240
1.45G
    assert(capacity && *capacity >= 0);
1241
1.45G
    assert(offset >= 0 && offset <= (*ppThis)->length);
1242
1.45G
    assert(len >= 0);
1243
1.45G
    if (len == 0)
1244
15.8M
        return;
1245
1.43G
    if (len > std::numeric_limits<sal_Int32>::max() - (*ppThis)->length) {
1246
0
        throw std::bad_alloc();
1247
0
    }
1248
1249
1.43G
    stringbuffer_ensureCapacity(ppThis, capacity, (*ppThis)->length + len);
1250
1251
1.43G
    sal_Int32 nOldLen = (*ppThis)->length;
1252
1.43G
    auto* pBuf = (*ppThis)->buffer;
1253
1254
    /* copy the tail */
1255
1.43G
    const sal_Int32 n = nOldLen - offset;
1256
1.43G
    if (n > 0)
1257
12.8M
        CopyBackward(pBuf + offset + len, pBuf + offset, n);
1258
1259
    /* insert the new characters */
1260
1.43G
    if (pStr != nullptr)
1261
1.27G
        Copy(pBuf + offset, pStr, len);
1262
1263
1.43G
    (*ppThis)->length = nOldLen + len;
1264
1.43G
    pBuf[nOldLen + len] = 0;
1265
1.43G
}
void rtl::str::stringbuffer_insert<_rtl_String, char>(_rtl_String**, int*, int, char const*, int)
Line
Count
Source
1238
254M
{
1239
254M
    assert(ppThis);
1240
254M
    assert(capacity && *capacity >= 0);
1241
254M
    assert(offset >= 0 && offset <= (*ppThis)->length);
1242
254M
    assert(len >= 0);
1243
254M
    if (len == 0)
1244
125k
        return;
1245
254M
    if (len > std::numeric_limits<sal_Int32>::max() - (*ppThis)->length) {
1246
0
        throw std::bad_alloc();
1247
0
    }
1248
1249
254M
    stringbuffer_ensureCapacity(ppThis, capacity, (*ppThis)->length + len);
1250
1251
254M
    sal_Int32 nOldLen = (*ppThis)->length;
1252
254M
    auto* pBuf = (*ppThis)->buffer;
1253
1254
    /* copy the tail */
1255
254M
    const sal_Int32 n = nOldLen - offset;
1256
254M
    if (n > 0)
1257
0
        CopyBackward(pBuf + offset + len, pBuf + offset, n);
1258
1259
    /* insert the new characters */
1260
254M
    if (pStr != nullptr)
1261
104M
        Copy(pBuf + offset, pStr, len);
1262
1263
254M
    (*ppThis)->length = nOldLen + len;
1264
254M
    pBuf[nOldLen + len] = 0;
1265
254M
}
void rtl::str::stringbuffer_insert<_rtl_uString, char>(_rtl_uString**, int*, int, char const*, int)
Line
Count
Source
1238
12.9M
{
1239
12.9M
    assert(ppThis);
1240
12.9M
    assert(capacity && *capacity >= 0);
1241
12.9M
    assert(offset >= 0 && offset <= (*ppThis)->length);
1242
12.9M
    assert(len >= 0);
1243
12.9M
    if (len == 0)
1244
138k
        return;
1245
12.7M
    if (len > std::numeric_limits<sal_Int32>::max() - (*ppThis)->length) {
1246
0
        throw std::bad_alloc();
1247
0
    }
1248
1249
12.7M
    stringbuffer_ensureCapacity(ppThis, capacity, (*ppThis)->length + len);
1250
1251
12.7M
    sal_Int32 nOldLen = (*ppThis)->length;
1252
12.7M
    auto* pBuf = (*ppThis)->buffer;
1253
1254
    /* copy the tail */
1255
12.7M
    const sal_Int32 n = nOldLen - offset;
1256
12.7M
    if (n > 0)
1257
4.60M
        CopyBackward(pBuf + offset + len, pBuf + offset, n);
1258
1259
    /* insert the new characters */
1260
12.7M
    if (pStr != nullptr)
1261
12.7M
        Copy(pBuf + offset, pStr, len);
1262
1263
12.7M
    (*ppThis)->length = nOldLen + len;
1264
12.7M
    pBuf[nOldLen + len] = 0;
1265
12.7M
}
void rtl::str::stringbuffer_insert<_rtl_uString, char16_t>(_rtl_uString**, int*, int, char16_t const*, int)
Line
Count
Source
1238
1.18G
{
1239
1.18G
    assert(ppThis);
1240
1.18G
    assert(capacity && *capacity >= 0);
1241
1.18G
    assert(offset >= 0 && offset <= (*ppThis)->length);
1242
1.18G
    assert(len >= 0);
1243
1.18G
    if (len == 0)
1244
15.5M
        return;
1245
1.16G
    if (len > std::numeric_limits<sal_Int32>::max() - (*ppThis)->length) {
1246
0
        throw std::bad_alloc();
1247
0
    }
1248
1249
1.16G
    stringbuffer_ensureCapacity(ppThis, capacity, (*ppThis)->length + len);
1250
1251
1.16G
    sal_Int32 nOldLen = (*ppThis)->length;
1252
1.16G
    auto* pBuf = (*ppThis)->buffer;
1253
1254
    /* copy the tail */
1255
1.16G
    const sal_Int32 n = nOldLen - offset;
1256
1.16G
    if (n > 0)
1257
8.23M
        CopyBackward(pBuf + offset + len, pBuf + offset, n);
1258
1259
    /* insert the new characters */
1260
1.16G
    if (pStr != nullptr)
1261
1.16G
        Copy(pBuf + offset, pStr, len);
1262
1263
1.16G
    (*ppThis)->length = nOldLen + len;
1264
1.16G
    pBuf[nOldLen + len] = 0;
1265
1.16G
}
1266
1267
template <class rtl_tString>
1268
void stringbuffer_remove(rtl_tString** ppThis, sal_Int32 start, sal_Int32 len)
1269
33.8M
{
1270
33.8M
    assert(ppThis);
1271
33.8M
    assert(start >= 0 && start <= (*ppThis)->length);
1272
33.8M
    assert(len >= 0);
1273
1274
33.8M
    if (len > (*ppThis)->length - start)
1275
371
        len = (*ppThis)->length - start;
1276
1277
    //remove nothing
1278
33.8M
    if (!len)
1279
606k
        return;
1280
1281
33.2M
    auto* pBuf = (*ppThis)->buffer;
1282
33.2M
    const sal_Int32 nTailLen = (*ppThis)->length - (start + len);
1283
1284
33.2M
    if (nTailLen)
1285
5.60M
    {
1286
        /* move the tail */
1287
5.60M
        Copy(pBuf + start, pBuf + start + len, nTailLen);
1288
5.60M
    }
1289
1290
33.2M
    (*ppThis)->length -= len;
1291
33.2M
    pBuf[(*ppThis)->length] = 0;
1292
33.2M
}
Unexecuted instantiation: void rtl::str::stringbuffer_remove<_rtl_String>(_rtl_String**, int, int)
void rtl::str::stringbuffer_remove<_rtl_uString>(_rtl_uString**, int, int)
Line
Count
Source
1269
33.8M
{
1270
33.8M
    assert(ppThis);
1271
33.8M
    assert(start >= 0 && start <= (*ppThis)->length);
1272
33.8M
    assert(len >= 0);
1273
1274
33.8M
    if (len > (*ppThis)->length - start)
1275
371
        len = (*ppThis)->length - start;
1276
1277
    //remove nothing
1278
33.8M
    if (!len)
1279
606k
        return;
1280
1281
33.2M
    auto* pBuf = (*ppThis)->buffer;
1282
33.2M
    const sal_Int32 nTailLen = (*ppThis)->length - (start + len);
1283
1284
33.2M
    if (nTailLen)
1285
5.60M
    {
1286
        /* move the tail */
1287
5.60M
        Copy(pBuf + start, pBuf + start + len, nTailLen);
1288
5.60M
    }
1289
1290
33.2M
    (*ppThis)->length -= len;
1291
33.2M
    pBuf[(*ppThis)->length] = 0;
1292
33.2M
}
1293
1294
template <class S, typename CharTypeFrom, typename CharTypeTo>
1295
void newReplaceAllFromIndex(S** s, S* s1, CharTypeFrom const* from, sal_Int32 fromLength,
1296
                            CharTypeTo const* to, sal_Int32 toLength, sal_Int32 fromIndex)
1297
43.7M
{
1298
43.7M
    assert(s != nullptr);
1299
43.7M
    assert(s1 != nullptr);
1300
43.7M
    assert(fromLength >= 0);
1301
43.7M
    assert(from != nullptr || fromLength == 0);
1302
43.7M
    assert(toLength >= 0);
1303
43.7M
    assert(to != nullptr || toLength == 0);
1304
43.7M
    assert(fromIndex >= 0 && fromIndex <= s1->length);
1305
43.7M
    sal_Int32 i = indexOfStr_WithLength(s1->buffer + fromIndex, s1->length - fromIndex,
1306
43.7M
                                        from, fromLength);
1307
43.7M
    if (i >= 0)
1308
4.47M
    {
1309
4.47M
        if (s1->length - fromLength > SAL_MAX_INT32 - toLength)
1310
0
            std::abort();
1311
4.47M
        i += fromIndex;
1312
4.47M
        sal_Int32 nCapacity = s1->length + (toLength - fromLength);
1313
4.47M
        if (fromLength < toLength)
1314
123k
        {
1315
            // Pre-allocate up to 16 replacements more
1316
123k
            const sal_Int32 nMaxMoreFinds = (s1->length - i - fromLength) / fromLength;
1317
123k
            const sal_Int32 nIncrease = toLength - fromLength;
1318
123k
            const sal_Int32 nMoreReplacements = std::min(
1319
123k
                { nMaxMoreFinds, (SAL_MAX_INT32 - nCapacity) / nIncrease, sal_Int32(16) });
1320
123k
            nCapacity += nMoreReplacements * nIncrease;
1321
123k
        }
1322
4.47M
        const auto pOld = *s;
1323
4.47M
        *s = Alloc<S>(nCapacity);
1324
4.47M
        (*s)->length = 0;
1325
4.47M
        fromIndex = 0;
1326
4.47M
        do
1327
8.67M
        {
1328
8.67M
            stringbuffer_insert(s, &nCapacity, (*s)->length, s1->buffer + fromIndex, i);
1329
8.67M
            stringbuffer_insert(s, &nCapacity, (*s)->length, to, toLength);
1330
8.67M
            fromIndex += i + fromLength;
1331
8.67M
            i = indexOfStr_WithLength(s1->buffer + fromIndex, s1->length - fromIndex,
1332
8.67M
                                      from, fromLength);
1333
8.67M
        } while (i >= 0);
1334
        // the rest
1335
4.47M
        stringbuffer_insert(s, &nCapacity, (*s)->length,
1336
4.47M
                            s1->buffer + fromIndex, s1->length - fromIndex);
1337
4.47M
        if (pOld)
1338
0
            release(pOld); // Must be last in case *s == s1
1339
4.47M
    }
1340
39.2M
    else
1341
39.2M
        assign(s, s1);
1342
1343
43.7M
    RTL_LOG_STRING_NEW(*s);
1344
43.7M
}
void rtl::str::newReplaceAllFromIndex<_rtl_String, char, char>(_rtl_String**, _rtl_String*, char const*, int, char const*, int, int)
Line
Count
Source
1297
1.62k
{
1298
1.62k
    assert(s != nullptr);
1299
1.62k
    assert(s1 != nullptr);
1300
1.62k
    assert(fromLength >= 0);
1301
1.62k
    assert(from != nullptr || fromLength == 0);
1302
1.62k
    assert(toLength >= 0);
1303
1.62k
    assert(to != nullptr || toLength == 0);
1304
1.62k
    assert(fromIndex >= 0 && fromIndex <= s1->length);
1305
1.62k
    sal_Int32 i = indexOfStr_WithLength(s1->buffer + fromIndex, s1->length - fromIndex,
1306
1.62k
                                        from, fromLength);
1307
1.62k
    if (i >= 0)
1308
216
    {
1309
216
        if (s1->length - fromLength > SAL_MAX_INT32 - toLength)
1310
0
            std::abort();
1311
216
        i += fromIndex;
1312
216
        sal_Int32 nCapacity = s1->length + (toLength - fromLength);
1313
216
        if (fromLength < toLength)
1314
0
        {
1315
            // Pre-allocate up to 16 replacements more
1316
0
            const sal_Int32 nMaxMoreFinds = (s1->length - i - fromLength) / fromLength;
1317
0
            const sal_Int32 nIncrease = toLength - fromLength;
1318
0
            const sal_Int32 nMoreReplacements = std::min(
1319
0
                { nMaxMoreFinds, (SAL_MAX_INT32 - nCapacity) / nIncrease, sal_Int32(16) });
1320
0
            nCapacity += nMoreReplacements * nIncrease;
1321
0
        }
1322
216
        const auto pOld = *s;
1323
216
        *s = Alloc<S>(nCapacity);
1324
216
        (*s)->length = 0;
1325
216
        fromIndex = 0;
1326
216
        do
1327
216
        {
1328
216
            stringbuffer_insert(s, &nCapacity, (*s)->length, s1->buffer + fromIndex, i);
1329
216
            stringbuffer_insert(s, &nCapacity, (*s)->length, to, toLength);
1330
216
            fromIndex += i + fromLength;
1331
216
            i = indexOfStr_WithLength(s1->buffer + fromIndex, s1->length - fromIndex,
1332
216
                                      from, fromLength);
1333
216
        } while (i >= 0);
1334
        // the rest
1335
216
        stringbuffer_insert(s, &nCapacity, (*s)->length,
1336
216
                            s1->buffer + fromIndex, s1->length - fromIndex);
1337
216
        if (pOld)
1338
0
            release(pOld); // Must be last in case *s == s1
1339
216
    }
1340
1.40k
    else
1341
1.40k
        assign(s, s1);
1342
1343
1.62k
    RTL_LOG_STRING_NEW(*s);
1344
1.62k
}
void rtl::str::newReplaceAllFromIndex<_rtl_uString, char, char>(_rtl_uString**, _rtl_uString*, char const*, int, char const*, int, int)
Line
Count
Source
1297
8.51M
{
1298
8.51M
    assert(s != nullptr);
1299
8.51M
    assert(s1 != nullptr);
1300
8.51M
    assert(fromLength >= 0);
1301
8.51M
    assert(from != nullptr || fromLength == 0);
1302
8.51M
    assert(toLength >= 0);
1303
8.51M
    assert(to != nullptr || toLength == 0);
1304
8.51M
    assert(fromIndex >= 0 && fromIndex <= s1->length);
1305
8.51M
    sal_Int32 i = indexOfStr_WithLength(s1->buffer + fromIndex, s1->length - fromIndex,
1306
8.51M
                                        from, fromLength);
1307
8.51M
    if (i >= 0)
1308
154k
    {
1309
154k
        if (s1->length - fromLength > SAL_MAX_INT32 - toLength)
1310
0
            std::abort();
1311
154k
        i += fromIndex;
1312
154k
        sal_Int32 nCapacity = s1->length + (toLength - fromLength);
1313
154k
        if (fromLength < toLength)
1314
348
        {
1315
            // Pre-allocate up to 16 replacements more
1316
348
            const sal_Int32 nMaxMoreFinds = (s1->length - i - fromLength) / fromLength;
1317
348
            const sal_Int32 nIncrease = toLength - fromLength;
1318
348
            const sal_Int32 nMoreReplacements = std::min(
1319
348
                { nMaxMoreFinds, (SAL_MAX_INT32 - nCapacity) / nIncrease, sal_Int32(16) });
1320
348
            nCapacity += nMoreReplacements * nIncrease;
1321
348
        }
1322
154k
        const auto pOld = *s;
1323
154k
        *s = Alloc<S>(nCapacity);
1324
154k
        (*s)->length = 0;
1325
154k
        fromIndex = 0;
1326
154k
        do
1327
1.02M
        {
1328
1.02M
            stringbuffer_insert(s, &nCapacity, (*s)->length, s1->buffer + fromIndex, i);
1329
1.02M
            stringbuffer_insert(s, &nCapacity, (*s)->length, to, toLength);
1330
1.02M
            fromIndex += i + fromLength;
1331
1.02M
            i = indexOfStr_WithLength(s1->buffer + fromIndex, s1->length - fromIndex,
1332
1.02M
                                      from, fromLength);
1333
1.02M
        } while (i >= 0);
1334
        // the rest
1335
154k
        stringbuffer_insert(s, &nCapacity, (*s)->length,
1336
154k
                            s1->buffer + fromIndex, s1->length - fromIndex);
1337
154k
        if (pOld)
1338
0
            release(pOld); // Must be last in case *s == s1
1339
154k
    }
1340
8.35M
    else
1341
8.35M
        assign(s, s1);
1342
1343
8.51M
    RTL_LOG_STRING_NEW(*s);
1344
8.51M
}
void rtl::str::newReplaceAllFromIndex<_rtl_uString, char, char16_t>(_rtl_uString**, _rtl_uString*, char const*, int, char16_t const*, int, int)
Line
Count
Source
1297
1.05M
{
1298
1.05M
    assert(s != nullptr);
1299
1.05M
    assert(s1 != nullptr);
1300
1.05M
    assert(fromLength >= 0);
1301
1.05M
    assert(from != nullptr || fromLength == 0);
1302
1.05M
    assert(toLength >= 0);
1303
1.05M
    assert(to != nullptr || toLength == 0);
1304
1.05M
    assert(fromIndex >= 0 && fromIndex <= s1->length);
1305
1.05M
    sal_Int32 i = indexOfStr_WithLength(s1->buffer + fromIndex, s1->length - fromIndex,
1306
1.05M
                                        from, fromLength);
1307
1.05M
    if (i >= 0)
1308
993k
    {
1309
993k
        if (s1->length - fromLength > SAL_MAX_INT32 - toLength)
1310
0
            std::abort();
1311
993k
        i += fromIndex;
1312
993k
        sal_Int32 nCapacity = s1->length + (toLength - fromLength);
1313
993k
        if (fromLength < toLength)
1314
0
        {
1315
            // Pre-allocate up to 16 replacements more
1316
0
            const sal_Int32 nMaxMoreFinds = (s1->length - i - fromLength) / fromLength;
1317
0
            const sal_Int32 nIncrease = toLength - fromLength;
1318
0
            const sal_Int32 nMoreReplacements = std::min(
1319
0
                { nMaxMoreFinds, (SAL_MAX_INT32 - nCapacity) / nIncrease, sal_Int32(16) });
1320
0
            nCapacity += nMoreReplacements * nIncrease;
1321
0
        }
1322
993k
        const auto pOld = *s;
1323
993k
        *s = Alloc<S>(nCapacity);
1324
993k
        (*s)->length = 0;
1325
993k
        fromIndex = 0;
1326
993k
        do
1327
995k
        {
1328
995k
            stringbuffer_insert(s, &nCapacity, (*s)->length, s1->buffer + fromIndex, i);
1329
995k
            stringbuffer_insert(s, &nCapacity, (*s)->length, to, toLength);
1330
995k
            fromIndex += i + fromLength;
1331
995k
            i = indexOfStr_WithLength(s1->buffer + fromIndex, s1->length - fromIndex,
1332
995k
                                      from, fromLength);
1333
995k
        } while (i >= 0);
1334
        // the rest
1335
993k
        stringbuffer_insert(s, &nCapacity, (*s)->length,
1336
993k
                            s1->buffer + fromIndex, s1->length - fromIndex);
1337
993k
        if (pOld)
1338
0
            release(pOld); // Must be last in case *s == s1
1339
993k
    }
1340
66.4k
    else
1341
66.4k
        assign(s, s1);
1342
1343
1.05M
    RTL_LOG_STRING_NEW(*s);
1344
1.05M
}
void rtl::str::newReplaceAllFromIndex<_rtl_uString, char16_t, char>(_rtl_uString**, _rtl_uString*, char16_t const*, int, char const*, int, int)
Line
Count
Source
1297
4.71k
{
1298
4.71k
    assert(s != nullptr);
1299
4.71k
    assert(s1 != nullptr);
1300
4.71k
    assert(fromLength >= 0);
1301
4.71k
    assert(from != nullptr || fromLength == 0);
1302
4.71k
    assert(toLength >= 0);
1303
4.71k
    assert(to != nullptr || toLength == 0);
1304
4.71k
    assert(fromIndex >= 0 && fromIndex <= s1->length);
1305
4.71k
    sal_Int32 i = indexOfStr_WithLength(s1->buffer + fromIndex, s1->length - fromIndex,
1306
4.71k
                                        from, fromLength);
1307
4.71k
    if (i >= 0)
1308
0
    {
1309
0
        if (s1->length - fromLength > SAL_MAX_INT32 - toLength)
1310
0
            std::abort();
1311
0
        i += fromIndex;
1312
0
        sal_Int32 nCapacity = s1->length + (toLength - fromLength);
1313
0
        if (fromLength < toLength)
1314
0
        {
1315
            // Pre-allocate up to 16 replacements more
1316
0
            const sal_Int32 nMaxMoreFinds = (s1->length - i - fromLength) / fromLength;
1317
0
            const sal_Int32 nIncrease = toLength - fromLength;
1318
0
            const sal_Int32 nMoreReplacements = std::min(
1319
0
                { nMaxMoreFinds, (SAL_MAX_INT32 - nCapacity) / nIncrease, sal_Int32(16) });
1320
0
            nCapacity += nMoreReplacements * nIncrease;
1321
0
        }
1322
0
        const auto pOld = *s;
1323
0
        *s = Alloc<S>(nCapacity);
1324
0
        (*s)->length = 0;
1325
0
        fromIndex = 0;
1326
0
        do
1327
0
        {
1328
0
            stringbuffer_insert(s, &nCapacity, (*s)->length, s1->buffer + fromIndex, i);
1329
0
            stringbuffer_insert(s, &nCapacity, (*s)->length, to, toLength);
1330
0
            fromIndex += i + fromLength;
1331
0
            i = indexOfStr_WithLength(s1->buffer + fromIndex, s1->length - fromIndex,
1332
0
                                      from, fromLength);
1333
0
        } while (i >= 0);
1334
        // the rest
1335
0
        stringbuffer_insert(s, &nCapacity, (*s)->length,
1336
0
                            s1->buffer + fromIndex, s1->length - fromIndex);
1337
0
        if (pOld)
1338
0
            release(pOld); // Must be last in case *s == s1
1339
0
    }
1340
4.71k
    else
1341
4.71k
        assign(s, s1);
1342
1343
4.71k
    RTL_LOG_STRING_NEW(*s);
1344
4.71k
}
void rtl::str::newReplaceAllFromIndex<_rtl_uString, char16_t, char16_t>(_rtl_uString**, _rtl_uString*, char16_t const*, int, char16_t const*, int, int)
Line
Count
Source
1297
34.1M
{
1298
34.1M
    assert(s != nullptr);
1299
34.1M
    assert(s1 != nullptr);
1300
34.1M
    assert(fromLength >= 0);
1301
34.1M
    assert(from != nullptr || fromLength == 0);
1302
34.1M
    assert(toLength >= 0);
1303
34.1M
    assert(to != nullptr || toLength == 0);
1304
34.1M
    assert(fromIndex >= 0 && fromIndex <= s1->length);
1305
34.1M
    sal_Int32 i = indexOfStr_WithLength(s1->buffer + fromIndex, s1->length - fromIndex,
1306
34.1M
                                        from, fromLength);
1307
34.1M
    if (i >= 0)
1308
3.32M
    {
1309
3.32M
        if (s1->length - fromLength > SAL_MAX_INT32 - toLength)
1310
0
            std::abort();
1311
3.32M
        i += fromIndex;
1312
3.32M
        sal_Int32 nCapacity = s1->length + (toLength - fromLength);
1313
3.32M
        if (fromLength < toLength)
1314
123k
        {
1315
            // Pre-allocate up to 16 replacements more
1316
123k
            const sal_Int32 nMaxMoreFinds = (s1->length - i - fromLength) / fromLength;
1317
123k
            const sal_Int32 nIncrease = toLength - fromLength;
1318
123k
            const sal_Int32 nMoreReplacements = std::min(
1319
123k
                { nMaxMoreFinds, (SAL_MAX_INT32 - nCapacity) / nIncrease, sal_Int32(16) });
1320
123k
            nCapacity += nMoreReplacements * nIncrease;
1321
123k
        }
1322
3.32M
        const auto pOld = *s;
1323
3.32M
        *s = Alloc<S>(nCapacity);
1324
3.32M
        (*s)->length = 0;
1325
3.32M
        fromIndex = 0;
1326
3.32M
        do
1327
6.65M
        {
1328
6.65M
            stringbuffer_insert(s, &nCapacity, (*s)->length, s1->buffer + fromIndex, i);
1329
6.65M
            stringbuffer_insert(s, &nCapacity, (*s)->length, to, toLength);
1330
6.65M
            fromIndex += i + fromLength;
1331
6.65M
            i = indexOfStr_WithLength(s1->buffer + fromIndex, s1->length - fromIndex,
1332
6.65M
                                      from, fromLength);
1333
6.65M
        } while (i >= 0);
1334
        // the rest
1335
3.32M
        stringbuffer_insert(s, &nCapacity, (*s)->length,
1336
3.32M
                            s1->buffer + fromIndex, s1->length - fromIndex);
1337
3.32M
        if (pOld)
1338
0
            release(pOld); // Must be last in case *s == s1
1339
3.32M
    }
1340
30.8M
    else
1341
30.8M
        assign(s, s1);
1342
1343
34.1M
    RTL_LOG_STRING_NEW(*s);
1344
34.1M
}
1345
1346
template <class rtl_tString, typename C1, typename C2>
1347
void newReplaceFirst(rtl_tString** s, rtl_tString* s1, C1 const* from, sal_Int32 fromLength,
1348
                     C2 const* to, sal_Int32 toLength, sal_Int32& fromIndex)
1349
162k
{
1350
162k
    assert(s != nullptr);
1351
162k
    assert(s1 != nullptr);
1352
162k
    assert(fromLength >= 0);
1353
162k
    assert(from != nullptr || fromLength == 0);
1354
162k
    assert(toLength >= 0);
1355
162k
    assert(to != nullptr || toLength == 0);
1356
162k
    assert(fromIndex >= 0 && fromIndex <= s1->length);
1357
162k
    sal_Int32 i = indexOfStr_WithLength(s1->buffer + fromIndex, s1->length - fromIndex,
1358
162k
                                        from, fromLength);
1359
162k
    if (i >= 0)
1360
162k
    {
1361
162k
        if (s1->length - fromLength > SAL_MAX_INT32 - toLength)
1362
0
            std::abort();
1363
162k
        i += fromIndex;
1364
162k
        newReplaceStrAt(s, s1, i, fromLength, to, toLength);
1365
162k
    }
1366
0
    else
1367
0
        assign(s, s1);
1368
1369
162k
    fromIndex = i;
1370
162k
}
void rtl::str::newReplaceFirst<_rtl_uString, char, char>(_rtl_uString**, _rtl_uString*, char const*, int, char const*, int, int&)
Line
Count
Source
1349
1.37k
{
1350
1.37k
    assert(s != nullptr);
1351
1.37k
    assert(s1 != nullptr);
1352
1.37k
    assert(fromLength >= 0);
1353
1.37k
    assert(from != nullptr || fromLength == 0);
1354
1.37k
    assert(toLength >= 0);
1355
1.37k
    assert(to != nullptr || toLength == 0);
1356
1.37k
    assert(fromIndex >= 0 && fromIndex <= s1->length);
1357
1.37k
    sal_Int32 i = indexOfStr_WithLength(s1->buffer + fromIndex, s1->length - fromIndex,
1358
1.37k
                                        from, fromLength);
1359
1.37k
    if (i >= 0)
1360
1.37k
    {
1361
1.37k
        if (s1->length - fromLength > SAL_MAX_INT32 - toLength)
1362
0
            std::abort();
1363
1.37k
        i += fromIndex;
1364
1.37k
        newReplaceStrAt(s, s1, i, fromLength, to, toLength);
1365
1.37k
    }
1366
0
    else
1367
0
        assign(s, s1);
1368
1369
1.37k
    fromIndex = i;
1370
1.37k
}
void rtl::str::newReplaceFirst<_rtl_uString, char, char16_t>(_rtl_uString**, _rtl_uString*, char const*, int, char16_t const*, int, int&)
Line
Count
Source
1349
161k
{
1350
161k
    assert(s != nullptr);
1351
161k
    assert(s1 != nullptr);
1352
161k
    assert(fromLength >= 0);
1353
161k
    assert(from != nullptr || fromLength == 0);
1354
161k
    assert(toLength >= 0);
1355
161k
    assert(to != nullptr || toLength == 0);
1356
161k
    assert(fromIndex >= 0 && fromIndex <= s1->length);
1357
161k
    sal_Int32 i = indexOfStr_WithLength(s1->buffer + fromIndex, s1->length - fromIndex,
1358
161k
                                        from, fromLength);
1359
161k
    if (i >= 0)
1360
161k
    {
1361
161k
        if (s1->length - fromLength > SAL_MAX_INT32 - toLength)
1362
0
            std::abort();
1363
161k
        i += fromIndex;
1364
161k
        newReplaceStrAt(s, s1, i, fromLength, to, toLength);
1365
161k
    }
1366
0
    else
1367
0
        assign(s, s1);
1368
1369
161k
    fromIndex = i;
1370
161k
}
Unexecuted instantiation: void rtl::str::newReplaceFirst<_rtl_uString, char16_t, char>(_rtl_uString**, _rtl_uString*, char16_t const*, int, char const*, int, int&)
Unexecuted instantiation: void rtl::str::newReplaceFirst<_rtl_uString, char16_t, char16_t>(_rtl_uString**, _rtl_uString*, char16_t const*, int, char16_t const*, int, int&)
1371
1372
// doubleToString implementation
1373
1374
static inline constexpr sal_uInt64 eX[] = { 10ull,
1375
                                            100ull,
1376
                                            1000ull,
1377
                                            10000ull,
1378
                                            100000ull,
1379
                                            1000000ull,
1380
                                            10000000ull,
1381
                                            100000000ull,
1382
                                            1000000000ull,
1383
                                            10000000000ull,
1384
                                            100000000000ull,
1385
                                            1000000000000ull,
1386
                                            10000000000000ull,
1387
                                            100000000000000ull,
1388
                                            1000000000000000ull,
1389
                                            10000000000000000ull,
1390
                                            100000000000000000ull,
1391
                                            1000000000000000000ull,
1392
                                            10000000000000000000ull };
1393
1394
template <typename rtl_tString>
1395
void doubleToString(rtl_tString** pResult, sal_Int32* pResultCapacity, sal_Int32 nResultOffset,
1396
                    double fValue, rtl_math_StringFormat eFormat, sal_Int32 nDecPlaces,
1397
                    Char_T<rtl_tString> cDecSeparator, sal_Int32 const* pGroups,
1398
                    Char_T<rtl_tString> cGroupSeparator, bool bEraseTrailingDecZeros)
1399
18.7M
{
1400
18.7M
    auto decimalDigits = [](sal_uInt64 n) {
1401
18.7M
        return std::distance(std::begin(eX), std::upper_bound(std::begin(eX), std::end(eX), n)) + 1;
1402
18.7M
    };
_ZZN3rtl3str14doubleToStringI11_rtl_StringEEvPPT_Piid21rtl_math_StringFormatiu15__remove_extentIDtsrS3_6bufferEEPKiS9_bENKUlmE_clEm
Line
Count
Source
1400
1.51M
    auto decimalDigits = [](sal_uInt64 n) {
1401
1.51M
        return std::distance(std::begin(eX), std::upper_bound(std::begin(eX), std::end(eX), n)) + 1;
1402
1.51M
    };
_ZZN3rtl3str14doubleToStringI12_rtl_uStringEEvPPT_Piid21rtl_math_StringFormatiu15__remove_extentIDtsrS3_6bufferEEPKiS9_bENKUlmE_clEm
Line
Count
Source
1400
17.2M
    auto decimalDigits = [](sal_uInt64 n) {
1401
17.2M
        return std::distance(std::begin(eX), std::upper_bound(std::begin(eX), std::end(eX), n)) + 1;
1402
17.2M
    };
1403
1404
18.7M
    auto roundToPow10 = [](sal_uInt64 n, int e) {
1405
16.4M
        assert(e > 0 && o3tl::make_unsigned(e) <= std::size(eX));
1406
16.4M
        const sal_uInt64 d = eX[e - 1];
1407
16.4M
        return (n + d / 2) / d * d;
1408
16.4M
    };
_ZZN3rtl3str14doubleToStringI11_rtl_StringEEvPPT_Piid21rtl_math_StringFormatiu15__remove_extentIDtsrS3_6bufferEEPKiS9_bENKUlmiE_clEmi
Line
Count
Source
1404
349k
    auto roundToPow10 = [](sal_uInt64 n, int e) {
1405
        assert(e > 0 && o3tl::make_unsigned(e) <= std::size(eX));
1406
349k
        const sal_uInt64 d = eX[e - 1];
1407
349k
        return (n + d / 2) / d * d;
1408
349k
    };
_ZZN3rtl3str14doubleToStringI12_rtl_uStringEEvPPT_Piid21rtl_math_StringFormatiu15__remove_extentIDtsrS3_6bufferEEPKiS9_bENKUlmiE_clEmi
Line
Count
Source
1404
16.0M
    auto roundToPow10 = [](sal_uInt64 n, int e) {
1405
        assert(e > 0 && o3tl::make_unsigned(e) <= std::size(eX));
1406
16.0M
        const sal_uInt64 d = eX[e - 1];
1407
16.0M
        return (n + d / 2) / d * d;
1408
16.0M
    };
1409
1410
18.7M
    auto append = [](rtl_tString** s, sal_Int32* pCapacity, sal_Int32 rOffset, auto sv)
1411
18.7M
    {
1412
18.7M
        if (!pCapacity)
1413
17.0M
            newFromStr_WithLength(s, sv.data(), sv.size());
1414
1.64M
        else
1415
1.64M
            stringbuffer_insert(s, pCapacity, rOffset, sv.data(), sv.size());
1416
18.7M
    };
_ZZN3rtl3str14doubleToStringI11_rtl_StringEEvPPT_Piid21rtl_math_StringFormatiu15__remove_extentIDtsrS3_6bufferEEPKiS9_bENKUlPPS2_S6_iS3_E_clINSt3__117basic_string_viewIcNSG_11char_traitsIcEEEEEEDaSD_S6_iS3_
Line
Count
Source
1411
1.51M
    {
1412
1.51M
        if (!pCapacity)
1413
121k
            newFromStr_WithLength(s, sv.data(), sv.size());
1414
1.39M
        else
1415
1.39M
            stringbuffer_insert(s, pCapacity, rOffset, sv.data(), sv.size());
1416
1.51M
    };
_ZZN3rtl3str14doubleToStringI12_rtl_uStringEEvPPT_Piid21rtl_math_StringFormatiu15__remove_extentIDtsrS3_6bufferEEPKiS9_bENKUlPPS2_S6_iS3_E_clINSt3__117basic_string_viewIcNSG_11char_traitsIcEEEEEEDaSD_S6_iS3_
Line
Count
Source
1411
2.12k
    {
1412
2.12k
        if (!pCapacity)
1413
1.84k
            newFromStr_WithLength(s, sv.data(), sv.size());
1414
286
        else
1415
286
            stringbuffer_insert(s, pCapacity, rOffset, sv.data(), sv.size());
1416
2.12k
    };
_ZZN3rtl3str14doubleToStringI12_rtl_uStringEEvPPT_Piid21rtl_math_StringFormatiu15__remove_extentIDtsrS3_6bufferEEPKiS9_bENKUlPPS2_S6_iS3_E_clINSt3__117basic_string_viewIDsNSG_11char_traitsIDsEEEEEEDaSD_S6_iS3_
Line
Count
Source
1411
17.2M
    {
1412
17.2M
        if (!pCapacity)
1413
16.9M
            newFromStr_WithLength(s, sv.data(), sv.size());
1414
252k
        else
1415
252k
            stringbuffer_insert(s, pCapacity, rOffset, sv.data(), sv.size());
1416
17.2M
    };
1417
1418
18.7M
    if (std::isnan(fValue))
1419
1.81k
    {
1420
        // #i112652# XMLSchema-2
1421
1.81k
        static constexpr std::string_view nan{ "NaN" };
1422
1.81k
        return append(pResult, pResultCapacity, nResultOffset, nan);
1423
1.81k
    }
1424
1425
    // sign adjustment, instead of testing for fValue<0.0 this will also fetch -0.0
1426
18.7M
    bool bSign = std::signbit(fValue);
1427
1428
18.7M
    if (std::isinf(fValue))
1429
307
    {
1430
        // #i112652# XMLSchema-2
1431
307
        std::string_view inf = bSign ? std::string_view("-INF") : std::string_view("INF");
1432
307
        return append(pResult, pResultCapacity, nResultOffset, inf);
1433
307
    }
1434
1435
18.7M
    if (bSign)
1436
337k
        fValue = -fValue;
1437
1438
18.7M
    decltype(jkj::dragonbox::to_decimal(fValue, jkj::dragonbox::policy::sign::ignore,
1439
18.7M
                                        jkj::dragonbox::policy::trailing_zero::ignore)) aParts{};
1440
18.7M
    if (fValue) // to_decimal is documented to only handle non-zero finite numbers
1441
17.0M
        aParts = jkj::dragonbox::to_decimal(fValue, jkj::dragonbox::policy::sign::ignore,
1442
17.0M
                                            jkj::dragonbox::policy::trailing_zero::ignore);
1443
1444
18.7M
    int nOrigDigits = decimalDigits(aParts.significand);
1445
18.7M
    int nExp = nOrigDigits + aParts.exponent - 1;
1446
18.7M
    int nRoundDigits = 15;
1447
1448
    // Unfortunately the old rounding below writes 1.79769313486232e+308 for
1449
    // DBL_MAX and 4 subsequent nextafter(...,0).
1450
18.7M
    static const double fB1 = std::nextafter(std::numeric_limits<double>::max(), 0);
1451
18.7M
    static const double fB2 = std::nextafter(fB1, 0);
1452
18.7M
    static const double fB3 = std::nextafter(fB2, 0);
1453
18.7M
    static const double fB4 = std::nextafter(fB3, 0);
1454
18.7M
    if ((fValue >= fB4) && eFormat != rtl_math_StringFormat_F)
1455
591
    {
1456
        // 1.7976931348623157e+308 instead of rounded 1.79769313486232e+308
1457
        // that can't be converted back as out of range. For rounded values if
1458
        // they exceed range they should not be written to exchange strings or
1459
        // file formats.
1460
1461
591
        eFormat = rtl_math_StringFormat_E;
1462
591
        nDecPlaces = std::clamp<sal_Int32>(nDecPlaces, 0, 16);
1463
591
        nRoundDigits = 17;
1464
591
    }
1465
1466
    // Use integer representation for integer values that fit into the
1467
    // mantissa (1.((2^53)-1)) with a precision of 1 for highest accuracy.
1468
18.7M
    if ((eFormat == rtl_math_StringFormat_Automatic || eFormat == rtl_math_StringFormat_F)
1469
1.91M
        && aParts.exponent >= 0 && fValue < 0x1p53)
1470
1.13M
    {
1471
1.13M
        eFormat = rtl_math_StringFormat_F;
1472
1.13M
        if (nDecPlaces == rtl_math_DecimalPlaces_Max)
1473
27.6k
            nDecPlaces = 0;
1474
1.11M
        else
1475
1.11M
            nDecPlaces = std::clamp<sal_Int32>(nDecPlaces, -15, 15);
1476
1477
1.13M
        if (bEraseTrailingDecZeros && nDecPlaces > 0)
1478
1.10M
            nDecPlaces = 0;
1479
1480
1.13M
        nRoundDigits = nOrigDigits; // no rounding
1481
1.13M
    }
1482
1483
18.7M
    switch (eFormat)
1484
18.7M
    {
1485
408k
        case rtl_math_StringFormat_Automatic:
1486
            // E or F depending on exponent magnitude
1487
408k
            if (nExp <= -15 || nExp >= 15)
1488
11.6k
            {
1489
11.6k
                if (nDecPlaces == rtl_math_DecimalPlaces_Max)
1490
11.6k
                    nDecPlaces = 14;
1491
11.6k
                eFormat = rtl_math_StringFormat_E;
1492
11.6k
            }
1493
396k
            else
1494
396k
            {
1495
396k
                if (nDecPlaces == rtl_math_DecimalPlaces_Max)
1496
396k
                    nDecPlaces = (nExp < 14) ? 15 - nExp - 1 : 15;
1497
396k
                eFormat = rtl_math_StringFormat_F;
1498
396k
            }
1499
408k
            break;
1500
1501
16.8M
        case rtl_math_StringFormat_G:
1502
16.8M
        case rtl_math_StringFormat_G1:
1503
16.8M
        case rtl_math_StringFormat_G2:
1504
            // G-Point, similar to sprintf %G
1505
16.8M
            if (nDecPlaces == rtl_math_DecimalPlaces_DefaultSignificance)
1506
0
                nDecPlaces = 6;
1507
1508
16.8M
            if (nExp < -4 || nExp >= nDecPlaces)
1509
47.1k
            {
1510
47.1k
                nDecPlaces = std::max<sal_Int32>(1, nDecPlaces - 1);
1511
1512
47.1k
                if (eFormat == rtl_math_StringFormat_G)
1513
47.1k
                    eFormat = rtl_math_StringFormat_E;
1514
0
                else if (eFormat == rtl_math_StringFormat_G2)
1515
0
                    eFormat = rtl_math_StringFormat_E2;
1516
0
                else if (eFormat == rtl_math_StringFormat_G1)
1517
0
                    eFormat = rtl_math_StringFormat_E1;
1518
47.1k
            }
1519
16.7M
            else
1520
16.7M
            {
1521
16.7M
                if (nOrigDigits <= nDecPlaces && aParts.exponent >= 0 && fValue < 0x1p53)
1522
579k
                {
1523
                    // Use integer representation with highest accuracy.
1524
579k
                    nRoundDigits = nOrigDigits; // no rounding
1525
579k
                }
1526
16.7M
                nDecPlaces = std::max<sal_Int32>(0, nDecPlaces - nExp - 1);
1527
16.7M
                eFormat = rtl_math_StringFormat_F;
1528
16.7M
            }
1529
16.8M
            break;
1530
1531
1.51M
        default:
1532
1.51M
            break;
1533
18.7M
    }
1534
1535
    // Too large values for nDecPlaces make no sense; it might also be
1536
    // rtl_math_DecimalPlaces_Max was passed with rtl_math_StringFormat_F or
1537
    // others, but we don't want to allocate/deallocate 2GB just to fill it
1538
    // with trailing '0' characters..
1539
18.7M
    nDecPlaces = std::clamp<sal_Int32>(nDecPlaces, -309, 309);
1540
1541
18.7M
    sal_Int32 nDigits = nDecPlaces + 1;
1542
1543
18.7M
    if (eFormat == rtl_math_StringFormat_F)
1544
18.6M
        nDigits += nExp;
1545
1546
    // Round the number
1547
18.7M
    nRoundDigits = std::min<int>(nDigits, nRoundDigits);
1548
18.7M
    if (nDigits >= 0 && nOrigDigits > nRoundDigits)
1549
16.4M
    {
1550
16.4M
        aParts.significand = roundToPow10(aParts.significand, nOrigDigits - nRoundDigits);
1551
16.4M
        assert(aParts.significand <= eX[nOrigDigits - 1]);
1552
16.4M
        if (aParts.significand == eX[nOrigDigits - 1]) // up-rounding to the next decade
1553
670
        {
1554
670
            nOrigDigits++;
1555
670
            nExp++;
1556
1557
670
            if (eFormat == rtl_math_StringFormat_F)
1558
314
                nDigits++;
1559
670
        }
1560
16.4M
    }
1561
1562
18.7M
    sal_Int32 nBuf
1563
18.7M
        = (nDigits <= 0 ? std::max<sal_Int32>(nDecPlaces, std::abs(nExp)) : nDigits + nDecPlaces)
1564
18.7M
          + 10 + (pGroups ? std::abs(nDigits) * 2 : 0);
1565
    // max(nDigits) = max(nDecPlaces) + 1 + max(nExp) + 1 = 309 + 1 + 308 + 1 = 619
1566
    // max(nBuf) = max(nDigits) + max(nDecPlaces) + 10 + max(nDigits) * 2 = 619 * 3 + 309 + 10 = 2176
1567
18.7M
    assert(nBuf <= 2176);
1568
18.7M
    auto* const pBuf = static_cast<Char_T<rtl_tString>*>(alloca(nBuf * sizeof(Char_T<rtl_tString>)));
1569
18.7M
    auto* p = pBuf;
1570
18.7M
    if (bSign)
1571
337k
        *p++ = '-';
1572
1573
18.7M
    bool bHasDec = false;
1574
1575
18.7M
    int nDecPos;
1576
    // Check for F format and number < 1
1577
18.7M
    if (eFormat == rtl_math_StringFormat_F)
1578
18.6M
    {
1579
18.6M
        if (nExp < 0)
1580
5.34M
        {
1581
5.34M
            *p++ = '0';
1582
5.34M
            if (nDecPlaces > 0)
1583
5.34M
            {
1584
5.34M
                *p++ = cDecSeparator;
1585
5.34M
                bHasDec = true;
1586
5.34M
            }
1587
1588
5.34M
            sal_Int32 i = (nDigits <= 0 ? nDecPlaces : -nExp - 1);
1589
1590
9.95M
            while ((i--) > 0)
1591
4.61M
                *p++ = '0';
1592
1593
5.34M
            nDecPos = 0;
1594
5.34M
        }
1595
13.3M
        else
1596
13.3M
            nDecPos = nExp + 1;
1597
18.6M
    }
1598
64.1k
    else
1599
64.1k
        nDecPos = 1;
1600
1601
18.7M
    int nGrouping = 0, nGroupSelector = 0, nGroupExceed = 0;
1602
18.7M
    if (nDecPos > 1 && pGroups && pGroups[0] && cGroupSeparator)
1603
0
    {
1604
0
        while (nGrouping + pGroups[nGroupSelector] < nDecPos)
1605
0
        {
1606
0
            nGrouping += pGroups[nGroupSelector];
1607
0
            if (pGroups[nGroupSelector + 1])
1608
0
            {
1609
0
                if (nGrouping + pGroups[nGroupSelector + 1] >= nDecPos)
1610
0
                    break; // while
1611
1612
0
                ++nGroupSelector;
1613
0
            }
1614
0
            else if (!nGroupExceed)
1615
0
                nGroupExceed = nGrouping;
1616
0
        }
1617
0
    }
1618
1619
    // print the number
1620
18.7M
    if (nDigits > 0)
1621
18.7M
    {
1622
18.7M
        for (int nCurExp = nOrigDigits - 1;;)
1623
298M
        {
1624
298M
            int nDigit;
1625
298M
            if (aParts.significand > 0 && nCurExp > 0)
1626
218M
            {
1627
218M
                --nCurExp;
1628
218M
                nDigit = aParts.significand / eX[nCurExp];
1629
218M
                aParts.significand %= eX[nCurExp];
1630
218M
            }
1631
80.0M
            else
1632
80.0M
            {
1633
80.0M
                nDigit = aParts.significand;
1634
80.0M
                aParts.significand = 0;
1635
80.0M
            }
1636
298M
            assert(nDigit >= 0 && nDigit < 10);
1637
298M
            *p++ = nDigit + '0';
1638
1639
298M
            if (!--nDigits)
1640
18.7M
                break; // for
1641
1642
279M
            if (nDecPos)
1643
22.7M
            {
1644
22.7M
                if (!--nDecPos)
1645
12.2M
                {
1646
12.2M
                    *p++ = cDecSeparator;
1647
12.2M
                    bHasDec = true;
1648
12.2M
                }
1649
10.5M
                else if (nDecPos == nGrouping)
1650
0
                {
1651
0
                    *p++ = cGroupSeparator;
1652
0
                    nGrouping -= pGroups[nGroupSelector];
1653
1654
0
                    if (nGroupSelector && nGrouping < nGroupExceed)
1655
0
                        --nGroupSelector;
1656
0
                }
1657
22.7M
            }
1658
279M
        }
1659
18.7M
    }
1660
1661
18.7M
    if (!bHasDec && eFormat == rtl_math_StringFormat_F)
1662
1.17M
    { // nDecPlaces < 0 did round the value
1663
1.17M
        while (--nDecPos > 0)
1664
0
        { // fill before decimal point
1665
0
            if (nDecPos == nGrouping)
1666
0
            {
1667
0
                *p++ = cGroupSeparator;
1668
0
                nGrouping -= pGroups[nGroupSelector];
1669
1670
0
                if (nGroupSelector && nGrouping < nGroupExceed)
1671
0
                    --nGroupSelector;
1672
0
            }
1673
1674
0
            *p++ = '0';
1675
0
        }
1676
1.17M
    }
1677
1678
18.7M
    if (bEraseTrailingDecZeros && bHasDec)
1679
17.5M
    {
1680
95.5M
        while (*(p - 1) == '0')
1681
77.9M
            p--;
1682
1683
17.5M
        if (*(p - 1) == cDecSeparator)
1684
1.12M
            p--;
1685
17.5M
    }
1686
1687
    // Print the exponent ('E', followed by '+' or '-', followed by exactly
1688
    // three digits for rtl_math_StringFormat_E). The code in
1689
    // rtl_[u]str_valueOf{Float|Double} relies on this format.
1690
18.7M
    if (eFormat == rtl_math_StringFormat_E || eFormat == rtl_math_StringFormat_E2
1691
18.6M
        || eFormat == rtl_math_StringFormat_E1)
1692
64.1k
    {
1693
64.1k
        if (p == pBuf)
1694
0
            *p++ = '1';
1695
        // maybe no nDigits if nDecPlaces < 0
1696
1697
64.1k
        *p++ = 'E';
1698
64.1k
        if (nExp < 0)
1699
39.9k
        {
1700
39.9k
            nExp = -nExp;
1701
39.9k
            *p++ = '-';
1702
39.9k
        }
1703
24.2k
        else
1704
24.2k
            *p++ = '+';
1705
1706
64.1k
        if (eFormat == rtl_math_StringFormat_E || nExp >= 100)
1707
63.9k
            *p++ = nExp / 100 + '0';
1708
1709
64.1k
        nExp %= 100;
1710
1711
64.1k
        if (eFormat == rtl_math_StringFormat_E || eFormat == rtl_math_StringFormat_E2 || nExp >= 10)
1712
64.1k
            *p++ = nExp / 10 + '0';
1713
1714
64.1k
        *p++ = nExp % 10 + '0';
1715
64.1k
    }
1716
1717
18.7M
    append(pResult, pResultCapacity, nResultOffset, std::basic_string_view(pBuf, p - pBuf));
1718
18.7M
}
_ZN3rtl3str14doubleToStringI11_rtl_StringEEvPPT_Piid21rtl_math_StringFormatiu15__remove_extentIDtsrS3_6bufferEEPKiS9_b
Line
Count
Source
1399
1.51M
{
1400
1.51M
    auto decimalDigits = [](sal_uInt64 n) {
1401
1.51M
        return std::distance(std::begin(eX), std::upper_bound(std::begin(eX), std::end(eX), n)) + 1;
1402
1.51M
    };
1403
1404
1.51M
    auto roundToPow10 = [](sal_uInt64 n, int e) {
1405
1.51M
        assert(e > 0 && o3tl::make_unsigned(e) <= std::size(eX));
1406
1.51M
        const sal_uInt64 d = eX[e - 1];
1407
1.51M
        return (n + d / 2) / d * d;
1408
1.51M
    };
1409
1410
1.51M
    auto append = [](rtl_tString** s, sal_Int32* pCapacity, sal_Int32 rOffset, auto sv)
1411
1.51M
    {
1412
1.51M
        if (!pCapacity)
1413
1.51M
            newFromStr_WithLength(s, sv.data(), sv.size());
1414
1.51M
        else
1415
1.51M
            stringbuffer_insert(s, pCapacity, rOffset, sv.data(), sv.size());
1416
1.51M
    };
1417
1418
1.51M
    if (std::isnan(fValue))
1419
0
    {
1420
        // #i112652# XMLSchema-2
1421
0
        static constexpr std::string_view nan{ "NaN" };
1422
0
        return append(pResult, pResultCapacity, nResultOffset, nan);
1423
0
    }
1424
1425
    // sign adjustment, instead of testing for fValue<0.0 this will also fetch -0.0
1426
1.51M
    bool bSign = std::signbit(fValue);
1427
1428
1.51M
    if (std::isinf(fValue))
1429
0
    {
1430
        // #i112652# XMLSchema-2
1431
0
        std::string_view inf = bSign ? std::string_view("-INF") : std::string_view("INF");
1432
0
        return append(pResult, pResultCapacity, nResultOffset, inf);
1433
0
    }
1434
1435
1.51M
    if (bSign)
1436
0
        fValue = -fValue;
1437
1438
1.51M
    decltype(jkj::dragonbox::to_decimal(fValue, jkj::dragonbox::policy::sign::ignore,
1439
1.51M
                                        jkj::dragonbox::policy::trailing_zero::ignore)) aParts{};
1440
1.51M
    if (fValue) // to_decimal is documented to only handle non-zero finite numbers
1441
410k
        aParts = jkj::dragonbox::to_decimal(fValue, jkj::dragonbox::policy::sign::ignore,
1442
410k
                                            jkj::dragonbox::policy::trailing_zero::ignore);
1443
1444
1.51M
    int nOrigDigits = decimalDigits(aParts.significand);
1445
1.51M
    int nExp = nOrigDigits + aParts.exponent - 1;
1446
1.51M
    int nRoundDigits = 15;
1447
1448
    // Unfortunately the old rounding below writes 1.79769313486232e+308 for
1449
    // DBL_MAX and 4 subsequent nextafter(...,0).
1450
1.51M
    static const double fB1 = std::nextafter(std::numeric_limits<double>::max(), 0);
1451
1.51M
    static const double fB2 = std::nextafter(fB1, 0);
1452
1.51M
    static const double fB3 = std::nextafter(fB2, 0);
1453
1.51M
    static const double fB4 = std::nextafter(fB3, 0);
1454
1.51M
    if ((fValue >= fB4) && eFormat != rtl_math_StringFormat_F)
1455
0
    {
1456
        // 1.7976931348623157e+308 instead of rounded 1.79769313486232e+308
1457
        // that can't be converted back as out of range. For rounded values if
1458
        // they exceed range they should not be written to exchange strings or
1459
        // file formats.
1460
1461
0
        eFormat = rtl_math_StringFormat_E;
1462
0
        nDecPlaces = std::clamp<sal_Int32>(nDecPlaces, 0, 16);
1463
0
        nRoundDigits = 17;
1464
0
    }
1465
1466
    // Use integer representation for integer values that fit into the
1467
    // mantissa (1.((2^53)-1)) with a precision of 1 for highest accuracy.
1468
1.51M
    if ((eFormat == rtl_math_StringFormat_Automatic || eFormat == rtl_math_StringFormat_F)
1469
1.39M
        && aParts.exponent >= 0 && fValue < 0x1p53)
1470
1.10M
    {
1471
1.10M
        eFormat = rtl_math_StringFormat_F;
1472
1.10M
        if (nDecPlaces == rtl_math_DecimalPlaces_Max)
1473
0
            nDecPlaces = 0;
1474
1.10M
        else
1475
1.10M
            nDecPlaces = std::clamp<sal_Int32>(nDecPlaces, -15, 15);
1476
1477
1.10M
        if (bEraseTrailingDecZeros && nDecPlaces > 0)
1478
1.10M
            nDecPlaces = 0;
1479
1480
1.10M
        nRoundDigits = nOrigDigits; // no rounding
1481
1.10M
    }
1482
1483
1.51M
    switch (eFormat)
1484
1.51M
    {
1485
0
        case rtl_math_StringFormat_Automatic:
1486
            // E or F depending on exponent magnitude
1487
0
            if (nExp <= -15 || nExp >= 15)
1488
0
            {
1489
0
                if (nDecPlaces == rtl_math_DecimalPlaces_Max)
1490
0
                    nDecPlaces = 14;
1491
0
                eFormat = rtl_math_StringFormat_E;
1492
0
            }
1493
0
            else
1494
0
            {
1495
0
                if (nDecPlaces == rtl_math_DecimalPlaces_Max)
1496
0
                    nDecPlaces = (nExp < 14) ? 15 - nExp - 1 : 15;
1497
0
                eFormat = rtl_math_StringFormat_F;
1498
0
            }
1499
0
            break;
1500
1501
121k
        case rtl_math_StringFormat_G:
1502
121k
        case rtl_math_StringFormat_G1:
1503
121k
        case rtl_math_StringFormat_G2:
1504
            // G-Point, similar to sprintf %G
1505
121k
            if (nDecPlaces == rtl_math_DecimalPlaces_DefaultSignificance)
1506
0
                nDecPlaces = 6;
1507
1508
121k
            if (nExp < -4 || nExp >= nDecPlaces)
1509
0
            {
1510
0
                nDecPlaces = std::max<sal_Int32>(1, nDecPlaces - 1);
1511
1512
0
                if (eFormat == rtl_math_StringFormat_G)
1513
0
                    eFormat = rtl_math_StringFormat_E;
1514
0
                else if (eFormat == rtl_math_StringFormat_G2)
1515
0
                    eFormat = rtl_math_StringFormat_E2;
1516
0
                else if (eFormat == rtl_math_StringFormat_G1)
1517
0
                    eFormat = rtl_math_StringFormat_E1;
1518
0
            }
1519
121k
            else
1520
121k
            {
1521
121k
                if (nOrigDigits <= nDecPlaces && aParts.exponent >= 0 && fValue < 0x1p53)
1522
0
                {
1523
                    // Use integer representation with highest accuracy.
1524
0
                    nRoundDigits = nOrigDigits; // no rounding
1525
0
                }
1526
121k
                nDecPlaces = std::max<sal_Int32>(0, nDecPlaces - nExp - 1);
1527
121k
                eFormat = rtl_math_StringFormat_F;
1528
121k
            }
1529
121k
            break;
1530
1531
1.39M
        default:
1532
1.39M
            break;
1533
1.51M
    }
1534
1535
    // Too large values for nDecPlaces make no sense; it might also be
1536
    // rtl_math_DecimalPlaces_Max was passed with rtl_math_StringFormat_F or
1537
    // others, but we don't want to allocate/deallocate 2GB just to fill it
1538
    // with trailing '0' characters..
1539
1.51M
    nDecPlaces = std::clamp<sal_Int32>(nDecPlaces, -309, 309);
1540
1541
1.51M
    sal_Int32 nDigits = nDecPlaces + 1;
1542
1543
1.51M
    if (eFormat == rtl_math_StringFormat_F)
1544
1.51M
        nDigits += nExp;
1545
1546
    // Round the number
1547
1.51M
    nRoundDigits = std::min<int>(nDigits, nRoundDigits);
1548
1.51M
    if (nDigits >= 0 && nOrigDigits > nRoundDigits)
1549
349k
    {
1550
349k
        aParts.significand = roundToPow10(aParts.significand, nOrigDigits - nRoundDigits);
1551
349k
        assert(aParts.significand <= eX[nOrigDigits - 1]);
1552
349k
        if (aParts.significand == eX[nOrigDigits - 1]) // up-rounding to the next decade
1553
0
        {
1554
0
            nOrigDigits++;
1555
0
            nExp++;
1556
1557
0
            if (eFormat == rtl_math_StringFormat_F)
1558
0
                nDigits++;
1559
0
        }
1560
349k
    }
1561
1562
1.51M
    sal_Int32 nBuf
1563
1.51M
        = (nDigits <= 0 ? std::max<sal_Int32>(nDecPlaces, std::abs(nExp)) : nDigits + nDecPlaces)
1564
1.51M
          + 10 + (pGroups ? std::abs(nDigits) * 2 : 0);
1565
    // max(nDigits) = max(nDecPlaces) + 1 + max(nExp) + 1 = 309 + 1 + 308 + 1 = 619
1566
    // max(nBuf) = max(nDigits) + max(nDecPlaces) + 10 + max(nDigits) * 2 = 619 * 3 + 309 + 10 = 2176
1567
1.51M
    assert(nBuf <= 2176);
1568
1.51M
    auto* const pBuf = static_cast<Char_T<rtl_tString>*>(alloca(nBuf * sizeof(Char_T<rtl_tString>)));
1569
1.51M
    auto* p = pBuf;
1570
1.51M
    if (bSign)
1571
0
        *p++ = '-';
1572
1573
1.51M
    bool bHasDec = false;
1574
1575
1.51M
    int nDecPos;
1576
    // Check for F format and number < 1
1577
1.51M
    if (eFormat == rtl_math_StringFormat_F)
1578
1.51M
    {
1579
1.51M
        if (nExp < 0)
1580
127k
        {
1581
127k
            *p++ = '0';
1582
127k
            if (nDecPlaces > 0)
1583
127k
            {
1584
127k
                *p++ = cDecSeparator;
1585
127k
                bHasDec = true;
1586
127k
            }
1587
1588
127k
            sal_Int32 i = (nDigits <= 0 ? nDecPlaces : -nExp - 1);
1589
1590
190k
            while ((i--) > 0)
1591
62.6k
                *p++ = '0';
1592
1593
127k
            nDecPos = 0;
1594
127k
        }
1595
1.38M
        else
1596
1.38M
            nDecPos = nExp + 1;
1597
1.51M
    }
1598
0
    else
1599
0
        nDecPos = 1;
1600
1601
1.51M
    int nGrouping = 0, nGroupSelector = 0, nGroupExceed = 0;
1602
1.51M
    if (nDecPos > 1 && pGroups && pGroups[0] && cGroupSeparator)
1603
0
    {
1604
0
        while (nGrouping + pGroups[nGroupSelector] < nDecPos)
1605
0
        {
1606
0
            nGrouping += pGroups[nGroupSelector];
1607
0
            if (pGroups[nGroupSelector + 1])
1608
0
            {
1609
0
                if (nGrouping + pGroups[nGroupSelector + 1] >= nDecPos)
1610
0
                    break; // while
1611
1612
0
                ++nGroupSelector;
1613
0
            }
1614
0
            else if (!nGroupExceed)
1615
0
                nGroupExceed = nGrouping;
1616
0
        }
1617
0
    }
1618
1619
    // print the number
1620
1.51M
    if (nDigits > 0)
1621
1.51M
    {
1622
1.51M
        for (int nCurExp = nOrigDigits - 1;;)
1623
5.10M
        {
1624
5.10M
            int nDigit;
1625
5.10M
            if (aParts.significand > 0 && nCurExp > 0)
1626
2.72M
            {
1627
2.72M
                --nCurExp;
1628
2.72M
                nDigit = aParts.significand / eX[nCurExp];
1629
2.72M
                aParts.significand %= eX[nCurExp];
1630
2.72M
            }
1631
2.37M
            else
1632
2.37M
            {
1633
2.37M
                nDigit = aParts.significand;
1634
2.37M
                aParts.significand = 0;
1635
2.37M
            }
1636
5.10M
            assert(nDigit >= 0 && nDigit < 10);
1637
5.10M
            *p++ = nDigit + '0';
1638
1639
5.10M
            if (!--nDigits)
1640
1.51M
                break; // for
1641
1642
3.59M
            if (nDecPos)
1643
767k
            {
1644
767k
                if (!--nDecPos)
1645
282k
                {
1646
282k
                    *p++ = cDecSeparator;
1647
282k
                    bHasDec = true;
1648
282k
                }
1649
485k
                else if (nDecPos == nGrouping)
1650
0
                {
1651
0
                    *p++ = cGroupSeparator;
1652
0
                    nGrouping -= pGroups[nGroupSelector];
1653
1654
0
                    if (nGroupSelector && nGrouping < nGroupExceed)
1655
0
                        --nGroupSelector;
1656
0
                }
1657
767k
            }
1658
3.59M
        }
1659
1.51M
    }
1660
1661
1.51M
    if (!bHasDec && eFormat == rtl_math_StringFormat_F)
1662
1.10M
    { // nDecPlaces < 0 did round the value
1663
1.10M
        while (--nDecPos > 0)
1664
0
        { // fill before decimal point
1665
0
            if (nDecPos == nGrouping)
1666
0
            {
1667
0
                *p++ = cGroupSeparator;
1668
0
                nGrouping -= pGroups[nGroupSelector];
1669
1670
0
                if (nGroupSelector && nGrouping < nGroupExceed)
1671
0
                    --nGroupSelector;
1672
0
            }
1673
1674
0
            *p++ = '0';
1675
0
        }
1676
1.10M
    }
1677
1678
1.51M
    if (bEraseTrailingDecZeros && bHasDec)
1679
410k
    {
1680
1.62M
        while (*(p - 1) == '0')
1681
1.21M
            p--;
1682
1683
410k
        if (*(p - 1) == cDecSeparator)
1684
41.4k
            p--;
1685
410k
    }
1686
1687
    // Print the exponent ('E', followed by '+' or '-', followed by exactly
1688
    // three digits for rtl_math_StringFormat_E). The code in
1689
    // rtl_[u]str_valueOf{Float|Double} relies on this format.
1690
1.51M
    if (eFormat == rtl_math_StringFormat_E || eFormat == rtl_math_StringFormat_E2
1691
1.51M
        || eFormat == rtl_math_StringFormat_E1)
1692
0
    {
1693
0
        if (p == pBuf)
1694
0
            *p++ = '1';
1695
        // maybe no nDigits if nDecPlaces < 0
1696
1697
0
        *p++ = 'E';
1698
0
        if (nExp < 0)
1699
0
        {
1700
0
            nExp = -nExp;
1701
0
            *p++ = '-';
1702
0
        }
1703
0
        else
1704
0
            *p++ = '+';
1705
1706
0
        if (eFormat == rtl_math_StringFormat_E || nExp >= 100)
1707
0
            *p++ = nExp / 100 + '0';
1708
1709
0
        nExp %= 100;
1710
1711
0
        if (eFormat == rtl_math_StringFormat_E || eFormat == rtl_math_StringFormat_E2 || nExp >= 10)
1712
0
            *p++ = nExp / 10 + '0';
1713
1714
0
        *p++ = nExp % 10 + '0';
1715
0
    }
1716
1717
1.51M
    append(pResult, pResultCapacity, nResultOffset, std::basic_string_view(pBuf, p - pBuf));
1718
1.51M
}
_ZN3rtl3str14doubleToStringI12_rtl_uStringEEvPPT_Piid21rtl_math_StringFormatiu15__remove_extentIDtsrS3_6bufferEEPKiS9_b
Line
Count
Source
1399
17.2M
{
1400
17.2M
    auto decimalDigits = [](sal_uInt64 n) {
1401
17.2M
        return std::distance(std::begin(eX), std::upper_bound(std::begin(eX), std::end(eX), n)) + 1;
1402
17.2M
    };
1403
1404
17.2M
    auto roundToPow10 = [](sal_uInt64 n, int e) {
1405
17.2M
        assert(e > 0 && o3tl::make_unsigned(e) <= std::size(eX));
1406
17.2M
        const sal_uInt64 d = eX[e - 1];
1407
17.2M
        return (n + d / 2) / d * d;
1408
17.2M
    };
1409
1410
17.2M
    auto append = [](rtl_tString** s, sal_Int32* pCapacity, sal_Int32 rOffset, auto sv)
1411
17.2M
    {
1412
17.2M
        if (!pCapacity)
1413
17.2M
            newFromStr_WithLength(s, sv.data(), sv.size());
1414
17.2M
        else
1415
17.2M
            stringbuffer_insert(s, pCapacity, rOffset, sv.data(), sv.size());
1416
17.2M
    };
1417
1418
17.2M
    if (std::isnan(fValue))
1419
1.81k
    {
1420
        // #i112652# XMLSchema-2
1421
1.81k
        static constexpr std::string_view nan{ "NaN" };
1422
1.81k
        return append(pResult, pResultCapacity, nResultOffset, nan);
1423
1.81k
    }
1424
1425
    // sign adjustment, instead of testing for fValue<0.0 this will also fetch -0.0
1426
17.2M
    bool bSign = std::signbit(fValue);
1427
1428
17.2M
    if (std::isinf(fValue))
1429
307
    {
1430
        // #i112652# XMLSchema-2
1431
307
        std::string_view inf = bSign ? std::string_view("-INF") : std::string_view("INF");
1432
307
        return append(pResult, pResultCapacity, nResultOffset, inf);
1433
307
    }
1434
1435
17.2M
    if (bSign)
1436
337k
        fValue = -fValue;
1437
1438
17.2M
    decltype(jkj::dragonbox::to_decimal(fValue, jkj::dragonbox::policy::sign::ignore,
1439
17.2M
                                        jkj::dragonbox::policy::trailing_zero::ignore)) aParts{};
1440
17.2M
    if (fValue) // to_decimal is documented to only handle non-zero finite numbers
1441
16.6M
        aParts = jkj::dragonbox::to_decimal(fValue, jkj::dragonbox::policy::sign::ignore,
1442
16.6M
                                            jkj::dragonbox::policy::trailing_zero::ignore);
1443
1444
17.2M
    int nOrigDigits = decimalDigits(aParts.significand);
1445
17.2M
    int nExp = nOrigDigits + aParts.exponent - 1;
1446
17.2M
    int nRoundDigits = 15;
1447
1448
    // Unfortunately the old rounding below writes 1.79769313486232e+308 for
1449
    // DBL_MAX and 4 subsequent nextafter(...,0).
1450
17.2M
    static const double fB1 = std::nextafter(std::numeric_limits<double>::max(), 0);
1451
17.2M
    static const double fB2 = std::nextafter(fB1, 0);
1452
17.2M
    static const double fB3 = std::nextafter(fB2, 0);
1453
17.2M
    static const double fB4 = std::nextafter(fB3, 0);
1454
17.2M
    if ((fValue >= fB4) && eFormat != rtl_math_StringFormat_F)
1455
591
    {
1456
        // 1.7976931348623157e+308 instead of rounded 1.79769313486232e+308
1457
        // that can't be converted back as out of range. For rounded values if
1458
        // they exceed range they should not be written to exchange strings or
1459
        // file formats.
1460
1461
591
        eFormat = rtl_math_StringFormat_E;
1462
591
        nDecPlaces = std::clamp<sal_Int32>(nDecPlaces, 0, 16);
1463
591
        nRoundDigits = 17;
1464
591
    }
1465
1466
    // Use integer representation for integer values that fit into the
1467
    // mantissa (1.((2^53)-1)) with a precision of 1 for highest accuracy.
1468
17.2M
    if ((eFormat == rtl_math_StringFormat_Automatic || eFormat == rtl_math_StringFormat_F)
1469
522k
        && aParts.exponent >= 0 && fValue < 0x1p53)
1470
37.5k
    {
1471
37.5k
        eFormat = rtl_math_StringFormat_F;
1472
37.5k
        if (nDecPlaces == rtl_math_DecimalPlaces_Max)
1473
27.6k
            nDecPlaces = 0;
1474
9.81k
        else
1475
9.81k
            nDecPlaces = std::clamp<sal_Int32>(nDecPlaces, -15, 15);
1476
1477
37.5k
        if (bEraseTrailingDecZeros && nDecPlaces > 0)
1478
5.88k
            nDecPlaces = 0;
1479
1480
37.5k
        nRoundDigits = nOrigDigits; // no rounding
1481
37.5k
    }
1482
1483
17.2M
    switch (eFormat)
1484
17.2M
    {
1485
408k
        case rtl_math_StringFormat_Automatic:
1486
            // E or F depending on exponent magnitude
1487
408k
            if (nExp <= -15 || nExp >= 15)
1488
11.6k
            {
1489
11.6k
                if (nDecPlaces == rtl_math_DecimalPlaces_Max)
1490
11.6k
                    nDecPlaces = 14;
1491
11.6k
                eFormat = rtl_math_StringFormat_E;
1492
11.6k
            }
1493
396k
            else
1494
396k
            {
1495
396k
                if (nDecPlaces == rtl_math_DecimalPlaces_Max)
1496
396k
                    nDecPlaces = (nExp < 14) ? 15 - nExp - 1 : 15;
1497
396k
                eFormat = rtl_math_StringFormat_F;
1498
396k
            }
1499
408k
            break;
1500
1501
16.6M
        case rtl_math_StringFormat_G:
1502
16.6M
        case rtl_math_StringFormat_G1:
1503
16.6M
        case rtl_math_StringFormat_G2:
1504
            // G-Point, similar to sprintf %G
1505
16.6M
            if (nDecPlaces == rtl_math_DecimalPlaces_DefaultSignificance)
1506
0
                nDecPlaces = 6;
1507
1508
16.6M
            if (nExp < -4 || nExp >= nDecPlaces)
1509
47.1k
            {
1510
47.1k
                nDecPlaces = std::max<sal_Int32>(1, nDecPlaces - 1);
1511
1512
47.1k
                if (eFormat == rtl_math_StringFormat_G)
1513
47.1k
                    eFormat = rtl_math_StringFormat_E;
1514
0
                else if (eFormat == rtl_math_StringFormat_G2)
1515
0
                    eFormat = rtl_math_StringFormat_E2;
1516
0
                else if (eFormat == rtl_math_StringFormat_G1)
1517
0
                    eFormat = rtl_math_StringFormat_E1;
1518
47.1k
            }
1519
16.6M
            else
1520
16.6M
            {
1521
16.6M
                if (nOrigDigits <= nDecPlaces && aParts.exponent >= 0 && fValue < 0x1p53)
1522
579k
                {
1523
                    // Use integer representation with highest accuracy.
1524
579k
                    nRoundDigits = nOrigDigits; // no rounding
1525
579k
                }
1526
16.6M
                nDecPlaces = std::max<sal_Int32>(0, nDecPlaces - nExp - 1);
1527
16.6M
                eFormat = rtl_math_StringFormat_F;
1528
16.6M
            }
1529
16.6M
            break;
1530
1531
119k
        default:
1532
119k
            break;
1533
17.2M
    }
1534
1535
    // Too large values for nDecPlaces make no sense; it might also be
1536
    // rtl_math_DecimalPlaces_Max was passed with rtl_math_StringFormat_F or
1537
    // others, but we don't want to allocate/deallocate 2GB just to fill it
1538
    // with trailing '0' characters..
1539
17.2M
    nDecPlaces = std::clamp<sal_Int32>(nDecPlaces, -309, 309);
1540
1541
17.2M
    sal_Int32 nDigits = nDecPlaces + 1;
1542
1543
17.2M
    if (eFormat == rtl_math_StringFormat_F)
1544
17.1M
        nDigits += nExp;
1545
1546
    // Round the number
1547
17.2M
    nRoundDigits = std::min<int>(nDigits, nRoundDigits);
1548
17.2M
    if (nDigits >= 0 && nOrigDigits > nRoundDigits)
1549
16.0M
    {
1550
16.0M
        aParts.significand = roundToPow10(aParts.significand, nOrigDigits - nRoundDigits);
1551
16.0M
        assert(aParts.significand <= eX[nOrigDigits - 1]);
1552
16.0M
        if (aParts.significand == eX[nOrigDigits - 1]) // up-rounding to the next decade
1553
670
        {
1554
670
            nOrigDigits++;
1555
670
            nExp++;
1556
1557
670
            if (eFormat == rtl_math_StringFormat_F)
1558
314
                nDigits++;
1559
670
        }
1560
16.0M
    }
1561
1562
17.2M
    sal_Int32 nBuf
1563
17.2M
        = (nDigits <= 0 ? std::max<sal_Int32>(nDecPlaces, std::abs(nExp)) : nDigits + nDecPlaces)
1564
17.2M
          + 10 + (pGroups ? std::abs(nDigits) * 2 : 0);
1565
    // max(nDigits) = max(nDecPlaces) + 1 + max(nExp) + 1 = 309 + 1 + 308 + 1 = 619
1566
    // max(nBuf) = max(nDigits) + max(nDecPlaces) + 10 + max(nDigits) * 2 = 619 * 3 + 309 + 10 = 2176
1567
17.2M
    assert(nBuf <= 2176);
1568
17.2M
    auto* const pBuf = static_cast<Char_T<rtl_tString>*>(alloca(nBuf * sizeof(Char_T<rtl_tString>)));
1569
17.2M
    auto* p = pBuf;
1570
17.2M
    if (bSign)
1571
337k
        *p++ = '-';
1572
1573
17.2M
    bool bHasDec = false;
1574
1575
17.2M
    int nDecPos;
1576
    // Check for F format and number < 1
1577
17.2M
    if (eFormat == rtl_math_StringFormat_F)
1578
17.1M
    {
1579
17.1M
        if (nExp < 0)
1580
5.21M
        {
1581
5.21M
            *p++ = '0';
1582
5.21M
            if (nDecPlaces > 0)
1583
5.21M
            {
1584
5.21M
                *p++ = cDecSeparator;
1585
5.21M
                bHasDec = true;
1586
5.21M
            }
1587
1588
5.21M
            sal_Int32 i = (nDigits <= 0 ? nDecPlaces : -nExp - 1);
1589
1590
9.76M
            while ((i--) > 0)
1591
4.54M
                *p++ = '0';
1592
1593
5.21M
            nDecPos = 0;
1594
5.21M
        }
1595
11.9M
        else
1596
11.9M
            nDecPos = nExp + 1;
1597
17.1M
    }
1598
64.1k
    else
1599
64.1k
        nDecPos = 1;
1600
1601
17.2M
    int nGrouping = 0, nGroupSelector = 0, nGroupExceed = 0;
1602
17.2M
    if (nDecPos > 1 && pGroups && pGroups[0] && cGroupSeparator)
1603
0
    {
1604
0
        while (nGrouping + pGroups[nGroupSelector] < nDecPos)
1605
0
        {
1606
0
            nGrouping += pGroups[nGroupSelector];
1607
0
            if (pGroups[nGroupSelector + 1])
1608
0
            {
1609
0
                if (nGrouping + pGroups[nGroupSelector + 1] >= nDecPos)
1610
0
                    break; // while
1611
1612
0
                ++nGroupSelector;
1613
0
            }
1614
0
            else if (!nGroupExceed)
1615
0
                nGroupExceed = nGrouping;
1616
0
        }
1617
0
    }
1618
1619
    // print the number
1620
17.2M
    if (nDigits > 0)
1621
17.2M
    {
1622
17.2M
        for (int nCurExp = nOrigDigits - 1;;)
1623
293M
        {
1624
293M
            int nDigit;
1625
293M
            if (aParts.significand > 0 && nCurExp > 0)
1626
215M
            {
1627
215M
                --nCurExp;
1628
215M
                nDigit = aParts.significand / eX[nCurExp];
1629
215M
                aParts.significand %= eX[nCurExp];
1630
215M
            }
1631
77.7M
            else
1632
77.7M
            {
1633
77.7M
                nDigit = aParts.significand;
1634
77.7M
                aParts.significand = 0;
1635
77.7M
            }
1636
293M
            assert(nDigit >= 0 && nDigit < 10);
1637
293M
            *p++ = nDigit + '0';
1638
1639
293M
            if (!--nDigits)
1640
17.2M
                break; // for
1641
1642
275M
            if (nDecPos)
1643
21.9M
            {
1644
21.9M
                if (!--nDecPos)
1645
11.9M
                {
1646
11.9M
                    *p++ = cDecSeparator;
1647
11.9M
                    bHasDec = true;
1648
11.9M
                }
1649
10.0M
                else if (nDecPos == nGrouping)
1650
0
                {
1651
0
                    *p++ = cGroupSeparator;
1652
0
                    nGrouping -= pGroups[nGroupSelector];
1653
1654
0
                    if (nGroupSelector && nGrouping < nGroupExceed)
1655
0
                        --nGroupSelector;
1656
0
                }
1657
21.9M
            }
1658
275M
        }
1659
17.2M
    }
1660
1661
17.2M
    if (!bHasDec && eFormat == rtl_math_StringFormat_F)
1662
69.6k
    { // nDecPlaces < 0 did round the value
1663
69.6k
        while (--nDecPos > 0)
1664
0
        { // fill before decimal point
1665
0
            if (nDecPos == nGrouping)
1666
0
            {
1667
0
                *p++ = cGroupSeparator;
1668
0
                nGrouping -= pGroups[nGroupSelector];
1669
1670
0
                if (nGroupSelector && nGrouping < nGroupExceed)
1671
0
                    --nGroupSelector;
1672
0
            }
1673
1674
0
            *p++ = '0';
1675
0
        }
1676
69.6k
    }
1677
1678
17.2M
    if (bEraseTrailingDecZeros && bHasDec)
1679
17.1M
    {
1680
93.8M
        while (*(p - 1) == '0')
1681
76.7M
            p--;
1682
1683
17.1M
        if (*(p - 1) == cDecSeparator)
1684
1.08M
            p--;
1685
17.1M
    }
1686
1687
    // Print the exponent ('E', followed by '+' or '-', followed by exactly
1688
    // three digits for rtl_math_StringFormat_E). The code in
1689
    // rtl_[u]str_valueOf{Float|Double} relies on this format.
1690
17.2M
    if (eFormat == rtl_math_StringFormat_E || eFormat == rtl_math_StringFormat_E2
1691
17.1M
        || eFormat == rtl_math_StringFormat_E1)
1692
64.1k
    {
1693
64.1k
        if (p == pBuf)
1694
0
            *p++ = '1';
1695
        // maybe no nDigits if nDecPlaces < 0
1696
1697
64.1k
        *p++ = 'E';
1698
64.1k
        if (nExp < 0)
1699
39.9k
        {
1700
39.9k
            nExp = -nExp;
1701
39.9k
            *p++ = '-';
1702
39.9k
        }
1703
24.2k
        else
1704
24.2k
            *p++ = '+';
1705
1706
64.1k
        if (eFormat == rtl_math_StringFormat_E || nExp >= 100)
1707
63.9k
            *p++ = nExp / 100 + '0';
1708
1709
64.1k
        nExp %= 100;
1710
1711
64.1k
        if (eFormat == rtl_math_StringFormat_E || eFormat == rtl_math_StringFormat_E2 || nExp >= 10)
1712
64.1k
            *p++ = nExp / 10 + '0';
1713
1714
64.1k
        *p++ = nExp % 10 + '0';
1715
64.1k
    }
1716
1717
17.2M
    append(pResult, pResultCapacity, nResultOffset, std::basic_string_view(pBuf, p - pBuf));
1718
17.2M
}
1719
1720
template <sal_Int32 maxLen, typename C, typename T> sal_Int32 SAL_CALL valueOfFP(C* pStr, T f)
1721
0
{
1722
0
    assert(pStr);
1723
0
    rtl_String* pResult = nullptr;
1724
0
    doubleToString(&pResult, nullptr, 0, f, rtl_math_StringFormat_G,
1725
0
                   maxLen - std::size("-x.E-xxx") + 1, '.', nullptr, 0, true);
1726
0
    const sal_Int32 nLen = pResult->length;
1727
    assert(nLen < maxLen);
1728
0
    Copy(pStr, pResult->buffer, nLen + 1);
1729
0
    release(pResult);
1730
0
    return nLen;
1731
0
}
Unexecuted instantiation: int rtl::str::valueOfFP<15, char, float>(char*, float)
Unexecuted instantiation: int rtl::str::valueOfFP<25, char, double>(char*, double)
Unexecuted instantiation: int rtl::str::valueOfFP<15, char16_t, float>(char16_t*, float)
Unexecuted instantiation: int rtl::str::valueOfFP<25, char16_t, double>(char16_t*, double)
1732
1733
}
1734
1735
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */