-- FTPUtilities.mesa, Edited by: HGM July 31, 1980  5:51 PM  

-- Copyright  Xerox Corporation 1979, 1980

DIRECTORY
  Stream USING [Block],
  ByteBlt USING [ByteBlt],
  FTPDefs,
  FTPPrivateDefs;

FTPUtilities: PROGRAM
  IMPORTS ByteBlt, FTPPrivateDefs EXPORTS FTPPrivateDefs SHARES FTPDefs =
  BEGIN OPEN FTPDefs, FTPPrivateDefs;


  -- **********************!  Transmission Primitives  !***********************

  -- Note:  These transmission primitives increment the connection's total byte count
  --   and do not trace the transmitted data.

  SendBlock: PUBLIC PROCEDURE [
    ftper: FTPer, source: POINTER, byteCount: CARDINAL] =
    BEGIN OPEN ftper;
    -- Note:  Forces transmission.
    -- local variables
    bytePointerObject: BytePointerObject ← [source, FALSE, byteCount];
    -- send block
    communicationPrimitives.SendBytes[
      communicationSystem, connection, @bytePointerObject];
    -- force transmission
    communicationPrimitives.ForceOutput[communicationSystem, connection];
    -- increment total byte count for connection
    totalByteCount ← totalByteCount + byteCount;
    END;

  ReceiveBlock: PUBLIC PROCEDURE [
    ftper: FTPer, destination: POINTER, maxWordCount: CARDINAL]
    RETURNS [actualByteCount: CARDINAL] =
    BEGIN OPEN ftper;
    -- local variables
    bytePointerObject: BytePointerObject ←
      [destination, FALSE, bytesPerWord*maxWordCount];
    -- receive next block
    communicationPrimitives.ReceiveBytes[
      communicationSystem, connection, @bytePointerObject, TRUE];
    actualByteCount ← bytesPerWord*maxWordCount - bytePointerObject.count;
    -- increment total byte count for connection
    totalByteCount ← totalByteCount + actualByteCount;
    END;

  SendBytes: PUBLIC PROCEDURE [ftper: FTPer, bytePointer: BytePointer] =
    BEGIN OPEN ftper;
    -- Note:  No operation if bytePointer.count=0.
    -- local constants
    byteCount: CARDINAL = bytePointer.count;
    -- nop if no bytes
    IF bytePointer.count = 0 THEN RETURN;
    -- send bytes
    communicationPrimitives.SendBytes[
      communicationSystem, connection, bytePointer];
    -- increment total byte count for connection
    totalByteCount ← totalByteCount + byteCount;
    END;

  ReceiveBytes: PUBLIC PROCEDURE [ftper: FTPer, bytePointer: BytePointer] =
    BEGIN OPEN ftper;
    -- Note:  No operation if bytePointer.count=0.
    -- local constants
    byteCount: CARDINAL = bytePointer.count;
    -- nop if no bytes
    IF bytePointer.count = 0 THEN RETURN;
    -- receive bytes
    communicationPrimitives.ReceiveBytes[
      communicationSystem, connection, bytePointer, FALSE];
    -- increment total byte count for connection
    totalByteCount ← totalByteCount + byteCount;
    END;

  SendWord: PUBLIC PROCEDURE [ftper: FTPer, word: WORD] =
    BEGIN OPEN ftper;
    -- local constants
    wordPointer: Word = LOOPHOLE[@word];
    -- send word
    communicationPrimitives.SendByte[
      communicationSystem, connection, wordPointer.lhByte];
    communicationPrimitives.SendByte[
      communicationSystem, connection, wordPointer.rhByte];
    -- increment total byte count for connection
    totalByteCount ← totalByteCount + bytesPerWord;
    END;

  ReceiveWord: PUBLIC PROCEDURE [ftper: FTPer] RETURNS [word: WORD] =
    BEGIN OPEN ftper;
    -- local constants
    wordPointer: Word = LOOPHOLE[@word];
    -- receive word
    [wordPointer.lhByte, ] ← communicationPrimitives.ReceiveByte[
      communicationSystem, connection, FALSE];
    [wordPointer.rhByte, ] ← communicationPrimitives.ReceiveByte[
      communicationSystem, connection, FALSE];
    -- increment total byte count for connection
    totalByteCount ← totalByteCount + bytesPerWord;
    END;

  SendByte: PUBLIC PROCEDURE [ftper: FTPer, byte: Byte] =
    BEGIN OPEN ftper;
    -- send byte
    communicationPrimitives.SendByte[communicationSystem, connection, byte];
    -- increment total byte count for connection
    totalByteCount ← totalByteCount + 1;
    END;

  ReceiveByte: PUBLIC PROCEDURE [ftper: FTPer] RETURNS [byte: Byte] =
    BEGIN OPEN ftper;
    -- receive byte
    [byte, ] ← communicationPrimitives.ReceiveByte[
      communicationSystem, connection, FALSE];
    -- increment total byte count for connection
    totalByteCount ← totalByteCount + 1;
    END;

  -- **********************!  Byte Primitives  !***********************

  TransferBytes: PUBLIC PROCEDURE [srcBytePointer, dstBytePointer: BytePointer] =
    BEGIN
    to, from: Stream.Block;
    bytes: CARDINAL;
    from.blockPointer ← srcBytePointer.address;
    from.startIndex ← IF srcBytePointer.offset THEN 1 ELSE 0;
    from.stopIndexPlusOne ← from.startIndex + srcBytePointer.count;
    to.blockPointer ← dstBytePointer.address;
    to.startIndex ← IF dstBytePointer.offset THEN 1 ELSE 0;
    to.stopIndexPlusOne ← to.startIndex + dstBytePointer.count;
    bytes ← ByteBlt.ByteBlt[to: to, from: from];
    AdvanceBytePointer[srcBytePointer, bytes];
    AdvanceBytePointer[dstBytePointer, bytes];
    END;


  -- **********************!  Main Program  !***********************

  -- no operation

  END. -- of FTPUtilities