-
Notifications
You must be signed in to change notification settings - Fork 290
Add _bst user-defined literal for BSTR-shaped wide strings
#647
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -252,11 +252,67 @@ inline auto str_raw_ptr(basic_zstring_view<TChar> str) | |
|
|
||
| inline namespace literals | ||
| { | ||
| #if __WI_LIBCPP_STD_VER >= 20 | ||
| /** | ||
| A statically-allocated, BSTR-shaped literal: a length-prefixed wide string whose data pointer is a valid | ||
| BSTR (usable with SysStringLen, SysStringByteLen, wcslen). No heap allocation; size is the literal's exact | ||
| length. Lifetime is tied to the literal object itself. | ||
|
|
||
| Example: | ||
| void Use(BSTR); | ||
| Use(L"foo"_bst); | ||
| */ | ||
| template <std::size_t N> | ||
| struct wchar_literal_storage | ||
| { | ||
| wchar_t value[N]; | ||
| constexpr wchar_literal_storage(const wchar_t (&str)[N]) WI_NOEXCEPT | ||
| { | ||
| for (std::size_t i = 0; i < N; ++i) | ||
| { | ||
| value[i] = str[i]; | ||
| } | ||
| } | ||
| }; | ||
|
|
||
| template <std::size_t N> | ||
| wchar_literal_storage(const wchar_t (&)[N]) -> wchar_literal_storage<N>; | ||
|
|
||
| // N includes the trailing L'\0'; the BSTR byte-length prefix excludes it. | ||
| template <std::size_t N> | ||
| struct bstr_literal_t | ||
| { | ||
| unsigned long m_byte_length; | ||
| wchar_t m_data[N]; | ||
|
|
||
| constexpr bstr_literal_t(const wchar_t (&text)[N]) WI_NOEXCEPT : | ||
| m_byte_length(static_cast<unsigned long>((N - 1) * sizeof(wchar_t))), m_data{} | ||
| { | ||
| for (std::size_t i = 0; i < N; ++i) | ||
| { | ||
| m_data[i] = text[i]; | ||
| } | ||
| } | ||
|
|
||
| WI_NODISCARD constexpr operator BSTR() const WI_NOEXCEPT | ||
| { | ||
| return const_cast<wchar_t*>(&m_data[0]); | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do you need to guard against N=0? In that case this is getting the address of a zero-size buffer.
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Zero sized arrays are not valid in C++ |
||
| } | ||
| }; | ||
|
|
||
| template <wchar_literal_storage Lit> | ||
| WI_NODISCARD constexpr auto operator""_bst() WI_NOEXCEPT | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. My personal expectation is that this would be
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. One thing worth mentioning is that "bst" could stand for "binary search tree" (not that that would make much sense for a user defined literal) |
||
| { | ||
| return bstr_literal_t<sizeof(Lit.value) / sizeof(wchar_t)>{Lit.value}; | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Add something like: static constexpr const std::size_t size = N;or a ( |
||
| } | ||
|
|
||
| #endif // __WI_LIBCPP_STD_VER >= 20 | ||
|
|
||
| constexpr zstring_view operator""_zv(const char* str, std::size_t len) noexcept | ||
| { | ||
| return {str, len}; | ||
| } | ||
|
|
||
| constexpr zwstring_view operator""_zv(const wchar_t* str, std::size_t len) noexcept | ||
| { | ||
| return {str, len}; | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -128,7 +128,7 @@ TEST_CASE("StlTests::TestZStringView", "[stl][zstring_view]") | |
|
|
||
| TEST_CASE("StlTests::TestZWStringView literal", "[stl][zwstring_view]") | ||
| { | ||
|
|
||
| SECTION("Literal creates correct zwstring_view") | ||
| { | ||
| auto str = L"Hello, world!"_zv; | ||
|
|
@@ -137,7 +137,22 @@ TEST_CASE("StlTests::TestZWStringView literal", "[stl][zwstring_view]") | |
| REQUIRE(str[12] == L'!'); | ||
| } | ||
| } | ||
|
|
||
|
|
||
| TEST_CASE("StlTests::TestBSTR literal", "[stl][bstr]") | ||
| { | ||
| #if __WI_LIBCPP_STD_VER >= 20 | ||
| SECTION("Literal creates a valid BSTR") | ||
| { | ||
| const auto literal = L"foo"_bst; | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should also include a |
||
| const BSTR value = literal; | ||
| REQUIRE(value != nullptr); | ||
| REQUIRE(SysStringLen(value) == 3); | ||
| REQUIRE(SysStringLen(L"zot"_bst) == 3); | ||
| REQUIRE(std::wstring_view(value) == L"foo"); | ||
| } | ||
| #endif | ||
| } | ||
|
|
||
| TEST_CASE("StlTests::TestZStringView literal", "[stl][zstring_view]") | ||
| { | ||
|
|
||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Consider: something like
static_assert(offsetof(m_data) == 4)