summaryrefslogtreecommitdiffstats
path: root/include/o3tl/string_view.hxx
blob: 4cb9790900f6d47f7306044df50bf7a2218cb682 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */
/*
 * This file is part of the LibreOffice project.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 */

#pragma once

#include <sal/config.h>

#include <cassert>
#include <cstddef>
#include <string>
#include <string_view>
#include <type_traits>

#include <rtl/ustring.h>

namespace o3tl
{
// Like OUString::equalsIgnoreAsciiCase, but for two std::u16string_view:
inline bool equalsIgnoreAsciiCase(std::u16string_view s1, std::u16string_view s2)
{
    return rtl_ustr_compareIgnoreAsciiCase_WithLength(s1.data(), s1.size(), s2.data(), s2.size());
};

// Similar to OString::getToken, returning the first token of a std::string_view, starting at a
// given position (and if needed, it can be turned into a template to also cover std::u16string_view
// etc., or extended to return the n'th token instead of just the first, or support an initial
// position of npos):
inline std::string_view getToken(std::string_view sv, char delimiter, std::size_t& position)
{
    assert(position <= sv.size());
    auto const n = sv.find(delimiter, position);
    std::string_view t;
    if (n == std::string_view::npos)
    {
        t = sv.substr(position);
        position = std::string_view::npos;
    }
    else
    {
        t = sv.substr(position, n - position);
        position = n + 1;
    }
    return t;
}

// Implementations of C++20 std::basic_string_view::starts_with and
// std::basic_string_view::ends_with, until we can use those directly on all platforms:
template <typename charT, typename traits = std::char_traits<charT>>
constexpr bool starts_with(std::basic_string_view<charT, traits> sv,
                           std::basic_string_view<charT, traits> x) noexcept
{
#if defined __cpp_lib_starts_ends_with
    return sv.starts_with(x);
#else
    return sv.substr(0, x.size()) == x;
#endif
}
template <typename charT, typename traits = std::char_traits<charT>>
constexpr bool starts_with(std::basic_string_view<charT, traits> sv, charT x) noexcept
{
#if defined __cpp_lib_starts_ends_with
    return sv.starts_with(x);
#else
    return !sv.empty() && traits::eq(sv.front(), x);
#endif
}
template <typename charT, typename traits = std::char_traits<charT>>
constexpr bool starts_with(std::basic_string_view<charT, traits> sv, charT const* x)
{
#if defined __cpp_lib_starts_ends_with
    return sv.starts_with(x);
#else
    return starts_with(sv, std::basic_string_view<charT, traits>(x));
#endif
}
template <typename charT, typename traits = std::char_traits<charT>>
constexpr bool ends_with(std::basic_string_view<charT, traits> sv,
                         std::basic_string_view<charT, traits> x) noexcept
{
#if defined __cpp_lib_ends_ends_with
    return sv.ends_with(x);
#else
    return sv.size() >= x.size()
           && sv.compare(sv.size() - x.size(), std::basic_string_view<charT, traits>::npos, x) == 0;
#endif
}
template <typename charT, typename traits = std::char_traits<charT>>
constexpr bool ends_with(std::basic_string_view<charT, traits> sv, charT x) noexcept
{
#if defined __cpp_lib_ends_ends_with
    return sv.ends_with(x);
#else
    return !sv.empty() && traits::eq(sv.back(), x);
#endif
}
template <typename charT, typename traits = std::char_traits<charT>>
constexpr bool ends_with(std::basic_string_view<charT, traits> sv, charT const* x)
{
#if defined __cpp_lib_ends_ends_with
    return sv.ends_with(x);
#else
    return ends_with(sv, std::basic_string_view<charT, traits>(x));
#endif
}
// The following overloads prevent deduction failures that would occur with their template
// counterparts, when x is of a type that is implicitly convertible to basic_string_view (like
// OString or OUString, and we only bother to provide overloads for the char and char16_t cases, not
// also for char32_t and wchar_t, nor for C++20 char8_t):
constexpr bool starts_with(std::string_view sv, std::string_view x) noexcept
{
    return starts_with<char>(sv, x);
}
constexpr bool starts_with(std::u16string_view sv, std::u16string_view x) noexcept
{
    return starts_with<char16_t>(sv, x);
}
constexpr bool ends_with(std::string_view sv, std::string_view x) noexcept
{
    return ends_with<char>(sv, x);
}
constexpr bool ends_with(std::u16string_view sv, std::u16string_view x) noexcept
{
    return ends_with<char16_t>(sv, x);
}

// Variants of C++20 std::basic_string_view::starts_with and
// std::basic_string_view::ends_with that have a rest out parameter, similar to our OString and
// OUString startsWith and endsWith member functions:
template <typename charT, typename traits = std::char_traits<charT>>
constexpr bool starts_with(std::basic_string_view<charT, traits> sv,
                           std::basic_string_view<charT, traits> x,
                           std::basic_string_view<charT, traits>* rest) noexcept
{
    assert(rest != nullptr);
    auto const found = starts_with(sv, x);
    if (found)
    {
        *rest = sv.substr(x.length());
    }
    return found;
}
template <typename charT, typename traits = std::char_traits<charT>>
constexpr bool starts_with(std::basic_string_view<charT, traits> sv, charT x,
                           std::basic_string_view<charT, traits>* rest) noexcept
{
    assert(rest != nullptr);
    auto const found = starts_with(sv, x);
    if (found)
    {
        *rest = sv.substr(1);
    }
    return found;
}
template <typename charT, typename traits = std::char_traits<charT>>
constexpr bool starts_with(std::basic_string_view<charT, traits> sv, charT const* x,
                           std::basic_string_view<charT, traits>* rest)
{
    assert(rest != nullptr);
    auto const found = starts_with(sv, x);
    if (found)
    {
        *rest = sv.substr(traits::length(x));
    }
    return found;
}
template <typename charT, typename traits = std::char_traits<charT>>
constexpr bool ends_with(std::basic_string_view<charT, traits> sv,
                         std::basic_string_view<charT, traits> x,
                         std::basic_string_view<charT, traits>* rest) noexcept
{
    assert(rest != nullptr);
    auto const found = ends_with(sv, x);
    if (found)
    {
        *rest = sv.substr(0, sv.length() - x.length());
    }
    return found;
}
template <typename charT, typename traits = std::char_traits<charT>>
constexpr bool ends_with(std::basic_string_view<charT, traits> sv, charT x,
                         std::basic_string_view<charT, traits>* rest) noexcept
{
    assert(rest != nullptr);
    auto const found = ends_with(sv, x);
    if (found)
    {
        *rest = sv.substr(0, sv.length() - 1);
    }
    return found;
}
template <typename charT, typename traits = std::char_traits<charT>>
constexpr bool ends_with(std::basic_string_view<charT, traits> sv, charT const* x,
                         std::basic_string_view<charT, traits>* rest)
{
    assert(rest != nullptr);
    auto const found = ends_with(sv, x);
    if (found)
    {
        *rest = sv.substr(0, sv.length() - traits::length(x));
    }
    return found;
}
// The following overloads prevent deduction failures that would occur with their template
// counterparts, when x is of a type that is implicitly convertible to basic_string_view (like
// OString or OUString, and we only bother to provide overloads for the char and char16_t cases, not
// also for char32_t and wchar_t, nor for C++20 char8_t):
constexpr bool starts_with(std::string_view sv, std::string_view x, std::string_view* rest) noexcept
{
    return starts_with<char>(sv, x, rest);
}
constexpr bool starts_with(std::u16string_view sv, std::u16string_view x,
                           std::u16string_view* rest) noexcept
{
    return starts_with<char16_t>(sv, x, rest);
}
constexpr bool ends_with(std::string_view sv, std::string_view x, std::string_view* rest) noexcept
{
    return ends_with<char>(sv, x, rest);
}
constexpr bool ends_with(std::u16string_view sv, std::u16string_view x,
                         std::u16string_view* rest) noexcept
{
    return ends_with<char16_t>(sv, x, rest);
}
}

/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */