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
|
// Copyright 2025 Steven Le Rouzic
//
// SPDX-License-Identifier: BSD-3-Clause
#pragma once
#include "asl/base/integers.hpp"
#include "asl/base/meta.hpp"
#include "asl/types/span.hpp"
#include "asl/memory/memory.hpp"
namespace asl
{
// NOLINTBEGIN(*-convert-member-functions-to-static)
class string_view
{
const char* m_data{};
isize_t m_size{};
public:
constexpr string_view() = default;
constexpr string_view(nullptr_t) : string_view() {} // NOLINT(*explicit*)
constexpr string_view(const char* data, isize_t size)
: m_data{data}
, m_size{size}
{}
template<isize_t kSize>
constexpr string_view(const char (&str)[kSize]) // NOLINT(*explicit*)
requires (kSize >= 1)
: m_data{static_cast<const char*>(str)}
, m_size{kSize - 1}
{
ASL_ASSERT(m_data[kSize - 1] == '\0'); // NOLINT(*-pointer-arithmetic)
}
static constexpr string_view from_zstr(const char* str)
{
return {str, asl::strlen(str)};
}
constexpr string_view(const string_view&) = default;
constexpr string_view(string_view&&) = default;
constexpr string_view& operator=(const string_view&) = default;
constexpr string_view& operator=(string_view&&) = default;
~string_view() = default;
[[nodiscard]] constexpr isize_t size(this string_view self)
{
return self.m_size;
}
[[nodiscard]] constexpr bool is_empty(this string_view self)
{
return self.m_size == 0;
}
[[nodiscard]] constexpr const char* data(this string_view self)
{
return self.m_data;
}
[[nodiscard]] constexpr contiguous_iterator<const char> begin(this string_view self)
{
return contiguous_iterator{self.m_data};
}
[[nodiscard]] constexpr contiguous_iterator<const char> end(this string_view self)
{
// NOLINTNEXTLINE(*-pointer-arithmetic)
return contiguous_iterator{self.m_data + self.m_size};
}
[[nodiscard]] constexpr span<const char> as_span(this string_view self)
{
return {self.m_data, self.m_size};
}
[[nodiscard]] constexpr char operator[](this string_view self, isize_t i)
{
ASL_ASSERT(i >= 0 && i < self.m_size);
return self.m_data[i]; // NOLINT(*-pointer-arithmetic)
}
[[nodiscard]] constexpr string_view substr(this string_view self, isize_t offset, isize_t size)
{
ASL_ASSERT(offset >= 0 && size >= 0 && offset + size <= self.m_size);
return string_view{self.m_data + offset, size}; // NOLINT(*-pointer-arithmetic)
}
[[nodiscard]] constexpr string_view substr(this string_view self, isize_t offset)
{
ASL_ASSERT(offset >= 0 && offset <= self.m_size);
return string_view{self.m_data + offset, self.m_size - offset}; // NOLINT(*-pointer-arithmetic)
}
[[nodiscard]] constexpr string_view first(this string_view self, isize_t size)
{
return self.substr(0, size);
}
[[nodiscard]] constexpr string_view last(this string_view self, isize_t size)
{
return self.substr(self.m_size - size);
}
constexpr bool operator==(this string_view self, string_view other)
{
if (self.m_size != other.m_size) { return false; }
return asl::memcmp(self.m_data, other.m_data, self.m_size) == 0;
}
template<typename H>
friend H AslHashValue(H h, string_view sv)
{
return H::combine(H::combine_contiguous(h, as_bytes(sv.as_span())), sv.size());
}
};
// NOLINTEND(*-convert-member-functions-to-static)
} // namespace asl
constexpr asl::string_view operator ""_sv(const char* s, size_t len)
{
return {s, static_cast<isize_t>(len)};
}
|