comp.lang.ada
 help / color / mirror / Atom feed
From: "G.B." <bauhaus@futureapps.invalid>
Subject: Re: Creating an empty file with Ada.Text_IO
Date: Tue, 25 Aug 2015 18:45:08 +0200
Date: 2015-08-25T18:45:08+02:00	[thread overview]
Message-ID: <mri5vb$g3u$1@dont-email.me> (raw)
In-Reply-To: <1c1a3b38-4810-4002-b4f5-ec09b5f97041@googlegroups.com>

On 25.08.15 17:26, Maciej Sobczak wrote:
>
>>     procedure Write_String_To_File (File_Name : in String; S : in String) is
>>        A : Ada.Streams.Stream_Element_Array (1 .. S'Length);
>>        F : Ada.Streams.Stream_IO.File_Type;
>>     begin
>>        -- convert S to stream elements
>>        for I in S'Range loop
>>           A (Ada.Streams.Stream_Element_Offset (I)) :=
>>              Ada.Streams.Stream_Element (Character'Pos (S (I)));
>>        end loop;
>
> Before anybody uses it in a rocket - there is no provision above that S'First will be 1 and the indices might not be compatible in the above assignment.
>
> Correct version is:
>
>        for I in S'Range loop
>           A (Ada.Streams.Stream_Element_Offset (I - S'First + 1)) :=
>              Ada.Streams.Stream_Element (Character'Pos (S (I)));
>        end loop;
>
> And there are actually several ways to write it.
> Now this procedure can write String slices that do not begin at index 1.
>
> (Frankly, this part of Ada is inherently error-prone. I stumble on it repeatedly.)
>

subtypes seem helpful. If S can be made of a constraint subtype,
too, then an unchecked conversion should work, too. (Does, using GNAT).


with Ada.Characters.Latin_1;
with Ada.Streams.Stream_IO;

procedure Test is

    subtype S_E_Offset is Ada.Streams.Stream_Element_Offset;
    use type S_E_Offset;
    -- static assert:
    Is_Positive_in_S_E_Offset : constant array (Boolean) of Integer :=
      (
       S_E_Offset'First > S_E_Offset (Positive'First) => 123,
       S_E_Offset'Last >= S_E_Offset (Positive'Last) => 123
      );

    procedure Write_String_To_File (File_Name : in String; S : in String) is
       subtype Index is S_E_Offset
         range S_E_Offset (S'First) .. S_E_Offset (S'Last);

       A : Ada.Streams.Stream_Element_Array (Index);
       F : Ada.Streams.Stream_IO.File_Type;
    begin
       -- convert S to stream elements
       for I in S'Range loop
          A (S_E_Offset (I)) :=
            Ada.Streams.Stream_Element (Character'Pos (S (I)));
       end loop;

       -- create a stream file and write the content (which might be empty)
       Ada.Streams.Stream_IO.Create (F, Ada.Streams.Stream_IO.Out_File, 
File_Name);
       Ada.Streams.Stream_IO.Write (F, A);
       Ada.Streams.Stream_IO.Close (F);
    end Write_String_To_File;

begin
    -- empty file:
    Write_String_To_File ("file1.txt", "");

    -- file with one, non-terminated line:
    Write_String_To_File ("file2.txt",
                          String'(22 => 'a',
                                  23 => 'b',
                                  24 => 'c'));

    -- file with "one line and a half":
    Write_String_To_File ("file3.txt",
       "abc" & Ada.Characters.Latin_1.LF & "xyz");
end Test;

  parent reply	other threads:[~2015-08-25 16:45 UTC|newest]

Thread overview: 9+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-08-24 14:16 Creating an empty file with Ada.Text_IO Maciej Sobczak
2015-08-24 16:15 ` Dmitry A. Kazakov
2015-08-25  8:20   ` Maciej Sobczak
2015-08-25 15:26     ` Maciej Sobczak
2015-08-25 16:18       ` J-P. Rosen
2015-08-25 16:45       ` G.B. [this message]
2015-08-24 18:51 ` AdaMagica
2015-08-24 22:22   ` Randy Brukardt
2015-08-25  0:06 ` Dennis Lee Bieber
replies disabled

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox