module Assocext: sig endAn associative extent should be seen as a null array and an ordered list of extent, each extent possessing a value and covering a certain part of the array. Single extents are contiguous, and can not overlap. An extent can have zero length. Many extents of zero length can fit between the same two elements of the array - they are not said to overlap. They can also fit between two non-zero-length extents. However, they won't fit inside an extent. The ordering is maintained among zero-length extent.
A range in the list above is also called a reserved extent. The complement of the union of all the reserved ranges can be written as a disjoint union of non-overlapping non-empty contiguous intervals of the array, called free intervals.
The functionality of assocexts is driven by the functionality desired
of ligands. For instance, zero-length reserved extents are important
because we can collapse any given non-empty extent to an empty
one. Also, there is currently no way to reserve an empty extent
between, say, two other given extent, since the reserve function
below always reserves the leftmost possible extent. But this
functionality is not needed.
This type is not thread-safe.
See also testing/test_assocext.ml for simple examples of how to use this
module.
type 'a extent
type interval = {
|
start : |
|
length : |
{start = 0; length
= 0}; the entire string {start = 0; length = 1}; and the strict end
of the string {start = 1; length = 0}.val get_interval : 'a extent -> intervalextent type.val get_value : 'a extent -> 'aextent type.type 'a t
'a to extents.val create : int -> 'a tcreate n creates a new associative extent of length n. It
originally has a single interval in it, which is free and whose range
is {start = 0; length = n}.val get_length : 'a t -> intget_length q returns the total length of the assocext q. It
was set at the beginning by the create command, and may be changed
through the use of the change_length function below.exception Illegal_range
val check : 'a t -> int -> int -> boolcheck e start len returns true if the range of length len
starting at start does not overlap with any reserved range, false
otherwise. In other words, it returns true if and only if reserve
(see below) with the same parameters does not raise an exception.
If start + len is greater than the length of the original extent,
exception Illegal_range will be raised.
This also applies to a range of length zero.
exception Extent_occupied
val reserve : 'a t -> 'a -> int -> int -> 'a extentreserve q v start len will allocate value v to a new reserved
extent ranging from start to start + len and return that extent,
if that range does not overlap with an existing reserved extent. If
not, it will raise Extent_occupied.
If start + len is greater than the length of the original extent,
exception Illegal_range will be raised.
If the range has length zero, the reserved range will be the leftmost (that is, first) in the ordering.
exception Extent_illegal
val free : 'a extent -> 'a t -> unitfree e q returns the previously reserved extent e in the
associative extent queue q to the free state. e must correspond
exactly to a reserved extent, otherwise exception Extent_illegal is
raised.val list_extents : 'a t -> 'a extent listextents. FIXME: Should be
sorted.val list_free_intervals : 'a t -> interval listexception Illegal_position
get_pos_extent below.type 'a holder =
| |
Free of |
| |
Reserved of |
val get_pos_extent : 'a t -> int -> 'a holderget_pos_extent q pos returns either the reserved extent or the
free interval which contains the array entry (of length one!) at
position pos, or throws Illegal_position if the position does not
fit within the extent. The range returned is either free or reserved,
but necessarily non-empty.val change_length : 'a extent -> 'a t -> int -> unitchange_length e q n sets the length of the reserved extend e
in the assocext q to n, shifting all the other extents if
necessary (if the length changes). e must be reserved, otherwise
exception Extent_illegal is raised. The length may be set to zero.
The validity of all the other extents is unaffected.exception Out_of_bounds
exception Empty
first and last if the assocexts are empty.val first : 'a t -> 'a extentval last : 'a t -> 'a extentval next_extent : 'a extent -> 'a extentnext_extent e q returns the extent which follows e in the
assocext q. Raises Out_of_bounds if e is the last extent.val prev_extent : 'a extent -> 'a extent
val iter : ('a extent -> unit) -> 'a t -> unititer f q applies the function f to each extent e of q, in
the order in which they appear, starting from the first to the
last. f must have type 'a extent -> unit.