#pragma once
#include <algorithm>
#include <cassert>
#include <cstdint>
#include <cstring>
#include "db/dbformat.h"
#include "port/port.h"
#include "rocksdb/slice.h"
#include "util/coding.h"
#include "util/math.h"
namespace ROCKSDB_NAMESPACE {
struct DecodeEntry {
inline const char* operator()(const char* p, const char* limit,
uint32_t* shared, uint32_t* non_shared,
uint32_t* value_length,
uint32_t* value_offset) {
assert(limit - p >= 3);
*shared = reinterpret_cast<const unsigned char*>(p)[0];
*non_shared = reinterpret_cast<const unsigned char*>(p)[1];
*value_length = reinterpret_cast<const unsigned char*>(p)[2];
if ((*shared | *non_shared | *value_length) < 128) {
p += 3;
} else {
if ((p = GetVarint32Ptr(p, limit, shared)) == nullptr) {
return nullptr;
}
if ((p = GetVarint32Ptr(p, limit, non_shared)) == nullptr) {
return nullptr;
}
if ((p = GetVarint32Ptr(p, limit, value_length)) == nullptr) {
return nullptr;
}
}
if (value_offset) {
if ((p = GetVarint32Ptr(p, limit, value_offset)) == nullptr) {
return nullptr;
}
}
return p;
}
};
struct DecodeKey {
inline const char* operator()(const char* p, const char* limit,
uint32_t* shared, uint32_t* non_shared,
uint32_t* value_offset) {
uint32_t value_length;
return DecodeEntry()(p, limit, shared, non_shared, &value_length,
value_offset);
}
};
struct DecodeKeyV4 {
inline const char* operator()(const char* p, const char* limit,
uint32_t* shared, uint32_t* non_shared,
uint32_t* value_offset) {
if (limit - p < 3) {
return nullptr;
}
*shared = reinterpret_cast<const unsigned char*>(p)[0];
*non_shared = reinterpret_cast<const unsigned char*>(p)[1];
if ((*shared | *non_shared) < 128) {
p += 2;
} else {
if ((p = GetVarint32Ptr(p, limit, shared)) == nullptr) {
return nullptr;
}
if ((p = GetVarint32Ptr(p, limit, non_shared)) == nullptr) {
return nullptr;
}
}
if (value_offset) {
if ((p = GetVarint32Ptr(p, limit, value_offset)) == nullptr) {
return nullptr;
}
}
return p;
}
};
struct DecodeEntryV4 {
inline const char* operator()(const char* p, const char* limit,
uint32_t* shared, uint32_t* non_shared,
uint32_t* value_length,
uint32_t* value_offset) {
assert(value_length);
*value_length = 0;
return DecodeKeyV4()(p, limit, shared, non_shared, value_offset);
}
};
inline uint64_t ReadBe64FromKey(Slice s, bool is_user_key, size_t offset) {
if (!is_user_key) {
assert(s.size() >= kNumInternalBytes);
s = Slice(s.data(), s.size() - kNumInternalBytes);
}
offset = std::min(offset, s.size());
size_t remaining = s.size() - offset;
if (remaining >= 8) {
uint64_t val;
memcpy(&val, s.data() + offset, sizeof(val));
if (port::kLittleEndian) {
return EndianSwapValue(val);
}
return val;
}
uint64_t val = 0;
for (size_t i = 0; i < remaining; i++) {
val = (val << 8) | static_cast<uint8_t>(s.data()[offset + i]);
}
if (remaining > 0) {
val <<= (8 - remaining) * 8; }
return val;
}
}