Lightweight 0.20250904.0
Loading...
Searching...
No Matches
SqlDynamicString.hpp
1// SPDX-License-Identifier: Apache-2.0
2
3#pragma once
4
5#include "../SqlColumnTypeDefinitions.hpp"
6#include "../Utils.hpp"
7#include "Core.hpp"
8#include "UnicodeConverter.hpp"
9
10#include <format>
11#include <limits>
12#include <string>
13
14namespace Lightweight
15{
16
17constexpr size_t SqlMaxColumnSize = (std::numeric_limits<uint32_t>::max)();
18
19/// SQL dynamic-capacity string that mimmicks standard library string.
20///
21/// The underlying memory is allocated dynamically and the string can grow up to the maximum size of a SQL column.
22///
23/// @ingroup DataTypes
24template <std::size_t N, typename T = char>
26{
27 public:
28 static constexpr std::size_t DynamicCapacity = N;
29 using value_type = T;
30 using string_type = std::basic_string<T>;
31
32 /// Constructs a fixed-size string from a string literal.
33 template <std::size_t SourceSize>
34 constexpr LIGHTWEIGHT_FORCE_INLINE SqlDynamicString(T const (&text)[SourceSize]):
35 _value { text, SourceSize - 1 }
36 {
37 static_assert(SourceSize <= N + 1, "RHS string size must not exceed target string's capacity.");
38 }
39
40 /// Constructs a fixed-size string from a string pointer and end pointer.
41 LIGHTWEIGHT_FORCE_INLINE constexpr SqlDynamicString(T const* s, T const* e) noexcept:
42 _value { s, e }
43 {
44 }
45
46 LIGHTWEIGHT_FORCE_INLINE constexpr SqlDynamicString() noexcept = default;
47 LIGHTWEIGHT_FORCE_INLINE constexpr SqlDynamicString(SqlDynamicString const&) noexcept = default;
48 LIGHTWEIGHT_FORCE_INLINE constexpr SqlDynamicString& operator=(SqlDynamicString const&) noexcept = default;
49 LIGHTWEIGHT_FORCE_INLINE constexpr SqlDynamicString(SqlDynamicString&&) noexcept = default;
50 LIGHTWEIGHT_FORCE_INLINE constexpr SqlDynamicString& operator=(SqlDynamicString&&) noexcept = default;
51 LIGHTWEIGHT_FORCE_INLINE constexpr ~SqlDynamicString() noexcept = default;
52
53 /// Constructs a fixed-size string from a string view.
54 LIGHTWEIGHT_FORCE_INLINE constexpr SqlDynamicString(std::basic_string_view<T> s) noexcept:
55 _value { s }
56 {
57 }
58
59 /// Constructs a fixed-size string from a string.
60 LIGHTWEIGHT_FORCE_INLINE constexpr SqlDynamicString(std::basic_string<T> const& s) noexcept:
61 _value { s }
62 {
63 }
64
65 /// Returns a string view of the string.
66 [[nodiscard]] LIGHTWEIGHT_FORCE_INLINE constexpr std::basic_string_view<T> str() const noexcept
67 {
68 return std::basic_string_view<T> { data(), size() };
69 }
70
71 /// Retrieves the string's inner value (std::basic_string<T>).
72 [[nodiscard]] LIGHTWEIGHT_FORCE_INLINE string_type const& value() const noexcept
73 {
74 return _value;
75 }
76
77 /// Retrieves the string's inner value (std::basic_string<T>).
78 [[nodiscard]] LIGHTWEIGHT_FORCE_INLINE string_type& value() noexcept
79 {
80 return _value;
81 }
82
83 /// Retrieves the string's inner value (as T const*).
84 [[nodiscard]] LIGHTWEIGHT_FORCE_INLINE T const* data() const noexcept
85 {
86 return _value.data();
87 }
88
89 /// Retrieves the string's inner value (as T*).
90 [[nodiscard]] LIGHTWEIGHT_FORCE_INLINE T* data() noexcept
91 {
92 return _value.data();
93 }
94
95 /// Retrieves the string's inner value (as T const*).
96 [[nodiscard]] LIGHTWEIGHT_FORCE_INLINE T const* c_str() const noexcept
97 {
98 return _value.c_str();
99 }
100
101 /// Retrieves the string's capacity.
102 [[nodiscard]] LIGHTWEIGHT_FORCE_INLINE std::size_t capacity() const noexcept
103 {
104 return N;
105 }
106
107 /// Retrieves the string's size.
108 [[nodiscard]] LIGHTWEIGHT_FORCE_INLINE std::size_t size() const noexcept
109 {
110 return _value.size();
111 }
112
113 /// Tests if the string is empty.
114 [[nodiscard]] LIGHTWEIGHT_FORCE_INLINE constexpr bool empty() const noexcept
115 {
116 return _value.empty();
117 }
118
119 /// Clears the string.
120 LIGHTWEIGHT_FORCE_INLINE constexpr void clear() noexcept
121 {
122 _value.clear();
123 }
124
125 /// Resizes the string.
126 LIGHTWEIGHT_FORCE_INLINE constexpr void resize(std::size_t n) noexcept
127 {
128 _value.resize(n);
129 }
130
131 /// Retrieves a string view of the string.
132 [[nodiscard]] LIGHTWEIGHT_FORCE_INLINE constexpr std::basic_string_view<T> ToStringView() const noexcept
133 {
134 return { _value.data(), _value.size() };
135 }
136
137 [[nodiscard]] LIGHTWEIGHT_FORCE_INLINE constexpr T& operator[](std::size_t index) noexcept
138 {
139 return _value[index];
140 }
141
142 [[nodiscard]] LIGHTWEIGHT_FORCE_INLINE constexpr T const& operator[](std::size_t index) const noexcept
143 {
144 return _value[index];
145 }
146
147 [[nodiscard]] LIGHTWEIGHT_FORCE_INLINE constexpr explicit operator std::basic_string_view<T>() const noexcept
148 {
149 return ToStringView();
150 }
151
152 template <std::size_t OtherSize>
153 LIGHTWEIGHT_FORCE_INLINE std::weak_ordering operator<=>(SqlDynamicString<OtherSize, T> const& other) const noexcept
154 {
155 return _value <=> other._value;
156 }
157
158 template <std::size_t OtherSize>
159 LIGHTWEIGHT_FORCE_INLINE constexpr bool operator==(SqlDynamicString<OtherSize, T> const& other) const noexcept
160 {
161 return (*this <=> other) == std::weak_ordering::equivalent;
162 }
163
164 template <std::size_t OtherSize>
165 LIGHTWEIGHT_FORCE_INLINE constexpr bool operator!=(SqlDynamicString<OtherSize, T> const& other) const noexcept
166 {
167 return !(*this == other);
168 }
169
170 LIGHTWEIGHT_FORCE_INLINE constexpr bool operator==(std::basic_string_view<T> other) const noexcept
171 {
172 return (ToStringView() <=> other) == std::weak_ordering::equivalent;
173 }
174
175 LIGHTWEIGHT_FORCE_INLINE constexpr bool operator!=(std::basic_string_view<T> other) const noexcept
176 {
177 return !(*this == other);
178 }
179
180 private:
181 string_type _value;
182};
183
184template <std::size_t N, typename CharT>
185struct detail::SqlViewHelper<SqlDynamicString<N, CharT>>
186{
187 static LIGHTWEIGHT_FORCE_INLINE std::basic_string_view<CharT> View(SqlDynamicString<N, CharT> const& str) noexcept
188 {
189 return { str.data(), str.size() };
190 }
191};
192
193namespace detail
194{
195
196 template <typename>
197 struct IsSqlDynamicStringImpl: std::false_type
198 {
199 };
200
201 template <std::size_t N, typename T>
202 struct IsSqlDynamicStringImpl<SqlDynamicString<N, T>>: std::true_type
203 {
204 };
205
206 template <std::size_t N, typename T>
207 struct IsSqlDynamicStringImpl<std::optional<SqlDynamicString<N, T>>>: std::true_type
208 {
209 };
210
211} // namespace detail
212
213template <typename T>
214constexpr bool IsSqlDynamicString = detail::IsSqlDynamicStringImpl<T>::value;
215
216/// Fixed-size string of element type `char` with a capacity of `N` characters.
217///
218/// @ingroup DataTypes
219template <std::size_t N>
221
222/// Fixed-size string of element type `char16_t` with a capacity of `N` characters.
223///
224/// @ingroup DataTypes
225template <std::size_t N>
227
228/// Fixed-size string of element type `char32_t` with a capacity of `N` characters.
229///
230/// @ingroup DataTypes
231template <std::size_t N>
233
234/// Fixed-size string of element type `wchar_t` with a capacity of `N` characters.
235///
236/// @ingroup DataTypes
237template <std::size_t N>
239
240} // namespace Lightweight
241
242template <std::size_t N, typename T>
243struct std::formatter<Lightweight::SqlDynamicString<N, T>>: std::formatter<std::string>
244{
245 using value_type = Lightweight::SqlDynamicString<N, T>;
246
247 auto format(value_type const& text, format_context& ctx) const
248 {
249 if constexpr (Lightweight::detail::OneOf<T, wchar_t, char32_t, char16_t>)
250 return std::formatter<std::string>::format((char const*) Lightweight::ToUtf8(text.ToStringView()).c_str(), ctx);
251 else
252 return std::formatter<std::string>::format((char const*) text.data(), ctx);
253 }
254};
255
256template <std::size_t N, typename T>
257struct std::formatter<std::optional<Lightweight::SqlDynamicString<N, T>>>: std::formatter<string>
258{
259 using value_type = std::optional<Lightweight::SqlDynamicString<N, T>>;
260
261 auto format(value_type const& text, format_context& ctx) const
262 {
263 if (!text.has_value())
264 return std::formatter<std::string>::format("nullopt", ctx);
265 return std::formatter<std::string>::format(std::format("{}", text.value()), ctx);
266 }
267};
268
269namespace Lightweight
270{
271
272template <std::size_t N, typename T>
273struct SqlBasicStringOperations<SqlDynamicString<N, T>>
274{
275 using CharType = T;
276 using ValueType = SqlDynamicString<N, CharType>;
277
278 static constexpr SqlColumnTypeDefinition ColumnType = []() constexpr {
279 if constexpr (std::same_as<CharType, char>)
280 return SqlColumnTypeDefinitions::Varchar { N };
281 else
282 return SqlColumnTypeDefinitions::NVarchar { N };
283 }();
284
285 static CharType const* Data(ValueType const* str) noexcept
286 {
287 return str->data();
288 }
289
290 static CharType* Data(ValueType* str) noexcept
291 {
292 return str->data();
293 }
294
295 static SQLULEN Size(ValueType const* str) noexcept
296 {
297 return str->size();
298 }
299
300 static void Clear(ValueType* str) noexcept
301 {
302 str->value().clear();
303 }
304
305 static void Reserve(ValueType* str, size_t capacity) noexcept
306 {
307 str->value().resize((std::min) (N, capacity));
308 }
309
310 static void Resize(ValueType* str, SQLLEN indicator) noexcept
311 {
312 str->value().resize(indicator);
313 }
314};
315
316} // namespace Lightweight
LIGHTWEIGHT_FORCE_INLINE std::size_t size() const noexcept
Retrieves the string's size.
LIGHTWEIGHT_FORCE_INLINE std::size_t capacity() const noexcept
Retrieves the string's capacity.
LIGHTWEIGHT_FORCE_INLINE T const * c_str() const noexcept
Retrieves the string's inner value (as T const*).
LIGHTWEIGHT_FORCE_INLINE T const * data() const noexcept
Retrieves the string's inner value (as T const*).
LIGHTWEIGHT_FORCE_INLINE constexpr std::basic_string_view< T > str() const noexcept
Returns a string view of the string.
LIGHTWEIGHT_FORCE_INLINE constexpr bool empty() const noexcept
Tests if the string is empty.
LIGHTWEIGHT_FORCE_INLINE constexpr std::basic_string_view< T > ToStringView() const noexcept
Retrieves a string view of the string.
constexpr LIGHTWEIGHT_FORCE_INLINE SqlDynamicString(T const (&text)[SourceSize])
Constructs a fixed-size string from a string literal.
LIGHTWEIGHT_FORCE_INLINE T * data() noexcept
Retrieves the string's inner value (as T*).
LIGHTWEIGHT_FORCE_INLINE string_type & value() noexcept
Retrieves the string's inner value (std::basic_string<T>).
LIGHTWEIGHT_FORCE_INLINE constexpr SqlDynamicString(std::basic_string< T > const &s) noexcept
Constructs a fixed-size string from a string.
LIGHTWEIGHT_FORCE_INLINE string_type const & value() const noexcept
Retrieves the string's inner value (std::basic_string<T>).
LIGHTWEIGHT_FORCE_INLINE constexpr SqlDynamicString(T const *s, T const *e) noexcept
Constructs a fixed-size string from a string pointer and end pointer.
LIGHTWEIGHT_FORCE_INLINE constexpr void clear() noexcept
Clears the string.
LIGHTWEIGHT_FORCE_INLINE constexpr void resize(std::size_t n) noexcept
Resizes the string.
LIGHTWEIGHT_API std::u8string ToUtf8(std::u32string_view u32InputString)