-- CharIOPack.Mesa  Edited by Sandman on September 12, 1980  8:19 AM
-- Copyright  Xerox Corporation 1979, 1980

DIRECTORY
  CharIO USING [NumberFormat, CR, SP],
  StreamDefs USING [StreamHandle],
  String USING [AppendChar, AppendNumber, StringToNumber, SubString];

CharIOPack: PROGRAM IMPORTS String EXPORTS CharIO =
  BEGIN OPEN CharIO;

  StreamHandle: TYPE = StreamDefs.StreamHandle;

  -- String i/o


  GetString: PUBLIC PROCEDURE [
    in: StreamHandle, s: STRING, test: PROCEDURE [CHARACTER] RETURNS [BOOLEAN]] =
    BEGIN
    c: CHARACTER;
    UNTIL in.endof[in] OR test[c ← in.get[in]] DO String.AppendChar[s, c] ENDLOOP;
    END;

  PutString: PUBLIC PROCEDURE [out: StreamHandle, s: STRING] =
    BEGIN i: CARDINAL; FOR i IN [0..s.length) DO out.put[out, s[i]] ENDLOOP; END;

  PutSubString: PUBLIC PROCEDURE [out: StreamHandle, s: String.SubString] =
    BEGIN
    i: CARDINAL;
    FOR i IN [s.offset..s.offset + s.length) DO out.put[out, s.base[i]] ENDLOOP;
    END;

  GetLine: PUBLIC PROCEDURE [in: StreamHandle, s: STRING] =
    BEGIN GetString[in, s, IsCR]; END;

  IsCR: PROCEDURE [c: CHARACTER] RETURNS [BOOLEAN] = BEGIN RETURN[c = CR] END;

  GetID: PUBLIC PROCEDURE [in: StreamHandle, s: STRING] =
    BEGIN
    c: CHARACTER;
    WHILE ~in.endof[in] AND (c ← in.get[in]) = SP DO NULL ENDLOOP;
    UNTIL in.endof[in] OR c = SP OR c = CR DO
      String.AppendChar[s, c]; c ← in.get[in] ENDLOOP;
    END;

  --  Numerical i/o


  GetNumber: PUBLIC PROCEDURE [in: StreamHandle, radix: CARDINAL]
    RETURNS [UNSPECIFIED] =
    BEGIN
    s: STRING = [10];
    GetID[in, s];
    RETURN[String.StringToNumber[s, radix]]
    END;

  PutNumber: PUBLIC PROCEDURE [
    out: StreamHandle, val: INTEGER, format: NumberFormat] =
    BEGIN
    i: CARDINAL;
    neg: BOOLEAN ← FALSE;
    fill: CHARACTER = (IF format.zerofill THEN '0 ELSE ' );
    s: STRING = [17];
    IF val < 0 AND ~format.unsigned THEN BEGIN val ← -val; neg ← TRUE END;
    String.AppendNumber[s, val, format.base];
    i ← s.length;
    IF neg THEN
      BEGIN
      i ← i + 1;
      IF format.zerofill THEN BEGIN out.put[out, '-]; neg ← FALSE END;
      END;
    THROUGH (i..format.columns] DO out.put[out, fill] ENDLOOP;
    IF neg THEN out.put[out, '-];
    FOR i IN [0..s.length) DO out.put[out, s[i]] ENDLOOP;
    END;

  PutDecimal: PUBLIC PROCEDURE [out: StreamHandle, n: INTEGER] =
    BEGIN PutNumber[out, n, NumberFormat[10, FALSE, FALSE, 0]]; END;

  PutOctal: PUBLIC PROCEDURE [out: StreamHandle, n: UNSPECIFIED] =
    BEGIN
    PutNumber[out, n, NumberFormat[8, FALSE, TRUE, 0]];
    IF n ~IN [0..7] THEN out.put[out, 'B];
    END;


  END.