1
0
Fork 0

improve binary search a bit, improve string comparisons (#10069)

This commit is contained in:
Jan 2019-09-24 18:20:34 +02:00 committed by GitHub
parent a2e0fc643b
commit ca3c742652
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 16 additions and 27 deletions

View File

@ -114,7 +114,7 @@ int64_t Slice::getSmallIntUnchecked() const noexcept {
// translates an integer key into a string, without checks // translates an integer key into a string, without checks
Slice Slice::translateUnchecked() const { Slice Slice::translateUnchecked() const {
uint8_t const* result = Options::Defaults.attributeTranslator->translate(getUIntUnchecked()); uint8_t const* result = Options::Defaults.attributeTranslator->translate(getUIntUnchecked());
if (result != nullptr) { if (VELOCYPACK_LIKELY(result != nullptr)) {
return Slice(result); return Slice(result);
} }
return Slice(); return Slice();
@ -384,9 +384,7 @@ int Slice::compareString(StringRef const& value) const {
int res = memcmp(k, value.data(), compareLength); int res = memcmp(k, value.data(), compareLength);
if (res == 0) { if (res == 0) {
if (keyLength != length) { return static_cast<int>(keyLength - length);
return (keyLength > length) ? 1 : -1;
}
} }
return res; return res;
} }
@ -400,9 +398,7 @@ int Slice::compareStringUnchecked(StringRef const& value) const noexcept {
int res = memcmp(k, value.data(), compareLength); int res = memcmp(k, value.data(), compareLength);
if (res == 0) { if (res == 0) {
if (keyLength != length) { return static_cast<int>(keyLength - length);
return (keyLength > length) ? 1 : -1;
}
} }
return res; return res;
} }
@ -598,49 +594,42 @@ Slice Slice::searchObjectKeyBinary(StringRef const& attribute,
bool const useTranslator = (Options::Defaults.attributeTranslator != nullptr); bool const useTranslator = (Options::Defaults.attributeTranslator != nullptr);
VELOCYPACK_ASSERT(n > 0); VELOCYPACK_ASSERT(n > 0);
ValueLength l = 0; int64_t l = 0;
ValueLength r = n - 1; int64_t r = static_cast<int64_t>(n) - 1;
ValueLength index = r / 2; int64_t index = r / 2;
while (true) { do {
ValueLength offset = ieBase + index * offsetSize; ValueLength offset = ieBase + index * offsetSize;
Slice key(_start + readIntegerFixed<ValueLength, offsetSize>(_start + offset)); Slice key(_start + readIntegerFixed<ValueLength, offsetSize>(_start + offset));
int res; int res;
if (key.isString()) { if (key.isString()) {
res = key.compareStringUnchecked(attribute.data(), attribute.size()); res = key.compareStringUnchecked(attribute.data(), attribute.size());
} else if (key.isSmallInt() || key.isUInt()) { } else {
VELOCYPACK_ASSERT(key.isSmallInt() || key.isUInt());
// translate key // translate key
if (VELOCYPACK_UNLIKELY(!useTranslator)) { if (VELOCYPACK_UNLIKELY(!useTranslator)) {
// no attribute translator // no attribute translator
throw Exception(Exception::NeedAttributeTranslator); throw Exception(Exception::NeedAttributeTranslator);
} }
res = key.translateUnchecked().compareString(attribute); res = key.translateUnchecked().compareString(attribute);
} else {
// invalid key
return Slice();
}
if (res == 0) {
// found. now return a Slice pointing at the value
return Slice(key.start() + key.byteSize());
} }
if (res > 0) { if (res > 0) {
if (index == 0) {
return Slice();
}
r = index - 1; r = index - 1;
} else if (res == 0) {
// found. now return a Slice pointing at the value
return Slice(key.start() + key.byteSize());
} else { } else {
l = index + 1; l = index + 1;
} }
if (r < l) {
return Slice();
}
// determine new midpoint // determine new midpoint
index = l + ((r - l) / 2); index = l + ((r - l) / 2);
} } while (r >= l);
// not found
return Slice();
} }
// template instanciations for searchObjectKeyBinary // template instanciations for searchObjectKeyBinary