Coverage Report

Created: 2026-05-16 09:25

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libreoffice/include/o3tl/string_view.hxx
Line
Count
Source
1
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */
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
10
#pragma once
11
12
#include <sal/config.h>
13
14
#include <cassert>
15
#include <cstddef>
16
#include <string>
17
#include <string_view>
18
#include <type_traits>
19
20
#include <o3tl/intcmp.hxx>
21
#include <rtl/character.hxx>
22
#include <rtl/ustring.h>
23
#include <rtl/math.h>
24
#include <sal/types.h>
25
26
namespace o3tl
27
{
28
// Like OUString::equalsAscii/OUString::equalsAsciiL, but for std::u16string_view:
29
inline bool equalsAscii(std::u16string_view s1, std::string_view s2)
30
24.2M
{
31
24.2M
    return s1.size() == s2.size()
32
834k
           && rtl_ustr_ascii_shortenedCompare_WithLength(s1.data(), s1.size(), s2.data(), s2.size())
33
834k
                  == 0;
34
24.2M
}
35
36
// Like OUString::compareToAscii, but for std::u16string_view and std::string_view:
37
inline int compareToAscii(std::u16string_view s1, std::string_view s2)
38
3.48k
{
39
3.48k
    return rtl_ustr_asciil_reverseCompare_WithLength(s1.data(), s1.size(), s2.data(), s2.size());
40
3.48k
};
41
42
// Like OUString::equalsIgnoreAsciiCase, but for two std::u16string_view:
43
inline bool equalsIgnoreAsciiCase(std::u16string_view s1, std::u16string_view s2)
44
465k
{
45
465k
    if (s1.size() != s2.size())
46
243k
        return false;
47
221k
    if (s1.data() == s2.data())
48
31
        return true;
49
221k
    return rtl_ustr_compareIgnoreAsciiCase_WithLength(s1.data(), s1.size(), s2.data(), s2.size())
50
221k
           == 0;
51
221k
};
52
53
inline bool equalsIgnoreAsciiCase(std::u16string_view s1, std::string_view s2)
54
2.75M
{
55
2.75M
    return s1.size() == s2.size()
56
122k
           && (rtl_ustr_ascii_shortenedCompareIgnoreAsciiCase_WithLength(s1.data(), s1.size(),
57
122k
                                                                         s2.data(), s2.size())
58
122k
               == 0);
59
2.75M
}
60
61
inline bool equalsIgnoreAsciiCase(std::string_view s1, std::string_view s2)
62
30
{
63
30
    if (s1.size() != s2.size())
64
30
        return false;
65
0
    if (s1.data() == s2.data())
66
0
        return true;
67
0
    return rtl_str_compareIgnoreAsciiCase_WithLength(s1.data(), s1.size(), s2.data(), s2.size())
68
0
           == 0;
69
0
};
70
71
// Like OUString::compareToIgnoreAsciiCase, but for two std::u16string_view:
72
inline int compareToIgnoreAsciiCase(std::u16string_view s1, std::u16string_view s2)
73
13.6M
{
74
13.6M
    return rtl_ustr_compareIgnoreAsciiCase_WithLength(s1.data(), s1.size(), s2.data(), s2.size());
75
13.6M
};
76
77
// Like OUString::matchIgnoreAsciiCase, but for two std::u16string_view:
78
inline bool matchIgnoreAsciiCase(std::u16string_view s1, std::u16string_view s2,
79
                                 sal_Int32 fromIndex = 0)
80
6.02M
{
81
6.02M
    return rtl_ustr_shortenedCompareIgnoreAsciiCase_WithLength(
82
6.02M
               s1.data() + fromIndex, s1.size() - fromIndex, s2.data(), s2.size(), s2.size())
83
6.02M
           == 0;
84
6.02M
}
85
86
// Like OUString::matchIgnoreAsciiCase, but for std::u16string_view and std::string_view:
87
inline bool matchIgnoreAsciiCase(std::u16string_view s1, std::string_view s2,
88
                                 sal_Int32 fromIndex = 0)
89
272k
{
90
272k
    return rtl_ustr_ascii_shortenedCompareIgnoreAsciiCase_WithLength(
91
272k
               s1.data() + fromIndex, s1.size() - fromIndex, s2.data(), s2.size())
92
272k
           == 0;
93
272k
}
94
95
// Like OUString::endsWithIgnoreAsciiCase, but for std::u16string_view
96
inline bool endsWithIgnoreAsciiCase(std::u16string_view s1, std::u16string_view s2,
97
                                    std::u16string_view* rest = nullptr)
98
0
{
99
0
    auto const b = s2.size() <= s1.size() && matchIgnoreAsciiCase(s1, s2, s1.size() - s2.size());
100
0
    if (b && rest != nullptr)
101
0
    {
102
0
        *rest = s1.substr(0, s1.size() - s2.size());
103
0
    }
104
0
    return b;
105
0
}
106
107
inline bool endsWithIgnoreAsciiCase(std::u16string_view s1, std::string_view s2,
108
                                    std::u16string_view* rest = nullptr)
109
0
{
110
0
    auto const b = s2.size() <= s1.size()
111
0
                   && rtl_ustr_ascii_compareIgnoreAsciiCase_WithLengths(
112
0
                          s1.data() + s1.size() - s2.size(), s2.size(), s2.data(), s2.size())
113
0
                          == 0;
114
0
    if (b && rest != nullptr)
115
0
    {
116
0
        *rest = s1.substr(0, s1.size() - s2.size());
117
0
    }
118
0
    return b;
119
0
}
120
121
// Similar to O[U]String::getToken, returning the first token of a std::[u16]string_view starting
122
// at a given position.
123
//
124
// Attention:  There are two sets of o3tl::getToken overloads here.  This first set has an interface
125
// based on std::size_t length parameters, and its semantics don't match those of
126
// O[U]String::getToken exactly (buf if needed, it can be extended to return the n'th token instead
127
// of just the first, and/or support an initial position of npos, to make the semantics match).
128
template <typename charT, typename traits = std::char_traits<charT>>
129
inline std::basic_string_view<charT, traits> getToken(std::basic_string_view<charT, traits> sv,
130
                                                      charT delimiter, std::size_t& position)
131
166k
{
132
166k
    assert(position <= sv.size());
133
166k
    auto const n = sv.find(delimiter, position);
134
166k
    std::basic_string_view<charT, traits> t;
135
166k
    if (n == std::string_view::npos)
136
149k
    {
137
149k
        t = sv.substr(position);
138
149k
        position = std::string_view::npos;
139
149k
    }
140
16.2k
    else
141
16.2k
    {
142
16.2k
        t = sv.substr(position, n - position);
143
16.2k
        position = n + 1;
144
16.2k
    }
145
166k
    return t;
146
166k
}
std::__1::basic_string_view<char16_t, std::__1::char_traits<char16_t> > o3tl::getToken<char16_t, std::__1::char_traits<char16_t> >(std::__1::basic_string_view<char16_t, std::__1::char_traits<char16_t> >, char16_t, unsigned long&)
Line
Count
Source
131
157k
{
132
157k
    assert(position <= sv.size());
133
157k
    auto const n = sv.find(delimiter, position);
134
157k
    std::basic_string_view<charT, traits> t;
135
157k
    if (n == std::string_view::npos)
136
143k
    {
137
143k
        t = sv.substr(position);
138
143k
        position = std::string_view::npos;
139
143k
    }
140
14.9k
    else
141
14.9k
    {
142
14.9k
        t = sv.substr(position, n - position);
143
14.9k
        position = n + 1;
144
14.9k
    }
145
157k
    return t;
146
157k
}
std::__1::basic_string_view<char, std::__1::char_traits<char> > o3tl::getToken<char, std::__1::char_traits<char> >(std::__1::basic_string_view<char, std::__1::char_traits<char> >, char, unsigned long&)
Line
Count
Source
131
8.04k
{
132
8.04k
    assert(position <= sv.size());
133
8.04k
    auto const n = sv.find(delimiter, position);
134
8.04k
    std::basic_string_view<charT, traits> t;
135
8.04k
    if (n == std::string_view::npos)
136
6.71k
    {
137
6.71k
        t = sv.substr(position);
138
6.71k
        position = std::string_view::npos;
139
6.71k
    }
140
1.33k
    else
141
1.33k
    {
142
1.33k
        t = sv.substr(position, n - position);
143
1.33k
        position = n + 1;
144
1.33k
    }
145
8.04k
    return t;
146
8.04k
}
147
// The following two overloads prevent overload resolution mistakes that would occur with their
148
// template counterpart, when sv is of a type that is implicitly convertible to basic_string_view
149
// (like OString or OUString), in which case overload resolution would erroneously choose the
150
// three-argument overloads (taking sv, nToken, cTok) from the second set of
151
// o3tl::getToken overloads below:
152
inline std::string_view getToken(std::string_view sv, char delimiter, std::size_t& position)
153
8.04k
{
154
8.04k
    return getToken<char>(sv, delimiter, position);
155
8.04k
}
156
inline std::u16string_view getToken(std::u16string_view sv, char16_t delimiter,
157
                                    std::size_t& position)
158
157k
{
159
157k
    return getToken<char16_t>(sv, delimiter, position);
160
157k
}
161
162
// Similar to O[U]String::getToken.
163
//
164
// Attention:  There are two sets of o3tl::getToken overloads here.  This second set has an
165
// interface based on sal_Int32 length parameters, and is meant to be a drop-in replacement for
166
// O[U]String::getToken.
167
template <typename charT, typename traits = std::char_traits<charT>>
168
inline std::basic_string_view<charT, traits> getToken(std::basic_string_view<charT, traits> pStr,
169
                                                      sal_Int32 nToken, charT cTok,
170
                                                      sal_Int32& rnIndex)
171
4.60M
{
172
4.60M
    assert(o3tl::IntCmp(rnIndex) <= o3tl::IntCmp(pStr.size()));
173
174
    // Return an empty string and set rnIndex to -1 if either nToken or rnIndex is
175
    // negative:
176
4.60M
    if (rnIndex >= 0 && nToken >= 0)
177
4.58M
    {
178
4.58M
        const charT* pOrgCharStr = pStr.data();
179
4.58M
        const charT* pCharStr = pOrgCharStr + rnIndex;
180
4.58M
        sal_Int32 nLen = pStr.size() - rnIndex;
181
4.58M
        sal_Int32 nTokCount = 0;
182
4.58M
        const charT* pCharStrStart = pCharStr;
183
142M
        while (nLen > 0)
184
139M
        {
185
139M
            if (*pCharStr == cTok)
186
1.58M
            {
187
1.58M
                nTokCount++;
188
189
1.58M
                if (nTokCount > nToken)
190
1.41M
                    break;
191
168k
                if (nTokCount == nToken)
192
168k
                    pCharStrStart = pCharStr + 1;
193
168k
            }
194
195
137M
            pCharStr++;
196
137M
            nLen--;
197
137M
        }
198
4.58M
        if (nTokCount >= nToken)
199
4.58M
        {
200
4.58M
            if (nLen > 0)
201
1.41M
                rnIndex = pCharStr - pOrgCharStr + 1;
202
3.16M
            else
203
3.16M
                rnIndex = -1;
204
4.58M
            return std::basic_string_view<charT, traits>(pCharStrStart, pCharStr - pCharStrStart);
205
4.58M
        }
206
4.58M
    }
207
208
18.1k
    rnIndex = -1;
209
18.1k
    return std::basic_string_view<charT, traits>();
210
4.60M
}
Unexecuted instantiation: std::__1::basic_string_view<char, std::__1::char_traits<char> > o3tl::getToken<char, std::__1::char_traits<char> >(std::__1::basic_string_view<char, std::__1::char_traits<char> >, int, char, int&)
std::__1::basic_string_view<char16_t, std::__1::char_traits<char16_t> > o3tl::getToken<char16_t, std::__1::char_traits<char16_t> >(std::__1::basic_string_view<char16_t, std::__1::char_traits<char16_t> >, int, char16_t, int&)
Line
Count
Source
171
4.60M
{
172
4.60M
    assert(o3tl::IntCmp(rnIndex) <= o3tl::IntCmp(pStr.size()));
173
174
    // Return an empty string and set rnIndex to -1 if either nToken or rnIndex is
175
    // negative:
176
4.60M
    if (rnIndex >= 0 && nToken >= 0)
177
4.58M
    {
178
4.58M
        const charT* pOrgCharStr = pStr.data();
179
4.58M
        const charT* pCharStr = pOrgCharStr + rnIndex;
180
4.58M
        sal_Int32 nLen = pStr.size() - rnIndex;
181
4.58M
        sal_Int32 nTokCount = 0;
182
4.58M
        const charT* pCharStrStart = pCharStr;
183
142M
        while (nLen > 0)
184
139M
        {
185
139M
            if (*pCharStr == cTok)
186
1.58M
            {
187
1.58M
                nTokCount++;
188
189
1.58M
                if (nTokCount > nToken)
190
1.41M
                    break;
191
168k
                if (nTokCount == nToken)
192
168k
                    pCharStrStart = pCharStr + 1;
193
168k
            }
194
195
137M
            pCharStr++;
196
137M
            nLen--;
197
137M
        }
198
4.58M
        if (nTokCount >= nToken)
199
4.58M
        {
200
4.58M
            if (nLen > 0)
201
1.41M
                rnIndex = pCharStr - pOrgCharStr + 1;
202
3.16M
            else
203
3.16M
                rnIndex = -1;
204
4.58M
            return std::basic_string_view<charT, traits>(pCharStrStart, pCharStr - pCharStrStart);
205
4.58M
        }
206
4.58M
    }
207
208
18.1k
    rnIndex = -1;
209
18.1k
    return std::basic_string_view<charT, traits>();
210
4.60M
}
211
// The following two overloads prevent deduction failures that would occur with their template
212
// counterpart, when sv is of a type that is implicitly convertible to basic_string_view (like
213
// OString or OUString):
214
inline std::string_view getToken(std::string_view sv, sal_Int32 nToken, char cTok,
215
                                 sal_Int32& rnIndex)
216
0
{
217
0
    return getToken<char>(sv, nToken, cTok, rnIndex);
218
0
}
219
inline std::u16string_view getToken(std::u16string_view sv, sal_Int32 nToken, char16_t cTok,
220
                                    sal_Int32& rnIndex)
221
4.55M
{
222
4.55M
    return getToken<char16_t>(sv, nToken, cTok, rnIndex);
223
4.55M
}
224
inline std::string_view getToken(std::string_view sv, sal_Int32 nToken, char cTok)
225
0
{
226
0
    sal_Int32 nIndex = 0;
227
0
    return getToken<char>(sv, nToken, cTok, nIndex);
228
0
}
229
inline std::u16string_view getToken(std::u16string_view sv, sal_Int32 nToken, char16_t cTok)
230
44.8k
{
231
44.8k
    sal_Int32 nIndex = 0;
232
44.8k
    return getToken<char16_t>(sv, nToken, cTok, nIndex);
233
44.8k
}
234
235
// Implementations of C++20 std::basic_string_view::starts_with and
236
// std::basic_string_view::ends_with, until we can use those directly on all platforms:
237
template <typename charT, typename traits = std::char_traits<charT>>
238
constexpr bool starts_with(std::basic_string_view<charT, traits> sv,
239
                           std::basic_string_view<charT, traits> x) noexcept
240
83.8M
{
241
83.8M
#if defined __cpp_lib_starts_ends_with
242
83.8M
    return sv.starts_with(x);
243
#else
244
    return sv.substr(0, x.size()) == x;
245
#endif
246
83.8M
}
bool o3tl::starts_with<char16_t, std::__1::char_traits<char16_t> >(std::__1::basic_string_view<char16_t, std::__1::char_traits<char16_t> >, std::__1::basic_string_view<char16_t, std::__1::char_traits<char16_t> >)
Line
Count
Source
240
83.6M
{
241
83.6M
#if defined __cpp_lib_starts_ends_with
242
83.6M
    return sv.starts_with(x);
243
#else
244
    return sv.substr(0, x.size()) == x;
245
#endif
246
83.6M
}
bool o3tl::starts_with<char, std::__1::char_traits<char> >(std::__1::basic_string_view<char, std::__1::char_traits<char> >, std::__1::basic_string_view<char, std::__1::char_traits<char> >)
Line
Count
Source
240
169k
{
241
169k
#if defined __cpp_lib_starts_ends_with
242
169k
    return sv.starts_with(x);
243
#else
244
    return sv.substr(0, x.size()) == x;
245
#endif
246
169k
}
247
template <typename charT, typename traits = std::char_traits<charT>>
248
constexpr bool starts_with(std::basic_string_view<charT, traits> sv, charT x) noexcept
249
{
250
#if defined __cpp_lib_starts_ends_with
251
    return sv.starts_with(x);
252
#else
253
    return !sv.empty() && traits::eq(sv.front(), x);
254
#endif
255
}
256
template <typename charT, typename traits = std::char_traits<charT>>
257
constexpr bool starts_with(std::basic_string_view<charT, traits> sv, charT const* x)
258
3.93M
{
259
3.93M
#if defined __cpp_lib_starts_ends_with
260
3.93M
    return sv.starts_with(x);
261
#else
262
    return starts_with(sv, std::basic_string_view<charT, traits>(x));
263
#endif
264
3.93M
}
bool o3tl::starts_with<char16_t, std::__1::char_traits<char16_t> >(std::__1::basic_string_view<char16_t, std::__1::char_traits<char16_t> >, char16_t const*)
Line
Count
Source
258
3.93M
{
259
3.93M
#if defined __cpp_lib_starts_ends_with
260
3.93M
    return sv.starts_with(x);
261
#else
262
    return starts_with(sv, std::basic_string_view<charT, traits>(x));
263
#endif
264
3.93M
}
bool o3tl::starts_with<char, std::__1::char_traits<char> >(std::__1::basic_string_view<char, std::__1::char_traits<char> >, char const*)
Line
Count
Source
258
723
{
259
723
#if defined __cpp_lib_starts_ends_with
260
723
    return sv.starts_with(x);
261
#else
262
    return starts_with(sv, std::basic_string_view<charT, traits>(x));
263
#endif
264
723
}
265
template <typename charT, typename traits = std::char_traits<charT>>
266
constexpr bool ends_with(std::basic_string_view<charT, traits> sv,
267
                         std::basic_string_view<charT, traits> x) noexcept
268
1.41M
{
269
1.41M
#if defined __cpp_lib_starts_ends_with
270
1.41M
    return sv.ends_with(x);
271
#else
272
    return sv.size() >= x.size()
273
           && sv.compare(sv.size() - x.size(), std::basic_string_view<charT, traits>::npos, x) == 0;
274
#endif
275
1.41M
}
Unexecuted instantiation: bool o3tl::ends_with<char, std::__1::char_traits<char> >(std::__1::basic_string_view<char, std::__1::char_traits<char> >, std::__1::basic_string_view<char, std::__1::char_traits<char> >)
bool o3tl::ends_with<char16_t, std::__1::char_traits<char16_t> >(std::__1::basic_string_view<char16_t, std::__1::char_traits<char16_t> >, std::__1::basic_string_view<char16_t, std::__1::char_traits<char16_t> >)
Line
Count
Source
268
1.41M
{
269
1.41M
#if defined __cpp_lib_starts_ends_with
270
1.41M
    return sv.ends_with(x);
271
#else
272
    return sv.size() >= x.size()
273
           && sv.compare(sv.size() - x.size(), std::basic_string_view<charT, traits>::npos, x) == 0;
274
#endif
275
1.41M
}
276
template <typename charT, typename traits = std::char_traits<charT>>
277
constexpr bool ends_with(std::basic_string_view<charT, traits> sv, charT x) noexcept
278
{
279
#if defined __cpp_lib_starts_ends_with
280
    return sv.ends_with(x);
281
#else
282
    return !sv.empty() && traits::eq(sv.back(), x);
283
#endif
284
}
285
template <typename charT, typename traits = std::char_traits<charT>>
286
constexpr bool ends_with(std::basic_string_view<charT, traits> sv, charT const* x)
287
1.28M
{
288
1.28M
#if defined __cpp_lib_starts_ends_with
289
1.28M
    return sv.ends_with(x);
290
#else
291
    return ends_with(sv, std::basic_string_view<charT, traits>(x));
292
#endif
293
1.28M
}
294
// The following overloads prevent deduction failures that would occur with their template
295
// counterparts, when x is of a type that is implicitly convertible to basic_string_view (like
296
// OString or OUString, and we only bother to provide overloads for the char and char16_t cases, not
297
// also for char32_t and wchar_t, nor for C++20 char8_t):
298
constexpr bool starts_with(std::string_view sv, std::string_view x) noexcept
299
169k
{
300
169k
    return starts_with<char>(sv, x);
301
169k
}
302
constexpr bool starts_with(std::u16string_view sv, std::u16string_view x) noexcept
303
83.6M
{
304
83.6M
    return starts_with<char16_t>(sv, x);
305
83.6M
}
306
constexpr bool ends_with(std::string_view sv, std::string_view x) noexcept
307
0
{
308
0
    return ends_with<char>(sv, x);
309
0
}
310
constexpr bool ends_with(std::u16string_view sv, std::u16string_view x) noexcept
311
1.41M
{
312
1.41M
    return ends_with<char16_t>(sv, x);
313
1.41M
}
314
315
// Variants of C++20 std::basic_string_view::starts_with and
316
// std::basic_string_view::ends_with that have a rest out parameter, similar to our OString and
317
// OUString startsWith and endsWith member functions:
318
template <typename charT, typename traits = std::char_traits<charT>>
319
constexpr bool starts_with(std::basic_string_view<charT, traits> sv,
320
                           std::basic_string_view<charT, traits> x,
321
                           std::basic_string_view<charT, traits>* rest) noexcept
322
158k
{
323
158k
    assert(rest != nullptr);
324
158k
    auto const found = starts_with(sv, x);
325
158k
    if (found)
326
32.7k
    {
327
32.7k
        *rest = sv.substr(x.length());
328
32.7k
    }
329
158k
    return found;
330
158k
}
Unexecuted instantiation: bool o3tl::starts_with<char, std::__1::char_traits<char> >(std::__1::basic_string_view<char, std::__1::char_traits<char> >, std::__1::basic_string_view<char, std::__1::char_traits<char> >, std::__1::basic_string_view<char, std::__1::char_traits<char> >*)
bool o3tl::starts_with<char16_t, std::__1::char_traits<char16_t> >(std::__1::basic_string_view<char16_t, std::__1::char_traits<char16_t> >, std::__1::basic_string_view<char16_t, std::__1::char_traits<char16_t> >, std::__1::basic_string_view<char16_t, std::__1::char_traits<char16_t> >*)
Line
Count
Source
322
158k
{
323
158k
    assert(rest != nullptr);
324
158k
    auto const found = starts_with(sv, x);
325
158k
    if (found)
326
32.7k
    {
327
32.7k
        *rest = sv.substr(x.length());
328
32.7k
    }
329
158k
    return found;
330
158k
}
331
template <typename charT, typename traits = std::char_traits<charT>>
332
constexpr bool starts_with(std::basic_string_view<charT, traits> sv, charT x,
333
                           std::basic_string_view<charT, traits>* rest) noexcept
334
{
335
    assert(rest != nullptr);
336
    auto const found = starts_with(sv, x);
337
    if (found)
338
    {
339
        *rest = sv.substr(1);
340
    }
341
    return found;
342
}
343
template <typename charT, typename traits = std::char_traits<charT>>
344
constexpr bool starts_with(std::basic_string_view<charT, traits> sv, charT const* x,
345
                           std::basic_string_view<charT, traits>* rest)
346
295k
{
347
295k
    assert(rest != nullptr);
348
295k
    auto const found = starts_with(sv, x);
349
295k
    if (found)
350
121k
    {
351
121k
        *rest = sv.substr(traits::length(x));
352
121k
    }
353
295k
    return found;
354
295k
}
bool o3tl::starts_with<char16_t, std::__1::char_traits<char16_t> >(std::__1::basic_string_view<char16_t, std::__1::char_traits<char16_t> >, char16_t const*, std::__1::basic_string_view<char16_t, std::__1::char_traits<char16_t> >*)
Line
Count
Source
346
295k
{
347
295k
    assert(rest != nullptr);
348
295k
    auto const found = starts_with(sv, x);
349
295k
    if (found)
350
121k
    {
351
121k
        *rest = sv.substr(traits::length(x));
352
121k
    }
353
295k
    return found;
354
295k
}
Unexecuted instantiation: bool o3tl::starts_with<char, std::__1::char_traits<char> >(std::__1::basic_string_view<char, std::__1::char_traits<char> >, char const*, std::__1::basic_string_view<char, std::__1::char_traits<char> >*)
355
template <typename charT, typename traits = std::char_traits<charT>>
356
constexpr bool ends_with(std::basic_string_view<charT, traits> sv,
357
                         std::basic_string_view<charT, traits> x,
358
                         std::basic_string_view<charT, traits>* rest) noexcept
359
0
{
360
0
    assert(rest != nullptr);
361
0
    auto const found = ends_with(sv, x);
362
0
    if (found)
363
0
    {
364
0
        *rest = sv.substr(0, sv.length() - x.length());
365
0
    }
366
0
    return found;
367
0
}
Unexecuted instantiation: bool o3tl::ends_with<char, std::__1::char_traits<char> >(std::__1::basic_string_view<char, std::__1::char_traits<char> >, std::__1::basic_string_view<char, std::__1::char_traits<char> >, std::__1::basic_string_view<char, std::__1::char_traits<char> >*)
Unexecuted instantiation: bool o3tl::ends_with<char16_t, std::__1::char_traits<char16_t> >(std::__1::basic_string_view<char16_t, std::__1::char_traits<char16_t> >, std::__1::basic_string_view<char16_t, std::__1::char_traits<char16_t> >, std::__1::basic_string_view<char16_t, std::__1::char_traits<char16_t> >*)
368
template <typename charT, typename traits = std::char_traits<charT>>
369
constexpr bool ends_with(std::basic_string_view<charT, traits> sv, charT x,
370
                         std::basic_string_view<charT, traits>* rest) noexcept
371
{
372
    assert(rest != nullptr);
373
    auto const found = ends_with(sv, x);
374
    if (found)
375
    {
376
        *rest = sv.substr(0, sv.length() - 1);
377
    }
378
    return found;
379
}
380
template <typename charT, typename traits = std::char_traits<charT>>
381
constexpr bool ends_with(std::basic_string_view<charT, traits> sv, charT const* x,
382
                         std::basic_string_view<charT, traits>* rest)
383
5
{
384
5
    assert(rest != nullptr);
385
5
    auto const found = ends_with(sv, x);
386
5
    if (found)
387
5
    {
388
5
        *rest = sv.substr(0, sv.length() - traits::length(x));
389
5
    }
390
5
    return found;
391
5
}
392
// The following overloads prevent deduction failures that would occur with their template
393
// counterparts, when x is of a type that is implicitly convertible to basic_string_view (like
394
// OString or OUString, and we only bother to provide overloads for the char and char16_t cases, not
395
// also for char32_t and wchar_t, nor for C++20 char8_t):
396
constexpr bool starts_with(std::string_view sv, std::string_view x, std::string_view* rest) noexcept
397
0
{
398
0
    return starts_with<char>(sv, x, rest);
399
0
}
400
constexpr bool starts_with(std::u16string_view sv, std::u16string_view x,
401
                           std::u16string_view* rest) noexcept
402
158k
{
403
158k
    return starts_with<char16_t>(sv, x, rest);
404
158k
}
405
constexpr bool ends_with(std::string_view sv, std::string_view x, std::string_view* rest) noexcept
406
0
{
407
0
    return ends_with<char>(sv, x, rest);
408
0
}
409
constexpr bool ends_with(std::u16string_view sv, std::u16string_view x,
410
                         std::u16string_view* rest) noexcept
411
0
{
412
0
    return ends_with<char16_t>(sv, x, rest);
413
0
}
414
415
namespace internal
416
{
417
inline bool implIsWhitespace(sal_Unicode c)
418
112M
{
419
    /* Space or Control character? */
420
112M
    if ((c <= 32) && c)
421
9.50M
        return true;
422
423
    /* Only in the General Punctuation area Space or Control characters are included? */
424
102M
    if ((c < 0x2000) || (c > 0x2029))
425
102M
        return false;
426
427
22.5k
    if ((c <= 0x200B) || /* U+2000 - U+200B All Spaces */
428
20.0k
        (c >= 0x2028)) /* U+2028 LINE SEPARATOR, U+2029 PARAGRAPH SEPARATOR */
429
3.60k
        return true;
430
431
18.8k
    return false;
432
22.5k
}
433
} // namespace internal
434
435
// Like OUString::trim, but for std::[u16]string_view:
436
template <typename charT, typename traits = std::char_traits<charT>>
437
std::basic_string_view<charT, traits> trim(std::basic_string_view<charT, traits> str)
438
4.09M
{
439
4.09M
    auto pFirst = str.data();
440
4.09M
    auto pLast = pFirst + str.size();
441
442
11.5M
    while ((pFirst < pLast) && internal::implIsWhitespace(*pFirst))
443
7.43M
        ++pFirst;
444
445
4.09M
    if (pFirst == pLast)
446
1.09M
        return {};
447
448
3.00M
    do
449
4.92M
        --pLast;
450
4.92M
    while (internal::implIsWhitespace(*pLast));
451
452
3.00M
    return std::basic_string_view<charT, traits>(pFirst, pLast - pFirst + 1);
453
4.09M
}
std::__1::basic_string_view<char, std::__1::char_traits<char> > o3tl::trim<char, std::__1::char_traits<char> >(std::__1::basic_string_view<char, std::__1::char_traits<char> >)
Line
Count
Source
438
5.24k
{
439
5.24k
    auto pFirst = str.data();
440
5.24k
    auto pLast = pFirst + str.size();
441
442
5.37k
    while ((pFirst < pLast) && internal::implIsWhitespace(*pFirst))
443
136
        ++pFirst;
444
445
5.24k
    if (pFirst == pLast)
446
1
        return {};
447
448
5.24k
    do
449
5.24k
        --pLast;
450
5.24k
    while (internal::implIsWhitespace(*pLast));
451
452
5.24k
    return std::basic_string_view<charT, traits>(pFirst, pLast - pFirst + 1);
453
5.24k
}
std::__1::basic_string_view<char16_t, std::__1::char_traits<char16_t> > o3tl::trim<char16_t, std::__1::char_traits<char16_t> >(std::__1::basic_string_view<char16_t, std::__1::char_traits<char16_t> >)
Line
Count
Source
438
4.09M
{
439
4.09M
    auto pFirst = str.data();
440
4.09M
    auto pLast = pFirst + str.size();
441
442
11.5M
    while ((pFirst < pLast) && internal::implIsWhitespace(*pFirst))
443
7.43M
        ++pFirst;
444
445
4.09M
    if (pFirst == pLast)
446
1.09M
        return {};
447
448
2.99M
    do
449
4.92M
        --pLast;
450
4.92M
    while (internal::implIsWhitespace(*pLast));
451
452
2.99M
    return std::basic_string_view<charT, traits>(pFirst, pLast - pFirst + 1);
453
4.09M
}
454
455
// "deduction guides"
456
457
5.24k
inline auto trim(std::string_view str) { return trim<>(str); }
458
4.09M
inline auto trim(std::u16string_view str) { return trim<>(str); }
459
460
// Like OString::toInt32, but for std::string_view:
461
inline sal_Int32 toInt32(std::u16string_view str, sal_Int16 radix = 10)
462
78.5M
{
463
78.5M
    sal_Int64 n = rtl_ustr_toInt64_WithLength(str.data(), radix, str.size());
464
78.5M
    if (n < SAL_MIN_INT32 || n > SAL_MAX_INT32)
465
52.5k
        n = 0;
466
78.5M
    return n;
467
78.5M
}
468
inline sal_Int32 toInt32(std::string_view str, sal_Int16 radix = 10)
469
10.3M
{
470
10.3M
    sal_Int64 n = rtl_str_toInt64_WithLength(str.data(), radix, str.size());
471
10.3M
    if (n < SAL_MIN_INT32 || n > SAL_MAX_INT32)
472
3.83k
        n = 0;
473
10.3M
    return n;
474
10.3M
}
475
476
// Like OString::toUInt32, but for std::string_view:
477
inline sal_uInt32 toUInt32(std::u16string_view str, sal_Int16 radix = 10)
478
6.30k
{
479
6.30k
    sal_Int64 n = rtl_ustr_toInt64_WithLength(str.data(), radix, str.size());
480
6.30k
    if (n < 0 || n > SAL_MAX_UINT32)
481
0
        n = 0;
482
6.30k
    return n;
483
6.30k
}
484
inline sal_uInt32 toUInt32(std::string_view str, sal_Int16 radix = 10)
485
349k
{
486
349k
    sal_Int64 n = rtl_str_toInt64_WithLength(str.data(), radix, str.size());
487
349k
    if (n < 0 || n > SAL_MAX_UINT32)
488
1
        n = 0;
489
349k
    return n;
490
349k
}
491
492
// Like OString::toInt64, but for std::string_view:
493
inline sal_Int64 toInt64(std::u16string_view str, sal_Int16 radix = 10)
494
23.1k
{
495
23.1k
    return rtl_ustr_toInt64_WithLength(str.data(), radix, str.size());
496
23.1k
}
497
inline sal_Int64 toInt64(std::string_view str, sal_Int16 radix = 10)
498
41.6k
{
499
41.6k
    return rtl_str_toInt64_WithLength(str.data(), radix, str.size());
500
41.6k
}
501
502
// Like OString::toDouble, but for std::string_view:
503
inline double toDouble(std::u16string_view str)
504
761
{
505
761
    return rtl_math_uStringToDouble(str.data(), str.data() + str.size(), '.', 0, nullptr, nullptr);
506
761
}
507
inline double toDouble(std::string_view str)
508
970k
{
509
970k
    return rtl_math_stringToDouble(str.data(), str.data() + str.size(), '.', 0, nullptr, nullptr);
510
970k
}
511
512
// Like OUString::iterateCodePoints, but for std::string_view:
513
template <typename T>
514
requires(std::is_same_v<T, sal_Int32> || std::is_same_v<T, std::size_t>) sal_uInt32
515
    iterateCodePoints(std::u16string_view string, T* indexUtf16, sal_Int32 incrementCodePoints = 1)
516
4.02G
{
517
4.02G
    std::size_t n;
518
4.02G
    char16_t cu;
519
4.02G
    sal_uInt32 cp;
520
4.02G
    assert(indexUtf16 != nullptr);
521
4.02G
    n = *indexUtf16;
522
4.02G
    assert(n <= string.length());
523
4.09G
    while (incrementCodePoints < 0)
524
67.0M
    {
525
67.0M
        assert(n > 0);
526
67.0M
        cu = string[--n];
527
67.0M
        if (rtl::isLowSurrogate(cu) && n != 0 && rtl::isHighSurrogate(string[n - 1]))
528
80.1k
        {
529
80.1k
            --n;
530
80.1k
        }
531
67.0M
        ++incrementCodePoints;
532
67.0M
    }
533
4.02G
    assert(n < string.length());
534
4.02G
    cu = string[n];
535
4.02G
    if (rtl::isHighSurrogate(cu) && string.length() - n >= 2 && rtl::isLowSurrogate(string[n + 1]))
536
2.59M
    {
537
2.59M
        cp = rtl::combineSurrogates(cu, string[n + 1]);
538
2.59M
    }
539
4.02G
    else
540
4.02G
    {
541
4.02G
        cp = cu;
542
4.02G
    }
543
6.77G
    while (incrementCodePoints > 0)
544
2.74G
    {
545
2.74G
        assert(n < string.length());
546
2.74G
        cu = string[n++];
547
2.74G
        if (rtl::isHighSurrogate(cu) && n != string.length() && rtl::isLowSurrogate(string[n]))
548
1.40M
        {
549
1.40M
            ++n;
550
1.40M
        }
551
2.74G
        --incrementCodePoints;
552
2.74G
    }
553
    assert(n <= string.length());
554
4.02G
    *indexUtf16 = n;
555
4.02G
    return cp;
556
4.02G
}
_ZN4o3tl17iterateCodePointsIiQoosr3stdE9is_same_vIT_iEsr3stdE9is_same_vIS1_mEEEjNSt3__117basic_string_viewIDsNS2_11char_traitsIDsEEEEPS1_i
Line
Count
Source
516
4.02G
{
517
4.02G
    std::size_t n;
518
4.02G
    char16_t cu;
519
4.02G
    sal_uInt32 cp;
520
4.02G
    assert(indexUtf16 != nullptr);
521
4.02G
    n = *indexUtf16;
522
4.02G
    assert(n <= string.length());
523
4.09G
    while (incrementCodePoints < 0)
524
67.0M
    {
525
67.0M
        assert(n > 0);
526
67.0M
        cu = string[--n];
527
67.0M
        if (rtl::isLowSurrogate(cu) && n != 0 && rtl::isHighSurrogate(string[n - 1]))
528
80.1k
        {
529
80.1k
            --n;
530
80.1k
        }
531
67.0M
        ++incrementCodePoints;
532
67.0M
    }
533
4.02G
    assert(n < string.length());
534
4.02G
    cu = string[n];
535
4.02G
    if (rtl::isHighSurrogate(cu) && string.length() - n >= 2 && rtl::isLowSurrogate(string[n + 1]))
536
2.59M
    {
537
2.59M
        cp = rtl::combineSurrogates(cu, string[n + 1]);
538
2.59M
    }
539
4.02G
    else
540
4.02G
    {
541
4.02G
        cp = cu;
542
4.02G
    }
543
6.77G
    while (incrementCodePoints > 0)
544
2.74G
    {
545
2.74G
        assert(n < string.length());
546
2.74G
        cu = string[n++];
547
2.74G
        if (rtl::isHighSurrogate(cu) && n != string.length() && rtl::isLowSurrogate(string[n]))
548
1.40M
        {
549
1.40M
            ++n;
550
1.40M
        }
551
2.74G
        --incrementCodePoints;
552
2.74G
    }
553
    assert(n <= string.length());
554
4.02G
    *indexUtf16 = n;
555
4.02G
    return cp;
556
4.02G
}
Unexecuted instantiation: _ZN4o3tl17iterateCodePointsImQoosr3stdE9is_same_vIT_iEsr3stdE9is_same_vIS1_mEEEjNSt3__117basic_string_viewIDsNS2_11char_traitsIDsEEEEPS1_i
557
558
} // namespace
559
560
/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */