blob: 3ceb4f70e7b710c29cefda40380e82d795a948d6 [file] [log] [blame]
// Copyright 2019 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef SRC_DEVELOPER_DEBUG_SHARED_LARGEST_LESS_OR_EQUAL_H_
#define SRC_DEVELOPER_DEBUG_SHARED_LARGEST_LESS_OR_EQUAL_H_
#include <algorithm>
namespace debug_ipc {
// Returns an iterator pointing to the largest element in [first, last) less than or equal to the
// given |val|. As with std::lower_bound, the range [first, last) must be sorted according to
// the |less| comparator.
//
// If the query matches exactly a sequence of equal items, the first duplicate will be returned. If
// the query value matches a sequence of duplicates and does not exactly equal to them (it's
// returning the previous item), the last of the sequence will be returned.
//
// For example, if you had a sorted range of addresses and you want to know which one begins the
// range which an address falls into:
//
// std::vector<AddressRecord> ranges;
// int64_t address;
//
// auto found = LargestLessOrEqual(
// ranges.begin(), ranges.end(), address,
// [](const AddressRecord& record, uint64_t addr) { return record.addr < addr; },
// [](const AddressRecord& record, uint64_t addr) { return record.addr == addr; });
//
// For simple types, you can pass |std::less<T>()| and |std::equal_to<T>()| from <functional> for
// the comparators.
template <class BidirectionalIterator, class T, class CompareLess, class CompareEqual>
BidirectionalIterator LargestLessOrEqual(BidirectionalIterator first, BidirectionalIterator last,
const T& val, CompareLess less, CompareEqual equals) {
if (first == last)
return last; // Nothing to return.
auto lower_bound = std::lower_bound(first, last, val, less);
if (lower_bound != last && equals(*lower_bound, val))
return lower_bound; // Got an exact match.
// Otherwise, the result is the previous item in the range.
if (lower_bound == first)
return last; // No previous item, |val| is before the range.
return --lower_bound;
}
} // namespace debug_ipc
#endif // SRC_DEVELOPER_DEBUG_SHARED_LARGEST_LESS_OR_EQUAL_H_