// Copyright (c) 2011 The LevelDB Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. See the AUTHORS file for names of contributors. #include <algorithm> #include <cstdint> #include <string> #include "leveldb/comparator.h" #include "leveldb/slice.h" #include "util/logging.h" #include "util/no_destructor.h" namespace leveldb { Comparator::~Comparator() {} namespace { class BytewiseComparatorImpl : public Comparator { public: BytewiseComparatorImpl() {} virtual const char* Name() const { return "leveldb.BytewiseComparator"; } virtual int Compare(const Slice& a, const Slice& b) const { return a.compare(b); } virtual void FindShortestSeparator(std::string* start, const Slice& limit) const { // Find length of common prefix size_t min_length = std::min(start->size(), limit.size()); size_t diff_index = 0; while ((diff_index < min_length) && ((*start)[diff_index] == limit[diff_index])) { diff_index++; } if (diff_index >= min_length) { // Do not shorten if one string is a prefix of the other } else { uint8_t diff_byte = static_cast<uint8_t>((*start)[diff_index]); if (diff_byte < static_cast<uint8_t>(0xff) && diff_byte + 1 < static_cast<uint8_t>(limit[diff_index])) { (*start)[diff_index]++; start->resize(diff_index + 1); assert(Compare(*start, limit) < 0); } } } virtual void FindShortSuccessor(std::string* key) const { // Find first character that can be incremented size_t n = key->size(); for (size_t i = 0; i < n; i++) { const uint8_t byte = (*key)[i]; if (byte != static_cast<uint8_t>(0xff)) { (*key)[i] = byte + 1; key->resize(i + 1); return; } } // *key is a run of 0xffs. Leave it alone. } }; } // namespace const Comparator* BytewiseComparator() { static NoDestructor<BytewiseComparatorImpl> singleton; return singleton.get(); } } // namespace leveldb