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.
13 #include "rocksdb/comparator.h"
14 #include "rocksdb/slice.h"
15 #include "port/port.h"
16 #include "util/logging.h"
21 class BytewiseComparatorImpl
: public Comparator
{
23 BytewiseComparatorImpl() { }
25 virtual const char* Name() const override
{
26 return "leveldb.BytewiseComparator";
29 virtual int Compare(const Slice
& a
, const Slice
& b
) const override
{
33 virtual bool Equal(const Slice
& a
, const Slice
& b
) const override
{
37 virtual void FindShortestSeparator(std::string
* start
,
38 const Slice
& limit
) const override
{
39 // Find length of common prefix
40 size_t min_length
= std::min(start
->size(), limit
.size());
41 size_t diff_index
= 0;
42 while ((diff_index
< min_length
) &&
43 ((*start
)[diff_index
] == limit
[diff_index
])) {
47 if (diff_index
>= min_length
) {
48 // Do not shorten if one string is a prefix of the other
50 uint8_t start_byte
= static_cast<uint8_t>((*start
)[diff_index
]);
51 uint8_t limit_byte
= static_cast<uint8_t>(limit
[diff_index
]);
52 if (start_byte
>= limit_byte
) {
53 // Cannot shorten since limit is smaller than start or start is
54 // already the shortest possible.
57 assert(start_byte
< limit_byte
);
59 if (diff_index
< limit
.size() - 1 || start_byte
+ 1 < limit_byte
) {
60 (*start
)[diff_index
]++;
61 start
->resize(diff_index
+ 1);
67 // Incrementing the current byte will make start bigger than limit, we
68 // will skip this byte, and find the first non 0xFF byte in start and
72 while (diff_index
< start
->size()) {
73 // Keep moving until we find the first non 0xFF byte to
75 if (static_cast<uint8_t>((*start
)[diff_index
]) <
76 static_cast<uint8_t>(0xff)) {
77 (*start
)[diff_index
]++;
78 start
->resize(diff_index
+ 1);
84 assert(Compare(*start
, limit
) < 0);
88 virtual void FindShortSuccessor(std::string
* key
) const override
{
89 // Find first character that can be incremented
90 size_t n
= key
->size();
91 for (size_t i
= 0; i
< n
; i
++) {
92 const uint8_t byte
= (*key
)[i
];
93 if (byte
!= static_cast<uint8_t>(0xff)) {
99 // *key is a run of 0xffs. Leave it alone.
102 virtual bool IsSameLengthImmediateSuccessor(const Slice
& s
,
103 const Slice
& t
) const override
{
104 if (s
.size() != t
.size() || s
.size() == 0) {
107 size_t diff_ind
= s
.difference_offset(t
);
109 if (diff_ind
>= s
.size()) return false;
110 uint8_t byte_s
= static_cast<uint8_t>(s
[diff_ind
]);
111 uint8_t byte_t
= static_cast<uint8_t>(t
[diff_ind
]);
112 // first different byte must be consecutive, and remaining bytes must be
113 // 0xff for s and 0x00 for t
114 if (byte_s
!= uint8_t{0xff} && byte_s
+ 1 == byte_t
) {
115 for (size_t i
= diff_ind
+ 1; i
< s
.size(); ++i
) {
116 byte_s
= static_cast<uint8_t>(s
[i
]);
117 byte_t
= static_cast<uint8_t>(t
[i
]);
118 if (byte_s
!= uint8_t{0xff} || byte_t
!= uint8_t{0x00}) {
128 virtual bool CanKeysWithDifferentByteContentsBeEqual() const override
{
133 class ReverseBytewiseComparatorImpl
: public BytewiseComparatorImpl
{
135 ReverseBytewiseComparatorImpl() { }
137 virtual const char* Name() const override
{
138 return "rocksdb.ReverseBytewiseComparator";
141 virtual 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 virtual bool CanKeysWithDifferentByteContentsBeEqual() const override
{
202 const Comparator
* BytewiseComparator() {
203 static BytewiseComparatorImpl bytewise
;
207 const Comparator
* ReverseBytewiseComparator() {
208 static ReverseBytewiseComparatorImpl rbytewise
;
212 } // namespace rocksdb