mirror of
https://github.com/isar/libmdbx.git
synced 2024-10-29 23:19:20 +08:00
mdbx++: Add support for C++17 polymorphic allocators.
Change-Id: I76054829551c247a4d8f81288fc47db47ead0288
This commit is contained in:
parent
08faeda430
commit
aa7695c513
223
src/mdbx.c++
223
src/mdbx.c++
@ -25,7 +25,6 @@
|
||||
#include "internals.h"
|
||||
|
||||
#include <atomic>
|
||||
#include <sstream>
|
||||
#include <system_error>
|
||||
|
||||
#if defined(__has_include) && __has_include(<version>)
|
||||
@ -150,10 +149,11 @@ __cold std::string format_va(const char *fmt, va_list ap) {
|
||||
#endif
|
||||
assert(needed >= 0);
|
||||
std::string result;
|
||||
result.reserve((size_t)needed + 1);
|
||||
result.resize((size_t)needed, '\0');
|
||||
assert((int)result.capacity() > needed);
|
||||
int actual = vsnprintf((char *)result.data(), result.capacity(), fmt, ones);
|
||||
result.reserve(size_t(needed + 1));
|
||||
result.resize(size_t(needed), '\0');
|
||||
assert(int(result.capacity()) > needed);
|
||||
int actual = vsnprintf(const_cast<char *>(result.data()), result.capacity(),
|
||||
fmt, ones);
|
||||
assert(actual == needed);
|
||||
(void)actual;
|
||||
va_end(ones);
|
||||
@ -275,6 +275,10 @@ namespace mdbx {
|
||||
"mdbx:: exceeded the maximal length of data/slice/buffer");
|
||||
}
|
||||
|
||||
[[noreturn]] __cold void throw_too_small_target_buffer() {
|
||||
throw std::length_error("mdbx:: the target buffer is too small");
|
||||
}
|
||||
|
||||
__cold exception::exception(const error &error) noexcept
|
||||
: base(error.what()), error_(error) {}
|
||||
|
||||
@ -430,6 +434,61 @@ __cold void error::throw_exception() const {
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
char *slice::to_hex(char *dst, size_t dst_size, bool uppercase) const {
|
||||
if (mdbx_unlikely((dst_size >> 1) < length()))
|
||||
throw_too_small_target_buffer();
|
||||
auto src = byte_ptr();
|
||||
const auto end = src + length();
|
||||
const char x0A = (uppercase ? 'A' : 'a') - 10;
|
||||
while (src != end) {
|
||||
const char high = *src >> 4;
|
||||
const char low = *src & 15;
|
||||
dst[0] = (high < 10) ? high + '0' : high + x0A;
|
||||
dst[1] = (low < 10) ? low + '0' : low + x0A;
|
||||
src += 1;
|
||||
dst += 2;
|
||||
}
|
||||
return dst;
|
||||
}
|
||||
|
||||
char *slice::from_hex(char *dest, size_t dest_size) const {
|
||||
if (length() % 2)
|
||||
throw std::invalid_argument(
|
||||
"mdbx::from_hex:: odd length of hexadecimal string");
|
||||
(void)dest;
|
||||
(void)dest_size;
|
||||
NOT_IMPLEMENTED();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
char *slice::to_base58(char *dest, size_t dest_size) const {
|
||||
(void)dest;
|
||||
(void)dest_size;
|
||||
NOT_IMPLEMENTED();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
char *slice::from_base58(char *dest, size_t dest_size) const {
|
||||
(void)dest;
|
||||
(void)dest_size;
|
||||
NOT_IMPLEMENTED();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
char *slice::to_base64(char *dest, size_t dest_size) const {
|
||||
(void)dest;
|
||||
(void)dest_size;
|
||||
NOT_IMPLEMENTED();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
char *slice::from_base64(char *dest, size_t dest_size) const {
|
||||
(void)dest;
|
||||
(void)dest_size;
|
||||
NOT_IMPLEMENTED();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool slice::is_base64() const noexcept {
|
||||
NOT_IMPLEMENTED();
|
||||
return true;
|
||||
@ -445,149 +504,13 @@ bool slice::is_printable(bool allow_utf8) const noexcept {
|
||||
return allow_utf8;
|
||||
}
|
||||
|
||||
std::string slice::hex_string(bool uppercase) const {
|
||||
std::string result;
|
||||
if (length() > 0) {
|
||||
result.reserve(length() * 2);
|
||||
const uint8_t *ptr = static_cast<const uint8_t *>(data());
|
||||
const uint8_t *const end = ptr + length();
|
||||
const char x0A = (uppercase ? 'A' : 'a') - 10;
|
||||
do {
|
||||
char high = *ptr >> 4;
|
||||
char low = *ptr & 15;
|
||||
result.push_back((high < 10) ? high + '0' : high + x0A);
|
||||
result.push_back((low < 10) ? low + '0' : low + x0A);
|
||||
} while (++ptr < end);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
std::string slice::base64_string() const {
|
||||
std::string result;
|
||||
NOT_IMPLEMENTED();
|
||||
return result;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
void buffer::reserve(size_t head_room, size_t tail_room) {
|
||||
if (unlikely(head_room > max_length || tail_room > max_length ||
|
||||
head_room + tail_room > max_length - slice_.length()))
|
||||
throw_max_length_exceeded();
|
||||
template class LIBMDBX_API_TYPE buffer<default_allocator>;
|
||||
|
||||
const size_t whole = head_room + slice_.length() + tail_room;
|
||||
if (whole == 0)
|
||||
silo_.clear();
|
||||
else if (is_reference() || slice_.empty()) {
|
||||
silo_.reserve(whole);
|
||||
silo_.append(head_room, '\0');
|
||||
silo_.append(slice_.char_ptr(), slice_.length());
|
||||
} else {
|
||||
std::string buffer;
|
||||
buffer.reserve(whole);
|
||||
buffer.append(head_room, '\0');
|
||||
buffer.append(slice_.char_ptr(), slice_.length());
|
||||
silo_.assign(std::move(buffer));
|
||||
}
|
||||
slice_.iov_base = const_cast<char *>(silo_.data());
|
||||
}
|
||||
|
||||
void buffer::insulate() {
|
||||
assert(is_reference());
|
||||
silo_.assign(slice_.char_ptr(), slice_.length());
|
||||
slice_.iov_base = const_cast<char *>(silo_.data());
|
||||
}
|
||||
|
||||
buffer &buffer::assign_reference(const void *ptr, size_t bytes) noexcept {
|
||||
silo_.clear();
|
||||
slice_.assign(ptr, bytes);
|
||||
return *this;
|
||||
}
|
||||
|
||||
buffer &buffer::assign_freestanding(const void *ptr, size_t bytes) {
|
||||
silo_.assign(static_cast<const char *>(ptr), check_length(bytes));
|
||||
slice_.assign(silo_);
|
||||
return *this;
|
||||
}
|
||||
|
||||
void buffer::clear() noexcept {
|
||||
slice_.reset();
|
||||
silo_.clear();
|
||||
}
|
||||
|
||||
void buffer::shrink_to_fit() {
|
||||
if (silo_.capacity() != length()) {
|
||||
if (silo_.length() != length())
|
||||
silo_.assign(char_ptr(), length());
|
||||
silo_.shrink_to_fit();
|
||||
slice_.assign(silo_);
|
||||
}
|
||||
}
|
||||
|
||||
void buffer::shrink() {
|
||||
if (silo_.length() != length()) {
|
||||
silo_.assign(char_ptr(), length());
|
||||
slice_.assign(silo_);
|
||||
}
|
||||
}
|
||||
|
||||
int buffer::thunk::cb_copy(void *context, MDBX_val *target, const void *src,
|
||||
size_t bytes) noexcept {
|
||||
thunk *self = static_cast<thunk *>(context);
|
||||
assert(self->is_clean());
|
||||
try {
|
||||
owner_of(static_cast<slice *>(target), &buffer::slice_)
|
||||
->assign(src, bytes, false);
|
||||
return MDBX_RESULT_FALSE;
|
||||
} catch (... /* capture any exception to rethrow it over C code */) {
|
||||
self->capture();
|
||||
return MDBX_RESULT_TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
buffer::buffer(size_t head_room, size_t tail_room) {
|
||||
if (unlikely(head_room > max_length || tail_room > max_length ||
|
||||
head_room + tail_room > max_length))
|
||||
throw_max_length_exceeded();
|
||||
silo_.reserve(head_room + tail_room);
|
||||
silo_.append(head_room, '\0');
|
||||
slice_.iov_base = const_cast<char *>(silo_.data());
|
||||
assert(slice_.iov_len == 0);
|
||||
}
|
||||
|
||||
buffer::buffer(size_t head_room, const slice &src, size_t tail_room) {
|
||||
if (unlikely(head_room > max_length || tail_room > max_length ||
|
||||
head_room + tail_room > max_length - slice_.length()))
|
||||
throw_max_length_exceeded();
|
||||
silo_.reserve(head_room + src.length() + tail_room);
|
||||
silo_.append(head_room, '\0');
|
||||
silo_.append(src.char_ptr(), src.length());
|
||||
slice_.iov_base = const_cast<char *>(silo_.data());
|
||||
slice_.iov_len = src.length();
|
||||
}
|
||||
|
||||
buffer::buffer(size_t capacity) {
|
||||
silo_.reserve(check_length(capacity));
|
||||
slice_.iov_base = const_cast<char *>(silo_.data());
|
||||
assert(slice_.iov_len == 0);
|
||||
}
|
||||
|
||||
buffer::buffer(const txn_ref &txn, const slice &src)
|
||||
: buffer(src, !txn.is_dirty(src.data())) {}
|
||||
|
||||
buffer buffer::decode_hex(const slice &hex) {
|
||||
if (hex.length() % 2)
|
||||
throw std::invalid_argument("odd length of hexadecimal string");
|
||||
buffer result(hex.length() / 2);
|
||||
NOT_IMPLEMENTED();
|
||||
return result;
|
||||
}
|
||||
|
||||
buffer buffer::decode_base64(const slice &base64) {
|
||||
buffer result(base64.length() * 4 / 3);
|
||||
NOT_IMPLEMENTED();
|
||||
return result;
|
||||
}
|
||||
#if defined(__cpp_lib_memory_resource) && __cpp_lib_memory_resource >= 201603L
|
||||
template class LIBMDBX_API_TYPE buffer<polymorphic_allocator>;
|
||||
#endif /* __cpp_lib_memory_resource >= 201603L */
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
@ -858,10 +781,6 @@ __cold ::std::ostream &operator<<(::std::ostream &, const pair &) {
|
||||
NOT_IMPLEMENTED();
|
||||
}
|
||||
|
||||
__cold ::std::ostream &operator<<(::std::ostream &, const buffer &) {
|
||||
NOT_IMPLEMENTED();
|
||||
}
|
||||
|
||||
__cold ::std::ostream &operator<<(::std::ostream &, const env_ref::geometry &) {
|
||||
NOT_IMPLEMENTED();
|
||||
}
|
||||
@ -954,12 +873,6 @@ __cold string to_string(const ::mdbx::pair &value) {
|
||||
return out.str();
|
||||
}
|
||||
|
||||
__cold string to_string(const ::mdbx::buffer &value) {
|
||||
ostringstream out;
|
||||
out << value;
|
||||
return out.str();
|
||||
}
|
||||
|
||||
__cold string to_string(const ::mdbx::env_ref::geometry &value) {
|
||||
ostringstream out;
|
||||
out << value;
|
||||
|
Loading…
Reference in New Issue
Block a user