OXYGENHUB
◆ main openmsx / src / utils / zstring_view.hh
5.2 KiB · C++ · last changed chore(): initial commit 1 month ago source blame history raw
1
#ifndef ZSTRING_VIEW_HH
2
#define ZSTRING_VIEW_HH
3
4
#include <cassert>
5
#include <cstring>
6
#include <iostream>
7
#include <string>
8
#include <string_view>
9
#include <type_traits>
10
11
/**
12
 * Like std::string_view, but with the extra guarantee that it refers to a
13
 * zero-terminated string. In other words it has this additional invariant:
14
 *    data()[size()] == '\0'
15
 *
16
 * Current version only implements a subset of the std::string_view API. That
17
 * is because:
18
 * - Some functions cannot be implemented (those that trim the tail).
19
 * - Most were not yet required. We can implement those on demand.
20
 */
21
class zstring_view
22
{
23
public:
24
	using size_type = size_t;
25
	using const_iterator = const char*;
26
27
	static constexpr auto npos = std::string_view::npos;
28
29
	constexpr zstring_view()
30
		: dat(nullptr), siz(0) {}
31
	constexpr zstring_view(const char* s)
32
		: dat(s), siz(std::char_traits<char>::length(s)) {}
33
	constexpr zstring_view(const char* s, size_t n)
34
		: dat(s), siz(n) { assert(s[n] == '\0'); }
35
	constexpr zstring_view(const std::string& s)
36
		: dat(s.c_str()), siz(s.size()) {}
37
38
	[[nodiscard]] constexpr auto begin() const { return dat; }
39
	[[nodiscard]] constexpr auto end()   const { return dat + siz; }
40
41
	[[nodiscard]] constexpr auto size()  const { return siz; }
42
	[[nodiscard]] constexpr auto empty() const { return siz == 0; }
43
44
	[[nodiscard]] constexpr char operator[](size_type i) const {
45
		assert(i < siz);
46
		return dat[i];
47
	}
48
	[[nodiscard]] constexpr char front() const { return *dat; }
49
	[[nodiscard]] constexpr char back() const { return *(dat + siz - 1); }
50
	[[nodiscard]] constexpr const char* data()  const { return dat; }
51
	[[nodiscard]] constexpr const char* c_str() const { return dat; }
52
53
	[[nodiscard]] constexpr auto find(char c, size_type pos = 0) const {
54
		return view().find(c, pos);
55
	}
56
	[[nodiscard]] constexpr auto find(const char* s, size_type pos = 0) const {
57
		return view().find(s, pos);
58
	}
59
60
	[[nodiscard]] constexpr zstring_view substr(size_type pos) const {
61
		assert(pos <= siz);
62
		return {dat + pos, siz - pos};
63
	}
64
	[[nodiscard]] constexpr std::string_view substr(size_type pos, size_type count) const {
65
		assert(pos <= siz);
66
		return view().substr(pos, count);
67
	}
68
69
	constexpr void remove_prefix(size_type n) {
70
		assert(n <= siz);
71
		siz -= n;
72
		dat += n;
73
	}
74
75
	[[nodiscard]] constexpr bool starts_with(std::string_view sv) const {
76
		return view().starts_with(sv);
77
	}
78
	[[nodiscard]] constexpr bool starts_with(char c) const {
79
		return view().starts_with(c);
80
	}
81
	[[nodiscard]] constexpr bool starts_with(const char* s) const {
82
		return view().starts_with(s);
83
	}
84
	[[nodiscard]] constexpr bool ends_with(std::string_view sv) const {
85
		return view().ends_with(sv);
86
	}
87
	[[nodiscard]] constexpr bool ends_with(char c) const {
88
		return view().ends_with(c);
89
	}
90
	[[nodiscard]] constexpr bool ends_with(const char* s) const {
91
		return view().ends_with(s);
92
	}
93
	[[nodiscard]] constexpr bool contains(std::string_view sv) const {
94
		return view().contains(sv);
95
	}
96
	[[nodiscard]] constexpr bool contains(char c) const {
97
		return view().contains(c);
98
	}
99
	[[nodiscard]] constexpr bool contains(const char* s) const {
100
		return view().contains(s);
101
	}
102
103
	[[nodiscard]] explicit operator std::string() const {
104
		return {dat, siz};
105
	}
106
	[[nodiscard]] constexpr std::string_view view() const {
107
		return {dat, siz};
108
	}
109
	[[nodiscard]] explicit(false) constexpr operator std::string_view() const {
110
		return view();
111
	}
112
113
	[[nodiscard]] constexpr friend bool operator==(const zstring_view& x, const zstring_view& y) {
114
		return std::string_view(x) == std::string_view(y);
115
	}
116
	[[nodiscard]] friend bool operator==(const zstring_view& x, const std::string& y) {
117
		return std::string_view(x) == std::string_view(y);
118
	}
119
	[[nodiscard]] constexpr friend bool operator==(const zstring_view& x, const std::string_view& y) {
120
		return std::string_view(x) == y;
121
	}
122
	[[nodiscard]] constexpr friend bool operator==(const zstring_view& x, const char* y) {
123
		return std::string_view(x) == std::string_view(y);
124
	}
125
	[[nodiscard]] constexpr friend auto operator<=>(const zstring_view& x, const zstring_view& y) {
126
		return std::string_view(x) <=> std::string_view(y);
127
	}
128
	[[nodiscard]] friend auto operator<=>(const zstring_view& x, const std::string& y) {
129
		return std::string_view(x) <=> std::string_view(y);
130
	}
131
	[[nodiscard]] constexpr friend auto operator<=>(const zstring_view& x, const std::string_view& y) {
132
		return std::string_view(x) <=> y;
133
	}
134
	[[nodiscard]] constexpr friend auto operator<=>(const zstring_view& x, const char* y) {
135
		return std::string_view(x) <=> std::string_view(y);
136
	}
137
138
	friend std::ostream& operator<<(std::ostream& os, const zstring_view& str)
139
	{
140
		os << std::string_view(str);
141
		return os;
142
	}
143
144
private:
145
	const char* dat;
146
	size_type siz;
147
};
148
149
static_assert(std::is_trivially_destructible_v<zstring_view>);
150
static_assert(std::is_trivially_copyable_v<zstring_view>);
151
static_assert(std::is_trivially_copy_constructible_v<zstring_view>);
152
static_assert(std::is_trivially_move_constructible_v<zstring_view>);
153
static_assert(std::is_trivially_assignable_v<zstring_view, zstring_view>);
154
static_assert(std::is_trivially_copy_assignable_v<zstring_view>);
155
static_assert(std::is_trivially_move_assignable_v<zstring_view>);
156
157
[[nodiscard]] constexpr auto begin(const zstring_view& x) { return x.begin(); }
158
[[nodiscard]] constexpr auto end  (const zstring_view& x) { return x.end();   }
159
160
#endif