blob: 0848875175acdc4b557e60512e33a8c6396fe743 [file] [log] [blame]
// 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_