Skip to content

Commit

Permalink
Merge branch 'dev'
Browse files Browse the repository at this point in the history
  • Loading branch information
gershnik committed Jun 9, 2022
2 parents 033d504 + 1344b59 commit 3d67f3e
Show file tree
Hide file tree
Showing 7 changed files with 76 additions and 36 deletions.
3 changes: 3 additions & 0 deletions doc/Windows.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@
On Windows there isn't a single, universally used system string type. Win32 API uses plain `wchar_t *`, traditional OLE/COM relies on `BSTR`, while newer C++/WinRT uses `HSTRING`. To target your specific scenario `sys_string` can be configured at compile time to use either of these types of storage.
If no configuration flags are specified the default storage is plain `wchar_t *`.

Additionally, some programs rely on Unix compatibility APIs exclusively and, for those, Windows platform also supports "generic Unix" storage which stores `char *` and is meant to interoperate with plain Unix API.
It can be selected via `#define SYS_STRING_USE_GENERIC 1` and is described under [Linux](Linux.md).

Being the lowest-common denominator, zero-cost conversions to `const wchar_t *` are available in all configurations.

Conversions supported by each storage type are described below.
Expand Down
15 changes: 13 additions & 2 deletions lib/inc/sys_string/impl/platform.h
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@
#include <sys_string/impl/platforms/windows_bstr.h>
#include <sys_string/impl/platforms/windows_hstring.h>
#include <sys_string/impl/platforms/windows_generic.h>
#include <sys_string/impl/platforms/unix_generic.h>

#if SYS_STRING_WIN_BSTR

Expand All @@ -87,7 +88,7 @@

#define SYS_STRING_STATIC SYS_STRING_STATIC_HSTRING

#else
#elif SYS_STRING_USE_GENERIC

namespace sysstr
{
Expand All @@ -97,9 +98,19 @@

#define SYS_STRING_STATIC SYS_STRING_STATIC_GENERIC

#else

namespace sysstr
{
using sys_string = sys_string_win_generic;
using sys_string_builder = sys_string_win_generic_builder;
}

#define SYS_STRING_STATIC SYS_STRING_STATIC_WIN_GENERIC

#endif

#elif defined(__linux__)
#elif defined(__linux__) || defined(__FreeBSD__)
#include <sys_string/impl/platforms/unix_generic.h>


Expand Down
7 changes: 7 additions & 0 deletions lib/inc/sys_string/impl/platforms/unix_generic.h
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,13 @@ namespace sysstr
public:
using super::super;

#ifdef _MSC_VER
template<class Char>
generic_storage(const Char * str, size_t len, std::enable_if_t<has_utf_encoding<Char>> * = nullptr):
super(str, len)
{}
#endif

protected:
~generic_storage() noexcept = default;
generic_storage(const generic_storage & src) noexcept = default;
Expand Down
62 changes: 31 additions & 31 deletions lib/inc/sys_string/impl/platforms/windows_generic.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
namespace sysstr::util
{

struct generic_traits
struct win_generic_traits
{
using storage_type = char16_t;
using size_type = size_t;
Expand All @@ -25,48 +25,48 @@ namespace sysstr::util
};

template<size_t N>
using generic_static_buffer = generic::static_buffer<generic_traits::storage_type, generic_traits::size_type, N>;
using generic_dynamic_buffer = generic::dynamic_buffer<generic_traits::storage_type, generic_traits::size_type>;
using win_generic_static_buffer = generic::static_buffer<win_generic_traits::storage_type, win_generic_traits::size_type, N>;
using win_generic_dynamic_buffer = generic::dynamic_buffer<win_generic_traits::storage_type, win_generic_traits::size_type>;

using generic_buffer = generic::buffer<generic_traits::storage_type, generic_traits::size_type>;
using win_generic_buffer = generic::buffer<win_generic_traits::storage_type, win_generic_traits::size_type>;

using generic_builder_impl = generic::buffer_builder<generic_traits::storage_type, generic_traits::size_type>;
using win_generic_builder_impl = generic::buffer_builder<win_generic_traits::storage_type, win_generic_traits::size_type>;

using generic_char_access = generic::char_access<generic_traits::storage_type, generic_traits::size_type>;
using win_generic_char_access = generic::char_access<win_generic_traits::storage_type, win_generic_traits::size_type>;

}

namespace sysstr
{
class generic_storage: private util::generic::storage<util::generic_traits::storage_type, util::generic_traits::size_type>
class win_generic_storage: private util::generic::storage<util::win_generic_traits::storage_type, util::win_generic_traits::size_type>
{
friend util::generic_char_access;
friend util::win_generic_char_access;
private:
using super = util::generic::storage<util::generic_traits::storage_type, util::generic_traits::size_type>;
using super = util::generic::storage<util::win_generic_traits::storage_type, util::win_generic_traits::size_type>;
public:
using super::size_type;
using super::storage_type;

using hash_type = util::generic_traits::hash_type;
using char_access = util::generic_char_access;
using builder_impl = util::generic_builder_impl;
using hash_type = util::win_generic_traits::hash_type;
using char_access = util::win_generic_char_access;
using builder_impl = util::win_generic_builder_impl;

static constexpr auto max_size = util::generic_traits::max_size;
static constexpr auto max_size = util::win_generic_traits::max_size;

public:
using super::super;

template<class Char>
generic_storage(const Char * str, size_t len, std::enable_if_t<has_utf_encoding<Char>> * = nullptr):
win_generic_storage(const Char * str, size_t len, std::enable_if_t<has_utf_encoding<Char>> * = nullptr):
super(str, len)
{}

protected:
~generic_storage() noexcept = default;
generic_storage(const generic_storage & src) noexcept = default;
generic_storage(generic_storage && src) noexcept = default;
generic_storage & operator=(const generic_storage & rhs) noexcept = default;
generic_storage & operator=(generic_storage && rhs) noexcept = default;
~win_generic_storage() noexcept = default;
win_generic_storage(const win_generic_storage & src) noexcept = default;
win_generic_storage(win_generic_storage && src) noexcept = default;
win_generic_storage & operator=(const win_generic_storage & rhs) noexcept = default;
win_generic_storage & operator=(win_generic_storage && rhs) noexcept = default;

public:
using super::data;
Expand All @@ -92,47 +92,47 @@ namespace sysstr::util
template<>
template<>
inline
generic_char_access::char_access(const sys_string_t<generic_storage> & src) noexcept:
win_generic_char_access::char_access(const sys_string_t<win_generic_storage> & src) noexcept:
char_access(src.m_buffer)
{}

template<>
inline
sys_string_t<generic_storage> build(generic_builder_impl & builder) noexcept
sys_string_t<win_generic_storage> build(win_generic_builder_impl & builder) noexcept
{
return sys_string_t<generic_storage>(convert_to_string(builder));
return sys_string_t<win_generic_storage>(convert_to_string(builder));
}
}

namespace sysstr
{
template<>
inline
sys_string_t<generic_storage>::sys_string_t(const char_access::cursor & src, size_type length):
sys_string_t<win_generic_storage>::sys_string_t(const char_access::cursor & src, size_type length):
sys_string_t(src.iterator(), length)
{}

template<>
inline
sys_string_t<generic_storage>::sys_string_t(const char_access::reverse_cursor & src, size_type length):
sys_string_t<win_generic_storage>::sys_string_t(const char_access::reverse_cursor & src, size_type length):
sys_string_t(src.iterator() - length, length)
{}

template<>
inline
sys_string_t<generic_storage>::sys_string_t(const char_access::iterator & first, const char_access::iterator & last):
sys_string_t<win_generic_storage>::sys_string_t(const char_access::iterator & first, const char_access::iterator & last):
sys_string_t(first, last - first)
{}

using sys_string_generic = sys_string_t<generic_storage>;
using sys_string_generic_builder = sys_string_builder_t<generic_storage>;
using sys_string_win_generic = sys_string_t<win_generic_storage>;
using sys_string_win_generic_builder = sys_string_builder_t<win_generic_storage>;
}

#define SYS_STRING_STATIC_GENERIC(x) ([] () noexcept -> ::sysstr::sys_string_generic { \
#define SYS_STRING_STATIC_WIN_GENERIC(x) ([] () noexcept -> ::sysstr::sys_string_win_generic { \
constexpr ::size_t size = sizeof(u##x) / sizeof(char16_t); \
static const ::sysstr::util::generic_static_buffer<size> sbuf{0, true, u##x}; \
::sysstr::util::generic_buffer buf((::sysstr::util::generic_dynamic_buffer *)&sbuf, size - 1, 0); \
return *reinterpret_cast<::sysstr::sys_string_generic *>(&buf); \
static const ::sysstr::util::win_generic_static_buffer<size> sbuf{0, true, u##x}; \
::sysstr::util::win_generic_buffer buf((::sysstr::util::win_generic_dynamic_buffer *)&sbuf, size - 1, 0); \
return *reinterpret_cast<::sysstr::sys_string_win_generic *>(&buf); \
}())


Expand Down
2 changes: 1 addition & 1 deletion lib/scripts/genmappings.py
Original file line number Diff line number Diff line change
Expand Up @@ -227,7 +227,7 @@ def make_whitespaces():
read_ucd_file(datadir/'DerivedCoreProperties.txt', parse_derived_properties)

prop_builder.generate()
print(f'{prop_builder.block_size}: {len(prop_builder.stage1)}, {len(prop_builder.blocks)}, {len(prop_builder.stage1) + len(prop_builder.blocks) * prop_builder.block_size // prop_builder.count_per_byte}')
#print(f'{prop_builder.block_size}: {len(prop_builder.stage1)}, {len(prop_builder.blocks)}, {len(prop_builder.stage1) + len(prop_builder.blocks) * prop_builder.block_size // prop_builder.count_per_byte}')


write_file(cppfile, f'''//THIS FILE IS GENERATED. PLEASE DO NOT EDIT DIRECTLY
Expand Down
1 change: 1 addition & 0 deletions test/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ if (WIN32)
bstr
hstring
win_gen
unix_gen
)

elseif(${CMAKE_SYSTEM_NAME} STREQUAL "Darwin")
Expand Down
22 changes: 20 additions & 2 deletions test/test_windows.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
//
#include <sys_string/sys_string.h>


#include "catch.hpp"

using namespace sysstr;
Expand Down Expand Up @@ -111,6 +110,25 @@ using namespace sysstr;
WindowsDeleteString(hstr);
}

#elif SYS_STRING_USE_GENERIC

TEST_CASE( "Windows Conversions", "[windows]") {

REQUIRE(sys_string().c_str());
CHECK(strcmp(sys_string().c_str(), "") == 0);

REQUIRE(S("").c_str());
CHECK(strcmp(S("").c_str(), "") == 0);

REQUIRE(sys_string("").c_str());
CHECK(strcmp(sys_string("").c_str(), "") == 0);

REQUIRE(sys_string((const char*)nullptr).c_str());
CHECK(strcmp(sys_string((const char*)nullptr).c_str(), "") == 0);

CHECK(strcmp(sys_string("a水𐀀𝄞bcå🤢").c_str(), "a水𐀀𝄞bcå🤢") == 0);
}

#else

TEST_CASE( "Windows Conversions", "[windows]") {
Expand All @@ -130,4 +148,4 @@ using namespace sysstr;
CHECK(wcscmp(sys_string(L"a水𐀀𝄞bcå🤢").w_str(), L"a水𐀀𝄞bcå🤢") == 0);
}

#endif
#endif

0 comments on commit 3d67f3e

Please sign in to comment.