comp.lang.ada
 help / color / mirror / Atom feed
From: "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de>
Subject: Re: Howto read line from a stream
Date: Sun, 31 May 2009 14:02:35 +0200
Date: 2009-05-31T14:02:37+02:00	[thread overview]
Message-ID: <nbzc2bvk6qep$.e39390ifjqzw$.dlg@40tude.net> (raw)
In-Reply-To: 1a90e055-44a3-4d00-b4cd-64798c731a55@e24g2000vbe.googlegroups.com

On Sun, 31 May 2009 04:29:33 -0700 (PDT), Tomek Wa�kuski wrote:

> I have done so far:
> 
>    function Read_Line (Channel : in Stream_Access) return String is
>       Buffer : String (1 .. 1);
>       Result : Unbounded_String;
>    begin
>       loop
>          String'Read (Channel, Buffer);
>          Append (Result, Buffer);
>          exit when Buffer (1) = ASCII.LF;
>       end loop;
>       return To_String(Result);
>    end Read_Line;
> 
> I know, this is completely NOT smart solution.

It is OK except for Unbounded_String, especially Append per each character.
That should be very slow.

I would do something like:

with Ada.Finalization;
with Ada.Streams; use Ada.Streams;
package Buffers is
      -- Buffer to accumulate read lines
   type Line_Buffer is tagged limited private;
      -- Get the line in the buffer (longer than the line read)
   function Get_Line (Buffer : Line_Buffer) return not null access String;
      -- Get the length of the line in the buffer
   function Get_Length (Buffer : Line_Buffer) return Natural;
      -- Read new line into the buffer
   procedure Read
             (  Buffer : in out Line_Buffer;
                Stream : in out Root_Stream_Type'Class
             );
private
   type String_Ptr is access String;
   type Line_Buffer is new Ada.Finalization.Limited_Controlled with record
      Length : Natural := 0;
      Line   : String_Ptr; -- The line body, dynamically allocated
   end record;
   overriding procedure Finalize (Buffer : in out Line_Buffer);
end Buffers;

You would use it like:

   loop
      Read (Buffer, Stream);  -- Read line
      declare
          Line : String renames Buffer.Get_Line (1..Buffer.Get_Length));
      begin
         ... -- Process Line
      end;
   end loop;

The implementation could be like:

with Ada.Unchecked_Deallocation;
package body Buffers is
   Increment : constant := 1024;
   procedure Free is new Ada.Unchecked_Deallocation (String, String_Ptr);

   function Get_Line (Buffer : Line_Buffer)
      return not null access String is
   begin
      return Buffer.Line;
   end Get_Line;

   function Get_Length (Buffer : Line_Buffer) return Natural is
   begin
      return Buffer.Length;
   end Get_Length;

   procedure Read
             (  Buffer : in out Line_Buffer;
                Stream : in out Root_Stream_Type'Class
             )  is
      Data : Character;
   begin
      Buffer.Length := 0;
      loop
         Character'Read (Stream'Access, Data);
         exit when Data = Character'Val (10);
         if Buffer.Line = null then
            Buffer.Line := new String (1..Increment);
         end if;
         if Buffer.Line'Length = Buffer.Length then
            declare
               Old : String_Ptr := Buffer.Line;
            begin
               Buffer.Line := new String (1..Old'Length + Increment);
               Buffer.Line (1..Old'Length) := Old.all;
               Free (Old);
            end;
         end if;
         Buffer.Length := Buffer.Length + 1;
         Buffer.Line (Buffer.Length) := Data;
      end loop;
   end Read;

   procedure Finalize (Buffer : in out Line_Buffer) is
   begin
      Free (Buffer.Line);
   end Finalize;

end Buffers;

-- 
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de



  reply	other threads:[~2009-05-31 12:02 UTC|newest]

Thread overview: 44+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2009-05-31 10:41 Howto read line from a stream Tomek Walkuski
2009-05-31 11:29 ` Tomek Wałkuski
2009-05-31 12:02   ` Dmitry A. Kazakov [this message]
2009-05-31 12:56     ` Tomek Wałkuski
2009-05-31 14:30       ` Tomek Wałkuski
2009-05-31 15:13       ` Dmitry A. Kazakov
2009-06-01 23:30         ` Randy Brukardt
2009-06-02  7:30           ` Dmitry A. Kazakov
2009-06-02  9:36             ` Georg Bauhaus
2009-06-02 10:24               ` Dmitry A. Kazakov
2009-06-02 21:15             ` Randy Brukardt
2009-06-01  6:34     ` Pascal Obry
2009-06-01  0:05   ` Jeffrey R. Carter
2009-06-03 15:49     ` Tomek Wałkuski
2009-06-03 18:04       ` Jeffrey R. Carter
2009-06-03 21:41         ` Maciej Sobczak
2009-06-04  8:56           ` Jean-Pierre Rosen
2009-06-04  9:05             ` Ludovic Brenta
2009-06-04 13:05             ` Maciej Sobczak
2009-06-04 14:16               ` Jean-Pierre Rosen
2009-06-04 19:48                 ` Ludovic Brenta
2009-06-04 14:24               ` Dmitry A. Kazakov
2009-06-03 19:07       ` sjw
2009-06-03 19:26         ` Dmitry A. Kazakov
2009-06-03 19:43           ` Georg Bauhaus
2009-06-03 20:11             ` Dmitry A. Kazakov
2009-06-03 22:09               ` Georg Bauhaus
2009-06-04  8:19                 ` Dmitry A. Kazakov
2009-06-04  9:41                   ` Georg Bauhaus
2009-06-04 10:23                     ` Dmitry A. Kazakov
2009-06-04 12:14                       ` Georg Bauhaus
2009-06-04 14:54                         ` Dmitry A. Kazakov
2009-06-04 16:33                           ` Georg Bauhaus
2009-06-05  9:57                             ` Dmitry A. Kazakov
2009-06-04 14:16         ` andrew
2009-06-01 19:12   ` björn lundin
2009-05-31 11:34 ` Dmitry A. Kazakov
2009-05-31 15:38   ` sjw
2009-05-31 16:07     ` Dmitry A. Kazakov
2009-05-31 20:39       ` Niklas Holsti
2009-05-31 22:00       ` sjw
2009-06-01  8:35         ` Dmitry A. Kazakov
2009-06-01 23:34     ` Randy Brukardt
2009-06-02  2:27 ` anon
replies disabled

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