(*
9			The Bounded Character String


A bounded implementation of the String abstraction, described in the previous chapter, is
presented.  This particular form has the properties: Sequential, Bounded, Managed, and
Iterator, which describe specific aspects of the implementation as follows:

Sequential:	Can only be used in a non-tasking environment, or by only one task.
Bounded:	The maximum size of a string is given when the string is created.
Managed:	Memory space for items and objects is returned to the system when no
			longer needed.
Iterator:	Routines for looping over each of the string items are provided.


As noted last chapter, strings are nearly always formed of characters, or items that can be
represented using characters.  For this reason both bounded and unbounded string modules
will use the Character Items module instead of the more generic Items module.



Section 9.1 contains the interface to the String Enumerations module which is used by
the string implementations of this, and the next, chapter.  The bounded string module
interface follows in Section 9.2 and its implementation in Section 9.3.
*)



(*
9.2		StringCSBMI Interface


The interface to the bounded string is presented below.  The purpose and implementation
specifics of each routine is briefly described along with mention of the complexity
measure of the actual implementation.
*)



DEFINITION MODULE StrCSBMI;
(*==========================================================
    Version  : 1.00  29 Apr 1989  C. Lins
    Compiler : TopSpeed Modula-2
    Component: Monolithic Structure String (Opaque version)
               Character Sequential Bounded Managed Iterator

    THE ABSTRACTION
    This module provides the String data type localized for
    CHAR items.

    REVISION HISTORY
    v1.00  29 Apr 1989  C. Lins:
       Initial implementation.
==========================================================*)

FROM ErrorHandling IMPORT
    (*--Type*) HandlerProc;

FROM CharItems IMPORT
    (*--Type*) Item, AccessProc, ChangeProc, LoopAccessProc,
               LoopChangeProc;

FROM Relations IMPORT
    (*--Type*) Relation;

FROM StrEnum IMPORT
    (*--Type*) Exceptions;

    (*-----------------------*)


TYPE  String;
TYPE  StringSize = [ 1 .. 32000 ];
TYPE  Position   = StringSize;
CONST NullString = String(NIL);


(*	9.2.1		Exceptions

The ModuleID is used by the exception handling mechanism to distinguish this module
from all other modules.

StringError returns the exception code from the most recent string operation.  A result of
noerr indicates successful completion of the operation.  O(1).

GetHandler returns the exception handler routine associated with the given exception. 
Though the routine is a function procedure returning a procedure as its result, the
HandlerProc  may not be called from within the GetHandler call itself.  The procedure
result must be first assigned to a procedure variable before invocation.  Exception handlers
are given an initial value of ExitOnError except for the handler for noerr  which is
initialized to the null exception handler.  For example, the statement

  GetHandler(overflow)(someErrorCode);

would be flagged as an error by the compiler.  O(1).

SetHandler associates an exception handler routine with the given exception and is the
inverse of GetHandler.  This routine may be used to override the default settings for the
exception handlers.  O(1).
*)

CONST ModuleID = 1;

PROCEDURE StringError ()              : Exceptions  (*-- out   *);

PROCEDURE GetHandler  (    theError   : Exceptions  (*-- in    *))
                                      : HandlerProc (*-- out   *);

PROCEDURE SetHandler  (    theError   : Exceptions  (*-- in    *);
                           theHandler : HandlerProc (*-- in    *));



(*	9.2.2		Constructors

The Create operation attempts to generate a new, empty string of the given maximum
size (theSize),  which defines the desired maximum string length.  Since this module uses
character items, all the standard operations, (such as assignment and comparison), can be
applied directly and therefore a TypeID and associated user-defined routines are
unnecessary.  Create returns the new string upon successful completion of the routine.  If
it is not possible to create the string, the overflow exception is raised and the constant
NullString  will be returned. O(1).

Destroy takes the given string, clears it of any items, and then destroys the string itself. 
Where Create defines a string, Destroy is its inverse, making the string undefined. O(1).

Clear takes the given string and removes all of its items.  Clearing the string returns it
to the empty state. O(1).

The Assign operation attempts to generate a duplicate of the source string (theString) in
the target string (toString).  The target string is automatically created using the size
attribute of the source string, if necessary.  If this step is unnecessary, (the target string
has already been previously created), the target is cleared of its present contents, but the
size is left unchanged.  There is no guarantee that the client module would desire the
target string to be defined with the same size as the source.  The minimum requirement
for the target string size is that it be capable of storing all of the items present in the
source string.  It may be desirable that the target string size be greater than the source
string size.  Such a situation could occur during error recovery of a bounded string
overflow caused by the string length encountering the string size, and the client module
may effectively attempt to increase the the string size using the assignment mechanism. 
O(n).

Prepend adds the first string to the beginning of the second string O(mn), Append adds the
first string to the end of the second string  O(mn), while Insert adds adds the first string to
the second string at the given string index position.  O(mn).

Delete  removes characters from the given string between the given index positions,
inclusive.  O(n).

Replace removes characters from the given string from the given index position to the
end of the string and then inserts the replacement string at the end of the given source
string.  The length of the source string may grow due to the effects of the replacement.

SetItem changes a single character of the source string at the specified index position.
O(1).

Construct  allows one to build a dynamic string from the usual Modula-2 form of string. 
O(n).
*)

PROCEDURE Create    (    theSize    : StringSize (*-- in    *))
                                    : String     (*-- out   *);

PROCEDURE Destroy   (VAR theString  : String     (*-- inout *));

PROCEDURE Clear     (VAR theString  : String     (*-- inout *));

PROCEDURE Assign    (    theString  : String     (*-- in    *);
                     VAR toString   : String     (*-- inout *));

PROCEDURE Prepend   (    theString  : String     (*-- in    *);
                     VAR toString   : String     (*-- inout *));

PROCEDURE Append    (    theString  : String     (*-- in    *);
                     VAR toString   : String     (*-- inout *));

PROCEDURE Insert    (    theString  : String     (*-- in    *);
                     VAR toString   : String     (*-- inout *);
                         theIndex   : Position   (*-- in    *));

PROCEDURE Delete    (VAR theString  : String     (*-- inout *);
                         fromIndex  : Position   (*-- in    *);
                         toIndex    : Position   (*-- in    *));

PROCEDURE Replace   (VAR theString  : String     (*-- inout *);
                         theIndex   : Position   (*-- in    *);
                         withString : String     (*-- in    *));

PROCEDURE SetItem   (VAR theString  : String     (*-- inout *);
                         theIndex   : Position   (*-- in    *);
                         theItem    : Item       (*-- in    *));

PROCEDURE Construct (VAR theString   : String        (*-- inout *);
                         theSubstring: ARRAY OF Item (*-- in    *));



(*	9.2.3		Selectors


IsDefined attempts to determine whether the given string is valid, e.g., has been created
and not yet destroyed.  How this is accomplished may be as simple or complicated as the
implementer desires and the requirements of the application.  O(1).

IsEmpty returns true if the given string contains no items, and false otherwise. 
Undefined strings are considered empty.  O(1).

SizeOf returns the maximum possible size (and therefore, position) for the given string
O(1), while LengthOf  returns the number of characters present in the string O(1).  The
function  result from both routines are declared CARDINAL (instead of StringSize or
Position) as undefined strings cause zero to be returned.

Compare establishes the ordering relation between two strings. IsEqual  returns true if
two strings contain the same items.

ItemOf retrieves a single item at the given index position from the string O(1); SliceOf
returns a contiguous sequence of characters from a string between two index positions;
and SubstringOf  returns the whole string as a contiguous sequence of characters.  Both
SliceOf and SubstringOf terminate their results with 0C if necessary by the rules of
Modula-2.
*)

PROCEDURE IsDefined  (    theString  : String      (*-- in    *))
                                     : BOOLEAN     (*-- out   *);

PROCEDURE IsEmpty    (    theString  : String      (*-- in    *))
                                     : BOOLEAN     (*-- out   *);

PROCEDURE SizeOf     (    theString  : String      (*-- in    *))
                                     : CARDINAL    (*-- out   *);

PROCEDURE LengthOf   (    theString  : String      (*-- in    *))
                                     : CARDINAL    (*-- out   *);

PROCEDURE Compare    (    left       : String      (*-- in    *);
                          right      : String      (*-- in    *))
                                     : Relation    (*-- out   *);

PROCEDURE IsEqual    (    left       : String      (*-- in    *);
                          right      : String      (*-- in    *))
                                     : BOOLEAN     (*-- out   *);

PROCEDURE ItemOf     (    theString  : String      (*-- in    *);
                          theIndex   : Position    (*-- in    *))
                                     : Item        (*-- out   *);

PROCEDURE SliceOf    (    theString  : String        (*-- in    *);
                          fromIndex  : Position      (*-- in    *);
                          toIndex    : Position      (*-- in    *);
                      VAR theSlice   : ARRAY OF Item (*-- out   *));

PROCEDURE SubstringOf(    theString  : String        (*-- in    *);
                      VAR toSubstring: ARRAY OF Item (*-- out   *));



(*	9.2.4		Iterators

The iterator routines LoopOver and LoopChange provide facilities for looping over some
or all items of a string, with read-only and read-write access to each item, respectively. 
theProcess  procedure parameter to these routines returns a BOOLEAN function result
where TRUE allows the iteration to proceed to the next item and FALSE causes the
iteration to be terminated.  O(n).

Traverse and TravChange iterators provide facilities for looping over all items of a
string, with read-only and read-write access to each item, respectively.  O(n).

All four iterators traverse the given string from the item at the first position towards
items at greater positions within the string.  Obviously, if given an empty string the
processing procedure will not be invoked.
*)

PROCEDURE LoopOver   (    theString : String         (*-- in    *);
                          theProcess: LoopAccessProc (*-- in    *));

PROCEDURE LoopChange (    theString : String         (*-- in    *);
                          theProcess: LoopChangeProc (*-- in    *));

PROCEDURE Traverse   (    theString : String         (*-- in    *);
                          theProcess: AccessProc     (*-- in    *));

PROCEDURE TravChange (    theString : String         (*-- in    *);
                          theProcess: ChangeProc     (*-- in    *));

END StrCSBMI.
