-
Notifications
You must be signed in to change notification settings - Fork 0
CryptAda.Pragmatics
This package defines a set of types and operations on those types that are widely used along the library. Next sections describe the types used and the operations on those types.
The package provides basic modular type definitions for 8, 16, 32 and 64-bit values based on those provided in the Interfaces package.
type Byte is new Interfaces.Unsigned_8;
type Two_Bytes is new Interfaces.Unsigned_16;
type Four_Bytes is new Interfaces.Unsigned_32;
type Eight_Bytes is new Interfaces.Unsigned_64;
The package includes definitions of unconstrained, Positive indexed array types for the basic modular types:
type Byte_Array is array(Positive range <>) of Byte;
type Two_Bytes_Array is array(Positive range <>) of Two_Bytes;
type Four_Bytes_Array is array(Positive range <>) of Four_Bytes;
type Eight_Bytes_Array is array(Positive range <>) of Eight_Bytes;
Next subtypes provide support for extracting (unpacking) the bytes that conform the basic modular types and to build basic modular types from byte arrays (packing):
subtype Unpacked_Two_Bytes is Byte_Array(1 .. 2);
subtype Unpacked_Four_Bytes is Byte_Array(1 .. 4);
subtype Unpacked_Eight_Bytes is Byte_Array(1 .. 8);
The package also include a set of access types to basic modular array values.
type Byte_Array_Ptr is access all Byte_Array;
type Two_Bytes_Array_Ptr is access all Two_Bytes_Array;
type Four_Bytes_Array_Ptr is access all Four_Bytes_Array;
type Eight_Bytes_Array_Ptr is access all Eight_Bytes_Array;
Finally, the package provides an enumeration type, Byte_Order, that identifies the order of bytes in Byte_Array values that will be converted to basic modular values or that are obtained from unpacking basic modular values. Byte_Order values are:
- Little_Endian. Significance of bytes in the byte array increases as the index of the array increases. The lower the index the less significance of the byte.
- Big_Endian. Significance of bytes in the byte array decreases as the index of the array increases. The lower the index the greater the significance of bytes.
type Byte_Order is (Little_Endian, Big_Endian);
There are a number of subprograms that allow to obtain parts of modular values. These subprograms are inlined for performance reasons and do not raise any exceptions. Since their definition is clear and straightforward no further description is provided.
function Lo_Nibble(
B : in Byte)
return Byte;
function Hi_Nibble(
B : in Byte)
return Byte;
function Lo_Byte(
T : in Two_Bytes)
return Byte;
function Hi_Byte(
T : in Two_Bytes)
return Byte;
function Lo_Two_Bytes(
F : in Four_Bytes)
return Two_Bytes;
function Hi_Two_Bytes(
F : in Four_Bytes)
return Two_Bytes;
function Lo_Four_Bytes(
E : in Eight_Bytes)
return Four_Bytes;
function Hi_Four_Bytes(
E : in Eight_Bytes)
return Four_Bytes;
Next subprograms allow to build modular values out of other modular values. These subprograms do not raise any exceptions. Since their definition is clear and straightforward no further description is provided.
Argument names indicate the significance of the part (L => Low, H => High).
function Make_Two_Bytes(
L : in Byte;
H : in Byte)
return Two_Bytes;
function Make_Four_Bytes(
LL : in Byte;
LH : in Byte;
HL : in Byte;
HH : in Byte)
return Four_Bytes;
function Make_Four_Bytes(
L : in Two_Bytes;
H : in Two_Bytes)
return Four_Bytes;
function Make_Eight_Bytes(
LLL : in Byte;
LLH : in Byte;
LHL : in Byte;
LHH : in Byte;
HLL : in Byte;
HLH : in Byte;
HHL : in Byte;
HHH : in Byte)
return Eight_Bytes;
function Make_Eight_Bytes(
LL : in Two_Bytes;
LH : in Two_Bytes;
HL : in Two_Bytes;
HH : in Two_Bytes)
return Eight_Bytes;
function Make_Eight_Bytes(
L : in Four_Bytes;
H : in Four_Bytes)
return Eight_Bytes;
Next subprograms allow to 'pack' byte arrays' bytes into modular values. The subprograms provide an argument (Order) that allow to specify the significance of the bytes into the resulting modular value.
function Pack(
Unpacked : in Unpacked_Two_Bytes;
Order : in Byte_Order := Little_Endian)
return Two_Bytes;
function Pack(
Unpacked : in Unpacked_Four_Bytes;
Order : in Byte_Order := Little_Endian)
return Four_Bytes;
function Pack(
Unpacked : in Unpacked_Eight_Bytes;
Order : in Byte_Order := Little_Endian)
return Eight_Bytes;
Example:
declare
BA : constant Byte_Array(1 .. 4) := (16#01#, 16#02#, 16#03#, 16#04#);
FB_LE : constant Four_Bytes := Pack(BA, Little_Endian);
FB_BE : constant Four_Bytes := Pack(BA, Big_Endian);
begin
-- The values of FB_LE and FB_BE are:
-- FB_LE => 16#04030201#
-- FB_BE => 16#01020304#
end;
Next subprograms allow to 'unpack' modular values into byte arrays. The subprograms provide an argument (Order) that allow to specify the order of the modular value's bytes into the array.
function Unpack(
Packed : in Two_Bytes;
Order : in Byte_Order := Little_Endian)
return Unpacked_Two_Bytes;
function Unpack(
Packed : in Four_Bytes;
Order : in Byte_Order := Little_Endian)
return Unpacked_Four_Bytes;
function Unpack(
Packed : in Eight_Bytes;
Order : in Byte_Order := Little_Endian)
return Unpacked_Eight_Bytes;
Example:
declare
FB : constant Four_Bytes := 16#01020304#;
BA_LE : constant Byte_Array(1 .. 4) := Unpack(FB, Little_Endian);
BA_BE : constant Byte_Array(1 .. 4) := Unpack(FB, Big_Endian);
begin
-- The values of BA_LE and BA_BE are:
-- BA_LE => (16#04#, 16#03#, 16#02#, 16#01#)
-- BA_BE => (16#01#, 16#02#, 16#03#, 16#04#)
end;