.. index::
   pair: address range; design

.. _design-range:


Ranges of addresses
===================

.. mps:prefix:: design.mps.range


Introduction
------------

:mps:tag:`intro` This is the design of the Range module, which implements
objects representing address ranges.

:mps:tag:`readership` This document is intended for any MPS developer.


Requirements
------------

:mps:tag:`req.range` A range object must be able to represent an arbitrary
range of addresses that neither starts at :c:macro:`NULL` nor includes the
top grain of the address space.

:mps:tag:`req.empty` A range object must be able to represent the empty
range.

:mps:tag:`req.stack-alloc` It must be possible to allocate range objects on
the stack: that is, they do not require any heap resource.


Interface
---------

.. c:type:: RangeStruct *Range

:c:type:`Range` is the type of a range. It is an alias for ``RangeStruct *``. :c:type:`RangeStruct` is defined in the header so that it can be
inlined in client structures or allocated on the stack. Clients must
not depend on its implementation details.

.. c:function:: void RangeInit(Range range, Addr base, Addr limit)

Initialize a range object to represent the half-open address range
between ``base`` (inclusive) and ``limit`` (exclusive). It must be the
case that ``base <= limit``. If ``base == limit`` then the range is
empty.

.. c:function:: void RangeCopy(Range dest, Range src)

Initialize ``dest`` to be a copy of ``src``.

.. c:function:: void RangeInitSize(Range range, Addr base, Size size)

Initialize a range object to represent the half-open address range
between ``base`` (inclusive) and ``base + size`` (exclusive). If
``size == 0`` then the range is empty.

.. c:function:: void RangeFinish(Range range)

Finish a range object. Because a range object uses no heap resources
(:mps:ref:`.req.stack-alloc`) it is not necessary to call this. However,
clients may wish to do so in order to ensure that the range object is
invalid.

.. c:function:: Addr RangeBase(Range range)

Return the base of the range. (This is implemented as a macro, but
there is a function too.)

.. c:function:: Addr RangeLimit(Range range)

Return the limit of the range. (This is implemented as a macro, but
there is a function too.)

.. c:function:: Size RangeSize(Range range)

Return the size of the range. (This is implemented as a macro, but
there is a function too. The macro evaluates its argument twice.)

.. c:function:: Bool RangeContains(Range range, Addr addr)

Return :c:macro:`TRUE` if ``addr`` belongs to the range, or :c:macro:`FALSE` if it
does not. (This is implemented as a macro, but there is a function
too. The macro evaluates its arguments twice.)

.. c:function:: Bool RangeIsEmpty(Range range)

Return :c:macro:`TRUE` if the range is empty (contains no addresses),
:c:macro:`FALSE` otherwise. (This is implemented as a macro, but there is a
function too. The macro evaluates its argument twice.)

.. c:function:: Bool RangeIsAligned(Range range, Align alignment)

Return :c:macro:`TRUE` if the base and limit of the range are both aligned to
the given alignment, or :c:macro:`FALSE` if either is not.

.. c:function:: Bool RangesOverlap(Range range1, Range range2)

Return :c:macro:`TRUE` if the two ranges overlap (have at least one address
in common), or :c:macro:`FALSE` if they do not. Note that ranges [*A*, *B*) and
[*B*, *C*) do not overlap.

.. c:function:: Bool RangesNest(Range outer, Range inner)

Return :c:macro:`TRUE` if all addresses in ``inner`` are also in ``outer``,
or :c:macro:`FALSE` otherwise.