libGimbal 0.1.0
C17-Based Extended Standard Library and Cross-Language Runtime Framework
Loading...
Searching...
No Matches
gimbal_string_view.hpp
Go to the documentation of this file.
1/*! \file
2 * \brief StringView C++ bindings for GblStringView
3 * \ingroup strings
4 *
5 * This file contains the gbl::StringView C++ bindings
6 * around the GblStringView structure and C API. Along
7 * with fully supporting both the C and C++ APIs,
8 * gbl::StringView is type-compatible with std::string
9 * and std::string_view.
10 *
11 * \todo
12 * - return iterators from searches
13 * - implement forward/reverse iteration
14 *
15 * \author 2023 Falco Girgis
16 * \copyright MIT License
17 */
18#ifndef GIMBAL_STRING_VIEW_HPP
19#define GIMBAL_STRING_VIEW_HPP
20
22#include "../containers/gimbal_generics.hpp"
23#include "gimbal_quark.hpp"
24#include <string>
25#include <string_view>
26#include <functional>
27#include <compare>
28#include <type_traits>
29#include <optional>
30
31namespace gbl {
32
33class StringView;
34
35template<typename T>
36std::optional<T> string_view_to_value(const StringView& view) {
37 return std::nullopt;
38}
39
40/*! OO C++ binding object around GblStringView
41 * \ingroup strings
42 *
43 * gbl::StringView is intended to be a complete all-in-one
44 * replacement for the builtin std::string_view, including
45 * all of its functionality and more.
46 */
48 public GblStringView,
49 public ReadWriteContiguousIndexable<const StringView, std::size_t, char, false>,
50 public RandomAccessIterable<const StringView, std::size_t, char>
51{
52 static constinit const std::size_t npos = GBL_STRING_VIEW_NPOS;
53
54 const char& getElement_(std::size_t idx) const { return data()[idx]; }
55 std::size_t getElementCount_() const noexcept { return length(); }
56
57 auto spaceShip_(int result) const noexcept {
58 if(result < 0)
59 return std::strong_ordering::less;
60 else if(result > 0)
61 return std::strong_ordering::greater;
62 else
63 return std::strong_ordering::equal;
64 }
65
66 constexpr StringView() noexcept:
67 GblStringView({0}) {}
68
69 constexpr StringView(const char* pStr, size_t size=0) noexcept:
70 GblStringView({ .pData = pStr })
71 {
72 if(!size) {
73 static_cast<GblStringView*>(this)->length = std::char_traits<char>::length(pStr);
74 this->nullTerminated = true;
75 } else {
76 static_cast<GblStringView*>(this)->length = size;
77 this->nullTerminated = false;
78 }
79 }
80
81 constexpr StringView(const StringView& rhs) noexcept:
82 GblStringView(rhs) {}
83
84 constexpr StringView(GblStringView gblStrv) noexcept:
85 GblStringView(gblStrv) {}
86
87 constexpr StringView(std::string_view view) noexcept:
88 StringView(view.data(), view.length()) {}
89
90 constexpr const char* data() const noexcept { return pData; }
91 constexpr std::size_t length() const noexcept { return static_cast<const GblStringView*>(this)->length; }
92 constexpr bool isNullTerminated() const noexcept { return nullTerminated; }
93
94 int compareIgnoreCase(const char* pString, std::size_t len=0) const noexcept {
95 return GblStringView_compareIgnoreCase(*this, pString, len);
96 }
97
98 bool equalsIgnoreCase(const char* pString, std::size_t len=0) const noexcept {
99 return GblStringView_equalsIgnoreCase(*this, pString, len);
100 }
101
102 //rethrow
103 void copy(void* pDst, std::size_t offset, std::size_t bytes) const noexcept {
104 GblStringView_copy(*this, pDst, offset, bytes);
105 }
106
107 bool empty() const noexcept {
108 return GblStringView_empty(*this);
109 }
110
111 bool isBlank() const noexcept {
112 return GblStringView_blank(*this);
113 }
114
115 constexpr char operator[](std::size_t index) const {
116 if(index >= length())
117 throw std::out_of_range("Invalid StringView index!");
118 if (std::is_constant_evaluated()) {
119 return data()[index];
120 } else {
121 return GblStringView_at(*this, index);
122 }
123 }
124
125 char first() const {
126 if(empty())
127 throw std::out_of_range("Cannot get first char of empty StringView!");
128
129 return GblStringView_first(*this);
130 }
131
132 char last() const {
133 if(empty())
134 throw std::out_of_range("Cannot get last char of empty StringView!");
135
136 return GblStringView_last(*this);
137 }
138
139 StringView removePrefix(std::size_t len) const {
140 if(len > length())
141 throw std::out_of_range("Cannot remove prefix length > StringView.length!");
142 return GblStringView_removePrefix(*this, len);
143
144 }
145
146 StringView removeSuffix(std::size_t len) const {
147 if(len > length())
148 throw std::out_of_range("Cannot remove suffix length > StringView.length!");
149 return GblStringView_removeSuffix(*this, len);
150
151 }
152
153 StringView chomp() const noexcept {
154 return GblStringView_chomp(*this);
155 }
156
157 StringView substr(std::size_t offset, std::size_t length) const noexcept {
158 return GblStringView_substr(*this, offset, length);
159 }
160
161 bool contains(const char* pStr, std::size_t len=0) const noexcept {
162 return GblStringView_contains(*this, pStr, len);
163 }
164
165 bool containsIgnoreCase(const char* pStr, std::size_t len=0) const noexcept {
166 return GblStringView_containsIgnoreCase(*this, pStr, len);
167 }
168
169 std::size_t count(const char* pStr, std::size_t len=0) const noexcept {
170 return GblStringView_count(*this, pStr, len);
171 }
172
173 std::size_t countIgnoreCase(const char* pStr, std::size_t len=0) const noexcept {
174 return GblStringView_countIgnoreCase(*this, pStr, len);
175 }
176
177 std::size_t find(const char* pStr, std::size_t len=0) const noexcept {
178 return GblStringView_find(*this, pStr, len);
179 }
180
181 std::size_t findIgnoreCase(const char* pStr, std::size_t len=0) const noexcept {
182 return GblStringView_findIgnoreCase(*this, pStr, len);
183 }
184
185 std::size_t rfind(const char* pStr, std::size_t len=0) const noexcept {
186 return GblStringView_rfind(*this, pStr, len);
187 }
188
189 std::size_t rfindIgnoreCase(const char* pStr, std::size_t len=0) const noexcept {
190 return GblStringView_rfindIgnoreCase(*this, pStr, len);
191 }
192
193 bool startsWith(const char* pStr, std::size_t len=0) const noexcept {
194 return GblStringView_startsWith(*this, pStr, len);
195 }
196
197 bool startsWithIgnoreCase(const char* pStr, std::size_t len=0) const noexcept {
198 return GblStringView_startsWithIgnoreCase(*this, pStr, len);
199 }
200
201 bool endsWith(const char* pStr, std::size_t len=0) const noexcept {
202 return GblStringView_endsWith(*this, pStr, len);
203 }
204
205 bool endsWithIgnoreCase(const char* pStr, std::size_t len=0) const noexcept {
206 return GblStringView_endsWithIgnoreCase(*this, pStr, len);
207 }
208
209 std::size_t findFirstOf(const char* pChars, std::size_t len=0, std::size_t offset=0) const noexcept {
210 return GblStringView_findFirstOf(*this, pChars, len, offset);
211 }
212
213 std::size_t findLastOf(const char* pChars, std::size_t len=0, std::size_t offset=npos) const noexcept {
214 return GblStringView_findLastOf(*this, pChars, len, offset);
215 }
216
217 std::size_t findFirstNotOf(const char* pChars, std::size_t len=0, std::size_t offset=0) const noexcept {
218 return GblStringView_findFirstNotOf(*this, pChars, len, offset);
219 }
220
221 std::size_t findLastNotOf(const char* pChars, std::size_t len=0, std::size_t offset=npos) const noexcept {
222 return GblStringView_findLastNotOf(*this, pChars, len, offset);
223 }
224
225 std::string toStdString() const {
226 std::string str;
227 str.resize(length());
228 GblStringView_toCString(*this, str.data(), str.capacity());
229 return str;
230 }
231
232 Quark quark() const noexcept {
233 return GblStringView_quark(*this);
234 }
235
236 Quark tryQuark() const noexcept {
237 return GblStringView_tryQuark(*this);
238 }
239
240 const char* intern() const noexcept {
241 return GblStringView_intern(*this);
242 }
243
244 bool toNil() const noexcept { return GblStringView_toNil(*this); }
245
246 template<typename T>
247 auto toValue() const noexcept{ return string_view_to_value<T>(*this); }
248
249 friend std::ostream& operator<<(std::ostream &os, StringView view) {
250 os << std::string_view(view.data(), view.length());
251 return os;
252 }
253
254 bool operator==(const char* pStr) const noexcept {
255 return GblStringView_equals(*this, pStr);
256 }
257
258 auto operator<=>(const char* pStr) const noexcept {
259 return spaceShip_(GblStringView_compare(*this, pStr));
260 }
261
262 bool operator==(StringView rhs) const noexcept {
263 return GblStringView_equals(*this, rhs.data(), rhs.length());
264 }
265
266 auto operator<=>(StringView rhs) const noexcept {
267 return spaceShip_(GblStringView_compare(*this, rhs.data(), rhs.length()));
268 }
269
270 bool operator==(const std::string& rhs) const noexcept {
271 return GblStringView_equals(*this, rhs.data(), rhs.length());
272 }
273
274 auto operator<=>(const std::string& rhs) const noexcept {
275 return spaceShip_(GblStringView_compare(*this, rhs.data(), rhs.length()));
276 }
277
278 friend void swap(StringView& lhs, StringView& rhs) noexcept {
279 std::swap(static_cast<GblStringView&>(lhs),
280 static_cast<GblStringView&>(rhs));
281 }
282};
283
284#define GBL_STRING_VIEW_TO_VALUE_(type, postfix)
285 template<>
286 inline std::optional<type> string_view_to_value<type>(const StringView& view) {
287 GblBool ok;
288 type value = GblStringView_##postfix(view, &ok);
289 return ok? std::optional{value} : std::nullopt;
290 }
291
292GBL_STRING_VIEW_TO_VALUE_(bool, toBool)
293GBL_STRING_VIEW_TO_VALUE_(char, toChar)
294GBL_STRING_VIEW_TO_VALUE_(uint8_t, toUint8)
295GBL_STRING_VIEW_TO_VALUE_(uint16_t, toUint16)
296GBL_STRING_VIEW_TO_VALUE_(int16_t, toInt16)
297GBL_STRING_VIEW_TO_VALUE_(uint32_t, toUint32)
298GBL_STRING_VIEW_TO_VALUE_(int32_t, toInt32)
299GBL_STRING_VIEW_TO_VALUE_(uint64_t, toUint64)
300GBL_STRING_VIEW_TO_VALUE_(int64_t, toInt64)
301GBL_STRING_VIEW_TO_VALUE_(float, toFloat)
302GBL_STRING_VIEW_TO_VALUE_(double, toDouble)
303GBL_STRING_VIEW_TO_VALUE_(void*, toPointer)
304
305#undef GBL_STRING_VIEW_TO_VALUE_
306
307consteval inline StringView operator""_strv(const char* pString, std::size_t size) noexcept {
308 return StringView(pString, size);
309}
310
311}
312
313template<>
314struct std::hash<gbl::StringView> {
315 std::size_t operator()(const gbl::StringView& view) const noexcept {
316 return GblStringView_hash(view);
317 }
318};
319
320#endif // GIMBAL_STRING_VIEW_HPP
OO C++ wrapper object around GblQuark.
#define GBL_STRING_VIEW_NPOS
Constant value used to signify the last position or an invalid position in a GblStringView.
#define GBL_STRING_VIEW_TO_VALUE_(type, postfix)
Immutable substring type.
size_t nullTerminated
Reserved bit for maintaining whether the string is NULL terminated or not.
const char * pData
Start address of the string being viewed.
OO C++ binding object around GblStringView.