...
 
Commits (7)
...@@ -5,11 +5,10 @@ all: ...@@ -5,11 +5,10 @@ all:
@echo A testcase can be build from source with "make test" @echo A testcase can be build from source with "make test"
install: uninstall install: uninstall
mkdir -p obj && rm -f obj/taste-asn1-iterators && \ mkdir -p obj && cp src/taste-asn1-iterators.py obj/taste-asn1-iterators
sed 's,$$PREFIX,$(PREFIX),g' src/taste-asn1-iterators > obj/taste-asn1-iterators && \
chmod +x obj/taste-asn1-iterators
gprbuild -p asn1_iterators.gpr gprbuild -p asn1_iterators.gpr
gprinstall -p -XLIBRARY_TYPE=dynamic --build-name=shared --prefix=$(PREFIX) asn1_iterators.gpr gprinstall -p -XLIBRARY_TYPE=dynamic --build-name=shared --prefix=$(PREFIX) asn1_iterators.gpr
rm -rf obj
@echo Do not forget to export ADA_PROJECT_PATH=$(PREFIX)/share/gpr @echo Do not forget to export ADA_PROJECT_PATH=$(PREFIX)/share/gpr
test_build: clean install test_build: clean install
......
PREFIX?=$(HOME)/.local
all:
@echo You can install with "make install"
@echo A testcase can be build from source with "make test"
install: uninstall
mkdir -p obj && rm -f obj/taste-asn1-iterators && \
sed 's,$$PREFIX,$(PREFIX),g' src/taste-asn1-iterators > obj/taste-asn1-iterators && \
chmod +x obj/taste-asn1-iterators
gprbuild -p asn1_iterators.gpr
gprinstall -p -XLIBRARY_TYPE=dynamic --build-name=shared --prefix=$(PREFIX) asn1_iterators.gpr
@echo Do not forget to export ADA_PROJECT_PATH=$(PREFIX)/share/gpr
test_build: clean install
mkdir -p build_test
cp test/DataView.asn build_test
cd build_test && taste-asn1-iterators DataView.asn
gprbuild -p -P test_generic.gpr
test: test_build
build_test/test_generic
uninstall:
gprinstall --uninstall --prefix=$(PREFIX) asn1_iterators || :
clean:
gprclean test_generic.gpr || :
gprclean asn1_iterators.gpr || :
.PHONY: all clean install test test_build
asn1-iterators asn1-iterators
============== ==============
(c) 2016-2017 European Space Agency (c) 2016-2019 European Space Agency
Author/Contact: Maxime.Perrotin@esa.int Author/Contact: Maxime.Perrotin@esa.int
Generic iterator functions in Ada for generating all combinations of values of ASN.1 data types Generic iterator functions in Ada for generating all combinations of values of ASN.1 data types
v0.1 support for INTEGER with a range and SEQUENCE OF INTEGER (fixed and variable size arrays) Support integer, enumerated, sequence, sequence of (fixed and variable sizes)
test:
cd src
make
Work in progress... Part of the TASTE project. Work in progress... Part of the TASTE project.
...@@ -16,33 +16,33 @@ package body ASN1_Iterators.Generic_Basic is ...@@ -16,33 +16,33 @@ package body ASN1_Iterators.Generic_Basic is
Self.Is_Valid := True; Self.Is_Valid := True;
end; end;
function Has_Element (Ptr : Iterator_Ptr) return Boolean is function Has_Element (Position : Cursor) return Boolean is
(Ptr.Value.Has_Element and Ptr.Is_Valid); (Position.Value.Has_Element and Position.Is_Valid);
function First (Item : Iterator) return Iterator_Ptr is function First (Item : Iterator) return Cursor is
begin begin
Item.Ptr.Value.First; Item.Position.Value.First;
-- Reset validity flag -- Reset validity flag
Item.Ptr.Is_Valid := True; Item.Position.Is_Valid := True;
return Item.Ptr; return Item.Position;
end; end;
function Next (Item : Iterator; function Next (Item : Iterator;
Ptr : Iterator_Ptr) return Iterator_Ptr is Position : Cursor) return Cursor is
pragma Unreferenced (Item); pragma Unreferenced (Item);
begin begin
Ptr.Value.Next; Position.Value.Next;
return Ptr; return Position;
exception exception
when Stop_Iteration => Ptr.Is_Valid := False; when Stop_Iteration => Position.Is_Valid := False;
return Ptr; return Position;
end; end;
function Iterate (Self : Basic_ASN1_Iterator) function Iterate (Self : Basic_ASN1_Iterator)
return Forward_Iterator is return Forward_Iterator is
begin begin
return I: Iterator do return I: Iterator do
I.Ptr := Self'Unrestricted_Access; I.Position := Self'Unrestricted_Access;
end return; end return;
end; end;
end; end;
...@@ -4,44 +4,44 @@ use Ada.Finalization; ...@@ -4,44 +4,44 @@ use Ada.Finalization;
with ASN1_Iterators.SimpleTypes; with ASN1_Iterators.SimpleTypes;
generic generic
with package P is new SimpleTypes (<>); with package P is new SimpleTypes (<>);
package ASN1_Iterators.Generic_Basic is package ASN1_Iterators.Generic_Basic is
-- Provides an iterator for a basic type -- Provides an iterator for a basic type
subtype Sort is P.Sort; subtype Sort is P.Sort;
type Basic_ASN1_Iterator is new Controlled type Basic_ASN1_Iterator is new Controlled
with record with record
Value : P.SimpleType; Value : P.SimpleType;
Is_Valid : Boolean := True; Is_Valid : Boolean := True;
end record end record
with Default_Iterator => Iterate, with Default_Iterator => Iterate,
Iterator_Element => P.Sort, Iterator_Element => P.Sort,
Constant_Indexing => Elem_Value; Constant_Indexing => Elem_Value;
procedure Initialize (self: in out Basic_ASN1_Iterator); procedure Initialize (self: in out Basic_ASN1_Iterator);
type Iterator_Ptr is access all Basic_ASN1_Iterator; type Cursor is access all Basic_ASN1_Iterator;
function Has_Element (Ptr : Iterator_Ptr) return Boolean; function Has_Element (Position : Cursor) return Boolean;
package Iterators is package Iterators is
new Ada.Iterator_Interfaces (Iterator_Ptr, Has_Element); new Ada.Iterator_Interfaces (Cursor, Has_Element);
type Iterator is new Iterators.Forward_Iterator with record type Iterator is new Iterators.Forward_Iterator with record
Ptr : Iterator_Ptr; Position : Cursor;
end record; end record;
function Ptr (Item: Iterator) return Iterator_Ptr is (Item.Ptr); function Get_Cursor (Item : Iterator) return Cursor is (Item.Position);
overriding function First (Item : Iterator) return Iterator_Ptr; overriding function First (Item : Iterator) return Cursor;
overriding function Next (Item : Iterator; overriding function Next (Item : Iterator;
Ptr : Iterator_Ptr) return Iterator_Ptr; Position : Cursor) return Cursor;
subtype Forward_Iterator is Iterators.Forward_Iterator'Class; subtype Forward_Iterator is Iterators.Forward_Iterator'Class;
function Iterate (Self : Basic_ASN1_Iterator) return Forward_Iterator; function Iterate (Self : Basic_ASN1_Iterator) return Forward_Iterator;
function Elem_Value (Self : Basic_ASN1_Iterator; function Elem_Value (Self : Basic_ASN1_Iterator;
Ptr : Iterator_Ptr) Position : Cursor)
return P.Sort is (Ptr.Value.Element_Value); return P.Sort is (Position.Value.Element_Value);
end; end ASN1_Iterators.Generic_Basic;
...@@ -5,22 +5,22 @@ with Interfaces; ...@@ -5,22 +5,22 @@ with Interfaces;
use Interfaces; use Interfaces;
generic generic
type Sort is (<>); -- a discrete type, such as enumerated type Sort is (<>); -- a discrete type, such as enumerated
package ASN1_Iterators.Generic_Enumerated is package ASN1_Iterators.Generic_Enumerated is
function Elem_Init return Sort; function Elem_Init return Sort;
function Has_Elem (Value : Sort) return Boolean; function Has_Elem (Value : Sort) return Boolean;
function Elem_First return Sort is (Sort'First); function Elem_First return Sort is (Sort'First);
function Elem_Next (Value : Sort) return Sort; function Elem_Next (Value : Sort) return Sort;
package Discrete_Type is new SimpleTypes (Sort => Sort, package Discrete_Type is new SimpleTypes (Sort => Sort,
Elem_Init => Elem_Init, Elem_Init => Elem_Init,
Has_Elem => Has_Elem, Has_Elem => Has_Elem,
Elem_First => Elem_First, Elem_First => Elem_First,
Elem_Next => Elem_Next); Elem_Next => Elem_Next);
package It is new Generic_Basic (P => Discrete_Type); package It is new Generic_Basic (P => Discrete_Type);
subtype Instance is It.Basic_ASN1_Iterator; subtype Instance is It.Basic_ASN1_Iterator;
end; end ASN1_Iterators.Generic_Enumerated;
...@@ -8,65 +8,65 @@ package body ASN1_Iterators.Generic_Fixed_SeqOf is ...@@ -8,65 +8,65 @@ package body ASN1_Iterators.Generic_Fixed_SeqOf is
if Self.Length > 1 then if Self.Length > 1 then
Self.Rest := new ASN1_SeqOf (self.Length - 1); Self.Rest := new ASN1_SeqOf (self.Length - 1);
Self.RestIt := new ASN1_SeqOf_It'(ASN1_SeqOf_It (Self.Rest.Iterate)); Self.RestIt := new ASN1_SeqOf_It'(ASN1_SeqOf_It (Self.Rest.Iterate));
Self.RestIt.Ptr := Self.RestIt.First; Self.RestIt.Position := Self.RestIt.First;
end if; end if;
end; end;
function Has_Element_SeqOf (Ptr: ASN1_SeqOf_Ptr) return Boolean is function Has_Element_SeqOf (Position: Cursor) return Boolean is
(P.Has_Element(P.Ptr(Ptr.FirstIt))); (P.Has_Element(P.Get_Cursor (Position.FirstIt)));
function Iterate (Self : ASN1_SeqOf) function Iterate (Self : ASN1_SeqOf)
return ASN1_SeqOf_It'Class is --Iterators_SeqOf.Forward_Iterator'Class is return ASN1_SeqOf_It'Class is --Iterators_SeqOf.Forward_Iterator'Class is
begin begin
return I: ASN1_SeqOf_It do return I: ASN1_SeqOf_It do
I.Ptr := Self'Unrestricted_Access; I.Position := Self'Unrestricted_Access;
end return; end return;
end; end;
function First (Item : ASN1_SeqOf_It) return ASN1_SeqOf_Ptr is function First (Item : ASN1_SeqOf_It) return Cursor is
Ptr_Elem : P.Iterator_Ptr := P.Ptr (Item.Ptr.FirstIt); Ptr_Elem : P.Cursor := P.Get_Cursor (Item.Position.FirstIt);
begin begin
-- Initialize the iterator (Compute first value) -- Initialize the iterator (Compute first value)
Item.Ptr.FirstIt := P.Iterator (Item.Ptr.FirstVal.Iterate); Item.Position.FirstIt := P.Iterator (Item.Position.FirstVal.Iterate);
Ptr_Elem := P.First (Item.Ptr.FirstIt); Ptr_Elem := P.First (Item.Position.FirstIt);
Item.Ptr.Value.Data (1) := P.Elem_Value (Item.Ptr.FirstVal, Item.Position.Value.Data (1) := P.Elem_Value (Item.Position.FirstVal,
Ptr_elem); Ptr_elem);
if Item.Ptr.Length > 1 then if Item.Position.Length > 1 then
Item.Ptr.Value.Data (2 .. Item.Ptr.Length) := Item.Position.Value.Data (2 .. Item.Position.Length) :=
Item.Ptr.RestIt.Ptr.Value.Data (1 .. Item.Ptr.RestIt.Ptr.Length); Item.Position.RestIt.Position.Value.Data (1 .. Item.Position.RestIt.Position.Length);
end if; end if;
return Item.Ptr; return Item.Position;
end; end;
function Next (Item : ASN1_SeqOf_It; function Next (Item : ASN1_SeqOf_It;
Ptr : ASN1_SeqOf_Ptr) return ASN1_SeqOf_Ptr is Position : Cursor) return Cursor is
pragma Unreferenced (Item); pragma Unreferenced (Item);
Ptr_elem : P.Iterator_Ptr := P.Ptr (Ptr.FirstIt); Ptr_elem : P.Cursor := P.Get_Cursor (Position.FirstIt);
begin begin
if Ptr.Length > 1 then if Position.Length > 1 then
Ptr.RestIt.Ptr := Ptr.RestIt.Next (Ptr.RestIt.Ptr); Position.RestIt.Position := Position.RestIt.Next (Position.RestIt.Position);
if Has_Element_SeqOf (Ptr.RestIt.Ptr) then if Has_Element_SeqOf (Position.RestIt.Position) then
Ptr.Value.Data (2 .. Ptr.Length) := Position.Value.Data (2 .. Position.Length) :=
Ptr.RestIt.Ptr.Value.Data (1 .. Ptr.RestIt.Ptr.Value.Length); Position.RestIt.Position.Value.Data (1 .. Position.RestIt.Position.Value.Length);
else else
Ptr.RestIt.Ptr := Ptr.RestIt.First; Position.RestIt.Position := Position.RestIt.First;
-- Exhausted "rest": iterate on the first item -- Exhausted "rest": iterate on the first item
Ptr_elem := P.Next(Ptr.FirstIt, Ptr_elem); Ptr_elem := P.Next(Position.FirstIt, Ptr_elem);
if P.Has_Element (Ptr_elem) then if P.Has_Element (Ptr_elem) then
Ptr.Value.Data (1) := P.Elem_Value (Ptr.FirstVal, Ptr_elem); Position.Value.Data (1) := P.Elem_Value (Position.FirstVal, Ptr_elem);
Ptr.Value.Data (2 .. Ptr.Length) := Position.Value.Data (2 .. Position.Length) :=
Ptr.RestIt.Ptr.Value.Data (1 .. Ptr.RestIt.Ptr.Length); Position.RestIt.Position.Value.Data (1 .. Position.RestIt.Position.Length);
end if; end if;
end if; end if;
else else
-- Size is 0 or 1 -- Size is 0 or 1
Ptr_elem := P.Next (Ptr.FirstIt, Ptr_elem); Ptr_elem := P.Next (Position.FirstIt, Ptr_elem);
if P.Has_Element (Ptr_elem) then if P.Has_Element (Ptr_elem) then
Ptr.Value.Data (1) := P.Elem_Value (Ptr.FirstVal, Ptr_elem); Position.Value.Data (1) := P.Elem_Value (Position.FirstVal, Ptr_elem);
end if; end if;
end if; end if;
return Ptr; return Position;
end; end;
end; end;
...@@ -7,56 +7,56 @@ with ASN1_Iterators.Generic_Basic; ...@@ -7,56 +7,56 @@ with ASN1_Iterators.Generic_Basic;
with ASN1_Iterators.SimpleTypes; with ASN1_Iterators.SimpleTypes;
generic generic
with package P is new Generic_Basic (<>); with package P is new Generic_Basic (<>);
package ASN1_Iterators.Generic_Fixed_SeqOf is package ASN1_Iterators.Generic_Fixed_SeqOf is
type DataArray is array (natural range <>) of P.Sort; type DataArray is array (natural range <>) of P.Sort;
type SeqOf (Max : Natural) is record type SeqOf (Max : Natural) is record
Length : Integer; Length : Integer;
Data : DataArray (1 .. Max); Data : DataArray (1 .. Max);
end record; end record;
type ASN1_SeqOf_Ptr; type Cursor;
type ASN1_SeqOf_It; type ASN1_SeqOf_It;
type ASN1_SeqOf (Size : Natural) is new Controlled type ASN1_SeqOf (Size : Natural) is new Controlled
with record with record
Length : Natural := Size; Length : Natural := Size;
Value : SeqOf (Size); Value : SeqOf (Size);
-- First value -- First value
FirstVal : P.Basic_ASN1_Iterator; FirstVal : P.Basic_ASN1_Iterator;
FirstIt : P.Iterator; FirstIt : P.Iterator;
-- The rest (recursive) -- The rest (recursive)
Rest : access ASN1_SeqOf; Rest : access ASN1_SeqOf;
RestIt : access ASN1_SeqOf_It; RestIt : access ASN1_SeqOf_It;
end record end record
with Default_Iterator => Iterate, with Default_Iterator => Iterate,
Iterator_Element => SeqOf, Iterator_Element => SeqOf,
Constant_Indexing => Element_SeqOf_Value; Constant_Indexing => Element_SeqOf_Value;
type ASN1_SeqOf_Ptr is access all ASN1_SeqOf; type Cursor is access all ASN1_SeqOf;
-- Constructor (called automatically) -- Constructor (called automatically)
procedure Initialize (Self : in out ASN1_SeqOf); procedure Initialize (Self : in out ASN1_SeqOf);
function Has_Element_SeqOf (Ptr : ASN1_SeqOf_Ptr) return Boolean; function Has_Element_SeqOf (Position : Cursor) return Boolean;
package Iterators_SeqOf is package Iterators_SeqOf is
new Ada.Iterator_Interfaces (ASN1_SeqOf_Ptr, Has_Element_SeqOf); new Ada.Iterator_Interfaces (Cursor, Has_Element_SeqOf);
type ASN1_SeqOf_It is new Iterators_SeqOf.Forward_Iterator with record type ASN1_SeqOf_It is new Iterators_SeqOf.Forward_Iterator with record
Ptr : ASN1_SeqOf_Ptr; Position : Cursor;
end record; end record;
overriding function First (Item : ASN1_SeqOf_It) return ASN1_SeqOf_Ptr; overriding function First (Item : ASN1_SeqOf_It) return Cursor;
overriding function Next (Item : ASN1_SeqOf_It; overriding function Next (Item : ASN1_SeqOf_It;
Ptr : ASN1_SeqOf_Ptr) return ASN1_SeqOf_Ptr; Position : Cursor) return Cursor;
function Iterate (self : ASN1_SeqOf) function Iterate (self : ASN1_SeqOf)
return ASN1_SeqOf_It'Class; -- Iterators_SeqOf.Forward_Iterator'Class; return ASN1_SeqOf_It'Class;
function Element_SeqOf_Value (Self : ASN1_SeqOf; function Element_SeqOf_Value (Self : ASN1_SeqOf;
Ptr : ASN1_SeqOf_Ptr) Position : Cursor)
return SeqOf is (self.Value); return SeqOf is (self.Value);
end; end ASN1_Iterators.Generic_Fixed_SeqOf;
...@@ -5,27 +5,27 @@ with Interfaces, ...@@ -5,27 +5,27 @@ with Interfaces,
use Interfaces; use Interfaces;
generic generic
Min: Interfaces.Integer_64; Min : Interfaces.Integer_64;
Max: Interfaces.Integer_64; Max : Interfaces.Integer_64;
package ASN1_Iterators.Generic_Integer is package ASN1_Iterators.Generic_Integer is
function Elem_Init return Interfaces.Integer_64 is (Min); function Elem_Init return Interfaces.Integer_64 is (Min);
function Has_Elem (Value : Interfaces.Integer_64) function Has_Elem (Value : Interfaces.Integer_64)
return Boolean is (Value <= Max); return Boolean is (Value <= Max);
function Elem_First return Interfaces.Integer_64 is (Min); function Elem_First return Interfaces.Integer_64 is (Min);
function Elem_Next (Value : Interfaces.Integer_64) function Elem_Next (Value : Interfaces.Integer_64)
return Interfaces.Integer_64 is (Value + 1); return Interfaces.Integer_64 is (Value + 1);
package Signed_Integer is new SimpleTypes package Signed_Integer is new SimpleTypes
(Sort => Interfaces.Integer_64, (Sort => Interfaces.Integer_64,
Elem_Init => Elem_Init, Elem_Init => Elem_Init,
Has_Elem => Has_Elem, Has_Elem => Has_Elem,
Elem_First => Elem_First, Elem_First => Elem_First,
Elem_Next => Elem_Next); Elem_Next => Elem_Next);
package It is new Generic_Basic (P => Signed_Integer); package It is new Generic_Basic (P => Signed_Integer);
subtype Instance is It.Basic_ASN1_Iterator; subtype Instance is It.Basic_ASN1_Iterator;
end; end ASN1_Iterators.Generic_Integer;
...@@ -7,18 +7,18 @@ package body ASN1_Iterators.Generic_Iterator is ...@@ -7,18 +7,18 @@ package body ASN1_Iterators.Generic_Iterator is
-- end; -- end;
function First (Item : Iterator) return Cursor is function First (Item : Iterator) return Cursor is
C: constant Cursor := Item.Ptr; C: constant Cursor := Item.Position;
begin begin
C.Item.Value := ASN1_Iterable.First(ASN1_Iterable.Iterable'Class(Item.Ptr.all.Item)); C.Item.Value := ASN1_Iterable.First(ASN1_Iterable.Iterable'Class(Item.Position.all.Item));
return C; return C;
end; end;
function Next (Item : Iterator; function Next (Item : Iterator;
Ptr : Cursor) Position : Cursor)
return Cursor is return Cursor is
C: constant Cursor := Item.Ptr; C: constant Cursor := Item.Position;
begin begin
C.Item.Value := ASN1_Iterable.Next(ASN1_Iterable.Iterable'Class(Ptr.all.Item)); C.Item.Value := ASN1_Iterable.Next(ASN1_Iterable.Iterable'Class(Position.all.Item));
return C; return C;
end; end;
...@@ -26,7 +26,7 @@ package body ASN1_Iterators.Generic_Iterator is ...@@ -26,7 +26,7 @@ package body ASN1_Iterators.Generic_Iterator is
return Iterators.Forward_Iterator'Class is return Iterators.Forward_Iterator'Class is
begin begin
return I: Iterator do return I: Iterator do
I.Ptr := self'Unrestricted_Access; I.Position := self'Unrestricted_Access;
end return; end return;
end; end;
......
...@@ -19,16 +19,16 @@ package ASN1_Iterators.Generic_Iterator is ...@@ -19,16 +19,16 @@ package ASN1_Iterators.Generic_Iterator is
type Cursor is access all Generic_Iterator_Type; type Cursor is access all Generic_Iterator_Type;
function Elem (Self : Generic_Iterator_Type; Ptr : Cursor) function Elem (Self : Generic_Iterator_Type; Position : Cursor)
return ASN1_Type is (Ptr.Item.Element); return ASN1_Type is (Position.Item.Element);
function Has_Element (Ptr : Cursor) return Boolean is function Has_Element (Position : Cursor) return Boolean is
(ASN1_Iterable.Has_Element(ASN1_Iterable.Iterable'Class(Ptr.all.Item))); (ASN1_Iterable.Has_Element(ASN1_Iterable.Iterable'Class(Position.all.Item)));
package Iterators is new Ada.Iterator_Interfaces (Cursor, Has_Element); package Iterators is new Ada.Iterator_Interfaces (Cursor, Has_Element);
type Iterator is new Iterators.Forward_Iterator with record type Iterator is new Iterators.Forward_Iterator with record
Ptr : Cursor; Position : Cursor;
end record; end record;
--overriding --overriding
...@@ -39,7 +39,7 @@ package ASN1_Iterators.Generic_Iterator is ...@@ -39,7 +39,7 @@ package ASN1_Iterators.Generic_Iterator is
overriding overriding
function Next (Item : Iterator; function Next (Item : Iterator;
Ptr : Cursor) Position : Cursor)
return Cursor; return Cursor;
function Iterate (self : Generic_Iterator_Type) function Iterate (self : Generic_Iterator_Type)
......
...@@ -7,60 +7,68 @@ package body ASN1_Iterators.Generic_SeqOf is ...@@ -7,60 +7,68 @@ package body ASN1_Iterators.Generic_SeqOf is
self.RestVal := new P.ASN1_SeqOf(Self.Length); self.RestVal := new P.ASN1_SeqOf(Self.Length);
self.RestIt := self.RestIt :=
new P.ASN1_SeqOf_It'(P.ASN1_SeqOf_It(Self.RestVal.Iterate)); new P.ASN1_SeqOf_It'(P.ASN1_SeqOf_It(Self.RestVal.Iterate));
self.RestIt.Ptr := self.RestIt.First; self.RestIt.Position := self.RestIt.First;
end if; end if;
end; end;
function Has_Element_Variable_SeqOf (Ptr: ASN1_Variable_SeqOf_Ptr) function Has_Element_Variable_SeqOf
return Boolean is (Length_Pkg.Has_Element(Length_Pkg.Ptr(Ptr.LenIt))); (Position : Cursor)
return Boolean is
(Length_Pkg.Has_Element(Length_Pkg.Get_Cursor (Position.LenIt)));
function Iterate (self : ASN1_Variable_SeqOf) function Iterate (self : ASN1_Variable_SeqOf)
return Iterators_Variable_SeqOf.Forward_Iterator'Class is return Iterators_Variable_SeqOf.Forward_Iterator'Class is
begin begin
return I: ASN1_Variable_SeqOf_It do return I: ASN1_Variable_SeqOf_It do
I.Ptr := Self'Unrestricted_Access; I.Position := Self'Unrestricted_Access;
end return; end return;
end; end;
function First (Item : ASN1_Variable_SeqOf_It) function First (Item : ASN1_Variable_SeqOf_It)
return ASN1_Variable_SeqOf_Ptr is return Cursor is
begin begin
-- Initialize the iterator (Compute first value) -- Initialize the iterator (Compute first value)
Item.Ptr.LenIt := Length_Pkg.Iterator(Item.Ptr.LenVal.Iterate); Item.Position.LenIt :=
Length_Pkg.Iterator(Item.Position.LenVal.Iterate);
-- Copy only the actual size, since the arrays may be different in size -- Copy only the actual size, since the arrays may be different in size
Item.Ptr.Value.Data (1 .. Item.Ptr.RestIt.Ptr.Value.Data'Length) := Item.Position.Value.Data
Item.Ptr.RestIt.Ptr.Value.Data; (1 .. Item.Position.RestIt.Position.Value.Data'Length) :=
return Item.Ptr; Item.Position.RestIt.Position.Value.Data;
return Item.Position;
end; end;
function Next (Item : ASN1_Variable_SeqOf_It; function Next (Item : ASN1_Variable_SeqOf_It;
Ptr : ASN1_Variable_SeqOf_Ptr) Position : Cursor)
return ASN1_Variable_SeqOf_Ptr return Cursor
is is
pragma Unreferenced (Item); pragma Unreferenced (Item);
Ptr_elem : Length_Pkg.Iterator_Ptr := Length_Pkg.Ptr(Ptr.LenIt); Position_elem : Length_Pkg.Cursor :=
begin Length_Pkg.Get_Cursor (Position.LenIt);
Ptr.RestIt.Ptr := Ptr.RestIt.Next (Ptr.RestIt.Ptr); begin
if P.Has_Element_SeqOf (Ptr.RestIt.Ptr) then Position.RestIt.Position := Position.RestIt.Next (Position.RestIt.Position);
Ptr.Value.Data (1 .. Ptr.RestIt.Ptr.Value.Data'Length) := if P.Has_Element_SeqOf (Position.RestIt.Position) then
Ptr.RestIt.Ptr.Value.Data; Position.Value.Data
(1 .. Position.RestIt.Position.Value.Data'Length) :=
Position.RestIt.Position.Value.Data;
else else
Ptr.RestIt.Ptr := Ptr.RestIt.First; Position.RestIt.Position := Position.RestIt.First;
-- Exhausted "rest": iterate on the first item -- Exhausted "rest": iterate on the first item
Ptr_elem := Ptr.LenIt.Next (Ptr_elem); Position_elem := Position.LenIt.Next (Position_elem);
if Length_Pkg.Has_Element (Ptr_elem) then if Length_Pkg.Has_Element (Position_elem) then
Ptr.Value.Length := Integer (Ptr_Elem.Value.Value); Position.Value.Length := Integer (Position_Elem.Value.Value);
Ptr.Length := Ptr.Value.Length; Position.Length := Position.Value.Length;
Ptr.RestVal := new P.ASN1_SeqOf(Ptr.Value.Length); Position.RestVal := new P.ASN1_SeqOf(Position.Value.Length);
Ptr.RestIt := Position.RestIt :=
new P.ASN1_SeqOf_It'(P.ASN1_SeqOf_It (Ptr.RestVal.Iterate)); new P.ASN1_SeqOf_It'(P.ASN1_SeqOf_It
Ptr.RestIt.Ptr := Ptr.RestIt.First; (Position.RestVal.Iterate));
Ptr.Value.Data (1 .. Ptr.RestIt.Ptr.Value.Data'Length) := Position.RestIt.Position := Position.RestIt.First;
Ptr.RestIt.Ptr.Value.Data; Position.Value.Data
end if; (1 .. Position.RestIt.Position.Value.Data'Length) :=
end if; Position.RestIt.Position.Value.Data;
return Ptr; end if;
end; end if;
end; return Position;
end;
end ASN1_Iterators.Generic_SeqOF;
...@@ -10,73 +10,71 @@ with ASN1_Iterators.Generic_Fixed_SeqOf, ...@@ -10,73 +10,71 @@ with ASN1_Iterators.Generic_Fixed_SeqOf,
with Interfaces; with Interfaces;
use Interfaces; use Interfaces;
-- Iterator for a variable-size array of basic type -- Iterator for a variable-size array of basic type
generic generic
Min : Natural; Min : Natural;
Max : Natural; Max : Natural;
with package Basic is new Generic_Basic (<>); with package Basic is new Generic_Basic (<>);
package ASN1_Iterators.Generic_SeqOf is package ASN1_Iterators.Generic_SeqOf is
Package P is new Generic_Fixed_SeqOF (P => Basic); package P is new Generic_Fixed_SeqOF (P => Basic);
-- Create an integer type with a range constraint to iterate on -- Create an integer type with a range constraint to iterate on
package Length_ty is new Generic_Integer (Integer_64(Min), package Length_ty is new Generic_Integer (Integer_64 (Min),
Integer_64(Max)); Integer_64 (Max));
-- Instantiate the package to iterate on the integer for the length -- Instantiate the package to iterate on the integer for the length
package Length_Pkg renames Length_ty.It; package Length_Pkg renames Length_ty.It;
type ASN1_Variable_SeqOf_Ptr is private; type Cursor is private;
subtype MySeqOf is P.SeqOf(Max); subtype Sequence_Of is P.SeqOf (Max);
type ASN1_Variable_SeqOf is new Controlled type ASN1_Variable_SeqOf is new Controlled
with record with record
Length : Natural := Min; Length : Natural := Min;
Value : MySeqOf; -- P.SeqOf(Max); Value : Sequence_Of;
-- Iterate on the length -- Iterate on the length
LenVal : Length_ty.Instance; LenVal : Length_ty.Instance;
LenIt : Length_Pkg.Iterator; LenIt : Length_Pkg.Iterator;
-- And on the value -- And on the value
RestVal : access P.ASN1_SeqOf; RestVal : access P.ASN1_SeqOf;
RestIt : access P.ASN1_SeqOf_It; RestIt : access P.ASN1_SeqOf_It;
end record end record
with Default_Iterator => Iterate, with Default_Iterator => Iterate,
Iterator_Element => MySeqOf, --P.SeqOf, Iterator_Element => Sequence_Of,
Constant_Indexing => Element_Variable_SeqOf_Value; Constant_Indexing => Element_Variable_SeqOf_Value;
-- Constructor (called automatically) -- Constructor (called automatically)
procedure Initialize(self: in out ASN1_Variable_SeqOf); procedure Initialize (Self : in out ASN1_Variable_SeqOf);
function Has_Element_Variable_SeqOf (Ptr : ASN1_Variable_SeqOf_Ptr) function Has_Element_Variable_SeqOf (Position : Cursor)
return Boolean; return Boolean;
package Iterators_Variable_SeqOf is package Iterators_Variable_SeqOf is
new Ada.Iterator_Interfaces (ASN1_Variable_SeqOf_Ptr, new Ada.Iterator_Interfaces (Cursor,
Has_Element_Variable_SeqOf); Has_Element_Variable_SeqOf);
type ASN1_Variable_SeqOf_It type ASN1_Variable_SeqOf_It
is new Iterators_Variable_SeqOf.Forward_Iterator with record is new Iterators_Variable_SeqOf.Forward_Iterator with record
Ptr : ASN1_Variable_SeqOf_Ptr; Position : Cursor;
end record; end record;
overriding overriding
function First (Item : ASN1_Variable_SeqOf_It) function First (Item : ASN1_Variable_SeqOf_It)
return ASN1_Variable_SeqOf_Ptr; return Cursor;
overriding overriding
function Next (Item : ASN1_Variable_SeqOf_It; function Next (Item : ASN1_Variable_SeqOf_It;
Ptr : ASN1_Variable_SeqOf_Ptr) Position : Cursor)
return ASN1_Variable_SeqOf_Ptr; return Cursor;
function Iterate (self : ASN1_Variable_SeqOf) function Iterate (self : ASN1_Variable_SeqOf)
return Iterators_Variable_SeqOf.Forward_Iterator'Class; return Iterators_Variable_SeqOf.Forward_Iterator'Class;
function Element_Variable_SeqOf_Value (Self : ASN1_Variable_SeqOf; function Element_Variable_SeqOf_Value (Self : ASN1_Variable_SeqOf;
Ptr : ASN1_Variable_SeqOf_Ptr) Position : Cursor)
--return P.SeqOf is (Self.Value); return Sequence_Of is (Self.Value);
return MySeqOf is (Self.Value);
subtype Instance is ASN1_Variable_SeqOf;
subtype Instance is ASN1_Variable_SeqOf;
private
private type Cursor is access all ASN1_Variable_SeqOf;
type ASN1_Variable_SeqOf_Ptr is access all ASN1_Variable_SeqOf;
end ASN1_Iterators.Generic_SeqOF;
end;
...@@ -5,24 +5,24 @@ with Interfaces; ...@@ -5,24 +5,24 @@ with Interfaces;
use Interfaces; use Interfaces;
generic generic
Min: Interfaces.Unsigned_64; Min : Interfaces.Unsigned_64;
Max: Interfaces.Unsigned_64; Max : Interfaces.Unsigned_64;
package ASN1_Iterators.Generic_Unsigned_Integer is package ASN1_Iterators.Generic_Unsigned_Integer is
function Elem_Init return Interfaces.Unsigned_64 is (Min); function Elem_Init return Interfaces.Unsigned_64 is (Min);
function Has_Elem(Value: Interfaces.Unsigned_64) return Boolean is function Has_Elem (Value : Interfaces.Unsigned_64) return Boolean is
(Value <= Max); (Value <= Max);
function Elem_First return Interfaces.Unsigned_64 is (Min); function Elem_First return Interfaces.Unsigned_64 is (Min);
function Elem_Next(Value: Interfaces.Unsigned_64) function Elem_Next (Value : Interfaces.Unsigned_64)
return Interfaces.Unsigned_64 is (Value + 1); return Interfaces.Unsigned_64 is (Value + 1);
package Unsigned_Type is new SimpleTypes package Unsigned_Type is new SimpleTypes
(Sort => Interfaces.Unsigned_64, (Sort => Interfaces.Unsigned_64,
Elem_Init => Elem_Init, Elem_Init => Elem_Init,
Has_Elem => Has_Elem, Has_Elem => Has_Elem,
Elem_First => Elem_First, Elem_First => Elem_First,
Elem_Next => Elem_Next); Elem_Next => Elem_Next);
package It is new Generic_Basic (P => Unsigned_Type); package It is new Generic_Basic (P => Unsigned_Type);
subtype Instance is It.Basic_ASN1_Iterator; subtype Instance is It.Basic_ASN1_Iterator;
end; end ASN1_Iterators.Generic_Unsigned_Integer;
...@@ -34,6 +34,6 @@ package ASN1_Iterators.Iterable_Integer is ...@@ -34,6 +34,6 @@ package ASN1_Iterators.Iterable_Integer is
-- If it is needed to iterate manually, provide Cursor and Iterator: -- If it is needed to iterate manually, provide Cursor and Iterator:
subtype Cursor is Custom_Iterator.Cursor; subtype Cursor is Custom_Iterator.Cursor;
subtype Iterator is Custom_Iterator.Iterators.Forward_Iterator'Class; subtype Iterator is Custom_Iterator.Iterators.Forward_Iterator'Class;
function Has_Element (Ptr: Cursor) return Boolean function Has_Element (Position : Cursor) return Boolean
renames Custom_Iterator.Has_Element; renames Custom_Iterator.Has_Element;
end; end;
...@@ -11,13 +11,11 @@ package body ASN1_Iterators.Iterable_SeqOF is ...@@ -11,13 +11,11 @@ package body ASN1_Iterators.Iterable_SeqOF is
end; end;
function Has_Element (It: ASN1_SequenceOf) return Boolean is function Has_Element (It: ASN1_SequenceOf) return Boolean is
-- (P.Has_Element(P.Ptr(Ptr.FirstIt)));
begin begin
return False; return False;
end; end;
function First (It: in out ASN1_SequenceOf) return Generic_SeqOf is function First (It: in out ASN1_SequenceOf) return Generic_SeqOf is
-- Ptr_elem : P.Iterator_Ptr := P.Ptr(Item.Ptr.FirstIt);
Ret : constant Generic_SeqOf := It.Value; Ret : constant Generic_SeqOf := It.Value;
begin begin
It.Value.Length := It.Length; It.Value.Length := It.Length;
...@@ -30,48 +28,14 @@ package body ASN1_Iterators.Iterable_SeqOF is ...@@ -30,48 +28,14 @@ package body ASN1_Iterators.Iterable_SeqOF is
It.Rest_It := It.Rest_It :=
new Cust_Iterator'(Custom_Iterator.Iterator (It.Rest.Iterate) new Cust_Iterator'(Custom_Iterator.Iterator (It.Rest.Iterate)
with others => <>); with others => <>);
It.Rest_It.Ptr := It.Rest_It.First; It.Rest_It.Position := It.Rest_It.First;
end if; end if;
-- Initialize the iterator (Compute first value)
-- Item.Ptr.FirstIt := P.Iterator(Item.Ptr.FirstVal.Iterate);
-- Ptr_elem := P.First(Item.Ptr.FirstIt);
-- Item.Ptr.Value.Data(1) := P.Elem_Value(Item.Ptr.FirstVal,
-- Ptr_elem);
-- if Item.Ptr.Length > 1 then
-- Item.Ptr.Value.Data(2 .. Item.Ptr.Length) :=
-- Item.Ptr.Rest_It.Ptr.Value.Data(1..Item.Ptr.Rest_It.Ptr.Length);
-- end if;
-- return Item.Ptr;
return Ret; return Ret;
end; end;
function Next (It: ASN1_SequenceOf) return Generic_SeqOf is function Next (It: ASN1_SequenceOf) return Generic_SeqOf is
--Ptr_elem : P.Iterator_Ptr := P.Ptr(Ptr.FirstIt);
Temp : constant Generic_SeqOf := It.Value; Temp : constant Generic_SeqOf := It.Value;
begin begin
-- if Ptr.Length > 1 then
-- Ptr.Rest_It.Ptr := Ptr.Rest_It.Next (Ptr.Rest_It.Ptr);
-- if Has_Element_SeqOf (Ptr.Rest_It.Ptr) then
-- Ptr.Value.Data (2..Ptr.Length) :=
-- Ptr.Rest_It.Ptr.Value.Data (1..Ptr.Rest_It.Ptr.Value.Length);
-- else
-- Ptr.Rest_It.Ptr := Ptr.Rest_It.First;
-- -- Exhausted "rest": iterate on the first item
-- Ptr_elem := P.Next(Ptr.FirstIt, Ptr_elem);
-- if P.Has_Element (Ptr_elem) then
-- Ptr.Value.Data(1) := P.Elem_Value(Ptr.FirstVal, Ptr_elem);
-- Ptr.Value.Data(2..Ptr.Length) := Ptr.Rest_It.Ptr.Value.Data (1..Ptr.Rest_It.Ptr.Length);
-- end if;
-- end if;
-- else
-- -- Size is 0 or 1
-- Ptr_elem := P.Next(Ptr.FirstIt, Ptr_elem);
-- if P.Has_Element (Ptr_elem) then
-- Ptr.Value.Data(1) := P.Elem_Value(Ptr.FirstVal, Ptr_elem);
-- end if;
-- end if;
-- return Ptr;
return Temp; return Temp;
end; end;
end; end;
...@@ -55,7 +55,7 @@ package ASN1_Iterators.Iterable_SeqOF is ...@@ -55,7 +55,7 @@ package ASN1_Iterators.Iterable_SeqOF is
subtype Iterator is Custom_Iterator.Iterators.Forward_Iterator'Class; subtype Iterator is Custom_Iterator.Iterators.Forward_Iterator'Class;
type Cust_Iterator is new Custom_Iterator.Iterator with null record; type Cust_Iterator is new Custom_Iterator.Iterator with null record;
function Has_Element (Ptr: Cursor) return Boolean function Has_Element (Position : Cursor) return Boolean
renames Custom_Iterator.Has_Element; renames Custom_Iterator.Has_Element;
......
generic generic
type Sort is private; type Sort is private;
with function Elem_Init return Sort; with function Elem_Init return Sort;
with function Has_Elem (Value : Sort) return Boolean; with function Has_Elem (Value : Sort) return Boolean;
with function Elem_First return Sort; with function Elem_First return Sort;
with function Elem_Next (Value : Sort) return Sort; with function Elem_Next (Value : Sort) return Sort;
package ASN1_Iterators.SimpleTypes is package ASN1_Iterators.SimpleTypes is
type SimpleType is tagged record type SimpleType is tagged record
Value : Sort; Value : Sort;
end record; end record;
procedure Initialize (Self : in out SimpleType); procedure Initialize (Self : in out SimpleType);
function Has_Element (Self : in out SimpleType) return Boolean is function Has_Element (Self : in out SimpleType) return Boolean is
(Has_Elem (Self.Value)); (Has_Elem (Self.Value));
procedure First (Self : in out SimpleType); procedure First (Self : in out SimpleType);
procedure Next (Self : in out SimpleType); procedure Next (Self : in out SimpleType);
function Element_Value (Self : in out SimpleType) return Sort is function Element_Value (Self : in out SimpleType) return Sort is
(Self.Value); (Self.Value);
end; end ASN1_Iterators.SimpleTypes;
package ASN1_Iterators is package ASN1_Iterators is
Stop_Iteration : exception; Stop_Iteration : exception;
end; end ASN1_Iterators;
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
This application generates the Ada code needed to iterate on ASN.1 values
It is part of the TASTE project
Copyright (c) 2019 Maxime Perrotin
(c) 2019 European Space Agency
Contact : maxime.perrotin@esa.int
"""
__version__ = "3.0.0"
import os
import signal
import argparse
import traceback
import logging
from typing import List
LOG = logging.getLogger(__name__)
import opengeode.Asn1scc as asn1scc
import opengeode.ogParser as parser
LF = '\n'
def indent(nb: int, phrase: List[str], sep=""):
# offer indenting of multiple line strings when referenced inside f-strings
phase1 = LF.join(phrase)
phase2 = (sep+LF+nb*" ").join(phase1.splitlines())
# remove trailing spaces:
return LF.join(line.rstrip() for line in phase2.splitlines())
def adb_template(packages: List[str]) -> str:
''' Top-level template to generate the .adb file '''
return f'''-- This file was generated by TASTE: DO NOT EDIT
with Ada.Strings,
Ada.Strings.Fixed,
Ada.Strings.Unbounded,
Ada.Characters.Handling;
use Ada.Strings,
Ada.Strings.Fixed,
Ada.Strings.Unbounded,
Ada.Characters.Handling;
package body ASN1_Ada_Iterators.Iterators is
{indent(3, packages)}
end ASN1_Ada_Iterators.Iterators;
'''
def unsigned_int_adb_template (sort: str, minR: int, maxR: int) -> str:
''' Template for iterating on an unsigned integer '''
return f'''package body {sort}_Pkg is
procedure To_ASN1 (From : Interfaces.Unsigned_64;
To : out asn1Scc{sort}) is
begin
To := From;
end To_ASN1;
function Image (Elm : asn1Scc{sort}) return String is
(Ada.Strings.Fixed.Trim (Elm'Img, Both));
end {sort}_Pkg;'''
def signed_int_adb_template (sort: str, minR: int, maxR: int) -> str:
''' Template for iterating on a signed integer '''
return f'''package body {sort}_Pkg is
procedure To_ASN1 (From : Interfaces.Integer_64;
To : out asn1Scc{sort}) is
begin
To := From;
end To_ASN1;
function Image (Elm : asn1Scc{sort}) return String is
(Ada.Strings.Fixed.Trim (Elm'Img, Both));
end {sort}_Pkg;'''
def seq_of_adb_template (sort: str, inner: str, minR: int, maxR: int) -> str:
''' Template for iterating on an array '''
if minR == maxR:
return f'''package body {sort}_Pkg is
procedure To_ASN1 (From : Inner.Sequence_Of;
To : out asn1Scc{sort}) is
begin
for Idx in 1 .. From.Length loop
To.Data (Idx) := From.Data (Idx);
end loop;
end To_ASN1;
function Image (Elm : asn1Scc{sort}) return String is
Res : Unbounded_String;
begin
if Elm.Data'Length >= 1 then
Res := To_Unbounded_String (Image (Elm.Data (1)));
end if;
if Elm.Data'Length > 1 then
for Idx in 2 .. Elm.Data'Length loop
Res := Res & ", " & Image (Elm.Data (Idx));
end loop;
end if;
return To_String ("{{" & Res & "}}");
end Image;
end {sort}_Pkg;'''
else:
# Variable-size sequence of
return f'''package body {sort}_Pkg is
procedure To_ASN1 (From : Inner.Sequence_Of;
To : out asn1Scc{sort}) is
begin
for Idx in 1 .. From.Length loop
To.Data (Idx) := From.Data (Idx);
end loop;
To.Length := From.Length;
end To_ASN1;
function Image (Elm : asn1Scc{sort}) return String is
function Image_Rec (Elm : asn1Scc{sort}) return String is
(if Elm.Length > 0 then
(Image (Elm.Data (1))
& (if Elm.Length > 1 then ", "
& Image_Rec (asn1Scc{sort}'(Length => Elm.Length - 1,
Data => Elm.Data (2 .. Elm.Length) &
Elm.Data (1 .. Elm.Data'Length - Elm.Length + 1)))
else ""))
else "");
begin
return "{{ " & Image_Rec (Elm) & " }}";
end Image;
end {sort}_Pkg;'''
def enum_adb_template (sort: str) -> str:
''' Template for iterating on an enumerated '''
return f'''package body {sort}_Pkg is
function Image (Elm : asn1Scc{sort}) return String is
(Delete (To_Lower (Elm'Img), From => 1, Through => 7)); -- remove "asn1scc" prefix
end {sort}_Pkg;'''
def fields_adb_init (fields : dict) -> List [str]:
'''
Template for the fields of a sequence used in the Initialize function
'''
result = []
for name in fields.keys():
result.append (f"Container.{name}_it := P_{name}.Iterator (Container.{name}_val.Iterate);")
return result
def fields_first_key (fields : dict) -> List [str]:
'''
Return the first field name.. The dict is ordered in python 3.7+
'''
try:
return next(iter(fields))
except StopIteration:
return ""
def fields_adb_first (fields : dict) -> List [str]:
'''
Generate SEQUENCE fields code for the "First" function
'''
result = []
for name in fields.keys():
result.append (f"unused_Cursor_{name} : P_{name}.Cursor := Item.Position.{name}_it.First;")
return result
def fields_adb_next (fields : dict) -> List [str]:
'''
Generate SEQUENCE fields code for the "Next" function (declarations)
'''
result = []
for name in fields.keys():
result.append (f"Cursor_{name} : P_{name}.Cursor := Position.{name}_it.Get_Cursor;")
return result
def fields_adb_iterate (fields : dict) -> List [str]:
'''
Generate SEQUENCE iteration code (for the "Next" function)
'''
# Exhaust the last field, then the previous one, and so on
def rec_it (names : List[str]) -> List [str]:
result = []
name = names[-1]
result.append(f"Cursor_{name} := Position.{name}_it.Next (Cursor_{name});")
if len(names) > 1: # not the last one -> go recursively
result.append(f"if not P_{name}.Has_Element (Cursor_{name}) then")
result.append(f" Cursor_{name} := Position.{name}_it.First;")
result.append(f" {indent(3, rec_it(names[0:-1]))}")
result.append(f"end if;")
return result
return rec_it (list(fields.keys()))
def fields_adb_image (fields : dict) -> List [str]:
'''
Generate GSER representation code for a list of SEQUENCE fields
'''
result = []
first = True
for name, sort in fields.items():
if not first:
result.append('& ", "')
result.append (f'& "{name} " & {sort}_Pkg.Image (Elm.{name})')
first = False
return result
def sequence_adb_template (sort: str, fields: dict) -> str:
''' Template for iterating on a record '''
return f'''package body {sort}_Pkg is
procedure Initialize (Container : in out {sort}) is
begin
{indent(6, fields_adb_init(fields))}
end Initialize;
function Has_Element (Position : Cursor) return Boolean is
(P_{fields_first_key(fields)}.Has_Element
(Position.{fields_first_key(fields)}_it.Get_Cursor));
function Iterate (Container : {sort}) return {sort}_It'Class is
begin
return I : {sort}_It do
I.Position := Container'Unrestricted_Access;
end return;
end Iterate;
function First (Item : {sort}_It) return Cursor is
{indent(6, fields_adb_first(fields))}
begin
return Item.Position;
end First;
function Next (Item : {sort}_It;
Position : Cursor) return Cursor is
pragma Unreferenced (Item);
{indent(6, fields_adb_next(fields))}
begin
-- Iterate on the last field then on the previous ones
{indent(6, fields_adb_iterate(fields))}
return Position;
end Next;
function Image (Elm : asn1Scc{sort}) return String is
begin
return "{{"
{indent(13, fields_adb_image(fields))}
& "}}";
end Image;
end {sort}_Pkg;'''
def top_ads_template(modules: List[str]) -> str:
''' Template for asn1_ada_iterators.ads '''
withs = (f'''with {module}; use {module}; pragma Unreferenced ({module});'''
for module in modules)
withs_str = '\n'.join(withs)
return f'''-- This file was generated by TASTE: DO NOT EDIT
{withs_str}
package ASN1_Ada_Iterators is
end;'''
def ads_template(packages: List[str]) -> str:
''' Top-level template to generate the .ads file '''
return f'''-- This file was generated by TASTE: DO NOT EDIT
with Ada.Iterator_Interfaces,
Ada.Finalization,
Interfaces,
ASN1_Ada_Iterators,
ASN1_Iterators.Generic_Integer,
ASN1_Iterators.Generic_Unsigned_Integer,
ASN1_Iterators.Generic_Enumerated,
ASN1_Iterators.Generic_SeqOf;
pragma Unreferenced (ASN1_Ada_Iterators);
use Ada.Finalization,
Interfaces,
ASN1_Iterators;
package ASN1_Ada_Iterators.Iterators is
{indent(3, packages)}
end ASN1_Ada_Iterators.Iterators;
'''
def unsigned_int_ads_template (sort: str, minR: int, maxR: int) -> str:
''' Template for iterating on an unsigned integer '''
return f'''package {sort}_Pkg is
package Inner is new Generic_Unsigned_Integer (Min => {minR},
Max => {maxR});
package It renames Inner.It;
procedure To_ASN1 (From : Interfaces.Unsigned_64;
To : out asn1Scc{sort});
subtype Instance is Inner.Instance;
function Image (Elm : asn1Scc{sort}) return String;
end {sort}_Pkg;'''
def signed_int_ads_template (sort: str, minR: int, maxR: int) -> str:
''' Template for iterating on an signed integer '''
return f'''package {sort}_Pkg is
package Inner is new Generic_Integer (Min => {minR},
Max => {maxR});
package It renames Inner.It;
procedure To_ASN1 (From : Interfaces.Integer_64;
To : out asn1Scc{sort});
subtype Instance is Inner.Instance;
function Image (Elm : asn1Scc{sort}) return String;
end {sort}_Pkg;'''
def seq_of_ads_template (sort: str, inner: str, minR: int, maxR: int) -> str:
''' Template for iterating on an array '''
return f'''package {sort}_Pkg is
package Inner is new Generic_SeqOf (Min => {minR},
Max => {maxR},
Basic => {inner}_Pkg.It);
use {inner}_Pkg;
procedure To_ASN1 (From : Inner.Sequence_Of;
To : out asn1Scc{sort});
subtype Instance is Inner.Instance;
function Image (Elm : asn1Scc{sort}) return String;
end {sort}_Pkg;'''
def enum_ads_template (sort: str) -> str:
''' Template for iterating on an enumerated '''
return f'''package {sort}_Pkg is
package Inner is new Generic_Enumerated (Sort => asn1Scc{sort});
package It renames Inner.It;
subtype Instance is Inner.Instance;
function Image (Elm : asn1Scc{sort}) return String;
end {sort}_Pkg;'''
def fields_ads_pkg (fields : dict) -> List [str]:
''' for each field of a sequence, do a package renaming :
package P_<field> renames <Sort>_Pkg.It
This makes further code more readable '''
result = []
for name, sort in fields.items():
result.append (f"package P_{name} renames {sort}_Pkg.It;")
return result
def fields_ads_record (fields : dict) -> List [str]:
''' Declare the fields for iteration in an ASN.1 SEQUENCE type '''
result = []
for field in fields.keys():
result.append (f"{field}_val : P_{field}.Basic_ASN1_Iterator;")
result.append (f"{field}_it : P_{field}.Iterator;")
return result
def fields_ads_value (fields : dict) -> List [str]:
''' Code that return the value of an ASN.1 SEQUENCE type '''
result = []
for field in fields.keys():
result.append (f"{field} => Container.{field}_val.Elem_Value (Container.{field}_it.Position)")
return result
def sequence_ads_template (sort: str, fields: dict) -> str:
''' Template for iterating on a record '''
return f'''package {sort}_Pkg is
{indent(3, fields_ads_pkg(fields))}
type {sort}_It;
type {sort} is new Controlled with record
{indent(6, fields_ads_record(fields))}
end record
with Default_Iterator => Iterate,
Iterator_Element => asn1Scc{sort},
Constant_Indexing => Element;
type Cursor is access all {sort};
-- Constructor (called automatically)
procedure Initialize (Container : in out {sort});
function Has_Element (Position : Cursor) return Boolean;
package Iterators_{sort} is
new Ada.Iterator_Interfaces (Cursor, Has_Element);
type {sort}_It is new Iterators_{sort}.Forward_Iterator with record
Position : Cursor;
end record;
overriding function First (Item : {sort}_It) return Cursor;
overriding function Next (Item : {sort}_It;
Position : Cursor) return Cursor;
function Iterate (Container : {sort}) return {sort}_It'Class;
function Element (Container : {sort};
Position : Cursor) return asn1Scc{sort} is
({indent(7, fields_ads_value(fields), sep=",")});
subtype Instance is {sort};
function Image (Elm : asn1Scc{sort}) return String;
end {sort}_Pkg;'''
def init_logging(options):
''' Initialize logging '''
terminal_formatter = logging.Formatter(fmt="[%(levelname)s] %(message)s")
handler_console = logging.StreamHandler()
handler_console.setFormatter(terminal_formatter)
LOG.addHandler(handler_console)
level = logging.DEBUG if options.debug else logging.INFO
LOG.setLevel(level)
def parse_args():
''' Parse command line arguments '''
parser = argparse.ArgumentParser()
parser.add_argument(
'-v',
'--version',
action='version',
version=__version__)
parser.add_argument(
'-g',
'--debug',
action='store_true',
default=False,
help='Display debug information')
parser.add_argument(
'-o',
'--output',
type=str,
metavar='folder',
default='iterators',
help='Set the output folder')
parser.add_argument(
'files',
metavar='file.asn',
type=str,
nargs='*',
help='ASN.1 file(s)')
return parser.parse_args()
def run(options):
asn1_files = options.files
if not asn1_files:
LOG.error ("You must specify at least one ASN.1 file")
return
try:
ast = asn1scc.parse_asn1(
asn1_files,
ast_version=asn1scc.ASN1.UniqueEnumeratedNames,
rename_policy=asn1scc.ASN1.NoRename,
flags=[asn1scc.ASN1.AstOnly],
pretty_print=False)
except (ImportError, NameError, TypeError) as err:
LOG.error(str(err))
LOG.error("ASN.1 Parsing error (run with -g for debug infomation)")
LOG.debug(traceback.format_exc())
return
modules = []
packages_ads, packages_adb = [], []
# Parse the ASN.1 AST to know the types and generate the corresponding code
sorts = {}
for module, types in ast.exportedTypes.items():
modules.append(module.replace('-', '_'))
for sort in types:
sort_def = ast.types[sort]
basic = parser.find_basic_type (sort_def.type)
sorts[sort.replace("-", "_")] = basic
for name, basic in sorts.items():
if basic.kind == "IntegerType" and int(basic.Min) >= 0:
packages_ads.append(
unsigned_int_ads_template(name,
int(basic.Min),
int(basic.Max)))
packages_adb.append(
unsigned_int_adb_template(name,
int(basic.Min),
int(basic.Max)))
elif basic.kind == "IntegerType" and int(basic.Min < 0):
packages_ads.append(
signed_int_ads_template(name,
int(basic.Min),
int(basic.Max)))
packages_adb.append(
signed_int_adb_template(name,
int(basic.Min),
int(basic.Max)))
elif basic.kind == "EnumeratedType":
packages_ads.append(enum_ads_template(name))
packages_adb.append(enum_adb_template(name))
elif basic.kind == "SequenceOfType":
inner=basic.type.ReferencedTypeName.replace("-", "_")
packages_ads.append(
seq_of_ads_template (name,
inner,
int(basic.Min),
int(basic.Max)))
packages_adb.append(
seq_of_adb_template (name,
inner,
int(basic.Min),
int(