cachelib/common/BytesEqual.h (52 lines of code) (raw):
/*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#pragma once
#include <folly/CPortability.h>
#include <folly/Likely.h>
#include <cassert>
#include <cstddef>
#include <cstdint>
#include <cstring>
#include <type_traits>
namespace facebook {
namespace cachelib {
// Dereferencing the pointer through uintX_t* will violate strict aliasing
// rules. To get around, @ngbronson suggested this hack which cheats by
// tricking the compiler. This should be generate the same machine
// instructions as (*(uint64_t*)a) == (*(uint64_t*)b)
template <typename T>
inline bool eq(const char* a, const char* b) {
static_assert(std::is_integral<T>::value, "Non integral type");
T lhs;
T rhs;
memcpy(&lhs, a, sizeof(T));
memcpy(&rhs, b, sizeof(T));
return lhs == rhs;
}
// Compare the two byte arrays up to the len and return if they are equal or
// not. Defaults to using memcmp for more than 1024 byte comparisons. Use this
// only when you are comparing less than 64 byte buffers for getting a win.
//
// @param a first buffer
// @param b second buffer
// @param len length of the buffers
// @return true if the byte arrays are the same. False if not.
// bool bytesEqual(const void* a_, const void* b_, size_t len);
FOLLY_ALWAYS_INLINE bool bytesEqual(const void* a_,
const void* b_,
size_t len) {
const char* a = (const char*)a_;
const char* b = (const char*)b_;
if (UNLIKELY(len >= 1024)) {
return memcmp(a_, b_, len) == 0;
}
while (len >= 8 && eq<uint64_t>(a, b)) {
a += 8;
b += 8;
len -= 8;
}
if (len >= 8) {
return false;
}
if (len >= 4 && eq<uint32_t>(a, b)) {
a += 4;
b += 4;
len -= 4;
}
if (len >= 4) {
return false;
}
if (len >= 2 && eq<uint16_t>(a, b)) {
a += 2;
b += 2;
len -= 2;
}
return (len == 1 && *a == *b) || len == 0;
}
} // namespace cachelib
} // namespace facebook