From 5a59ce41495ecb887276df95ce05e0a357ee9d62 Mon Sep 17 00:00:00 2001 From: Fenggang Wu Date: Mon, 16 Jul 2018 23:34:47 -0700 Subject: [PATCH] Coding.h: Added Fixed16 support (#4142) Summary: Added Get Put Encode Decode support for Fixed16 (uint16_t). Unit test added in `coding_test.cc` Pull Request resolved: https://github.com/facebook/rocksdb/pull/4142 Differential Revision: D8873516 Pulled By: fgwu fbshipit-source-id: 331913e0a9a8fe9c95606a08e856e953477d64d3 --- util/coding.h | 44 ++++++++++++++++++++++++++++++++++++++++++++ util/coding_test.cc | 13 +++++++++++++ 2 files changed, 57 insertions(+) diff --git a/util/coding.h b/util/coding.h index 5cf009472..803e4349d 100644 --- a/util/coding.h +++ b/util/coding.h @@ -32,6 +32,7 @@ namespace rocksdb { const unsigned int kMaxVarint64Length = 10; // Standard Put... routines append to a string +extern void PutFixed16(std::string* dst, uint16_t value); extern void PutFixed32(std::string* dst, uint32_t value); extern void PutFixed64(std::string* dst, uint64_t value); extern void PutVarint32(std::string* dst, uint32_t value); @@ -54,6 +55,7 @@ extern void PutLengthPrefixedSliceParts(std::string* dst, // and advance the slice past the parsed value. extern bool GetFixed64(Slice* input, uint64_t* value); extern bool GetFixed32(Slice* input, uint32_t* value); +extern bool GetFixed16(Slice* input, uint16_t* value); extern bool GetVarint32(Slice* input, uint32_t* value); extern bool GetVarint64(Slice* input, uint64_t* value); extern bool GetLengthPrefixedSlice(Slice* input, Slice* result); @@ -74,6 +76,7 @@ extern int VarintLength(uint64_t v); // Lower-level versions of Put... that write directly into a character buffer // REQUIRES: dst has enough space for the value being written +extern void EncodeFixed16(char* dst, uint16_t value); extern void EncodeFixed32(char* dst, uint32_t value); extern void EncodeFixed64(char* dst, uint64_t value); @@ -86,6 +89,18 @@ extern char* EncodeVarint64(char* dst, uint64_t value); // Lower-level versions of Get... that read directly from a character buffer // without any bounds checking. +inline uint16_t DecodeFixed16(const char* ptr) { + if (port::kLittleEndian) { + // Load the raw bytes + uint16_t result; + memcpy(&result, ptr, sizeof(result)); // gcc optimizes this to a plain load + return result; + } else { + return ((static_cast(static_cast(ptr[0]))) | + (static_cast(static_cast(ptr[1])) << 8)); + } +} + inline uint32_t DecodeFixed32(const char* ptr) { if (port::kLittleEndian) { // Load the raw bytes @@ -131,6 +146,15 @@ inline const char* GetVarint32Ptr(const char* p, } // -- Implementation of the functions declared above +inline void EncodeFixed16(char* buf, uint16_t value) { + if (port::kLittleEndian) { + memcpy(buf, &value, sizeof(value)); + } else { + buf[0] = value & 0xff; + buf[1] = (value >> 8) & 0xff; + } +} + inline void EncodeFixed32(char* buf, uint32_t value) { if (port::kLittleEndian) { memcpy(buf, &value, sizeof(value)); @@ -158,6 +182,17 @@ inline void EncodeFixed64(char* buf, uint64_t value) { } // Pull the last 8 bits and cast it to a character +inline void PutFixed16(std::string* dst, uint16_t value) { + if (port::kLittleEndian) { + dst->append(const_cast(reinterpret_cast(&value)), + sizeof(value)); + } else { + char buf[sizeof(value)]; + EncodeFixed16(buf, value); + dst->append(buf, sizeof(buf)); + } +} + inline void PutFixed32(std::string* dst, uint32_t value) { if (port::kLittleEndian) { dst->append(const_cast(reinterpret_cast(&value)), @@ -286,6 +321,15 @@ inline bool GetFixed32(Slice* input, uint32_t* value) { return true; } +inline bool GetFixed16(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; +} + inline bool GetVarint32(Slice* input, uint32_t* value) { const char* p = input->data(); const char* limit = p + input->size(); diff --git a/util/coding_test.cc b/util/coding_test.cc index 49fb73d4a..f7b1671d1 100644 --- a/util/coding_test.cc +++ b/util/coding_test.cc @@ -14,6 +14,19 @@ namespace rocksdb { class Coding { }; +TEST(Coding, Fixed16) { + std::string s; + for (uint16_t v = 0; v < 0xFFFF; v++) { + PutFixed16(&s, v); + } + + const char* p = s.data(); + for (uint16_t v = 0; v < 0xFFFF; v++) { + uint16_t actual = DecodeFixed16(p); + ASSERT_EQ(v, actual); + p += sizeof(uint16_t); + } +} TEST(Coding, Fixed32) { std::string s;