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;

Reply via email to