From dd01aabaebee262552f3920e57f66fed2d04dbd3 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: Mon, 8 Aug 2022 15:06:27 +0300 Subject: [PATCH 1/4] mdbx: add `MDBX_WEAK_IMPORT_ATTRIBUTE` macro. --- src/base.h | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/base.h b/src/base.h index e5297745..4c9e77cd 100644 --- a/src/base.h +++ b/src/base.h @@ -611,6 +611,19 @@ __extern_C key_t ftok(const char *, int); #endif #endif /* __anonymous_struct_extension__ */ +#ifndef MDBX_WEAK_IMPORT_ATTRIBUTE +#ifdef WEAK_IMPORT_ATTRIBUTE +#define MDBX_WEAK_IMPORT_ATTRIBUTE WEAK_IMPORT_ATTRIBUTE +#elif __has_attribute(__weak__) && __has_attribute(__weak_import__) +#define MDBX_WEAK_IMPORT_ATTRIBUTE __attribute__((__weak__, __weak_import__)) +#elif __has_attribute(__weak__) || \ + (defined(__GNUC__) && __GNUC__ >= 4 && defined(__ELF__)) +#define MDBX_WEAK_IMPORT_ATTRIBUTE __attribute__((__weak__)) +#else +#define MDBX_WEAK_IMPORT_ATTRIBUTE +#endif +#endif /* MDBX_WEAK_IMPORT_ATTRIBUTE */ + /*----------------------------------------------------------------------------*/ #if defined(MDBX_USE_VALGRIND) From 6d85e35876cc55d3079b2f6238044b67d90a4151 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: Mon, 8 Aug 2022 15:08:18 +0300 Subject: [PATCH 2/4] mdbx: never use modern `__cxa_thread_atexit()` on Apple's OSes. --- src/base.h | 4 +-- src/core.c | 71 +++++++++++++++++++++++++----------------------------- 2 files changed, 35 insertions(+), 40 deletions(-) diff --git a/src/base.h b/src/base.h index 4c9e77cd..ec5321ff 100644 --- a/src/base.h +++ b/src/base.h @@ -157,12 +157,12 @@ #define nullptr NULL #endif -#ifdef __APPLE__ +#if defined(__APPLE__) || defined(_DARWIN_C_SOURCE) #include +#include #ifndef MAC_OS_X_VERSION_MIN_REQUIRED #define MAC_OS_X_VERSION_MIN_REQUIRED 1070 /* Mac OS X 10.7, 2011 */ #endif -#include #endif /* Apple OSX & iOS */ #if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || \ diff --git a/src/core.c b/src/core.c index 13a02338..553f8c7d 100644 --- a/src/core.c +++ b/src/core.c @@ -1269,55 +1269,50 @@ rthc_compare_and_clean(const void *rthc, const uint64_t signature) { static __inline int rthc_atexit(void (*dtor)(void *), void *obj, void *dso_symbol) { - int rc = MDBX_ENOSYS; +#ifndef MDBX_HAVE_CXA_THREAD_ATEXIT_IMPL +#if defined(LIBCXXABI_HAS_CXA_THREAD_ATEXIT_IMPL) || \ + defined(HAVE___CXA_THREAD_ATEXIT_IMPL) || __GLIBC_PREREQ(2, 18) || \ + defined(ANDROID) +#define MDBX_HAVE_CXA_THREAD_ATEXIT_IMPL 1 +#else +#define MDBX_HAVE_CXA_THREAD_ATEXIT_IMPL 0 +#endif +#endif /* MDBX_HAVE_CXA_THREAD_ATEXIT_IMPL */ -#if defined(__APPLE__) || defined(_DARWIN_C_SOURCE) -#if !defined(MAC_OS_X_VERSION_MIN_REQUIRED) || !defined(MAC_OS_X_VERSION_10_7) -#error \ - "The should be included and MAC_OS_X_VERSION_MIN_REQUIRED must be defined" -#elif MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_7 +#ifndef MDBX_HAVE_CXA_THREAD_ATEXIT +#if defined(LIBCXXABI_HAS_CXA_THREAD_ATEXIT) || \ + defined(HAVE___CXA_THREAD_ATEXIT) +#define MDBX_HAVE_CXA_THREAD_ATEXIT 1 +#elif !MDBX_HAVE_CXA_THREAD_ATEXIT_IMPL && \ + (defined(__linux__) || defined(__gnu_linux__)) +#define MDBX_HAVE_CXA_THREAD_ATEXIT 1 +#else +#define MDBX_HAVE_CXA_THREAD_ATEXIT 0 +#endif +#endif /* MDBX_HAVE_CXA_THREAD_ATEXIT */ + + int rc = MDBX_ENOSYS; +#if MDBX_HAVE_CXA_THREAD_ATEXIT_IMPL && !MDBX_HAVE_CXA_THREAD_ATEXIT +#define __cxa_thread_atexit __cxa_thread_atexit_impl +#endif +#if MDBX_HAVE_CXA_THREAD_ATEXIT || defined(__cxa_thread_atexit) + extern int __cxa_thread_atexit(void (*dtor)(void *), void *obj, + void *dso_symbol) MDBX_WEAK_IMPORT_ATTRIBUTE; + if (&__cxa_thread_atexit) + rc = __cxa_thread_atexit(dtor, obj, dso_symbol); +#elif defined(__APPLE__) || defined(_DARWIN_C_SOURCE) extern void _tlv_atexit(void (*termfunc)(void *objAddr), void *objAddr) - __attribute__((__weak__, __weak_import__)); - if (rc && &_tlv_atexit) { + MDBX_WEAK_IMPORT_ATTRIBUTE; + if (&_tlv_atexit) { (void)dso_symbol; _tlv_atexit(dtor, obj); rc = 0; } -#elif !defined(MDBX_HAVE_CXA_THREAD_ATEXIT) -#define MDBX_HAVE_CXA_THREAD_ATEXIT 1 -#endif /* MAC_OS_X_VERSION_MIN_REQUIRED */ -#endif /* Apple */ - -#if defined(MDBX_HAVE_CXA_THREAD_ATEXIT) && MDBX_HAVE_CXA_THREAD_ATEXIT - extern int __cxa_thread_atexit(void (*dtor)(void *), void *obj, - void *dso_symbol) -#ifdef WEAK_IMPORT_ATTRIBUTE - WEAK_IMPORT_ATTRIBUTE -#elif defined(MAC_OS_X_VERSION_MIN_REQUIRED) && \ - MAC_OS_X_VERSION_MIN_REQUIRED >= 1020 && \ - ((__has_attribute(__weak__) && __has_attribute(__weak_import__)) || \ - (defined(__GNUC__) && __GNUC__ >= 4)) - __attribute__((__weak__, __weak_import__)) -#elif (__has_attribute(__weak__) || (defined(__GNUC__) && __GNUC__ >= 4)) && \ - !defined(MAC_OS_X_VERSION_MIN_REQUIRED) - __attribute__((__weak__)) -#endif - ; - if (rc && &__cxa_thread_atexit) - rc = __cxa_thread_atexit(dtor, obj, dso_symbol); -#elif __GLIBC_PREREQ(2, 18) || defined(ANDROID) || defined(__linux__) || \ - defined(__gnu_linux__) - extern int __cxa_thread_atexit_impl(void (*dtor)(void *), void *obj, - void *dso_symbol) - __attribute__((__weak__)); - if (rc && &__cxa_thread_atexit_impl) - rc = __cxa_thread_atexit_impl(dtor, obj, dso_symbol); #else (void)dtor; (void)obj; (void)dso_symbol; #endif - return rc; } From c8b1392cbe0a2e50273d81e67dbdc2a7b0c60b87 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 16:12:24 +0300 Subject: [PATCH 3/4] mdbx: use `MultiByteToWideChar(CP_THREAD_ACP)` instead of `mbstowcs()`. --- src/core.c | 8 ++------ src/mdbx.c++ | 33 ++++++++++++--------------------- src/osal.c | 49 +++++++++++++++++++++++++++++++------------------ src/osal.h | 19 +++++++++++++++++++ 4 files changed, 64 insertions(+), 45 deletions(-) diff --git a/src/core.c b/src/core.c index 553f8c7d..0dc38fba 100644 --- a/src/core.c +++ b/src/core.c @@ -12971,12 +12971,8 @@ __cold static int mdbx_handle_env_pathname(MDBX_handle_env_pathname *ctx, return MDBX_EINVAL; #if defined(_WIN32) || defined(_WIN64) - const size_t wlen = mbstowcs(nullptr, pathname, INT_MAX); - if (wlen < 1 || wlen > /* MAX_PATH */ INT16_MAX) - return ERROR_INVALID_NAME; - wchar_t *const pathnameW = _alloca((wlen + 1) * sizeof(wchar_t)); - if (wlen != mbstowcs(pathnameW, pathname, wlen + 1)) - return ERROR_INVALID_NAME; + const wchar_t *pathnameW = nullptr; + MUSTDIE_MB2WIDE(pathname, pathnameW); const DWORD dwAttrib = GetFileAttributesW(pathnameW); if (dwAttrib == INVALID_FILE_ATTRIBUTES) { diff --git a/src/mdbx.c++ b/src/mdbx.c++ index ccb5fa3e..56cb345f 100644 --- a/src/mdbx.c++ +++ b/src/mdbx.c++ @@ -216,26 +216,17 @@ MDBX_MAYBE_UNUSED PATH pchar_to_path(const char *c_str) { #if defined(_WIN32) || defined(_WIN64) -#ifndef WC_ERR_INVALID_CHARS -static const DWORD WC_ERR_INVALID_CHARS = - (6 /* Windows Vista */ <= /* MajorVersion */ LOBYTE(LOWORD(GetVersion()))) - ? 0x00000080 - : 0; -#endif /* WC_ERR_INVALID_CHARS */ - template <> struct path_to_pchar { std::string str; path_to_pchar(const std::wstring &path) { if (!path.empty()) { - const int chars = - WideCharToMultiByte(CP_UTF8, WC_ERR_INVALID_CHARS, path.data(), - int(path.size()), nullptr, 0, nullptr, nullptr); - if (chars == 0) + const auto chars = mdbx_w2mb(nullptr, 0, path.data(), path.size()); + if (chars < 1) mdbx::error::throw_exception(GetLastError()); str.append(chars, '\0'); - WideCharToMultiByte(CP_UTF8, WC_ERR_INVALID_CHARS, path.data(), - int(path.size()), const_cast(str.data()), - chars, nullptr, nullptr); + if (!mdbx_w2mb(const_cast(str.data()), chars, path.data(), + path.size())) + mdbx::error::throw_exception(GetLastError()); } } operator const char *() const { return str.c_str(); } @@ -245,14 +236,14 @@ template <> MDBX_MAYBE_UNUSED std::wstring pchar_to_path(const char *c_str) { std::wstring wstr; if (c_str && *c_str) { - const int chars = MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, c_str, - int(strlen(c_str)), nullptr, 0); - if (chars == 0) + const auto c_str_len = strlen(c_str); + const auto wchars = mdbx_mb2w(nullptr, 0, c_str, c_str_len); + if (wchars < 1) + mdbx::error::throw_exception(GetLastError()); + wstr.append(wchars, '\0'); + if (!mdbx_mb2w(const_cast(wstr.data()), wchars, c_str, + c_str_len)) mdbx::error::throw_exception(GetLastError()); - wstr.append(chars, '\0'); - MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, c_str, - int(strlen(c_str)), const_cast(wstr.data()), - chars); } return wstr; } diff --git a/src/osal.c b/src/osal.c index f2ad4ab8..f0bbbc32 100644 --- a/src/osal.c +++ b/src/osal.c @@ -518,14 +518,35 @@ MDBX_INTERNAL_FUNC int mdbx_fastmutex_release(mdbx_fastmutex_t *fastmutex) { /*----------------------------------------------------------------------------*/ +#if defined(_WIN32) || defined(_WIN64) + +#ifndef WC_ERR_INVALID_CHARS +static const DWORD WC_ERR_INVALID_CHARS = + (6 /* Windows Vista */ <= /* MajorVersion */ LOBYTE(LOWORD(GetVersion()))) + ? 0x00000080 + : 0; +#endif /* WC_ERR_INVALID_CHARS */ + +MDBX_INTERNAL_FUNC size_t mdbx_mb2w(wchar_t *dst, size_t dst_n, const char *src, + size_t src_n) { + return MultiByteToWideChar(CP_THREAD_ACP, MB_ERR_INVALID_CHARS, src, + (int)src_n, dst, (int)dst_n); +} + +MDBX_INTERNAL_FUNC size_t mdbx_w2mb(char *dst, size_t dst_n, const wchar_t *src, + size_t src_n) { + return WideCharToMultiByte(CP_THREAD_ACP, WC_ERR_INVALID_CHARS, src, + (int)src_n, dst, (int)dst_n, nullptr, nullptr); +} + +#endif /* Windows */ + +/*----------------------------------------------------------------------------*/ + MDBX_INTERNAL_FUNC int mdbx_removefile(const char *pathname) { #if defined(_WIN32) || defined(_WIN64) - const size_t wlen = mbstowcs(nullptr, pathname, INT_MAX); - if (wlen < 1 || wlen > /* MAX_PATH */ INT16_MAX) - return ERROR_INVALID_NAME; - wchar_t *const pathnameW = _alloca((wlen + 1) * sizeof(wchar_t)); - if (wlen != mbstowcs(pathnameW, pathname, wlen + 1)) - return ERROR_INVALID_NAME; + const wchar_t *pathnameW = nullptr; + MUSTDIE_MB2WIDE(pathname, pathnameW); return DeleteFileW(pathnameW) ? MDBX_SUCCESS : (int)GetLastError(); #else return unlink(pathname) ? errno : MDBX_SUCCESS; @@ -538,12 +559,8 @@ static bool is_valid_fd(int fd) { return !(isatty(fd) < 0 && errno == EBADF); } MDBX_INTERNAL_FUNC int mdbx_removedirectory(const char *pathname) { #if defined(_WIN32) || defined(_WIN64) - const size_t wlen = mbstowcs(nullptr, pathname, INT_MAX); - if (wlen < 1 || wlen > /* MAX_PATH */ INT16_MAX) - return ERROR_INVALID_NAME; - wchar_t *const pathnameW = _alloca((wlen + 1) * sizeof(wchar_t)); - if (wlen != mbstowcs(pathnameW, pathname, wlen + 1)) - return ERROR_INVALID_NAME; + const wchar_t *pathnameW = nullptr; + MUSTDIE_MB2WIDE(pathname, pathnameW); return RemoveDirectoryW(pathnameW) ? MDBX_SUCCESS : (int)GetLastError(); #else return rmdir(pathname) ? errno : MDBX_SUCCESS; @@ -557,12 +574,8 @@ MDBX_INTERNAL_FUNC int mdbx_openfile(const enum mdbx_openfile_purpose purpose, *fd = INVALID_HANDLE_VALUE; #if defined(_WIN32) || defined(_WIN64) - const size_t wlen = mbstowcs(nullptr, pathname, INT_MAX); - if (wlen < 1 || wlen > /* MAX_PATH */ INT16_MAX) - return ERROR_INVALID_NAME; - wchar_t *const pathnameW = _alloca((wlen + 1) * sizeof(wchar_t)); - if (wlen != mbstowcs(pathnameW, pathname, wlen + 1)) - return ERROR_INVALID_NAME; + const wchar_t *pathnameW = nullptr; + MUSTDIE_MB2WIDE(pathname, pathnameW); DWORD CreationDisposition = unix_mode_bits ? OPEN_ALWAYS : OPEN_EXISTING; DWORD FlagsAndAttributes = diff --git a/src/osal.h b/src/osal.h index 049d99dc..3ac5ce44 100644 --- a/src/osal.h +++ b/src/osal.h @@ -180,6 +180,11 @@ static inline void mdbx_free(void *ptr) { HeapFree(GetProcessHeap(), 0, ptr); } #define vsnprintf _vsnprintf /* ntdll */ #endif +MDBX_INTERNAL_FUNC size_t mdbx_mb2w(wchar_t *dst, size_t dst_n, const char *src, + size_t src_n); +MDBX_INTERNAL_FUNC size_t mdbx_w2mb(char *dst, size_t dst_n, const wchar_t *src, + size_t src_n); + #else /*----------------------------------------------------------------------*/ typedef pthread_t mdbx_thread_t; @@ -549,6 +554,20 @@ MDBX_INTERNAL_FUNC int mdbx_rpid_check(MDBX_env *env, uint32_t pid); #if defined(_WIN32) || defined(_WIN64) +#define MUSTDIE_MB2WIDE(FROM, TO) \ + do { \ + const char *const from_tmp = (FROM); \ + const size_t from_mblen = strlen(from_tmp); \ + const size_t to_wlen = mdbx_mb2w(nullptr, 0, from_tmp, from_mblen); \ + if (to_wlen < 1 || to_wlen > /* MAX_PATH */ INT16_MAX) \ + return ERROR_INVALID_NAME; \ + wchar_t *const to_tmp = _alloca((to_wlen + 1) * sizeof(wchar_t)); \ + if (to_wlen + 1 != \ + mdbx_mb2w(to_tmp, to_wlen + 1, from_tmp, from_mblen + 1)) \ + return ERROR_INVALID_NAME; \ + (TO) = to_tmp; \ + } while (0) + typedef void(WINAPI *MDBX_srwlock_function)(MDBX_srwlock *); MDBX_INTERNAL_VAR MDBX_srwlock_function mdbx_srwlock_Init, mdbx_srwlock_AcquireShared, mdbx_srwlock_ReleaseShared, 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 4/4] 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() {