(**************************************************************************)
(*                                                                        *)
(*  Encryption library                                                    *)
(*  Copyright (C) 2018   Peter Moylan                                     *)
(*                                                                        *)
(*  This program is free software: you can redistribute it and/or modify  *)
(*  it under the terms of the GNU General Public License as published by  *)
(*  the Free Software Foundation, either version 3 of the License, or     *)
(*  (at your option) any later version.                                   *)
(*                                                                        *)
(*  This program is distributed in the hope that it will be useful,       *)
(*  but WITHOUT ANY WARRANTY; without even the implied warranty of        *)
(*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *)
(*  GNU General Public License for more details.                          *)
(*                                                                        *)
(*  You should have received a copy of the GNU General Public License     *)
(*  along with this program.  If not, see <http://www.gnu.org/licenses/>. *)
(*                                                                        *)
(*  To contact author:   http://www.pmoylan.org   peter@pmoylan.org       *)
(*                                                                        *)
(**************************************************************************)


<* WOFF316+ *>

IMPLEMENTATION MODULE HexData;

        (********************************************************)
        (*                                                      *)
        (*   Misc procedures for dealing with arrays of bytes   *)
        (*                                                      *)
        (*  Programmer:         P. Moylan                       *)
        (*  Started:            12 October 2017                 *)
        (*  Last edited:        10 April 2018                   *)
        (*  Status:             OK                              *)
        (*                                                      *)
        (********************************************************)

FROM SYSTEM IMPORT
    (* type *)  CARD8, CARD16, CARD32,
    (* proc *)  CAST;

FROM STextIO IMPORT
    (* proc *)  WriteChar, WriteString, WriteLn;

FROM LowLevel IMPORT
    (* proc *)  IXOR, IXORB;

(************************************************************************)
(*                     WRITE HEX TO STANDARD OUTPUT                     *)
(************************************************************************)

PROCEDURE DumpHex1 (b: CARD8);

    (* Writes one-digit hex number. *)

    BEGIN
        IF b < 10 THEN
            WriteChar (CHR(b + ORD('0')));
        ELSE
            WriteChar (CHR(b - 10 + ORD('a')));
        END (*IF*);
    END DumpHex1;

(************************************************************************)

PROCEDURE DumpByte (b: CARD8);

    (* Writes word in bigendian hex notation. *)

    BEGIN
        DumpHex1 (b DIV 16);  DumpHex1 (b MOD 16);
    END DumpByte;

(************************************************************************)

PROCEDURE DumpByteArray (N: CARDINAL;  B: ARRAY OF CARD8);

    (* Writes N bytes in hex notation. *)

    VAR j: CARDINAL;

    BEGIN
        FOR j := 0 TO N-1 DO
            DumpByte (B[j]);
            IF j < N-1 THEN
                IF j MOD 20 = 19 THEN
                    WriteLn;  WriteString ("       ");
                ELSE
                    WriteString (" ");
                END (*IF*);
            END (*IF*);
        END (*FOR*);
    END DumpByteArray;

(************************************************************************)

PROCEDURE DumpHalfWord (w: CARD16);

    (* Writes w in hexadecimal. *)

    BEGIN
        DumpByte (w DIV 256);
        DumpByte (w MOD 256);
    END DumpHalfWord;

(************************************************************************)

PROCEDURE DumpWord (w: CARD32);

    (* Writes w in hexadecimal. *)

    BEGIN
        DumpHalfWord (w DIV 65536);
        DumpHalfWord (w MOD 65536);
    END DumpWord;

(************************************************************************)
(*                 CONVERSION FROM HEX CHARACTERS TO BYTES              *)
(************************************************************************)

TYPE CharSet = SET OF CHAR;

PROCEDURE Hex1ToByte (ch: CHAR): CARD8;

    (* Converts 1-digit hex number. *)

    BEGIN
        IF ch IN CharSet{'0'..'9'} THEN
            RETURN ORD(ch) - ORD('0');
        ELSIF ch IN CharSet{'A'..'F'} THEN
            RETURN ORD(ch) - ORD('A') + 10;
        ELSIF ch IN CharSet{'a'..'f'} THEN
            RETURN ORD(ch) - ORD('a') + 10;
        ELSE
            RETURN MAX(CARD8);
        END (*IF*);
    END Hex1ToByte;

(************************************************************************)

PROCEDURE Hex2ToByte (str: ARRAY OF CHAR;  VAR (*INOUT*) pos: CARDINAL): CARD8;

    (* Converts 2-digit hex number at str[pos], updates pos. *)

    VAR result: CARD8;

    BEGIN
        result := 16*Hex1ToByte(str[pos]) + Hex1ToByte(str[pos+1]);
        INC (pos, 2);
        RETURN result;
    END Hex2ToByte;

(************************************************************************)

PROCEDURE HexToBytes (str: ARRAY OF CHAR;
                            VAR (*OUT*) A: ARRAY OF CARD8): CARDINAL;

    (* Converts string of 2-digit hex numbers.  Returns number of bytes. *)

    VAR j, k: CARDINAL;

    BEGIN
        j := 0;  k := 0;
        WHILE (j <= HIGH(str)) AND (str[j] <> CHR(0)) AND (k <= HIGH(A)) DO
            A[k] := Hex2ToByte (str, j);  INC(k);
            WHILE (j <= HIGH(str)) AND (str[j] = ' ') DO
                INC(j);
            END (*WHILE*);
        END (*WHILE*);
        RETURN k;
    END HexToBytes;

(************************************************************************)

END HexData.

