mirror of
				https://github.com/isar/libmdbx.git
				synced 2025-10-31 03:29:01 +08:00 
			
		
		
		
	mdbx++: Add support for C++17 polymorphic allocators.
Change-Id: I76054829551c247a4d8f81288fc47db47ead0288
This commit is contained in:
		
							
								
								
									
										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; | ||||
|   | ||||
		Reference in New Issue
	
	Block a user