| // Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file |
| // for details. All rights reserved. Use of this source code is governed by a |
| // BSD-style license that can be found in the LICENSE file. |
| |
| #ifndef RUNTIME_VM_COMPILER_FFI_RANGE_H_ |
| #define RUNTIME_VM_COMPILER_FFI_RANGE_H_ |
| |
| #include "platform/assert.h" |
| #include "platform/utils.h" |
| #include "vm/allocation.h" |
| |
| namespace dart { |
| |
| namespace compiler { |
| |
| namespace ffi { |
| |
| // A non-empty range. |
| // |
| // Ranges are positive and non-empty. |
| // |
| // The end is exclusive. |
| class Range : public ValueObject { |
| public: |
| // Constructs a Range from start (inclusive) and length. |
| // |
| // The resulting range is `[start_inclusive, start_inclusive + length)`. |
| static Range StartAndLength(intptr_t start_inclusive, intptr_t length) { |
| return Range(start_inclusive, start_inclusive + length); |
| } |
| |
| // Constructs a Range from start (inclusive) and end (exclusive). |
| // |
| // The resulting range is `[start_inclusive, end_exclusive)`. |
| static Range StartAndEnd(intptr_t start_inclusive, intptr_t end_exclusive) { |
| return Range(start_inclusive, end_exclusive); |
| } |
| |
| Range(const Range& other) |
| : start_(other.start_), end_exclusive_(other.end_exclusive_) {} |
| |
| intptr_t start() const { return start_; } |
| intptr_t end_exclusive() const { return end_exclusive_; } |
| intptr_t end_inclusive() const { return end_exclusive_ - 1; } |
| |
| intptr_t Length() const { return end_exclusive_ - start_; } |
| |
| // Returs true iff number is in this range. |
| bool Contains(intptr_t number) const { |
| return start_ <= number && number < end_exclusive_; |
| } |
| |
| // Returns true iff [this] contains [other] completely. |
| bool Contains(const Range& other) const { |
| return Contains(other.start_) && Contains(other.end_inclusive()); |
| } |
| |
| // Returns true iff [this] is completey after [other]. |
| bool After(const Range& other) const { |
| return other.end_exclusive_ <= start_; |
| } |
| |
| // Returns true iff [this] contains some numbers of [other]. |
| bool Overlaps(const Range& other) const { |
| return !this->After(other) && !other.After(*this); |
| } |
| |
| // Returns the intersection of [this] with [other]. |
| // |
| // Requires [this] and [other] to overlap. |
| const Range Intersect(const Range& other) const { |
| ASSERT(Overlaps(other)); |
| return Range(Utils::Maximum(start_, other.start_), |
| Utils::Minimum(end_exclusive_, other.end_exclusive_)); |
| } |
| |
| // Returns a range moved by [delta]. |
| // |
| // `this.start() - delta` must be positive. |
| const Range Translate(intptr_t delta) const { |
| return Range(start_ + delta, end_exclusive_ + delta); |
| } |
| |
| private: |
| Range(intptr_t start_inclusive, intptr_t end_exclusive) |
| : start_(start_inclusive), end_exclusive_(end_exclusive) { |
| if (!(start_ >= 0 && end_exclusive_ > start_)) { |
| ASSERT(start_ >= 0); |
| ASSERT(end_exclusive_ > start_); |
| } |
| } |
| |
| const intptr_t start_; |
| const intptr_t end_exclusive_; |
| }; |
| |
| } // namespace ffi |
| |
| } // namespace compiler |
| |
| } // namespace dart |
| |
| #endif // RUNTIME_VM_COMPILER_FFI_RANGE_H_ |