5#include "../SqlColumnTypeDefinitions.hpp"
7#include "UnicodeConverter.hpp"
17enum class SqlFixedStringMode : uint8_t
20 FIXED_SIZE_RIGHT_TRIMMED,
31template <std::
size_t N,
typename T =
char, SqlFixedStringMode Mode = SqlFixedStringMode::FIXED_SIZE>
36 std::size_t _size = 0;
41 using const_iterator = T
const*;
42 using pointer_type = T*;
43 using const_pointer_type = T
const*;
45 static constexpr std::size_t Capacity = N;
46 static constexpr SqlFixedStringMode PostRetrieveOperation = Mode;
49 template <std::
size_t SourceSize>
50 constexpr LIGHTWEIGHT_FORCE_INLINE
SqlFixedString(T
const (&text)[SourceSize]):
51 _size { SourceSize - 1 }
53 static_assert(SourceSize <= N + 1,
"RHS string size must not exceed target string's capacity.");
54 std::copy_n(text, SourceSize, _data);
57 LIGHTWEIGHT_FORCE_INLINE
constexpr SqlFixedString() noexcept = default;
62 LIGHTWEIGHT_FORCE_INLINE constexpr ~
SqlFixedString() noexcept = default;
65 LIGHTWEIGHT_FORCE_INLINE constexpr
SqlFixedString(std::basic_string_view<T> s) noexcept:
66 _size { (std::min) (N, s.size()) }
68 std::copy_n(s.data(), _size, _data);
72 LIGHTWEIGHT_FORCE_INLINE
constexpr SqlFixedString(std::basic_string<T>
const& s)
noexcept:
73 _size { (std::min) (N, s.size()) }
75 std::copy_n(s.data(), _size, _data);
79 LIGHTWEIGHT_FORCE_INLINE
constexpr SqlFixedString(T
const* s, std::size_t len)
noexcept:
80 _size { (std::min) (N, len) }
82 std::copy_n(s, _size, _data);
86 LIGHTWEIGHT_FORCE_INLINE
constexpr SqlFixedString(T
const* s, T
const* e)
noexcept:
87 _size { (std::min) (N,
static_cast<std::size_t
>(e - s)) }
89 std::copy(s, e, _data);
92 LIGHTWEIGHT_FORCE_INLINE
void reserve(std::size_t
capacity)
95 throw std::length_error(std::format(
"SqlFixedString: capacity {} exceeds maximum capacity {}",
capacity, N));
99 [[nodiscard]] LIGHTWEIGHT_FORCE_INLINE
constexpr bool empty() const noexcept
105 [[nodiscard]] LIGHTWEIGHT_FORCE_INLINE
constexpr std::size_t
size() const noexcept
111 LIGHTWEIGHT_FORCE_INLINE
void setsize(std::size_t n)
noexcept
113 auto const newSize = (std::min) (n, N);
115 _data[newSize] =
'\0';
122 LIGHTWEIGHT_FORCE_INLINE
constexpr void resize(std::size_t n)
noexcept
124 auto const newSize = (std::min) (n, N);
126 _data[newSize] =
'\0';
130 [[nodiscard]] LIGHTWEIGHT_FORCE_INLINE
constexpr std::size_t
capacity() const noexcept
136 LIGHTWEIGHT_FORCE_INLINE
constexpr void clear() noexcept
142 template <std::
size_t SourceSize>
143 LIGHTWEIGHT_FORCE_INLINE
constexpr void assign(T
const (&source)[SourceSize])
noexcept
145 static_assert(SourceSize <= N + 1,
"Source string must not overflow the target string's capacity.");
146 _size = SourceSize - 1;
147 std::copy_n(source, SourceSize, _data);
151 LIGHTWEIGHT_FORCE_INLINE
constexpr void assign(std::basic_string_view<T> s)
noexcept
153 _size = (std::min) (N, s.size());
154 std::copy_n(s.data(), _size, _data);
158 LIGHTWEIGHT_FORCE_INLINE
constexpr void push_back(T c)
noexcept
168 LIGHTWEIGHT_FORCE_INLINE
constexpr void pop_back() noexcept
175 [[nodiscard]] LIGHTWEIGHT_FORCE_INLINE
constexpr std::basic_string_view<T>
substr(
176 std::size_t offset = 0, std::size_t count = (std::numeric_limits<std::size_t>::max)()) const noexcept
180 if (count == (std::numeric_limits<std::size_t>::max)())
181 return std::basic_string_view<T>(_data + offset, _size - offset);
182 if (offset + count > _size)
183 return std::basic_string_view<T>(_data + offset, _size - offset);
184 return std::basic_string_view<T>(_data + offset, count);
188 [[nodiscard]] LIGHTWEIGHT_FORCE_INLINE
constexpr std::basic_string_view<T>
str() const noexcept
190 return std::basic_string_view<T> { _data, _size };
194 [[nodiscard]] LIGHTWEIGHT_FORCE_INLINE
constexpr pointer_type c_str() noexcept { _data[_size] =
'\0';
return _data; }
195 [[nodiscard]] LIGHTWEIGHT_FORCE_INLINE
constexpr pointer_type data() noexcept {
return _data; }
196 [[nodiscard]] LIGHTWEIGHT_FORCE_INLINE
constexpr iterator begin() noexcept {
return _data; }
197 [[nodiscard]] LIGHTWEIGHT_FORCE_INLINE
constexpr iterator end() noexcept {
return _data +
size(); }
198 [[nodiscard]] LIGHTWEIGHT_FORCE_INLINE
constexpr T& at(std::size_t i)
noexcept {
return _data[i]; }
199 [[nodiscard]] LIGHTWEIGHT_FORCE_INLINE
constexpr T& operator[](std::size_t i)
noexcept {
return _data[i]; }
201 [[nodiscard]] LIGHTWEIGHT_FORCE_INLINE
constexpr const_pointer_type c_str() const noexcept {
return _data; }
202 [[nodiscard]] LIGHTWEIGHT_FORCE_INLINE
constexpr const_pointer_type data() const noexcept {
return _data; }
203 [[nodiscard]] LIGHTWEIGHT_FORCE_INLINE
constexpr const_iterator begin() const noexcept {
return _data; }
204 [[nodiscard]] LIGHTWEIGHT_FORCE_INLINE
constexpr const_iterator end() const noexcept {
return _data +
size(); }
205 [[nodiscard]] LIGHTWEIGHT_FORCE_INLINE
constexpr T
const& at(std::size_t i)
const noexcept {
return _data[i]; }
206 [[nodiscard]] LIGHTWEIGHT_FORCE_INLINE
constexpr T
const& operator[](std::size_t i)
const noexcept {
return _data[i]; }
210 [[nodiscard]] LIGHTWEIGHT_FORCE_INLINE
constexpr std::basic_string<T>
ToString() const noexcept
212 return { _data, _size };
216 [[nodiscard]] LIGHTWEIGHT_FORCE_INLINE
constexpr explicit operator std::basic_string<T>() const noexcept
222 [[nodiscard]] LIGHTWEIGHT_FORCE_INLINE
constexpr std::basic_string_view<T>
ToStringView() const noexcept
224 return { _data, _size };
228 [[nodiscard]] LIGHTWEIGHT_FORCE_INLINE
constexpr explicit operator std::basic_string_view<T>() const noexcept
233 template <std::
size_t OtherSize, SqlFixedStringMode OtherMode>
234 LIGHTWEIGHT_FORCE_INLINE std::weak_ordering operator<=>(
235 SqlFixedString<OtherSize, T, OtherMode>
const& other)
const noexcept
237 if ((
void*)
this == (
void*) &other) [[unlikely]]
238 return std::weak_ordering::equivalent;
240 for (
auto const i: std::views::iota(0U, (std::min) (
size(), other.
size())))
241 if (auto const cmp = _data[i] <=> other._data[i]; cmp != std::weak_ordering::equivalent) [[unlikely]]
243 return size() <=> other.size();
246 template <std::
size_t OtherSize, SqlFixedStringMode OtherMode>
247 LIGHTWEIGHT_FORCE_INLINE
constexpr bool operator==(SqlFixedString<OtherSize, T, OtherMode>
const& other)
const noexcept
249 return (*this <=> other) == std::weak_ordering::equivalent;
252 template <std::
size_t OtherSize, SqlFixedStringMode OtherMode>
253 LIGHTWEIGHT_FORCE_INLINE
constexpr bool operator!=(SqlFixedString<OtherSize, T, OtherMode>
const& other)
const noexcept
255 return !(*
this == other);
258 LIGHTWEIGHT_FORCE_INLINE
constexpr bool operator==(std::basic_string_view<T> other)
const noexcept
260 return (
substr() <=> other) == std::weak_ordering::equivalent;
263 LIGHTWEIGHT_FORCE_INLINE
constexpr bool operator!=(std::basic_string_view<T> other)
const noexcept
265 return !(*
this == other);
269template <std::
size_t N,
typename CharT, SqlFixedStringMode Mode>
270struct detail::SqlViewHelper<SqlFixedString<N, CharT, Mode>>
272 static LIGHTWEIGHT_FORCE_INLINE std::basic_string_view<CharT> View(SqlFixedString<N, CharT, Mode>
const& str)
noexcept
274 return { str.data(), str.size() };
282 struct IsSqlFixedStringTypeImpl: std::false_type
286 template <std::
size_t N,
typename T, SqlFixedStringMode Mode>
287 struct IsSqlFixedStringTypeImpl<SqlFixedString<N, T, Mode>>: std::true_type
294constexpr bool IsSqlFixedString = detail::IsSqlFixedStringTypeImpl<T>::value;
299template <std::
size_t N>
305template <std::
size_t N>
311template <std::
size_t N>
317template <std::
size_t N>
323template <std::
size_t N>
329template <std::
size_t N>
332template <std::
size_t N,
typename T =
char>
335template <std::
size_t N,
typename T, SqlFixedStringMode Mode>
340 static constexpr auto ColumnType = []()
constexpr -> SqlColumnTypeDefinition {
341 if constexpr (std::same_as<CharType, char>)
343 if constexpr (Mode == SqlFixedStringMode::VARIABLE_SIZE)
344 return SqlColumnTypeDefinitions::Varchar { N };
346 return SqlColumnTypeDefinitions::Char { N };
350 if constexpr (Mode == SqlFixedStringMode::VARIABLE_SIZE)
351 return SqlColumnTypeDefinitions::NVarchar { N };
353 return SqlColumnTypeDefinitions::NChar { N };
357 static CharType
const* Data(ValueType
const* str)
noexcept
362 static CharType* Data(ValueType* str)
noexcept
367 static SQLULEN Size(ValueType
const* str)
noexcept
372 static void Clear(ValueType* str)
noexcept
377 static void Reserve(ValueType* str,
size_t capacity)
noexcept
379 str->reserve((std::min) (N, capacity));
380 str->resize((std::min) (N, capacity));
383 static void Resize(ValueType* str, SQLLEN indicator)
noexcept
385 str->resize(indicator);
388 static void PostProcessOutputColumn(ValueType* result, SQLLEN indicator)
399 auto const len = (std::min) (N,
static_cast<std::size_t
>(indicator) /
sizeof(CharType));
400 result->setsize(len);
402 if constexpr (Mode == SqlFixedStringMode::FIXED_SIZE_RIGHT_TRIMMED)
404 TrimRight(result, indicator);
411 LIGHTWEIGHT_FORCE_INLINE
static void TrimRight(ValueType* boundOutputString, SQLLEN indicator)
noexcept
414 size_t n = (std::min) (
static_cast<size_t>(indicator) /
sizeof(CharType), N - 1);
416 size_t n = std::min(
static_cast<size_t>(indicator), N - 1);
418 while (n > 0 && std::isspace((*boundOutputString)[n - 1]))
420 boundOutputString->setsize(n);
426template <std::
size_t N,
typename T, Lightweight::SqlFixedStringMode P>
427struct std::formatter<Lightweight::SqlFixedString<N, T, P>>: std::formatter<std::string>
430 auto format(value_type
const& text, format_context& ctx)
const -> format_context::iterator
432 if constexpr (std::same_as<T, wchar_t>)
433 return std::formatter<std::string>::format(
ToUtf8(text.ToStringView()), ctx);
435 return std::formatter<std::string>::format(text.c_str(), ctx);
LIGHTWEIGHT_FORCE_INLINE constexpr SqlFixedString(T const *s, std::size_t len) noexcept
Constructs a fixed-size string from a string pointer and length.
LIGHTWEIGHT_FORCE_INLINE constexpr std::size_t capacity() const noexcept
Returns the maximum capacity of the string.
LIGHTWEIGHT_FORCE_INLINE constexpr SqlFixedString(T const *s, T const *e) noexcept
Constructs a fixed-size string from a string pointer and end pointer.
LIGHTWEIGHT_FORCE_INLINE constexpr std::basic_string_view< T > str() const noexcept
Returns a string view of the string.
LIGHTWEIGHT_FORCE_INLINE constexpr void clear() noexcept
Clears the string.
LIGHTWEIGHT_FORCE_INLINE constexpr void resize(std::size_t n) noexcept
LIGHTWEIGHT_FORCE_INLINE constexpr void push_back(T c) noexcept
Appends a character to the string.
LIGHTWEIGHT_FORCE_INLINE constexpr void assign(T const (&source)[SourceSize]) noexcept
Assigns a string literal to the string.
LIGHTWEIGHT_FORCE_INLINE constexpr void assign(std::basic_string_view< T > s) noexcept
Assigns a string view to the string.
LIGHTWEIGHT_FORCE_INLINE constexpr bool empty() const noexcept
Tests if the string is empty.
constexpr LIGHTWEIGHT_FORCE_INLINE SqlFixedString(T const (&text)[SourceSize])
Constructs a fixed-size string from a string literal.
LIGHTWEIGHT_FORCE_INLINE constexpr std::basic_string_view< T > ToStringView() const noexcept
Returns a std::basic_string_view<T> from the string.
LIGHTWEIGHT_FORCE_INLINE constexpr std::basic_string_view< T > substr(std::size_t offset=0, std::size_t count=(std::numeric_limits< std::size_t >::max)()) const noexcept
Returns a sub string of the string.
LIGHTWEIGHT_FORCE_INLINE constexpr std::basic_string< T > ToString() const noexcept
Returns a std::basic_string<T> from the string.
LIGHTWEIGHT_FORCE_INLINE constexpr SqlFixedString(std::basic_string< T > const &s) noexcept
Constructs a fixed-size string from a string.
LIGHTWEIGHT_FORCE_INLINE constexpr std::size_t size() const noexcept
Returns the size of the string.
LIGHTWEIGHT_FORCE_INLINE constexpr void pop_back() noexcept
Removes the last character from the string.
LIGHTWEIGHT_API std::u8string ToUtf8(std::u32string_view u32InputString)