This is an automated email from the ASF dual-hosted git repository.
twice pushed a commit to branch unstable
in repository https://gitbox.apache.org/repos/asf/kvrocks.git
The following commit(s) were added to refs/heads/unstable by this push:
new 9d0d9266 Refactor encoding via templates (#1683)
9d0d9266 is described below
commit 9d0d9266231d7a982b7306056d288dcddcaf0b36
Author: Twice <[email protected]>
AuthorDate: Sun Aug 20 07:43:28 2023 +0800
Refactor encoding via templates (#1683)
We refactor encoding utils via templates in this PR.
All existing interfaces remain unchanged, and some missing and generic
interfaces are added.
---
src/common/encoding.cc | 144 +++++++-----------------------------------------
src/common/encoding.h | 83 +++++++++++++++++++++-------
src/common/event_util.h | 9 +--
src/common/status.h | 24 +++-----
src/common/type_util.h | 16 ++++++
5 files changed, 109 insertions(+), 167 deletions(-)
diff --git a/src/common/encoding.cc b/src/common/encoding.cc
index 20b30c9c..c2f738c9 100644
--- a/src/common/encoding.cc
+++ b/src/common/encoding.cc
@@ -29,106 +29,40 @@
#include <string>
#include <utility>
-void EncodeFixed8(char *buf, uint8_t value) { buf[0] = static_cast<char>(value
& 0xff); }
+inline uint64_t EncodeDoubleToUInt64(double value) {
+ uint64_t result = 0;
-void EncodeFixed16(char *buf, uint16_t value) {
- if constexpr (IsLittleEndian()) {
- value = __builtin_bswap16(value);
- }
- __builtin_memcpy(buf, &value, sizeof(value));
-}
-
-void EncodeFixed32(char *buf, uint32_t value) {
- if constexpr (IsLittleEndian()) {
- value = __builtin_bswap32(value);
- }
- __builtin_memcpy(buf, &value, sizeof(value));
-}
-
-void EncodeFixed64(char *buf, uint64_t value) {
- if constexpr (IsLittleEndian()) {
- value = __builtin_bswap64(value);
- }
- __builtin_memcpy(buf, &value, sizeof(value));
-}
-
-void PutFixed8(std::string *dst, uint8_t value) {
- char buf[1];
- EncodeFixed8(buf, value);
- dst->append(buf, sizeof(buf));
-}
-
-void PutFixed16(std::string *dst, uint16_t value) {
- char buf[sizeof(value)];
- EncodeFixed16(buf, value);
- dst->append(buf, sizeof(buf));
-}
-
-void PutFixed32(std::string *dst, uint32_t value) {
- char buf[sizeof(value)];
- EncodeFixed32(buf, value);
- dst->append(buf, sizeof(buf));
-}
+ __builtin_memcpy(&result, &value, sizeof(value));
-void PutFixed64(std::string *dst, uint64_t value) {
- char buf[sizeof(value)];
- EncodeFixed64(buf, value);
- dst->append(buf, sizeof(buf));
-}
-
-void PutDouble(std::string *dst, double value) {
- uint64_t u64 = 0;
-
- __builtin_memcpy(&u64, &value, sizeof(value));
-
- if ((u64 >> 63) == 1) {
+ if ((result >> 63) == 1) {
// signed bit would be zero
- u64 ^= 0xffffffffffffffff;
+ result ^= 0xffffffffffffffff;
} else {
// signed bit would be one
- u64 |= 0x8000000000000000;
+ result |= 0x8000000000000000;
}
- PutFixed64(dst, u64);
+ return result;
}
-bool GetFixed8(rocksdb::Slice *input, uint8_t *value) {
- const char *data = nullptr;
- if (input->size() < sizeof(uint8_t)) {
- return false;
+inline double DecodeDoubleFromUInt64(uint64_t value) {
+ if ((value >> 63) == 0) {
+ value ^= 0xffffffffffffffff;
+ } else {
+ value &= 0x7fffffffffffffff;
}
- data = input->data();
- *value = static_cast<uint8_t>(data[0] & 0xff);
- input->remove_prefix(sizeof(uint8_t));
- return true;
-}
-bool GetFixed64(rocksdb::Slice *input, uint64_t *value) {
- if (input->size() < sizeof(uint64_t)) {
- return false;
- }
- *value = DecodeFixed64(input->data());
- input->remove_prefix(sizeof(uint64_t));
- return true;
-}
+ double result = 0;
+ __builtin_memcpy(&result, &value, sizeof(result));
-bool GetFixed32(rocksdb::Slice *input, uint32_t *value) {
- if (input->size() < sizeof(uint32_t)) {
- return false;
- }
- *value = DecodeFixed32(input->data());
- input->remove_prefix(sizeof(uint32_t));
- return true;
+ return result;
}
-bool GetFixed16(rocksdb::Slice *input, uint16_t *value) {
- if (input->size() < sizeof(uint16_t)) {
- return false;
- }
- *value = DecodeFixed16(input->data());
- input->remove_prefix(sizeof(uint16_t));
- return true;
-}
+void EncodeDouble(char *buf, double value) { EncodeFixed64(buf,
EncodeDoubleToUInt64(value)); }
+
+void PutDouble(std::string *dst, double value) { PutFixed64(dst,
EncodeDoubleToUInt64(value)); }
+
+double DecodeDouble(const char *ptr) { return
DecodeDoubleFromUInt64(DecodeFixed64(ptr)); }
bool GetDouble(rocksdb::Slice *input, double *value) {
if (input->size() < sizeof(double)) return false;
@@ -137,44 +71,6 @@ bool GetDouble(rocksdb::Slice *input, double *value) {
return true;
}
-uint16_t DecodeFixed16(const char *ptr) {
- uint16_t value = 0;
-
- __builtin_memcpy(&value, ptr, sizeof(value));
-
- return IsLittleEndian() ? __builtin_bswap16(value) : value;
-}
-
-uint32_t DecodeFixed32(const char *ptr) {
- uint32_t value = 0;
-
- __builtin_memcpy(&value, ptr, sizeof(value));
-
- return IsLittleEndian() ? __builtin_bswap32(value) : value;
-}
-
-uint64_t DecodeFixed64(const char *ptr) {
- uint64_t value = 0;
-
- __builtin_memcpy(&value, ptr, sizeof(value));
-
- return IsLittleEndian() ? __builtin_bswap64(value) : value;
-}
-
-double DecodeDouble(const char *ptr) {
- uint64_t decoded = DecodeFixed64(ptr);
-
- if ((decoded >> 63) == 0) {
- decoded ^= 0xffffffffffffffff;
- } else {
- decoded &= 0x7fffffffffffffff;
- }
-
- double value = 0;
- __builtin_memcpy(&value, &decoded, sizeof(value));
- return value;
-}
-
char *EncodeVarint32(char *dst, uint32_t v) {
// Operate on characters as unsigneds
auto *ptr = reinterpret_cast<unsigned char *>(dst);
diff --git a/src/common/encoding.h b/src/common/encoding.h
index ea1c48bf..1fa4b020 100644
--- a/src/common/encoding.h
+++ b/src/common/encoding.h
@@ -32,28 +32,73 @@ enum class Endian {
NATIVE = __BYTE_ORDER__,
};
-constexpr bool IsLittleEndian() { return Endian::NATIVE == Endian::LITTLE; }
-constexpr bool IsBigEndian() { return Endian::NATIVE == Endian::BIG; }
+constexpr inline bool IsLittleEndian() { return Endian::NATIVE ==
Endian::LITTLE; }
+constexpr inline bool IsBigEndian() { return Endian::NATIVE == Endian::BIG; }
-bool GetFixed8(rocksdb::Slice *input, uint8_t *value);
-bool GetFixed16(rocksdb::Slice *input, uint16_t *value);
-bool GetFixed32(rocksdb::Slice *input, uint32_t *value);
-bool GetFixed64(rocksdb::Slice *input, uint64_t *value);
-bool GetDouble(rocksdb::Slice *input, double *value);
-void PutFixed8(std::string *dst, uint8_t value);
-void PutFixed16(std::string *dst, uint16_t value);
-void PutFixed32(std::string *dst, uint32_t value);
-void PutFixed64(std::string *dst, uint64_t value);
-void PutDouble(std::string *dst, double value);
+constexpr inline uint8_t BitSwap(uint8_t x) { return x; }
+
+constexpr inline uint16_t BitSwap(uint16_t x) { return __builtin_bswap16(x); }
+
+constexpr inline uint32_t BitSwap(uint32_t x) { return __builtin_bswap32(x); }
+
+constexpr inline uint64_t BitSwap(uint64_t x) { return __builtin_bswap64(x); }
+
+template <typename T>
+constexpr void EncodeFixed(char *buf, T value) {
+ if constexpr (IsLittleEndian()) {
+ value = BitSwap(value);
+ }
+ __builtin_memcpy(buf, &value, sizeof(value));
+}
+
+inline void EncodeFixed8(char *buf, uint8_t value) { EncodeFixed(buf, value); }
+inline void EncodeFixed16(char *buf, uint16_t value) { EncodeFixed(buf,
value); }
+inline void EncodeFixed32(char *buf, uint32_t value) { EncodeFixed(buf,
value); }
+inline void EncodeFixed64(char *buf, uint64_t value) { EncodeFixed(buf,
value); }
+
+template <typename T>
+void PutFixed(std::string *dst, T value) {
+ char buf[sizeof(value)];
+ EncodeFixed(buf, value);
+ dst->append(buf, sizeof(buf));
+}
+
+inline void PutFixed8(std::string *dst, uint8_t value) { PutFixed(dst, value);
}
+inline void PutFixed16(std::string *dst, uint16_t value) { PutFixed(dst,
value); }
+inline void PutFixed32(std::string *dst, uint32_t value) { PutFixed(dst,
value); }
+inline void PutFixed64(std::string *dst, uint64_t value) { PutFixed(dst,
value); }
-void EncodeFixed8(char *buf, uint8_t value);
-void EncodeFixed16(char *buf, uint16_t value);
-void EncodeFixed32(char *buf, uint32_t value);
-void EncodeFixed64(char *buf, uint64_t value);
-uint16_t DecodeFixed16(const char *ptr);
-uint32_t DecodeFixed32(const char *ptr);
-uint64_t DecodeFixed64(const char *ptr);
+template <typename T>
+constexpr T DecodeFixed(const char *ptr) {
+ T value = 0;
+
+ __builtin_memcpy(&value, ptr, sizeof(value));
+
+ return IsLittleEndian() ? BitSwap(value) : value;
+}
+
+inline uint8_t DecodeFixed8(const char *ptr) { return
DecodeFixed<uint8_t>(ptr); }
+inline uint16_t DecodeFixed16(const char *ptr) { return
DecodeFixed<uint16_t>(ptr); }
+inline uint32_t DecodeFixed32(const char *ptr) { return
DecodeFixed<uint32_t>(ptr); }
+inline uint64_t DecodeFixed64(const char *ptr) { return
DecodeFixed<uint64_t>(ptr); }
+
+template <typename T>
+bool GetFixed(rocksdb::Slice *input, T *value) {
+ if (input->size() < sizeof(T)) return false;
+ *value = DecodeFixed<T>(input->data());
+ input->remove_prefix(sizeof(T));
+ return true;
+}
+
+inline bool GetFixed8(rocksdb::Slice *input, uint8_t *value) { return
GetFixed(input, value); }
+inline bool GetFixed16(rocksdb::Slice *input, uint16_t *value) { return
GetFixed(input, value); }
+inline bool GetFixed32(rocksdb::Slice *input, uint32_t *value) { return
GetFixed(input, value); }
+inline bool GetFixed64(rocksdb::Slice *input, uint64_t *value) { return
GetFixed(input, value); }
+
+void EncodeDouble(char *buf, double value);
+void PutDouble(std::string *dst, double value);
double DecodeDouble(const char *ptr);
+bool GetDouble(rocksdb::Slice *input, double *value);
char *EncodeVarint32(char *dst, uint32_t v);
void PutVarint32(std::string *dst, uint32_t v);
diff --git a/src/common/event_util.h b/src/common/event_util.h
index 8df67be3..fccdfd53 100644
--- a/src/common/event_util.h
+++ b/src/common/event_util.h
@@ -28,14 +28,7 @@
#include "event2/bufferevent.h"
#include "event2/event.h"
#include "event2/listener.h"
-
-template <typename F, F *f>
-struct StaticFunction {
- template <typename... Ts>
- auto operator()(Ts &&...args) const ->
decltype(f(std::forward<Ts>(args)...)) { // NOLINT
- return f(std::forward<Ts>(args)...);
// NOLINT
- }
-};
+#include "type_util.h"
using StaticFree = StaticFunction<decltype(std::free), std::free>;
diff --git a/src/common/status.h b/src/common/status.h
index 55cfcef1..37eae9d8 100644
--- a/src/common/status.h
+++ b/src/common/status.h
@@ -30,6 +30,8 @@
#include <type_traits>
#include <utility>
+#include "type_util.h"
+
class [[nodiscard]] Status {
public:
enum Code : unsigned char {
@@ -133,14 +135,6 @@ class [[nodiscard]] Status {
friend struct StatusOr;
};
-namespace type_details {
-template <typename... Ts>
-using FirstElement = typename std::tuple_element_t<0, std::tuple<Ts...>>;
-
-template <typename T>
-using RemoveCVRef = typename std::remove_cv_t<typename
std::remove_reference_t<T>>;
-} // namespace type_details
-
template <typename, typename = void>
struct StringInStatusOr : private std::string {
using BaseType = std::string;
@@ -222,14 +216,12 @@ struct [[nodiscard]] StatusOr {
new (&error) ErrorType(std::move(msg));
}
- template <
- typename... Ts,
- typename std::enable_if<(sizeof...(Ts) > 0 &&
- !std::is_same_v<Status,
type_details::RemoveCVRef<type_details::FirstElement<Ts...>>> &&
- !std::is_same_v<Code,
type_details::RemoveCVRef<type_details::FirstElement<Ts...>>> &&
- !std::is_same_v<StatusOr,
type_details::RemoveCVRef<type_details::FirstElement<Ts...>>>),
- int>::type = 0> // NOLINT
- StatusOr(Ts&&... args) : code_(Status::cOK) { // NOLINT
+ template <typename... Ts,
+ typename std::enable_if<(sizeof...(Ts) > 0 &&
!std::is_same_v<Status, RemoveCVRef<FirstElement<Ts...>>> &&
+ !std::is_same_v<Code,
RemoveCVRef<FirstElement<Ts...>>> &&
+ !std::is_same_v<StatusOr,
RemoveCVRef<FirstElement<Ts...>>>),
+ int>::type = 0> // NOLINT
+ StatusOr(Ts&&... args) : code_(Status::cOK) { // NOLINT
new (&value) ValueType(std::forward<Ts>(args)...);
}
diff --git a/src/common/type_util.h b/src/common/type_util.h
index 8e90b721..d55019f7 100644
--- a/src/common/type_util.h
+++ b/src/common/type_util.h
@@ -20,6 +20,22 @@
#pragma once
+#include <utility>
+
+template <typename F, F *f>
+struct StaticFunction {
+ template <typename... Ts>
+ auto operator()(Ts &&...args) const ->
decltype(f(std::forward<Ts>(args)...)) { // NOLINT
+ return f(std::forward<Ts>(args)...);
// NOLINT
+ }
+};
+
+template <typename... Ts>
+using FirstElement = typename std::tuple_element_t<0, std::tuple<Ts...>>;
+
+template <typename T>
+using RemoveCVRef = typename std::remove_cv_t<typename
std::remove_reference_t<T>>;
+
// dependent false for static_assert with constexpr if, see CWG2518/P2593R1
template <typename T>
constexpr bool AlwaysFalse = false;