-- File: LongStringImpl.Mesa  Edited by Sandman on July 28, 1980  9:04 AM

DIRECTORY
  Inline USING [BITOR],
  Strings USING [String, SubString];

LongStringImpl: PROGRAM IMPORTS Inline EXPORTS Strings = PUBLIC
  BEGIN OPEN Strings;
  
  StringBoundsFault: SIGNAL [s: String] RETURNS [ns: String] = CODE;

  AppendChar: PROCEDURE [s: String, c: CHARACTER] =
    BEGIN
    IF s = NIL THEN RETURN;
    UNTIL s.length < s.maxlength DO s ← SIGNAL StringBoundsFault[s]; ENDLOOP;
    s[s.length] ← c;
    s.length ← s.length + 1;
    RETURN
    END;
    
  AppendString: PROCEDURE [to: String, from: String] =
    BEGIN
    i, j, n: CARDINAL;
    IF to = NIL OR from = NIL THEN RETURN;
    WHILE from.length + to.length > to.maxlength DO
      to ← SIGNAL StringBoundsFault[to]; ENDLOOP;
    n ← MIN[from.length, LOOPHOLE[to.maxlength - to.length, CARDINAL]];
    i ← to.length;
    j ← 0;
    WHILE j < n DO to[i] ← from[j]; i ← i + 1; j ← j + 1; ENDLOOP;
    to.length ← i;
    RETURN
    END;
    
  AppendSubString: PROCEDURE [to: String, from: SubString] =
    BEGIN
    i, j, n: CARDINAL;
    s: String;
    IF to = NIL OR (s ← from.base) = NIL THEN RETURN;
    WHILE from.length + to.length > to.maxlength DO
      to ← SIGNAL StringBoundsFault[to]; ENDLOOP;
    i ← to.length;
    j ← from.offset;
    n ← MIN[from.length, LOOPHOLE[to.maxlength - to.length, CARDINAL]];
    WHILE n > 0 DO to[i] ← s[j]; i ← i + 1; j ← j + 1; n ← n - 1; ENDLOOP;
    to.length ← i;
    RETURN
    END;
    
  EqualSubString, EqualSubStrings: PROCEDURE [s1, s2: SubString]
    RETURNS [BOOLEAN] =
    BEGIN
    i1, i2, n: CARDINAL;
    b1, b2: String;
    IF s1.length # s2.length THEN RETURN[FALSE];
    b1 ← s1.base;
    i1 ← s1.offset;
    b2 ← s2.base;
    i2 ← s2.offset;
    FOR n ← s1.length, n - 1 WHILE n > 0 DO
      IF b1[i1] # b2[i2] THEN RETURN[FALSE]; i1 ← i1 + 1; i2 ← i2 + 1; ENDLOOP;
    RETURN[TRUE]
    END;
    
  EquivalentSubString, EquivalentSubStrings: PROCEDURE [s1, s2: SubString]
    RETURNS [BOOLEAN] =
    BEGIN OPEN Inline;
    casebit: WORD = 40B;
    i1, i2, n: CARDINAL;
    b1, b2: String;
    IF s1.length # s2.length THEN RETURN[FALSE];
    b1 ← s1.base;
    i1 ← s1.offset;
    b2 ← s2.base;
    i2 ← s2.offset;
    FOR n ← s1.length, n - 1 WHILE n > 0 DO
      IF BITOR[b1[i1], casebit] # BITOR[b2[i2], casebit] THEN RETURN[FALSE];
      i1 ← i1 + 1;
      i2 ← i2 + 1;
      ENDLOOP;
    RETURN[TRUE]
    END;
    
  END.