I believe this would work, but Iām not running it through a compiler to doublecheck:
type T_Range_Descr (Count : Integer) is record
Color: String;
Octets: array (1 .. Count) of Integer;
end record;
This is called a discriminated record.
As for initialization, Ada has a uniform syntax for this.
A : T_Range_Descr := ("blue", (1, 2));
I may have made some minor mistakes, but this is roughly correct, at the least. Notice that the variable A neednāt have a constraint, as it can be inferred from the initialization expression.
Actually, I donāt believe that works for records, but I know it works for arrays.
Thx for your quick reply, but - unfortunately - this is not what Iām looking for. As you can see from the initialization, the Array contains three Records, each of which contains an unconstrained Array with a different number of elements (which is crucial for the program).
Also, I donāt want to add a length field, or a semaphore (would neither be required in Delphi, nor in C++ tooā¦).
Oh, I think the array will need to hold access types which point to the records, in that case. Alternatively, each record can hold an access type which points to the subarray.
I would use a variant record with the discriminant being the array length and then use Ada.Containers.Indefinite_Vectors to hold the variant records like an array. Example below, but I had to use dummy types to get a complete compileable example for you.
with Ada.Text_IO; use Ada.Text_IO;
with Ada.Containers.Indefinite_Vectors;
procedure jdoodle is
type Octet_Array is array(Positive range <>) of Integer;
type Range_Description
(Octet_Count : Positive;
Name_Length : Positive)
is record
Octets : Octet_Array(1..Octet_Count);
Name : String(1..Name_Length);
end record;
package Description_Vectors is new Ada.Containers.Indefinite_Vectors
(Index_Type => Positive,
Element_Type => Range_Description);
subtype Description_Vector is Description_Vectors.Vector;
use type Description_Vector; -- make "&" visible
Private_Nets : constant Description_Vector := Description_Vectors.Empty_Vector
& (Octet_Count => 1, Name_Length => 14, Octets => (1 => 10), Name => "COLOR_PRIVATE1")
& (Octet_Count => 2, Name_Length => 14, Octets => (172, 16), Name => "COLOR_PRIVATE2")
& (Octet_Count => 2, Name_Length => 14, Octets => (172, 168), Name => "COLOR_PRIVATE3");
begin
for Net of Private_Nets loop
Put_Line(Net.Name);
end loop;
end jdoodle;
type Byte_List is array (Positive range <>) of Unsigned_8);
type Range_Descr (Num_Bytes : Positive) is record
Octet : Byte_List (1 .. Num_Bytes);
Color : Unbounded_String;
end record;
package Range_Lists is new Ada.Containers.Indefinite_Vectors (Index_Type => Positive, Element_Type => Range_Descr);
subtype Range_List is Range_Lists.Vector;
use type Range_List;
Private_Net : Range_List := Range_Lists.Emtpy_Vector &
(Num_Bytes => 1, Octet => (1 => 10), Name => Color_Private1) &
(Num_Bytes => 2, Octet => (172, 16), Name => Color_Private2) &
(Num_Bytes => 2, Octet => (172, 168), Name => Color_Private3) );
Both are wrong: a component must be defined by a subtype name, so the anonymous array type is illegal, and must be definite, so the use of String is illegal.
Is there a reason people are avoiding using Vectors? They would work for the indicated task and would also be modifiable, in case octets need to be added.
I think the following code is closer to what youād like (and to what is in the FreePascal code):
with Ada.Containers.Vectors;
with Ada.Strings.Unbounded;
procedure Test_Vect is
use Ada.Strings.Unbounded;
type Byte is mod 2 ** 8;
package Byte_Vectors is
new Ada.Containers.Vectors (Positive, Byte);
type Range_Descr is record
Octets : Byte_Vectors.Vector;
Color : Unbounded_String;
end record;
begin
null;
end;
The FreePascal dynamic array corresponds an Ada container vector.
An unconstrained type is something different that exists perhaps only in Ada. The objects have fixed dimensions, but their type hasnāt. They are by default stack-allocated. See the type String as the most basic example.
Thx for all your answers so far. Currently I have ended up with this āproggyā:
pragma Ada_2022;
with Ada.Text_IO;
with Ada.Containers.Vectors;
with Ada.Strings.Unbounded;
with Ada.Strings.Unbounded.Text_IO;
use Ada.Text_IO;
use Ada.Strings.Unbounded;This text will be hidden
procedure SplitCIDR is
type Byte is Mod 2 ** 8;
type Bytes_Array is Array(0..3) Of Byte;
type Info_Record is Record
Mask: Bytes_Array;
Net: Bytes_Array;
broadcast: Bytes_Array;
End Record;
package Byte_Vectors is new Ada.Containers.Vectors(Positive, Byte);
type Range_Descr is Record
Octets: Byte_Vectors.Vector;
Color: Unbounded_String;
End Record;
COLOR_NORMAL: Unbounded_String := To_Unbounded_String("<esc>[m"); -- Side problem: HOW WOULD I SPECIFY "<esc>"?
COLOR_VERSION: Unbounded_String := To_Unbounded_String("<esc>[33m");
COLOR_PRIVATE1: Unbounded_String := To_Unbounded_String("<esc>[33;1m");
COLOR_PRIVATE2: Unbounded_String := To_Unbounded_String("<esc>[32;1m");
COLOR_PRIVATE3: Unbounded_String := To_Unbounded_String("<esc>[31;1m");
PRIVATE_NETS: Array(0 .. 2) Of Range_Descr :=
(
(Octets => [10], Color => COLOR_PRIVATE1),
(Octets => [172, 16], Color => COLOR_PRIVATE2),
(Octets => [172, 168], Color => COLOR_PRIVATE3)
);
begin
Put_Line(PRIVATE_NETS(1).Color'Image);
Put_Line(PRIVATE_NETS(1).Octets(0)); -- HOW WOULD I OUTPUT THIS?
-- Side problem:
-- Using Bounded_String gives me:
-- x.adb:44:04: error: no candidate interpretations match the actuals:
-- x.adb:44:04: error: missing argument for parameter "Item" in call to "Put_Line" declared at a-textio.ads:555
-- x.adb:44:28: error: expected type "Standard.String"
-- x.adb:44:28: error: found private type "Ada.Containers.Vectors.Constant_Reference_Type" from instance at line 22
-- x.adb:44:28: error: ==> in call to "Put_Line" at a-textio.ads:566
end;
As I said, Iām new to Ada, so I seem to have issues with some very basic problems, namely:
How to use (#27 in Delphi, \x27 in C) in a [[un]bounded] string?
How do I print the first Octet?
How do I use Bounded_Strings in place of Unbounded_Strings?
Sorry for the many simple questions, and thx for you patience (so far)
For #1:
In Ada, you can transform any number sequence to a character usint the āValā attribute:
Value : Character := Character'Val(27)
For #2:
Depends on how you want to print it. Ada.Text_IO has a generic package Modular_IO that you can use to instantiate and print numbers to a string. Adaās default string format for numbers not in base 10 is ## (EX: ā16#F1#ā). Modular_IO has a Put operation where you supply the output string, the number, and what base you want to print in. If that default format doesnāt work for you, you can make a function to customize it:
with Ada.Text_IO; use Ada.Text_IO;
procedure jdoodle is
type Byte is Mod 2 ** 8;
function To_Hex(Value : Byte) return String is
Result : String := "16#00#"; --Preformat to get the correct length
Pound_Position : constant Positive := 3;
package IO is new Ada.Text_IO.Modular_IO(Byte);
use IO;
begin
Put(To => Result,
Item => Value,
Base => 16);
case Result(Pound_Position) is
when '#' =>
-- If the pound is in the original position, this is a
-- two character string
return Result(Pound_Position + 1 .. Pound_Position + 2);
when '6' =>
-- If it is the '6' from "16", then the string is only
-- one character long
return Result(Pound_Position + 2 .. Pound_Position + 2);
when others =>
-- Should never get here, but testing out
raise Constraint_Error;
end case;
end To_Hex;
begin
for Value in Byte'Range loop
Put_Line(To_Hex(Value));
end loop;
end jdoodle;
You can further adjust the logic to do things like put in leading zeros, etc.
For #3:
You can mostly just copy/paste replace the āunboundedā with āboundedā everywhere, then in your record you add the maximum capacity:
type Range_Descr is Record
Octets: Byte_Vectors.Vector;
Color: Bounded_String(80);
End Record;
There might be a few other small niche things, but that should get you started.
FWIW You might want to look at this page. In your case, itās Ada.Characters.Latin_1.ESC? (Correct me if Iām wrong.) IMHO itās a better idea to use meaningful symbols than numbers.