| // 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_ZXDB_COMMON_ADDRESS_RANGES_H_ | |
| #define SRC_DEVELOPER_DEBUG_ZXDB_COMMON_ADDRESS_RANGES_H_ | |
| #include <optional> | |
| #include <string> | |
| #include <vector> | |
| #include "src/developer/debug/zxdb/common/address_range.h" | |
| namespace zxdb { | |
| // A set of address ranges. It exposes a read-only vector-like interface along with some helper | |
| // functions to test for inclusion. | |
| // | |
| // The ranges in the structure are always stored in canonical form: sorted by the begin address, | |
| // non-overlapping, no empty ranges. | |
| class AddressRanges { | |
| public: | |
| using RangeVector = std::vector<AddressRange>; | |
| using const_iterator = RangeVector::const_iterator; | |
| using const_reverse_iterator = RangeVector::const_reverse_iterator; | |
| // Indicates the type of input. Canonical input is a set of sorted, non-overlapping ranges. | |
| // Non-canonical input can be anything. Non-canonical input will be sorted and un-overlapped. | |
| enum Format { kCanonical, kNonCanonical }; | |
| // Creates an empty set of ranges. | |
| AddressRanges() = default; | |
| AddressRanges(const AddressRanges& other) : ranges_(other.ranges_) {} | |
| AddressRanges(AddressRanges&& other) noexcept : ranges_(std::move(other.ranges_)) {} | |
| // Creates a single-range set. If the range is empty it will not be added. | |
| explicit AddressRanges(const AddressRange& r) { | |
| if (!r.empty()) | |
| ranges_.push_back(r); | |
| } | |
| // Creates from a set of ranges. | |
| AddressRanges(Format, RangeVector ranges); | |
| AddressRanges& operator=(const AddressRanges& other) { | |
| ranges_ = other.ranges_; | |
| return *this; | |
| } | |
| AddressRanges& operator=(AddressRanges&& other) { | |
| ranges_ = std::move(other.ranges_); | |
| return *this; | |
| } | |
| bool operator==(const AddressRanges& other) const { return ranges_ == other.ranges_; } | |
| bool operator!=(const AddressRanges& other) const { return !operator==(other); } | |
| size_t size() const noexcept { return ranges_.size(); } | |
| bool empty() const { return ranges_.empty(); } | |
| const AddressRange& operator[](size_t i) const { return ranges_[i]; } | |
| const AddressRange& front() const { return ranges_.front(); } | |
| const AddressRange& back() const { return ranges_.back(); } | |
| const_iterator begin() const noexcept { return ranges_.begin(); } | |
| const_iterator cbegin() const noexcept { return ranges_.cbegin(); } | |
| const_iterator end() const noexcept { return ranges_.end(); } | |
| const_iterator cend() const noexcept { return ranges_.cend(); } | |
| const_reverse_iterator rbegin() const noexcept { return ranges_.rbegin(); } | |
| const_reverse_iterator crbegin() const noexcept { return ranges_.crbegin(); } | |
| const_reverse_iterator rend() const noexcept { return ranges_.rend(); } | |
| const_reverse_iterator crend() const noexcept { return ranges_.crend(); } | |
| // Returns the individual subrange that includes the given address if one exists. | |
| std::optional<AddressRange> GetRangeContaining(uint64_t addr) const; | |
| // Returns true if the address is included in any of the ranges. | |
| bool InRange(uint64_t addr) const; | |
| // Returns the range covering all sub ranges. If there are no sub-ranges, the result will be an | |
| // empty range. | |
| AddressRange GetExtent() const; | |
| // Returns a string representing this set of ranges for debugging purposes. | |
| std::string ToString() const; | |
| // Returns true if the given vector is in canonical form. | |
| static bool IsCanonical(const AddressRanges::RangeVector& ranges); | |
| private: | |
| void Canonicalize(); | |
| RangeVector ranges_; | |
| }; | |
| } // namespace zxdb | |
| #endif // SRC_DEVELOPER_DEBUG_ZXDB_COMMON_ADDRESS_RANGES_H_ |