mirror of
https://github.com/dragonflydb/dragonfly.git
synced 2024-12-14 11:58:02 +00:00
144 lines
3.1 KiB
C++
144 lines
3.1 KiB
C++
// Copyright 2022, Roman Gershman. All rights reserved.
|
|
// See LICENSE for licensing terms.
|
|
//
|
|
|
|
#include "core/small_string.h"
|
|
|
|
#include <xxhash.h>
|
|
|
|
#include <memory>
|
|
|
|
#include "base/logging.h"
|
|
#include "core/segment_allocator.h"
|
|
|
|
namespace dfly {
|
|
using namespace std;
|
|
|
|
namespace {
|
|
|
|
class XXH3_Deleter {
|
|
public:
|
|
void operator()(XXH3_state_t* ptr) const {
|
|
XXH3_freeState(ptr);
|
|
}
|
|
};
|
|
|
|
struct TL {
|
|
unique_ptr<XXH3_state_t, XXH3_Deleter> xxh_state;
|
|
unique_ptr<SegmentAllocator> seg_alloc;
|
|
};
|
|
|
|
thread_local TL tl;
|
|
|
|
constexpr XXH64_hash_t kHashSeed = 24061983; // same as in compact_object.cc
|
|
|
|
} // namespace
|
|
|
|
void SmallString::InitThreadLocal() {
|
|
SegmentAllocator* ns = new SegmentAllocator(mi_heap_get_backing());
|
|
|
|
tl.seg_alloc.reset(ns);
|
|
tl.xxh_state.reset(XXH3_createState());
|
|
XXH3_64bits_reset_withSeed(tl.xxh_state.get(), kHashSeed);
|
|
}
|
|
|
|
static_assert(sizeof(SmallString) == 16);
|
|
|
|
// we should use only for sizes greater than kPrefLen
|
|
void SmallString::Assign(std::string_view s) {
|
|
DCHECK_GT(s.size(), kPrefLen);
|
|
|
|
uint8_t* realptr = nullptr;
|
|
|
|
if (size_ == 0) {
|
|
auto [sp, rp] = tl.seg_alloc->Allocate(s.size() - kPrefLen);
|
|
small_ptr_ = sp;
|
|
realptr = rp;
|
|
|
|
size_ = s.size();
|
|
} else if (size_ == s.size()) {
|
|
realptr = tl.seg_alloc->Translate(small_ptr_);
|
|
} else {
|
|
LOG(FATAL) << "TBD: Bad usage";
|
|
}
|
|
|
|
memcpy(prefix_, s.data(), kPrefLen);
|
|
memcpy(realptr, s.data() + kPrefLen, s.size() - kPrefLen);
|
|
}
|
|
|
|
void SmallString::Free() {
|
|
if (size_ <= kPrefLen)
|
|
return;
|
|
|
|
tl.seg_alloc->Free(small_ptr_);
|
|
size_ = 0;
|
|
}
|
|
|
|
bool SmallString::Equal(std::string_view o) const {
|
|
if (size_ != o.size())
|
|
return false;
|
|
|
|
if (size_ == 0)
|
|
return true;
|
|
|
|
DCHECK_GT(size_, kPrefLen);
|
|
|
|
if (memcmp(prefix_, o.data(), kPrefLen) != 0)
|
|
return false;
|
|
|
|
uint8_t* realp = tl.seg_alloc->Translate(small_ptr_);
|
|
|
|
return memcmp(realp, o.data() + kPrefLen, size_ - kPrefLen) == 0;
|
|
}
|
|
|
|
bool SmallString::Equal(const SmallString& os) const {
|
|
if (size_ != os.size_)
|
|
return false;
|
|
|
|
string_view me[2], other[2];
|
|
unsigned n1 = GetV(me);
|
|
unsigned n2 = os.GetV(other);
|
|
|
|
if (n1 != n2)
|
|
return false;
|
|
|
|
return me[0] == other[0] && me[1] == other[1];
|
|
}
|
|
|
|
uint64_t SmallString::HashCode() const {
|
|
DCHECK_GT(size_, kPrefLen);
|
|
|
|
string_view slice[2];
|
|
|
|
GetV(slice);
|
|
XXH3_state_t* state = tl.xxh_state.get();
|
|
XXH3_64bits_reset_withSeed(state, kHashSeed);
|
|
XXH3_64bits_update(state, slice[0].data(), slice[0].size());
|
|
XXH3_64bits_update(state, slice[1].data(), slice[1].size());
|
|
|
|
return XXH3_64bits_digest(state);
|
|
}
|
|
|
|
void SmallString::Get(std::string* dest) const {
|
|
dest->resize(size_);
|
|
if (size_) {
|
|
DCHECK_GT(size_, kPrefLen);
|
|
memcpy(dest->data(), prefix_, kPrefLen);
|
|
uint8_t* ptr = tl.seg_alloc->Translate(small_ptr_);
|
|
memcpy(dest->data() + kPrefLen, ptr, size_ - kPrefLen);
|
|
}
|
|
}
|
|
|
|
unsigned SmallString::GetV(string_view dest[2]) const {
|
|
if (size_ <= kPrefLen) {
|
|
dest[0] = string_view{prefix_, size_};
|
|
return 1;
|
|
}
|
|
|
|
dest[0] = string_view{prefix_, kPrefLen};
|
|
uint8_t* ptr = tl.seg_alloc->Translate(small_ptr_);
|
|
dest[1] = string_view{reinterpret_cast<char*>(ptr), size_ - kPrefLen};
|
|
return 2;
|
|
}
|
|
|
|
} // namespace dfly
|