-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathutf8_sv.hpp
More file actions
116 lines (96 loc) · 3.34 KB
/
Copy pathutf8_sv.hpp
File metadata and controls
116 lines (96 loc) · 3.34 KB
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
// Manipulate utf8 unicode charactars in a std::string_view converted
// string.
//
// Header-only file.
//
// Copyright (C) 2026, Martin Young <martin_young@live.cn>
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
//------------------------------------------------------------------------
#pragma once
#include <string_view>
#include <concepts>
#include <cstddef>
class utf8_sv {
private:
std::string_view sv_;
public:
static constexpr size_t npos = std::string_view::npos;
constexpr utf8_sv() noexcept = default;
template <typename T>
requires std::convertible_to<T, std::string_view>
constexpr utf8_sv(const T& str) noexcept : sv_(str) {}
constexpr operator std::string_view() const noexcept { return sv_; }
constexpr std::string_view base() const noexcept { return sv_; }
constexpr bool empty() const noexcept { return sv_.empty(); }
constexpr size_t length() const noexcept {
size_t count = 0;
for (char c : sv_) if ((c & 0xC0) != 0x80) count++;
return count;
}
constexpr std::string_view left(size_t n = npos) const noexcept {
if (n == 0) return {};
if (n == npos) return sv_;
size_t b_idx = 0;
size_t chars_seen = 0;
const size_t sz = sv_.size();
while (b_idx < sz) {
if ((sv_[b_idx] & 0xC0) != 0x80) {
if (chars_seen == n) break;
chars_seen++;
}
b_idx++;
}
return sv_.substr(0, b_idx);
}
constexpr std::string_view right(size_t n = npos) const noexcept {
if (n == 0) return {};
if (n == npos || sv_.empty()) return sv_;
size_t b_idx = sv_.size();
size_t chars_seen = 0;
while (b_idx > 0) {
b_idx--;
if ((sv_[b_idx] & 0xC0) != 0x80) {
chars_seen++;
if (chars_seen == n) break;
}
}
return sv_.substr(b_idx);
}
constexpr std::string_view substr(size_t pos = 0, size_t count = npos) const noexcept {
if (pos == 0 && count == npos) return sv_;
size_t b_idx = 0;
size_t chars_seen = 0;
const size_t sz = sv_.size();
while (b_idx < sz) {
if ((sv_[b_idx] & 0xC0) != 0x80) {
if (chars_seen == pos) break;
chars_seen++;
}
b_idx++;
}
if (b_idx == sz) return {};
if (count == npos) return sv_.substr(b_idx);
size_t end_idx = b_idx;
chars_seen = 0;
while (end_idx < sz) {
if ((sv_[end_idx] & 0xC0) != 0x80) {
if (chars_seen == count) break;
chars_seen++;
}
end_idx++;
}
return sv_.substr(b_idx, end_idx - b_idx);
}
};