1 // Copyright (c) 2011-present, Facebook, Inc. All rights reserved.
2 // This source code is licensed under both the GPLv2 (found in the
3 // COPYING file in the root directory) and Apache 2.0 License
4 // (found in the LICENSE.Apache file in the root directory).
6 // Copyright (c) 2011 The LevelDB Authors. All rights reserved.
7 // Use of this source code is governed by a BSD-style license that can be
8 // found in the LICENSE file. See the AUTHORS file for names of contributors.
10 #include "rocksdb/comparator.h"
14 #include "logging/logging.h"
15 #include "port/port.h"
16 #include "rocksdb/slice.h"
18 namespace ROCKSDB_NAMESPACE
{
21 class BytewiseComparatorImpl
: public Comparator
{
23 BytewiseComparatorImpl() { }
25 const char* Name() const override
{ return "leveldb.BytewiseComparator"; }
27 int Compare(const Slice
& a
, const Slice
& b
) const override
{
31 bool Equal(const Slice
& a
, const Slice
& b
) const override
{ return a
== b
; }
33 void FindShortestSeparator(std::string
* start
,
34 const Slice
& limit
) const override
{
35 // Find length of common prefix
36 size_t min_length
= std::min(start
->size(), limit
.size());
37 size_t diff_index
= 0;
38 while ((diff_index
< min_length
) &&
39 ((*start
)[diff_index
] == limit
[diff_index
])) {
43 if (diff_index
>= min_length
) {
44 // Do not shorten if one string is a prefix of the other
46 uint8_t start_byte
= static_cast<uint8_t>((*start
)[diff_index
]);
47 uint8_t limit_byte
= static_cast<uint8_t>(limit
[diff_index
]);
48 if (start_byte
>= limit_byte
) {
49 // Cannot shorten since limit is smaller than start or start is
50 // already the shortest possible.
53 assert(start_byte
< limit_byte
);
55 if (diff_index
< limit
.size() - 1 || start_byte
+ 1 < limit_byte
) {
56 (*start
)[diff_index
]++;
57 start
->resize(diff_index
+ 1);
63 // Incrementing the current byte will make start bigger than limit, we
64 // will skip this byte, and find the first non 0xFF byte in start and
68 while (diff_index
< start
->size()) {
69 // Keep moving until we find the first non 0xFF byte to
71 if (static_cast<uint8_t>((*start
)[diff_index
]) <
72 static_cast<uint8_t>(0xff)) {
73 (*start
)[diff_index
]++;
74 start
->resize(diff_index
+ 1);
80 assert(Compare(*start
, limit
) < 0);
84 void FindShortSuccessor(std::string
* key
) const override
{
85 // Find first character that can be incremented
86 size_t n
= key
->size();
87 for (size_t i
= 0; i
< n
; i
++) {
88 const uint8_t byte
= (*key
)[i
];
89 if (byte
!= static_cast<uint8_t>(0xff)) {
95 // *key is a run of 0xffs. Leave it alone.
98 bool IsSameLengthImmediateSuccessor(const Slice
& s
,
99 const Slice
& t
) const override
{
100 if (s
.size() != t
.size() || s
.size() == 0) {
103 size_t diff_ind
= s
.difference_offset(t
);
105 if (diff_ind
>= s
.size()) return false;
106 uint8_t byte_s
= static_cast<uint8_t>(s
[diff_ind
]);
107 uint8_t byte_t
= static_cast<uint8_t>(t
[diff_ind
]);
108 // first different byte must be consecutive, and remaining bytes must be
109 // 0xff for s and 0x00 for t
110 if (byte_s
!= uint8_t{0xff} && byte_s
+ 1 == byte_t
) {
111 for (size_t i
= diff_ind
+ 1; i
< s
.size(); ++i
) {
112 byte_s
= static_cast<uint8_t>(s
[i
]);
113 byte_t
= static_cast<uint8_t>(t
[i
]);
114 if (byte_s
!= uint8_t{0xff} || byte_t
!= uint8_t{0x00}) {
124 bool CanKeysWithDifferentByteContentsBeEqual() const override
{
128 int CompareWithoutTimestamp(const Slice
& a
, const Slice
& b
) const override
{
133 class ReverseBytewiseComparatorImpl
: public BytewiseComparatorImpl
{
135 ReverseBytewiseComparatorImpl() { }
137 const char* Name() const override
{
138 return "rocksdb.ReverseBytewiseComparator";
141 int Compare(const Slice
& a
, const Slice
& b
) const override
{
142 return -a
.compare(b
);
145 void FindShortestSeparator(std::string
* start
,
146 const Slice
& limit
) const override
{
147 // Find length of common prefix
148 size_t min_length
= std::min(start
->size(), limit
.size());
149 size_t diff_index
= 0;
150 while ((diff_index
< min_length
) &&
151 ((*start
)[diff_index
] == limit
[diff_index
])) {
155 assert(diff_index
<= min_length
);
156 if (diff_index
== min_length
) {
157 // Do not shorten if one string is a prefix of the other
159 // We could handle cases like:
163 // in a similar way as BytewiseComparator::FindShortestSeparator().
164 // We keep it simple by not implementing it. We can come back to it
165 // later when needed.
167 uint8_t start_byte
= static_cast<uint8_t>((*start
)[diff_index
]);
168 uint8_t limit_byte
= static_cast<uint8_t>(limit
[diff_index
]);
169 if (start_byte
> limit_byte
&& diff_index
< start
->size() - 1) {
179 // In this case "AA2" will be good.
181 std::string old_start
= *start
;
183 start
->resize(diff_index
+ 1);
185 assert(old_start
>= *start
);
187 assert(Slice(*start
).compare(limit
) > 0);
192 void FindShortSuccessor(std::string
* /*key*/) const override
{
193 // Don't do anything for simplicity.
196 bool CanKeysWithDifferentByteContentsBeEqual() const override
{
200 int CompareWithoutTimestamp(const Slice
& a
, const Slice
& b
) const override
{
201 return -a
.compare(b
);
206 const Comparator
* BytewiseComparator() {
207 static BytewiseComparatorImpl bytewise
;
211 const Comparator
* ReverseBytewiseComparator() {
212 static ReverseBytewiseComparatorImpl rbytewise
;
216 } // namespace ROCKSDB_NAMESPACE