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