with
  Ada.Text_IO,
  Interfaces.C.Strings,
  System.Storage_Elements,
  POSIX.Files,
  POSIX.IO,
  POSIX.Memory_Mapping;

with
  EUP.Text_IO;

package body Generic_Memory_Map is
   use type System.Storage_Elements.Storage_Offset;
   Size : constant System.Storage_Elements.Storage_Offset :=
     Data'Size / System.Storage_Elements.Storage_Element'Size;

   File     : POSIX.IO.File_Descriptor;
   Address  : System.Address;

   procedure Open (Name : String) is
      use POSIX.IO, POSIX,
        System.Storage_Elements,
        POSIX.Memory_Mapping;
   begin
      if POSIX.Files.Is_File_Present (To_POSIX_String (Name)) then
         EUP.Text_IO.Open (File => File,
                           Name => Name,
                           Mode => Read_Write);
      else
         EUP.Text_IO.Create (File => File,
                             Name => Name,
                             Mode => Read_Write);
      end if;

      if File_Size (File) < IO_Count (Size) then
         declare
            procedure Write is new Generic_Write (Data);
         begin
            Write (File => File,
                   Item => Default_Value);
         end;
      end if;
      Address := Map_Memory (Length     => Size,
                             Protection => Allow_Write + Allow_Read,
                             Mapping    => Map_Shared,
                             File       => File,
                             Offset     => 0);
   end Open;

   procedure Close is
      use POSIX.Memory_Mapping,
        POSIX.IO;
   begin
      Unmap_Memory (First  => Address,
                    Length => Size);

      Close (File => File);
   end Close;

   function Is_Open return Boolean is
   begin
     return POSIX.IO.Is_Open (File => File);
   end Is_Open;

   function Get return Data_Reference is
   begin
      return References.To_Pointer (Address);
   end Get;
end Generic_Memory_Map;

