Coverage Report

Created: 2025-07-07 10:01

/src/libreoffice/include/o3tl/string_view.hxx
Line
Count
Source (jump to first uncovered line)
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
37.1M
{
31
37.1M
    return s1.size() == s2.size()
32
37.1M
           && rtl_ustr_ascii_shortenedCompare_WithLength(s1.data(), s1.size(), s2.data(), s2.size())
33
1.08M
                  == 0;
34
37.1M
}
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
652k
{
45
652k
    if (s1.size() != s2.size())
46
289k
        return false;
47
363k
    if (s1.data() == s2.data())
48
1
        return true;
49
363k
    return rtl_ustr_compareIgnoreAsciiCase_WithLength(s1.data(), s1.size(), s2.data(), s2.size())
50
363k
           == 0;
51
363k
};
52
53
inline bool equalsIgnoreAsciiCase(std::u16string_view s1, std::string_view s2)
54
3.34M
{
55
3.34M
    return s1.size() == s2.size()
56
3.34M
           && (rtl_ustr_ascii_shortenedCompareIgnoreAsciiCase_WithLength(s1.data(), s1.size(),
57
193k
                                                                         s2.data(), s2.size())
58
193k
               == 0);
59
3.34M
}
60
61
inline bool equalsIgnoreAsciiCase(std::string_view s1, std::string_view s2)
62
0
{
63
0
    if (s1.size() != s2.size())
64
0
        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
12.3M
{
74
12.3M
    return rtl_ustr_compareIgnoreAsciiCase_WithLength(s1.data(), s1.size(), s2.data(), s2.size());
75
12.3M
};
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.64M
{
81
6.64M
    return rtl_ustr_shortenedCompareIgnoreAsciiCase_WithLength(
82
6.64M
               s1.data() + fromIndex, s1.size() - fromIndex, s2.data(), s2.size(), s2.size())
83
6.64M
           == 0;
84
6.64M
}
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
352k
{
90
352k
    return rtl_ustr_ascii_shortenedCompareIgnoreAsciiCase_WithLength(
91
352k
               s1.data() + fromIndex, s1.size() - fromIndex, s2.data(), s2.size())
92
352k
           == 0;
93
352k
}
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
51.0k
{
132
51.0k
    assert(position <= sv.size());
133
51.0k
    auto const n = sv.find(delimiter, position);
134
51.0k
    std::basic_string_view<charT, traits> t;
135
51.0k
    if (n == std::string_view::npos)
136
27.3k
    {
137
27.3k
        t = sv.substr(position);
138
27.3k
        position = std::string_view::npos;
139
27.3k
    }
140
23.7k
    else
141
23.7k
    {
142
23.7k
        t = sv.substr(position, n - position);
143
23.7k
        position = n + 1;
144
23.7k
    }
145
51.0k
    return t;
146
51.0k
}
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
41.3k
{
132
41.3k
    assert(position <= sv.size());
133
41.3k
    auto const n = sv.find(delimiter, position);
134
41.3k
    std::basic_string_view<charT, traits> t;
135
41.3k
    if (n == std::string_view::npos)
136
19.6k
    {
137
19.6k
        t = sv.substr(position);
138
19.6k
        position = std::string_view::npos;
139
19.6k
    }
140
21.6k
    else
141
21.6k
    {
142
21.6k
        t = sv.substr(position, n - position);
143
21.6k
        position = n + 1;
144
21.6k
    }
145
41.3k
    return t;
146
41.3k
}
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
9.73k
{
132
9.73k
    assert(position <= sv.size());
133
9.73k
    auto const n = sv.find(delimiter, position);
134
9.73k
    std::basic_string_view<charT, traits> t;
135
9.73k
    if (n == std::string_view::npos)
136
7.65k
    {
137
7.65k
        t = sv.substr(position);
138
7.65k
        position = std::string_view::npos;
139
7.65k
    }
140
2.08k
    else
141
2.08k
    {
142
2.08k
        t = sv.substr(position, n - position);
143
2.08k
        position = n + 1;
144
2.08k
    }
145
9.73k
    return t;
146
9.73k
}
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
9.73k
{
154
9.73k
    return getToken<char>(sv, delimiter, position);
155
9.73k
}
156
inline std::u16string_view getToken(std::u16string_view sv, char16_t delimiter,
157
                                    std::size_t& position)
158
41.3k
{
159
41.3k
    return getToken<char16_t>(sv, delimiter, position);
160
41.3k
}
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.72M
{
172
4.72M
    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.72M
    if (rnIndex >= 0 && nToken >= 0)
177
4.71M
    {
178
4.71M
        const charT* pOrgCharStr = pStr.data();
179
4.71M
        const charT* pCharStr = pOrgCharStr + rnIndex;
180
4.71M
        sal_Int32 nLen = pStr.size() - rnIndex;
181
4.71M
        sal_Int32 nTokCount = 0;
182
4.71M
        const charT* pCharStrStart = pCharStr;
183
195M
        while (nLen > 0)
184
192M
        {
185
192M
            if (*pCharStr == cTok)
186
1.78M
            {
187
1.78M
                nTokCount++;
188
189
1.78M
                if (nTokCount > nToken)
190
1.56M
                    break;
191
223k
                if (nTokCount == nToken)
192
223k
                    pCharStrStart = pCharStr + 1;
193
223k
            }
194
195
190M
            pCharStr++;
196
190M
            nLen--;
197
190M
        }
198
4.71M
        if (nTokCount >= nToken)
199
4.71M
        {
200
4.71M
            if (nLen > 0)
201
1.56M
                rnIndex = pCharStr - pOrgCharStr + 1;
202
3.14M
            else
203
3.14M
                rnIndex = -1;
204
4.71M
            return std::basic_string_view<charT, traits>(pCharStrStart, pCharStr - pCharStrStart);
205
4.71M
        }
206
4.71M
    }
207
208
12.7k
    rnIndex = -1;
209
12.7k
    return std::basic_string_view<charT, traits>();
210
4.72M
}
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.72M
{
172
4.72M
    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.72M
    if (rnIndex >= 0 && nToken >= 0)
177
4.71M
    {
178
4.71M
        const charT* pOrgCharStr = pStr.data();
179
4.71M
        const charT* pCharStr = pOrgCharStr + rnIndex;
180
4.71M
        sal_Int32 nLen = pStr.size() - rnIndex;
181
4.71M
        sal_Int32 nTokCount = 0;
182
4.71M
        const charT* pCharStrStart = pCharStr;
183
195M
        while (nLen > 0)
184
192M
        {
185
192M
            if (*pCharStr == cTok)
186
1.78M
            {
187
1.78M
                nTokCount++;
188
189
1.78M
                if (nTokCount > nToken)
190
1.56M
                    break;
191
223k
                if (nTokCount == nToken)
192
223k
                    pCharStrStart = pCharStr + 1;
193
223k
            }
194
195
190M
            pCharStr++;
196
190M
            nLen--;
197
190M
        }
198
4.71M
        if (nTokCount >= nToken)
199
4.71M
        {
200
4.71M
            if (nLen > 0)
201
1.56M
                rnIndex = pCharStr - pOrgCharStr + 1;
202
3.14M
            else
203
3.14M
                rnIndex = -1;
204
4.71M
            return std::basic_string_view<charT, traits>(pCharStrStart, pCharStr - pCharStrStart);
205
4.71M
        }
206
4.71M
    }
207
208
12.7k
    rnIndex = -1;
209
12.7k
    return std::basic_string_view<charT, traits>();
210
4.72M
}
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.63M
{
222
4.63M
    return getToken<char16_t>(sv, nToken, cTok, rnIndex);
223
4.63M
}
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
86.3k
{
231
86.3k
    sal_Int32 nIndex = 0;
232
86.3k
    return getToken<char16_t>(sv, nToken, cTok, nIndex);
233
86.3k
}
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
118M
{
241
118M
#if defined __cpp_lib_starts_ends_with
242
118M
    return sv.starts_with(x);
243
#else
244
    return sv.substr(0, x.size()) == x;
245
#endif
246
118M
}
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> >)
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
118M
{
241
118M
#if defined __cpp_lib_starts_ends_with
242
118M
    return sv.starts_with(x);
243
#else
244
    return sv.substr(0, x.size()) == x;
245
#endif
246
118M
}
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
5.19M
{
259
5.19M
#if defined __cpp_lib_starts_ends_with
260
5.19M
    return sv.starts_with(x);
261
#else
262
    return starts_with(sv, std::basic_string_view<charT, traits>(x));
263
#endif
264
5.19M
}
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
5.19M
{
259
5.19M
#if defined __cpp_lib_starts_ends_with
260
5.19M
    return sv.starts_with(x);
261
#else
262
    return starts_with(sv, std::basic_string_view<charT, traits>(x));
263
#endif
264
5.19M
}
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
808
{
259
808
#if defined __cpp_lib_starts_ends_with
260
808
    return sv.starts_with(x);
261
#else
262
    return starts_with(sv, std::basic_string_view<charT, traits>(x));
263
#endif
264
808
}
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.80M
{
269
1.80M
#if defined __cpp_lib_starts_ends_with
270
1.80M
    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.80M
}
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.80M
{
269
1.80M
#if defined __cpp_lib_starts_ends_with
270
1.80M
    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.80M
}
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.31M
{
288
1.31M
#if defined __cpp_lib_starts_ends_with
289
1.31M
    return sv.ends_with(x);
290
#else
291
    return ends_with(sv, std::basic_string_view<charT, traits>(x));
292
#endif
293
1.31M
}
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
0
{
300
0
    return starts_with<char>(sv, x);
301
0
}
302
constexpr bool starts_with(std::u16string_view sv, std::u16string_view x) noexcept
303
118M
{
304
118M
    return starts_with<char16_t>(sv, x);
305
118M
}
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.80M
{
312
1.80M
    return ends_with<char16_t>(sv, x);
313
1.80M
}
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
3.49k
{
323
3.49k
    assert(rest != nullptr);
324
3.49k
    auto const found = starts_with(sv, x);
325
3.49k
    if (found)
326
1.22k
    {
327
1.22k
        *rest = sv.substr(x.length());
328
1.22k
    }
329
3.49k
    return found;
330
3.49k
}
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
3.49k
{
323
3.49k
    assert(rest != nullptr);
324
3.49k
    auto const found = starts_with(sv, x);
325
3.49k
    if (found)
326
1.22k
    {
327
1.22k
        *rest = sv.substr(x.length());
328
1.22k
    }
329
3.49k
    return found;
330
3.49k
}
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
345k
{
347
345k
    assert(rest != nullptr);
348
345k
    auto const found = starts_with(sv, x);
349
345k
    if (found)
350
155k
    {
351
155k
        *rest = sv.substr(traits::length(x));
352
155k
    }
353
345k
    return found;
354
345k
}
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
345k
{
347
345k
    assert(rest != nullptr);
348
345k
    auto const found = starts_with(sv, x);
349
345k
    if (found)
350
155k
    {
351
155k
        *rest = sv.substr(traits::length(x));
352
155k
    }
353
345k
    return found;
354
345k
}
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
3.49k
{
403
3.49k
    return starts_with<char16_t>(sv, x, rest);
404
3.49k
}
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
161M
{
419
    /* Space or Control character? */
420
161M
    if ((c <= 32) && c)
421
9.50M
        return true;
422
423
    /* Only in the General Punctuation area Space or Control characters are included? */
424
152M
    if ((c < 0x2000) || (c > 0x2029))
425
152M
        return false;
426
427
14.7k
    if ((c <= 0x200B) || /* U+2000 - U+200B All Spaces */
428
14.7k
        (c >= 0x2028)) /* U+2028 LINE SEPARATOR, U+2029 PARAGRAPH SEPARATOR */
429
1.43k
        return true;
430
431
13.3k
    return false;
432
14.7k
}
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.44M
{
439
4.44M
    auto pFirst = str.data();
440
4.44M
    auto pLast = pFirst + str.size();
441
442
12.5M
    while ((pFirst < pLast) && internal::implIsWhitespace(*pFirst))
443
8.10M
        ++pFirst;
444
445
4.44M
    if (pFirst == pLast)
446
1.42M
        return {};
447
448
3.01M
    do
449
4.27M
        --pLast;
450
4.27M
    while (internal::implIsWhitespace(*pLast));
451
452
3.01M
    return std::basic_string_view<charT, traits>(pFirst, pLast - pFirst + 1);
453
4.44M
}
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
7.95k
{
439
7.95k
    auto pFirst = str.data();
440
7.95k
    auto pLast = pFirst + str.size();
441
442
8.43k
    while ((pFirst < pLast) && internal::implIsWhitespace(*pFirst))
443
477
        ++pFirst;
444
445
7.95k
    if (pFirst == pLast)
446
6
        return {};
447
448
7.94k
    do
449
7.95k
        --pLast;
450
7.95k
    while (internal::implIsWhitespace(*pLast));
451
452
7.94k
    return std::basic_string_view<charT, traits>(pFirst, pLast - pFirst + 1);
453
7.95k
}
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.43M
{
439
4.43M
    auto pFirst = str.data();
440
4.43M
    auto pLast = pFirst + str.size();
441
442
12.5M
    while ((pFirst < pLast) && internal::implIsWhitespace(*pFirst))
443
8.10M
        ++pFirst;
444
445
4.43M
    if (pFirst == pLast)
446
1.42M
        return {};
447
448
3.01M
    do
449
4.26M
        --pLast;
450
4.26M
    while (internal::implIsWhitespace(*pLast));
451
452
3.01M
    return std::basic_string_view<charT, traits>(pFirst, pLast - pFirst + 1);
453
4.43M
}
454
455
// "deduction guides"
456
457
7.95k
inline auto trim(std::string_view str) { return trim<>(str); }
458
4.43M
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
125M
{
463
125M
    sal_Int64 n = rtl_ustr_toInt64_WithLength(str.data(), radix, str.size());
464
125M
    if (n < SAL_MIN_INT32 || n > SAL_MAX_INT32)
465
20.3k
        n = 0;
466
125M
    return n;
467
125M
}
468
inline sal_Int32 toInt32(std::string_view str, sal_Int16 radix = 10)
469
10.1M
{
470
10.1M
    sal_Int64 n = rtl_str_toInt64_WithLength(str.data(), radix, str.size());
471
10.1M
    if (n < SAL_MIN_INT32 || n > SAL_MAX_INT32)
472
4.16k
        n = 0;
473
10.1M
    return n;
474
10.1M
}
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.69k
{
479
6.69k
    sal_Int64 n = rtl_ustr_toInt64_WithLength(str.data(), radix, str.size());
480
6.69k
    if (n < 0 || n > SAL_MAX_UINT32)
481
0
        n = 0;
482
6.69k
    return n;
483
6.69k
}
484
inline sal_uInt32 toUInt32(std::string_view str, sal_Int16 radix = 10)
485
422k
{
486
422k
    sal_Int64 n = rtl_str_toInt64_WithLength(str.data(), radix, str.size());
487
422k
    if (n < 0 || n > SAL_MAX_UINT32)
488
1
        n = 0;
489
422k
    return n;
490
422k
}
491
492
// Like OString::toInt64, but for std::string_view:
493
inline sal_Int64 toInt64(std::u16string_view str, sal_Int16 radix = 10)
494
34.8k
{
495
34.8k
    return rtl_ustr_toInt64_WithLength(str.data(), radix, str.size());
496
34.8k
}
497
inline sal_Int64 toInt64(std::string_view str, sal_Int16 radix = 10)
498
7.74k
{
499
7.74k
    return rtl_str_toInt64_WithLength(str.data(), radix, str.size());
500
7.74k
}
501
502
// Like OString::toDouble, but for std::string_view:
503
inline double toDouble(std::u16string_view str)
504
511
{
505
511
    return rtl_math_uStringToDouble(str.data(), str.data() + str.size(), '.', 0, nullptr, nullptr);
506
511
}
507
inline double toDouble(std::string_view str)
508
950k
{
509
950k
    return rtl_math_stringToDouble(str.data(), str.data() + str.size(), '.', 0, nullptr, nullptr);
510
950k
}
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.50G
{
517
4.50G
    std::size_t n;
518
4.50G
    char16_t cu;
519
4.50G
    sal_uInt32 cp;
520
4.50G
    assert(indexUtf16 != nullptr);
521
4.50G
    n = *indexUtf16;
522
4.50G
    assert(n <= string.length());
523
4.56G
    while (incrementCodePoints < 0)
524
64.7M
    {
525
64.7M
        assert(n > 0);
526
64.7M
        cu = string[--n];
527
64.7M
        if (rtl::isLowSurrogate(cu) && n != 0 && rtl::isHighSurrogate(string[n - 1]))
528
66.9k
        {
529
66.9k
            --n;
530
66.9k
        }
531
64.7M
        ++incrementCodePoints;
532
64.7M
    }
533
4.50G
    assert(n < string.length());
534
4.50G
    cu = string[n];
535
4.50G
    if (rtl::isHighSurrogate(cu) && string.length() - n >= 2 && rtl::isLowSurrogate(string[n + 1]))
536
2.00M
    {
537
2.00M
        cp = rtl::combineSurrogates(cu, string[n + 1]);
538
2.00M
    }
539
4.50G
    else
540
4.50G
    {
541
4.50G
        cp = cu;
542
4.50G
    }
543
7.94G
    while (incrementCodePoints > 0)
544
3.43G
    {
545
3.43G
        assert(n < string.length());
546
3.43G
        cu = string[n++];
547
3.43G
        if (rtl::isHighSurrogate(cu) && n != string.length() && rtl::isLowSurrogate(string[n]))
548
1.40M
        {
549
1.40M
            ++n;
550
1.40M
        }
551
3.43G
        --incrementCodePoints;
552
3.43G
    }
553
4.50G
    assert(n <= string.length());
554
4.50G
    *indexUtf16 = n;
555
4.50G
    return cp;
556
4.50G
}
_ZN4o3tl17iterateCodePointsIiQoosr3stdE9is_same_vIT_iEsr3stdE9is_same_vIS1_mEEEjNSt3__117basic_string_viewIDsNS2_11char_traitsIDsEEEEPS1_i
Line
Count
Source
516
4.50G
{
517
4.50G
    std::size_t n;
518
4.50G
    char16_t cu;
519
4.50G
    sal_uInt32 cp;
520
4.50G
    assert(indexUtf16 != nullptr);
521
4.50G
    n = *indexUtf16;
522
4.50G
    assert(n <= string.length());
523
4.56G
    while (incrementCodePoints < 0)
524
64.7M
    {
525
64.7M
        assert(n > 0);
526
64.7M
        cu = string[--n];
527
64.7M
        if (rtl::isLowSurrogate(cu) && n != 0 && rtl::isHighSurrogate(string[n - 1]))
528
66.9k
        {
529
66.9k
            --n;
530
66.9k
        }
531
64.7M
        ++incrementCodePoints;
532
64.7M
    }
533
4.50G
    assert(n < string.length());
534
4.50G
    cu = string[n];
535
4.50G
    if (rtl::isHighSurrogate(cu) && string.length() - n >= 2 && rtl::isLowSurrogate(string[n + 1]))
536
2.00M
    {
537
2.00M
        cp = rtl::combineSurrogates(cu, string[n + 1]);
538
2.00M
    }
539
4.50G
    else
540
4.50G
    {
541
4.50G
        cp = cu;
542
4.50G
    }
543
7.94G
    while (incrementCodePoints > 0)
544
3.43G
    {
545
3.43G
        assert(n < string.length());
546
3.43G
        cu = string[n++];
547
3.43G
        if (rtl::isHighSurrogate(cu) && n != string.length() && rtl::isLowSurrogate(string[n]))
548
1.40M
        {
549
1.40M
            ++n;
550
1.40M
        }
551
3.43G
        --incrementCodePoints;
552
3.43G
    }
553
4.50G
    assert(n <= string.length());
554
4.50G
    *indexUtf16 = n;
555
4.50G
    return cp;
556
4.50G
}
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: */