blob: 03daa7ff183ad61169bd2f63435eaa24a2e789d4 [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_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_