-- File: StringsA.Mesa  Edited by:
-- Sandman on July 1, 1980  8:39 AM
-- Sapsford on May 8, 1980  4:04 PM
-- Forrest on October 16, 1980  3:45 PM
-- Copyright  Xerox Corporation 1979, 1980

DIRECTORY
  Inline USING [BITOR],
  String USING [CharsPerWord, StringHeaderSize, SubString];

StringsImplA: PROGRAM IMPORTS Inline EXPORTS String = PUBLIC
  BEGIN OPEN String;

  WordsForString: PROCEDURE [nchars: CARDINAL] RETURNS [CARDINAL] =
    BEGIN
    RETURN[StringHeaderSize + (nchars + (CharsPerWord - 1))/CharsPerWord]
    END;

  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;

  EqualString, EqualStrings: PROCEDURE [s1, s2: STRING] RETURNS [BOOLEAN] =
    BEGIN
    i: CARDINAL;
    IF s1 = NIL AND s2 = NIL THEN RETURN[TRUE];
    IF s1 = NIL OR s2 = NIL OR s1.length # s2.length THEN RETURN[FALSE];
    FOR i IN [0..s1.length) DO IF s1[i] # s2[i] THEN RETURN[FALSE]; ENDLOOP;
    RETURN[TRUE]
    END;

  EquivalentString, EquivalentStrings: PROCEDURE [s1, s2: STRING]
    RETURNS [BOOLEAN] =
    BEGIN OPEN Inline;
    i: CARDINAL;
    casebit: WORD = 40B;
    IF s1 = NIL AND s2 = NIL THEN RETURN[TRUE];
    IF s1 = NIL OR s2 = NIL OR s1.length # s2.length THEN RETURN[FALSE];
    FOR i IN [0..s1.length) DO
      IF BITOR[s1[i], casebit] # BITOR[s2[i], casebit] THEN RETURN[FALSE];
      ENDLOOP;
    RETURN[TRUE]
    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;

  DeleteSubString: PROCEDURE [s: SubString] =
    BEGIN
    b: STRING = s.base;
    i: CARDINAL ← s.offset;
    j: CARDINAL ← i + s.length;
    WHILE j < b.length DO b[i] ← b[j]; i ← i + 1; j ← j + 1; ENDLOOP;
    b.length ← i;
    RETURN
    END;


  END....