INTERFACEMTextRd ; IMPORT Rd, MText, Thread; TYPE T <: Public; Public = Rd.T OBJECT METHODS init (m : MText.T := NIL; start : CARDINAL := 0; rangeStart: CARDINAL := 0; rangeEnd : CARDINAL := LAST (CARDINAL); reverse : BOOLEAN := FALSE ): T RAISES {Rd.Failure, Thread.Alerted} END;
rd.init(m, ...)
initializes a seekable, non-intermittent reader for the
MText m
.
It is intended that this method be called more than once, to re-initialize
a reader (and avoid re-allocating storage for rd.buff
); in this case, it
is permitted for m
to be NIL
, and the default value is the MText
that
was previously used by the reader.
The reader's source may be a proper subsequence of the underlying MText
,
and the reader can be initialized to read in reverse order.
src(rd)
comprises the characters of m
that are contained in the
interval
[first(rd) .. last(rd)]where
first(rd)) = rangeStartand
last(rd) = MIN (rangeEnd, MText.Length(m)) - 1]
len(rd) = MAX (last(rd) - first(rd) + 1, 0)In a forward reader (
reverse = FALSE
), Rd.GetChar
delivers characters
from start
to last(rd)
. Rd.Index
returns the index relative to
first(rd)
. Hence just after a forward reader rd
is initialized,
cur(rd) = start - first(rd)In a reverse reader,
Rd.GetChar
delivers characters from start-1
(not
start
) to first(rd)
. Rd.Index
returns the index relative to
last(rd)+1
. Hence just after a reverse reader rd
is initialized,
cur(rd) = last(rd) + 1 - startThus the value returned by
Rd.Index
increases by 1 with each call to
Rd.GetChar
, regardless of the reader's direction.
The coordinate system used by Rd.Seek
is consistent with Rd.Index
.
If the underlying MText
is modified, the reader is invalid and should be
re-initialized.
rd.init
calls Rd.Seek(rd, rd.cur)
, which can raise Rd.Failure
or
Thread.Alerted
.
Synchronization: it is not possible to have several readers reading the mtext concurrently. The reason is that a read to a file node causes the mtext data structure to change. If you don't use file nodes, then it's safe. (JRM doesn't believe this.)
PROCEDURE New (m : MText.T; start : CARDINAL := 0; rangeStart: CARDINAL := 0; rangeEnd : CARDINAL := LAST (CARDINAL); reverse : BOOLEAN := FALSE ): T RAISES {Rd.Failure, Thread.Alerted};
This is equivalent toNEW (T).init (m, start, rangeStart, rangeEnd, reverse, alertable)
END MTextRd.