From 0287a00ee34fc536054e434eaaa0ce96e87658b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9B=D0=B5=D0=BE=D0=BD=D0=B8=D0=B4=20=D0=AE=D1=80=D1=8C?= =?UTF-8?q?=D0=B5=D0=B2=20=28Leonid=20Yuriev=29?= Date: Tue, 9 Aug 2022 17:09:05 +0300 Subject: [PATCH] mdbx++: refine/simplify `wchar_t` support for pathnames. --- src/mdbx.c++ | 224 ++++++++++++++++++--------------------------------- 1 file changed, 80 insertions(+), 144 deletions(-) diff --git a/src/mdbx.c++ b/src/mdbx.c++ index 56cb345f..2375a1b7 100644 --- a/src/mdbx.c++ +++ b/src/mdbx.c++ @@ -203,49 +203,35 @@ __cold bug::~bug() noexcept {} //------------------------------------------------------------------------------ -template struct path_to_pchar { - const std::string str; - path_to_pchar(const PATH &path) : str(path.generic_string()) {} - operator const char *() const { return str.c_str(); } -}; - -template -MDBX_MAYBE_UNUSED PATH pchar_to_path(const char *c_str) { - return PATH(c_str); -} - #if defined(_WIN32) || defined(_WIN64) -template <> struct path_to_pchar { - std::string str; - path_to_pchar(const std::wstring &path) { - if (!path.empty()) { - const auto chars = mdbx_w2mb(nullptr, 0, path.data(), path.size()); - if (chars < 1) - mdbx::error::throw_exception(GetLastError()); - str.append(chars, '\0'); - if (!mdbx_w2mb(const_cast(str.data()), chars, path.data(), - path.size())) - mdbx::error::throw_exception(GetLastError()); - } +std::string w2mb(const std::wstring &in) { + std::string out; + if (!in.empty()) { + const auto out_len = mdbx_w2mb(nullptr, 0, in.data(), in.size()); + if (out_len < 1) + mdbx::error::throw_exception(GetLastError()); + out.append(out_len, '\0'); + if (out_len != mdbx_w2mb(const_cast(out.data()), out_len, in.data(), + in.size())) + mdbx::error::throw_exception(GetLastError()); } - operator const char *() const { return str.c_str(); } -}; + return out; +} -template <> -MDBX_MAYBE_UNUSED std::wstring pchar_to_path(const char *c_str) { - std::wstring wstr; - if (c_str && *c_str) { - const auto c_str_len = strlen(c_str); - const auto wchars = mdbx_mb2w(nullptr, 0, c_str, c_str_len); - if (wchars < 1) +std::wstring mb2w(const char *in) { + std::wstring out; + if (in && *in) { + const auto in_len = strlen(in); + const auto out_len = mdbx_mb2w(nullptr, 0, in, in_len); + if (out_len < 1) mdbx::error::throw_exception(GetLastError()); - wstr.append(wchars, '\0'); - if (!mdbx_mb2w(const_cast(wstr.data()), wchars, c_str, - c_str_len)) + out.append(out_len, '\0'); + if (out_len != + mdbx_mb2w(const_cast(out.data()), out_len, in, in_len)) mdbx::error::throw_exception(GetLastError()); } - return wstr; + return out; } #endif /* Windows */ @@ -1230,31 +1216,14 @@ bool env::is_pristine() const { bool env::is_empty() const { return get_stat().ms_leaf_pages == 0; } -#ifdef MDBX_STD_FILESYSTEM_PATH -env &env::copy(const MDBX_STD_FILESYSTEM_PATH &destination, bool compactify, - bool force_dynamic_size) { - const path_to_pchar utf8(destination); +env &env::copy(filehandle fd, bool compactify, bool force_dynamic_size) { error::success_or_throw( - ::mdbx_env_copy(handle_, utf8, - (compactify ? MDBX_CP_COMPACT : MDBX_CP_DEFAULTS) | - (force_dynamic_size ? MDBX_CP_FORCE_DYNAMIC_SIZE - : MDBX_CP_DEFAULTS))); + ::mdbx_env_copy2fd(handle_, fd, + (compactify ? MDBX_CP_COMPACT : MDBX_CP_DEFAULTS) | + (force_dynamic_size ? MDBX_CP_FORCE_DYNAMIC_SIZE + : MDBX_CP_DEFAULTS))); return *this; } -#endif /* MDBX_STD_FILESYSTEM_PATH */ - -#if defined(_WIN32) || defined(_WIN64) -env &env::copy(const ::std::wstring &destination, bool compactify, - bool force_dynamic_size) { - const path_to_pchar<::std::wstring> utf8(destination); - error::success_or_throw( - ::mdbx_env_copy(handle_, utf8, - (compactify ? MDBX_CP_COMPACT : MDBX_CP_DEFAULTS) | - (force_dynamic_size ? MDBX_CP_FORCE_DYNAMIC_SIZE - : MDBX_CP_DEFAULTS))); - return *this; -} -#endif /* Windows */ env &env::copy(const char *destination, bool compactify, bool force_dynamic_size) { @@ -1271,38 +1240,32 @@ env &env::copy(const ::std::string &destination, bool compactify, return copy(destination.c_str(), compactify, force_dynamic_size); } -env &env::copy(filehandle fd, bool compactify, bool force_dynamic_size) { - error::success_or_throw( - ::mdbx_env_copy2fd(handle_, fd, - (compactify ? MDBX_CP_COMPACT : MDBX_CP_DEFAULTS) | - (force_dynamic_size ? MDBX_CP_FORCE_DYNAMIC_SIZE - : MDBX_CP_DEFAULTS))); - return *this; -} - -path env::get_path() const { - const char *c_str; - error::success_or_throw(::mdbx_env_get_path(handle_, &c_str)); - return pchar_to_path(c_str); -} - #ifdef MDBX_STD_FILESYSTEM_PATH -bool env::remove(const MDBX_STD_FILESYSTEM_PATH &pathname, - const remove_mode mode) { - const path_to_pchar utf8(pathname); - return error::boolean_or_throw( - ::mdbx_env_delete(utf8, MDBX_env_delete_mode_t(mode))); +env &env::copy(const MDBX_STD_FILESYSTEM_PATH &destination, bool compactify, + bool force_dynamic_size) { + return copy(destination.native(), compactify, force_dynamic_size); } #endif /* MDBX_STD_FILESYSTEM_PATH */ #if defined(_WIN32) || defined(_WIN64) -bool env::remove(const ::std::wstring &pathname, const remove_mode mode) { - const path_to_pchar<::std::wstring> utf8(pathname); - return error::boolean_or_throw( - ::mdbx_env_delete(utf8, MDBX_env_delete_mode_t(mode))); +env &env::copy(const ::std::wstring &destination, bool compactify, + bool force_dynamic_size) { + return copy(w2mb(destination), compactify, force_dynamic_size); } #endif /* Windows */ +path env::get_path() const { + const char *c_str; + error::success_or_throw(::mdbx_env_get_path(handle_, &c_str)); +#if defined(_WIN32) || defined(_WIN64) + static_assert(sizeof(path::value_type) == sizeof(wchar_t), "Oops"); + return path(mb2w(c_str)); +#else + static_assert(sizeof(path::value_type) == sizeof(char), "Oops"); + return path(c_str); +#endif +} + bool env::remove(const char *pathname, const remove_mode mode) { return error::boolean_or_throw( ::mdbx_env_delete(pathname, MDBX_env_delete_mode_t(mode))); @@ -1312,6 +1275,19 @@ bool env::remove(const ::std::string &pathname, const remove_mode mode) { return remove(pathname.c_str(), mode); } +#ifdef MDBX_STD_FILESYSTEM_PATH +bool env::remove(const MDBX_STD_FILESYSTEM_PATH &pathname, + const remove_mode mode) { + return remove(pathname.native(), mode); +} +#endif /* MDBX_STD_FILESYSTEM_PATH */ + +#if defined(_WIN32) || defined(_WIN64) +bool env::remove(const ::std::wstring &pathname, const remove_mode mode) { + return remove(w2mb(pathname), mode); +} +#endif /* Windows */ + //------------------------------------------------------------------------------ static inline MDBX_env *create_env() { @@ -1348,68 +1324,6 @@ __cold void env_managed::setup(unsigned max_maps, unsigned max_readers) { error::success_or_throw(::mdbx_env_set_maxdbs(handle_, max_maps)); } -#ifdef MDBX_STD_FILESYSTEM_PATH -__cold env_managed::env_managed(const MDBX_STD_FILESYSTEM_PATH &pathname, - const operate_parameters &op, bool accede) - : env_managed(create_env()) { - setup(op.max_maps, op.max_readers); - const path_to_pchar utf8(pathname); - error::success_or_throw( - ::mdbx_env_open(handle_, utf8, op.make_flags(accede), 0)); - - if (op.options.nested_write_transactions && - !get_options().nested_write_transactions) - MDBX_CXX20_UNLIKELY error::throw_exception(MDBX_INCOMPATIBLE); -} - -__cold env_managed::env_managed(const MDBX_STD_FILESYSTEM_PATH &pathname, - const env_managed::create_parameters &cp, - const env::operate_parameters &op, bool accede) - : env_managed(create_env()) { - setup(op.max_maps, op.max_readers); - const path_to_pchar utf8(pathname); - set_geometry(cp.geometry); - error::success_or_throw( - ::mdbx_env_open(handle_, utf8, op.make_flags(accede, cp.use_subdirectory), - cp.file_mode_bits)); - - if (op.options.nested_write_transactions && - !get_options().nested_write_transactions) - MDBX_CXX20_UNLIKELY error::throw_exception(MDBX_INCOMPATIBLE); -} -#endif /* MDBX_STD_FILESYSTEM_PATH */ - -#if defined(_WIN32) || defined(_WIN64) -__cold env_managed::env_managed(const ::std::wstring &pathname, - const operate_parameters &op, bool accede) - : env_managed(create_env()) { - setup(op.max_maps, op.max_readers); - const path_to_pchar<::std::wstring> utf8(pathname); - error::success_or_throw( - ::mdbx_env_open(handle_, utf8, op.make_flags(accede), 0)); - - if (op.options.nested_write_transactions && - !get_options().nested_write_transactions) - MDBX_CXX20_UNLIKELY error::throw_exception(MDBX_INCOMPATIBLE); -} - -__cold env_managed::env_managed(const ::std::wstring &pathname, - const env_managed::create_parameters &cp, - const env::operate_parameters &op, bool accede) - : env_managed(create_env()) { - setup(op.max_maps, op.max_readers); - const path_to_pchar<::std::wstring> utf8(pathname); - set_geometry(cp.geometry); - error::success_or_throw( - ::mdbx_env_open(handle_, utf8, op.make_flags(accede, cp.use_subdirectory), - cp.file_mode_bits)); - - if (op.options.nested_write_transactions && - !get_options().nested_write_transactions) - MDBX_CXX20_UNLIKELY error::throw_exception(MDBX_INCOMPATIBLE); -} -#endif /* Windows */ - __cold env_managed::env_managed(const char *pathname, const operate_parameters &op, bool accede) : env_managed(create_env()) { @@ -1446,6 +1360,28 @@ __cold env_managed::env_managed(const ::std::string &pathname, const env::operate_parameters &op, bool accede) : env_managed(pathname.c_str(), cp, op, accede) {} +#ifdef MDBX_STD_FILESYSTEM_PATH +__cold env_managed::env_managed(const MDBX_STD_FILESYSTEM_PATH &pathname, + const operate_parameters &op, bool accede) + : env_managed(pathname.native(), op, accede) {} + +__cold env_managed::env_managed(const MDBX_STD_FILESYSTEM_PATH &pathname, + const env_managed::create_parameters &cp, + const env::operate_parameters &op, bool accede) + : env_managed(pathname.native(), cp, op, accede) {} +#endif /* MDBX_STD_FILESYSTEM_PATH */ + +#if defined(_WIN32) || defined(_WIN64) +__cold env_managed::env_managed(const ::std::wstring &pathname, + const operate_parameters &op, bool accede) + : env_managed(w2mb(pathname), op, accede) {} + +__cold env_managed::env_managed(const ::std::wstring &pathname, + const env_managed::create_parameters &cp, + const env::operate_parameters &op, bool accede) + : env_managed(w2mb(pathname), cp, op, accede) {} +#endif /* Windows */ + //------------------------------------------------------------------------------ txn_managed txn::start_nested() {